ctx.ts100 lines · main
1/**
2 * `Ctx` is the object injected into every query / mutation / action
3 * function at invocation time by the briven runtime. It is declared in
4 * `@briven/schema` so authors can type their functions without importing
5 * anything from the runtime itself.
6 *
7 * The runtime provides the concrete implementation; this file is the
8 * compile-time surface.
9 */
10export interface Ctx {
11 /** Typed query builder against the project's postgres schema. */
12 readonly db: DbClient;
13 /** Invocation identifier — stable per request, correlated in logs. */
14 readonly requestId: string;
15 /** Structured logger — never log customer data (CLAUDE.md §5.1). */
16 readonly log: Logger;
17 /** Secrets / env vars injected by the control plane. */
18 readonly env: Readonly<Record<string, string | undefined>>;
19 /** If the call was authenticated, the resolved user. */
20 readonly auth: AuthContext | null;
21}
22
23export interface AuthContext {
24 readonly userId: string;
25 readonly tokenType: 'session' | 'api_key';
26}
27
28export interface Logger {
29 debug(event: string, fields?: Record<string, unknown>): void;
30 info(event: string, fields?: Record<string, unknown>): void;
31 warn(event: string, fields?: Record<string, unknown>): void;
32 error(event: string, fields?: Record<string, unknown>): void;
33}
34
35/**
36 * Minimal query surface. Phase 1 covers the 90% path: select, insert,
37 * update, delete. The returned builders are async-iterable for streaming
38 * results; the runtime maps each call into a parameterised SQL statement
39 * against the project's schema.
40 */
41export interface DbClient {
42 <TTable extends string>(table: TTable): TableQuery;
43 execute(sql: string, params?: readonly unknown[]): Promise<unknown[]>;
44}
45
46export interface TableQuery {
47 select(columns?: readonly string[]): SelectQuery;
48 insert(values: Record<string, unknown> | readonly Record<string, unknown>[]): InsertQuery;
49 update(patch: Record<string, unknown>): UpdateQuery;
50 delete(): DeleteQuery;
51 /**
52 * Nearest-neighbour search against a pgvector column. Compiles to
53 * SELECT … FROM <table> WHERE … ORDER BY <column> <distance-op> $1 LIMIT $2
54 * where `distance-op` is `<->` (L2, default), `<#>` (negative inner
55 * product), or `<=>` (cosine). The vector column must be declared via
56 * `vector(N)` in the project schema; ordering by a non-vector column
57 * is a runtime error.
58 */
59 vectorSearch(input: VectorSearchInput): VectorSearchQuery;
60}
61
62export interface SelectQuery extends PromiseLike<unknown[]> {
63 where(predicate: Record<string, unknown>): SelectQuery;
64 orderBy(column: string, direction?: 'asc' | 'desc'): SelectQuery;
65 limit(n: number): SelectQuery;
66 offset(n: number): SelectQuery;
67}
68
69export interface VectorSearchInput {
70 /** Column name on the table — must be a `vector(N)` column. */
71 readonly column: string;
72 /** Query embedding. Length must match the column's declared dimensions
73 * or the runtime throws. */
74 readonly vector: readonly number[];
75 /** Distance operator. Default 'l2'. */
76 readonly distance?: 'l2' | 'inner_product' | 'cosine';
77 /** Top-K. Default 10, hard cap 1000. */
78 readonly limit?: number;
79}
80
81export interface VectorSearchQuery extends PromiseLike<unknown[]> {
82 /** Restrict the candidate set before ranking. Same shape as SelectQuery.where. */
83 where(predicate: Record<string, unknown>): VectorSearchQuery;
84 /** Choose the columns the query returns. Default is all columns. */
85 select(columns: readonly string[]): VectorSearchQuery;
86}
87
88export interface InsertQuery extends PromiseLike<unknown[]> {
89 returning(columns?: readonly string[]): PromiseLike<unknown[]>;
90}
91
92export interface UpdateQuery extends PromiseLike<unknown[]> {
93 where(predicate: Record<string, unknown>): UpdateQuery;
94 returning(columns?: readonly string[]): PromiseLike<unknown[]>;
95}
96
97export interface DeleteQuery extends PromiseLike<unknown[]> {
98 where(predicate: Record<string, unknown>): DeleteQuery;
99 returning(columns?: readonly string[]): PromiseLike<unknown[]>;
100}