Skip to content

Personal Backend Function

Minimum supported version:

@lovrabet/sdk >= 1.5.3.

About client in this page: it refers to the LovrabetClient instance returned by createClient(...). It carries the current app's appCode and authentication settings, and exposes the personal function client through client.personal.bff.

typescript
import { createClient, type LovrabetClient } from "@lovrabet/sdk";

const client: LovrabetClient = createClient({
  appCode: "your-app-code",
});

The SDK entry point is client.personal.bff.execute. It executes a personal function of the current user in the current app by scriptId and returns the function's business result directly.

typescript
const result = await client.personal.bff.execute<ResultType>({
  scriptId: 123,
  params: { status: "active" },
});

Namespace and functions

MemberMeaning
client.personalNamespace for the current user's personal resources.
client.personal.bffThe Personal Backend Function client.
client.personal.bff.executeExecutes a function by its personal function ID.

TypeScript signature:

typescript
interface PersonalBffExecuteRequest {
  scriptId: number;
  params?: Record<string, unknown>;
  options?: Omit<RequestInit, "method" | "body">;
}

execute<T = unknown>(
  request: PersonalBffExecuteRequest
): Promise<T>;

Parameters

FieldTypeRequiredDescription
scriptIdnumberYesThe personal function ID. Must be a safe integer greater than 0 and belong to the current user and app.
paramsRecord<string, unknown>NoBusiness parameters passed to the function. When omitted, the request sends no body.
optionsPersonalRequestOptionsNofetch settings for this request, such as signal and extra headers. The HTTP method and body are controlled by the SDK and cannot be overridden.

Take scriptId from lovrabet personal-bff list, detail, or the creation result. A function name cannot substitute for the scriptId.

Return value

execute<T>() returns a Promise<T>. The resolved value is exactly the business result of the personal function — no execSuccess, execResult, or any other SDK wrapper.

typescript
interface OrderSummary {
  total: number;
  rows: Array<{ id: number; amount: number }>;
}

const summary = await client.personal.bff.execute<OrderSummary>({
  scriptId: 123,
  params: { status: "active" },
});

console.log(summary.total);
console.log(summary.rows);

The generic T is a compile-time hint only; nothing is validated at runtime. Pages should still check required fields, nulls, and enum values themselves.

Error handling

When parameters, authentication, or the network request fail, the SDK throws a LovrabetError. HTTP errors returned by the server are preserved as-is — they are never turned into success results.

ErrorTriggerWhat to do
PERSONAL_BFF_SCRIPT_ID_INVALIDscriptId is not a safe integer greater than 0.Re-obtain the ID from list, detail, or the creation result.
PERSONAL_BFF_AUTH_MODE_UNSUPPORTEDCalling a personal function via OpenAPI.Use Cookie in the browser; use a Client AK in a Node service.
HTTP 400 / 401 / 403 / 500Parameters, login state, permissions, or function execution failed.Read status, code, message, and description, and handle the original error.
TIMEOUTThe request exceeded the client's timeout.Check the function's runtime and the request chain before adjusting the timeout.
typescript
import { LovrabetError } from "@lovrabet/sdk";

try {
  const result = await client.personal.bff.execute<OrderSummary>({
    scriptId: 123,
    params: { status: "active" },
  });
} catch (error) {
  if (error instanceof LovrabetError) {
    console.error(error.status, error.code, error.message, error.description);
  } else {
    throw error;
  }
}

Safe calls and undefined

When accommodating an older SDK or a client injected from outside, check the namespace and the method first. Use optional chaining only to read the capability — never to invoke the function.

typescript
const personalBff = lovrabetClient?.personal?.bff;
if (typeof personalBff?.execute !== "function") {
  throw new Error("client.personal.bff.execute is not available");
}

const result = await personalBff.execute<OrderSummary>({
  scriptId: 123,
  params: { status: "active" },
});

Never write lovrabetClient?.personal?.bff?.execute?.(...). When the method does not exist, that expression silently evaluates to undefined — the request was never sent. Also avoid extracting execute and calling it bare, which loses the method's context.

In the browser, use the current login Cookie and omit authMode when creating the client. The SDK sends the browser credentials automatically. Never bake Cookies, AccessKeys, SecretKeys, or tokens into frontend code, build variables, or page configuration.

typescript
import { createClient } from "@lovrabet/sdk";

const client = createClient({
  appCode: "your-app-code",
});

const personalBff = client.personal?.bff;
if (typeof personalBff?.execute !== "function") {
  throw new Error("client.personal.bff.execute is not available");
}

const summary = await personalBff.execute<OrderSummary>({
  scriptId: 123,
  params: { status: "active" },
});

Node example: Client AK

In a Node service using a Client AK, set authMode: "client-ak" explicitly. Read the AccessKey only from the server-side secret store. Personal functions do not support OpenAPI.

typescript
import { createClient } from "@lovrabet/sdk";

const client = createClient({
  appCode: "your-app-code",
  authMode: "client-ak",
  accessKey: serverSecrets.lovrabetAccessKey,
});

const summary = await client.personal.bff.execute<OrderSummary>({
  scriptId: 123,
  params: { status: "active" },
});

What a Personal Backend Function is

A Personal Backend Function is a lightweight function maintained by the current user within the current app. It fits when a page's multi-step queries, result shaping, or personal workflows belong on the server side — the page just passes parameters and consumes the result.

Personal functions suit personal workflows, feature validation, and light orchestration. Interfaces meant for long-term reuse by many people and maintained centrally should be regular Backend Functions.

Verify before integrating

The SDK only calls personal functions that already exist. Before wiring a page in, verify the same scriptId with the CLI:

bash
lovrabet personal-bff exec \
  --id 123 \
  --params '{"status":"active"}' \
  --format compress

Only after confirming the parameters, returned fields, null cases, and error shapes should you define the TypeScript return type and integrate the page.

基于飞书知识库同步生成,内容以飞书源文档为准