Rayfin SDK はデコレーター駆動型プログラミング モデルを使用します。このモデルでは、TypeScript でデータ スキーマを 1 回定義し、運用対応の API、タイプ セーフ なクライアント、インフラストラクチャを自動的に受け取ります。
主な概念
Rayfin SDK は、次の 3 つの主要な要素を組み合わせたものになります。
- デコレーター 駆動型スキーマ: TypeScript デコレーターを使用して、データ モデル、アクセス許可、およびリレーションシップを定義します。
- API の自動生成: 修飾されたクラスは、コントローラー コードを記述せずに GraphQL エンドポイントになります。
- タイプ セーフ クライアント: 生成された TypeScript クライアントは、クエリと変更に対してコンパイル時の検証を提供します。
どのように機能するのか
Fabric アプリを作成すると、コードは次のステージを通過します。
| # | 段階 | 何が起きるか |
|---|---|---|
| 1 | Developer | 選択したエディターでアプリを作成します。 |
| 2 | TypeScript | TypeScript でエンティティ クラスを記述します。 |
| 3 | Decorators | クラスとフィールドには、 @entity、 @uuid、 @text、 @role、およびその他のデコレーターを使用して注釈を付けます。 |
| 4 | Schema | CLI は、修飾されたクラスをデータベース スキーマ、アクセス許可ポリシー、および API 構成にコンパイルします。 |
| 5 | API(アプリケーションプログラミングインターフェース) | スキーマは GraphQL エンドポイントとして発行されます。 |
| 6 | Client | 生成された RayfinClient は、これらのエンドポイント経由でタイプ セーフなデータと認証クライアントを公開します。 |
| 7 | Application | フロントエンド アプリケーションは、クライアントを使用してデータの読み取りと書き込みを行います。 |
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() |
小数 | number |
@bool() |
ビット | boolean |
@date() |
DATETIME2 | Date |
権限デコレーター
| デコレーター | Purpose |
|---|---|
@role() |
ロールベースのアクセス許可を定義する |
承認の詳細については、「 データ権限の定義 」を参照してください。
Functions
1つの 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 Token(JWT)を提供します。 安定したユーザーIDを得るために sub の主張を解読してください。 |
ctx.Tokens.<Audience> |
RayfinContext注釈で宣言されたオーディエンスに対してプラットフォーム提供のリソーストークンを受け取ります。 デプロイド関数はアプリのアイデンティティとその権限を使用します。 詳細は「 外部リソースへの機能接続」をご覧ください。 |
ctx.getSecret('NAME') |
現在の呼び出しのシークレットを取得します。 シークレットが設定されていない場合、undefined を返します。 |
ctx.getDataClient() |
エンティティ用の型付きデータ API を取得します。 クライアントは作成、 findMany、更新、削除、アップサート操作をサポートします。 |
ctx.baseUrl |
現在のアイテムのRayfinエンドポイントを提供します。 |
ctx.publishableKey |
現在の項目の公開可能なキーを提供します。 |
セットアップ、ローカルデバッグ、デプロイ手順については、「Fabric Appsの関数使用」を参照してください。
開発ワークフロー
一般的な開発サイクルは、次のパターンに従います。
- データ モデルを定義または変更 する - デコレーターを使用して TypeScript クラスを追加または更新する
-
リモート バックエンドでローカルにテストする -
npm run devを実行して、Fabricのアプリ バックエンドに対してフロントエンド コードの変更をテストします。 Fabric -を実行してマネージド 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;
}
この方法により、次のことが保証されます。
- セキュリティ規則は、保護するデータの横に表示されます
- 型セーフ なポリシー式は、コンパイル時にエラーをキャッチします
- エンティティ フィールドをリファクタリングすると、アクセス許可チェックが自動的に更新されます