@palbase/backend 2.0.2 → 4.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.
Files changed (53) hide show
  1. package/dist/chunk-EG7TTYHY.js +235 -0
  2. package/dist/chunk-EG7TTYHY.js.map +1 -0
  3. package/dist/chunk-WUQO76NW.js +101 -0
  4. package/dist/chunk-WUQO76NW.js.map +1 -0
  5. package/dist/db/env.cjs +19 -0
  6. package/dist/db/env.cjs.map +1 -0
  7. package/dist/db/env.d.cts +45 -0
  8. package/dist/db/env.d.ts +45 -0
  9. package/dist/db/env.js +1 -0
  10. package/dist/db/env.js.map +1 -0
  11. package/dist/db/index.cjs +143 -231
  12. package/dist/db/index.cjs.map +1 -1
  13. package/dist/db/index.d.cts +4 -20
  14. package/dist/db/index.d.ts +4 -20
  15. package/dist/db/index.js +13 -233
  16. package/dist/db/index.js.map +1 -1
  17. package/dist/{endpoint-Djk5L6G2.d.ts → endpoint-2d_DpASt.d.cts} +94 -96
  18. package/dist/{endpoint-BlcY2xNA.d.cts → endpoint-2d_DpASt.d.ts} +94 -96
  19. package/dist/index-DZW9CjiY.d.ts +463 -0
  20. package/dist/index-DzRFS3Tl.d.cts +463 -0
  21. package/dist/index.cjs +557 -60
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +278 -161
  24. package/dist/index.d.ts +278 -161
  25. package/dist/index.js +343 -12
  26. package/dist/index.js.map +1 -1
  27. package/dist/test/index.cjs +57 -2
  28. package/dist/test/index.cjs.map +1 -1
  29. package/dist/test/index.d.cts +1 -2
  30. package/dist/test/index.d.ts +1 -2
  31. package/dist/test/index.js +10 -2
  32. package/dist/test/index.js.map +1 -1
  33. package/docs/README.md +33 -12
  34. package/docs/background.md +19 -13
  35. package/docs/database.md +70 -17
  36. package/docs/endpoints.md +103 -79
  37. package/docs/errors.md +37 -31
  38. package/docs/events.md +25 -17
  39. package/docs/getting-started.md +38 -18
  40. package/docs/llms-full.txt +758 -267
  41. package/docs/llms.txt +3 -1
  42. package/docs/migrations.md +98 -0
  43. package/docs/resources.md +94 -0
  44. package/docs/routing.md +54 -27
  45. package/docs/schema.md +163 -42
  46. package/docs/services.md +17 -14
  47. package/package.json +12 -2
  48. package/dist/chunk-4J3F32SH.js +0 -96
  49. package/dist/chunk-4J3F32SH.js.map +0 -1
  50. package/dist/chunk-L36JLUPO.js +0 -97
  51. package/dist/chunk-L36JLUPO.js.map +0 -1
  52. package/dist/schema-BqfEhIC0.d.cts +0 -133
  53. package/dist/schema-BqfEhIC0.d.ts +0 -133
