Defina modelos de dados para Fabric Apps

O Fabric Apps utiliza decoradores TypeScript para definir modelos de dados que geram tabelas de base de dados e APIs. Defines cada entidade como uma classe decorada com @entity(), adicionas decoradores de campo para tipos de dados e mapeias relações entre as entidades.

Para orientações sobre autorização e controlo de acessos, consulte Definir permissões de dados.

Pré-requisitos

  • Um projeto Fabric Apps criado com npm create @microsoft/rayfin@latest ou inicializado com npx rayfin init.
  • Compreensão básica de classes e decoradores de TypeScript.

Definir uma entidade

Para criar um modelo de dados, adicione o @entity() decorador a uma classe TypeScript. Depois, importa os decoradores necessários de @microsoft/rayfin-core:

import { entity, uuid, text, date } from '@microsoft/rayfin-core';

@entity()
export class Todo {
  @uuid() id!: string;
  @text() title!: string;
  @text({ optional: true }) description?: string;
  @date() createdAt!: Date;
  @date() updatedAt!: Date;
}

Esta entidade gera uma Todo tabela com colunas para id, title, description, createdAt, e updatedAt.

Chaves primárias

Cada entidade utiliza um campo UUID string nomeado id como sua chave primária. Se não declarares id explicitamente, a Fabric Apps adiciona-o automaticamente ao esquema.

  • O id campo é opcional durante as operações de criação — o servidor gera um UUID se o omitir.
  • Pode fornecer o seu próprio UUID na altura da criação, se preferir identificadores gerados pelo cliente.
  • Chaves primárias compostas e nomes de chaves personalizadas não são suportados.
@entity()
export class Note {
  @uuid() id!: string;  // UUID primary key, auto-generated when omitted
  @text() title!: string;
  @text() content!: string;
}

Tipos de dados suportados

Use estes decoradores para definir os tipos de campo:

Decorador Tipo Descrição
@uuid() cadeia (de caracteres) Campo de identificador único.
@text() cadeia (de caracteres) Campo de texto com restrições opcionais de comprimento.
@int() número Campo inteiro.
@decimal() número Campo decimal ou numérico.
@boolean() Booleano Campo verdadeiro ou falso.
@date() Date Campo de data e hora, serializa a partir de strings ISO ou de objetos Date.
@email() cadeia (de caracteres) Campo de texto com validação de email.
@set() cadeia (de caracteres) Conjunto enumerado de literais de string.

Exemplo com múltiplos tipos

import { entity, uuid, text, int, decimal, boolean, date, set } from '@microsoft/rayfin-core';

@entity()
export class Product {
  @uuid() id!: string;
  @text() name!: string;
  @decimal() price!: number;
  @int() stockQuantity!: number;
  @boolean() isAvailable!: boolean;
  @date() createdAt!: Date;
  @set('draft', 'published', 'archived') status!: 'draft' | 'published' | 'archived';
}

Modificadores de tipo

Adicione modificadores aos decoradores de campos para configurar validação e restrições:

Modificador Descrição
{ optional: true } Permitir valores NULL. Os campos são obrigatórios por defeito.
{ unique: true } Adicione uma restrição única.
{ default: value } Defina uma expressão de valor padrão.
{ max: n }, { min: n } Restrições de comprimento da cadeia (número máximo e mínimo de caracteres).
{ min: n }, { max: n } Restrições de valor numérico.

Observação

O marcador opcional TypeScript (? após o nome de uma propriedade) afeta apenas o tipo TypeScript estático. Não torna a coluna da base de dados anulável. Para tornar um campo anulável, adicione { optional: true } ao decorador. Use ! para afirmar que um campo requerido é inicializado pelo framework.

Exemplo com modificadores

@entity()
export class User {
  @uuid() id!: string;
  @email({ unique: true }) email!: string;
  @text({ min: 3, max: 50 }) username!: string;
  @text({ optional: true, max: 500 }) bio?: string;
  @int({ min: 0, max: 150 }) age!: number;
  @boolean({ default: false }) isVerified!: boolean;
}

