@palbase/backend 0.10.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ // src/db/typed-db.ts
2
+ function makeTypedTable(name, raw) {
3
+ return {
4
+ insert: (data) => raw.insert(name, data),
5
+ update: (id, data) => raw.update(name, id, data),
6
+ delete: (id) => raw.delete(name, id),
7
+ findById: (id) => raw.findById(name, id),
8
+ findMany: (query) => raw.findMany(name, query)
9
+ };
10
+ }
11
+ function makeTypedDB(schema, raw) {
12
+ function buildTables(client) {
13
+ const tables = {};
14
+ for (const key of Object.keys(schema.tables)) {
15
+ const tableDef = schema.tables[key];
16
+ if (tableDef !== void 0) {
17
+ tables[key] = makeTypedTable(tableDef.name, client);
18
+ }
19
+ }
20
+ return tables;
21
+ }
22
+ const result = {
23
+ tables: buildTables(raw),
24
+ transaction: (fn) => raw.transaction((rawTx) => fn({ tables: buildTables(rawTx) }))
25
+ };
26
+ return result;
27
+ }
28
+
29
+ // src/runtime.ts
30
+ var runtime = null;
31
+ function __setRuntime(services) {
32
+ runtime = services;
33
+ }
34
+ function __getRuntime() {
35
+ if (runtime === null) {
36
+ throw new Error(
37
+ "Palbase services accessed outside a request scope. The Database/Documents/\u2026 singletons are only available inside an endpoint handler (or after the runtime has called __setRuntime)."
38
+ );
39
+ }
40
+ return runtime;
41
+ }
42
+ function makeServiceProxy(key) {
43
+ const handler = {
44
+ get(_target, prop, receiver) {
45
+ const client = __getRuntime()[key];
46
+ const value = Reflect.get(client, prop, receiver);
47
+ return typeof value === "function" ? value.bind(client) : value;
48
+ }
49
+ };
50
+ return new Proxy({}, handler);
51
+ }
52
+ var Database = makeServiceProxy("Database");
53
+ var Documents = makeServiceProxy("Documents");
54
+ var Storage = makeServiceProxy("Storage");
55
+ var Cache = makeServiceProxy("Cache");
56
+ var Queue = makeServiceProxy("Queue");
57
+ var Log = makeServiceProxy("Log");
58
+ var Notifications = makeServiceProxy("Notifications");
59
+ var Flags = makeServiceProxy("Flags");
60
+ function typedDatabase(schema) {
61
+ const typed = makeTypedDB(schema, Database);
62
+ const rawOps = {
63
+ query: (sql, params) => Database.query(sql, params),
64
+ insert: (table, data) => Database.insert(table, data),
65
+ update: (table, id, data) => Database.update(table, id, data),
66
+ delete: (table, id) => Database.delete(table, id),
67
+ findById: (table, id) => Database.findById(table, id),
68
+ findMany: (table, q) => Database.findMany(table, q),
69
+ transaction: (fn) => Database.transaction(fn)
70
+ };
71
+ return Object.assign(rawOps, typed);
72
+ }
73
+
74
+ export {
75
+ makeTypedDB,
76
+ __setRuntime,
77
+ __getRuntime,
78
+ Database,
79
+ Documents,
80
+ Storage,
81
+ Cache,
82
+ Queue,
83
+ Log,
84
+ Notifications,
85
+ Flags,
86
+ typedDatabase
87
+ };
88
+ //# sourceMappingURL=chunk-7N5ICXCB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db/typed-db.ts","../src/runtime.ts"],"sourcesContent":["/**\n * typed-db.ts — Task 2: TypedDB schema-derived insert/row shapes.\n *\n * Derives INSERT and full-row TypeScript types from a `defineSchema()` result\n * and wraps the untyped runtime `DBClient` with a typed facade.\n *\n * No value-any. No `as unknown as X`. The two narrow `as` casts in\n * `makeTypedTable` are safe because:\n * - `data as Record<string, unknown>`: InsertShape<T> maps string keys to\n * typed values; all value types are subsets of `unknown`, so the cast is\n * structurally sound.\n * - `result as RowShape<T>`: The runtime DBClient returns `Record<string,\n * unknown>` which is the erased form of the typed row; we're narrowing back\n * to the precise shape that the schema declared.\n * Both casts are narrowing only (not widening) and correctness is guaranteed\n * by the schema the caller provides.\n */\n\nimport type { ColValue, ColIsOptionalOnInsert, ColumnBuilder } from \"./columns.js\";\nimport type { TableDef, SchemaDef } from \"./schema.js\";\nimport type { DBClient, TxClient } from \"../endpoint.js\";\n\n// ---------------------------------------------------------------------------\n// Key discriminators — split a column map into required vs optional keys.\n// ---------------------------------------------------------------------------\n\n/** Keys of C whose columns are required on INSERT (not nullable, no default). */\ntype RequiredKeys<C> = {\n [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? never : K;\n}[keyof C];\n\n/** Keys of C whose columns are optional on INSERT (nullable or has a default). */\ntype OptionalKeys<C> = {\n [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? K : never;\n}[keyof C];\n\n// ---------------------------------------------------------------------------\n// Public shape types — exported so callers can reference them directly.\n// ---------------------------------------------------------------------------\n\n/**\n * The TypeScript type for an INSERT payload for table `T`.\n * - Required: columns that are NOT NULL and have no DB-level default.\n * - Optional: columns that are nullable or carry a default.\n *\n * When all columns are optional, `RequiredKeys<C>` resolves to `never` and\n * the first part becomes `{}`, which is a neutral element for `&`.\n */\nexport type InsertShape<T extends TableDef> = {\n [K in RequiredKeys<T[\"columns\"]>]: ColValue<T[\"columns\"][K]>;\n} & {\n [K in OptionalKeys<T[\"columns\"]>]?: ColValue<T[\"columns\"][K]>;\n};\n\n/**\n * The TypeScript type for a full row returned by the DB for table `T`.\n * Every column is present; nullable columns resolve to `T | null`.\n */\nexport type RowShape<T extends TableDef> = {\n [K in keyof T[\"columns\"]]: ColValue<T[\"columns\"][K]>;\n};\n\n// ---------------------------------------------------------------------------\n// TypedTable + TypedDB interfaces.\n// ---------------------------------------------------------------------------\n\n/** A typed table accessor that mirrors the runtime DBClient surface. */\nexport interface TypedTable<T extends TableDef> {\n insert(data: InsertShape<T>): Promise<RowShape<T>>;\n update(id: string, data: Partial<InsertShape<T>>): Promise<RowShape<T>>;\n delete(id: string): Promise<void>;\n findById(id: string): Promise<RowShape<T> | null>;\n findMany(query?: Partial<RowShape<T>>): Promise<RowShape<T>[]>;\n}\n\n/** A typed DB facade covering all tables declared in schema `S`. */\nexport interface TypedDB<S extends SchemaDef> {\n tables: {\n [K in keyof S[\"tables\"]]: TypedTable<S[\"tables\"][K]>;\n };\n transaction<T>(fn: (tx: TypedTx<S>) => Promise<T>): Promise<T>;\n}\n\n/** Transaction-scoped typed facade: same typed tables, no nested transaction. */\nexport interface TypedTx<S extends SchemaDef> {\n tables: {\n [K in keyof S[\"tables\"]]: TypedTable<S[\"tables\"][K]>;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Runtime factory.\n// ---------------------------------------------------------------------------\n\n/**\n * Builds a typed table accessor that delegates every call to `raw` using the\n * runtime table name string. Two narrow `as` casts bridge the mapped-type\n * shapes to/from `Record<string, unknown>` — see module-level doc comment.\n *\n * The `raw` param is typed `TxClient` (the op surface shared by `DBClient` and\n * the transaction-scoped client) because this only ever calls the five\n * insert/update/delete/findById/findMany ops — never `transaction`. This lets\n * the same factory wrap both the top-level db and a tx without any cast.\n */\nfunction makeTypedTable<T extends TableDef<Record<string, ColumnBuilder>>>(\n name: string,\n raw: TxClient,\n): TypedTable<T> {\n return {\n insert: (data: InsertShape<T>) =>\n raw.insert(name, data as Record<string, unknown>) as Promise<RowShape<T>>,\n\n update: (id: string, data: Partial<InsertShape<T>>) =>\n raw.update(name, id, data as Record<string, unknown>) as Promise<RowShape<T>>,\n\n delete: (id: string) => raw.delete(name, id),\n\n findById: (id: string) =>\n raw.findById(name, id) as Promise<RowShape<T> | null>,\n\n findMany: (query?: Partial<RowShape<T>>) =>\n raw.findMany(name, query as Record<string, unknown> | undefined) as Promise<RowShape<T>[]>,\n };\n}\n\n/**\n * Wraps a raw `DBClient` with the type-safe `TypedDB<S>` facade derived from\n * the provided schema. No behavior change — all calls delegate to `raw` with\n * the table name as a plain string.\n *\n * `buildTables` is the reusable factory that wraps any op-bearing client\n * (`TxClient` — the surface shared by `DBClient` and the transaction-scoped\n * client) into the typed tables map. It is used both for the top-level db\n * (wrapping `raw`) and inside `transaction`, where it wraps the raw `TxClient`\n * the runtime yields so the callback sees the same typed `.tables` API.\n *\n * `transaction` delegates straight to `raw.transaction`; the two narrow\n * `as TypedTx<S>` / `as TypedDB<S>` casts are single structural narrowings\n * from the dynamically-built tables object to the precise mapped type (TS\n * cannot infer through `Object.keys` iteration) — see module-level doc comment.\n */\nexport function makeTypedDB<S extends SchemaDef>(\n schema: S,\n raw: DBClient,\n): TypedDB<S> {\n function buildTables(client: TxClient): Record<string, TypedTable<TableDef>> {\n const tables = {} as Record<string, TypedTable<TableDef>>;\n for (const key of Object.keys(schema.tables)) {\n const tableDef = schema.tables[key];\n if (tableDef !== undefined) {\n tables[key] = makeTypedTable(tableDef.name, client);\n }\n }\n return tables;\n }\n\n const result = {\n tables: buildTables(raw),\n transaction: <T>(fn: (tx: TypedTx<S>) => Promise<T>): Promise<T> =>\n raw.transaction((rawTx) => fn({ tables: buildTables(rawTx) } as TypedTx<S>)),\n };\n\n // Narrow cast: `result.tables` is structurally identical to\n // TypedDB<S>[\"tables\"] — each key maps to a TypedTable for the matching\n // TableDef. TS cannot infer the mapped-type result through Object.keys\n // iteration, so a single `as` bridges the gap.\n return result as TypedDB<S>;\n}\n","/**\n * runtime.ts — request-scoped service singletons.\n *\n * The backend SDK no longer threads a `ctx` god-object through every handler.\n * Instead, endpoint authors import PascalCase service singletons directly:\n *\n * import { Database, Documents, Cache } from \"@palbase/backend\";\n *\n * export default defineEndpoint({\n * method: \"POST\",\n * handler: async (req) => {\n * const row = await Database.insert(\"todos\", { title: req.input.title });\n * return row;\n * },\n * });\n *\n * The singletons are thin Proxies. Every property access forwards to the live\n * client held in a per-process mutable slot, which the runtime sets with\n * {@link __setRuntime} BEFORE invoking the handler and (today) leaves in place\n * for the lifetime of that fresh Node subprocess. Because each `br-<ref>` pod\n * is single-tenant and every request runs in a fresh Node subprocess\n * (node_executor.go), there is no cross-tenant leakage risk.\n *\n * The seam that makes `import { Database } from \"@palbase/backend\"` resolve to\n * the runtime-injected client: `@palbase/backend` is marked esbuild-EXTERNAL\n * when the tenant bundle is built, and the package is installed globally in the\n * pod (NODE_PATH=/usr/local/lib/node_modules). So worker.js's\n * `require('@palbase/backend')` and the bundle's `import` resolve to ONE shared\n * module instance — calling `__setRuntime` on that instance is visible to the\n * singletons the bundle imported.\n */\n\nimport type {\n DBClient,\n CacheClient,\n QueueClient,\n Logger,\n PalbaseDocsClient,\n} from \"./endpoint.js\";\nimport type {\n PalbaseStorageClient,\n PalbaseNotificationsClient,\n PalbaseFlagsClient,\n} from \"./clients.js\";\nimport type { SchemaDef } from \"./db/schema.js\";\nimport type { TypedDB } from \"./db/typed-db.js\";\nimport { makeTypedDB } from \"./db/typed-db.js\";\n\n/** The set of live clients the runtime injects per request scope.\n *\n * EXCLUDED on purpose: Realtime, Functions, CMS, Links, Analytics, Auth. They\n * are not exposed as backend handler singletons (auth lives on the client SDK;\n * the rest are out of scope for backend endpoints). */\nexport interface RuntimeServices {\n Database: DBClient;\n Documents: PalbaseDocsClient;\n Storage: PalbaseStorageClient;\n Cache: CacheClient;\n Queue: QueueClient;\n Log: Logger;\n Notifications: PalbaseNotificationsClient;\n Flags: PalbaseFlagsClient;\n}\n\n/** Per-process slot holding the live clients for the current request scope. */\nlet runtime: RuntimeServices | null = null;\n\n/** Install the live clients for the current request scope.\n *\n * Called by the Palbase runtime (worker.js / dev-server.js) immediately before\n * invoking a handler. NOT part of the public author-facing API — exported with\n * a `__` prefix so the runtime can reach it across the shared module instance.\n */\nexport function __setRuntime(services: RuntimeServices): void {\n runtime = services;\n}\n\n/** Read the live clients, throwing if accessed outside a request scope.\n *\n * NOT part of the public author-facing API — exported with a `__` prefix for\n * the runtime and the singleton Proxies. */\nexport function __getRuntime(): RuntimeServices {\n if (runtime === null) {\n throw new Error(\n \"Palbase services accessed outside a request scope. The Database/Documents/… \" +\n \"singletons are only available inside an endpoint handler (or after the \" +\n \"runtime has called __setRuntime).\",\n );\n }\n return runtime;\n}\n\n/**\n * Build a Proxy singleton that forwards every property access to the live\n * client named `key` on the current runtime.\n *\n * The single `as RuntimeServices[K]` is the only contained cast in the surface:\n * `Reflect.get` on a typed object returns `unknown` for a `string | symbol`\n * key, but `prop` is constrained to keys of the client interface at the call\n * sites (the exported singletons are typed below), so the forward is sound.\n */\nfunction makeServiceProxy<K extends keyof RuntimeServices>(key: K): RuntimeServices[K] {\n const handler: ProxyHandler<RuntimeServices[K]> = {\n get(_target, prop, receiver) {\n const client = __getRuntime()[key];\n const value = Reflect.get(client as object, prop, receiver) as unknown;\n // Bind methods to their owning client so `this` stays correct when the\n // author destructures or calls `Database.query(...)`.\n return typeof value === \"function\" ? value.bind(client) : value;\n },\n };\n // The Proxy target is irrelevant (all access goes through `get`); the cast\n // names the surface type the singleton presents to authors.\n return new Proxy({} as RuntimeServices[K], handler);\n}\n\n/** The project's own Postgres (pgx, schema `env_<envId>`). Typed CRUD +\n * `query`/`transaction`. For a typed `.tables.<name>` API, wrap with\n * {@link typedDatabase}. */\nexport const Database: DBClient = makeServiceProxy(\"Database\");\n\n/** Firestore-like document client (PalDocs). */\nexport const Documents: PalbaseDocsClient = makeServiceProxy(\"Documents\");\n\n/** Object storage client (buckets, signed URLs). */\nexport const Storage: PalbaseStorageClient = makeServiceProxy(\"Storage\");\n\n/** JSON-typed cache (get/set/incr/getOrSet). */\nexport const Cache: CacheClient = makeServiceProxy(\"Cache\");\n\n/** Background job queue. */\nexport const Queue: QueueClient = makeServiceProxy(\"Queue\");\n\n/** Structured logger. */\nexport const Log: Logger = makeServiceProxy(\"Log\");\n\n/** Push / email / SMS / in-app notifications. */\nexport const Notifications: PalbaseNotificationsClient = makeServiceProxy(\"Notifications\");\n\n/** Feature flags. */\nexport const Flags: PalbaseFlagsClient = makeServiceProxy(\"Flags\");\n\n/**\n * Type the `Database` singleton against a `defineSchema()` result, returning a\n * facade with a typed `.tables.<name>.insert(...)` API alongside the raw\n * `query`/`transaction` ops.\n *\n * const Db = typedDatabase(schema);\n * const todo = await Db.tables.todos.insert({ title: \"x\" });\n *\n * This is per-endpoint (not global module augmentation), so one endpoint's\n * tables never leak into another's `Database` type.\n */\nexport function typedDatabase<TSchema extends SchemaDef>(\n schema: TSchema,\n): TypedDB<TSchema> & DBClient {\n // makeTypedDB wraps the raw DBClient with the typed `.tables` facade (and a\n // typed `transaction`). The full `& DBClient` surface also needs the raw ops\n // (query/insert/update/delete/findById/findMany), which we delegate straight\n // to the `Database` singleton — every call goes through its runtime Proxy.\n const typed = makeTypedDB(schema, Database);\n const rawOps: DBClient = {\n query: (sql, params) => Database.query(sql, params),\n insert: (table, data) => Database.insert(table, data),\n update: (table, id, data) => Database.update(table, id, data),\n delete: (table, id) => Database.delete(table, id),\n findById: (table, id) => Database.findById(table, id),\n findMany: (table, q) => Database.findMany(table, q),\n transaction: (fn) => Database.transaction(fn),\n };\n // typed.transaction (typed-tx) intentionally overrides rawOps.transaction so\n // the callback sees the typed `.tables` API.\n return Object.assign(rawOps, typed);\n}\n"],"mappings":";AAwGA,SAAS,eACP,MACA,KACe;AACf,SAAO;AAAA,IACL,QAAQ,CAAC,SACP,IAAI,OAAO,MAAM,IAA+B;AAAA,IAElD,QAAQ,CAAC,IAAY,SACnB,IAAI,OAAO,MAAM,IAAI,IAA+B;AAAA,IAEtD,QAAQ,CAAC,OAAe,IAAI,OAAO,MAAM,EAAE;AAAA,IAE3C,UAAU,CAAC,OACT,IAAI,SAAS,MAAM,EAAE;AAAA,IAEvB,UAAU,CAAC,UACT,IAAI,SAAS,MAAM,KAA4C;AAAA,EACnE;AACF;AAkBO,SAAS,YACd,QACA,KACY;AACZ,WAAS,YAAY,QAAwD;AAC3E,UAAM,SAAS,CAAC;AAChB,eAAW,OAAO,OAAO,KAAK,OAAO,MAAM,GAAG;AAC5C,YAAM,WAAW,OAAO,OAAO,GAAG;AAClC,UAAI,aAAa,QAAW;AAC1B,eAAO,GAAG,IAAI,eAAe,SAAS,MAAM,MAAM;AAAA,MACpD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS;AAAA,IACb,QAAQ,YAAY,GAAG;AAAA,IACvB,aAAa,CAAI,OACf,IAAI,YAAY,CAAC,UAAU,GAAG,EAAE,QAAQ,YAAY,KAAK,EAAE,CAAe,CAAC;AAAA,EAC/E;AAMA,SAAO;AACT;;;ACtGA,IAAI,UAAkC;AAQ/B,SAAS,aAAa,UAAiC;AAC5D,YAAU;AACZ;AAMO,SAAS,eAAgC;AAC9C,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AACA,SAAO;AACT;AAWA,SAAS,iBAAkD,KAA4B;AACrF,QAAM,UAA4C;AAAA,IAChD,IAAI,SAAS,MAAM,UAAU;AAC3B,YAAM,SAAS,aAAa,EAAE,GAAG;AACjC,YAAM,QAAQ,QAAQ,IAAI,QAAkB,MAAM,QAAQ;AAG1D,aAAO,OAAO,UAAU,aAAa,MAAM,KAAK,MAAM,IAAI;AAAA,IAC5D;AAAA,EACF;AAGA,SAAO,IAAI,MAAM,CAAC,GAAyB,OAAO;AACpD;AAKO,IAAM,WAAqB,iBAAiB,UAAU;AAGtD,IAAM,YAA+B,iBAAiB,WAAW;AAGjE,IAAM,UAAgC,iBAAiB,SAAS;AAGhE,IAAM,QAAqB,iBAAiB,OAAO;AAGnD,IAAM,QAAqB,iBAAiB,OAAO;AAGnD,IAAM,MAAc,iBAAiB,KAAK;AAG1C,IAAM,gBAA4C,iBAAiB,eAAe;AAGlF,IAAM,QAA4B,iBAAiB,OAAO;AAa1D,SAAS,cACd,QAC6B;AAK7B,QAAM,QAAQ,YAAY,QAAQ,QAAQ;AAC1C,QAAM,SAAmB;AAAA,IACvB,OAAO,CAAC,KAAK,WAAW,SAAS,MAAM,KAAK,MAAM;AAAA,IAClD,QAAQ,CAAC,OAAO,SAAS,SAAS,OAAO,OAAO,IAAI;AAAA,IACpD,QAAQ,CAAC,OAAO,IAAI,SAAS,SAAS,OAAO,OAAO,IAAI,IAAI;AAAA,IAC5D,QAAQ,CAAC,OAAO,OAAO,SAAS,OAAO,OAAO,EAAE;AAAA,IAChD,UAAU,CAAC,OAAO,OAAO,SAAS,SAAS,OAAO,EAAE;AAAA,IACpD,UAAU,CAAC,OAAO,MAAM,SAAS,SAAS,OAAO,CAAC;AAAA,IAClD,aAAa,CAAC,OAAO,SAAS,YAAY,EAAE;AAAA,EAC9C;AAGA,SAAO,OAAO,OAAO,QAAQ,KAAK;AACpC;","names":[]}
@@ -1,5 +1,5 @@
1
- import { S as SchemaDef } from '../schema-zk-a0Dv7.cjs';
2
- export { C as ColumnBuilder, a as ColumnDef, b as ColumnType, O as OnDeleteAction, T as TableDef, c as boolean, d as defineSchema, e as enumType, i as integer, j as jsonb, t as table, f as text, g as timestamp, u as uuid } from '../schema-zk-a0Dv7.cjs';
1
+ import { S as SchemaDef } from '../schema-BqfEhIC0.cjs';
2
+ export { b as ColumnBuilder, c as ColumnDef, d as ColumnType, O as OnDeleteAction, T as TableDef, e as boolean, f as defineSchema, g as enumType, i as integer, j as jsonb, t as table, h as text, k as timestamp, u as uuid } from '../schema-BqfEhIC0.cjs';
3
3
 