@@ -0,0 +1,463 @@
1
+ import { Tables, TableTypes } from './db/env.cjs';
2
+ import { D as DBClient } from './endpoint-2d_DpASt.cjs';
3
+
4
+ /** On delete action for foreign key references. */
5
+ type OnDeleteAction = 'cascade' | 'set null' | 'restrict' | 'no action';
6
+ /** Column type identifiers. */
7
+ type ColumnType = 'uuid' | 'text' | 'integer' | 'boolean' | 'timestamp' | 'jsonb' | 'enum';
8
+ /** Base column definition shared by all column types. */
9
+ interface ColumnDef {
10
+ type: ColumnType;
11
+ nullable: boolean;
12
+ primaryKey: boolean;
13
+ defaultValue?: unknown;
14
+ defaultRandom?: boolean;
15
+ defaultNow?: boolean;
16
+ references?: {
17
+ table: string;
18
+ column: string;
19
+ };
20
+ onDeleteAction?: OnDeleteAction;
21
+ enumName?: string;
22
+ enumValues?: string[];
23
+ }
24
+ declare const __colKind: unique symbol;
25
+ declare const __colNullable: unique symbol;
26
+ declare const __colHasDefault: unique symbol;
27
+ declare const __colEnumValues: unique symbol;
28
+ /**
29
+ * Fluent column builder with phantom type params:
30
+ * K — ColumnType literal (e.g. "text", "integer")
31
+ * N — boolean: true when nullable() has been called last (false = NOT NULL)
32
+ * D — boolean: true when a default has been set
33
+ * E — enum value union (never for non-enum columns)
34
+ *
35
+ * All four params have defaults so bare `ColumnBuilder` (no args) still
36
+ * satisfies `Record<string, ColumnBuilder>` in schema.ts without modification.
37
+ *
38
+ * The four `declare readonly` brand fields carry the phantom types into the
39
+ * structural shape so that conditional types like ColValue<C> can discriminate
40
+ * on K without requiring runtime values on those fields.
41
+ */
42
+ declare class ColumnBuilder<K extends ColumnType = ColumnType, N extends boolean = boolean, D extends boolean = boolean, E = unknown> {
43
+ readonly [__colKind]: K;
44
+ readonly [__colNullable]: N;
45
+ readonly [__colHasDefault]: D;
46
+ readonly [__colEnumValues]: E;
47
+ readonly _def: ColumnDef;
48
+ constructor(type: K, existingDef?: ColumnDef);
49
+ /** Mark this column as the primary key. */
50
+ primaryKey(): ColumnBuilder<K, N, D, E>;
51
+ /** Mark this column as NOT NULL (default). */
52
+ notNull(): ColumnBuilder<K, false, D, E>;
53
+ /** Allow NULL values. */
54
+ nullable(): ColumnBuilder<K, true, D, E>;
55
+ /** Set a default value. */
56
+ default(value: unknown): ColumnBuilder<K, N, true, E>;
57
+ /** UUID: generate a random default (gen_random_uuid()). */
58
+ defaultRandom(): ColumnBuilder<K, N, true, E>;
59
+ /** Timestamp: default to now(). */
60
+ defaultNow(): ColumnBuilder<K, N, true, E>;
61
+ /** Add a foreign key reference. */
62
+ references(table: string, column: string): ColumnBuilder<K, N, D, E>;
63
+ /** Set the ON DELETE action for a foreign key reference. */
64
+ onDelete(action: OnDeleteAction): ColumnBuilder<K, N, D, E>;
65
+ }
66
+ /**
67
+ * Extracts the TypeScript value type for a column, respecting nullability.
68
+ * - "uuid" | "text" | "timestamp" → string (or string | null when N = true)
69
+ * - "integer" → number
70
+ * - "boolean" → boolean
71
+ * - "jsonb" → unknown (opaque JSON)
72
+ * - "enum" → E (the union of literal values)
73
+ */
74
+ type ColValue<C> = C extends ColumnBuilder<'uuid' | 'text' | 'timestamp', infer N, infer _D, infer _E> ? N extends true ? string | null : string : C extends ColumnBuilder<'integer', infer N, infer _D, infer _E> ? N extends true ? number | null : number : C extends ColumnBuilder<'boolean', infer N, infer _D, infer _E> ? N extends true ? boolean | null : boolean : C extends ColumnBuilder<'jsonb', infer _N, infer _D, infer _E> ? unknown : C extends ColumnBuilder<'enum', infer N, infer _D, infer E> ? N extends true ? E | null : E : never;
75
+ /**
76
+ * True when a column is optional on INSERT:
77
+ * - nullable columns (N = true) — the DB allows NULL so the field may be omitted
78
+ * - columns with a default (D = true) — the DB fills in the value when absent
79
+ */
80
+ type ColIsOptionalOnInsert<C> = C extends ColumnBuilder<infer _K, true, infer _D, infer _E> ? true : C extends ColumnBuilder<infer _K, infer _N, true, infer _E> ? true : false;
81
+ /** Create a UUID column. */
82
+ declare function uuid(): ColumnBuilder<'uuid', false, false, never>;
83
+ /** Create a TEXT column. */
84
+ declare function text(): ColumnBuilder<'text', false, false, never>;
85
+ /** Create an INTEGER column. */
86
+ declare function integer(): ColumnBuilder<'integer', false, false, never>;
87
+ /** Create a BOOLEAN column. */
88
+ declare function boolean(): ColumnBuilder<'boolean', false, false, never>;
89
+ /** Create a TIMESTAMP column. */
90
+ declare function timestamp(): ColumnBuilder<'timestamp', false, false, never>;
91
+ /** Create a JSONB column. */
92
+ declare function jsonb(): ColumnBuilder<'jsonb', false, false, never>;
93
+ /**
94
+ * Create an ENUM column.
95
+ * @param name The PostgreSQL enum type name (used in DDL).
96
+ * @param values A readonly tuple of valid string values — kept `const` so the
97
+ * union `V[number]` is as narrow as possible.
98
+ */
99
+ declare function enumType<const V extends readonly string[]>(name: string, values: V): ColumnBuilder<'enum', false, false, V[number]>;
100
+
101
+ /**
102
+ * policy.ts — the RLS policy authoring DSL.
103
+ *
104
+ * `policy(name)` returns a fluent builder that mirrors the `ColumnBuilder`
105
+ * style in columns.ts: each chainable method mutates the underlying
106
+ * definition and returns the builder so calls compose. The terminal value is
107
+ * a plain {@link PolicyDef} — the exact JSON shape the runtime's
108
+ * `schema_extract.js` reads off the bundled module and the Go side parses into
109
+ * `PolicyJSON` (CONTRACT-POLICY).
110
+ *
111
+ * @example
112
+ * import { policy } from "@palbase/backend";
113
+ *
114
+ * policy("owner_select")
115
+ * .for("select")
116
+ * .to("authenticated")
117
+ * .using("owner = (select auth.uid())");
118
+ */
119
+ /** The SQL command a policy applies to. `"all"` covers SELECT/INSERT/UPDATE/DELETE. */
120
+ type PolicyCommand = "all" | "select" | "insert" | "update" | "delete";
121
+ /** Whether a policy is permissive (OR-combined, the default) or restrictive
122
+ * (AND-combined). Mirrors Postgres `CREATE POLICY ... AS PERMISSIVE|RESTRICTIVE`. */
123
+ type PolicyMode = "permissive" | "restrictive";
124
+ /**
125
+ * The compiled, serializable policy definition — the EXACT shape consumed by
126
+ * `schema_extract.js` → Go `PolicyJSON` (CONTRACT-POLICY).
127
+ *
128
+ * - `roles`: the DB roles this policy applies to (`TO` clause). An empty array
129
+ * means the policy applies to PUBLIC (all roles) — the Postgres default.
130
+ * - `using`: the `USING (...)` row-visibility expression, or `null` when none.
131
+ * - `withCheck`: the `WITH CHECK (...)` write-validation expression, or `null`.
132
+ * - `permissive`: `true` for `AS PERMISSIVE` (default), `false` for restrictive.
133
+ */
134
+ interface PolicyDef {
135
+ name: string;
136
+ command: PolicyCommand;
137
+ roles: string[];
138
+ using: string | null;
139
+ withCheck: string | null;
140
+ permissive: boolean;
141
+ }
142
+ /**
143
+ * Fluent RLS policy builder.
144
+ *
145
+ * Defaults (documented, applied at construction):
146
+ * - `command`: `"all"` — applies to every SQL command unless `.for(...)` narrows it.
147
+ * - `roles`: `["authenticated"]` — the common case is "rule applies to signed-in
148
+ * users". Call `.to(...)` to override; pass `.to()` with no roles (or never
149
+ * call it after a reset) to target PUBLIC.
150
+ * - `using` / `withCheck`: `null` — no row filter / write check until set.
151
+ * - `permissive`: `true` — `AS PERMISSIVE` (policies OR together).
152
+ *
153
+ * Each method mutates `_def` in place and returns `this`, so the chain is a
154
+ * single builder instance (no per-call allocation, like a tagged-template
155
+ * compile target). The terminal `PolicyDef` is read directly off `_def` by
156
+ * `schema_extract.js`.
157
+ */
158
+ declare class PolicyBuilder {
159
+ readonly _def: PolicyDef;
160
+ constructor(name: string);
161
+ /** Restrict the policy to a single SQL command (default `"all"`). */
162
+ for(command: PolicyCommand): this;
163
+ /**
164
+ * Set the DB roles the policy applies to (the `TO` clause), replacing any
165
+ * previously-set roles. Call with no arguments to target PUBLIC (all roles).
166
+ *
167
+ * @example
168
+ * policy("p").to("authenticated")
169
+ * policy("p").to("authenticated", "service_role")
170
+ * policy("p").to() // PUBLIC
171
+ */
172
+ to(...roles: string[]): this;
173
+ /** Set the `USING (...)` row-visibility expression (raw SQL). */
174
+ using(sqlExpr: string): this;
175
+ /** Set the `WITH CHECK (...)` write-validation expression (raw SQL). */
176
+ withCheck(sqlExpr: string): this;
177
+ /** Set the policy mode: `"permissive"` (default, OR-combined) or
178
+ * `"restrictive"` (AND-combined). */
179
+ as(mode: PolicyMode): this;
180
+ }
181
+ /**
182
+ * Start authoring an RLS policy. Returns a {@link PolicyBuilder}; the resulting
183
+ * `PolicyBuilder` is accepted directly in a table's `policies: [...]` array
184
+ * (its `_def` is read at schema-extract time).
185
+ *
186
+ * @param name The policy name. Palbase reconciliation keys policies by
187
+ * `(table, name)`, so names must be unique per table.
188
+ */
189
+ declare function policy(name: string): PolicyBuilder;
190
+
191
+ /**
192
+ * Postgres extensions a Palbase project can enable from its schema.
193
+ *
194
+ * Extensions are config-as-code: declare them in `defineSchema({ extensions })`
195
+ * and the deploy installs them (CREATE EXTENSION … SCHEMA extensions) using the
196
+ * deploy path's privileged connection. They are NOT toggled live from Studio —
197
+ * CREATE EXTENSION requires a superuser role that only the deploy path holds.
198
+ *
199
+ * The list is an allowlist (a string-literal union) so editors autocomplete the
200
+ * supported names and a typo fails typecheck. It is intentionally extensible:
201
+ * add a name here (+ confirm the base image ships it) to support more.
202
+ */
203
+ declare const PALBASE_EXTENSIONS: readonly ["vector", "pg_trgm", "unaccent", "citext", "postgis", "cube", "earthdistance", "hstore", "ltree", "pg_cron", "pgcrypto", "uuid-ossp"];
204
+ /** A Postgres extension supported by Palbase (allowlist union). */
205
+ type PalbaseExtension = (typeof PALBASE_EXTENSIONS)[number];
206
+ /**
207
+ * Extensions that depend on another extension. The deploy installs
208
+ * dependencies first; declaring `earthdistance` without `cube` still works
209
+ * because the deploy resolves the order, but listing both is clearer.
210
+ */
211
+ declare const EXTENSION_DEPENDENCIES: Partial<Record<PalbaseExtension, PalbaseExtension[]>>;
212
+ /** Runtime guard: is `name` a supported Palbase extension? */
213
+ declare function isPalbaseExtension(name: string): name is PalbaseExtension;
214
+
215
+ /**
216
+ * A map of column builders keyed by column name — the value you write under
217
+ * the `columns` key of `defineSchema({ tables: { <name>: { columns } } })`.
218
+ *
219
+ * The default `Record<string, ColumnBuilder>` keeps bare references compiling
220
+ * without a type argument.
221
+ */
222
+ type ColumnMap = Record<string, ColumnBuilder>;
223
+ /**
224
+ * The author-facing value written under each table key:
225
+ * `{ columns, rls?, policies? }`.
226
+ *
227
+ * - `columns`: the column map (required).
228
+ * - `rls`: enable + FORCE row-level security on this table. Implied when
229
+ * `policies` is non-empty; set it explicitly to enable RLS with no policies
230
+ * yet (deny-all — useful only as an intermediate step).
231
+ * - `policies`: the RLS policies for this table, authored with `policy(name)`.
232
+ * Each entry may be a {@link PolicyBuilder} (the normal `policy(...)` chain)
233
+ * or a raw {@link PolicyDef} object.
234
+ *
235
+ * The `C` type parameter preserves the precise per-column phantom types so the
236
+ * typed `Database.tables.*` surface keeps inferring insert/row shapes.
237
+ */
238
+ interface TableInput<C extends ColumnMap = ColumnMap> {
239
+ columns: C;
240
+ rls?: boolean;
241
+ policies?: (PolicyBuilder | PolicyDef)[];
242
+ }
243
+ /**
244
+ * A table definition — the runtime value the Go runtime's `schema_extract.js`
245
+ * reads. It keys tables by `tableDef.name`, reads `tableDef.columns` for the
246
+ * column DDL, and `tableDef.rls` + `tableDef.policies` for RLS.
247
+ *
248
+ * `defineSchema` derives `name` from the object key, so authors never repeat
249
+ * the table name. `rls`/`policies` are always present after normalization
250
+ * (defaulted to `false`/`[]`).
251
+ *
252
+ * The `C` type parameter preserves the precise per-column phantom types so that
253
+ * downstream mapped types (InsertShape, RowShape) can discriminate on them.
254
+ */
255
+ interface TableDef<C extends ColumnMap = ColumnMap> {
256
+ name: string;
257
+ columns: C;
258
+ rls: boolean;
259
+ policies: PolicyDef[];
260
+ }
261
+ /**
262
+ * A schema definition containing multiple tables, keyed by table name.
263
+ *
264
+ * The `T` type parameter preserves the exact `TableDef<...>` type for each
265
+ * table so that `SchemaDef["tables"]["rooms"]` resolves to the precise
266
+ * `TableDef<{ id: ColumnBuilder<'uuid', false, true, never>; ... }>`.
267
+ */
268
+ interface SchemaDef<T extends Record<string, TableDef> = Record<string, TableDef>> {
269
+ tables: T;
270
+ /** Postgres extensions to install on deploy. Normalized to `[]` when absent. */
271
+ extensions: PalbaseExtension[];
272
+ }
273
+ /** The author-facing input to `defineSchema` — a `tables` map whose keys are
274
+ * the table names and whose values are `{ columns, rls?, policies? }`, plus an
275
+ * optional `extensions` allowlist. */
276
+ interface SchemaInput<T extends Record<string, TableInput> = Record<string, TableInput>> {
277
+ tables: T;
278
+ /**
279
+ * Postgres extensions to enable for this project, e.g. `["vector"]`.
280
+ * Config-as-code: installed by the deploy (CREATE EXTENSION … SCHEMA
281
+ * extensions) with the privileged deploy connection. The type is an
282
+ * allowlist union, so unsupported names fail typecheck.
283
+ */
284
+ extensions?: PalbaseExtension[];
285
+ }
286
+ /** Map the author's `{ tables: { <name>: { columns } } }` input to the
287
+ * `{ tables: { <name>: TableDef<columns> } }` runtime/type shape, threading the
288
+ * per-table column map `T[K]["columns"]` so column-level inference survives. */
289
+ type TablesFromInput<T extends Record<string, TableInput>> = {
290
+ [K in keyof T]: TableDef<T[K]["columns"]>;
291
+ };
292
+ /**
293
+ * Define a schema. The table NAME comes from the object key. Each table value
294
+ * is `{ columns, rls?, policies? }`:
295
+ *
296
+ * export default defineSchema({
297
+ * tables: {
298
+ * todos: {
299
+ * columns: {
300
+ * id: uuid().primaryKey().defaultRandom(),
301
+ * owner: text().notNull(),
302
+ * title: text().notNull(),
303
+ * },
304
+ * rls: true,
305
+ * policies: [
306
+ * policy("owner_all").for("all").to("authenticated")
307
+ * .using("owner = (select auth.uid())")
308
+ * .withCheck("owner = (select auth.uid())"),
309
+ * ],
310
+ * },
311
+ * },
312
+ * });
313
+ *
314
+ * The returned value is
315
+ * `{ tables: { todos: { name, columns, rls, policies } } }` — the exact shape
316
+ * the runtime schema extractor parses. Per-column phantom types are preserved
317
+ * so `Database.tables.todos.insert({...})` stays typed.
318
+ *
319
+ * RLS normalization: `rls` defaults to `false`, `policies` to `[]`. When
320
+ * `policies` is non-empty, `rls` is forced on (ENABLE + FORCE) regardless of
321
+ * the declared `rls` flag — a table with policies must have RLS enabled or the
322
+ * policies would be inert.
323
+ */
324
+ declare function defineSchema<T extends Record<string, TableInput>>(input: SchemaInput<T>): SchemaDef<TablesFromInput<T>>;
325
+
326
+ /**
327
+ * typed-db.ts — Task 2: TypedDB schema-derived insert/row shapes.
328
+ *
329
+ * Derives INSERT and full-row TypeScript types from a `defineSchema()` result
330
+ * and wraps the untyped runtime `DBClient` with a typed facade.
331
+ *
332
+ * No value-any. No `as unknown as X`. The two narrow `as` casts in
333
+ * `makeTypedTable` are safe because:
334
+ * - `data as Record<string, unknown>`: InsertShape<T> maps string keys to
335
+ * typed values; all value types are subsets of `unknown`, so the cast is
336
+ * structurally sound.
337
+ * - `result as RowShape<T>`: The runtime DBClient returns `Record<string,
338
+ * unknown>` which is the erased form of the typed row; we're narrowing back
339
+ * to the precise shape that the schema declared.
340
+ * Both casts are narrowing only (not widening) and correctness is guaranteed
341
+ * by the schema the caller provides.
342
+ */
343
+
344
+ /** Keys of C whose columns are required on INSERT (not nullable, no default). */
345
+ type RequiredKeys<C> = {
346
+ [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? never : K;
347
+ }[keyof C];
348
+ /** Keys of C whose columns are optional on INSERT (nullable or has a default). */
349
+ type OptionalKeys<C> = {
350
+ [K in keyof C]: ColIsOptionalOnInsert<C[K]> extends true ? K : never;
351
+ }[keyof C];
352
+ /**
353
+ * The TypeScript type for an INSERT payload for table `T`.
354
+ * - Required: columns that are NOT NULL and have no DB-level default.
355
+ * - Optional: columns that are nullable or carry a default.
356
+ *
357
+ * When all columns are optional, `RequiredKeys<C>` resolves to `never` and
358
+ * the first part becomes `{}`, which is a neutral element for `&`.
359
+ */
360
+ type InsertShape<T extends TableDef> = {
361
+ [K in RequiredKeys<T["columns"]>]: ColValue<T["columns"][K]>;
362
+ } & {
363
+ [K in OptionalKeys<T["columns"]>]?: ColValue<T["columns"][K]>;
364
+ };
365
+ /**
366
+ * The TypeScript type for a full row returned by the DB for table `T`.
367
+ * Every column is present; nullable columns resolve to `T | null`.
368
+ */
369
+ type RowShape<T extends TableDef> = {
370
+ [K in keyof T["columns"]]: ColValue<T["columns"][K]>;
371
+ };
372
+ /** A typed table accessor that mirrors the runtime DBClient surface. */
373
+ interface TypedTable<T extends TableDef> {
374
+ insert(data: InsertShape<T>): Promise<RowShape<T>>;
375
+ update(id: string, data: Partial<InsertShape<T>>): Promise<RowShape<T>>;
376
+ delete(id: string): Promise<void>;
377
+ findById(id: string): Promise<RowShape<T> | null>;
378
+ findMany(query?: Partial<RowShape<T>>): Promise<RowShape<T>[]>;
379
+ }
380
+ /** A typed DB facade covering all tables declared in schema `S`. */
381
+ interface TypedDB<S extends SchemaDef> {
382
+ tables: {
383
+ [K in keyof S["tables"]]: TypedTable<S["tables"][K]>;
384
+ };
385
+ transaction<T>(fn: (tx: TypedTx<S>) => Promise<T>): Promise<T>;
386
+ }
387
+ /** Transaction-scoped typed facade: same typed tables, no nested transaction. */
388
+ interface TypedTx<S extends SchemaDef> {
389
+ tables: {
390
+ [K in keyof S["tables"]]: TypedTable<S["tables"][K]>;
391
+ };
392
+ }
393
+ /**
394
+ * Wraps a raw `DBClient` with the type-safe `TypedDB<S>` facade derived from
395
+ * the provided schema. No behavior change — all calls delegate to `raw` with
396
+ * the table name as a plain string.
397
+ *
398
+ * `buildTables` is the reusable factory that wraps any op-bearing client
399
+ * (`TxClient` — the surface shared by `DBClient` and the transaction-scoped
400
+ * client) into the typed tables map. It is used both for the top-level db
401
+ * (wrapping `raw`) and inside `transaction`, where it wraps the raw `TxClient`
402
+ * the runtime yields so the callback sees the same typed `.tables` API.
403
+ *
404
+ * `transaction` delegates straight to `raw.transaction`; the two narrow
405
+ * `as TypedTx<S>` / `as TypedDB<S>` casts are single structural narrowings
406
+ * from the dynamically-built tables object to the precise mapped type (TS
407
+ * cannot infer through `Object.keys` iteration) — see module-level doc comment.
408
+ */
409
+ declare function makeTypedDB<S extends SchemaDef>(schema: S, raw: DBClient): TypedDB<S>;
410
+ /** A typed table accessor derived from one env `Tables` entry's flat shapes. */
411
+ interface EnvTypedTable<T extends TableTypes> {
412
+ insert(data: T["insert"]): Promise<T["row"]>;
413
+ update(id: string, data: Partial<T["insert"]>): Promise<T["row"]>;
414
+ delete(id: string): Promise<void>;
415
+ findById(id: string): Promise<T["row"] | null>;
416
+ findMany(query?: Partial<T["row"]>): Promise<T["row"][]>;
417
+ }
418
+ /** The `tables` map exposed on `Database`/`tx`, keyed by the env `Tables`
419
+ * interface. When no schema is declared `Tables` is empty, so `tables` is an
420
+ * empty object — accessing `.tables.foo` is then a compile error (no member). */
421
+ type EnvTables = {
422
+ [K in keyof Tables]: EnvTypedTable<Tables[K]>;
423
+ };
424
+ /** Transaction-scoped typed facade for the env-augmented surface: same typed
425
+ * tables, no nested transaction. */
426
+ interface EnvTypedTx {
427
+ tables: EnvTables;
428
+ }
429
+ /**
430
+ * The RLS-bypass sibling returned by `Database.asService()`. Same typed surface
431
+ * as {@link EnvTypedDatabase} — `tables`, the raw string ops, and a typed
432
+ * `transaction` — but it does NOT re-expose `asService` (no double-bypass).
433
+ * Every op it performs runs as the `service_role` (BYPASSRLS).
434
+ */
435
+ interface EnvServiceDatabase extends Omit<DBClient, "transaction" | "asService"> {
436
+ tables: EnvTables;
437
+ transaction<T>(fn: (tx: EnvTypedTx) => Promise<T>): Promise<T>;
438
+ }
439
+ /**
440
+ * The typed-by-default Database surface: the raw string-keyed `DBClient` ops
441
+ * PLUS a `tables` map typed against the project's generated `palbase-env.d.ts`,
442
+ * a `transaction` whose callback receives the typed tables, and `asService()`
443
+ * for the explicit RLS-bypass sibling.
444
+ *
445
+ * `transaction` is declared here (overriding `DBClient["transaction"]`) so the
446
+ * `tx` the callback receives carries the typed `.tables` API. `asService` is
447
+ * re-typed to return the typed {@link EnvServiceDatabase} sibling.
448
+ */
449
+ interface EnvTypedDatabase extends Omit<DBClient, "transaction" | "asService"> {
450
+ tables: EnvTables;
451
+ transaction<T>(fn: (tx: EnvTypedTx) => Promise<T>): Promise<T>;
452
+ /**
453
+ * Return a sibling that bypasses RLS by running as the `service_role`. Use
454
+ * sparingly and explicitly — the default `Database.*` path is RLS-enforced.
455
+ *
456
+ * @example
457
+ * const all = await Database.asService().tables.todos.findMany({});
458
+ * const rows = await Database.asService().query("SELECT * FROM todos");
459
+ */
460
+ asService(): EnvServiceDatabase;
461
+ }
462
+
463
+ export { text as A, timestamp as B, ColumnBuilder as C, uuid as D, type EnvTypedDatabase as E, type InsertShape as I, type OnDeleteAction as O, PALBASE_EXTENSIONS as P, type RowShape as R, type SchemaDef as S, type TableDef as T, type ColumnDef as a, type ColumnMap as b, type ColumnType as c, EXTENSION_DEPENDENCIES as d, type EnvServiceDatabase as e, type EnvTables as f, type EnvTypedTable as g, type EnvTypedTx as h, type PalbaseExtension as i, PolicyBuilder as j, type PolicyCommand as k, type PolicyDef as l, type PolicyMode as m, type SchemaInput as n, type TableInput as o, type TypedDB as p, type TypedTable as q, type TypedTx as r, boolean as s, defineSchema as t, enumType as u, integer as v, isPalbaseExtension as w, jsonb as x, makeTypedDB as y, policy as z };