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 | */ |
| 10 | export 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 | |
| 23 | export interface AuthContext { |
| 24 | readonly userId: string; |
| 25 | readonly tokenType: 'session' | 'api_key'; |
| 26 | } |
| 27 | |
| 28 | export 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 | */ |
| 41 | export interface DbClient { |
| 42 | <TTable extends string>(table: TTable): TableQuery; |
| 43 | execute(sql: string, params?: readonly unknown[]): Promise<unknown[]>; |
| 44 | } |
| 45 | |
| 46 | export 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 | |
| 62 | export 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 | |
| 69 | export 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 | |
| 81 | export 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 | |
| 88 | export interface InsertQuery extends PromiseLike<unknown[]> { |
| 89 | returning(columns?: readonly string[]): PromiseLike<unknown[]>; |
| 90 | } |
| 91 | |
| 92 | export interface UpdateQuery extends PromiseLike<unknown[]> { |
| 93 | where(predicate: Record<string, unknown>): UpdateQuery; |
| 94 | returning(columns?: readonly string[]): PromiseLike<unknown[]>; |
| 95 | } |
| 96 | |
| 97 | export interface DeleteQuery extends PromiseLike<unknown[]> { |
| 98 | where(predicate: Record<string, unknown>): DeleteQuery; |
| 99 | returning(columns?: readonly string[]): PromiseLike<unknown[]>; |
| 100 | } |