Visão geral do modelo de programação

O Rayfin SDK utiliza um modelo de programação orientado por decoradores, onde define o seu esquema de dados uma vez em TypeScript e recebe automaticamente APIs prontas para produção, clientes seguros para tipos e infraestrutura.

Conceitos-chave

O Rayfin SDK combina três elementos fundamentais:

  • Esquema orientado por decoradores: Use decoradores TypeScript para definir modelos de dados, permissões e relações.
  • Geração automática de API: As suas classes decoradas tornam-se endpoints GraphQL sem escrever código controlador.
  • Clientes seguros para tipos: Os clientes TypeScript gerados fornecem validação em tempo de compilação para consultas e mutações.

Como funciona

Quando cria uma aplicação Fabric, o seu código passa por estas fases:

# Stage O que acontece
1 Desenvolvedor Tu crias a aplicação no editor que escolheres.
2 TypeScript Escreves classes de entidade em TypeScript.
3 Decorators Anotas classes e campos com @entity, @uuid, @text, @role e outros decoradores.
4 Schema A CLI compila as classes decoradas num esquema de base de dados, políticas de permissões e configuração da API.
5 APIs O esquema é disponibilizado como endpoints GraphQL.
6 Client O RayfinClient gerado expõe um cliente de dados e autenticação com segurança de tipos para esses endpoints.
7 Application A sua aplicação frontend consome o cliente para ler e escrever dados.

1. Definir modelos de dados com decoradores

Define a sua estrutura de dados usando classes TypeScript e decoradores a partir de @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. Geração de esquemas

A CLI do Rayfin (npx rayfin) analisa as suas classes decoradas e gera:

  • Esquema de base de dados - Tabelas, colunas, restrições e índices
  • Configuração da API - Definições de pontos de extremidade GraphQL
  • Políticas de permissões - Segurança ao nível de linha e controlo de acesso ao nível de campo

4. Utilização de cliente com segurança de tipos

As APIs GraphQL estão disponíveis para realizar operações CRUD na sua base de dados. O SDK Rayfin fornece uma operação cliente de dados pronta a usar para ler, escrever ou eliminar dados.

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

Referência do decorador

O Rayfin SDK fornece decoradores para padrões comuns de modelação de dados:

Decoradores de entidades

Decorador Purpose Example
@entity() Marque uma classe como entidade de base de dados @entity() class Product

Decoradores de propriedades

Decorador Tipo de base de dados Tipo TypeScript
@uuid() UNIQUEIDENTIFIER string
@text() NVARCHAR string
@int() INT number
@decimal() DECIMAL number
@bool() BIT boolean
@date() DATETIME2 Date

Decoradores de permissão

Decorador Purpose
@role() Definir permissões com base em funções

Consulte Definir permissões de dados para detalhes de autorização.

Funções

Crie uma UserDataFunctions instância e registre cada função chamando udf.func(name, handler, connections?).

Siga estas regras ao definir uma função:

  • Coloque o RayfinContext parâmetro em qualquer lugar da assinatura do handler. O tempo de execução identifica-o pelo tipo, injeta-o e exclui-o das entradas da função geradas.
  • Declare uma conexão para cada token delegado de que a função necessita. Omita o array de conexões para funções que apenas acedem a dados da app ou que não precisam de tokens delegados.

O exemplo seguinte regista uma função simples e uma função que utiliza o contexto de invocação:

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';
  },
);

O RayfinContext fornece os serviços de runtime da função:

Membro Purpose
ctx.accessToken Fornece o Rayfin JSON Web Token (JWT) do utilizador iniciado sessão. Decifra a sub reivindicação para obter um ID de utilizador estável.
ctx.Tokens.<Audience> Obtém um token de recurso fornecido pela plataforma para um destinatário declarado na anotação RayfinContext. As Funções Implementadas utilizam a identidade da aplicação e as suas permissões. Para mais detalhes, consulte Ligar Funções a recursos externos.
ctx.getSecret('NAME') Obtém um segredo para a invocação atual. Devolve undefined quando o segredo não estiver definido.
ctx.getDataClient() Obtém a API de dados tipificados das suas entidades. O cliente suporta operações de criação, findManyatualização, eliminação e upsert.
ctx.baseUrl Fornece o endpoint Rayfin para o item atual.
ctx.publishableKey Fornece a chave publicável para o item atual.

Para configuração, depuração local e instruções de implementação, consulte Usar Funções em Aplicações Fabric.

Fluxo de trabalho de desenvolvimento

Um ciclo típico de desenvolvimento segue este padrão:

  1. Definir ou modificar modelos de dados - Adicionar ou atualizar classes TypeScript com decoradores
  2. Testa localmente com backend remoto - Executa o npm run dev para testar as alterações no código do teu frontend com o backend da tua App no Fabric.
  3. Implementar no Fabric - Execute npx rayfin up para implementar no serviço gerido do Fabric e aplique as alterações ao esquema.

As alterações aos seus modelos TypeScript refletem-se automaticamente em toda a stack — desde o esquema da base de dados até aos endpoints da API e aos tipos do cliente.

Authorization

As permissões são definidas juntamente com os seus modelos de dados usando o @role decorador:

@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;
}

Esta abordagem garante:

  • As regras de segurança estão ao lado dos dados que protegem
  • Expressões de políticas seguras por tipos detetam erros em tempo de compilação
  • A refatorização dos campos da entidade atualiza automaticamente as verificações de permissão