Översikt över programmeringsmodell

Rayfin SDK använder en dekoratördriven programmeringsmodell där du definierar ditt dataschema en gång i TypeScript och automatiskt tar emot produktionsklara API:er, typsäkra klienter och infrastruktur.

Viktiga begrepp

Rayfin SDK kombinerar tre kärnelement:

  • Dekoratörsbaserat schema: Använd TypeScript-dekoratörer för att definiera datamodeller, behörigheter och relationer.
  • Automatisk API-generering: Dina dekorerade klasser blir GraphQL-slutpunkter utan att skriva kontrollantkod.
  • Typsäkra klienter: Genererade TypeScript-klienter tillhandahåller kompileringstidsverifiering för frågor och mutationer.

Så här fungerar det

När du skapar en Fabric app flödar koden genom dessa steg:

# Stadium Vad händer
1 Utvecklare Du skapar appen i valfri redigerare.
2 TypeScript Du skriver entitetsklasser i TypeScript.
3 Decorators Du kommenterar klasser och fält med @entity, @uuid, @text, @roleoch andra dekoratörer.
4 Schema CLI kompilerar de dekorerade klasserna till ett databasschema, behörighetsprinciper och API-konfiguration.
5 API:er Schemat publiceras som GraphQL-slutpunkter.
6 Client Den genererade RayfinClient exponerar en typsäker data- och autentiseringsklient över dessa slutpunkter.
7 Ansökan Frontendprogrammet använder klienten för att läsa och skriva data.

1. Definiera datamodeller med dekoratörer

Du definierar din datastruktur med hjälp av TypeScript-klasser och dekoratörer från @microsoft/rayfin-core:

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. Generering av schema

Rayfin CLI (npx rayfin) analyserar dina dekorerade klasser och genererar:

  • Databasschema – Tabeller, kolumner, begränsningar och index
  • API-konfiguration – GraphQL-slutpunktsdefinitioner
  • Behörighetsprinciper – säkerhet på radnivå och åtkomstkontroll på fältnivå

4. Typsäker klientanvändning

GraphQL-API:er är tillgängliga för att utföra CRUD-åtgärder i databasen. Rayfin SDK tillhandahåller en inbyggd dataklientfunktion för att läsa, skriva eller ta bort data.

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();

Referens för dekoratörer

Rayfin SDK tillhandahåller dekoratörer för vanliga datamodelleringsmönster:

Entitetsdekoratörer

Dekoratör Purpose Example
@entity() Markera en klass som en databasentitet @entity() class Product

Egenskapsdekoratörer

Dekoratör Databastyp TypeScript-typ
@uuid() UNIQUEIDENTIFIER string
@text() NVARCHAR string
@int() INT number
@decimal() DECIMAL number
@bool() BIT boolean
@date() DATETIME2 Date

Behörighetsdekoratörer

Dekoratör Purpose
@role() Definiera rollbaserade behörigheter

Se Definiera databehörigheter för auktoriseringsinformation.

Functions

Skapa en UserDataFunctions instans och registrera varje funktion genom att anropa udf.func(name, handler, connections?).

Följ dessa regler när du definierar en funktion:

  • Placera parametern RayfinContext var som helst i handlersignaturen. Körtiden identifierar den efter typ, injicerar den och exkluderar den från de genererade funktionsindatana.
  • Deklarera en anslutning för varje delegerad token som funktionen behöver. Utelämna anslutningsarrayen för funktioner som bara får tillgång till appdata eller inte behöver delegerade tokens.

Följande exempel registrerar en vanlig funktion och en funktion som använder anropskontexten:

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 tillhandahåller funktionens körtidstjänster:

Medlem Purpose
ctx.accessToken Tillhandahåller den inloggade användarens Rayfin JSON Web Token (JWT). Avkoda påståendet sub för att få ett stabilt användar-ID.
ctx.Tokens.<Audience> Hämtar en resurstoken som tillhandahålls av plattformen för en mottagare som deklareras i annotationen RayfinContext. Distribuerade funktioner använder appens identitet och dess behörigheter. För detaljer, se Koppla funktioner till externa resurser.
ctx.getSecret('NAME') Får en hemlighet för den aktuella åkallelsen. Returnerar undefined när hemligheten inte är angiven.
ctx.getDataClient() Hämtar API:et för typad data för dina enheter. Klienten stödjer skapa-, findMany, uppdatera-, borttagnings- och upsert-operationer.
ctx.baseUrl Tillhandahåller Rayfin-endpointen för det aktuella objektet.
ctx.publishableKey Tillhandahåller den publicerbara nyckeln för det aktuella objektet.

För installation, lokal felsökning och distributionsinstruktioner, se Use Functions in Fabric Apps.

Arbetsflöde för utveckling

En typisk utvecklingscykel följer det här mönstret:

  1. Definiera eller ändra datamodeller – Lägga till eller uppdatera TypeScript-klasser med dekoratörer
  2. Testa lokalt med fjärrserverdel – Kör npm run dev för att testa kodändringarna i klientdelen mot din appserverdel i Fabric.
  3. Distribution till Fabric – Kör npx rayfin up för att distribuera till den hanterade Fabric-tjänsten och tillämpa schemaändringarna.

Ändringar i TypeScript-modeller sprids automatiskt via hela stacken – från databasschema till API-slutpunkter till klienttyper.

Authorization

Behörigheter definieras tillsammans med dina datamodeller med hjälp av dekoratören @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;
}

Den här metoden säkerställer:

  • Säkerhetsregler finns bredvid de data som de skyddar
  • Typsäkra principuttryck fångar fel vid kompileringstidpunkt
  • Omfaktorisering av entitetsfält uppdaterar automatiskt behörighetskontroller