4
4
  /** Result of migration generation. */
5
5
  interface MigrationResult {
@@ -1,5 +1,5 @@
1
- import { S as SchemaDef } from '../schema-zk-a0Dv7.js';
2
- export { C as ColumnBuilder, a as ColumnDef, b as ColumnType, O as OnDeleteAction, T as TableDef, c as boolean, d as defineSchema, e as enumType, i as integer, j as jsonb, t as table, f as text, g as timestamp, u as uuid } from '../schema-zk-a0Dv7.js';
1
+ import { S as SchemaDef } from '../schema-BqfEhIC0.js';
2
+ export { b as ColumnBuilder, c as ColumnDef, d as ColumnType, O as OnDeleteAction, T as TableDef, e as boolean, f as defineSchema, g as enumType, i as integer, j as jsonb, t as table, h as text, k as timestamp, u as uuid } from '../schema-BqfEhIC0.js';
3
3
 
4
4
  /** Result of migration generation. */
5
5
  interface MigrationResult {
@@ -1,5 +1,5 @@
1
1
  import { ZodSchema, z } from 'zod';
2
- import { S as SchemaDef, T as TableDef, h as ColIsOptionalOnInsert, k as ColValue } from './schema-zk-a0Dv7.js';
2
+ import { S as SchemaDef } from './schema-BqfEhIC0.js';
3
3
 
4
4
  /** Supported HTTP methods for endpoints. */
5
5
  type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
@@ -47,90 +47,43 @@ type MiddlewareHandler = (ctx: MiddlewareContext, next: () => Promise<void>) =>
47
47
  */
48
48
  declare function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler;
49
49
 
50
- /**
51
- * typed-db.ts — Task 2: TypedDB schema-derived insert/row shapes.
50
+ /** HTTP error with structured error response format.
52
51
  *
53
- * Derives INSERT and full-row TypeScript types from a `defineSchema()` result
54
- * and wraps the untyped runtime `DBClient` with a typed facade.
52
+ * Two ways to construct one:
55
53
  *
56
- * No value-any. No `as unknown as X`. The two narrow `as` casts in
57
- * `makeTypedTable` are safe because:
58
- * - `data as Record<string, unknown>`: InsertShape<T> maps string keys to
59
- * typed values; all value types are subsets of `unknown`, so the cast is
60
- * structurally sound.
61
- * - `result as RowShape<T>`: The runtime DBClient returns `Record<string,
62
- * unknown>` which is the erased form of the typed row; we're narrowing back
63
- * to the precise shape that the schema declared.
64
- * Both casts are narrowing only (not widening) and correctness is guaranteed
65
- * by the schema the caller provides.
66
- */
67
-
68
- /** Keys of C whose columns are required on INSERT (not nullable, no default). */
69
- type RequiredKeys<C> = {
70
- [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? never : K;
71
- }[keyof C];
72
- /** Keys of C whose columns are optional on INSERT (nullable or has a default). */
73
- type OptionalKeys<C> = {
74
- [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? K : never;
75
- }[keyof C];
76
- /**
77
- * The TypeScript type for an INSERT payload for table `T`.
78
- * - Required: columns that are NOT NULL and have no DB-level default.
79
- * - Optional: columns that are nullable or carry a default.
54
+ * 1. Directly: `throw new HttpError(404, "todo_not_found", "No such todo")`.
55
+ * Surfaces on the wire (and to iOS) as `BackendError.server(code, status,
56
+ * message, requestId)`.
57
+ * 2. Via `ctx.errors.<name>(data?)` for declared errors see
58
+ * `EndpointConfig.errors`. The endpoint's OpenAPI spec describes each
59
+ * one, and the CLI codegen emits a typed `<Endpoint>.Error` enum so iOS
60
+ * callers can `catch <Endpoint>.Error.<case>` directly.
80
61
  *
81
- * When all columns are optional, `RequiredKeys<C>` resolves to `never` and
82
- * the first part becomes `{}`, which is a neutral element for `&`.
62
+ * The optional `data` field carries a structured payload alongside the
63
+ * standard envelope used by declared errors that need to ship extra context
64
+ * (e.g. `todoLocked({ retryAfter: 30 })`). It rides through to the iOS typed
65
+ * enum's associated value.
83
66
  */
84
- type InsertShape<T extends TableDef> = {
85
- [K in RequiredKeys<T["columns"]>]: ColValue<T["columns"][K]>;
86
- } & {
87
- [K in OptionalKeys<T["columns"]>]?: ColValue<T["columns"][K]>;
88
- };
89
- /**
90
- * The TypeScript type for a full row returned by the DB for table `T`.
91
- * Every column is present; nullable columns resolve to `T | null`.
92
- */
93
- type RowShape<T extends TableDef> = {
94
- [K in keyof T["columns"]]: ColValue<T["columns"][K]>;
95
- };
96
- /** A typed table accessor that mirrors the runtime DBClient surface. */
97
- interface TypedTable<T extends TableDef> {
98
- insert(data: InsertShape<T>): Promise<RowShape<T>>;
99
- update(id: string, data: Partial<InsertShape<T>>): Promise<RowShape<T>>;
100
- delete(id: string): Promise<void>;
101
- findById(id: string): Promise<RowShape<T> | null>;
102
- findMany(query?: Partial<RowShape<T>>): Promise<RowShape<T>[]>;
103
- }
104
- /** A typed DB facade covering all tables declared in schema `S`. */
105
- interface TypedDB<S extends SchemaDef> {
106
- tables: {
107
- [K in keyof S["tables"]]: TypedTable<S["tables"][K]>;
108
- };
109
- transaction<T>(fn: (tx: TypedTx<S>) => Promise<T>): Promise<T>;
110
- }
111
- /** Transaction-scoped typed facade: same typed tables, no nested transaction. */
112
- interface TypedTx<S extends SchemaDef> {
113
- tables: {
114
- [K in keyof S["tables"]]: TypedTable<S["tables"][K]>;
67
+ declare class HttpError extends Error {
68
+ readonly status: number;
69
+ readonly error: string;
70
+ readonly errorDescription: string;
71
+ readonly data?: unknown;
72
+ constructor(status: number, error: string, errorDescription: string, data?: unknown);
73
+ /**
74
+ * Serialize to the standard Palbase error response format.
75
+ * The `requestId` is injected by the runtime layer from the request context.
76
+ * When called without arguments (e.g. JSON.stringify), request_id is omitted.
77
+ * When `data` is set, it is appended as a strict-superset field.
78
+ */
79
+ toJSON(requestId?: string): {
80
+ error: string;
81
+ error_description: string;
82
+ status: number;
83
+ request_id?: string;
84
+ data?: unknown;
115
85
  };
116
86
  }
117
- /**
118
- * Wraps a raw `DBClient` with the type-safe `TypedDB<S>` facade derived from
119
- * the provided schema. No behavior change — all calls delegate to `raw` with
120
- * the table name as a plain string.
121
- *
122
- * `buildTables` is the reusable factory that wraps any op-bearing client
123
- * (`TxClient` — the surface shared by `DBClient` and the transaction-scoped
124
- * client) into the typed tables map. It is used both for the top-level db
125
- * (wrapping `raw`) and inside `transaction`, where it wraps the raw `TxClient`
126
- * the runtime yields so the callback sees the same typed `.tables` API.
127
- *
128
- * `transaction` delegates straight to `raw.transaction`; the two narrow
129
- * `as TypedTx<S>` / `as TypedDB<S>` casts are single structural narrowings
130
- * from the dynamically-built tables object to the precise mapped type (TS
131
- * cannot infer through `Object.keys` iteration) — see module-level doc comment.
132
- */
133
- declare function makeTypedDB<S extends SchemaDef>(schema: S, raw: DBClient): TypedDB<S>;
134
87
 
135
88
  /**
136
89
  * Local typed interfaces for the 9 Palbase module clients injected into
@@ -1287,7 +1240,7 @@ interface PalbaseQuerySnapshot<T = Record<string, unknown>> {
1287
1240
  }
1288
1241
  /** Comparison operators supported by docs.where(). */
1289
1242
  type PalbaseWhereOperator = "==" | "!=" | "<" | "<=" | ">" | ">=" | "in" | "array-contains";
1290
- /** Document reference exposed by ctx.docs.collection(...).doc(...). */
1243
+ /** Document reference exposed by Documents.collection(...).doc(...). */
1291
1244
  interface PalbaseDocumentRef<T = Record<string, unknown>> {
1292
1245
  readonly path: string;
1293
1246
  set(data: T): Promise<PalbaseResult<void>>;
@@ -1295,7 +1248,7 @@ interface PalbaseDocumentRef<T = Record<string, unknown>> {
1295
1248
  update(data: Partial<T>): Promise<PalbaseResult<void>>;
1296
1249
  delete(): Promise<PalbaseResult<void>>;
1297
1250
  }
1298
- /** Collection reference exposed by ctx.docs.collection(...). */
1251
+ /** Collection reference exposed by Documents.collection(...). */
1299
1252
  interface PalbaseCollectionRef<T = Record<string, unknown>> {
1300
1253
  readonly path: string;
1301
1254
  doc(id: string): PalbaseDocumentRef<T>;
@@ -1305,23 +1258,39 @@ interface PalbaseCollectionRef<T = Record<string, unknown>> {
1305
1258
  limit(n: number): PalbaseCollectionRef<T>;
1306
1259
  get(): Promise<PalbaseResult<PalbaseQuerySnapshot<T>>>;
1307
1260
  }
1308
- /** Docs client surface available on ctx.docs. */
1261
+ /** Docs client surface available on the Documents singleton. */
1309
1262
  interface PalbaseDocsClient {
1310
1263
  collection<T = Record<string, unknown>>(path: string): PalbaseCollectionRef<T>;
1311
1264
  doc<T = Record<string, unknown>>(path: string): PalbaseDocumentRef<T>;
1312
1265
  }
1313
- /** Palbase module clients surfaced directly on every context.
1266
+ /** Calling-client metadata, derived from request headers.
1314
1267
  *
1315
- * `ctx.docs`, `ctx.storage`, no `ctx.palbase.*` namespace. Structurally
1316
- * typed against the runtime's `ServerClient`; the runtime injects the real
1317
- * client, so mismatched names would surface as `undefined is not a function`
1318
- * at call time keep these in sync with `ServerClient`.
1268
+ * Populated from the `X-Palbase-*-Version` / platform headers the client SDKs
1269
+ * send. All fields are nullable: a request may come from a non-SDK caller
1270
+ * (curl, server-to-server) that sends none of them. The semver comparison
1271
+ * helpers (`appVersionAtLeast`, …) arrive in Phase 2 Phase 1 surfaces only
1272
+ * the raw data fields. */
1273
+ interface ClientInfo {
1274
+ /** Palbase SDK version (`X-Palbase-Sdk-Version`), or null. */
1275
+ sdkVersion: string | null;
1276
+ /** Calling app's own version (`X-Palbase-Client-Version`), or null. */
1277
+ appVersion: string | null;
1278
+ /** Platform identifier (e.g. "ios", "android", "web"), or null. */
1279
+ platform: string | null;
1280
+ /** OS version string, or null. */
1281
+ osVersion: string | null;
1282
+ }
1283
+ /** Palbase module clients, as a structural bundle.
1319
1284
  *
1320
- * Note: `db` here is NOT a module client `ctx.db` is the project's own
1321
- * Postgres (pgx, schema `env_<envId>`), declared separately on each context
1322
- * as `DBClient`. The SDK's PostgREST query-builder is not exposed inside
1323
- * endpoints.
1324
- */
1285
+ * NOT part of the endpoint surface anymoreendpoint handlers reach services
1286
+ * via the PascalCase singletons (`Database`, `Documents`, …). This type is
1287
+ * retained as an INTERNAL shape for the sibling contexts that still carry a
1288
+ * `ctx` (middleware, jobs, workers, hooks, webhooks — out of Phase 1 scope).
1289
+ * It is intentionally not re-exported from `index.ts`.
1290
+ *
1291
+ * Structurally typed against the runtime's `ServerClient`; the runtime injects
1292
+ * the real client, so mismatched names would surface as `undefined is not a
1293
+ * function` at call time — keep these in sync with `ServerClient`. */
1325
1294
  interface PalbaseModuleClients {
1326
1295
  auth: PalbaseAuthClient;
1327
1296
  storage: PalbaseStorageClient;
@@ -1334,40 +1303,97 @@ interface PalbaseModuleClients {
1334
1303
  links: PalbaseLinksClient;
1335
1304
  cms: PalbaseCmsClient;
1336
1305
  }
1337
- /** Endpoint context — injected into every handler. Module clients hang
1338
- * directly off ctx (`ctx.docs`, not `ctx.palbase.docs`); `ctx.db` is the
1339
- * project's own Postgres.
1306
+ /** Declared-error definition.
1307
+ *
1308
+ * `code` is the stable snake_case identifier that lands on the wire envelope's
1309
+ * `error` field. `status` is the HTTP status code returned. `data`, if set,
1310
+ * is a Zod schema whose value rides on the envelope's `data` field — the CLI
1311
+ * codegen lowers it to the typed enum's associated value on iOS.
1340
1312
  *
1341
- * When `TSchema` is a `SchemaDef`, `ctx.db` is `TypedDB<TSchema> & DBClient`:
1342
- * both `ctx.db.tables.rooms.insert({...})` (typed) and
1343
- * `ctx.db.insert("rooms", {...})` (legacy string API) compile.
1344
- * When `TSchema` is `undefined` (no schema), `ctx.db` is plain `DBClient`.
1313
+ * `description` is optional human-readable text; the OpenAPI generator uses it
1314
+ * for the response description and the iOS codegen surfaces it in the
1315
+ * generated method's doc-comment.
1345
1316
  */
1346
- interface EndpointContext<TInput = unknown, TSchema extends SchemaDef | undefined = undefined, TAuthed extends boolean = false> extends PalbaseModuleClients {
1317
+ interface ErrorDef<TData extends ZodSchema = ZodSchema> {
1318
+ status: number;
1319
+ code: string;
1320
+ description?: string;
1321
+ data?: TData;
1322
+ }
1323
+ /** Map of declared errors keyed by their TypeScript-side names.
1324
+ *
1325
+ * Keys are the friendly names the handler uses (`req.errors.todoLocked`);
1326
+ * `code` on each value is the wire identifier. The TS name is what the iOS
1327
+ * codegen lowers to (camelCase enum cases), and the wire `code` is what the
1328
+ * envelope's `error` field carries.
1329
+ */
1330
+ type ErrorMap = Record<string, ErrorDef>;
1331
+ /** Throwable proxy projected onto `req.errors` when `errors` is declared.
1332
+ *
1333
+ * Each entry is a constructor: declared errors with a `data` schema demand
1334
+ * the payload as a required argument; declared errors without `data` take
1335
+ * none. Throwing the result emits the standard envelope (with `data` when
1336
+ * present).
1337
+ *
1338
+ * throw req.errors.todoNotFound();
1339
+ * throw req.errors.todoLocked({ retryAfter: 30 });
1340
+ */
1341
+ type ErrorThrowers<TErrors extends ErrorMap | undefined> = TErrors extends ErrorMap ? {
1342
+ [K in keyof TErrors]: TErrors[K]["data"] extends ZodSchema ? (data: z.infer<NonNullable<TErrors[K]["data"]>>) => HttpError : () => HttpError;
1343
+ } : Record<string, never>;
1344
+ /** The request-scoped object passed to every endpoint handler.
1345
+ *
1346
+ * Replaces the old `ctx` god-object. `PBRequest` carries ONLY request-scoped
1347
+ * data — the typed `input`, route/query params, headers, the authenticated
1348
+ * `user`, calling-client metadata, trace ids, and the endpoint's declared
1349
+ * error throwers. Services (`Database`, `Documents`, `Cache`, …) are NOT on
1350
+ * the request: import them directly from `@palbase/backend` as singletons.
1351
+ *
1352
+ * import { defineEndpoint, Database } from "@palbase/backend";
1353
+ *
1354
+ * export default defineEndpoint({
1355
+ * method: "POST",
1356
+ * handler: async (req) => Database.insert("todos", { title: req.input.title }),
1357
+ * });
1358
+ *
1359
+ * Generic parameters:
1360
+ * - `TInput` — the validated `input` type (inferred from the `input` Zod
1361
+ * schema by `defineEndpoint`). The user-facing form is single-generic:
1362
+ * `PBRequest<TodoInput>`.
1363
+ * - `TAuthed` — whether `user` is non-null. DEFAULTS to `true` (the common
1364
+ * case; the auth pipeline returns 401 before the handler when auth is
1365
+ * required, so a non-null `user` is runtime-honest). `defineEndpoint` passes
1366
+ * `IsAuthed<TAuth>` here, so `auth: false` → `User | null`.
1367
+ * - `TErrors` — the declared `errors` map, typing `req.errors.<name>(...)`.
1368
+ */
1369
+ interface PBRequest<TInput = unknown, TAuthed extends boolean = true, TErrors extends ErrorMap | undefined = undefined> {
1370
+ /** Validated request input (body for POST/PUT/PATCH; `{}` otherwise). */
1347
1371
  input: TInput;
1372
+ /** Matched route params (e.g. `{ id }` for `/todos/[id]`). */
1348
1373
  params: Record<string, string>;
1374
+ /** Parsed query-string params. */
1349
1375
  query: Record<string, string>;
1376
+ /** Request headers (lowercase keys). */
1350
1377
  headers: Record<string, string>;
1351
- /** Authenticated user. Non-null (`User`) only when the endpoint's `auth`
1352
- * config forces authentication; otherwise `User | null`. The narrowing is
1353
- * driven by the `TAuthed` flag, which `defineEndpoint` computes from the
1354
- * `auth` literal via {@link IsAuthed}. */
1378
+ /** Authenticated user. Non-null (`User`) by default; `User | null` only when
1379
+ * the endpoint's `auth` config disables enforcement (driven by `TAuthed`,
1380
+ * which `defineEndpoint` computes from the `auth` literal via {@link IsAuthed}). */
1355
1381
  user: TAuthed extends true ? User : User | null;
1356
- /** HTTP method of the incoming request (e.g. "GET", "POST"). */
1357
- method: string;
1358
- /** Matched endpoint path (e.g. "/todos/create"). */
1359
- endpointPath: string;
1382
+ /** Calling-client metadata derived from request headers (all nullable). */
1383
+ client: ClientInfo;
1360
1384
  /** Uploaded file, or null when the request has no file part. */
1361
1385
  file: FileContext | null;
1362
- db: TSchema extends SchemaDef ? TypedDB<TSchema> & DBClient : DBClient;
1363
- env: Record<string, string>;
1364
- log: Logger;
1365
- cache: CacheClient;
1366
- /** Queue client for dispatching background jobs. */
1367
- queue: QueueClient;
1386
+ /** HTTP method of the incoming request (e.g. "GET", "POST"). */
1387
+ method: string;
1388
+ /** Per-request id (`req_<…>`), preserved for back-compat correlation. */
1368
1389
  requestId: string;
1369
- projectId: string;
1370
- environmentId: string;
1390
+ /** W3C trace id (primary correlation key across modules). */
1391
+ traceId: string;
1392
+ /** W3C span id for this handler invocation. */
1393
+ spanId: string;
1394
+ /** Typed throwers for the endpoint's declared errors. Empty when the
1395
+ * `errors` block is absent on `defineEndpoint`. */
1396
+ errors: ErrorThrowers<TErrors>;
1371
1397
  }
1372
1398
  /** Middleware function signature — uses MiddlewareContext (no input, not yet validated). */
1373
1399
  type Middleware = (ctx: MiddlewareContext, next: () => Promise<void>) => Promise<void>;
@@ -1379,11 +1405,11 @@ type Middleware = (ctx: MiddlewareContext, next: () => Promise<void>) => Promise
1379
1405
  */
1380
1406
  type AuthSpec = boolean | Partial<AuthConfig>;
1381
1407
  /** Compute, at the type level, whether an endpoint authenticates its caller —
1382
- * i.e. whether `ctx.user` should be `User` (non-null) instead of `User | null`.
1408
+ * i.e. whether `req.user` should be `User` (non-null) instead of `User | null`.
1383
1409
  *
1384
1410
  * This mirrors the Go pipeline's enforcement exactly (extract_meta.js + auth.go):
1385
1411
  * a request is authenticated ⟺ `auth === true` OR (`auth` is an object whose
1386
- * `required` is not explicitly `false`). So `ctx.user` stays nullable ONLY when
1412
+ * `required` is not explicitly `false`). So `req.user` stays nullable ONLY when
1387
1413
  * `auth` is absent (`undefined`), `auth === false`, or `auth: { required: false }`.
1388
1414
  *
1389
1415
  * | `TAuth` | `IsAuthed<TAuth>` |
@@ -1405,31 +1431,40 @@ type IsAuthed<TAuth> = TAuth extends {
1405
1431
  } ? false : TAuth extends true ? true : TAuth extends false ? false : TAuth extends object ? true : false;
1406
1432
  /** Configuration for defining an endpoint.
1407
1433
  *
1408
- * `TSchema` — optional `SchemaDef` that, when provided, types `ctx.db` as
1409
- * `TypedDB<TSchema> & DBClient` so both the typed `.tables` API and the
1410
- * legacy string API compile inside the handler.
1434
+ * `TSchema` — optional `SchemaDef` carried on the `schema` field. The runtime
1435
+ * uses it to wire a typed `.tables.*` API; authors opt in per endpoint with
1436
+ * `typedDatabase(schema)` (see runtime.ts).
1411
1437
  *
1412
1438
  * `TAuth` — captures the literal type of the `auth` field (via the `const`
1413
- * type parameter on `defineEndpoint`) so the handler's `ctx.user` can be
1439
+ * type parameter on `defineEndpoint`) so the handler's `req.user` can be
1414
1440
  * narrowed to non-null `User` when auth is required. See {@link IsAuthed}.
1441
+ *
1442
+ * `TErrors` — captures the literal `errors` map (via the `const` type
1443
+ * parameter on `defineEndpoint`) so `req.errors.<name>(...)` is typed per
1444
+ * declared entry. The OpenAPI generator emits each one as a discriminated
1445
+ * response under `responses[<status>]`, and the CLI codegen lowers them to
1446
+ * a typed `<Endpoint>.Error` enum on iOS.
1415
1447
  */
1416
- interface EndpointConfig<TInputSchema extends ZodSchema = ZodSchema, TOutputSchema extends ZodSchema = ZodSchema, TSchema extends SchemaDef | undefined = undefined, TAuth extends AuthSpec | undefined = undefined> {
1448
+ interface EndpointConfig<TInputSchema extends ZodSchema = ZodSchema, TOutputSchema extends ZodSchema = ZodSchema, TSchema extends SchemaDef | undefined = undefined, TAuth extends AuthSpec | undefined = undefined, TErrors extends ErrorMap | undefined = undefined> {
1417
1449
  method: HttpMethod;
1418
1450
  auth?: TAuth;
1419
1451
  rateLimit?: RateLimitConfig;
1420
1452
  input?: TInputSchema;
1421
1453
  output?: TOutputSchema;
1422
1454
  schema?: TSchema;
1455
+ errors?: TErrors;
1423
1456
  middleware?: Middleware[];
1424
- handler: (ctx: EndpointContext<z.infer<TInputSchema>, TSchema, IsAuthed<TAuth>>) => Promise<z.infer<TOutputSchema>>;
1457
+ handler: (req: PBRequest<z.infer<TInputSchema>, IsAuthed<TAuth>, TErrors>) => Promise<z.infer<TOutputSchema>>;
1425
1458
  }
1426
- /** Define a type-safe endpoint. Input schema infers the ctx.input type.
1427
- * Pass a `schema` (from `defineSchema`) to get a typed `ctx.db.tables.*` API.
1459
+ /** Define a type-safe endpoint. The input schema infers the `req.input` type.
1460
+ * Pass a `schema` (from `defineSchema`) and wrap `Database` with
1461
+ * `typedDatabase(schema)` in the handler for a typed `.tables.*` API.
1428
1462
  *
1429
- * The `const TAuth` type parameter captures the `auth` field as a literal
1430
- * (`true` / `{ required: true }` / `{ role: 'admin' }` …) so the handler's
1431
- * `ctx.user` is narrowed to `User` (non-null) whenever auth is enforced.
1463
+ * The `const TAuth` and `const TErrors` type parameters capture the `auth`
1464
+ * and `errors` fields as literals, so `req.user` narrows to non-null `User`
1465
+ * when auth is enforced and `req.errors.<name>(...)` is typed per declared
1466
+ * entry.
1432
1467
  */
1433
- declare function defineEndpoint<TInputSchema extends ZodSchema, TOutputSchema extends ZodSchema, TSchema extends SchemaDef | undefined = undefined, const TAuth extends AuthSpec | undefined = undefined>(config: EndpointConfig<TInputSchema, TOutputSchema, TSchema, TAuth>): EndpointConfig<TInputSchema, TOutputSchema, TSchema, TAuth>;
1468
+ declare function defineEndpoint<TInputSchema extends ZodSchema, TOutputSchema extends ZodSchema, TSchema extends SchemaDef | undefined = undefined, const TAuth extends AuthSpec | undefined = undefined, const TErrors extends ErrorMap | undefined = undefined>(config: EndpointConfig<TInputSchema, TOutputSchema, TSchema, TAuth, TErrors>): EndpointConfig<TInputSchema, TOutputSchema, TSchema, TAuth, TErrors>;
1434
1469
 
1435
- export { type PalbaseIdentifyTraits as $, type AuthConfig as A, type PalbaseDocumentRef as B, type CacheClient as C, type DBClient as D, type EndpointContext as E, type FileContext as F, type PalbaseDocumentSnapshot as G, type HttpMethod as H, type InsertShape as I, type PalbaseEmailClient as J, type PalbaseEmailSendParams as K, type Logger as L, type Middleware as M, type PalbaseEmailSendResponse as N, type PalbaseEventNamesResult as O, type PalbaseModuleClients as P, type QueueClient as Q, type PalbaseEventsQueryInput as R, type PalbaseEventsResult as S, type PalbaseFileObject as T, type PalbaseFlag as U, type PalbaseFlagContext as V, type PalbaseFlagVariant as W, type PalbaseFlagsClient as X, type PalbaseFunctionsClient as Y, type PalbaseFunnelQueryInput as Z, type PalbaseFunnelResult as _, type EndpointConfig as a, type PalbaseInboxClient as a0, type PalbaseInboxListOptions as a1, type PalbaseInboxListResult as a2, type PalbaseInboxMessage as a3, type PalbaseInboxSendParams as a4, type PalbaseInboxSendResponse as a5, type PalbaseInitialLink as a6, type PalbaseInvokeOptions as a7, type PalbaseLink as a8, type PalbaseLinkAnalytics as a9, type PalbaseSmsClient as aA, type PalbaseSmsSendParams as aB, type PalbaseSmsSendResponse as aC, type PalbaseStorageClient as aD, type PalbaseTransformOptions as aE, type PalbaseUpdateLinkParams as aF, type PalbaseUploadOptions as aG, type PalbaseUser as aH, type PalbaseUserDetailResult as aI, type PalbaseUsersQueryInput as aJ, type PalbaseUsersResult as aK, type PalbaseVerifyRequestSignatureParams as aL, type PalbaseWhereOperator as aM, type RateLimitConfig as aN, type RowShape as aO, type TxClient as aP, type TypedDB as aQ, type TypedTable as aR, type TypedTx as aS, type User as aT, defineEndpoint as aU, defineMiddleware as aV, makeTypedDB as aW, type PalbaseLinkDetails as aa, type PalbaseLinksClient as ab, type PalbaseListLinksOptions as ac, type PalbaseListLinksResult as ad, type PalbaseListOptions as ae, type PalbaseMatchParams as af, type PalbaseMultiChannelResponse as ag, type PalbaseNotificationsClient as ah, type PalbaseOverviewResult as ai, type PalbasePreferences as aj, type PalbasePreferencesClient as ak, type PalbasePublicUrlResponse as al, type PalbasePushClient as am, type PalbasePushSendParams as an, type PalbasePushSendResponse as ao, type PalbaseQrCodeOptions as ap, type PalbaseQuerySnapshot as aq, type PalbaseRealtimeChannel as ar, type PalbaseRealtimeClient as as, type PalbaseRealtimeMessage as at, type PalbaseRegisterDeviceParams as au, type PalbaseResult as av, type PalbaseRetentionQueryInput as aw, type PalbaseRetentionResult as ax, type PalbaseSession as ay, type PalbaseSignedUrlResponse as az, type MiddlewareContext as b, type MiddlewareHandler as c, type PalbaseAnalyticsClient as d, type PalbaseAnalyticsManagementNamespace as e, type PalbaseAnalyticsProperties as f, type PalbaseAnalyticsQueryNamespace as g, type PalbaseAttestAndroidParams as h, type PalbaseAttestAndroidResult as i, type PalbaseAttestiOSParams as j, type PalbaseAttestiOSResult as k, type PalbaseAuthClient as l, type PalbaseBindDeviceParams as m, type PalbaseBucketClient as n, type PalbaseCmsClient as o, type PalbaseCmsFindOneOptions as p, type PalbaseCmsFindOptions as q, type PalbaseCohortQueryInput as r, type PalbaseCohortResult as s, type PalbaseCollectionRef as t, type PalbaseCountQueryInput as u, type PalbaseCountResult as v, type PalbaseCreateLinkParams as w, type PalbaseDeviceInfo as x, type PalbaseDeviceTokenView as y, type PalbaseDocsClient as z };
1470
+ export { type PalbaseFileObject as $, type AuthConfig as A, type PalbaseCohortQueryInput as B, type CacheClient as C, type DBClient as D, type ErrorThrowers as E, type FileContext as F, type PalbaseCohortResult as G, HttpError as H, type PalbaseCollectionRef as I, type PalbaseCountQueryInput as J, type PalbaseCountResult as K, type Logger as L, type Middleware as M, type PalbaseCreateLinkParams as N, type PalbaseDeviceInfo as O, type PalbaseDocsClient as P, type QueueClient as Q, type PalbaseDeviceTokenView as R, type PalbaseDocumentRef as S, type PalbaseDocumentSnapshot as T, type User as U, type PalbaseEmailClient as V, type PalbaseEmailSendParams as W, type PalbaseEmailSendResponse as X, type PalbaseEventNamesResult as Y, type PalbaseEventsQueryInput as Z, type PalbaseEventsResult as _, type PalbaseFlagsClient as a, type PalbaseFlag as a0, type PalbaseFlagContext as a1, type PalbaseFlagVariant as a2, type PalbaseFunctionsClient as a3, type PalbaseFunnelQueryInput as a4, type PalbaseFunnelResult as a5, type PalbaseIdentifyTraits as a6, type PalbaseInboxClient as a7, type PalbaseInboxListOptions as a8, type PalbaseInboxListResult as a9, type PalbaseRegisterDeviceParams as aA, type PalbaseResult as aB, type PalbaseRetentionQueryInput as aC, type PalbaseRetentionResult as aD, type PalbaseSession as aE, type PalbaseSignedUrlResponse as aF, type PalbaseSmsClient as aG, type PalbaseSmsSendParams as aH, type PalbaseSmsSendResponse as aI, type PalbaseTransformOptions as aJ, type PalbaseUpdateLinkParams as aK, type PalbaseUploadOptions as aL, type PalbaseUser as aM, type PalbaseUserDetailResult as aN, type PalbaseUsersQueryInput as aO, type PalbaseUsersResult as aP, type PalbaseVerifyRequestSignatureParams as aQ, type PalbaseWhereOperator as aR, type RateLimitConfig as aS, type TxClient as aT, defineEndpoint as aU, defineMiddleware as aV, type PalbaseInboxMessage as aa, type PalbaseInboxSendParams as ab, type PalbaseInboxSendResponse as ac, type PalbaseInitialLink as ad, type PalbaseInvokeOptions as ae, type PalbaseLink as af, type PalbaseLinkAnalytics as ag, type PalbaseLinkDetails as ah, type PalbaseLinksClient as ai, type PalbaseListLinksOptions as aj, type PalbaseListLinksResult as ak, type PalbaseListOptions as al, type PalbaseMatchParams as am, type PalbaseMultiChannelResponse as an, type PalbaseOverviewResult as ao, type PalbasePreferences as ap, type PalbasePreferencesClient as aq, type PalbasePublicUrlResponse as ar, type PalbasePushClient as as, type PalbasePushSendParams as at, type PalbasePushSendResponse as au, type PalbaseQrCodeOptions as av, type PalbaseQuerySnapshot as aw, type PalbaseRealtimeChannel as ax, type PalbaseRealtimeClient as ay, type PalbaseRealtimeMessage as az, type PalbaseNotificationsClient as b, type PalbaseStorageClient as c, type PalbaseModuleClients as d, type ClientInfo as e, type EndpointConfig as f, type ErrorDef as g, type ErrorMap as h, type HttpMethod as i, type MiddlewareContext as j, type MiddlewareHandler as k, type PBRequest as l, type PalbaseAnalyticsClient as m, type PalbaseAnalyticsManagementNamespace as n, type PalbaseAnalyticsProperties as o, type PalbaseAnalyticsQueryNamespace as p, type PalbaseAttestAndroidParams as q, type PalbaseAttestAndroidResult as r, type PalbaseAttestiOSParams as s, type PalbaseAttestiOSResult as t, type PalbaseAuthClient as u, type PalbaseBindDeviceParams as v, type PalbaseBucketClient as w, type PalbaseCmsClient as x, type PalbaseCmsFindOneOptions as y, type PalbaseCmsFindOptions as z };