@microsoft/rayfin-guide 1.33.2 → 1.34.0-alpha.1148

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
17
17
  | `RAYFIN_PUBLIC_TENANT_ID` | Entra ID tenant for workspace disambiguation. | `rayfin up` |
18
18
  | `RAYFIN_PUBLIC_PORTAL_URL` | Fabric Portal base URL (for example, `https://app.fabric.microsoft.com/`). | `rayfin up` |
19
19
  | `RAYFIN_PUBLIC_SERVICE_MODE` | `rayfin` (real backend) or `mock` (local testing). | User-set in `rayfin/.env` |
20
+ | `RAYFIN_PUBLIC_FRONTEND_PORT` | Stable per-project frontend dev-server port. Assigned once and reused so the dev server pins a deterministic origin the deployed backend can allow-list. | `rayfin dev` / `rayfin up` |
20
21
 
21
22
  ### Framework mapping
22
23
 
@@ -31,9 +32,14 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
31
32
  | `RAYFIN_PUBLIC_TENANT_ID` | `VITE_FABRIC_TENANT_ID` | `NEXT_PUBLIC_FABRIC_TENANT_ID` | `TENANT_ID` |
32
33
  | `RAYFIN_PUBLIC_PORTAL_URL` | `VITE_FABRIC_PORTAL_URL` | `NEXT_PUBLIC_FABRIC_PORTAL_URL` | `PORTAL_URL` |
33
34
  | `RAYFIN_PUBLIC_SERVICE_MODE` | `VITE_SERVICE_MODE` | `NEXT_PUBLIC_SERVICE_MODE` | `SERVICE_MODE` |
35
+ | `RAYFIN_PUBLIC_FRONTEND_PORT` | `VITE_PORT` | `PORT` | `FRONTEND_PORT` |
34
36
 
35
37
  Custom `RAYFIN_PUBLIC_*` variables you add follow a generic pattern: `RAYFIN_PUBLIC_FOO` becomes `VITE_RAYFIN_FOO` (Vite), `NEXT_PUBLIC_RAYFIN_FOO` (Next.js), or `FOO` (plain).
36
38
 
39
+ `RAYFIN_PUBLIC_FRONTEND_PORT` maps to the port variable each dev server reads (`VITE_PORT` for Vite, `PORT` for Next.js).
40
+ The sample `vite.config.ts` files pin the server to it with `strictPort`, so if the assigned port is already taken the dev server fails fast instead of silently drifting to another port.
41
+ To run on a different port, set `RAYFIN_PUBLIC_FRONTEND_PORT` in `rayfin/.env` (then re-run `rayfin env`); `rayfin up` registers whatever value is assigned in the deployed redirect allow-list.
42
+
37
43
  ## Tooling overrides
38
44
 
39
45
  These variables configure CLI and extension behavior.
