Calling functions from your app
Invoke Rayfin functions from the frontend with RayfinClient, AppFunctionsSchema, per-call options, and local Vite routing.
Call functions from browser code through client.functions.<name>.invoke(...). The generated AppFunctionsSchema gives each function a typed input and output.
Note
Functions are generally available in Rayfin 1.36 and are not available in every Fabric region or tenant.
Pass the generated functions schema
Import AppFunctionsSchema from the generated functions package and pass it as the second type parameter to RayfinClient:
import { RayfinClient } from '@microsoft/rayfin-client';
import type { AppSchema } from '../../rayfin/data/schema';
import type { AppFunctionsSchema } from '../../rayfin/functions/src/types.js';
export const client = new RayfinClient<AppSchema, AppFunctionsSchema>({
baseUrl: import.meta.env.VITE_RAYFIN_API_URL,
publishableKey: import.meta.env.VITE_RAYFIN_PUBLISHABLE_KEY,
});Only names in AppFunctionsSchema are available on client.functions.
Invoke a function
import { client } from '../services/rayfinClient';
export async function greet(): Promise<string> {
return await client.functions.greet.invoke({
firstName: 'Ada',
lastName: 'Lovelace',
});
}For a no-input function, call invoke():
const entries = await client.functions.getEntries.invoke();invoke() resolves to the function output directly, not to a transport envelope.
Pass per-call options in the second argument
InvokeOptions supports headers and a per-call timeout. Options always occupy the second argument slot.
await client.functions.longRunning.invoke(
{ input: 'value' },
{ timeoutMs: 5_000, headers: { 'x-request-id': crypto.randomUUID() } },
);
await client.functions.ping.invoke(undefined, { timeoutMs: 5_000 });timeoutMs is capped at 250 seconds, the Fabric UDF host invocation ceiling.
Handle failures
import { FunctionsError } from '@microsoft/rayfin-functions';
import { NetworkError } from '@microsoft/rayfin-lib';
import { client } from '../services/rayfinClient';
export async function safeGreet(): Promise<string> {
try {
return await client.functions.greet.invoke({
firstName: 'Ada',
lastName: 'Lovelace',
});
} catch (error) {
if (error instanceof FunctionsError) {
return `Function failed: ${error.message}`;
}
if (error instanceof NetworkError) {
return 'Network error while calling the function.';
}
throw error;
}
}- A non-success status or non-empty
errorsarray throwsFunctionsErrorwith codeFUNCTION_EXECUTION_ERROR. - Unexpected invocation failures are wrapped with code
UNKNOWN_FUNCTION_ERROR. - The server-side
invocationIdis logged withconsole.debugfor correlation.
Route local Vite calls through the adapter
The package @microsoft/rayfin-local-dev is published at 1.36.2 and the bundled Vite templates use it for local Functions routing. During vite serve, the adapter proxies the SDK's same-origin /functions/<name>/invoke route to the Functions host selected by npx rayfin dev or npx rayfin dev functions apply. It also supports the legacy /.rayfin/api/<name> route when code passes an explicit functionsBaseUrl from resolveRayfinFunctionsBaseUrl().
For an older or custom Vite app, install and register the adapter:
npm install @microsoft/rayfin-local-devimport { rayfinLocalDev } from '@microsoft/rayfin-local-dev/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [rayfinLocalDev()],
});Most apps can leave functionsBaseUrl unset and let the adapter proxy the default /functions route. If existing code needs an explicit local Functions base URL, set functionsBaseUrl only during local development:
import { resolveRayfinFunctionsBaseUrl } from '@microsoft/rayfin-local-dev';
import { RayfinClient } from '@microsoft/rayfin-client';
import type { AppSchema } from '../../rayfin/data/schema';
import type { AppFunctionsSchema } from '../../rayfin/functions/src/types.js';
export const client = new RayfinClient<AppSchema, AppFunctionsSchema>({
baseUrl: import.meta.env.VITE_RAYFIN_API_URL,
publishableKey: import.meta.env.VITE_RAYFIN_PUBLISHABLE_KEY,
functionsBaseUrl: resolveRayfinFunctionsBaseUrl(),
});When functionsBaseUrl is set, the SDK calls ${functionsBaseUrl}/api/<name>; resolveRayfinFunctionsBaseUrl() resolves that to the adapter's same-origin /.rayfin base only while the Vite adapter is active. When functionsBaseUrl is unset, the SDK calls ${baseUrl}/functions/<name>/invoke; in Vite dev the adapter proxies that same-origin /functions route to the local host, and in production it reaches the deployed Fabric backend.
If the local Functions host is down while the Vite adapter is active, the /functions and /.rayfin/api proxies return HTTP 502 instead of falling back to deployed function code.
Do not call a function from the frontend until it is deployed or the local Functions host is running. A generated type proves the function was discovered at build time; it does not prove the deployed or local runtime currently has that handler loaded.
In my Rayfin app, wire the frontend to call an existing function.
Import `AppFunctionsSchema` from rayfin/functions/src/types.js and pass it as the second type parameter to `RayfinClient<AppSchema, AppFunctionsSchema>`. Call `client.functions.<name>.invoke(...)` with the generated input type. Put per-call headers or `timeoutMs` in the second argument; for a no-input function use `invoke(undefined, options)` when passing options. Catch `FunctionsError` from `@microsoft/rayfin-functions` before generic errors. If this is a Vite app that needs local function routing, add `@microsoft/rayfin-local-dev` and register `rayfinLocalDev()` in vite.config.ts. Leave `functionsBaseUrl` unset unless existing code explicitly needs the legacy `/.rayfin/api` route; in that case set it with `resolveRayfinFunctionsBaseUrl()`.