@microsoft/rayfin-guide 1.36.0-alpha.1756 → 1.36.0-beta.0
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 +36 -1
- package/assets/docs/cli/connectors/add.md +11 -1
- package/assets/docs/cli/connectors/index.md +1 -1
- package/assets/docs/cli/connectors/inspect.md +34 -1
- package/assets/docs/cli/functions/deploy.md +5 -1
- package/assets/docs/cli/functions/dev-apply.md +7 -1
- package/assets/docs/cli/functions/index.md +4 -2
- package/assets/docs/cli/functions/init.md +7 -1
- package/assets/docs/cli/index.md +19 -7
- package/assets/docs/cli/secrets.md +18 -8
- package/assets/docs/functions/connections/add-ado.md +8 -4
- package/assets/docs/functions/connections/add-azure-resource.md +17 -131
- package/assets/docs/functions/connections/add-fabric-resource.md +31 -61
- package/assets/docs/functions/connections/add-foundry.md +11 -4
- package/assets/docs/functions/connections/get-fabric-info.md +7 -25
- package/assets/docs/functions/connections/index.md +127 -22
- package/assets/docs/functions/index.md +39 -1
- package/assets/docs/functions/secrets.md +39 -11
- package/assets/docs/functions/writing-functions.md +27 -23
- package/assets/docs/getting-started/project-structure.md +3 -1
- package/package.json +1 -1
- package/assets/docs/functions/connections/add-work-iq.md +0 -39
|
@@ -62,6 +62,41 @@ npx rayfin up
|
|
|
62
62
|
|
|
63
63
|
If you are not signed in, the CLI launches an interactive login flow automatically.
|
|
64
64
|
|
|
65
|
+
### Prepare Fabric capacity
|
|
66
|
+
|
|
67
|
+
Before creating the Rayfin item, `rayfin up` checks whether the target workspace already has Fabric capacity.
|
|
68
|
+
If the workspace reports an assigned capacity, Rayfin uses it without changing or reevaluating the assignment.
|
|
69
|
+
|
|
70
|
+
On a first interactive deployment without a workspace target or `--capacity-id`, Rayfin asks you to choose:
|
|
71
|
+
|
|
72
|
+
1. `Use new workspace [Recommended]` runs workspace and capacity readiness.
|
|
73
|
+
2. `Select existing workspace` skips capacity readiness and opens the accessible-workspace picker.
|
|
74
|
+
|
|
75
|
+
Explicit workspace options and recorded deployments continue directly to their existing targeting flow without showing this choice.
|
|
76
|
+
Dry-run invocations do not show the choice.
|
|
77
|
+
An interactive invocation with `--capacity-id <id>` automatically prepares a new workspace and assigns that capacity without showing the workspace choice.
|
|
78
|
+
An untargeted non-interactive invocation automatically prepares a new workspace without prompting.
|
|
79
|
+
Pass `--capacity-id <id>` to use a specific capacity for that new workspace.
|
|
80
|
+
Pass an existing workspace target to deploy there instead.
|
|
81
|
+
|
|
82
|
+
When the workspace needs capacity, an interactive deployment asks for confirmation before assigning the selected or trial capacity.
|
|
83
|
+
Pass `--yes` to approve a deterministic capacity assignment without the prompt:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npx rayfin up --yes
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
To select a specific existing capacity, pass its Fabric capacity ID.
|
|
90
|
+
This explicitly approves assigning that capacity:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx rayfin up --capacity-id <capacity-guid>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Do not combine `--capacity-id` with `--workspace`, `--workspace-id`, or `--workspace-uri`.
|
|
97
|
+
If multiple premium capacities are available, select one explicitly with `--capacity-id`.
|
|
98
|
+
An existing recorded deployment keeps its current workspace capacity and ignores a newly supplied capacity ID.
|
|
99
|
+
|
|
65
100
|
### Choose a unique Fabric item name
|
|
66
101
|
|
|
67
102
|
By default, `rayfin up` uses the project ID from `rayfin.yml` as the Fabric item name.
|
|
@@ -84,7 +119,7 @@ npx rayfin up \
|
|
|
84
119
|
--output json
|
|
85
120
|
```
|
|
86
121
|
|
|
87
|
-
|
|
122
|
+
The `--yes` option also approves reuse of an existing same-named item, so use it only when both automatic capacity assignment and item reuse are acceptable.
|
|
88
123
|
|
|
89
124
|
### What `rayfin up` does
|
|
90
125
|
|
|
@@ -28,6 +28,15 @@ If you do not already know the workspace and item IDs, run [`connector search`](
|
|
|
28
28
|
| `-y, --yes` | no | Auto-accept overwrite and confirmation prompts (non-interactive). |
|
|
29
29
|
| `-v, --verbose` | no | Verbose diagnostics. |
|
|
30
30
|
|
|
31
|
+
## Authentication
|
|
32
|
+
|
|
33
|
+
`connector add` writes `auth.type: application` for Category A connectors: `fabric-sqlanalytics`, `fabric-warehouse`, and `fabric-sqldatabase`.
|
|
34
|
+
The connector accesses the data source with the app's identity rather than the signed-in end user's identity.
|
|
35
|
+
For per-user data-source access, explicitly set `auth.type: delegated` in `rayfin.yml` before deploying.
|
|
36
|
+
|
|
37
|
+
Category B connectors continue to require `auth.type: delegated`.
|
|
38
|
+
Existing declarations are not migrated, and omitting `auth.type` remains a validation error.
|
|
39
|
+
|
|
31
40
|
## Scoping operations
|
|
32
41
|
|
|
33
42
|
Without `--operations`, `connector add` writes **every** operation the catalog allows for the type. Prefer scoping at add time over hand-editing YAML afterwards:
|
|
@@ -46,7 +55,7 @@ connectors:
|
|
|
46
55
|
workspaceId: ${WS_ID}
|
|
47
56
|
itemId: ${ITEM_ID}
|
|
48
57
|
auth:
|
|
49
|
-
type:
|
|
58
|
+
type: application
|
|
50
59
|
operations:
|
|
51
60
|
- name: read
|
|
52
61
|
- name: update
|
|
@@ -97,6 +106,7 @@ With `--json`, the same information is available under `install`:
|
|
|
97
106
|
|
|
98
107
|
Running `connector add` against a name already in `rayfin.yml` refreshes the declaration.
|
|
99
108
|
It prompts before overwriting, or requires `--yes` when non-interactive.
|
|
109
|
+
This rewrites `auth.type` to the catalog default, so reapply an explicit `delegated` setting for a Category A connector after re-adding it if needed.
|
|
100
110
|
|
|
101
111
|
Your generated entity files under `rayfin/connectors/<name>/` are **preserved**.
|
|
102
112
|
Only `metadata.json` is rewritten, by schema discovery.
|
|
@@ -35,7 +35,7 @@ The commands available to a connector, and the code you write against it, depend
|
|
|
35
35
|
|
|
36
36
|
| | Category A — GraphQL entity connectors | Category B — function-bridge connectors |
|
|
37
37
|
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
|
|
38
|
-
| **Types** | `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase
|
|
38
|
+
| **Types** | `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase` | `fabric-semanticmodel`; `kusto` (**experimental**) |
|
|
39
39
|
| **App surface** | Generated entity files with typed CRUD through the data client | Named operations carrying raw queries |
|
|
40
40
|
| **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 |
|
|
41
41
|
| **Auth** | `delegated` or configured per project | Must be `delegated` |
|
|
@@ -54,11 +54,44 @@ Applies to `--entity` mode only.
|
|
|
54
54
|
|
|
55
55
|
Applies to `--entity` and `--query` modes.
|
|
56
56
|
|
|
57
|
-
- **SQL** — must start with `SELECT` or `WITH`;
|
|
57
|
+
- **SQL** — must start with `SELECT` or `WITH`; an embedded `;` is rejected while a trailing `;` is allowed; rejects `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `EXEC`/`EXECUTE`, and `INTO` anywhere outside a string literal.
|
|
58
|
+
- **SQL result contract** — the query must produce one result set. If Tedious emits a second result set, inspection rejects the query instead of combining rows with a different column contract.
|
|
58
59
|
- **DAX** — must start with `EVALUATE`.
|
|
59
60
|
- `--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.
|
|
60
61
|
- `--rows <n>` caps the sample size — maximum 100. The default is mode-specific: entity listing (neither `--entity` nor `--query`) defaults to **100**, while `--entity` and `--query` sampling default to **10**. The result reports `truncated: true` when the source had more rows than the cap; inspect fetches one row beyond the cap to detect that, then discards it.
|
|
61
62
|
|
|
63
|
+
## SQL column types and values
|
|
64
|
+
|
|
65
|
+
SQL inspection reads column types from Tedious result metadata, including when a query returns zero rows.
|
|
66
|
+
It never guesses a column type from row values.
|
|
67
|
+
Plain output lists each column as `name (type)` before populated or empty results.
|
|
68
|
+
If the contract exceeds the terminal width, it folds between column entries.
|
|
69
|
+
|
|
70
|
+
The `columns[].type` field in JSON uses this normalized vocabulary:
|
|
71
|
+
|
|
72
|
+
| Normalized type | Tedious metadata types |
|
|
73
|
+
| ------------------ | ------------------------------------------------------------------------ |
|
|
74
|
+
| `integer` | `TinyInt`, `SmallInt`, `Int`, `BigInt`, `IntN` |
|
|
75
|
+
| `decimal` | `Decimal`, `Numeric`, money types, and their nullable forms |
|
|
76
|
+
| `floating-point` | `Real`, `Float`, `FloatN` |
|
|
77
|
+
| `text` | Character and Unicode text types, plus `Xml` |
|
|
78
|
+
| `boolean` | `Bit`, `BitN` |
|
|
79
|
+
| `date` | `Date` |
|
|
80
|
+
| `time` | `Time` |
|
|
81
|
+
| `datetime` | `SmallDateTime`, `DateTime`, `DateTimeN`, `DateTime2`, `DateTimeOffset` |
|
|
82
|
+
| `uniqueidentifier` | `UniqueIdentifier` |
|
|
83
|
+
| `binary` | `Binary`, `VarBinary`, `Image` |
|
|
84
|
+
| `unknown` | `Null`, `Variant`, `UDT`, `TVP`, and unrecognized or custom types |
|
|
85
|
+
|
|
86
|
+
Plain output renders SQL `date` values as `YYYY-MM-DD`, so the calendar value does not shift with the local time zone.
|
|
87
|
+
SQL `time` values render as the UTC time portion `HH:mm:ss.sss`, without Tedious' internal 1970 date anchor.
|
|
88
|
+
SQL `datetime` and `datetime2` are timezone-naive values that Tedious represents using a JavaScript `Date`; plain and JSON output therefore use an ISO value with `Z` by driver convention.
|
|
89
|
+
SQL `datetimeoffset` is also returned as a JavaScript `Date`, so its original offset is not preserved.
|
|
90
|
+
SQL `bigint` row values are strings, while decimal and numeric row values are JavaScript numbers and can carry JavaScript precision limitations.
|
|
91
|
+
Binary and buffer-backed custom values render as terminal-safe `0x` hexadecimal in plain output and use the existing column-width truncation marker when needed.
|
|
92
|
+
JSON row serialization is unchanged: JavaScript `Date` values remain ISO strings, while `columns[].type` now reports the metadata-derived normalized type instead of `unknown`.
|
|
93
|
+
Queries that produce a second SQL result set are rejected when the driver emits its second column contract, including newline-separated batches without semicolons.
|
|
94
|
+
|
|
62
95
|
## Examples
|
|
63
96
|
|
|
64
97
|
```bash
|
|
@@ -14,6 +14,10 @@ npx rayfin up functions deploy [-v | --verbose] [--skip-build] [--json]
|
|
|
14
14
|
|
|
15
15
|
`npx rayfin up` already deploys functions as part of a full deployment. Use `up functions deploy` when you want to run **only** the functions step — for example to retry after a functions deploy failed, or to push a functions-only change without redeploying the rest of the app.
|
|
16
16
|
|
|
17
|
+
This standalone command uploads function code; it does not validate or apply `services.functions.auth.type` from YAML or migrate the remote Functions auth mode.
|
|
18
|
+
After setting `services.functions.auth.type: application` for an existing app, run a full `npx rayfin up` to apply project settings.
|
|
19
|
+
See [Application authentication](../../functions/index.md#application-authentication).
|
|
20
|
+
|
|
17
21
|
## Prerequisites
|
|
18
22
|
|
|
19
23
|
Run `npx rayfin up` at least once first. This command deploys to an existing remote item, so a remote endpoint must already exist. If there is no active deployment, run a full `npx rayfin up`.
|
|
@@ -35,4 +39,4 @@ Run `npx rayfin up` at least once first. This command deploys to an existing rem
|
|
|
35
39
|
|
|
36
40
|
- [`functions init`](./init.md) — scaffold and enable functions.
|
|
37
41
|
- [`dev functions apply`](./dev-apply.md) — run and debug functions locally before deploying.
|
|
38
|
-
- [Managing Secrets](../secrets.md) — push secrets that deployed functions read via `ctx.
|
|
42
|
+
- [Managing Secrets](../secrets.md) — push secrets that deployed functions read via `ctx.Secrets`.
|
|
@@ -42,6 +42,11 @@ This command does not start the frontend.
|
|
|
42
42
|
Run the Vite frontend separately to invoke local functions through `/.rayfin/api/<name>`, or use `npx rayfin dev` to start both together.
|
|
43
43
|
If the local Functions host is unavailable, the Vite adapter returns HTTP 502 instead of invoking deployed function code.
|
|
44
44
|
|
|
45
|
+
This standalone command does not validate or apply the project's Functions auth setting.
|
|
46
|
+
Full `npx rayfin up` and normal `npx rayfin dev` perform that validation when applying project settings.
|
|
47
|
+
Run a full `npx rayfin up` to apply [`services.functions.auth.type: application`](../../functions/index.md#application-authentication) to the remote app.
|
|
48
|
+
For local token identity, see [Local development](../../functions/connections/index.md#local-development).
|
|
49
|
+
|
|
45
50
|
## Automatic recompilation
|
|
46
51
|
|
|
47
52
|
Both `npx rayfin dev functions apply` and `npx rayfin dev` build the functions package once, then run its `build:watch` script alongside the local Functions host if the script is configured.
|
|
@@ -67,7 +72,7 @@ With debugging enabled (default), attach your debugger to the inspector port (`9
|
|
|
67
72
|
|
|
68
73
|
## Secrets in local development
|
|
69
74
|
|
|
70
|
-
Locally there is no deployed secret bag, so `ctx.
|
|
75
|
+
Locally there is no deployed secret bag, so `ctx.Secrets.<NAME>` falls back to `process.env`. To provide a secret, add it under `Values` in `rayfin/functions/local.settings.json`; the functions host loads those entries into `process.env`. See [Managing Secrets](../secrets.md#using-secrets-in-local-development).
|
|
71
76
|
|
|
72
77
|
## Next step
|
|
73
78
|
|
|
@@ -80,3 +85,4 @@ npx rayfin up functions deploy
|
|
|
80
85
|
```
|
|
81
86
|
|
|
82
87
|
See [`up functions deploy`](./deploy.md).
|
|
88
|
+
The standalone deployment uploads function code; it does not apply YAML auth settings or migrate the remote Functions auth mode.
|
|
@@ -7,6 +7,8 @@ sidebar_position: 4
|
|
|
7
7
|
Rayfin functions are server-side user-defined functions (UDFs) that run in the Fabric runtime and are invocable from your frontend through `RayfinClient`. Use them for logic that must run on the backend — secrets and API keys, privileged data access, server-side validation, and anything that should not be exposed or tampered with in client code.
|
|
8
8
|
|
|
9
9
|
The functions project lives at `rayfin/functions/` and is enabled by the `services.functions.enabled` flag in `rayfin.yml` (set for you the first time you run [`functions init`](./init.md)).
|
|
10
|
+
Enabled Functions also require explicit `services.functions.auth.type: application`, which new scaffolds set.
|
|
11
|
+
See [Application authentication](../../functions/index.md#application-authentication) for existing-app configuration and downstream resource permissions.
|
|
10
12
|
|
|
11
13
|
Each command has its own reference page:
|
|
12
14
|
|
|
@@ -34,8 +36,8 @@ functions init → write UDFs in src/function_app.ts → dev functions apply
|
|
|
34
36
|
- `rayfin/functions/src/function_app.ts` — where you register UDFs with `udf.func()`.
|
|
35
37
|
- `rayfin/functions/src/types.ts` — auto-generated `AppFunctionsSchema`; regenerated by `functions init` (one-shot) and by the watcher inside `dev functions apply`.
|
|
36
38
|
- `rayfin/functions/{package.json,host.json,tsconfig.json,local.settings.json}` — the functions app manifest, host config, TypeScript project references, and local settings.
|
|
37
|
-
- `rayfin.yml` — the `services.functions` block (`enabled`, `buildCommand`).
|
|
39
|
+
- `rayfin.yml` — the `services.functions` block (`enabled`, `auth.type`, `buildCommand`).
|
|
38
40
|
|
|
39
41
|
## Secrets
|
|
40
42
|
|
|
41
|
-
Functions read secrets at runtime
|
|
43
|
+
Functions read secrets at runtime as typed properties on `ctx.Secrets`, backed by the host secret bag with a `process.env` fallback. Manage remote secrets with `npx rayfin secret set` — or bulk-set them from a file with `npx rayfin secret set --env-file` — see [Managing Secrets](../secrets.md).
|
|
@@ -24,12 +24,15 @@ Run this from a directory that already contains a `rayfin/` project (i.e. you ha
|
|
|
24
24
|
## What it does
|
|
25
25
|
|
|
26
26
|
1. **Scaffolds** `rayfin/functions/` with a starter function app, `host.json`, `tsconfig.json`, `package.json`, and `local.settings.json`.
|
|
27
|
-
2. **Enables the service** in `rayfin.yml` by setting `services.functions.enabled: true` and `services.functions.buildCommand: 'npm run build'`.
|
|
27
|
+
2. **Enables the scaffolded service** in `rayfin.yml` by setting `services.functions.enabled: true`, `services.functions.auth.type: application`, and `services.functions.buildCommand: 'npm run build'`.
|
|
28
28
|
3. **Installs dependencies** for the functions project.
|
|
29
29
|
4. **Builds** the project.
|
|
30
30
|
5. **Generates types** — runs a one-shot typegen to produce `rayfin/functions/src/types.ts` (the `AppFunctionsSchema`).
|
|
31
31
|
6. **Installs AI agent files** so assistants understand the functions surface.
|
|
32
32
|
|
|
33
|
+
Enabled Functions require explicit application authentication.
|
|
34
|
+
For existing apps, see [Application authentication](../../functions/index.md#application-authentication) for the configuration and full-deployment requirement.
|
|
35
|
+
|
|
33
36
|
## Runtime version
|
|
34
37
|
|
|
35
38
|
Fresh and forced scaffolds pin `@microsoft/fabric-user-data-functions` to the exact version of the running Rayfin CLI, matching connector scaffolding.
|
|
@@ -60,6 +63,9 @@ rayfin/
|
|
|
60
63
|
- **Without `--force`** on an existing project, it preserves your `function_app.ts` and only refreshes dependencies, build, and generated types.
|
|
61
64
|
- **With `--force`**, it overwrites the scaffold (a warning is shown before your files are replaced).
|
|
62
65
|
|
|
66
|
+
Re-running without `--force` does not rewrite the existing Functions auth setting.
|
|
67
|
+
Set `services.functions.auth.type: application` explicitly in an existing app rather than relying on a re-run to migrate it.
|
|
68
|
+
|
|
63
69
|
## Next step
|
|
64
70
|
|
|
65
71
|
Start the local host and typegen watcher:
|
package/assets/docs/cli/index.md
CHANGED
|
@@ -89,7 +89,7 @@ Connectors let a Rayfin app read from — and, for some types, write to — Micr
|
|
|
89
89
|
|
|
90
90
|
### Secrets
|
|
91
91
|
|
|
92
|
-
Secrets are encrypted values stored on your deployed Rayfin item and read at runtime — for example by [functions](./functions/index.md) via `ctx.
|
|
92
|
+
Secrets are encrypted values stored on your deployed Rayfin item and read at runtime — for example by [functions](./functions/index.md) via `ctx.Secrets`. See [Managing Secrets](./secrets.md) for the full guide.
|
|
93
93
|
|
|
94
94
|
| Command | Description |
|
|
95
95
|
| --- | --- |
|
|
@@ -129,18 +129,30 @@ export RAYFIN_TELEMETRY_OPTOUT=1
|
|
|
129
129
|
|
|
130
130
|
## Diagnostic logs
|
|
131
131
|
|
|
132
|
-
`npx rayfin up
|
|
132
|
+
`npx rayfin up`, workflow-based `npx rayfin dev`, and `npx rayfin dev functions apply` record detailed diagnostics under `~/.rayfin/logs/` even when `--verbose` is absent, including when using `--json` or `--output json`.
|
|
133
133
|
After a failure, open the file identified by `Diagnostic log:` to inspect the original invocation without rerunning it.
|
|
134
134
|
JSON failures include the same path in the `diagnosticLog` field of the single result object.
|
|
135
135
|
`dev` JSON failures also include a `hint` with recovery guidance, including provider/configuration preflight errors and unexpected failures.
|
|
136
136
|
|
|
137
|
-
Adding `--verbose` also mirrors diagnostic records to stderr while
|
|
137
|
+
Adding `--verbose` also mirrors diagnostic records to stderr while these commands run.
|
|
138
138
|
The CLI rejects combining `--verbose` with `--json` or `--output json`; detailed diagnostics are still recorded in the log file without `--verbose`.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
Other standalone subcommands and Docker maintenance flags such as `dev --stop` do not record these logs.
|
|
140
|
+
|
|
141
|
+
Local Functions sessions show function endpoints, the debugger address, application output, and warnings or errors by default.
|
|
142
|
+
Recognized host startup and configuration detail, HTTP request metadata, and successful initial build output are kept in diagnostics; use `--verbose` to mirror that detail to the terminal.
|
|
143
|
+
When the initial build fails, human output includes a bounded tail of compiler output, and JSON errors include it in `buildOutput`.
|
|
144
|
+
The tail retains up to 100 complete lines and 64 KiB, with an explicit marker when earlier output is omitted.
|
|
145
|
+
Verbose mode does not replay the same compiler output a second time.
|
|
146
|
+
Terminal output preserves stack-frame paths and line numbers, while masking credentials and email addresses.
|
|
147
|
+
Application lines up to 16 KiB are preserved; oversized lines are replaced with an explicit truncation marker.
|
|
148
|
+
Persistent diagnostic logs continue to apply their separate privacy and size limits.
|
|
149
|
+
Failed HTTP responses show their status and, when request metadata is available, the method and path without query strings.
|
|
150
|
+
Unrecognized output remains visible.
|
|
151
|
+
Frontend output is unchanged.
|
|
152
|
+
Both `dev` and `dev functions apply` flush their logs after cleanup on Ctrl-C, runtime failure, or normal completion.
|
|
142
153
|
Piped runtime and build output is captured with a 1 MiB limit per stream.
|
|
143
|
-
Interactive
|
|
154
|
+
Interactive Functions sessions keep standard input attached for keyboard interaction, while stdout and stderr are piped for filtering and diagnostic capture.
|
|
155
|
+
Other interactive runtimes that inherit the terminal keep their keyboard and TTY behavior; their console output is not captured, and the log records that limitation alongside lifecycle events.
|
|
144
156
|
|
|
145
157
|
Logs stay on your machine and are independent of telemetry opt-out.
|
|
146
158
|
The log directory is shared across projects on your machine, so the retention limits below apply across all projects using it.
|
|
@@ -4,7 +4,7 @@ sidebar_position: 50
|
|
|
4
4
|
|
|
5
5
|
# Managing Secrets
|
|
6
6
|
|
|
7
|
-
Secrets are encrypted values — API keys, connection strings, tokens — that your app needs at runtime but must never ship in client code. They are stored securely on your deployed Rayfin item and read on the server by [functions](./functions/index.md) via `ctx.
|
|
7
|
+
Secrets are encrypted values — API keys, connection strings, tokens — that your app needs at runtime but must never ship in client code. They are stored securely on your deployed Rayfin item and read on the server by [functions](./functions/index.md) via `ctx.Secrets`.
|
|
8
8
|
|
|
9
9
|
Manage secrets with the `npx rayfin secret` command group:
|
|
10
10
|
|
|
@@ -105,18 +105,28 @@ Deleting a secret that does not exist reports a not-found error — run `npx ray
|
|
|
105
105
|
|
|
106
106
|
## Reading secrets from functions
|
|
107
107
|
|
|
108
|
-
Server-side functions read secrets at runtime
|
|
108
|
+
Server-side functions read secrets at runtime as typed properties on `ctx.Secrets`, which resolve against the deployed item's secret bag and fall back to `process.env`. Set a secret with `npx rayfin secret set <name>`, then read it by the same name inside your handler:
|
|
109
109
|
|
|
110
110
|
```ts
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
import { type RayfinContext } from "@microsoft/fabric-user-data-functions";
|
|
112
|
+
|
|
113
|
+
udf.func(
|
|
114
|
+
"summarize",
|
|
115
|
+
async (ctx: RayfinContext<AppSchema>, input: { text: string }) => {
|
|
116
|
+
const apiKey = ctx.Secrets.OPENAI_KEY;
|
|
117
|
+
// ... call the API with apiKey
|
|
118
|
+
},
|
|
119
|
+
[],
|
|
120
|
+
);
|
|
115
121
|
```
|
|
116
122
|
|
|
123
|
+
The `RayfinContext<AppSchema>` annotation is what makes this type-safe. An unannotated `ctx` is contextually `any`, so `ctx.Secrets.OPENAI_KEY` compiles whether or not the secret is declared — and the annotation is also how typegen recognises the parameter as the injected context rather than a request-body argument.
|
|
124
|
+
|
|
125
|
+
Setting the secret is what types it: the CLI regenerates `rayfin/functions/src/secrets.generated.ts`, so `ctx.Secrets.OPENAI_KEY` is a `string` and an undeclared name is a compile error. See [Secrets](../functions/secrets.md) for the full model.
|
|
126
|
+
|
|
117
127
|
## Using secrets in local development
|
|
118
128
|
|
|
119
|
-
When you run functions locally with [`npx rayfin dev functions apply`](./functions/dev-apply.md), there is no deployed secret bag, so `ctx.
|
|
129
|
+
When you run functions locally with [`npx rayfin dev functions apply`](./functions/dev-apply.md), there is no deployed secret bag, so `ctx.Secrets.<NAME>` falls back to `process.env`. To make a secret available locally, add it under `Values` in `rayfin/functions/local.settings.json` — the Azure Functions host loads those entries into `process.env`:
|
|
120
130
|
|
|
121
131
|
```json
|
|
122
132
|
{
|
|
@@ -166,6 +176,6 @@ If `secret delete` reports the secret was not found:
|
|
|
166
176
|
|
|
167
177
|
## See also
|
|
168
178
|
|
|
169
|
-
- [Functions](./functions/index.md) — read secrets from server-side functions with `ctx.
|
|
179
|
+
- [Functions](./functions/index.md) — read secrets from server-side functions with `ctx.Secrets`.
|
|
170
180
|
- [CLI quickstart](./quickstart.md)
|
|
171
181
|
- [Environment configuration](./env-interpolation.md)
|
|
@@ -4,10 +4,14 @@ sidebar_position: 5
|
|
|
4
4
|
|
|
5
5
|
# Add Azure DevOps
|
|
6
6
|
|
|
7
|
-
Call the [Azure DevOps REST API](https://learn.microsoft.com/en-us/rest/api/azure/devops/) from a function
|
|
7
|
+
Call the [Azure DevOps REST API](https://learn.microsoft.com/en-us/rest/api/azure/devops/) from a deployed function using `AudienceType.ADO`.
|
|
8
|
+
|
|
9
|
+
Grant the [application identity](../index.md#application-authentication) access to your Azure DevOps organization and the permissions required by the project or resource you call.
|
|
8
10
|
|
|
9
11
|
Provide your Azure DevOps **organization** (and project, if the call needs one) — e.g. `https://dev.azure.com/<org>`. The token is a standard bearer token — send it with `fetch`:
|
|
10
12
|
|
|
13
|
+
`AppSchema` below is your app's data schema — the same type you pass to `RayfinClient<AppSchema>`. See [Writing functions](../writing-functions.md#accessing-data-and-request-context).
|
|
14
|
+
|
|
11
15
|
```ts
|
|
12
16
|
import {
|
|
13
17
|
UserDataFunctions,
|
|
@@ -22,8 +26,8 @@ const ORG = "https://dev.azure.com/<org>";
|
|
|
22
26
|
|
|
23
27
|
udf.func(
|
|
24
28
|
"listProjects",
|
|
25
|
-
async (ctx: RayfinContext): Promise<unknown> => {
|
|
26
|
-
const token = ctx.
|
|
29
|
+
async (ctx: RayfinContext<AppSchema, AudienceType.ADO>): Promise<unknown> => {
|
|
30
|
+
const token = ctx.Tokens.ADO;
|
|
27
31
|
const res = await fetch(`${ORG}/_apis/projects?api-version=7.1`, {
|
|
28
32
|
headers: { Authorization: `Bearer ${token}` },
|
|
29
33
|
});
|
|
@@ -32,7 +36,7 @@ udf.func(
|
|
|
32
36
|
}
|
|
33
37
|
return res.json();
|
|
34
38
|
},
|
|
35
|
-
[
|
|
39
|
+
[],
|
|
36
40
|
);
|
|
37
41
|
```
|
|
38
42
|
|
|
@@ -4,58 +4,24 @@ sidebar_position: 3
|
|
|
4
4
|
|
|
5
5
|
# Add an Azure resource
|
|
6
6
|
|
|
7
|
-
Connect a function to
|
|
7
|
+
Connect a deployed function to **Azure Blob Storage**.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Grant the [application identity](../index.md#application-authentication) the storage data permissions required by your operations.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The storage account is an Azure resource, not a Fabric item, so its endpoint comes from the **Azure portal** (there is no Fabric lookup).
|
|
12
|
+
The pattern declares the audience in the `RayfinContext` annotation, reads the token from `ctx.Tokens`, and wraps it with the [`ContextTokenCredential`](./index.md#wrapping-the-token-for-azure-sdk-clients) helper for the Azure SDK.
|
|
13
|
+
See [Connecting to external resources](./index.md) for the shared model.
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
`AppSchema` below is your app's data schema — the same type you pass to `RayfinClient<AppSchema>`.
|
|
16
|
+
See [Writing functions](../writing-functions.md#accessing-data-and-request-context).
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
cd rayfin/functions
|
|
17
|
-
npm install @azure/keyvault-secrets @azure/identity
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
```ts
|
|
21
|
-
import {
|
|
22
|
-
UserDataFunctions,
|
|
23
|
-
AudienceType,
|
|
24
|
-
type RayfinContext,
|
|
25
|
-
} from "@microsoft/fabric-user-data-functions";
|
|
26
|
-
import { SecretClient } from "@azure/keyvault-secrets";
|
|
27
|
-
|
|
28
|
-
const udf = new UserDataFunctions();
|
|
29
|
-
|
|
30
|
-
udf.func(
|
|
31
|
-
"getVaultSecret",
|
|
32
|
-
async (
|
|
33
|
-
ctx: RayfinContext,
|
|
34
|
-
kvUrl: string,
|
|
35
|
-
secretName: string,
|
|
36
|
-
): Promise<string> => {
|
|
37
|
-
const credential = new ContextTokenCredential(
|
|
38
|
-
ctx.getToken(AudienceType.KeyVault),
|
|
39
|
-
);
|
|
40
|
-
const client = new SecretClient(kvUrl, credential);
|
|
41
|
-
const secret = await client.getSecret(secretName);
|
|
42
|
-
return secret.value ?? "";
|
|
43
|
-
},
|
|
44
|
-
[udf.connection({ audienceType: AudienceType.KeyVault })],
|
|
45
|
-
);
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Provide the vault URL (e.g. `https://my-vault.vault.azure.net/`).
|
|
49
|
-
|
|
50
|
-
> To read secrets stored with Rayfin itself (rather than an external Key Vault), use [`ctx.getSecret()`](../secrets.md) instead — no connection required.
|
|
51
|
-
|
|
52
|
-
## Cosmos DB
|
|
18
|
+
## Blob Storage
|
|
53
19
|
|
|
54
|
-
Connect to Azure
|
|
20
|
+
Connect to Azure Blob / Table / Queue storage using `AudienceType.Storage`:
|
|
55
21
|
|
|
56
22
|
```bash
|
|
57
23
|
cd rayfin/functions
|
|
58
|
-
npm install @azure/
|
|
24
|
+
npm install @azure/storage-blob @azure/identity
|
|
59
25
|
```
|
|
60
26
|
|
|
61
27
|
```ts
|
|
@@ -64,53 +30,17 @@ import {
|
|
|
64
30
|
AudienceType,
|
|
65
31
|
type RayfinContext,
|
|
66
32
|
} from "@microsoft/fabric-user-data-functions";
|
|
67
|
-
import {
|
|
33
|
+
import { BlobServiceClient } from "@azure/storage-blob";
|
|
68
34
|
|
|
69
35
|
const udf = new UserDataFunctions();
|
|
70
36
|
|
|
71
|
-
udf.func(
|
|
72
|
-
"readItems",
|
|
73
|
-
async (
|
|
74
|
-
ctx: RayfinContext,
|
|
75
|
-
endpoint: string,
|
|
76
|
-
databaseId: string,
|
|
77
|
-
containerId: string,
|
|
78
|
-
): Promise<unknown[]> => {
|
|
79
|
-
const credential = new ContextTokenCredential(
|
|
80
|
-
ctx.getToken(AudienceType.CosmosDB),
|
|
81
|
-
);
|
|
82
|
-
const client = new CosmosClient({ endpoint, aadCredentials: credential });
|
|
83
|
-
const { resources } = await client
|
|
84
|
-
.database(databaseId)
|
|
85
|
-
.container(containerId)
|
|
86
|
-
.items.readAll()
|
|
87
|
-
.fetchAll();
|
|
88
|
-
return resources;
|
|
89
|
-
},
|
|
90
|
-
[udf.connection({ audienceType: AudienceType.CosmosDB })],
|
|
91
|
-
);
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Provide the account endpoint and the database / container names.
|
|
95
|
-
|
|
96
|
-
## Blob Storage
|
|
97
|
-
|
|
98
|
-
Connect to Azure Blob / Table / Queue storage using `AudienceType.Storage`:
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
cd rayfin/functions
|
|
102
|
-
npm install @azure/storage-blob
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
import { BlobServiceClient } from "@azure/storage-blob";
|
|
107
|
-
|
|
108
37
|
udf.func(
|
|
109
38
|
"listBlobs",
|
|
110
|
-
async (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
39
|
+
async (
|
|
40
|
+
ctx: RayfinContext<AppSchema, AudienceType.Storage>,
|
|
41
|
+
accountUrl: string,
|
|
42
|
+
): Promise<string[]> => {
|
|
43
|
+
const credential = new ContextTokenCredential(ctx.Tokens.Storage);
|
|
114
44
|
const service = new BlobServiceClient(accountUrl, credential);
|
|
115
45
|
const names: string[] = [];
|
|
116
46
|
for await (const container of service.listContainers()) {
|
|
@@ -118,54 +48,10 @@ udf.func(
|
|
|
118
48
|
}
|
|
119
49
|
return names;
|
|
120
50
|
},
|
|
121
|
-
[
|
|
51
|
+
[],
|
|
122
52
|
);
|
|
123
53
|
```
|
|
124
54
|
|
|
125
55
|
Provide the storage account URL (e.g. `https://<account>.blob.core.windows.net`).
|
|
126
56
|
|
|
127
57
|
> `AudienceType.Storage` also covers **OneLake** files — that Fabric case is documented in [Add a Fabric resource → OneLake files](./add-fabric-resource.md#onelake-files).
|
|
128
|
-
|
|
129
|
-
## Event Grid
|
|
130
|
-
|
|
131
|
-
Publish events to an Azure Event Grid topic using `AudienceType.EventGrid`. The topic endpoint is in the Azure portal → your topic → **Overview** → _Topic Endpoint_.
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
cd rayfin/functions
|
|
135
|
-
npm install @azure/eventgrid
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
```ts
|
|
139
|
-
import {
|
|
140
|
-
UserDataFunctions,
|
|
141
|
-
AudienceType,
|
|
142
|
-
type RayfinContext,
|
|
143
|
-
} from "@microsoft/fabric-user-data-functions";
|
|
144
|
-
import { EventGridPublisherClient } from "@azure/eventgrid";
|
|
145
|
-
|
|
146
|
-
const udf = new UserDataFunctions();
|
|
147
|
-
|
|
148
|
-
const TOPIC_ENDPOINT =
|
|
149
|
-
"https://<topic>.<region>.eventgrid.azure.net/api/events";
|
|
150
|
-
|
|
151
|
-
udf.func(
|
|
152
|
-
"publishEvent",
|
|
153
|
-
async (ctx: RayfinContext, subject: string): Promise<string> => {
|
|
154
|
-
const client = new EventGridPublisherClient(
|
|
155
|
-
TOPIC_ENDPOINT,
|
|
156
|
-
"EventGrid",
|
|
157
|
-
new ContextTokenCredential(ctx.getToken(AudienceType.EventGrid)),
|
|
158
|
-
);
|
|
159
|
-
await client.send([
|
|
160
|
-
{
|
|
161
|
-
eventType: "Rayfin.Function.Event",
|
|
162
|
-
subject,
|
|
163
|
-
dataVersion: "1.0",
|
|
164
|
-
data: { source: "user-data-function" },
|
|
165
|
-
},
|
|
166
|
-
]);
|
|
167
|
-
return "published";
|
|
168
|
-
},
|
|
169
|
-
[udf.connection({ audienceType: AudienceType.EventGrid })],
|
|
170
|
-
);
|
|
171
|
-
```
|