@microsoft/rayfin-guide 1.35.0-alpha.1287 → 1.35.0-alpha.1331
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.
- package/assets/docs/app-backend/deploy.md +21 -2
- package/assets/docs/auth/fabric.md +5 -3
- package/assets/docs/cli/connectors/add.md +78 -0
- package/assets/docs/cli/connectors/index.md +58 -0
- package/assets/docs/cli/connectors/inspect.md +78 -0
- package/assets/docs/cli/connectors/invoke.md +76 -0
- package/assets/docs/cli/connectors/search.md +66 -0
- package/assets/docs/cli/environment-variables.md +38 -4
- package/assets/docs/cli/index.md +25 -2
- package/assets/docs/cli/installation.md +4 -11
- package/assets/docs/cli/quickstart.md +16 -2
- package/assets/docs/data/permissions.md +13 -12
- package/assets/docs/getting-started/create-app-with-cli.md +6 -4
- package/assets/docs/getting-started/index.md +9 -6
- package/assets/docs/getting-started/project-structure.md +15 -2
- package/assets/docs/hosting/index.md +9 -2
- package/assets/docs/preview/local-dev-docker.md +49 -12
- package/package.json +1 -1
|
@@ -149,13 +149,14 @@ Use `--exclude-services <names>` to skip the build/package/deploy phase for supp
|
|
|
149
149
|
The runtime settings POST still reflects your `rayfin.yml`, so the backend is never silently reconfigured.
|
|
150
150
|
The only currently supported value is `staticHosting`; other names fail with a clear error.
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
Use `rayfin dev` for the normal local-development workflow; it never publishes the static bundle.
|
|
153
|
+
The exclude flag remains useful for existing scripts and automation that intentionally run the deployment workflow while Vite serves the frontend:
|
|
153
154
|
|
|
154
155
|
```bash
|
|
155
156
|
npx rayfin up --exclude-services staticHosting
|
|
156
157
|
```
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
Rayfin's bundled samples and templates use `rayfin dev` for their `npm run dev` script.
|
|
159
160
|
|
|
160
161
|
## Apply database changes remotely
|
|
161
162
|
|
|
@@ -202,6 +203,24 @@ Add `--json` for machine-readable output:
|
|
|
202
203
|
npx rayfin up status --json
|
|
203
204
|
```
|
|
204
205
|
|
|
206
|
+
When static content is deployed, the human-readable output includes its public URL:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
Static app: https://silky-sand-4924b3ad1f-centraluseuap.webapp.rayfingwdev.com
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The JSON output exposes the same value as `deployment.hostingUrl`:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"deployment": {
|
|
217
|
+
"hostingUrl": "https://silky-sand-4924b3ad1f-centraluseuap.webapp.rayfingwdev.com"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
When no static app URL is recorded, the human-readable output omits the line and `deployment.hostingUrl` is `null` in JSON.
|
|
223
|
+
|
|
205
224
|
## Sign out
|
|
206
225
|
|
|
207
226
|
Clear cached credentials when you are done or need to switch accounts:
|
|
@@ -273,7 +273,8 @@ Most apps should use `ensureSignedInWithFabric` instead.
|
|
|
273
273
|
## Environment variables
|
|
274
274
|
|
|
275
275
|
Fabric auth requires three Vite environment variables so your frontend can build the `FabricAuthOptions` at runtime.
|
|
276
|
-
`npx rayfin
|
|
276
|
+
`npx rayfin dev` writes the underlying `RAYFIN_PUBLIC_*` values to `rayfin/.env` and maps them to Vite-compatible names in `.env.local` before starting the frontend.
|
|
277
|
+
Production builds retain the scaffolded `prebuild` hook to refresh those values before bundling.
|
|
277
278
|
|
|
278
279
|
| Source variable (`rayfin/.env`) | Vite variable (`.env.local`) | Description | Example |
|
|
279
280
|
| --- | --- | --- | --- |
|
|
@@ -302,7 +303,7 @@ const fabricOptions = {
|
|
|
302
303
|
|
|
303
304
|
## Deployment values
|
|
304
305
|
|
|
305
|
-
After running `npx rayfin up`, the CLI records deployment metadata in `rayfin/.deployments.json` and merges the corresponding `RAYFIN_PUBLIC_*` variables into `rayfin/.env`:
|
|
306
|
+
After running `npx rayfin dev` or `npx rayfin up`, the CLI records deployment metadata in `rayfin/.deployments.json` and merges the corresponding `RAYFIN_PUBLIC_*` variables into `rayfin/.env`:
|
|
306
307
|
|
|
307
308
|
```text
|
|
308
309
|
RAYFIN_PUBLIC_ITEM_ID=<guid>
|
|
@@ -310,7 +311,8 @@ RAYFIN_PUBLIC_WORKSPACE_ID=<guid>
|
|
|
310
311
|
RAYFIN_PUBLIC_PORTAL_URL=https://app.fabric.microsoft.com/
|
|
311
312
|
```
|
|
312
313
|
|
|
313
|
-
|
|
314
|
+
`rayfin dev` generates `.env.local` with Vite-compatible names before starting the frontend.
|
|
315
|
+
Use `RAYFIN_PUBLIC_ITEM_ID` as the `projectId` and `RAYFIN_PUBLIC_WORKSPACE_ID` as the `workspaceId` in your `FabricAuthOptions`.
|
|
314
316
|
|
|
315
317
|
## Troubleshooting
|
|
316
318
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 2
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# connector add
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx rayfin connector add --type <type> --workspace-id <ws-id> --item-id <item-id> [--name <name>] [--operations <ops>]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`connector add` declares a connector in `rayfin/rayfin.yml` and scaffolds its supporting files.
|
|
12
|
+
|
|
13
|
+
The CLI verifies the Fabric item, derives a connector `name` from the item's display name (override with `--name`), writes the entry to `rayfin.yml`, scaffolds `rayfin/connectors/<name>/schema.ts`, and runs schema discovery. `rayfin/connectors/<name>/metadata.json` is written so a subset of entities can be generated later.
|
|
14
|
+
|
|
15
|
+
If you do not already know the workspace and item IDs, run [`connector search`](./search.md) first — its `--json` output includes a ready-to-run `addCommand` for each result.
|
|
16
|
+
|
|
17
|
+
## Options
|
|
18
|
+
|
|
19
|
+
| Flag | Required | Purpose |
|
|
20
|
+
| --------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
21
|
+
| `--type <type>` | yes | The connector type, for example `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase`, `kusto`, or `fabric-semanticmodel`. |
|
|
22
|
+
| `--workspace-id <id>` | yes (Fabric) | Fabric workspace ID. Must be a literal — `${VAR}` placeholders are rejected. |
|
|
23
|
+
| `--item-id <id>` | yes (Fabric) | Fabric item or artifact ID. Must be a literal. |
|
|
24
|
+
| `--name <name>` | no | Connector name. Derived from the item display name when omitted. |
|
|
25
|
+
| `--operations <ops>` | no | Comma-separated subset of the type's allowed operations, for example `read,update`. Narrows the emitted `operations:` at add time. Omit for all allowed operations. Each value must be in the type's catalog allowlist. |
|
|
26
|
+
| `-y, --yes` | no | Auto-accept overwrite and confirmation prompts (non-interactive). |
|
|
27
|
+
| `-v, --verbose` | no | Verbose diagnostics. |
|
|
28
|
+
|
|
29
|
+
## Scoping operations
|
|
30
|
+
|
|
31
|
+
Without `--operations`, `connector add` writes **every** operation the catalog allows for the type. Prefer scoping at add time over hand-editing YAML afterwards:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx rayfin connector add --type fabric-warehouse --workspace-id <ws> --item-id <item> --operations read,update
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The resulting `rayfin.yml` entry lists operations as objects, not bare strings:
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
connectors:
|
|
41
|
+
- name: inventory
|
|
42
|
+
type: fabric-warehouse
|
|
43
|
+
config:
|
|
44
|
+
workspaceId: ${WS_ID}
|
|
45
|
+
itemId: ${ITEM_ID}
|
|
46
|
+
auth:
|
|
47
|
+
type: delegated
|
|
48
|
+
operations:
|
|
49
|
+
- name: read
|
|
50
|
+
- name: update
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Rules:
|
|
54
|
+
|
|
55
|
+
- You can narrow below the catalog default; you cannot widen above it.
|
|
56
|
+
- There is no `all` meta-operation — list every action explicitly.
|
|
57
|
+
- The host validator rejects unknown or duplicate operation names at `rayfin up` time.
|
|
58
|
+
|
|
59
|
+
## Category B connectors
|
|
60
|
+
|
|
61
|
+
For `kusto` and `fabric-semanticmodel`, `connector add` writes the `rayfin.yml` entry but there are no GraphQL entities to discover, so no entity files are generated and no row-level security applies:
|
|
62
|
+
|
|
63
|
+
- `executeQuery` is the only allowed operation.
|
|
64
|
+
- `auth.type` must be `delegated`.
|
|
65
|
+
- The connector is pinned to an adapter version.
|
|
66
|
+
- There is no `metadata.json` entity list to generate from.
|
|
67
|
+
|
|
68
|
+
After adding, exercise the connector with [`connector invoke`](./invoke.md) rather than writing entity code.
|
|
69
|
+
|
|
70
|
+
## Related commands
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx rayfin connector list [--verbose] [--json]
|
|
74
|
+
|
|
75
|
+
# Removes the rayfin.yml entry AND the rayfin/connectors/<name>/ directory.
|
|
76
|
+
# Re-add after remove to refresh metadata, then regenerate entity files yourself.
|
|
77
|
+
npx rayfin connector remove <name> [--yes]
|
|
78
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 6
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Connectors
|
|
6
|
+
|
|
7
|
+
Connectors let a Rayfin app read from — and, for some types, write to — Microsoft Fabric data sources: warehouses, SQL databases, Lakehouse SQL analytics endpoints, semantic models, and KQL databases.
|
|
8
|
+
|
|
9
|
+
## Prerequisite — the `connector` command group is feature-flagged
|
|
10
|
+
|
|
11
|
+
`rayfin connector ...` is only registered when the `RAYFIN_FEATURE_FLAGS` environment variable contains `connectors`. Without it the commands do not exist and the CLI reports an unknown command.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
RAYFIN_FEATURE_FLAGS=connectors npx rayfin connector search --help
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Each command has its own reference page:
|
|
18
|
+
|
|
19
|
+
- [`connector search`](./search.md) — discover Fabric sources the signed-in identity can add.
|
|
20
|
+
- [`connector add`](./add.md) — declare a connector in `rayfin.yml` and scaffold its files.
|
|
21
|
+
- [`connector inspect`](./inspect.md) — run a single read-only sample query against a source.
|
|
22
|
+
- [`connector invoke`](./invoke.md) — run one named operation against a configured connector.
|
|
23
|
+
|
|
24
|
+
A typical loop is search → add → inspect (Category A) or search → add → invoke (Category B).
|
|
25
|
+
|
|
26
|
+
## Two categories of connector
|
|
27
|
+
|
|
28
|
+
The commands available to a connector, and the code you write against it, depend on its category.
|
|
29
|
+
|
|
30
|
+
| | Category A — GraphQL entity connectors | Category B — function-bridge connectors |
|
|
31
|
+
| ------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------ |
|
|
32
|
+
| **Types** | `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase` | `kusto`, `fabric-semanticmodel` |
|
|
33
|
+
| **App surface** | Generated entity files with typed CRUD through the data client | A single `executeQuery` operation carrying a raw query |
|
|
34
|
+
| **Operations** | `read` only for `fabric-sqlanalytics` (Lakehouse SQL endpoints are read-only); `read`, `create`, `update`, `delete` for `fabric-warehouse` and `fabric-sqldatabase` (narrowable) | `executeQuery` only |
|
|
35
|
+
| **Auth** | `delegated` or configured per project | Must be `delegated` |
|
|
36
|
+
| **Entity files and `@role` policies** | Yes | No |
|
|
37
|
+
| **`metadata.json` entities** | Yes | No |
|
|
38
|
+
| **`connector inspect`** | Supported | `fabric-semanticmodel` only — `kusto` is not supported |
|
|
39
|
+
| **`connector invoke`** | Rarely needed | The main way to exercise the connector |
|
|
40
|
+
|
|
41
|
+
Category B connectors are pinned to an adapter version and expose no GraphQL entities, so there is nothing to generate and no row-level security to author.
|
|
42
|
+
|
|
43
|
+
## Where connector state lives
|
|
44
|
+
|
|
45
|
+
- `rayfin/rayfin.yml` — the `connectors:` block: each connector's `name`, `type`, `config` (workspace and item IDs), `auth`, and `operations`.
|
|
46
|
+
- `rayfin/connectors/<name>/metadata.json` — discovered schema for Category A connectors; the source for generating entity files.
|
|
47
|
+
- `rayfin/connectors/<name>/schema.ts` — placeholder scaffold written by `connector add`.
|
|
48
|
+
|
|
49
|
+
`npx rayfin connector list` prints the configured connectors; `npx rayfin connector remove <name>` deletes both the `rayfin.yml` entry and the `rayfin/connectors/<name>/` directory.
|
|
50
|
+
|
|
51
|
+
## Deploying connectors
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx rayfin up # deploy connectors to the cloud
|
|
55
|
+
npx rayfin up connector apply [--name <name>] # re-apply DAB config only
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Most connector commands work before deployment. The exception is [`connector invoke`](./invoke.md) for every type except `fabric-semanticmodel`, which posts to the deployed item and therefore requires a prior `rayfin up`.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# connector inspect
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx rayfin connector inspect (--name <name> | <direct-selector-flags>) (--entity <name> | --query <path>) [--rows <n>] [--verbose] [--json]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`connector inspect` takes no positional arguments — every selector and query mode is a flag.
|
|
12
|
+
|
|
13
|
+
`connector inspect` runs a single read-only sample query against a connector's underlying source, before you have written any app code. Use it to check a table's real data and shape ahead of entity generation, or to debug a row-level-security or query issue on an already-wired connector. It is a development aid — never use it to power app functionality.
|
|
14
|
+
|
|
15
|
+
Supported types: the three Category A SQL types (`fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase`) and `fabric-semanticmodel` (DAX). `kusto` is **not** supported today — the command errors with `Unsupported connector type: kusto`.
|
|
16
|
+
|
|
17
|
+
## Pick exactly one selector and one query mode
|
|
18
|
+
|
|
19
|
+
Two independent choices, each a mutually exclusive pair. Passing zero or both options in a pair fails validation before any network call.
|
|
20
|
+
|
|
21
|
+
| Choice | Option A | Option B |
|
|
22
|
+
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| **Selector** — which connector or item to query | `--name <name>` — a connector already declared in `rayfin.yml` | Direct mode — `--workspace-id`/`--workspace <name>` plus `--item-id`/`--item <name>` plus `--type <type>`, or `--url <portal-url>` for a semantic model (auto-extracts workspace and item IDs) |
|
|
24
|
+
| **Query mode** | `--entity <name>` — structured: builds `SELECT TOP (n) * FROM <entity>` (SQL) or `EVALUATE TOPN(n, '<entity>')` (DAX) for you | `--query <path>` — raw: runs the literal `.sql` or `.dax` file verbatim, still capped and validated |
|
|
25
|
+
|
|
26
|
+
All four combinations of `{--name, direct} × {--entity, --query}` are valid.
|
|
27
|
+
|
|
28
|
+
`--workspace` and `--item` accept display names and are resolved to IDs the same way [`connector add`](./add.md) fuzzy matching works; `--workspace-id` and `--item-id` take literal IDs directly.
|
|
29
|
+
|
|
30
|
+
## Entity resolution
|
|
31
|
+
|
|
32
|
+
Applies to `--entity` mode only.
|
|
33
|
+
|
|
34
|
+
- **`--name` plus `--entity` with an unqualified name (no `.`)** — first checked against the connector's local `rayfin/connectors/<name>/metadata.json`, with no network call. Zero matches falls through to live resolution; exactly one match auto-qualifies to `schema.table`; more than one match fails immediately asking you to disambiguate with a schema-qualified name. It does **not** fall through to live resolution in the ambiguous case.
|
|
35
|
+
- **Any other combination** — direct mode, or `--query` mode — never consults `metadata.json`. For SQL types, an unqualified `--entity` is resolved live via `SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE LOWER(TABLE_NAME) = LOWER('<entity>')`: zero matches passes the name through unqualified, one match auto-qualifies, more than one match throws asking you to disambiguate with `--entity <schema>.<table>`.
|
|
36
|
+
- A schema-qualified `--entity <schema>.<table>` skips resolution entirely, in both cases.
|
|
37
|
+
|
|
38
|
+
## Validation
|
|
39
|
+
|
|
40
|
+
Applies to both query modes.
|
|
41
|
+
|
|
42
|
+
- **SQL** — must start with `SELECT` or `WITH`; must be a single statement (a trailing `;` is fine, an embedded one is not); rejects `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `EXEC`/`EXECUTE`, and `INTO` anywhere outside a string literal.
|
|
43
|
+
- **DAX** — must start with `EVALUATE`.
|
|
44
|
+
- `--query <path>` must resolve to a `.sql` or `.dax` file inside the project root; paths outside it are rejected. The project root is the directory containing `rayfin/rayfin.yml` when one is found. Direct mode (no `--name`) falls back to the current working directory if no `rayfin.yml` exists, so `--query` never requires a Rayfin project.
|
|
45
|
+
- `--rows <n>` caps the sample size — default 10, maximum 100. The result reports `truncated: true` when the source had more rows than the cap.
|
|
46
|
+
|
|
47
|
+
## Examples
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# --name selector + structured entity mode
|
|
51
|
+
npx rayfin connector inspect --name inventory --entity Order
|
|
52
|
+
|
|
53
|
+
# --name selector + raw query file
|
|
54
|
+
npx rayfin connector inspect --name inventory --query rayfin/queries/order.sql
|
|
55
|
+
|
|
56
|
+
# Direct selector (literal IDs) + structured entity mode
|
|
57
|
+
npx rayfin connector inspect --workspace-id <ws-id> --item-id <item-id> --type fabric-warehouse --entity Order
|
|
58
|
+
|
|
59
|
+
# Direct selector (fuzzy display names) + raw query file
|
|
60
|
+
npx rayfin connector inspect --workspace "Sales Analytics" --item "Inventory Warehouse" --type fabric-warehouse --query rayfin/queries/order.sql
|
|
61
|
+
|
|
62
|
+
# Semantic model (DAX), resolved from a Fabric portal URL
|
|
63
|
+
npx rayfin connector inspect --url <fabric-portal-semantic-model-url> --query rayfin/queries/model.dax
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Combine `--workspace-id`, `--item-id`, and `--type` with either `--entity` or `--query` freely — none of the four combinations require `--name` or a `rayfin.yml` entry to exist.
|
|
67
|
+
|
|
68
|
+
## Errors
|
|
69
|
+
|
|
70
|
+
SQL errors are categorized before being shown:
|
|
71
|
+
|
|
72
|
+
| Condition | Surfaced as |
|
|
73
|
+
| -------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
74
|
+
| SQL Server error `229`, `230`, `262`, `297`, `300` | "Permission denied", with a permissions recovery hint. |
|
|
75
|
+
| SQL Server error `18456`, `4060`, or `ELOGIN` | "Authentication failed", with a `rayfin login` recovery hint. |
|
|
76
|
+
| Anything else, including invalid object name / table not found | The underlying message, with a generic "verify the entity/table name and access" hint. |
|
|
77
|
+
|
|
78
|
+
Semantic model HTTP errors map `401` to re-login, `403` to permissions, and everything else to the generic hint.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# connector invoke
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx rayfin connector invoke <connector-name> <operation> (--input '<json>' | --file <path>) [--verbose] [--json]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`connector invoke` runs a single named operation against a configured connector and prints the result. It is the loop for exercising [Category B connectors](./index.md#two-categories-of-connector) — `executeQuery` over DAX or KQL — without writing any app code.
|
|
12
|
+
|
|
13
|
+
Both positionals also have flag forms, `--name <name>` and `--operation <operation>`, which win over the positionals when both are given.
|
|
14
|
+
|
|
15
|
+
Run it from inside a Rayfin project: it resolves `rayfin/rayfin.yml`, and fails with a recovery hint if there is no project root or the `connectors:` block is empty.
|
|
16
|
+
|
|
17
|
+
## Payload input
|
|
18
|
+
|
|
19
|
+
Exactly one of these is required — passing both, or neither, fails:
|
|
20
|
+
|
|
21
|
+
- `--input '<json>'` — inline JSON payload for the operation input.
|
|
22
|
+
- `--file <path>` — path to a JSON file. The path is resolved against the project root, and **the resolved path must stay inside it**; a `../` escape is rejected before the file is read. An absolute path is accepted as long as it resolves inside the project root.
|
|
23
|
+
|
|
24
|
+
## Operation resolution
|
|
25
|
+
|
|
26
|
+
The requested operation is matched **case-insensitively** against the connector's `operations:` list in `rayfin.yml`. If that entry has no `operations:`, the connector type's full catalog allowlist is used instead. A miss fails with the allowed set listed.
|
|
27
|
+
|
|
28
|
+
## Transports
|
|
29
|
+
|
|
30
|
+
Two transports, chosen by connector type:
|
|
31
|
+
|
|
32
|
+
- **`fabric-semanticmodel`** — the CLI calls Fabric/Power BI **directly under the developer's own identity**, so this works whether or not `npx rayfin up` has been run. It requires `workspaceId` **and** `itemId` under the connector's `config:` block; without both, it fails up front rather than falling through to the deployed transport. The Power BI scope and audience are derived from the configured Fabric API base URL, so an INT ring mints an INT-audience token.
|
|
33
|
+
- **Every other type, including `kusto`** — POSTs to the deployed item at `<remote-endpoint>/__private/connectors/<name>/invoke`, so it requires a prior `npx rayfin up`.
|
|
34
|
+
|
|
35
|
+
## Token handling (semantic model path)
|
|
36
|
+
|
|
37
|
+
`npx rayfin login` only consents to the Fabric scope, not the Power BI scope this path needs. Consequences:
|
|
38
|
+
|
|
39
|
+
- Interactively (no `--json`), the CLI prompts to complete Power BI consent.
|
|
40
|
+
- With `--json`, token acquisition is **silent-only** so prompts cannot corrupt the single-JSON-object contract. If consent is still needed the command fails and tells you to drop `--json` or set `RAYFIN_TOKEN`.
|
|
41
|
+
- `RAYFIN_TOKEN`, when set, is passed through **unchanged** regardless of the scopes requested. Its audience is decoded and checked locally, so a wrong-audience or undecodable token fails with a clear message instead of surfacing later as a phantom workspace-permission error.
|
|
42
|
+
|
|
43
|
+
## Output
|
|
44
|
+
|
|
45
|
+
`--verbose` cannot be combined with `--json` — narration would break the single-object contract.
|
|
46
|
+
|
|
47
|
+
Success emits `{status: 'ok', connector, operation, output}`. In non-JSON modes it prints `✅ Invoked <name>.<operation>` followed by the output.
|
|
48
|
+
|
|
49
|
+
What `output` holds depends on the connector. `fabric-semanticmodel` normalises inside its `invoke` middleware, so `output` is already a discriminated result rather than the raw service envelope: `{status: 'success', table, requestId}`, where `table.columns` are `{name, dataType}` and `table.rows` are column-aligned arrays. No caller-side conversion is needed, and the same shape comes back whether the operation ran locally or through the deployed item.
|
|
50
|
+
|
|
51
|
+
A resolved call is **not** automatically a success, and the failure signal depends on the same distinction. A connector that normalises reports Power BI failures — expired token, missing Build permission, throttling — as `{status: 'error', error, requestId}`, where `error` carries `category`, `message`, and optional `code` and `details`. A connector that returns the raw envelope reports failure as `status: 'Failed'` instead. The CLI reads both, converts either into a non-zero exit, and surfaces the service-supplied request id for tracing.
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Inline payload, positional args
|
|
57
|
+
npx rayfin connector invoke mymodel executeQuery --input '{"query":"EVALUATE TOPN(10, Sales)"}'
|
|
58
|
+
|
|
59
|
+
# Same thing with flag forms and a payload file
|
|
60
|
+
npx rayfin connector invoke --name mymodel --operation executeQuery --file ./payload.json
|
|
61
|
+
|
|
62
|
+
# Machine-readable (no --verbose allowed alongside)
|
|
63
|
+
npx rayfin connector invoke mymodel executeQuery --input '{"query":"EVALUATE TOPN(1, Sales)"}' --json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Errors
|
|
67
|
+
|
|
68
|
+
| Message | Fix |
|
|
69
|
+
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
70
|
+
| `Missing required connector invoke arguments` | Supply both the connector name and the operation. |
|
|
71
|
+
| `Choose exactly one payload source` / `Missing payload input` | Pass exactly one of `--input` or `--file`. |
|
|
72
|
+
| `Input file must be inside the project` | Use a relative path under the project root. |
|
|
73
|
+
| `Operation "<op>" is not allowed for connector "<name>"` | Check the connector's `operations:` in `rayfin.yml`, or the type's allowlist. |
|
|
74
|
+
| `missing workspaceId/itemId in rayfin.yml` | Add both under `config:`, or re-run [`connector add`](./add.md). |
|
|
75
|
+
| `Access token has the wrong audience for the Power BI query API` | Unset or replace `RAYFIN_TOKEN`, or re-run without `--json` to consent interactively. |
|
|
76
|
+
| `No remote endpoint configured` | The non-semantic-model transport needs a deployed item — run `npx rayfin up` first. |
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# connector search
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx rayfin connector search [query] [--workspace-id <id> --type <types> | --all-workspaces --type <types>] [--limit <n>] [--json]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`connector search` finds Fabric data sources — warehouses, SQL databases, Lakehouses, semantic models, and KQL databases — that the signed-in identity can add as connectors, before you know exact workspace or item IDs.
|
|
12
|
+
|
|
13
|
+
Use it to find candidates for [`connector add`](./add.md). It never touches app data itself.
|
|
14
|
+
|
|
15
|
+
## Scope resolution
|
|
16
|
+
|
|
17
|
+
The search scope is resolved in priority order:
|
|
18
|
+
|
|
19
|
+
1. `--workspace-id <id>` — search exactly one workspace. **Requires** `--type`: without it, every discoverable item type would be fetched with a separate request to that workspace.
|
|
20
|
+
2. `--all-workspaces` — tenant-wide scan across every workspace the identity can access. **Requires** `--type` (the only server-side filter) to keep the scan bounded.
|
|
21
|
+
3. No scope flag, run inside a Rayfin project with deployments — defaults to the union of every workspace recorded in the project's deployments registry (dev, prod, and so on), without switching the active deployment. This is the only scope that does **not** require `--type`.
|
|
22
|
+
|
|
23
|
+
Only one of `--workspace-id` and `--all-workspaces` may be given. Outside a Rayfin project with zero deployments, one of them is required; omitting both fails with `workspace scope is required`.
|
|
24
|
+
|
|
25
|
+
## Filtering
|
|
26
|
+
|
|
27
|
+
| Flag | Purpose |
|
|
28
|
+
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| `[query]` (positional) or `--query <text>` | Case-insensitive name filter. Omit to list every connectable source in scope. `--query` wins if both are given. |
|
|
30
|
+
| `--type <types>` | Comma-separated subset of connector types, for example `fabric-warehouse,fabric-sqldatabase`. Required with `--workspace-id` and with `--all-workspaces`. |
|
|
31
|
+
| `--limit <n>` | Caps the rows shown. Ignored in interactive mode, where the picker paginates the full result set instead; applies only to plain and `--json` output. |
|
|
32
|
+
|
|
33
|
+
## Output modes
|
|
34
|
+
|
|
35
|
+
- **Interactive** (default on a TTY) — a paginated picker. Page size comes from `RAYFIN_CONNECTOR_SEARCH_PAGE_SIZE`, default 30. Picking a source runs a pre-flight access check (SQL endpoint, Kusto endpoint, or semantic model probe, depending on type) before handing off to [`connector add`](./add.md); a failed check re-shows the picker instead of aborting. `--yes` and `--verbose` are forwarded to the `connector add` it runs.
|
|
36
|
+
- **Plain** (non-TTY) — prints the list and exits, with no prompt.
|
|
37
|
+
- **`--json`** — a machine-readable envelope on stdout: `{status, query, scope, count, sources}`. Each row carries `workspaceId`, `itemId`, and `connectorType`, plus `suggestedName` (the sanitized display name to use as the connector name) and `addCommand` (the exact `rayfin connector add …` string to run). Skips both the picker and the access-check pre-flight.
|
|
38
|
+
|
|
39
|
+
Duplicate-looking entries — for example a SQL Database and its SQL-analytics-endpoint twin sharing a workspace and display name — are grouped visually next to each other in interactive and plain output only. They are never deduplicated, and `--json` always returns the canonical, ungrouped order.
|
|
40
|
+
|
|
41
|
+
The SQL-endpoint-permissions note ("Schema discovery for SQL-based connectors requires SQL endpoint permissions") only prints when at least one result is a SQL-dialect connector type — never for a semantic-model-only or Kusto-only result set.
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Query text as a positional argument, scoped to one workspace (--type is required with --workspace-id)
|
|
47
|
+
npx rayfin connector search "sales" --workspace-id <ws-id> --type fabric-warehouse
|
|
48
|
+
|
|
49
|
+
# Tenant-wide scan, narrowed to one or more types (--type is required with --all-workspaces)
|
|
50
|
+
npx rayfin connector search --all-workspaces --type fabric-warehouse,fabric-sqldatabase
|
|
51
|
+
|
|
52
|
+
# No scope flag inside a deployed project — searches every deployment workspace, no --type needed
|
|
53
|
+
npx rayfin connector search
|
|
54
|
+
|
|
55
|
+
# Machine-readable output, capped to 5 rows, skips the interactive picker
|
|
56
|
+
npx rayfin connector search --workspace-id <ws-id> --type fabric-warehouse --json --limit 5
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Errors
|
|
60
|
+
|
|
61
|
+
| Message | Fix |
|
|
62
|
+
| ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `Command incomplete: workspace scope is required` | No `--workspace-id` or `--all-workspaces` and no deployments found. Pass one of those flags. |
|
|
64
|
+
| `--type is required with --all-workspaces` | Add a `--type` filter to bound the tenant-wide scan. |
|
|
65
|
+
| `--type is required with --workspace-id` | Add a `--type` filter so a single request is made instead of one per discoverable item type. |
|
|
66
|
+
| `You don't have the required permission on <source>` | The pre-flight access check failed during the interactive add handoff. Pick a different source or request access. |
|
|
@@ -10,8 +10,9 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
|
|
|
10
10
|
|
|
11
11
|
| Variable | Description | Populated by |
|
|
12
12
|
| --- | --- | --- |
|
|
13
|
-
| `RAYFIN_PUBLIC_API_URL` | Rayfin backend URL
|
|
14
|
-
| `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | Public key for Rayfin SDK initialization. | `rayfin up` |
|
|
13
|
+
| `RAYFIN_PUBLIC_API_URL` | Rayfin backend URL selected for the development or deployed environment. | `rayfin dev` / `rayfin up` |
|
|
14
|
+
| `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | Public key for Rayfin SDK initialization. | `rayfin dev` / `rayfin up` |
|
|
15
|
+
| `RAYFIN_PUBLIC_FUNCTIONS_URL` | URL of the local Functions host started by `rayfin dev`. Removed when functions are disabled so local clients do not retain a stale host. | `rayfin dev` |
|
|
15
16
|
| `RAYFIN_PUBLIC_ITEM_ID` | Fabric AppBackend item ID. Used for Fabric brokered auth. | `rayfin up` |
|
|
16
17
|
| `RAYFIN_PUBLIC_WORKSPACE_ID` | Fabric workspace ID. Used for Fabric brokered auth. | `rayfin up` |
|
|
17
18
|
| `RAYFIN_PUBLIC_TENANT_ID` | Entra ID tenant for workspace disambiguation. | `rayfin up` |
|
|
@@ -27,6 +28,7 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
|
|
|
27
28
|
| --- | --- | --- | --- |
|
|
28
29
|
| `RAYFIN_PUBLIC_API_URL` | `VITE_RAYFIN_API_URL` | `NEXT_PUBLIC_RAYFIN_API_URL` | `API_URL` |
|
|
29
30
|
| `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | `VITE_RAYFIN_PUBLISHABLE_KEY` | `NEXT_PUBLIC_RAYFIN_PUBLISHABLE_KEY` | `PUBLISHABLE_KEY` |
|
|
31
|
+
| `RAYFIN_PUBLIC_FUNCTIONS_URL` | `VITE_RAYFIN_FUNCTIONS_URL` | `NEXT_PUBLIC_RAYFIN_FUNCTIONS_URL` | `FUNCTIONS_URL` |
|
|
30
32
|
| `RAYFIN_PUBLIC_ITEM_ID` | `VITE_FABRIC_ITEM_ID` | `NEXT_PUBLIC_FABRIC_ITEM_ID` | `ITEM_ID` |
|
|
31
33
|
| `RAYFIN_PUBLIC_WORKSPACE_ID` | `VITE_FABRIC_WORKSPACE_ID` | `NEXT_PUBLIC_FABRIC_WORKSPACE_ID` | `WORKSPACE_ID` |
|
|
32
34
|
| `RAYFIN_PUBLIC_TENANT_ID` | `VITE_FABRIC_TENANT_ID` | `NEXT_PUBLIC_FABRIC_TENANT_ID` | `TENANT_ID` |
|
|
@@ -40,6 +42,37 @@ Custom `RAYFIN_PUBLIC_*` variables you add follow a generic pattern: `RAYFIN_PUB
|
|
|
40
42
|
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
43
|
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
44
|
|
|
45
|
+
### Bare development runtime wiring
|
|
46
|
+
|
|
47
|
+
`npx rayfin dev` runs the local frontend against the Fabric backend by default.
|
|
48
|
+
Use `npx rayfin dev --provider fabric` to select the same provider explicitly.
|
|
49
|
+
The CLI reuses a registered deployment or provisions and records a missing AppBackend.
|
|
50
|
+
Set `RAYFIN_WORKSPACE_ID` to target a specific workspace; otherwise the active registered deployment or My workspace is used.
|
|
51
|
+
|
|
52
|
+
The CLI starts `npm run dev:frontend` when that script exists and falls back to `npm run dev` for existing projects.
|
|
53
|
+
This lets bundled templates expose `npm run dev` as the complete session without recursively starting the CLI.
|
|
54
|
+
When migrating an existing project to `"dev": "rayfin dev"`, also add a non-recursive child such as `"dev:frontend": "vite"`; otherwise the CLI fails with an actionable recursion error.
|
|
55
|
+
Scripts are resolved from `services.staticHosting.path` when configured, otherwise from the project root.
|
|
56
|
+
For a nested frontend package, declare `dev:frontend` (or the legacy `dev` fallback) in that package's `package.json`.
|
|
57
|
+
|
|
58
|
+
When `services.functions.enabled` is `true`, the same command builds and starts the configured functions package with Azure Functions Core Tools.
|
|
59
|
+
The CLI reserves the nearest available Functions port starting at `7071` and writes its URL to `RAYFIN_PUBLIC_FUNCTIONS_URL` before starting the frontend.
|
|
60
|
+
When functions are disabled, the CLI removes any stale `RAYFIN_PUBLIC_FUNCTIONS_URL` from `rayfin/.env` and regenerates the framework environment file without it.
|
|
61
|
+
|
|
62
|
+
The local functions setup makes these workspace changes:
|
|
63
|
+
|
|
64
|
+
- Merges backend coordinates and the Node inspector argument into the configured functions package's `local.settings.json`.
|
|
65
|
+
- Adds a `Functions: Attach` configuration to the root `.vscode/launch.json` after the Functions host becomes ready.
|
|
66
|
+
- Leaves JSON-with-comments launch files unchanged and reports that the attach configuration must be added manually.
|
|
67
|
+
- Patches recognized `src/services/rayfinClient.ts` and `src/services/bootstrap.ts` template files once so `functionsBaseUrl` reads `VITE_RAYFIN_FUNCTIONS_URL`.
|
|
68
|
+
- Regenerates the framework `.env.local` file unless `--no-emit-env` is set.
|
|
69
|
+
|
|
70
|
+
The Node inspector defaults to port `9229` and slides to the nearest available port when needed.
|
|
71
|
+
Use the `Functions: Attach` launch configuration after the host is ready to debug local function code.
|
|
72
|
+
|
|
73
|
+
To run the managed backend locally instead, enable the Docker preview and use `npx rayfin dev --provider docker`.
|
|
74
|
+
Frontend and functions code still run as local processes; only the managed Rayfin backend moves from Fabric to Docker.
|
|
75
|
+
|
|
43
76
|
## Tooling overrides
|
|
44
77
|
|
|
45
78
|
These variables configure CLI and extension behavior.
|
|
@@ -146,14 +179,15 @@ These variables are read from the shell environment and are never written to fil
|
|
|
146
179
|
| `RAYFIN_WORKSPACE_ID` | Fabric workspace ID for non-interactive setup. Used with `RAYFIN_TOKEN`. |
|
|
147
180
|
| `RAYFIN_TENANT_ID` | Entra ID tenant used by `rayfin up` for portal URLs and the `ctid` query parameter. Equivalent to the `-t, --tenant <id>` flag (precedence: flag > env var > signed-in tenant). |
|
|
148
181
|
| `RAYFIN_ENCRYPTION_FALLBACK_ENABLED` | Set to `true` to allow plaintext token cache on systems without OS credential storage. Development only. |
|
|
149
|
-
| `RAYFIN_FEATURE_FLAGS` | Comma-separated list of experimental feature names to enable (case-insensitive). Recognized values include `storage`, `functions`, and `postgresql`. |
|
|
150
|
-
| `RAYFIN_WEBSERVICE_IMAGE_NAME` | **Experimental.** Override the webservice container image used by `rayfin dev
|
|
182
|
+
| `RAYFIN_FEATURE_FLAGS` | Comma-separated list of experimental feature names to enable (case-insensitive). Recognized values include `docker-local-dev`, `storage`, `functions`, and `postgresql`. |
|
|
183
|
+
| `RAYFIN_WEBSERVICE_IMAGE_NAME` | **Experimental.** Override the webservice container image used by `rayfin dev --provider docker` and Docker Compose. Defaults to `ghcr.io/microsoft/project-rayfin/webservice:cli-<version>`. |
|
|
151
184
|
| `RAYFIN_APPINSIGHTS_CONNECTION_STRING` | Override the telemetry endpoint for the CLI and VS Code extension. |
|
|
152
185
|
|
|
153
186
|
### Recognized `RAYFIN_FEATURE_FLAGS` values
|
|
154
187
|
|
|
155
188
|
| Flag | Effect |
|
|
156
189
|
| --- | --- |
|
|
190
|
+
| `docker-local-dev` | Allows `rayfin dev --provider docker` and the Docker maintenance commands. Bare `rayfin dev` remains available without this flag and defaults to Fabric. |
|
|
157
191
|
| `storage` | Exposes storage commands (`rayfin dev storage *`) and storage prompts during `rayfin init`. |
|
|
158
192
|
| `functions` | Exposes Functions service prompts during `rayfin init`. |
|
|
159
193
|
| `postgresql` | Adds PostgreSQL as a selectable dialect during `rayfin init` and `rayfin init` with bundled templates. |
|
package/assets/docs/cli/index.md
CHANGED
|
@@ -16,10 +16,12 @@ see [CLI Installation](./installation.md).
|
|
|
16
16
|
```bash
|
|
17
17
|
npm create @microsoft/rayfin@latest my-app # 1. Create a project from a template
|
|
18
18
|
cd my-app
|
|
19
|
-
|
|
20
|
-
npm run dev # 3. Run the frontend dev server
|
|
19
|
+
npm run dev # 2. Start the complete development session
|
|
21
20
|
```
|
|
22
21
|
|
|
22
|
+
The scaffolded `dev` script runs `rayfin dev`.
|
|
23
|
+
It provisions or reuses a Fabric backend, applies the declared services and schema, and starts the frontend and enabled Functions locally.
|
|
24
|
+
|
|
23
25
|
> **Existing or empty projects:** Use `npx rayfin init` instead of `npm create` to add Rayfin to a project that already has source code or an empty directory.
|
|
24
26
|
> The init command walks you through enabling services, choosing a database dialect, and configuring static hosting without scaffolding a new template.
|
|
25
27
|
|
|
@@ -41,6 +43,13 @@ For the full walkthrough, see the [CLI Quickstart](./quickstart.md) or the [Buil
|
|
|
41
43
|
> Use this to enable or disable services, switch the database dialect, or toggle static hosting without editing `rayfin.yml` by hand.
|
|
42
44
|
> The CLI preserves your data model files under `rayfin/data/` during reconfiguration.
|
|
43
45
|
|
|
46
|
+
### Development
|
|
47
|
+
|
|
48
|
+
| Command | Description |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `npx rayfin dev` | Start the development session. Uses the Fabric backend provider by default, provisions a missing AppBackend, applies declared state, and starts frontend and Functions code locally. |
|
|
51
|
+
| `npx rayfin dev --provider docker` | Run the managed backend through the preview Docker provider while keeping frontend and Functions code local. |
|
|
52
|
+
|
|
44
53
|
### Deployment
|
|
45
54
|
|
|
46
55
|
| Command | Description |
|
|
@@ -55,6 +64,20 @@ For the full walkthrough, see the [CLI Quickstart](./quickstart.md) or the [Buil
|
|
|
55
64
|
| `npx rayfin up secrets apply` | Read secrets from `rayfin/.env` file (prefixed with `RAYFIN_SECRET_`) and securely apply them to the remote Rayfin item workload. Validates that secrets are persisted. Use `--env-file <path>` to specify a custom .env file location. |
|
|
56
65
|
| `npx rayfin up staticapp deploy` | Build, package, and deploy static content to the remote Rayfin item. Add `--skip-build` to deploy existing build output without rebuilding. |
|
|
57
66
|
|
|
67
|
+
### Connectors
|
|
68
|
+
|
|
69
|
+
Connectors let a Rayfin app read from existing Fabric sources. The `connector` command group is only registered when `RAYFIN_FEATURE_FLAGS` contains `connectors`. See [Connectors](./connectors/index.md) for the full guide.
|
|
70
|
+
|
|
71
|
+
| Command | Description |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `npx rayfin connector search [query]` | Discover Fabric sources you can connect to. See [Searching for sources](./connectors/search.md). |
|
|
74
|
+
| `npx rayfin connector add` | Declare a connector in `rayfin.yml` and run schema discovery. See [Adding a connector](./connectors/add.md). |
|
|
75
|
+
| `npx rayfin connector list` | List the connectors declared in the current project. |
|
|
76
|
+
| `npx rayfin connector remove <name>` | Remove a connector's `rayfin.yml` entry and its `rayfin/connectors/<name>/` directory. |
|
|
77
|
+
| `npx rayfin connector inspect` | Run a read-only sample query against a connector's source. See [Inspecting a source](./connectors/inspect.md). |
|
|
78
|
+
| `npx rayfin connector invoke <name> <operation>` | Run one named operation against a configured connector. See [Invoking an operation](./connectors/invoke.md). |
|
|
79
|
+
| `npx rayfin up connector apply` | Re-apply connector configuration to the remote Rayfin item. |
|
|
80
|
+
|
|
58
81
|
## Update the CLI
|
|
59
82
|
|
|
60
83
|
To get the latest version of the Rayfin CLI and its dependencies:
|
|
@@ -60,15 +60,14 @@ npx rayfin --help
|
|
|
60
60
|
|
|
61
61
|
## First steps
|
|
62
62
|
|
|
63
|
-
Start the
|
|
63
|
+
Start the complete development session:
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
|
|
66
|
+
npm run dev
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Wait for the deployment to complete before continuing.
|
|
69
|
+
The bundled templates' script runs `rayfin dev`.
|
|
70
|
+
It provisions or reuses the Fabric backend, applies declared state, generates framework environment variables, and starts the frontend and enabled Functions locally.
|
|
72
71
|
|
|
73
72
|
Apply schema changes after updating your data models:
|
|
74
73
|
|
|
@@ -76,12 +75,6 @@ Apply schema changes after updating your data models:
|
|
|
76
75
|
npx rayfin up db apply
|
|
77
76
|
```
|
|
78
77
|
|
|
79
|
-
Run your frontend dev server in a separate terminal:
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npm run dev
|
|
83
|
-
```
|
|
84
|
-
|
|
85
78
|
## Update the CLI
|
|
86
79
|
|
|
87
80
|
To get the latest version:
|
|
@@ -34,6 +34,19 @@ npx rayfin init
|
|
|
34
34
|
|
|
35
35
|
This installs the CLI and runs the interactive setup to create the `rayfin/` directory with starter configuration files.
|
|
36
36
|
|
|
37
|
+
## Develop locally
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx rayfin dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- Uses the Fabric backend provider by default and provisions a missing AppBackend.
|
|
44
|
+
- Applies runtime settings and database schema before starting user code.
|
|
45
|
+
- Starts the frontend and enabled Functions as local processes.
|
|
46
|
+
- Press `Ctrl+C` to end the session.
|
|
47
|
+
|
|
48
|
+
Bundled templates expose the same workflow as `npm run dev`.
|
|
49
|
+
|
|
37
50
|
## Deploy to Fabric
|
|
38
51
|
|
|
39
52
|
```bash
|
|
@@ -69,8 +82,9 @@ npx rayfin up db apply [--force]
|
|
|
69
82
|
|
|
70
83
|
If `staticHosting` is enabled in `rayfin/rayfin.yml`, `npx rayfin up` automatically builds, packages, and deploys your static assets.
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
`rayfin dev` never publishes static content, so Vite can serve the frontend without a static deployment.
|
|
86
|
+
|
|
87
|
+
The lower-level `npx rayfin up --exclude-services staticHosting` command remains available for existing scripts and automation that need to run the deployment workflow while skipping only static content.
|
|
74
88
|
|
|
75
89
|
To redeploy static content independently without running the full `rayfin up` flow:
|
|
76
90
|
|
|
@@ -26,7 +26,7 @@ Apply `@role` at the class level to control which roles can perform which action
|
|
|
26
26
|
| --- | --- |
|
|
27
27
|
| `roleName` | The role name (`'anonymous'` or `'authenticated'`). |
|
|
28
28
|
| `actions` | A single action or array of actions: `'create'`, `'read'`, `'update'`, `'delete'`, or `'*'` for all. |
|
|
29
|
-
| `options` | Optional object with `
|
|
29
|
+
| `options` | Optional object with `policy`, `include`, and `exclude` properties. |
|
|
30
30
|
|
|
31
31
|
## Basic example
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ import { entity, role, uuid, text } from '@microsoft/rayfin-core';
|
|
|
38
38
|
@entity()
|
|
39
39
|
@role('anonymous', 'read')
|
|
40
40
|
@role('authenticated', ['create', 'read', 'update', 'delete'], {
|
|
41
|
-
|
|
41
|
+
policy: (claims, item) => claims.sub.eq(item.user_id),
|
|
42
42
|
})
|
|
43
43
|
export class Todo {
|
|
44
44
|
@uuid() id!: string;
|
|
@@ -52,11 +52,11 @@ In this example, authenticated users can only access Todo items where `user_id`
|
|
|
52
52
|
|
|
53
53
|
## Type-safe policy expressions
|
|
54
54
|
|
|
55
|
-
The `
|
|
55
|
+
The `policy` callback provides typed access to both claims and entity fields.
|
|
56
56
|
TypeScript infers the entity type from the decorated class, so you get autocompletion and refactor safety with no extra configuration.
|
|
57
57
|
|
|
58
58
|
```typescript
|
|
59
|
-
|
|
59
|
+
policy: (claims, item) => claims.sub.eq(item.user_id)
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
### Supported claims
|
|
@@ -78,7 +78,7 @@ check: (claims, item) => claims.sub.eq(item.user_id)
|
|
|
78
78
|
Combine expressions with `.and()` and `.or()`:
|
|
79
79
|
|
|
80
80
|
```typescript
|
|
81
|
-
|
|
81
|
+
policy: (claims, item) =>
|
|
82
82
|
claims.sub.eq(item.user_id).and(item.isActive.eq(true))
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -86,7 +86,7 @@ Both sides are parenthesized automatically, so grouping is always explicit:
|
|
|
86
86
|
|
|
87
87
|
```typescript
|
|
88
88
|
// (claims.role eq 'admin') or (claims.sub eq @item.owner_id)
|
|
89
|
-
|
|
89
|
+
policy: (claims, item) =>
|
|
90
90
|
claims.role.eq('admin').or(claims.sub.eq(item.owner_id))
|
|
91
91
|
```
|
|
92
92
|
|
|
@@ -100,7 +100,7 @@ Only allow the `Title` field during create:
|
|
|
100
100
|
|
|
101
101
|
```typescript
|
|
102
102
|
@role('authenticated', 'create', {
|
|
103
|
-
|
|
103
|
+
policy: (claims, item) => claims.sub.eq(item.createdBy),
|
|
104
104
|
include: ['Title'],
|
|
105
105
|
})
|
|
106
106
|
```
|
|
@@ -111,7 +111,7 @@ Hide sensitive fields from read operations:
|
|
|
111
111
|
|
|
112
112
|
```typescript
|
|
113
113
|
@role('authenticated', 'read', {
|
|
114
|
-
|
|
114
|
+
policy: (_claims, item) => item.IsAdmin.eq(false),
|
|
115
115
|
exclude: ['last_login'],
|
|
116
116
|
})
|
|
117
117
|
```
|
|
@@ -127,14 +127,14 @@ Apply different rules per action by using multiple `@role` decorators with singl
|
|
|
127
127
|
@entity()
|
|
128
128
|
@role('anonymous', 'read')
|
|
129
129
|
@role('authenticated', 'create', {
|
|
130
|
-
|
|
130
|
+
policy: (claims, item) => claims.sub.eq(item.createdBy),
|
|
131
131
|
include: ['Title'],
|
|
132
132
|
})
|
|
133
133
|
@role('authenticated', 'read', {
|
|
134
|
-
|
|
134
|
+
policy: (claims, item) => claims.sub.eq(item.createdBy),
|
|
135
135
|
})
|
|
136
136
|
@role('authenticated', 'update', {
|
|
137
|
-
|
|
137
|
+
policy: (claims, item) => claims.sub.eq(item.createdBy),
|
|
138
138
|
exclude: ['adminContent'],
|
|
139
139
|
})
|
|
140
140
|
export class SecureDocument {
|
|
@@ -155,7 +155,7 @@ import { blob, role } from '@microsoft/rayfin-core';
|
|
|
155
155
|
|
|
156
156
|
@blob()
|
|
157
157
|
@role('authenticated', '*', {
|
|
158
|
-
|
|
158
|
+
policy: (claims, item) => claims.sub.eq(item.owner_id),
|
|
159
159
|
})
|
|
160
160
|
export class ProfileImage {
|
|
161
161
|
owner_id!: string;
|
|
@@ -167,6 +167,7 @@ export class ProfileImage {
|
|
|
167
167
|
- The `@role` decorator collects permission metadata at class definition time.
|
|
168
168
|
- When you run `npx rayfin up db apply`, the CLI reads that metadata and generates DAB-compliant permission entries in the configuration.
|
|
169
169
|
- Policy callbacks are compiled into DAB OData-style policy strings (for example `@claims.sub eq @item.user_id`).
|
|
170
|
+
In the generated DAB configuration the compiled expression appears under a `check` key; `policy` is the name you author with.
|
|
170
171
|
- Field `include`/`exclude` arrays map directly to DAB field permission configuration.
|
|
171
172
|
- Multiple `@role` decorators on the same class are aggregated per role.
|
|
172
173
|
Conflicting declarations produce a warning at generation time.
|
|
@@ -14,13 +14,15 @@ Run `npm create @microsoft/rayfin@latest` in a terminal window and select welcom
|
|
|
14
14
|
|
|
15
15
|
## Run the app
|
|
16
16
|
|
|
17
|
-
1.
|
|
18
|
-
|
|
17
|
+
1. Sign in to Fabric with `npx rayfin login`.
|
|
18
|
+
In an environment without OS credential storage, use `npx rayfin login --encryption-fallback-enabled` only if you accept plaintext token caching for development.
|
|
19
|
+
2. In the same terminal window, run `npm run dev`.
|
|
20
|
+
The command provisions or reuses the Fabric backend, applies declared state, and starts the frontend locally.
|
|
19
21
|
3. When the frontend starts, it will output the page to visit.
|
|
20
22
|
Visit and ensure you can view the Timestamp Tracker.
|
|
21
23
|
4. Click **Send Timestamp** to POST the current time to `/api/graphql/Timestamp`, then use **Refresh list** to pull back the newest 100 entries.
|
|
22
24
|
5. All UI plus data-fetching logic lives in a single file: `src/main.ts`.
|
|
23
|
-
6. To
|
|
25
|
+
6. To target a specific Fabric workspace, set `RAYFIN_WORKSPACE_ID` and re-run `npm run dev`.
|
|
24
26
|
|
|
25
27
|
## Update the data model
|
|
26
28
|
|
|
@@ -94,7 +96,7 @@ After updating your data models, test your app.
|
|
|
94
96
|
npm run dev
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
> NOTE:
|
|
99
|
+
> NOTE: Restart `npm run dev` after changing `rayfin.yml` so the backend receives the updated declared state.
|
|
98
100
|
|
|
99
101
|
## View your local database
|
|
100
102
|
|
|
@@ -8,15 +8,15 @@ title: Getting Started
|
|
|
8
8
|
Rayfin supports two development paths.
|
|
9
9
|
Choose the one that matches how you want to get started.
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Inner-loop development
|
|
12
12
|
|
|
13
|
-
Run
|
|
14
|
-
|
|
13
|
+
Run frontend and Functions code locally against a managed Rayfin backend.
|
|
14
|
+
Fabric is the default backend provider; the Docker provider is available separately as a preview.
|
|
15
|
+
The default path requires a Microsoft account with Fabric access, an accessible workspace, and the tenant settings needed to create an AppBackend.
|
|
15
16
|
|
|
16
17
|
1. Install prerequisites.
|
|
17
18
|
1. Scaffold a project with `npm create @microsoft/rayfin@latest` or [add Rayfin to an existing app](../cli/quickstart.md#add-rayfin-to-an-existing-project).
|
|
18
|
-
1. Start
|
|
19
|
-
1. Run your frontend with `npm run dev`.
|
|
19
|
+
1. Start the complete development session with `npm run dev` or `npx rayfin dev`.
|
|
20
20
|
|
|
21
21
|
**Start here:** [Build your first Rayfin app](./create-app-with-cli.md)
|
|
22
22
|
|
|
@@ -34,7 +34,10 @@ This path requires a Microsoft account with Fabric access and tenant admin setti
|
|
|
34
34
|
## Prerequisites
|
|
35
35
|
|
|
36
36
|
Install these tools before you begin with either path.
|
|
37
|
-
Rayfin requires Node.js 20 or later
|
|
37
|
+
Rayfin requires Node.js 20 or later and the GitHub CLI.
|
|
38
|
+
Docker Desktop or Docker Engine is required only for `rayfin dev --provider docker`.
|
|
39
|
+
Fabric development also requires OS credential storage for the token cache.
|
|
40
|
+
In dev containers, Codespaces, or Linux environments without a keychain, run `npx rayfin login --encryption-fallback-enabled` to explicitly allow the development-only plaintext fallback.
|
|
38
41
|
|
|
39
42
|
### Windows
|
|
40
43
|
|
|
@@ -15,6 +15,7 @@ your-project/
|
|
|
15
15
|
│ │ ├── schema.ts
|
|
16
16
|
│ │ └── *.ts
|
|
17
17
|
│ ├── .env
|
|
18
|
+
│ ├── .project.json
|
|
18
19
|
│ ├── rayfin.yml
|
|
19
20
|
│ └── tsconfig.json
|
|
20
21
|
├── src/
|
|
@@ -184,6 +185,16 @@ Configure an email provider for magic links, password resets, and email verifica
|
|
|
184
185
|
`rayfin/.env` is an optional environment file used to supply values to `rayfin.yml` via interpolation.
|
|
185
186
|
Do not commit secrets, and prefer a `rayfin/.env.example` file for documentation.
|
|
186
187
|
|
|
188
|
+
### rayfin/.project.json
|
|
189
|
+
|
|
190
|
+
`rayfin/.project.json` contains a random project-origin identifier created by `create-rayfin` when anonymous telemetry is enabled.
|
|
191
|
+
The CLI uses it to correlate the original scaffold event with later `rayfin up` deployment events without storing user, machine, workspace, or project names.
|
|
192
|
+
Commit this file so the project keeps the same scaffold lineage across machines, clones, and CI environments.
|
|
193
|
+
You should not need to edit it.
|
|
194
|
+
If you do not want deployments to share the scaffold lineage, you can safely delete `rayfin/.project.json`.
|
|
195
|
+
Deployments continue to work and stop reporting the origin correlation.
|
|
196
|
+
To keep the marker local, add it to `.gitignore` before committing it; if it is already tracked, remove it from source control.
|
|
197
|
+
|
|
187
198
|
### rayfin/data/*.ts
|
|
188
199
|
|
|
189
200
|
Files in `rayfin/data/` define your entities.
|
|
@@ -280,7 +291,8 @@ export default defineConfig({
|
|
|
280
291
|
### Environment variables
|
|
281
292
|
|
|
282
293
|
Rayfin manages environment variables through `rayfin/.env` using the `RAYFIN_PUBLIC_*` prefix convention.
|
|
283
|
-
When you run `
|
|
294
|
+
When you run `rayfin dev` (or the scaffolded `npm run dev` wrapper), the CLI prepares backend wiring and generates a `.env.local` file with framework-specific variable names before starting the frontend child script.
|
|
295
|
+
The file is written under `services.staticHosting.path` for nested frontends, or at the project root when no path is configured.
|
|
284
296
|
When the CLI detects a Vite or Next.js project automatically, you can omit `--framework`.
|
|
285
297
|
|
|
286
298
|
The following Vite variables are available in your frontend code after generation:
|
|
@@ -290,4 +302,5 @@ The following Vite variables are available in your frontend code after generatio
|
|
|
290
302
|
- `VITE_RAYFIN_PUBLISHABLE_KEY` — Publishable key used for Rayfin client authentication.
|
|
291
303
|
Sourced from `RAYFIN_PUBLIC_PUBLISHABLE_KEY` in `rayfin/.env`.
|
|
292
304
|
|
|
293
|
-
To override values, edit `rayfin/.env` directly and
|
|
305
|
+
To override values, edit `rayfin/.env` directly and restart `rayfin dev`.
|
|
306
|
+
You can also run `rayfin env --framework vite` directly when you only need to regenerate the framework file.
|
|
@@ -69,14 +69,21 @@ After deployment, the CLI prints the hosting URL and stores it in `rayfin/.deplo
|
|
|
69
69
|
|
|
70
70
|
#### Skip static deployment during local dev
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
Use `rayfin dev` for the normal inner loop.
|
|
73
|
+
It provisions or reuses the backend and starts Vite locally without publishing static content:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
rayfin dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Existing scripts and automation can still run `up` while skipping the static build/package/deploy phase:
|
|
73
80
|
|
|
74
81
|
```bash
|
|
75
82
|
rayfin up --exclude-services staticHosting
|
|
76
83
|
```
|
|
77
84
|
|
|
78
85
|
This skips only the static build/package/deploy phase — runtime settings are still posted, so previously deployed static content keeps serving from Fabric.
|
|
79
|
-
|
|
86
|
+
Rayfin's bundled samples and templates use `rayfin dev` instead.
|
|
80
87
|
|
|
81
88
|
### Standalone static deployment
|
|
82
89
|
|
|
@@ -5,15 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
Bare `rayfin dev` uses the Fabric provider by default.
|
|
9
|
+
Pass `--provider docker` to run the managed Rayfin backend and its services through Docker Compose instead.
|
|
10
|
+
|
|
11
|
+
The provider changes only the backend location.
|
|
12
|
+
The frontend and enabled functions always run as local processes during `rayfin dev`.
|
|
10
13
|
|
|
11
14
|
Docker and Docker Compose must be installed and running before using this command.
|
|
12
15
|
|
|
13
16
|
## Starting the environment
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
|
-
npx rayfin dev
|
|
19
|
+
npx rayfin dev --provider docker
|
|
17
20
|
```
|
|
18
21
|
|
|
19
22
|
This command:
|
|
@@ -23,8 +26,29 @@ This command:
|
|
|
23
26
|
- Allocates ports for each service.
|
|
24
27
|
- Starts containers for enabled services (WebService, database, and optional storage).
|
|
25
28
|
- Runs health checks and waits for all services to be healthy.
|
|
29
|
+
- Applies the project's declared data and storage configuration to the local backend.
|
|
30
|
+
- Starts the frontend with `npm run dev:frontend` when that script exists, falling back to `npm run dev` for existing projects.
|
|
31
|
+
- Resolves that script from `services.staticHosting.path` when the frontend lives in a nested package, otherwise from the project root.
|
|
32
|
+
- Builds and starts the configured local Functions host when `services.functions.enabled` is `true`.
|
|
33
|
+
|
|
34
|
+
The command remains attached to the frontend and Functions processes.
|
|
35
|
+
Press `Ctrl+C` to stop the session and tear down the provider-owned containers.
|
|
36
|
+
|
|
37
|
+
## Local functions and debugger
|
|
38
|
+
|
|
39
|
+
When functions are enabled, `rayfin dev --provider docker` reserves the nearest free Functions port starting at `7071` and starts Azure Functions Core Tools.
|
|
40
|
+
It writes the selected URL to `RAYFIN_PUBLIC_FUNCTIONS_URL` in `rayfin/.env` and regenerates the framework `.env.local` file.
|
|
41
|
+
When functions are disabled, it removes a stale Functions URL instead.
|
|
26
42
|
|
|
27
|
-
|
|
43
|
+
The command also:
|
|
44
|
+
|
|
45
|
+
- Merges local backend settings into the configured functions package's `local.settings.json`.
|
|
46
|
+
- Reserves a Node inspector port starting at `9229`.
|
|
47
|
+
- Adds `Functions: Attach` to the root `.vscode/launch.json` after the Functions host is ready.
|
|
48
|
+
- Patches recognized `src/services/rayfinClient.ts` and `src/services/bootstrap.ts` files to pass `VITE_RAYFIN_FUNCTIONS_URL` as `functionsBaseUrl`.
|
|
49
|
+
|
|
50
|
+
If `.vscode/launch.json` contains JSON with comments, Rayfin leaves it unchanged to avoid losing those comments and asks you to add the attach configuration manually.
|
|
51
|
+
Use `--no-emit-env` to leave a hand-managed `.env.local` file unchanged.
|
|
28
52
|
|
|
29
53
|
## Stopping and resetting
|
|
30
54
|
|
|
@@ -32,22 +56,31 @@ Wait for the `All services healthy` message before continuing.
|
|
|
32
56
|
|------|----------|
|
|
33
57
|
| `--stop` | Stop running containers without removing them |
|
|
34
58
|
| `--down` | Stop and remove containers |
|
|
35
|
-
| `--purge` |
|
|
59
|
+
| `--provider docker --purge` | Confirm deletion of provider-owned Docker volumes when the attached session ends |
|
|
60
|
+
| `--down --purge` | Confirm immediate container and volume deletion without starting a session |
|
|
61
|
+
| `--export-env` | Print the retained Docker provider environment in `.env` format |
|
|
36
62
|
|
|
37
63
|
```bash
|
|
38
64
|
npx rayfin dev --stop
|
|
39
65
|
npx rayfin dev --down
|
|
40
|
-
npx rayfin dev --purge
|
|
66
|
+
npx rayfin dev --down --purge
|
|
67
|
+
npx rayfin dev --export-env
|
|
68
|
+
npx rayfin dev --provider docker --purge
|
|
41
69
|
```
|
|
42
70
|
|
|
71
|
+
The retained `--stop`, `--down`, and `--export-env` maintenance actions operate only on Docker state.
|
|
72
|
+
They do not start a workflow session or contact Fabric.
|
|
73
|
+
Purge always requires interactive confirmation or global `--yes` in automation.
|
|
74
|
+
It cannot be combined with `--stop` or `--export-env`.
|
|
75
|
+
|
|
43
76
|
## Additional options
|
|
44
77
|
|
|
45
78
|
| Flag | Behavior |
|
|
46
79
|
|------|----------|
|
|
47
|
-
| `--
|
|
48
|
-
| `--
|
|
49
|
-
| `--
|
|
50
|
-
| `--
|
|
80
|
+
| `--provider docker` | Select the Docker backend instead of the default Fabric backend |
|
|
81
|
+
| `--skip-db-apply` | Skip automatic data configuration apply |
|
|
82
|
+
| `--no-emit-env` | Leave the existing framework `.env.local` file unchanged |
|
|
83
|
+
| `--verbose` | Show detailed diagnostic output |
|
|
51
84
|
|
|
52
85
|
## Subcommands
|
|
53
86
|
|
|
@@ -96,7 +129,7 @@ Changes to `rayfin.yml` require restarting the environment:
|
|
|
96
129
|
|
|
97
130
|
```bash
|
|
98
131
|
npx rayfin dev --down
|
|
99
|
-
npx rayfin dev
|
|
132
|
+
npx rayfin dev --provider docker
|
|
100
133
|
```
|
|
101
134
|
|
|
102
135
|
## Troubleshooting
|
|
@@ -105,7 +138,8 @@ npx rayfin dev
|
|
|
105
138
|
- **`rayfin dev db apply` fails** — make sure services are healthy first (`npx rayfin dev status`).
|
|
106
139
|
- **Stale services** — stop stale containers with `npx rayfin dev --down`, then restart.
|
|
107
140
|
- **`unsupported UUID` errors** — stop stale services with `npx rayfin dev --down`.
|
|
108
|
-
- **Port conflicts** —
|
|
141
|
+
- **Port conflicts** — stop the process using the reported port; Rayfin automatically slides the frontend, Functions, and inspector ports within bounded ranges.
|
|
142
|
+
- **Functions host missing** — install Azure Functions Core Tools by running `npx rayfin dev functions apply`, then retry.
|
|
109
143
|
|
|
110
144
|
## Enabling this feature
|
|
111
145
|
|
|
@@ -120,3 +154,6 @@ Or combine with other flags:
|
|
|
120
154
|
```bash
|
|
121
155
|
export RAYFIN_FEATURE_FLAGS=docker-local-dev,storage
|
|
122
156
|
```
|
|
157
|
+
|
|
158
|
+
This feature flag gates only Docker provider selection and Docker maintenance commands.
|
|
159
|
+
Bare `rayfin dev` is available without preview flags and uses Fabric.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/rayfin-guide",
|
|
3
|
-
"version": "1.35.0-alpha.
|
|
3
|
+
"version": "1.35.0-alpha.1331",
|
|
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": [
|