Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Fabric приложения используют декораторы TypeScript для определения моделей данных, создающих таблицы баз данных и API. Вы определяете каждую сущность как класс, украшенный @entity(), добавляйте декораторы полей для типов данных и сопоставляете связи между сущностями.
Рекомендации по авторизации и управлению доступом см. в разделе "Определение разрешений данных".
Необходимые условия
- Проект Fabric Apps, созданный с помощью
npm create @microsoft/rayfin@latestили инициализированный с помощьюnpx rayfin init. - Базовое понимание классов TypeScript и декораторов.
Определение сущности
Чтобы создать модель данных, добавьте декоратор @entity() к классу TypeScript. Затем импортируйте необходимые декораторы из @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;
}
Эта сущность создает таблицу Todo со столбцами для id, , titleи descriptioncreatedAtupdatedAt.
Первичные ключи
Каждая сущность использует поле UUID string с именем id в качестве первичного ключа. Если вы не объявляете id явно, Fabric Apps автоматически добавляет его в схему.
- Поле
idявляется необязательным во время операций создания— сервер создает идентификатор UUID, если он не указан. - Вы можете указать собственный идентификатор UUID во время создания, если вы предпочитаете идентификаторы, созданные клиентом.
- Составные первичные ключи и пользовательские имена ключей не поддерживаются.
@entity()
export class Note {
@uuid() id!: string; // UUID primary key, auto-generated when omitted
@text() title!: string;
@text() content!: string;
}
Поддерживаемые типы данных
Используйте эти декораторы для определения типов полей:
| Декоратор | Тип | Description |
|---|---|---|
@uuid() |
string | Поле уникального идентификатора. |
@text() |
string | Текстовое поле с необязательными ограничениями длины. |
@int() |
number | Целочисленное поле. |
@decimal() |
number | Поле для десятичных или числовых значений. |
@boolean() |
boolean | Поле со значением «истина» или «ложь». |
@date() |
Дата | Поле даты и времени, сериализуется из строк ISO или объектов Date. |
@email() |
string | Текстовое поле с проверкой электронной почты. |
@set() |
string | Перечисляемый набор строковых литералов. |
Пример с несколькими типами
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';
}
Модификаторы типов
Добавьте модификаторы в декораторы полей для настройки проверки и ограничений:
| Модификатор | Description |
|---|---|
{ optional: true } |
Разрешить значения NULL. Поля требуются по умолчанию. |
{ unique: true } |
Добавьте уникальное ограничение. |
{ default: value } |
Задайте выражение значения по умолчанию. |
{ max: n }, { min: n } |
Ограничения длины строки (максимальное и минимальное количество символов). |
{ min: n }, { max: n } |
Ограничения числовых значений. |
Замечание
Необязательный маркер TypeScript (? после имени свойства) влияет только на статический тип TypeScript. Он не делает столбец базы данных пустым. Чтобы сделать поле пустым, добавьте { optional: true } в декоратор. Используется ! для утверждения о том, что необходимое поле инициализировано платформой.
Пример с модификаторами
@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;
}
Определение связей
Используйте декораторы @one() и @many() для определения навигационных свойств между сущностями. Приложения Fabric автоматически создают столбцы внешнего ключа при создании связей.
-
Один-ко-многим — используйте
@many()в родительском элементе и@one()в дочернем элементе. -
Многие к одному — используйте
@one()в дочернем элементе, чтобы ссылаться на родительский элемент. - Отношения «многие ко многим» не поддерживаются — используйте вместо этого явную связующую сущность.
Пример связи "один ко многим"
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;
}
При определении @one(() => Notebook) для сущности Note Fabric Apps автоматически создает столбец внешнего ключа notebook_id. Объявите поле внешнего ключа явным образом, только если вы планируете считывать или задавать его в коде приложения.
Соглашение об именовании внешних ключей
При определении поля внешнего ключа используйте соглашение об именовании {property}_id:
@entity()
export class Note {
@uuid() id!: string;
@text() notebook_id!: string; // Foreign key field
@one(() => Notebook) notebook?: Notebook; // Navigation property
}
Пользовательские названия внешних ключей (параметры foreignKey, targetKey) не поддерживаются.
Эталонные системные сущности
Fabric Приложения не поддерживают связи @one(), указывающие на системные сущности, такие как встроенная сущность USER. Чтобы связать строку с вошедшим в систему пользователем, добавьте обычное поле user_id типа @text() и заполните его из утверждений аутентификации (обычно claims.sub):
@entity()
export class Task {
@uuid() id!: string;
@text() title!: string;
@text() user_id!: string; // System user ID from claims.sub
}
Фильтруйте строки по user_id в политиках ролей, чтобы обеспечить доступ для каждого пользователя.
Регистрация сущностей в схеме
Добавьте все классы сущностей в rayfin/data/schema.ts, чтобы клиент мог сгенерировать прокси GraphQL:
import type { Note } from './Note.js';
import type { Notebook } from './Notebook.js';
export type NotesAppSchema = {
Note: Note;
Notebook: Notebook;
};
Обновляйте этот тип каждый раз, когда вы создаёте новую сущность.
Применение изменений схемы
После определения или изменения сущностей примените изменения к базе данных:
Разверните обновленную схему в Fabric:
npx rayfin up db applyЕсли изменение схемы включает деструктивные операции (удаление столбцов, переименование таблиц), интерфейс командной строки предупреждает вас и отказывается продолжить. Используйте
--forceдля переопределения проверки безопасности:npx rayfin up db apply --force
Замечание
Использование --force может привести к потере данных. Внимательно просмотрите перечисленные операции, прежде чем продолжить.
Лучшие практики
- Определяйте поля внешних ключей только тогда, когда вам нужно читать или задавать их в коде — Fabric Apps автоматически создаёт их на основе декораторов навигации.
- Используйте относительные импорты с расширениями
.jsв файлах сущностей, чтобы сгенерированный JavaScript ESM корректно разрешался. - Шаблоны авторизации и доступ на основе ролей см. в разделе "Определение разрешений данных".
Troubleshooting
Отсутствующие связи
Если связи не отображаются в API, убедитесь, что:
- Декоратор навигации (
@one()или@many()) присутствует. - Объект зарегистрирован в
rayfin/data/schema.ts.