Functions

TypeScript functions run in response to collection and auth events. They are event-driven, non-blocking, and hot-reloadable during development.

Milestone: 5 — Functions Engine

Directory Layout

Place function files under functions/ next to bakend.json:

functions/
  posts/
    notify.ts
  users/
    welcome.ts

Bakend discovers all **/*.ts files recursively at startup.

Writing a Function

Import trigger helpers from bakend/functions:

import { onCreate } from "bakend/functions";

onCreate("posts", async ({ record, logger }) => {
  logger.info(`New post: ${record.title}`);
});

Triggers

HelperEventStatus
onCreate("posts", fn)posts.createdImplemented
onUpdate("posts", fn)posts.updatedImplemented
onDelete("posts", fn)posts.deletedImplemented
onLogin("users", fn)auth.loginImplemented
onRegister("users", fn)auth.registerImplemented

Function Context

Handlers receive:

interface FunctionContext {
  event: BakendEvent;
  record: Record<string, unknown>;
  db: Database;
  logger: Logger;
  auth: { user: AuthUser | null };
}

record is extracted from event.payload. auth.user is populated for auth.* events. storage provides get(id) and delete(id) — see Storage.

Lifecycle Events

The functions engine emits:

  • function.started
  • function.completed
  • function.failed

Error Handling

Handler failures are logged and isolated. A failing function does not crash Bakend or block API responses.

Hot Reload

During development, use:

bak dev

Or enable watching on start:

bak start --watch

When a file in functions/ changes, Bakend reloads all triggers automatically.

Example Workflow

  1. Define a posts collection in collections/posts.json
  2. Create functions/posts/notify.ts with an onCreate trigger
  3. Run bak dev
  4. POST /api/posts — the function runs after the record is saved

See events.md for the underlying event model.