Skip to content

composeSequentialCallback

composeSequentialCallback<TResult>(db, callback): Operation<TResult> & object

Defined in: packages/db/src/compose.ts:333

Sequential compose variant that accepts a callback for ad-hoc workflows where later operations depend on the results of earlier ones (e.g. inserting a child row that references the inserted parent’s id).

Permissions are still collected ahead-of-time: the callback is run twice. The first pass uses a tracking proxy that records every operation’s permission descriptors and returns sentinel values from .run() (so card.id and similar accesses don’t crash). The second pass runs the callback against the real Db to actually execute the queries.

Because the callback runs twice, it must be free of side effects outside of db.* calls (no fetch, no console.log you care about, no global state mutation). All control flow that depends on db results should use the sentinel- tolerant property accesses.

The dry-run pass is asynchronous, so op.permissions is empty until the dry-run resolves. Consumers that need to inspect permissions before calling .run() (e.g. the @cfast/actions permission UI) should await op.permissionsAsync() instead. Calling op.run() always awaits the dry-run internally, so permissions are guaranteed to be populated by the time the real callback runs.

TResult

The return type of the callback.

Db

The real Db that will execute the operations on the second pass.

(db) => Promise<TResult>

A function that receives a Db and returns a value.

Operation<TResult> & object

A single Operation whose .permissions is the union of every operation discovered during the dry-run pass and whose .run() re-executes the callback against the real Db. The returned object also exposes permissionsAsync() for guaranteed permission retrieval.

import { composeSequentialCallback } from "@cfast/db";
const op = composeSequentialCallback(db, async (tx) => {
const card = await tx.insert(cards).values({ title: "New" }).returning().run();
await tx.insert(activityLog).values({
cardId: (card as { id: string }).id,
action: "card_created",
}).run();
return card;
});
await op.permissionsAsync(); // [{ create, cards }, { create, activityLog }]
await op.run();