@microsoft/rayfin-guide 1.36.0-alpha.1593 → 1.36.0-alpha.1620
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/{experimental/cli → cli}/connectors/add.md +2 -0
- package/assets/docs/{experimental/cli → cli}/connectors/category-a-entities.md +1 -1
- package/assets/docs/{experimental/cli → cli}/connectors/category-b-function-bridge.md +38 -12
- package/assets/docs/cli/connectors/eventhouse.md +21 -0
- package/assets/docs/{experimental/cli → cli}/connectors/index.md +7 -22
- package/assets/docs/{experimental/cli → cli}/connectors/invoke.md +4 -0
- package/assets/docs/{experimental/cli → cli}/connectors/search.md +4 -2
- package/assets/docs/cli/environment-variables.md +2 -2
- package/assets/docs/cli/functions/deploy.md +38 -0
- package/assets/docs/cli/functions/dev-apply.md +62 -0
- package/assets/docs/cli/functions/index.md +41 -0
- package/assets/docs/cli/functions/init.md +62 -0
- package/assets/docs/cli/index.md +35 -1
- package/assets/docs/cli/secrets.md +97 -122
- package/assets/docs/cli/templates.md +7 -0
- package/assets/docs/functions/connections/add-ado.md +39 -0
- package/assets/docs/functions/connections/add-azure-resource.md +171 -0
- package/assets/docs/functions/connections/add-fabric-resource.md +186 -0
- package/assets/docs/functions/connections/add-foundry.md +46 -0
- package/assets/docs/functions/connections/add-work-iq.md +39 -0
- package/assets/docs/functions/connections/get-fabric-info.md +159 -0
- package/assets/docs/functions/connections/index.md +89 -0
- package/assets/docs/functions/index.md +91 -0
- package/assets/docs/functions/invoking-from-frontend.md +94 -0
- package/assets/docs/functions/secrets.md +70 -0
- package/assets/docs/functions/typegen.md +44 -0
- package/assets/docs/functions/writing-functions.md +140 -0
- package/assets/docs/getting-started/project-structure.md +91 -2
- package/package.json +1 -1
- /package/assets/docs/{experimental/cli → cli}/connectors/inspect.md +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Invoking functions from the frontend
|
|
6
|
+
|
|
7
|
+
Functions are called through `RayfinClient`. Pass your generated `AppFunctionsSchema` as the client's second type argument so every call is type-checked.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { RayfinClient } from "@microsoft/rayfin-client";
|
|
11
|
+
import type { AppSchema } from "../rayfin/data/schema";
|
|
12
|
+
import type { AppFunctionsSchema } from "../rayfin/functions/src/types.js";
|
|
13
|
+
|
|
14
|
+
const client = new RayfinClient<AppSchema, AppFunctionsSchema>({
|
|
15
|
+
publishableKey: import.meta.env.VITE_RAYFIN_PUBLISHABLE_KEY,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Type-safe: parameters and return type are checked against the schema.
|
|
19
|
+
const greeting = await client.functions.greet.invoke({
|
|
20
|
+
firstName: "Jane",
|
|
21
|
+
lastName: "Doe",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// For functions whose only parameter is RayfinContext, the input is `Record<string, never>`:
|
|
25
|
+
const entries = await client.functions.getEntries.invoke();
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The exact import path for `AppFunctionsSchema` depends on where your frontend lives relative to `rayfin/functions/src/types.ts`.
|
|
29
|
+
|
|
30
|
+
## Invocation behavior
|
|
31
|
+
|
|
32
|
+
- `invoke()` resolves to the function's output directly (typed as the schema's `output`) — not an envelope. By the time it resolves you can use the value without checking for `undefined`.
|
|
33
|
+
- On failure it **throws**: a non-empty `errors` array or a non-success status becomes a `FunctionsError`; network problems surface as a `NetworkError`.
|
|
34
|
+
- The server-side `invocationId` is emitted via `console.debug` for correlation with backend telemetry.
|
|
35
|
+
|
|
36
|
+
### Per-call options
|
|
37
|
+
|
|
38
|
+
Options always go in the **second** argument slot; the first argument is always the input:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// Input function with a per-call timeout:
|
|
42
|
+
await client.functions.longRunning.invoke(params, { timeoutMs: 5_000 });
|
|
43
|
+
|
|
44
|
+
// No-input function — pass `undefined` first, then options:
|
|
45
|
+
await client.functions.ping.invoke(undefined, { timeoutMs: 5_000 });
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`timeoutMs` is clamped to the Fabric UDF host ceiling of 250 seconds (`FUNCTIONS_INVOKE_TIMEOUT_MS`), since the host aborts any invocation at that limit regardless of the client value.
|
|
49
|
+
|
|
50
|
+
## Local development
|
|
51
|
+
|
|
52
|
+
By default, invocations route to your deployed backend.
|
|
53
|
+
Bundled Vite templates use `@microsoft/rayfin-local-dev` to keep local function calls on the frontend origin.
|
|
54
|
+
During `vite serve`, the client calls `/.rayfin/api/<name>` and the adapter forwards the request to the exact Functions host selected by `npx rayfin dev`.
|
|
55
|
+
|
|
56
|
+
For a custom or older Vite project, install the adapter:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install @microsoft/rayfin-local-dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Register it in `vite.config.ts`:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { rayfinLocalDev } from "@microsoft/rayfin-local-dev/vite";
|
|
66
|
+
import { defineConfig } from "vite";
|
|
67
|
+
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
plugins: [rayfinLocalDev()],
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then resolve the local base URL when you create the client:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { resolveRayfinFunctionsBaseUrl } from "@microsoft/rayfin-local-dev";
|
|
77
|
+
|
|
78
|
+
const client = new RayfinClient<AppSchema, AppFunctionsSchema>({
|
|
79
|
+
publishableKey: import.meta.env.VITE_RAYFIN_PUBLISHABLE_KEY,
|
|
80
|
+
functionsBaseUrl: resolveRayfinFunctionsBaseUrl(),
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The helper returns an absolute `/.rayfin` URL on the current browser origin only when the Vite adapter has registered local Functions routing.
|
|
85
|
+
In production it returns `undefined`, so calls use the deployed Fabric backend.
|
|
86
|
+
If the local Functions host becomes unavailable while the adapter is active, the proxy returns HTTP 502 instead of falling back to deployed function code.
|
|
87
|
+
The proxy is reachable wherever the Vite development server is reachable, so keep Vite bound to loopback or restrict its `host` and `allowedHosts` settings to a trusted development network.
|
|
88
|
+
|
|
89
|
+
`npx rayfin dev` starts the frontend and Functions host together and supplies the selected Functions URL to the adapter.
|
|
90
|
+
`npx rayfin dev functions apply` starts only the Functions host; start your Vite frontend separately to use the same-origin route.
|
|
91
|
+
See [`npx rayfin dev functions apply`](../cli/functions/dev-apply.md) for the local debugging workflow.
|
|
92
|
+
|
|
93
|
+
For frameworks other than Vite, pass the framework-mapped Functions URL directly during development and leave `functionsBaseUrl` undefined in production.
|
|
94
|
+
For example, use `NEXT_PUBLIC_RAYFIN_FUNCTIONS_URL` with an explicit development guard in Next.js.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 3
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Secrets
|
|
6
|
+
|
|
7
|
+
Functions read secret values through `ctx.getSecret(name)` on [`RayfinContext`](./writing-functions.md#rayfincontext-api).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
UserDataFunctions,
|
|
12
|
+
type RayfinContext,
|
|
13
|
+
} from "@microsoft/fabric-user-data-functions";
|
|
14
|
+
|
|
15
|
+
const udf = new UserDataFunctions();
|
|
16
|
+
|
|
17
|
+
udf.func(
|
|
18
|
+
"readApiKey",
|
|
19
|
+
async (ctx: RayfinContext): Promise<string> => {
|
|
20
|
+
const apiKey = ctx.getSecret("THIRD_PARTY_API_KEY");
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw new Error("Missing THIRD_PARTY_API_KEY secret.");
|
|
23
|
+
}
|
|
24
|
+
return apiKey;
|
|
25
|
+
},
|
|
26
|
+
[],
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## How resolution works
|
|
31
|
+
|
|
32
|
+
`ctx.getSecret(name)` returns `string | undefined`. It resolves in this order:
|
|
33
|
+
|
|
34
|
+
1. The host-provided secret bag delivered with the invocation.
|
|
35
|
+
2. `process.env[name]` as a fallback.
|
|
36
|
+
|
|
37
|
+
## Setting secrets
|
|
38
|
+
|
|
39
|
+
Manage project secrets with the CLI:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx rayfin secret set THIRD_PARTY_API_KEY
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
These are stored against your deployment and delivered to the function at invocation time.
|
|
46
|
+
See [Managing secrets](../cli/secrets.md) for the full `npx rayfin secret` command group.
|
|
47
|
+
|
|
48
|
+
## Secrets in local development
|
|
49
|
+
|
|
50
|
+
The host-provided secret bag is only present for deployed invocations.
|
|
51
|
+
When you debug locally with `npx rayfin dev functions apply`, add the same key under `Values` in `rayfin/functions/local.settings.json` so it flows into `process.env` and is picked up by the `getSecret` fallback:
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
{
|
|
55
|
+
"IsEncrypted": false,
|
|
56
|
+
"Values": {
|
|
57
|
+
"AzureWebJobsStorage": "",
|
|
58
|
+
"FUNCTIONS_WORKER_RUNTIME": "node",
|
|
59
|
+
"THIRD_PARTY_API_KEY": "local-development-value",
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`local.settings.json` is git-ignored, so these values stay on your machine.
|
|
65
|
+
See [Secrets in local development](../cli/secrets.md#using-secrets-in-local-development) for more.
|
|
66
|
+
|
|
67
|
+
## Best practices
|
|
68
|
+
|
|
69
|
+
- Prefer secrets set with `npx rayfin secret set <NAME>` as the source of truth for deployed functions.
|
|
70
|
+
- Use the `process.env` fallback only for local debugging — do not make it your primary production secret source.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 2
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Type generation
|
|
6
|
+
|
|
7
|
+
The Rayfin CLI parses every `udf.func()` call in `rayfin/functions/src/` and generates `rayfin/functions/src/types.ts`.
|
|
8
|
+
That file exports an `AppFunctionsSchema` type mapping each function name to its input and output types.
|
|
9
|
+
|
|
10
|
+
## The generated schema
|
|
11
|
+
|
|
12
|
+
For the two functions shown in [Writing functions](./writing-functions.md), typegen emits:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
export type AppFunctionsSchema = {
|
|
16
|
+
greet: {
|
|
17
|
+
input: { firstName: string; lastName: string };
|
|
18
|
+
output: string;
|
|
19
|
+
};
|
|
20
|
+
getEntries: {
|
|
21
|
+
input: Record<string, never>; // RayfinContext was stripped
|
|
22
|
+
output: { id: string; message: string }[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- Runtime-injected parameters such as `RayfinContext` are excluded from `input`.
|
|
28
|
+
- `Promise<T>` return types are unwrapped to `T` in `output`.
|
|
29
|
+
- The schema is a **closed** object type — only the listed function names are accepted by `client.functions.<name>.invoke(...)`.
|
|
30
|
+
|
|
31
|
+
## When typegen runs
|
|
32
|
+
|
|
33
|
+
| Command | Behavior |
|
|
34
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
35
|
+
| `npx rayfin functions init` | Runs typegen once after scaffolding to seed `types.ts`. |
|
|
36
|
+
| `npx rayfin dev functions apply` | Runs typegen once at startup, then keeps a watcher running (prefixed `[typegen]`) until you stop it. |
|
|
37
|
+
|
|
38
|
+
There is no standalone `typegen` command — it is driven by the commands above.
|
|
39
|
+
See [`npx rayfin dev functions apply`](../cli/functions/dev-apply.md).
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
- **Never hand-edit `types.ts`.** It is regenerated by `npx rayfin functions init` and by the watcher inside `npx rayfin dev functions apply`; your edits will be overwritten.
|
|
44
|
+
- **Never import Node.js packages into `types.ts`.** It is resolved by the frontend app's TypeScript compiler, which cannot resolve Node built-ins.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Writing functions
|
|
6
|
+
|
|
7
|
+
Functions are declared with the `UserDataFunctions` class from `@microsoft/fabric-user-data-functions` and registered with `udf.func()`.
|
|
8
|
+
|
|
9
|
+
## Registering a function
|
|
10
|
+
|
|
11
|
+
Create a single `UserDataFunctions` instance and register each function against it:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { UserDataFunctions } from "@microsoft/fabric-user-data-functions";
|
|
15
|
+
|
|
16
|
+
const udf = new UserDataFunctions();
|
|
17
|
+
|
|
18
|
+
udf.func(
|
|
19
|
+
"greet",
|
|
20
|
+
(firstName: string, lastName: string): string => {
|
|
21
|
+
return `Hello ${firstName} ${lastName}!`;
|
|
22
|
+
},
|
|
23
|
+
[],
|
|
24
|
+
);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`udf.func()` takes three arguments:
|
|
28
|
+
|
|
29
|
+
| Argument | Description |
|
|
30
|
+
| ------------- | --------------------------------------------------------------------------------------------- |
|
|
31
|
+
| `name` | The function name. Becomes the invocation route and the key in your generated schema. |
|
|
32
|
+
| `fn` | The handler. Its parameter and return types are read by [typegen](./typegen.md). |
|
|
33
|
+
| `connections` | Optional array of connection bindings. Pass `[]` when the function does not use a connection. |
|
|
34
|
+
|
|
35
|
+
The handler's typed parameters and return type are extracted into `types.ts` so the frontend can call the function type-safely.
|
|
36
|
+
`Promise<T>` return types are unwrapped to `T` in the generated schema.
|
|
37
|
+
|
|
38
|
+
## Accessing data and request context
|
|
39
|
+
|
|
40
|
+
To read your data, tokens, or logging from inside a function, declare a `RayfinContext` parameter.
|
|
41
|
+
Pass your app schema as a generic (`RayfinContext<AppSchema>`) — the same schema you use with `RayfinClient<AppSchema>` — for a fully typed data client:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import {
|
|
45
|
+
UserDataFunctions,
|
|
46
|
+
type RayfinContext,
|
|
47
|
+
} from "@microsoft/fabric-user-data-functions";
|
|
48
|
+
|
|
49
|
+
type AppSchema = {
|
|
50
|
+
Entry: { id: string; message: string; createdAt: string };
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const udf = new UserDataFunctions();
|
|
54
|
+
|
|
55
|
+
udf.func(
|
|
56
|
+
"getEntries",
|
|
57
|
+
async (
|
|
58
|
+
ctx: RayfinContext<AppSchema>,
|
|
59
|
+
): Promise<{ id: string; message: string }[]> => {
|
|
60
|
+
console.log("getEntries invoked");
|
|
61
|
+
const data = ctx.getDataClient();
|
|
62
|
+
return await data.Entry.select(["id", "message", "createdAt"]).execute();
|
|
63
|
+
},
|
|
64
|
+
[],
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `RayfinContext` API
|
|
69
|
+
|
|
70
|
+
| Member | Description |
|
|
71
|
+
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `ctx.getDataClient()` | Returns the typed entity data client. Query with `.select([...]).where(...).execute()`, the same chain as `client.data.<Entity>` on the frontend. Typed when a generic is supplied; untyped (`Record<string, any>`) otherwise. |
|
|
73
|
+
| `ctx.getSecret(name)` | Returns a secret value, or `undefined` when unset. See [Secrets](./secrets.md). |
|
|
74
|
+
| `ctx.getToken(audienceType)` | Returns the delegated OBO access token (a `string`) for an external resource. Only works for an audience you declared with `udf.connection({ audienceType })` in the third argument — throws otherwise. See [Connecting to external resources](./connections/index.md). |
|
|
75
|
+
| `ctx.baseUrl` | The Rayfin endpoint URL (readonly). |
|
|
76
|
+
| `ctx.accessToken` | The auth token for the current request (readonly). |
|
|
77
|
+
| `ctx.publishableKey` | The Rayfin publishable key (readonly). |
|
|
78
|
+
|
|
79
|
+
Use `console.log(...)` / `console.error(...)` for logging.
|
|
80
|
+
|
|
81
|
+
> **Import `RayfinContext` from `@microsoft/fabric-user-data-functions`** — not from `@microsoft/rayfin-functions`.
|
|
82
|
+
|
|
83
|
+
## Mixing parameters and context
|
|
84
|
+
|
|
85
|
+
A handler can take normal input parameters alongside a `RayfinContext`:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
udf.func(
|
|
89
|
+
"addEntry",
|
|
90
|
+
async (message: string, ctx: RayfinContext<AppSchema>): Promise<void> => {
|
|
91
|
+
console.log("addEntry invoked");
|
|
92
|
+
const data = ctx.getDataClient();
|
|
93
|
+
await data.Entry.create({ message });
|
|
94
|
+
},
|
|
95
|
+
[],
|
|
96
|
+
);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`RayfinContext` is injected by the runtime, so typegen strips it from the generated input type — only `message: string` appears in the schema for `addEntry`.
|
|
100
|
+
|
|
101
|
+
## Connecting to external resources
|
|
102
|
+
|
|
103
|
+
To call external Azure or Fabric resources (SQL, Storage, Key Vault, Cosmos DB, and more) from inside a function, declare a connection in the third argument of `udf.func()` and read a delegated token from the context:
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { AudienceType } from "@microsoft/fabric-user-data-functions";
|
|
107
|
+
|
|
108
|
+
udf.func(
|
|
109
|
+
"readSecret",
|
|
110
|
+
async (ctx: RayfinContext, secretName: string): Promise<string> => {
|
|
111
|
+
const token = ctx.getToken(AudienceType.KeyVault);
|
|
112
|
+
// Use `token` with the resource's SDK or REST API.
|
|
113
|
+
return secretName;
|
|
114
|
+
},
|
|
115
|
+
[udf.connection({ audienceType: AudienceType.KeyVault })],
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The runtime exchanges the caller's identity for a resource-scoped token, so the function acts **as the calling user**.
|
|
120
|
+
See [Connecting to external resources](./connections/index.md) for the full model, the list of supported audiences, and per-resource guides.
|
|
121
|
+
|
|
122
|
+
## Importing data entities
|
|
123
|
+
|
|
124
|
+
Share entity types between your data models and functions with TypeScript project references:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import type { Entry } from "../../data/Entry.js";
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- Use `import type` — entity classes are only needed for their type shape, not their runtime value. A non-type import would pull the decorator runtime into the functions bundle.
|
|
131
|
+
- The `../../data/` path resolves because `tsconfig.json` sets `"references": [{ "path": ".." }]`.
|
|
132
|
+
- Always use the `.js` extension on relative imports for correct ESM resolution.
|
|
133
|
+
|
|
134
|
+
## Rules
|
|
135
|
+
|
|
136
|
+
- Always register functions with `udf.func(name, handler, [])` — do not export bare functions.
|
|
137
|
+
- Use `RayfinContext<AppSchema>` for type-safe data access. Bare `RayfinContext` still works but gives no type safety on `getDataClient()`.
|
|
138
|
+
- Only call `ctx.getToken(audienceType)` for an audience you declared with `udf.connection({ audienceType })` in the third argument of `udf.func()` — calling it for an undeclared audience throws.
|
|
139
|
+
- A function must return a value or `void`. Throwing an error surfaces to the caller as an invocation failure carrying the error message.
|
|
140
|
+
- Use `import type` for data entity imports; never a runtime `import`.
|
|
@@ -24,6 +24,92 @@ your-project/
|
|
|
24
24
|
└── README.md
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
## Universal App workspace
|
|
28
|
+
|
|
29
|
+
Universal Apps generated by the Rayfin Copilot plugin use an npm workspace while preserving the same root workflow:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
your-universal-app/
|
|
33
|
+
├── package.json
|
|
34
|
+
├── tsconfig.base.json
|
|
35
|
+
├── tsconfig.json
|
|
36
|
+
├── rayfin/
|
|
37
|
+
│ └── rayfin.yml
|
|
38
|
+
└── packages/
|
|
39
|
+
├── frontend/
|
|
40
|
+
│ ├── src/
|
|
41
|
+
│ ├── package.json
|
|
42
|
+
│ └── vite.config.ts
|
|
43
|
+
├── data/
|
|
44
|
+
│ ├── src/index.ts
|
|
45
|
+
│ └── package.json
|
|
46
|
+
└── shared/
|
|
47
|
+
├── src/index.ts
|
|
48
|
+
└── package.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The workspace root owns the application identity, npm workspace declaration, orchestration scripts, applied capability-pack record, TypeScript project references, and `rayfin/rayfin.yml`.
|
|
52
|
+
It coordinates the packages but does not own application runtime code.
|
|
53
|
+
|
|
54
|
+
| Package | Stable name | Ownership |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `packages/frontend` | `@rayfin-app/frontend` | React, Vite, Fabric authentication, browser UI, and static output |
|
|
57
|
+
| `packages/data` | `@rayfin-app/data` | Rayfin entity registration and data schema exports |
|
|
58
|
+
| `packages/shared` | `@rayfin-app/shared` | Isomorphic contracts shared across runtime boundaries |
|
|
59
|
+
| `packages/functions` | `@rayfin-app/functions` | Opt-in trusted server workflows created by the functions capability pack |
|
|
60
|
+
|
|
61
|
+
Only the generated root package name is personalized.
|
|
62
|
+
The stable member names, cross-package dependency keys, and import specifiers are not renamed.
|
|
63
|
+
|
|
64
|
+
Use root commands for the complete app workflow:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm run build
|
|
68
|
+
npm run typecheck
|
|
69
|
+
npm run lint
|
|
70
|
+
npm test
|
|
71
|
+
npm run preview
|
|
72
|
+
npm run pack:add -- <pack>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The root build orders shared, data, and frontend work.
|
|
76
|
+
Focused package commands use npm's workspace selector, such as `npm run -w @rayfin-app/frontend test`.
|
|
77
|
+
|
|
78
|
+
The base workspace does not contain `packages/functions`, and `services.functions.enabled` is `false`.
|
|
79
|
+
Running `npm run pack:add -- functions` creates the stable functions package, enables its service, composes its build into root orchestration, and installs dependencies from the workspace root.
|
|
80
|
+
Capability packs do not use a nested functions lockfile or nested install.
|
|
81
|
+
|
|
82
|
+
### Universal App service paths
|
|
83
|
+
|
|
84
|
+
Universal App service paths point to the package that owns each deployable surface:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
services:
|
|
88
|
+
data:
|
|
89
|
+
enabled: false
|
|
90
|
+
path: packages/data
|
|
91
|
+
buildCommand: npm run build
|
|
92
|
+
staticHosting:
|
|
93
|
+
enabled: true
|
|
94
|
+
path: packages/frontend
|
|
95
|
+
folder: dist
|
|
96
|
+
buildCommand: npm run build:fabric
|
|
97
|
+
assetAccess: protected
|
|
98
|
+
functions:
|
|
99
|
+
enabled: false
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Rayfin resolves each `path` from the application root, then runs that service's `buildCommand` with the service directory as its working directory.
|
|
103
|
+
The static-hosting folder is therefore `packages/frontend/dist`, not a root `dist` directory.
|
|
104
|
+
After the functions pack is applied, functions uses `path: packages/functions` with its package-local `npm run build`.
|
|
105
|
+
|
|
106
|
+
The Project Rayfin repository keeps this Builder-facing workspace under `samples/universal-app/template`.
|
|
107
|
+
Its parent `samples/universal-app` is only a Rush validation harness that generates an ephemeral target and links that target to repository-local SDK packages.
|
|
108
|
+
The Copilot plugin bundles the inner template only; the harness and generated target are not distributed.
|
|
109
|
+
|
|
110
|
+
Existing flat Universal Apps remain supported by plugin validation and do not need to adopt this layout.
|
|
111
|
+
This workspace template does not add automatic workspace discovery, a migration command, support for package managers other than npm, or functions by default.
|
|
112
|
+
|
|
27
113
|
## Key files
|
|
28
114
|
|
|
29
115
|
### rayfin/rayfin.yml
|
|
@@ -103,6 +189,8 @@ services:
|
|
|
103
189
|
| --- | --- | --- | --- |
|
|
104
190
|
| `enabled` | `boolean` | `false` | Enable the data service. |
|
|
105
191
|
| `dialect` | `"mssql"` \| `"postgresql"` | `"mssql"` | Database dialect. Fabric deployments support MSSQL only. |
|
|
192
|
+
| `path` | `string` | Project root | Data project directory relative to the application root. |
|
|
193
|
+
| `buildCommand` | `string` | — | Command run from the resolved data service path before packaging. |
|
|
106
194
|
|
|
107
195
|
#### `services.auth`
|
|
108
196
|
|
|
@@ -171,9 +259,10 @@ Configure an email provider for magic links, password resets, and email verifica
|
|
|
171
259
|
| Field | Type | Default | Description |
|
|
172
260
|
| --- | --- | --- | --- |
|
|
173
261
|
| `enabled` | `boolean` | `false` | Enable static content hosting. |
|
|
262
|
+
| `path` | `string` | — | Frontend project directory relative to the application root. |
|
|
174
263
|
| `root` | `string` | — | Root directory of the frontend project (relative to the project root). |
|
|
175
|
-
| `folder` | `string` | `"dist"` | Directory containing built static assets
|
|
176
|
-
| `buildCommand` | `string` | — | Shell command
|
|
264
|
+
| `folder` | `string` | `"dist"` | Directory containing built static assets, relative to `path` or legacy `root`. |
|
|
265
|
+
| `buildCommand` | `string` | — | Shell command run from the resolved static-hosting path before packaging (for example, `npm run build`). |
|
|
177
266
|
| `indexDocument` | `string` | — | Default document served for the root path (e.g. `index.html`). |
|
|
178
267
|
|
|
179
268
|
> **Tip:** All string values support environment variable interpolation with `${VAR}` and `${VAR:-default}` syntax.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/rayfin-guide",
|
|
3
|
-
"version": "1.36.0-alpha.
|
|
3
|
+
"version": "1.36.0-alpha.1620",
|
|
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": [
|
|
File without changes
|