@@ -32,7 +32,7 @@ For the full walkthrough, see the [CLI Quickstart](./quickstart.md) or the [Buil
32
32
  | Command | Description |
33
33
  | --- | --- |
34
34
  | `npm install --save-dev @microsoft/rayfin-cli` | Install the Rayfin CLI as a dev dependency. Not needed if you scaffolded with `npm create @microsoft/rayfin@latest`. |
35
- | `npm create @microsoft/rayfin <name>` | Scaffold a new project from a template. Use `-t, --template <name>` to skip the interactive prompt or `--list-templates` to see available templates. |
35
+ | `npm create @microsoft/rayfin <name>` | Scaffold a new project from a template. See [Project templates](./templates.md) for choosing a built-in template, scaffolding from a git URL, registering your own template sources, and authoring templates. |
36
36
  | `npx rayfin init [directory]` | Initialize a new Rayfin project interactively. Prompts for project name, services (Auth, Data), and auth methods. Creates the `rayfin/` directory with starter files. |
37
37
  | `npx rayfin init ai-files install` | Install or refresh the [agent context files](./ai-files.md) (`AGENTS.md`, `.mcp.json`, `.agents/skills/rayfin/SKILL.md`) so coding agents know how to work with your project. Idempotent; auto-runs as part of the scaffold pipeline. |
38
38
  | `npx rayfin init ai-files status` | Print the current state of each agent file. Add `--json` for machine-readable output. |
@@ -20,7 +20,7 @@ The project name is a **positional argument** — not a flag.
20
20
  Provide a valid directory name like `my-app`, or use `.` to scaffold into the current directory.
21
21
 
22
22
  - The CLI prompts for a template and database dialect interactively.
23
- - Use `-t, --template <name>` to skip the template prompt (run `--list-templates` to see options).
23
+ - See [Project templates](./templates.md) for skipping the prompt with `-t, --template`, scaffolding from a git URL, or authoring your own templates.
24
24
  - Expected result: `✔ Project created`.
25
25
 
26
26
  ## Add Rayfin to an existing project
@@ -0,0 +1,391 @@
1
+ ---
2
+ sidebar_position: 3
3
+ ---
4
+
5
+ # Project templates
6
+
7
+ Templates let Rayfin builders scaffold a project from a known starting point: a built-in starter, a local directory, a git repository your team maintains, or a registered third-party source.
8
+
9
+ This page covers using templates and authoring your own.
10
+
11
+ ## Where templates come from
12
+
13
+ Every `npm create @microsoft/rayfin@latest` or `npx rayfin init` invocation can pull from any of these sources:
14
+
15
+ - **Built-in templates** ship inside `@microsoft/rayfin-cli` and work offline.
16
+ - **Local template directories** let you test or reuse a template on disk.
17
+ - **External git repositories** are cloned on demand from any HTTPS, SSH, or `git@` URL.
18
+ - **Template registries** are YAML files that name git URLs you (or your team) want to surface alongside the built-ins.
19
+
20
+ External and local template sources are discovered through `rayfin-template.yml` manifests inside the selected source directory.
21
+ Built-in templates are packaged with the CLI and appear in `--list-templates` automatically.
22
+
23
+ ## List available templates
24
+
25
+ Use `--list-templates` to see every template the CLI can scaffold from in your current directory:
26
+
27
+ ```bash
28
+ npx rayfin init --list-templates
29
+ ```
30
+
31
+ The output is a JSON document on stdout, suitable for piping to a script or AI agent.
32
+ The shape is versioned by `schemaVersion`:
33
+
34
+ ```json
35
+ {
36
+ "schemaVersion": 1,
37
+ "bundled": [
38
+ {
39
+ "name": "todoapp",
40
+ "displayName": "Basic Todo App",
41
+ "description": "End-to-end Fabric-authenticated todo CRUD with a Rayfin data model and per-user row-level security",
42
+ "source": "built-in"
43
+ }
44
+ ],
45
+ "registry": [
46
+ {
47
+ "name": "team-templates",
48
+ "displayName": "Team Templates",
49
+ "description": "Our team's starter collection",
50
+ "url": "https://github.com/example-org/rayfin-templates.git",
51
+ "ref": "v1.2.0",
52
+ "path": "catalogs/official",
53
+ "source": "C:\\Users\\you\\.rayfin\\template-registries.yml"
54
+ }
55
+ ]
56
+ }
57
+ ```
58
+
59
+ If any registry file fails to load or contains conflicts, a `warnings` array is appended to the output.
60
+ The list does **not** include arbitrary git URLs — it shows only built-ins plus what is registered through `template-registries.yml` files.
61
+ Template names in examples can change over time; run `--list-templates` for the current copy/paste-ready names.
62
+
63
+ ## Scaffold from a built-in template
64
+
65
+ The default flow prompts you to pick a template interactively:
66
+
67
+ ```bash
68
+ npm create @microsoft/rayfin@latest my-app
69
+ ```
70
+
71
+ To skip the prompt, pass `-t`/`--template <name>` using one of the names from `--list-templates`:
72
+
73
+ ```bash
74
+ npm create @microsoft/rayfin@latest my-app -- --template todoapp
75
+ ```
76
+
77
+ ## Scaffold from an external git repository
78
+
79
+ Pass any git URL to `-t`/`--template`:
80
+
81
+ ```bash
82
+ npx rayfin init my-app -t https://github.com/example-org/my-template.git
83
+ ```
84
+
85
+ Supported URL formats are HTTPS, SSH, `git@host:org/repo.git`, and `file://`.
86
+ The CLI does a shallow clone into a temp directory, scaffolds, then deletes the clone.
87
+
88
+ To pin to a specific branch, tag, or commit, append `#<ref>` to the URL:
89
+
90
+ ```bash
91
+ npx rayfin init my-app -t https://github.com/example-org/my-template.git#v1.2.0
92
+ npx rayfin init my-app -t https://github.com/example-org/my-template.git#main
93
+ ```
94
+
95
+ Use a branch name, tag name, or **full** 40-character commit SHA.
96
+ Abbreviated SHAs are rejected because `git clone --branch` would treat them ambiguously.
97
+ For repeated use, register the repo in a `template-registries.yml` so the `ref` is kept in configuration (see [Add a template registry](#add-a-template-registry)) — then `-t <registry-name>` clones the pinned ref automatically.
98
+
99
+ ## Scaffold from a local template directory
100
+
101
+ Pass a relative or absolute path to `-t`/`--template` when the template is already on disk:
102
+
103
+ ```bash
104
+ npx rayfin init my-app -t ./my-template
105
+ ```
106
+
107
+ Local templates use the same `rayfin-template.yml` file format as git-backed templates for top-level entries.
108
+
109
+ > **Bare names resolve as template names, not paths.**
110
+ > Use `./`, `../`, or an absolute path when pointing at a local directory:
111
+ >
112
+ > POSIX shells:
113
+ >
114
+ > ```bash
115
+ > npx rayfin init my-app -t ./my-templates # local relative path
116
+ > npx rayfin init my-app -t ../shared/templates # parent directory
117
+ > npx rayfin init my-app -t /opt/templates/web # POSIX absolute
118
+ > ```
119
+ >
120
+ > PowerShell:
121
+ >
122
+ > ```powershell
123
+ > npx rayfin init my-app -t C:\templates\web # Windows absolute
124
+ > ```
125
+ >
126
+ > A bare value like `-t my-templates` is treated as a template name and looked up against the built-ins and registries.
127
+
128
+ ### Authentication for private repositories
129
+
130
+ The CLI uses your existing git credentials — SSH keys, Git Credential Manager, GitHub CLI auth, or whatever your environment already provides.
131
+ No credentials are stored or managed by Rayfin.
132
+
133
+ Interactive credential prompts are disabled, so a misconfigured environment fails fast instead of hanging.
134
+ For GitHub repos, run `gh auth setup-git` to wire credentials through Git Credential Manager.
135
+
136
+ ### Multi-template repositories
137
+
138
+ A single repository can publish multiple templates via the `entries` array in its `rayfin-template.yml` manifest (see [Author a template](#author-a-template)).
139
+
140
+ When you scaffold from a multi-template source interactively, the CLI shows a picker.
141
+ For non-interactive flows, pass `--template-name` with the entry's `name` or `path`:
142
+
143
+ ```bash
144
+ npx rayfin init my-app \
145
+ -t https://github.com/example-org/templates.git \
146
+ --template-name api-service \
147
+ --yes
148
+ ```
149
+
150
+ `--template-name` requires `--template`/`-t` pointing at a multi-template source — passing it on its own is an error.
151
+ The value must match one of the source's entry `name` or `path` values; against a built-in template name it has no effect.
152
+
153
+ ## Add a template registry
154
+
155
+ A registry is a YAML file that lists template repositories you want to surface in `--list-templates` and the interactive picker.
156
+ Edit a `template-registries.yml` file at one of these locations:
157
+
158
+ | Tier | Path | When to use |
159
+ | --- | --- | --- |
160
+ | **User-global** | `~/.rayfin/template-registries.yml` | Templates you use across many projects on this machine |
161
+ | **Project-local** | `<projectDir>/.rayfin/template-registries.yml` | Templates pinned to a specific project (commit alongside the repo) |
162
+
163
+ Both files are optional — the CLI also loads a bundled registry that ships with `@microsoft/rayfin-cli` itself.
164
+ The bundled registry that ships with current CLI releases may be empty.
165
+ Some templates the CLI ships with are protected and can't be overridden by a user or project entry that reuses their `name`; the rest can (see [Conflict handling](#conflict-handling) below).
166
+
167
+ > **Manage registries by hand-editing the YAML files.** There is no CLI command to add or remove registry entries.
168
+
169
+ ### Registry file format
170
+
171
+ ```yaml
172
+ registries:
173
+ - name: team-templates
174
+ displayName: Team Templates
175
+ description: Our team's reusable starters
176
+ url: https://github.com/example-org/rayfin-templates.git
177
+ ref: v1.2.0
178
+ path: catalogs/official
179
+ ```
180
+
181
+ Each entry supports the following fields:
182
+
183
+ | Field | Required | Description |
184
+ | --- | --- | --- |
185
+ | `name` | Yes | Unique identifier for this entry |
186
+ | `url` | Yes | Git URL of the template repository (HTTPS, SSH, `git@`, or `file://`) |
187
+ | `displayName` | No | Human-readable label (defaults to `name`) |
188
+ | `description` | No | Short description shown in pickers and `--list-templates` |
189
+ | `ref` | No | Git tag, branch, or full commit SHA to pin to (defaults to the repository's default branch) |
190
+ | `path` | No | Subdirectory inside the repo where the manifest lives |
191
+ | `templateName` | No | For a multi-template repo, the entry `name` or `path` to pre-select so consumers skip the picker |
192
+
193
+ ### Conflict handling
194
+
195
+ The CLI loads registries in tier order (bundled → user-global → project-local).
196
+ The first occurrence of any `name` wins; later tiers with the same name are skipped and listed under `warnings` in `--list-templates` output.
197
+ A few templates the CLI ships with are protected: a user or project entry that reuses their `name` is ignored and gets a dedicated warning.
198
+ Other name conflicts still resolve by tier order; rename one of the conflicting entries to resolve.
199
+
200
+ ## Author a template
201
+
202
+ A template is a directory with a `rayfin-template.yml` manifest at its root.
203
+ Template files are copied into the target directory, then Rayfin applies a small fixed set of scaffold transforms.
204
+ If your template includes `package.json`, Rayfin rewrites its `name` field to the generated project slug.
205
+ If `package.json` is not valid JSON, Rayfin leaves it as-is.
206
+ If your template includes `README.md`, Rayfin replaces the supported placeholders listed below.
207
+ Other file contents are not templated.
208
+ `__projectName__` placeholders in **filenames** are replaced with the user's project name.
209
+
210
+ The user's project name comes from the `[directory]` positional (`npm create @microsoft/rayfin@latest my-app` → `my-app`) unless they pass `--project-name` to override.
211
+
212
+ ### Minimal template
213
+
214
+ ```text
215
+ my-template/
216
+ ├── rayfin-template.yml
217
+ └── template/
218
+ ├── package.json
219
+ ├── README.md
220
+ └── src/
221
+ └── __projectName__.config.ts
222
+ ```
223
+
224
+ `rayfin-template.yml`:
225
+
226
+ ```yaml
227
+ apiVersion: v1
228
+ metadata:
229
+ name: my-starter
230
+ displayName: My Starter
231
+ description: A starter template for Rayfin projects
232
+ entries:
233
+ - name: my-starter
234
+ path: ./template
235
+ ```
236
+
237
+ When scaffolded into `my-app/`, the file `src/__projectName__.config.ts` is written as `src/my-app.config.ts`.
238
+
239
+ ### Publish and share an external template repository
240
+
241
+ Once your template is working, share it as a git repository so your team (or anyone else) can scaffold from it.
242
+
243
+ #### 1. Initialize a git repo for the template
244
+
245
+ From your template directory:
246
+
247
+ ```bash
248
+ git init
249
+ git add .
250
+ git commit -m "Initial template"
251
+ git remote add origin https://github.com/example-org/my-template.git
252
+ git push -u origin main
253
+ ```
254
+
255
+ #### 2. Tag a release
256
+
257
+ Don't ask consumers to scaffold from the moving `main` branch — pin to a tag so their scaffolds are reproducible:
258
+
259
+ ```bash
260
+ git tag v1.0.0
261
+ git push origin v1.0.0
262
+ ```
263
+
264
+ Bump the tag whenever you ship a meaningful change to the template.
265
+
266
+ #### 3. Share the URL
267
+
268
+ The simplest path is to hand consumers the git URL. They scaffold with:
269
+
270
+ ```bash
271
+ npx rayfin init my-app -t https://github.com/example-org/my-template.git#v1.0.0
272
+ ```
273
+
274
+ #### 4. (Optional) Surface it through a registry
275
+
276
+ If you want the template to appear in `rayfin init --list-templates` and the interactive picker — without consumers having to remember the URL — add it to a `template-registries.yml` file (see [Add a template registry](#add-a-template-registry)).
277
+
278
+ A team-shared `.rayfin/template-registries.yml` committed to the project root, or a personal `~/.rayfin/template-registries.yml`, both work:
279
+
280
+ ```yaml
281
+ registries:
282
+ - name: my-starter
283
+ displayName: My Starter
284
+ description: Our team's Rayfin starter
285
+ url: https://github.com/example-org/my-template.git
286
+ ref: v1.0.0
287
+ ```
288
+
289
+ After that, consumers scaffold by name:
290
+
291
+ ```bash
292
+ npx rayfin init my-app -t my-starter
293
+ ```
294
+
295
+ When you ship a new tag, update the `ref` and (ideally) commit the registry change so everyone on the team picks it up.
296
+
297
+ ### Try it locally before publishing
298
+
299
+ Test your template against a local path before pushing or tagging:
300
+
301
+ ```bash
302
+ npx rayfin init test-output -t ./my-template --yes
303
+ ```
304
+
305
+ ### Manifest reference
306
+
307
+ ```yaml
308
+ apiVersion: v1 # required, must be 'v1'
309
+ metadata:
310
+ name: my-collection # required, identifier for the manifest
311
+ displayName: My Collection
312
+ description: Optional description
313
+ version: 1.2.0 # accepted, currently informational only
314
+ tags: [todo, auth] # accepted, currently informational only
315
+ entries: # required, at least one entry
316
+ - name: api-service # template entry: scaffolds files from path
317
+ path: ./api-service
318
+ description: REST API with Rayfin data layer
319
+ ```
320
+
321
+ `metadata.displayName` and `metadata.description` are shown when scaffolding from this template.
322
+ `metadata.version` and `metadata.tags` are accepted by the manifest schema but are not surfaced in the CLI today.
323
+ Entry-level `description` is shown in the local multi-template picker.
324
+ For git-backed nested navigation, group descriptions are shown; template entry descriptions are not.
325
+
326
+ ### Single-entry vs multi-entry manifests
327
+
328
+ A single-entry manifest auto-selects with no picker:
329
+
330
+ ```yaml
331
+ entries:
332
+ - name: my-starter
333
+ path: .
334
+ ```
335
+
336
+ A multi-entry manifest shows an interactive picker (or requires `--template-name` for non-interactive flows):
337
+
338
+ ```yaml
339
+ entries:
340
+ - name: api-service
341
+ path: ./templates/api-service
342
+ - name: fullstack
343
+ path: ./templates/fullstack
344
+ ```
345
+
346
+ For local template directories, keep entries at the top level of `entries`.
347
+ Grouped nested navigation is available for git-backed template sources.
348
+
349
+ ### Group entries for nested navigation
350
+
351
+ Use `group` entries to organize larger collections.
352
+ Groups can nest, and the picker walks users through the hierarchy:
353
+
354
+ ```yaml
355
+ entries:
356
+ - group:
357
+ name: starters
358
+ displayName: Starter Apps
359
+ entries:
360
+ - name: hello-world
361
+ path: ./starters/hello-world
362
+ - name: todo-app
363
+ path: ./starters/todo-app
364
+ - name: standalone-app
365
+ path: ./standalone-app
366
+ ```
367
+
368
+ ### What's currently supported
369
+
370
+ Templates are intentionally minimal:
371
+
372
+ - Most file contents are copied as-is.
373
+ - `README.md` supports `{{PROJECT_NAME}}`, `{{PROJECT_NAME_KEBAB}}`, and `{{PROJECT_NAME_PASCAL}}` placeholders.
374
+ - `package.json` `name` is set to the generated project slug.
375
+ - The only filename placeholder is `__projectName__`, replaced with the user's project name and with path separators sanitized.
376
+ - Files matching `rayfin-template.yml`, `.git`, `node_modules`, `.DS_Store`, and `Thumbs.db` are skipped during scaffolding.
377
+ - Symlinks are not followed.
378
+ - After scaffolding, the CLI installs its own agent files (`mcpServers.rayfin` inside `.mcp.json`, `.agents/skills/rayfin/`) into the project. You can ship `.mcp.json` with your own MCP servers, but do not include a `mcpServers.rayfin` key because the CLI manages that key. You can also ship an `AGENTS.md`; it's a one-time install and the CLI won't overwrite a template-provided one.
379
+
380
+ ## Gotchas
381
+
382
+ - `--list-templates` lists built-in and registered templates only — arbitrary git URLs you pass with `-t` are not in the list.
383
+ - The CLI clones a single ref shallowly. Tools that depend on git history or other branches won't have them at scaffold time.
384
+ - Private repositories rely on ambient git credentials. Interactive prompts are disabled, so missing credentials produce an immediate auth error.
385
+ - Non-interactive scaffolding from a multi-entry source fails unless `--template-name` is provided. The error message lists the available names.
386
+ - Bare values passed to `-t` resolve as template names. Use `./`, `../`, or an absolute path for local directories.
387
+
388
+ ## Related
389
+
390
+ - [CLI Quickstart](./quickstart.md) — common scaffolding workflows
391
+ - [Environment variables](./environment-variables.md) — runtime configuration after scaffolding
@@ -36,7 +36,7 @@ Some older examples may show `client.data.gql.<Entity>`.
36
36
 
37
37
  ### Read multiple records
38
38
 
39
- Here is an example to read all the records and order by a column.
39
+ Here is an example to read records and order by a column.
40
40
 
41
41
  ```typescript
42
42
  const notes = await this.rayfinClient.data.Note.select([
@@ -61,6 +61,11 @@ const notes = await this.rayfinClient.data.Note.select([
61
61
  return this.sortWithPinnedFirst(notes);
62
62
  ```
63
63
 
64
+ > **`.execute()` returns a single page (100 records by default).**
65
+ > The Data API caps a single response at its default page size (100 records).
66
+ > `.first(n)` raises the page size, but `.execute()` still returns only that one page and does **not** signal whether more records exist - so a list longer than the page is silently truncated.
67
+ > If your entity can grow beyond a single page (or you need a guaranteed-complete result set), use [pagination](#paginate-large-lists) instead of `.execute()`.
68
+
64
69
  ### Filter records
65
70
 
66
71
  Use `where` to filter results.
@@ -78,7 +83,16 @@ const pinnedNotes = await this.rayfinClient.data.Note.select([
78
83
 
79
84
  ### Paginate Large Lists
80
85
 
81
- Use cursor pagination for large lists.
86
+ Because `.execute()` returns only a single page (100 records by default) and gives no indication that more exist, use cursor pagination whenever a query can return more than one page.
87
+ Pagination uses `.first(n)` to set the page size and `.executePaginated()` to return one page plus the cursor metadata needed to fetch the next one.
88
+
89
+ **When to paginate vs. when `.execute()` is fine:**
90
+
91
+ - Use `.execute()` only for queries you know are bounded under one page (for example a `.where(...)` filter that can match at most a handful of rows, or a small lookup table).
92
+ - Use pagination for any unbounded or growing list - a user's notes, an order history, a product catalog. When in doubt, paginate.
93
+ - If you are building a UI list and aren't sure how large it will get, ask the user whether they want infinite scroll / a "load more" button (page-at-a-time) or the complete set up front (loop until `hasNextPage` is `false`, shown below).
94
+
95
+ **Fetch a single page:**
82
96
 
83
97
  ```typescript
84
98
  const page = await this.rayfinClient.data.Note.select([
@@ -90,11 +104,29 @@ const page = await this.rayfinClient.data.Note.select([
90
104
  .first(25)
91
105
  .executePaginated();
92
106
 
93
- const items = page.items;
94
- const cursor = page.endCursor;
95
- const hasNextPage = page.hasNextPage;
107
+ const items = page.items; // up to 25 records
108
+ const cursor = page.endCursor; // pass to .after(cursor) for the next page
109
+ const hasNextPage = page.hasNextPage; // true if more records remain
96
110
  ```
97
111
 
112
+ **Fetch the next page** by passing the previous `endCursor` to `.after()`:
113
+
114
+ ```typescript
115
+ const nextPage = await this.rayfinClient.data.Note.select(['id', 'title', 'createdAt'])
116
+ .orderBy({ createdAt: 'desc' })
117
+ .first(25)
118
+ .after(cursor)
119
+ .executePaginated();
120
+ ```
121
+
122
+ **Fetch every record** by repeating the call in a loop, passing each page's `endCursor` to `.after()`, until `hasNextPage` is `false`.
123
+ Keep the `.select()`, `.where()`, and `.orderBy()` clauses identical across pages - a stable sort order is required for the cursor to advance correctly.
124
+
125
+ > **`.first(n)` is bounded by DAB's maximum page size (100,000).**
126
+ > Rayfin returns a single default page of 100 records when a query omits `.first(n)`.
127
+ > For large result sets, the recommended pattern is to page through results with `.after()` rather than requesting everything in one large `.first(n)`.
128
+ > `.first(-1)` requests an unbounded page (all matching records), which DAB still caps at the maximum - so it works only when the full result set fits under that limit.
129
+
98
130
  ### Fetch a Single Record
99
131
 
100
132
  Here is an example to fetch a single record.
@@ -198,6 +230,8 @@ await this.rayfinClient.data.Note.delete({ id });
198
230
 
199
231
  ## Limitations and Workarounds
200
232
 
233
+ - `.execute()` returns only a single page (100 records by default) and does not signal whether more records exist, so lists longer than one page are silently truncated.
234
+ Use `.first(n)` with `.executePaginated()` and `.after(endCursor)` to page through the full result set.
201
235
  - `count()` is not implemented today; select the identifiers you need and use `results.length` or a custom aggregate.
202
236
  - `totalCount` appears on the `PagedResult` type but DAB does not populate it in paginated queries.
203
237
 
@@ -7,6 +7,10 @@ sidebar_position: 4
7
7
  Rayfin can generate a [Standard Schema](https://standardschema.dev) validator directly from your decorated entity classes.
8
8
  This lets you validate form input on the client without adding a separate validation library like Zod or Yup.
9
9
 
10
+ > **Note:** Rayfin entities use TC39 Stage 3 decorators, so any build tooling that compiles your client code must target **ES2022** (or later).
11
+ > If you see `Expression expected` errors on `@entity()` (or other decorators) when calling `toStandardSchema` or `getFieldConstraints`, your bundler is compiling to an older target.
12
+ > For Vite, set `target: 'es2022'` in your `vite.config.ts` — see [Vite configuration](../getting-started/project-structure.md#vite-configuration) — and use the default `@vitejs/plugin-react` (esbuild) plugin, since `@vitejs/plugin-react-swc` does not support these decorators regardless of the `target` setting.
13
+
10
14
  ## Build a validator from an entity
11
15
 
12
16
  Use `toStandardSchema` to create a validator from any `@entity()` class.
@@ -0,0 +1,41 @@
1
+ ---
2
+ sidebar_position: 75
3
+ ---
4
+
5
+ # Deprecation Warnings
6
+
7
+ Rayfin may emit deprecation warnings when your application uses an API or option that will change in a future release.
8
+ Warnings are printed with `console.warn` and include a stable code such as `[RAYFIN_DEP_USE_PROXY]` so you can search for the affected usage.
9
+
10
+ ## Silence warnings in application code
11
+
12
+ Use `setDeprecationsSilenced(true)` when you have reviewed the warnings and want to hide them for a specific environment.
13
+ Import the setting from `@microsoft/rayfin-client` and call it early in application startup before creating Rayfin clients or using deprecated APIs.
14
+
15
+ ```ts
16
+ import { setDeprecationsSilenced } from '@microsoft/rayfin-client';
17
+
18
+ setDeprecationsSilenced(true);
19
+ ```
20
+
21
+ You can call `setDeprecationsSilenced(false)` to enable warnings again.
22
+ Use `isDeprecationSilenced()` when you need to check the current setting.
23
+
24
+ ```ts
25
+ import { isDeprecationSilenced } from '@microsoft/rayfin-client';
26
+
27
+ console.log(isDeprecationSilenced());
28
+ ```
29
+
30
+ ## Silence warnings in Node.js
31
+
32
+ For Node.js scripts, tests, or server-side tools, set `RAYFIN_NO_DEPRECATION` to `1` or `true`.
33
+
34
+ ```bash
35
+ RAYFIN_NO_DEPRECATION=1 npm run dev
36
+ ```
37
+
38
+ ## Browser apps
39
+
40
+ Browser environments do not provide the Node.js environment variable that Rayfin checks.
41
+ Use the programmatic toggle in browser apps, and call it during startup before code paths that could emit deprecation warnings.
@@ -273,6 +273,9 @@ export default defineConfig({
273
273
 
274
274
  > **Tip:** Templates created with `npm create @microsoft/rayfin@latest` already include these settings.
275
275
  > If you are integrating Rayfin into an existing Vite project, add the three `target` entries shown above.
276
+ >
277
+ > **Note:** Use the default `@vitejs/plugin-react` plugin (esbuild-based).
278
+ > `@vitejs/plugin-react-swc` only supports legacy/experimental decorators and fails to parse Rayfin's TC39 decorators with an `Expression expected` error — regardless of the `target` setting.
276
279
 
277
280
  ### Environment variables
278
281
 
@@ -96,4 +96,5 @@ It can scaffold new projects, launch local infrastructure, sync schema changes,
96
96
  - Configure authentication with [Rayfin Auth](./auth/overview.md).
97
97
  - Deploy frontends with [Static Content Hosting](./hosting/index.md).
98
98
  - Explore CLI capabilities in [CLI Guide](./cli/index.md).
99
+ - Learn how to manage [Deprecation Warnings](./deprecations.md).
99
100
  - Review [Known Limitations](./known-limitations.md) for current behaviors and workarounds.
@@ -18,6 +18,10 @@ Use an explicit join entity with two `@one()` navigations instead.
18
18
  Some query limitations are imposed by Data API Builder.
19
19
  See [Data known limitations](./data/index.md#known-limitations).
20
20
 
21
+ - Collection queries return only one page unless the client pages through them.
22
+ The default page size is 100 records and the maximum page size is 100,000 records.
23
+ Use `.first(n)` with `.executePaginated()` and `.after(endCursor)` for lists that can exceed one page.
24
+
21
25
  ## Relationships
22
26
 
23
27
  - Rayfin auto-generates foreign key columns when you define `@one()` or `@many()` navigation decorators.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/rayfin-guide",
3
- "version": "1.33.2",
3
+ "version": "1.34.0-alpha.1148",
4
4
  "description": "Cross-cutting Builder guides for the Rayfin platform — discovered by `@microsoft/rayfin-docs` via the `rayfinDocs` package.json field convention.",
5
5
  "type": "module",
6
6
  "files": [