data-modeling
Use when the app needs to store or read data — records, a database, entities, CRUD, lists, "save/remember X", or per-user data with row-level security. This app's data layer is Rayfin's: you declare entities as TypeScript classes with decorators in packages/data/src/, register them in the schema, and read/write them through the typed rayfin-client. Covers: defining an @entity, field decorators, registering it, per-entity access with @role, owner-only row-level security, and the client query/mutation API. Triggers: data, database, model, entity, schema, table, record, CRUD, create, read, update, delete, list, store, save, persist, per-user, row-level security, RLS, access control, ownership.
- License 许可
- MIT
- 所属仓库
- microsoft/rayfin
- 最近更新
- 2026-10-30
- Stars
- ★ 655
- Forks
- 73
01 前言 Front Matter
- name
- data-modeling
- description
- Use when the app needs to store or read data — records, a database, entities, CRUD, lists, "save/remember X", or per-user data with row-level security. This app's data layer is Rayfin's: you declare entities as TypeScript classes with decorators in packages/data/src/, register them in the schema, and read/write them through the typed rayfin-client. Covers: defining an @entity, field decorators, registering it, per-entity access with @role, owner-only row-level security, and the client query/mutation API. Triggers: data, database, model, entity, schema, table, record, CRUD, create, read, update, delete, list, store, save, persist, per-user, row-level security, RLS, access control, ownership.
02 资源文件 4
- 脚本kit/data/Item.ts1.8 KB
- 脚本kit/data/schema.ts1.2 KB
- 脚本kit/shared/index.ts464 B
- 参考文档pack.json884 B
03 SKILL.md 正文
Data modeling — entities, schema, and row-level security
This app persists data with Rayfin data. You define entities as decorated
TypeScript classes under packages/data/src/, register them in
packages/data/src/index.ts, define their isomorphic contracts in
packages/shared/src/index.ts, and read/write them with the typed client from
packages/frontend/src/lib/rayfin-client.ts (await getRayfinClient()).
Read the docs first — they ship in the packages
Rayfin's data rules are owned by the installed packages, not by this skill. Decorators, field options, relationships, permissions, the query API and the platform's constraints all move between releases. Read them from disk:
| You need… | Read |
|---|---|
@entity, every field decorator, and their options |
node_modules/@microsoft/rayfin-core/assets/docs/decorators.md |
Permissions end to end — @role, the policy DSL, claims, include / exclude |
node_modules/@microsoft/rayfin-guide/assets/docs/data/permissions.md |
The @anonymous / @authenticated shorthands |
node_modules/@microsoft/rayfin-core/assets/docs/permissions.md |
| Entity authoring end to end, relationships, schema registration | node_modules/@microsoft/rayfin-guide/assets/docs/data/overview.md |
| Reading and writing with the client | node_modules/@microsoft/rayfin-guide/assets/docs/data/graphql.md |
| Paging, cursors, text-field nullability | node_modules/@microsoft/rayfin-data/assets/docs/index.md |
| Constraints that will bite you — text length, FK naming, many-to-many, dialect | node_modules/@microsoft/rayfin-guide/assets/docs/known-limitations.md |
Read known-limitations.md before you design entities. It is short, and it
is where the platform tells you what it will not do.
Everything below is about this template — what it turns on, where files go, and how its build is wired. For anything about Rayfin itself, use the table.
Step 1 — turn the data service on
The base template keeps the data service off, because a dashboard over a
semantic model does not need a database. Turn it on for an app that needs
persistence:
npm run pack:add -- data-modeling
That flips data.enabled in rayfin/rayfin.yml and plants a starter entity in
packages/data/src/Item.ts, registered in packages/data/src/index.ts, with its
isomorphic contract in packages/shared/src/index.ts.
Re-applying is safe: it keeps files you have edited, and --force-seeds is the
explicit way back to the pack's version.
The template authenticates before rendering app content through its dynamic auth provider and gate.
Keep that boundary intact and follow the installed rayfin-guide/assets/docs/auth/ pages for additional service-specific requirements.
Preserve server-side entity permissions and row-level security.
Do not replace an authentication failure with anonymous access or block the entire app because it is outside the Fabric portal.
Step 2 — write entity files
One file per entity under packages/data/src/, for example
packages/data/src/Note.ts.
Start from the seeded Item.ts — rename it and change the fields.
Editing a working entity is more reliable than writing one from nothing.
When the real model replaces the example, remove the unused starter Item
runtime entity, its packages/data/src/index.ts registration, and its
packages/shared/src/index.ts contract so it does not become user-visible.
@microsoft/rayfin-core, @microsoft/rayfin-data and @microsoft/rayfin-client
are already pinned in the base app — nothing to install.
For the decorator set, field options, relationship syntax, FK naming and the
many-to-many rule, read rayfin-core/assets/docs/decorators.md and
rayfin-guide/assets/docs/data/overview.md, then known-limitations.md.
Step 3 — register entities in this template's schema
packages/data/src/index.ts starts with the seeded Item registration, while
packages/shared/src/index.ts owns its isomorphic record contract and schema
type map.
Add every entity, including join entities, to both packages:
// packages/shared/src/index.ts
export interface NoteRecord {
id: number;
title: string;
}
export type UniversalAppSchema = {
Note: NoteRecord;
};
// packages/data/src/index.ts
import { Note } from './Note.js';
export const schema = [Note];
The client's generic type comes from
UniversalAppSchema(already referenced bypackages/frontend/src/lib/rayfin-client.ts), so add every entity to both theschemaarray: one registered in the array but missing from the type is reachable at runtime and invisible to the compiler.Type-check with
tsc -b, nevertsc --noEmit. The workspace packages are referenced TypeScript projects, and the frontend client imports the shared schema type, so a baretsc --noEmitfails withTS6305until the referenced project has been built. Runnpm run typecheckfor the real referenced-project check.npm run buildusestsc -b --noCheckfor speed and does not prove the entity types are correct.
Step 4 — read and write
The query chain, mutations, findById, filtering and paging are documented in
rayfin-guide/assets/docs/data/graphql.md and
rayfin-data/assets/docs/index.md. Use await getRayfinClient() from
packages/frontend/src/lib/rayfin-client.ts inside an async query or mutation; that helper is this template's;
the API it returns
is the package's.
For the interface over your entities — optimistic updates, forms, and the
loading / empty / error states — read crud-ui, which ships the kit.
Step 5 — per-user data
"Each person sees only their own …" is a server-side @role policy, never a
filter in the UI. A client-side filter still leaves the rows fetchable.
Read rayfin-guide/assets/docs/data/permissions.md for the decorator, the typed
policy DSL, the supported claims, logical composition, and field visibility — it
is the fullest treatment. rayfin-core/assets/docs/permissions.md adds the
@anonymous / @authenticated shorthands, owner-field typing, and owner
stamping.
Keep authentication and authorization on the data operations that require them.
Notes
- Stable features only. Use
@authenticated/@role('authenticated', …). Anonymous data access on Fabric requires a tenant admin switch — seerayfin-guide/assets/docs/data/overview.md. If asked for public data, say so and use authenticated access. - Deploying ships the data model. A schema change migrates on the next
deploy.
Read
app-deploymentand follow the installed, version-matched CLI guide.
<!-- MAINTAINERS: this skill owns this template — the data service toggle, the workspace schema shape, the tsc -b build note, and the auth pairing. It does not own Rayfin.
Rayfin's own rules are read at runtime from the installed packages' docs
(rayfinDocs.dir, today assets/docs), so they cannot drift from the version a
generated app actually has. That replaces the previous arrangement, where this
file hand-mirrored rules from the CLI's bundled skill:rayfin and had to be
diffed against it on every CLI bump. Drift under that arrangement had already
shipped once: bare @text() appeared in every example here while the
authoritative rule required an explicit max on MSSQL.
-->
04 同仓库更多 Skills
rayfin-getting-started
Use when starting or creating a NEW Rayfin app, or when a Rayfin task comes up and you are not yet inside a Rayfin project. Gets you into a project with the Rayfin CLI, then hands off to the authoritative, version-locked in-project rayfin skill/docs that own all in-project work. Triggers: build a Rayfin app, start a Rayfin project, create a new Rayfin app, create-rayfin, npm create @microsoft/rayfin, rayfin init, scaffold rayfin, rayfin CLI, rayfin template, universal app, awesome-rayfin gallery, get started with Rayfin
visuals
Use when user wants to incorporate charts, graphs, data grid, or other visual representations of data into their project. Use VegaVisual and DataGrid components to create these visuals, utilizing the shared DataTable input, formatting, theme, and interactivity. Covers the onInteraction selection/click events host apps consume, named multi-table data input for layered overlays and reference lines, and Vega-Lite native selections. Triggers: chart, graph, plot, dashboard, KPI, metric, trend, scorecard, data grid, visualize.
schema-discovery
Explore Power BI semantic model schemas using DAX INFO functions. Progressive metadata discovery strategy, scope estimation, and narrowing techniques for tables, columns, measures, and relationships.
query-design
Separates DAX data-fetching from TypeScript presentation. Guides when to use DAX vs. TypeScript vs. Vega-Lite for aggregation, total rows, FORMAT(), SELECTCOLUMNS, BLANK handling, filtering, multi-grain queries, cross-filtering and cross-highlight subset/overlay queries, and format strings.
functions-capability
Apply and build the Universal App functions capability. Use for trusted server-side logic, secrets, external APIs, custom model endpoints, published Fabric data agents, webhooks, or privileged operations.
fabric-sdk
How to query Fabric data from a running app through the Rayfin connectors client. Use getRayfinClient().connectors.<name>.executeQuery to run DAX against a semantic model, and toQueryResult to normalize the response.