Definir relações

Utilize os decoradores @one() e @many() para definir propriedades de navegação entre entidades. O Fabric Apps gera automaticamente colunas de chave estrangeira quando defines relações.

  • Um para muitos – Utilize @many() no pai e @one() no filho.
  • Muitos-para-um – Utilize @one() no filho para referenciar o pai.
  • As relações de muitos para muitos não são suportadas — utilize antes uma entidade associativa explícita.

Exemplo com a relação um-para-muitos

import { entity, uuid, text, date, one, many } from '@microsoft/rayfin-core';

@entity()
export class Notebook {
  @uuid() id!: string;
  @text() name!: string;
  @date() createdAt!: Date;
  @many(() => Note) notes?: Note[];
}

@entity()
export class Note {
  @uuid() id!: string;
  @text() title!: string;
  @text() content!: string;
  @date() createdAt!: Date;
  @text() notebook_id!: string;
  @one(() => Notebook) notebook?: Notebook;
}

Quando define @one(() => Notebook) na entidade Note, o Fabric Apps cria automaticamente uma coluna de chave estrangeira notebook_id. Declare explicitamente o campo chave estrangeira apenas se planear lê-lo ou defini-lo no código da aplicação.

Convenção de nomenclatura de chaves estrangeiras

Ao definir um campo de chave estrangeira, use a {property}_id convenção de nomenclatura:

@entity()
export class Note {
  @uuid() id!: string;
  @text() notebook_id!: string;      // Foreign key field
  @one(() => Notebook) notebook?: Notebook;  // Navigation property
}

Nomes de chave estrangeiras personalizados (foreignKey, targetKey opções) não são suportados.

Entidades do sistema de referência

Fabric Apps não suporta relações @one() que apontem para entidades do sistema como a entidade USER incorporada. Para associar uma linha ao utilizador iniciado sessão, adicione um campo simples user_id de tipo @text() e preencha-o a partir das reivindicações de autenticação (tipicamente claims.sub):

@entity()
export class Task {
  @uuid() id!: string;
  @text() title!: string;
  @text() user_id!: string;  // System user ID from claims.sub
}

Filtre as linhas por user_id nas suas políticas de função para impor o acesso por utilizador.

Registar entidades no esquema

Adicione todas as classes de entidade a rayfin/data/schema.ts para que o cliente possa gerar proxies GraphQL:

import type { Note } from './Note.js';
import type { Notebook } from './Notebook.js';

export type NotesAppSchema = {
  Note: Note;
  Notebook: Notebook;
};

Atualize este tipo sempre que criar uma nova entidade.

Aplicar alterações no esquema

Depois de definir ou modificar as entidades, aplique as alterações à base de dados:

  1. Implemente o esquema atualizado no Fabric:

    npx rayfin up db apply
    
  2. Se a alteração do esquema incluir operações destrutivas (eliminar colunas, renomear tabelas), o CLI avisa e recusa-se a avançar. Use --force para anular a verificação de segurança:

    npx rayfin up db apply --force
    

Observação

O uso --force pode causar perda de dados. Revise cuidadosamente as operações listadas antes de prosseguir.

Melhores práticas

  • Defina campos de chave estrangeira apenas quando precisar de os ler ou definir em código — o Fabric Apps gera-os automaticamente a partir dos decoradores de navegação.
  • Utilize importações relativas com extensões .js nos ficheiros de entidades para que o JavaScript ESM emitido seja corretamente resolvido.
  • Para padrões de autorização e acesso baseado em funções, veja Definir permissões de dados.

Solução de problemas

Relações em falta

Se as relações não aparecerem na API, verifique que:

  • O decorador de navegação (@one() ou @many()) está presente.
  • A entidade está registada em rayfin/data/schema.ts.