Rayfin SDK 使用修饰器驱动的编程模型,可在 TypeScript 中定义一次数据架构,并自动接收生产就绪的 API、类型安全的客户端和基础结构。
重要概念
Rayfin SDK 结合了三个核心元素:
- 修饰器驱动的架构:使用 TypeScript 修饰器定义数据模型、权限和关系。
- 自动生成 API:带有装饰器的类会自动变成 GraphQL 端点,无需编写控制器代码。
- 类型安全客户端:生成的 TypeScript 客户端为查询和突变提供编译时验证。
工作原理
创建Fabric应用时,代码将流经以下阶段:
| # | 阶段 | 发生的情况 |
|---|---|---|
| 1 | 开发人员 | 在所选编辑器中创作应用。 |
| 2 | TypeScript | 在 TypeScript 中编写实体类。 |
| 3 | Decorators | 你可以使用 @entity、@uuid、@text、@role 和其他装饰器为类和字段添加注解。 |
| 4 | Schema | CLI 将修饰的类编译为数据库架构、权限策略和 API 配置。 |
| 5 | 应用程序接口 | 该模式以 GraphQL 端点的形式发布。 |
| 6 | Client | 生成的 RayfinClient 通过这些端点提供一个类型安全的数据和身份验证客户端。 |
| 7 | 应用程序 | 前端应用程序使用客户端来读取和写入数据。 |
1. 使用修饰器定义数据模型
你可以使用来自 @microsoft/rayfin-core 的 TypeScript 类和修饰器来定义数据结构:
import { entity, uuid, text, int } from '@microsoft/rayfin-core';
@entity()
export class Product {
@uuid() id!: string;
@text() name!: string;
@text({ optional: true }) description?: string;
@int() price!: number;
}
2. 架构生成
Rayfin CLI(npx rayfin)分析带有装饰器的类,并生成:
- 数据库架构 - 表、列、约束和索引
- API 配置 - GraphQL 终结点定义
- 权限策略 - 行级安全性和字段级访问控制
4. 类型安全的客户端用法
GraphQL API 可用于对数据库执行 CRUD 操作。 Rayfin SDK 提供现装的数据客户端操作,用于读取或删除数据。
import { RayfinClient } from '@microsoft/rayfin-client';
const client = new RayfinClient();
// TypeScript knows about Product fields
const products = await client.data.products.query()
.select(['id', 'name', 'price'])
.execute();
// Compile-time error if field doesn't exist
const invalid = await client.data.products.query()
.select(['nonexistentField']) // ❌ TypeScript error
.execute();
装饰器参考
Rayfin SDK 为常见数据建模模式提供修饰器:
实体修饰器
| 装饰者 | Purpose | 例子 |
|---|---|---|
@entity() |
将类标记为数据库实体 | @entity() class Product |
属性修饰器
| 装饰者 | 数据库类型 | TypeScript 类型 |
|---|---|---|
@uuid() |
UNIQUEIDENTIFIER | string |
@text() |
NVARCHAR | string |
@int() |
INT | number |
@decimal() |
DECIMAL | number |
@bool() |
位 | boolean |
@date() |
DATETIME2 | Date |
权限修饰器
| 装饰者 | Purpose |
|---|---|
@role() |
定义基于角色的权限 |
有关授权详细信息,请参阅 “定义数据权限 ”。
Functions
创建一个 UserDataFunctions 实例,并通过调用 udf.func(name, handler, connections?)来注册每个函数。
定义函数时请遵循以下规则:
- 将参数放置在
RayfinContext处理器签名的任意位置。 运行时通过类型识别它,注入它,并将其排除在生成的函数输入中。 - 为函数所需的每个委托令牌声明一个连接。 对于只访问应用数据或不需要委托令牌的函数,省略连接数组。
以下示例注册了一个普通函数和一个使用调用上下文的函数:
import {
UserDataFunctions,
type RayfinContext,
} from '@microsoft/fabric-user-data-functions';
// Match rayfin/data/schema.ts so getDataClient() is fully typed.
import type { TripPlan } from '../../data/TripPlan.js';
type AppSchema = { TripPlan: TripPlan };
const udf = new UserDataFunctions();
udf.func('greet', async (name: string): Promise<string> => {
return `Hello, ${name}!`;
});
udf.func(
'whoAmI',
async (ctx: RayfinContext<AppSchema>): Promise<string> => {
return ctx.accessToken ? 'authenticated' : 'anonymous';
},
);
RayfinContext 为该函数提供运行时服务:
| 成员 | Purpose |
|---|---|
ctx.accessToken |
为登录用户提供 Rayfin JSON Web 令牌(JWT)。 解码声明 sub 以获得稳定的用户ID。 |
ctx.Tokens.<Audience> |
获得一个平台提供的资源令牌,用于注释中 RayfinContext 声明的受众。 部署功能使用应用身份及其权限。 详情请参见 “连接功能与外部资源”。 |
ctx.getSecret('NAME') |
获取当前调用的机密。 当未设置密钥时,返回 undefined。 |
ctx.getDataClient() |
它获取你实体的类型数据 API。 客户端支持创建、 findMany更新、删除和上传文本操作。 |
ctx.baseUrl |
提供当前项的 Rayfin 端点。 |
ctx.publishableKey |
提供当前项目的可发布密钥。 |
关于设置、本地调试和部署说明,请参见“在 Fabric 应用中使用函数”。
开发工作流
典型的开发周期遵循以下模式:
- 定义或修改数据模型 - 使用修饰器添加或更新 TypeScript 类
-
使用远程后端进行本地测试 - 运行
npm run dev,在 Fabric 中针对应用后端测试前端代码更改。 -
部署到 Fabric - 运行
npx rayfin up以部署到托管的 Fabric 服务并应用架构更改。
对 TypeScript 模型的更改会自动传播到整个堆栈, 从数据库架构到 API 终结点到客户端类型。
Authorization
权限与数据模型一起使用 @role 修饰器进行定义:
@entity()
@role('authenticated', ['create', 'read', 'update', 'delete'], {
policy: (claims, item) => claims.sub.eq(item.userId)
})
export class UserDocument {
@uuid() id!: string;
@text() userId!: string;
@text() content!: string;
}
此方法可确保:
- 安全规则位于他们保护的数据旁边
- 类型安全的策略表达式可在编译时发现错误
- 重构实体字段时会自动更新权限检查