Rayfin

Writing a function

Register Rayfin functions with udf.func, use RayfinContext for typed data access, and keep generated frontend types in sync.

Changed in 1.36

Write functions in the package configured by services.functions.path in rayfin/rayfin.yml. The default is rayfin/functions/.

Note

Functions are generally available in Rayfin 1.36 and are not available in every Fabric region or tenant.

Project layout

After npx rayfin functions init, the functions package lives at services.functions.path. The default path is rayfin/functions/:

rayfin/
  data/                 ← entity classes shared through TypeScript project references
  functions/
    src/
      function_app.ts   ← register functions here
      types.ts          ← generated AppFunctionsSchema; never hand-edit
      secrets.generated.ts ← generated secret registry; never hand-edit
    tsconfig.json        ← references: [{ "path": ".." }]
    package.json
    host.json
    local.settings.json  ← local-only settings and local secret values

The scaffolded tsconfig.json uses composite: true with a project reference to rayfin/, so functions can import entity types from rayfin/data/ without duplicating definitions. Install packages used only by functions in the functions package, not the app root.

Register handlers with udf.func

Create one UserDataFunctions instance and register every handler with udf.func(name, handler, []):

rayfin/functions/src/function_app.ts
import { UserDataFunctions } from '@microsoft/fabric-user-data-functions';

const udf = new UserDataFunctions();

udf.func(
  'greet',
  (firstName: string, lastName: string): string => {
    return `Hello ${firstName} ${lastName}!`;
  },
  [],
);
ArgumentDescription
nameFunction name. It becomes the generated schema key and the invocation route.
handlerTyped TypeScript function. Its parameters and return type are read by typegen.
connectionsPass []. Audience-scoped connections are declared in the RayfinContext type annotation in 1.36.

Do not export bare functions and expect Rayfin to discover them. Typegen and deployment metadata are based on udf.func(...) registrations.

Use RayfinContext for server context

Add a RayfinContext parameter when a handler needs Rayfin data, secrets, tokens, or runtime metadata. Pass the same app schema type you use with RayfinClient<AppSchema> so getDataClient() is typed.

rayfin/functions/src/function_app.ts
import {
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = {
  Entry: { id: string; message: string; createdAt: string };
};

const udf = new UserDataFunctions();

udf.func(
  'getEntries',
  async (
    ctx: RayfinContext<AppSchema>,
  ): Promise<{ id: string; message: string }[]> => {
    const data = ctx.getDataClient();
    return await data.Entry.select(['id', 'message']).execute();
  },
  [],
);

udf.func(
  'addEntry',
  async (message: string, ctx: RayfinContext<AppSchema>): Promise<void> => {
    const data = ctx.getDataClient();
    await data.Entry.create({ message });
  },
  [],
);

RayfinContext is injected by the runtime. Typegen strips it from the generated input type, so addEntry is invoked with { message }, not with a context value.

RayfinContext members

MemberDescription
ctx.getDataClient()Returns the typed Rayfin data client. It uses the invocation's Rayfin token, so Rayfin DB access stays caller-scoped.
ctx.SecretsTyped secret values declared in rayfin.yml. See Secrets in functions. New in 1.36
ctx.TokensTyped external-resource tokens for audiences declared on RayfinContext. Deployed functions use the app identity. See Connections. New in 1.36
ctx.baseUrlRayfin endpoint URL for the invocation.
ctx.accessTokenThe invocation's Rayfin token for caller-scoped Rayfin data access.
ctx.publishableKeyThe Rayfin publishable key.
ctx.getSecret(name)Deprecated untyped secret lookup. Use ctx.Secrets.<NAME>. Deprecated in 1.36
ctx.getToken(audienceType)Deprecated untyped token lookup. Use ctx.Tokens.<Audience>. Deprecated in 1.36

Import RayfinContext from @microsoft/fabric-user-data-functions, not from @microsoft/rayfin-functions.

Import entity types with import type

Functions can share entity types from rayfin/data/ through TypeScript project references. Use a type-only import with the .js extension:

rayfin/functions/src/function_app.ts
import type { Entry } from '../../data/Entry.js';

Do not use a runtime import for entity classes. A runtime import can pull the data decorator runtime into the functions bundle.

Use console.log(...) and console.error(...) for logging. There is no ctx.log API.

Generated types.ts

The CLI parses udf.func() registrations and writes rayfin/functions/src/types.ts:

rayfin/functions/src/types.ts
export type AppFunctionsSchema = {
  greet: {
    input: { firstName: string; lastName: string };
    output: string;
  };
  getEntries: {
    input: Record<string, never>;
    output: { id: string; message: string }[];
  };
};
  • Promise<T> return types are unwrapped to T.
  • Runtime-injected RayfinContext parameters are omitted from input.
  • The schema is closed: only listed function names are accepted by client.functions.<name>.invoke(...).
  • Never hand-edit types.ts; rayfin functions init and rayfin dev functions apply regenerate it.
  • Do not import Node.js packages into types.ts; the frontend TypeScript compiler reads it.

Keep types current while editing

CommandTypegen behavior
npx rayfin functions initRuns typegen once after scaffolding or refresh.
npx rayfin dev functions applyRuns typegen once at startup and keeps a watcher running with a [typegen] prefix. Changed in 1.36
npx rayfin devStarts the same local functions flow when Functions are enabled. Changed in 1.36
PromptWrite a typed Rayfin function
In my Rayfin project, add a function to rayfin/functions/src/function_app.ts. Register it with `udf.func('<name>', handler, [])`. Import `RayfinContext` from `@microsoft/fabric-user-data-functions` and use `RayfinContext<AppSchema>` when the handler reads or writes Rayfin entities. If you import entity types from rayfin/data/, use `import type` and include the `.js` extension. Never edit rayfin/functions/src/types.ts manually; regenerate or run `npx rayfin dev functions apply` so typegen updates it. Show the final handler and the generated `AppFunctionsSchema` entry.
Something wrong on this page?Report an issueEdit this page

On this page