@palbase/backend 25.1.0 → 27.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 (104) hide show
  1. package/dist/bin/palbase-backend.cjs +2401 -1039
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +87 -51
  4. package/dist/bin/palbase-backend.js.map +1 -1
  5. package/dist/chunk-CGNN2PUH.js +213 -0
  6. package/dist/chunk-CGNN2PUH.js.map +1 -0
  7. package/dist/chunk-DRZFQRJI.js +370 -0
  8. package/dist/chunk-DRZFQRJI.js.map +1 -0
  9. package/dist/chunk-GYK6QYS4.js +708 -0
  10. package/dist/chunk-GYK6QYS4.js.map +1 -0
  11. package/dist/chunk-I3C4PFIW.js +930 -0
  12. package/dist/chunk-I3C4PFIW.js.map +1 -0
  13. package/dist/{chunk-VDF2T4AS.js → chunk-OO7R25AI.js} +1213 -591
  14. package/dist/chunk-OO7R25AI.js.map +1 -0
  15. package/dist/chunk-TS4U7NBD.js +885 -0
  16. package/dist/chunk-TS4U7NBD.js.map +1 -0
  17. package/dist/{chunk-YOY5DFQS.js → chunk-TWX6JTGJ.js} +76 -34
  18. package/dist/{chunk-YOY5DFQS.js.map → chunk-TWX6JTGJ.js.map} +1 -1
  19. package/dist/{chunk-35PNTIRN.js → chunk-VVMJEVQP.js} +63 -162
  20. package/dist/chunk-VVMJEVQP.js.map +1 -0
  21. package/dist/{chunk-7D4SUZUM.js → chunk-VXPNPVAG.js} +3 -1
  22. package/dist/db/env.cjs.map +1 -1
  23. package/dist/db/env.d.cts +2 -2
  24. package/dist/db/env.d.ts +2 -2
  25. package/dist/db/index.cjs +754 -344
  26. package/dist/db/index.cjs.map +1 -1
  27. package/dist/db/index.d.cts +2 -2
  28. package/dist/db/index.d.ts +2 -2
  29. package/dist/db/index.js +7 -4
  30. package/dist/engine/index.cjs +2339 -1006
  31. package/dist/engine/index.cjs.map +1 -1
  32. package/dist/engine/index.d.cts +6 -6
  33. package/dist/engine/index.d.ts +6 -6
  34. package/dist/engine/index.js +7 -6
  35. package/dist/index-BrvvxSpn.d.ts +4844 -0
  36. package/dist/index-Bve7BBTL.d.cts +4844 -0
  37. package/dist/{index-CUomTA3e.d.ts → index-NuzRCuxe.d.ts} +171 -296
  38. package/dist/{index-ClpDeSos.d.cts → index-VtToZmUm.d.cts} +171 -296
  39. package/dist/index.cjs +2694 -1169
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +165 -19
  42. package/dist/index.d.ts +165 -19
  43. package/dist/index.js +738 -477
  44. package/dist/index.js.map +1 -1
  45. package/dist/module-Dl1KFVtc.d.cts +54 -0
  46. package/dist/module-Dl1KFVtc.d.ts +54 -0
  47. package/dist/openapi/index.cjs +1330 -484
  48. package/dist/openapi/index.cjs.map +1 -1
  49. package/dist/openapi/index.d.cts +4 -2
  50. package/dist/openapi/index.d.ts +4 -2
  51. package/dist/openapi/index.js +1264 -474
  52. package/dist/openapi/index.js.map +1 -1
  53. package/dist/{registry-dZZ5JKYg.d.ts → registry-B0eyOF9x.d.ts} +1 -1
  54. package/dist/{registry-CC0WBQq6.d.cts → registry-Bk9_rbNd.d.cts} +1 -1
  55. package/dist/stack.cjs.map +1 -1
  56. package/dist/test/index.cjs +705 -141
  57. package/dist/test/index.cjs.map +1 -1
  58. package/dist/test/index.d.cts +30 -4
  59. package/dist/test/index.d.ts +30 -4
  60. package/dist/test/index.js +472 -124
  61. package/dist/test/index.js.map +1 -1
  62. package/docs/README.md +33 -18
  63. package/docs/auth.md +1 -1
  64. package/docs/background.md +2 -2
  65. package/docs/database.md +221 -50
  66. package/docs/endpoints.md +3 -4
  67. package/docs/events.md +3 -3
  68. package/docs/getting-started.md +1 -1
  69. package/docs/llms-full.txt +401 -117
  70. package/docs/migrations.md +2 -2
  71. package/docs/schema.md +19 -10
  72. package/docs/services.md +116 -26
  73. package/package.json +8 -4
  74. package/stager/generics.js +205 -0
  75. package/stager/stage.js +39 -3
  76. package/template/AGENTS.md +110 -72
  77. package/template/db/public.ts +1 -1
  78. package/template/{controllers → modules/health}/health.controller.ts +1 -1
  79. package/template/modules/health/health.module.ts +24 -0
  80. package/template/modules/notes/note.service.test.ts +49 -0
  81. package/template/modules/notes/note.service.ts +108 -0
  82. package/template/{controllers → modules/notes}/notes.controller.ts +17 -11
  83. package/template/modules/notes/notes.module.ts +37 -0
  84. package/template/package.json +5 -3
  85. package/template/scripts/test.sh +33 -0
  86. package/template/tsconfig.json +29 -30
  87. package/dist/chunk-35PNTIRN.js.map +0 -1
  88. package/dist/chunk-CJSKYY76.js +0 -627
  89. package/dist/chunk-CJSKYY76.js.map +0 -1
  90. package/dist/chunk-CRQKCRGF.js +0 -276
  91. package/dist/chunk-CRQKCRGF.js.map +0 -1
  92. package/dist/chunk-G4R6BTLV.js +0 -662
  93. package/dist/chunk-G4R6BTLV.js.map +0 -1
  94. package/dist/chunk-VDF2T4AS.js.map +0 -1
  95. package/dist/chunk-XABBC7JP.js +0 -55
  96. package/dist/chunk-XABBC7JP.js.map +0 -1
  97. package/dist/endpoint-CTEHhb7A.d.ts +0 -2386
  98. package/dist/endpoint-DYHMo6cC.d.cts +0 -2386
  99. package/dist/index-CW21M9Z3.d.ts +0 -1222
  100. package/dist/index-CmBK76nx.d.cts +0 -1222
  101. package/template/services/note.service.test.ts +0 -45
  102. package/template/services/note.service.ts +0 -76
  103. /package/dist/{chunk-7D4SUZUM.js.map → chunk-VXPNPVAG.js.map} +0 -0
  104. /package/template/{models/notes → modules/notes/dto}/create.ts +0 -0
@@ -1,662 +0,0 @@
1
- import {
2
- TxPlanBuilder,
3
- qualifiedTableKey,
4
- runTxPlan
5
- } from "./chunk-CJSKYY76.js";
6
-
7
- // src/db/policy.ts
8
- function quote(name) {
9
- return `"${name.replace(/"/g, '""')}"`;
10
- }
11
- var PolicyBuilder = class {
12
- _def;
13
- constructor(name) {
14
- this._def = {
15
- name,
16
- command: "all",
17
- roles: ["authenticated"],
18
- using: null,
19
- withCheck: null,
20
- permissive: true
21
- };
22
- }
23
- /** Restrict the policy to a single SQL command (default `"all"`). */
24
- for(command) {
25
- this._def.command = command;
26
- return this;
27
- }
28
- /**
29
- * Set the DB roles the policy applies to (the `TO` clause), replacing any
30
- * previously-set roles. Call with no arguments to target PUBLIC (all roles).
31
- *
32
- * @example
33
- * policy("p").to("authenticated")
34
- * policy("p").to("authenticated", "service_role")
35
- * policy("p").to() // PUBLIC
36
- */
37
- to(...roles) {
38
- this._def.roles = roles;
39
- return this;
40
- }
41
- /** Set the `USING (...)` row-visibility expression (raw SQL). */
42
- using(sqlExpr) {
43
- this._def.using = sqlExpr;
44
- return this;
45
- }
46
- /**
47
- * "Rows of THIS table whose owner the caller is a member of" — the membership
48
- * pattern, written so it cannot recurse.
49
- *
50
- * THE TRAP IT EXISTS FOR. Written by hand, membership policies point at each
51
- * other: `channels` is visible to members, so its policy reads
52
- * `channel_members`; `channel_members` is visible to members, so its policy
53
- * reads `channels`. Postgres refuses the pair at query time with `infinite
54
- * recursion detected in policy for relation ...`, and the error names the
55
- * relation but not the cycle. The way out is asymmetry — the MEMBERSHIP table
56
- * is protected by `user_id = auth.uid()` and nothing else, and every other
57
- * table subqueries INTO it. That shape was in the platform's own schema and
58
- * written down nowhere; a customer recovered it by reading that schema.
59
- *
60
- * `(select auth.uid())` rather than a bare call: the scalar subquery is
61
- * evaluated ONCE per statement instead of per row.
62
- *
63
- * @example
64
- * // channels: visible to members. The membership table gets the simple one.
65
- * policy("member_read").for("select").to("authenticated")
66
- * .memberOf("channel_members", "channel_id")
67
- * // → id IN (SELECT "channel_id" FROM "channel_members"
68
- * // WHERE "user_id" = (select auth.uid()))
69
- */
70
- memberOf(membershipTable, foreignKey, options = {}) {
71
- if (this._def.using !== null) {
72
- throw new Error(
73
- `policy(${this._def.name}).memberOf(): this policy already has a using() expression. Write one or the other \u2014 memberOf IS the using expression.`
74
- );
75
- }
76
- const column = options.column ?? "id";
77
- const userColumn = options.userColumn ?? "user_id";
78
- this._def.using = `${quote(column)} IN (SELECT ${quote(foreignKey)} FROM ${quote(membershipTable)} WHERE ${quote(userColumn)} = (select auth.uid()))`;
79
- return this;
80
- }
81
- /** Set the `WITH CHECK (...)` write-validation expression (raw SQL). */
82
- withCheck(sqlExpr) {
83
- this._def.withCheck = sqlExpr;
84
- return this;
85
- }
86
- /** Set the policy mode: `"permissive"` (default, OR-combined) or
87
- * `"restrictive"` (AND-combined). */
88
- as(mode) {
89
- this._def.permissive = mode === "permissive";
90
- return this;
91
- }
92
- };
93
- function policy(name) {
94
- return new PolicyBuilder(name);
95
- }
96
-
97
- // src/db/schema.ts
98
- function toPolicyDef(p) {
99
- return p instanceof PolicyBuilder ? p._def : p;
100
- }
101
- var TABLE_META = /* @__PURE__ */ Symbol.for("palbase.table.meta");
102
- function defineTable(name, input) {
103
- if (name.trim() === "") {
104
- throw new Error("defineTable(name, \u2026): name must not be empty");
105
- }
106
- const policies = (input.policies ?? []).map(toPolicyDef);
107
- const rls = policies.length > 0 || input.rls !== false;
108
- const owned = {};
109
- for (const [colName, b] of Object.entries(input.columns)) {
110
- const builder = b;
111
- const clone = Object.create(Object.getPrototypeOf(builder));
112
- Object.defineProperty(clone, "_def", { value: { ...builder._def }, enumerable: true, writable: true });
113
- owned[colName] = clone;
114
- }
115
- const def = {
116
- name,
117
- columns: owned,
118
- rls,
119
- policies
120
- };
121
- if (input.primaryKey !== void 0) def.primaryKey = input.primaryKey;
122
- if (input.unique !== void 0) def.unique = input.unique;
123
- if (input.raw !== void 0 && input.raw.length > 0) def.raw = input.raw.slice();
124
- if (input.checks !== void 0 && input.checks.length > 0) def.checks = input.checks.slice();
125
- if (input.indexes !== void 0 && input.indexes.length > 0) def.indexes = input.indexes.slice();
126
- if (input.search !== void 0) {
127
- const s = input.search;
128
- if (s.from !== void 0) {
129
- if (s.vector !== void 0) {
130
- throw new Error(
131
- `table ${name}: search beyan\u0131nda tek bi\xE7im kullan\u0131n \u2014 'from' (yeni) ile 'vector' (eski) birlikte olamaz`
132
- );
133
- }
134
- if (s.from.length === 0) {
135
- throw new Error(`table ${name}: search.from bo\u015F olamaz`);
136
- }
137
- if (s.model === void 0) {
138
- throw new Error(
139
- `table ${name}: search.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin (BYO i\xE7in eski 'vector' bi\xE7imini kullan\u0131n)`
140
- );
141
- }
142
- if (Array.isArray(s.text) && s.text.length === 0) {
143
- throw new Error(`table ${name}: search.text bo\u015F dizi olamaz \u2014 FTS istemiyorsan text: false yaz\u0131n`);
144
- }
145
- } else {
146
- if (typeof s.text === "boolean") {
147
- throw new Error(`table ${name}: text:${String(s.text)} yaln\u0131z yeni bi\xE7imde ('from' ile) ge\xE7erli`);
148
- }
149
- if (s.text === void 0 && s.vector === void 0) {
150
- throw new Error(
151
- `table ${name}: search beyan\u0131 bo\u015F \u2014 en az bir kol (text ya da vector) verin, yoksa alan\u0131 hi\xE7 yazmay\u0131n`
152
- );
153
- }
154
- if (s.text !== void 0 && s.text.length === 0) {
155
- throw new Error(`table ${name}: search.text bo\u015F olamaz \u2014 FTS kolu istemiyorsan alan\u0131 hi\xE7 yazma`);
156
- }
157
- const legs = s.vector === void 0 ? [] : Array.isArray(s.vector) ? s.vector : [s.vector];
158
- for (const leg of legs) {
159
- if (leg.model !== void 0 && (leg.from === void 0 || leg.from.length === 0)) {
160
- throw new Error(`table ${name}: search.vector.model beyan edildi ama 'from' yok \u2014 embed kayna\u011F\u0131 kolonlar zorunlu (C-2)`);
161
- }
162
- if (leg.model === void 0 && leg.from !== void 0) {
163
- throw new Error(`table ${name}: search.vector.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin`);
164
- }
165
- }
166
- }
167
- def.search = s;
168
- }
169
- if (input.memory !== void 0) {
170
- if (input.memory.from.length === 0) {
171
- throw new Error(`table ${name}: memory.from bo\u015F olamaz`);
172
- }
173
- def.memory = input.memory;
174
- }
175
- for (const b of Object.values(owned)) {
176
- b._def.ownerTable = def;
177
- }
178
- const handle = { ...owned };
179
- Object.defineProperty(handle, TABLE_META, { value: def, enumerable: false });
180
- return handle;
181
- }
182
- var declaringSchemaOf = /* @__PURE__ */ new WeakMap();
183
- function resolveReferences(tables, schemaName) {
184
- for (const table of Object.values(tables)) {
185
- for (const [colName, builder] of Object.entries(table.columns)) {
186
- const def = builder._def;
187
- if (def.selfRefColumn !== void 0) {
188
- if (!(def.selfRefColumn in table.columns)) {
189
- throw new Error(
190
- `table "${table.name}" column "${colName}": selfReferences("${def.selfRefColumn}") \u2014 no such column on this table`
191
- );
192
- }
193
- def.references = {
194
- table: qualifiedTableKey(schemaName, table.name),
195
- column: def.selfRefColumn
196
- };
197
- continue;
198
- }
199
- if (def.referencesThunk === void 0) continue;
200
- const target = def.referencesThunk();
201
- const owner = target?._def?.ownerTable;
202
- if (owner === void 0) {
203
- throw new Error(
204
- `table "${table.name}" column "${colName}": references(() => \u2026) must point at a column of a table declared with defineTable(...)`
205
- );
206
- }
207
- const targetColumn = Object.entries(owner.columns).find(
208
- ([, b]) => b._def === target._def
209
- )?.[0];
210
- if (targetColumn === void 0) {
211
- throw new Error(
212
- `table "${table.name}" column "${colName}": the referenced column was not found on table "${owner.name}"`
213
- );
214
- }
215
- const targetSchema = declaringSchemaOf.get(owner);
216
- if (targetSchema === void 0) {
217
- throw new Error(
218
- `table "${table.name}" column "${colName}": references(() => \u2026) points at table "${owner.name}", which no defineSchema(...) has claimed yet \u2014 a foreign key cannot be written without its target's schema. Declare that table's schema first (one file per schema: db/public.ts, db/billing.ts \u2026, imported by this one).`
219
- );
220
- }
221
- def.references = {
222
- table: qualifiedTableKey(targetSchema, owner.name),
223
- column: targetColumn
224
- };
225
- }
226
- }
227
- }
228
- function defineSchema(name, input) {
229
- if (typeof name !== "string") {
230
- throw new Error(
231
- `defineSchema(...) takes the schema NAME first: defineSchema("public", { tables: [todos, lists] }). The one-argument form defineSchema({ tables: { \u2026 } }) is gone \u2014 a schema that does not say its own name cannot be told apart from another schema's table of the same name, which is what a cross-schema foreign key has to do. Migrate db/public.ts (one file per schema: db/public.ts, db/billing.ts \u2026): name the schema, and lift each table key onto the table itself with defineTable("todos", { columns: { \u2026 } }), then list the tables in the array.`
232
- );
233
- }
234
- if (name.trim() === "") {
235
- throw new Error("defineSchema(name, \u2026): name must not be empty");
236
- }
237
- const tables = {};
238
- for (const handle of input.tables) {
239
- const table = handle[TABLE_META];
240
- if (tables[table.name] !== void 0) {
241
- throw new Error(
242
- `defineSchema("${name}"): two tables declare the name "${table.name}" \u2014 table names must be unique within a schema`
243
- );
244
- }
245
- tables[table.name] = table;
246
- declaringSchemaOf.set(table, name);
247
- }
248
- resolveReferences(tables, name);
249
- for (const [name2, def] of Object.entries(tables)) {
250
- const m = def.memory;
251
- if (m === void 0) continue;
252
- const target = Object.values(tables).find((t) => t.name === m.into);
253
- if (target === void 0) {
254
- throw new Error(`table ${name2}: memory.into "${m.into}" \u015Femada declared de\u011Fil`);
255
- }
256
- const subject = m.subject ?? "owner";
257
- if (!(subject in def.columns)) {
258
- throw new Error(`table ${name2}: memory.subject "${subject}" kolonu kaynak tabloda yok`);
259
- }
260
- if (!(subject in target.columns)) {
261
- throw new Error(`table ${name2}: memory.subject "${subject}" kolonu hedef "${m.into}" tablosunda yok`);
262
- }
263
- const factCol = target.columns["fact"];
264
- const factDef = factCol !== void 0 && "_def" in factCol ? factCol._def : factCol;
265
- if (factDef === void 0 || factDef.type !== "text") {
266
- throw new Error(`table ${name2}: memory.into "${m.into}" tablosunda "fact" (text) kolonu zorunlu`);
267
- }
268
- for (const c of m.from) {
269
- if (!(c in def.columns)) {
270
- throw new Error(`table ${name2}: memory.from kolonu "${c}" kaynak tabloda yok`);
271
- }
272
- }
273
- }
274
- const extensions = [...new Set(input.extensions ?? [])];
275
- return {
276
- name,
277
- tables,
278
- extensions,
279
- exposed: input.exposed ?? name === "public"
280
- };
281
- }
282
-
283
- // src/db/extensions.ts
284
- var PALBASE_EXTENSIONS = [
285
- // Search & text
286
- "vector",
287
- // pgvector: AI embeddings + vector similarity search (semantic search / RAG).
288
- // NB: the Postgres extension is named "vector", not "pgvector" — declare "vector".
289
- "pg_trgm",
290
- // trigram fuzzy / typo-tolerant text search
291
- "unaccent",
292
- // accent-insensitive text search
293
- "citext",
294
- // case-insensitive text type
295
- // Geospatial / location
296
- "cube",
297
- // multi-dimensional cubes (dependency of earthdistance)
298
- "earthdistance",
299
- // great-circle distance (needs cube)
300
- // Data types & structures
301
- "hstore",
302
- // key/value pairs in a single column
303
- "ltree",
304
- // hierarchical tree-structured labels
305
- // Indexing & constraints
306
- "btree_gist",
307
- // GiST operator classes for scalar types — needed for EXCLUDE
308
- // constraints that mix "=" with a range/&& overlap (e.g. no-double-booking).
309
- // Scheduling
310
- // Crypto / ids (also installed by default; listable for explicitness)
311
- "pgcrypto",
312
- // cryptographic functions (hashing, encryption)
313
- "uuid-ossp"
314
- // UUID generation functions
315
- ];
316
- var EXTENSION_DEPENDENCIES = {
317
- earthdistance: ["cube"]
318
- };
319
- function isPalbaseExtension(name) {
320
- return PALBASE_EXTENSIONS.includes(name);
321
- }
322
-
323
- // src/db/columns.ts
324
- function refuseOnVector(def, modifier) {
325
- if (def.type === "vector") {
326
- throw new Error(`vector column: .${modifier}() is not supported (FR-002 \u2014 allowed: nullable()/notNull())`);
327
- }
328
- }
329
- var ColumnBuilder = class _ColumnBuilder {
330
- _def;
331
- constructor(type, existingDef) {
332
- this._def = existingDef ?? {
333
- type,
334
- nullable: false,
335
- primaryKey: false
336
- };
337
- }
338
- /** Mark this column as the primary key. */
339
- primaryKey() {
340
- refuseOnVector(this._def, "primaryKey");
341
- this._def.primaryKey = true;
342
- return new _ColumnBuilder(this._def.type, this._def);
343
- }
344
- /** Mark this column as NOT NULL (default). */
345
- notNull() {
346
- this._def.nullable = false;
347
- return new _ColumnBuilder(this._def.type, this._def);
348
- }
349
- /** Allow NULL values. */
350
- nullable() {
351
- this._def.nullable = true;
352
- return new _ColumnBuilder(this._def.type, this._def);
353
- }
354
- /** Set a default value. */
355
- default(value) {
356
- refuseOnVector(this._def, "default");
357
- this._def.defaultValue = value;
358
- return new _ColumnBuilder(this._def.type, this._def);
359
- }
360
- /** UUID: generate a random default (gen_random_uuid()). */
361
- defaultRandom() {
362
- refuseOnVector(this._def, "defaultRandom");
363
- this._def.defaultRandom = true;
364
- return new _ColumnBuilder(this._def.type, this._def);
365
- }
366
- /** Timestamp: default to now(). */
367
- defaultNow() {
368
- refuseOnVector(this._def, "defaultNow");
369
- this._def.defaultNow = true;
370
- return new _ColumnBuilder(this._def.type, this._def);
371
- }
372
- /**
373
- * The DATABASE assigns this column's value — a trigger, a rule, an identity.
374
- *
375
- * The column becomes optional on INSERT (the author has nothing to send) while
376
- * the DDL stays free of a DEFAULT this schema would not honour. It is NOT
377
- * `default()`: that declares a value the schema promises to write.
378
- *
379
- * Naming: deliberately not `generated()`. Postgres has GENERATED columns and
380
- * they are a different thing; borrowing the word would send a reader — or a
381
- * model writing a schema — to the wrong feature.
382
- */
383
- dbAssigned() {
384
- this._def.dbAssigned = true;
385
- return new _ColumnBuilder(this._def.type, this._def);
386
- }
387
- /** Add a foreign key reference. */
388
- /**
389
- * Declares that this column used to be called `previous`.
390
- *
391
- * A schema diff sees one name gone and another present; it cannot know whether
392
- * you renamed a column or dropped one and added another, and the two are very
393
- * different — the second loses every value. Saying so here turns the plan into
394
- * `ALTER TABLE … RENAME COLUMN` instead.
395
- *
396
- * Once the rename has been applied the annotation is inert (the old name is no
397
- * longer there to rename), so it can be deleted at your leisure.
398
- */
399
- renamedFrom(previous) {
400
- this._def.renamedFrom = previous;
401
- return this;
402
- }
403
- /**
404
- * See {@link ColumnDef.ignored}.
405
- *
406
- * COPIES the def rather than mutating it. The constructor takes an existing
407
- * def BY REFERENCE, so every builder derived from another shares one object —
408
- * `const a = slug.unique()` leaves `a._def === slug._def`. An in-place
409
- * `ignored = true` therefore marks every column sharing that def, including
410
- * one another table actively reads, and the gate would let THAT column be
411
- * dropped. Measured before this copy existed.
412
- *
413
- * The aliasing is older than this method and other fields leak through it too.
414
- * The reason this one cannot wait: every other leak produces a VISIBLE schema
415
- * difference — the plan shows it, the DDL shows it. This one is invisible by
416
- * design (no DDL, no diff, no plan line), so its only effect is to disarm a
417
- * safety gate in silence.
418
- */
419
- ignored() {
420
- return new _ColumnBuilder(this._def.type, {
421
- ...this._def,
422
- ignored: true
423
- });
424
- }
425
- /**
426
- * Foreign key onto another table's column.
427
- *
428
- * The target is a THUNK, not a direct reference. In a cycle (`x → y`, `y → x`)
429
- * the second table does not exist yet when the first is built; a direct
430
- * reference makes TypeScript chase its own tail (TS7022 — measured, and making
431
- * the return type independent of the target does NOT help). The thunk is
432
- * invoked in `defineSchema`, where every binding exists and every table
433
- * already knows its name.
434
- *
435
- * In a cycle, ONE side needs an explicit return type:
436
- * `references((): AnyColumn => y.id)`. One side is enough — measured.
437
- * For a self-reference use `selfReferences(column)`: no thunk, no annotation.
438
- *
439
- * `as` names the FORWARD relation (`author_id` → `author` by default);
440
- * `reverseAs` names the REVERSE one on the parent, whose default is this
441
- * table's own name (`users.posts`). Two foreign keys from one table onto one
442
- * parent therefore need a `reverseAs` on at least one of them — the reverse
443
- * names would otherwise both be this table's name.
444
- */
445
- references(target, opts) {
446
- refuseOnVector(this._def, "references");
447
- if (typeof target !== "function") {
448
- throw new Error(
449
- `references(...) takes a callback: write references(() => otherTable.column). The two-string form references("table", "column") is gone \u2014 a string cannot be type-checked and cannot point at a table that does not exist yet.`
450
- );
451
- }
452
- this._def.referencesThunk = target;
453
- if (opts?.as !== void 0) this._def.refAs = opts.as;
454
- if (opts?.reverseAs !== void 0) this._def.reverseAs = opts.reverseAs;
455
- if (opts?.onDelete !== void 0) this._def.onDeleteAction = opts.onDelete;
456
- return new _ColumnBuilder(this._def.type, this._def);
457
- }
458
- /**
459
- * Foreign key onto THIS table (`parent_id → id`) — category trees, comment
460
- * replies, org charts.
461
- *
462
- * No thunk and no type annotation: the target table is the one being declared,
463
- * so there is nothing to defer and nothing for TypeScript to chase in a circle.
464
- * Drizzle forces an explicit `(): AnyPgColumn =>` here because its reference
465
- * always goes through a callback; measured, we do not need one.
466
- */
467
- selfReferences(column, opts) {
468
- refuseOnVector(this._def, "selfReferences");
469
- this._def.selfRefColumn = column;
470
- if (opts?.as !== void 0) this._def.refAs = opts.as;
471
- if (opts?.onDelete !== void 0) this._def.onDeleteAction = opts.onDelete;
472
- return new _ColumnBuilder(this._def.type, this._def);
473
- }
474
- /** Set the ON DELETE action for a foreign key reference. */
475
- onDelete(action) {
476
- this._def.onDeleteAction = action;
477
- return new _ColumnBuilder(this._def.type, this._def);
478
- }
479
- /** Add a single-column UNIQUE constraint. */
480
- unique() {
481
- refuseOnVector(this._def, "unique");
482
- this._def.unique = true;
483
- return new _ColumnBuilder(this._def.type, this._def);
484
- }
485
- /**
486
- * Declare how this column's value is projected in and out of the process.
487
- *
488
- * The DDL does not move: `numeric` stays `numeric`, and the driver still hands
489
- * back what Postgres sent. What changes is the type the row surface exposes —
490
- * it becomes `Target`:
491
- *
492
- * amount: numeric().transform<number>({ fromDb: Number, toDb: String })
493
- *
494
- * `numeric` surfacing as `string` is CORRECT (a JS number cannot hold
495
- * arbitrary precision), and that is exactly why this exists: application code
496
- * that does arithmetic on the column otherwise rewrites the same
497
- * `Number(row.amount)` / `String(x)` pair in every controller that touches it,
498
- * and each rewrite is a place the two directions can drift apart.
499
- *
500
- * A transform is a PROJECTION, never a constraint: it lives only in this
501
- * process, so it can neither validate nor migrate what is stored.
502
- */
503
- transform(fns) {
504
- this._def.transform = fns;
505
- return new _ColumnBuilder(this._def.type, this._def);
506
- }
507
- };
508
- function uuid() {
509
- return new ColumnBuilder("uuid");
510
- }
511
- function text() {
512
- return new ColumnBuilder("text");
513
- }
514
- function integer() {
515
- return new ColumnBuilder("integer");
516
- }
517
- function bigint() {
518
- return new ColumnBuilder("bigint");
519
- }
520
- function numeric() {
521
- return new ColumnBuilder("numeric");
522
- }
523
- function boolean() {
524
- return new ColumnBuilder("boolean");
525
- }
526
- function timestamp() {
527
- return new ColumnBuilder("timestamp");
528
- }
529
- function jsonb() {
530
- return new ColumnBuilder("jsonb");
531
- }
532
- function enumType(name, values) {
533
- const builder = new ColumnBuilder("enum");
534
- builder._def.enumName = name;
535
- builder._def.enumValues = [...values];
536
- return builder;
537
- }
538
- function vector(dimensions) {
539
- if (!Number.isInteger(dimensions) || dimensions < 1 || dimensions > 2e3) {
540
- throw new Error(`vector(): dimensions must be an integer in [1, 2000], got ${String(dimensions)}`);
541
- }
542
- const b = new ColumnBuilder("vector");
543
- b._def.dimensions = dimensions;
544
- return b;
545
- }
546
- function ownedByUser() {
547
- const b = new ColumnBuilder("text");
548
- b._def.nullable = false;
549
- b._def.references = { table: "auth.users", column: "id" };
550
- b._def.onDeleteAction = "cascade";
551
- b._def.owns = true;
552
- return b;
553
- }
554
- function userRef(opts) {
555
- const b = new ColumnBuilder("text");
556
- b._def.references = { table: "auth.users", column: "id" };
557
- b._def.onDeleteAction = opts.onDelete;
558
- if (opts.as !== void 0) b._def.refAs = opts.as;
559
- return b;
560
- }
561
- function installationRef(opts) {
562
- const b = new ColumnBuilder("text");
563
- b._def.references = { table: "auth.installations", column: "id" };
564
- b._def.onDeleteAction = opts.onDelete;
565
- if (opts.as !== void 0) b._def.refAs = opts.as;
566
- return b;
567
- }
568
-
569
- // src/db/raw.ts
570
- function raw(name, up, opts) {
571
- return { name, up, ...opts?.down != null ? { down: opts.down } : {} };
572
- }
573
-
574
- // src/db/embedding.ts
575
- var openai = {
576
- embedding(model, opts) {
577
- return {
578
- provider: "openai",
579
- model,
580
- apiKeyName: opts?.apiKeyName ?? "OPENAI_API_KEY",
581
- ...opts?.dimensions !== void 0 ? { dimensions: opts.dimensions } : {},
582
- ...opts?.baseURL !== void 0 ? { baseURL: opts.baseURL } : {}
583
- };
584
- },
585
- chat(model) {
586
- return { provider: "openai", model };
587
- }
588
- };
589
-
590
- // src/db/typed-db.ts
591
- function makeTypedTable(name, raw2) {
592
- return {
593
- insert: (data) => raw2.insert(name, data),
594
- upsert: (data, opts) => raw2.upsert(name, data, opts),
595
- update: (id, data) => raw2.update(name, id, data),
596
- delete: (id) => raw2.delete(name, id),
597
- findById: (id) => raw2.findById(name, id),
598
- findMany: (query, opts) => raw2.findMany(name, query, opts),
599
- updateMany: (where, set) => raw2.updateMany(
600
- name,
601
- where,
602
- set
603
- ),
604
- deleteMany: (where) => raw2.deleteMany(name, where),
605
- count: (where) => raw2.count(name, where)
606
- };
607
- }
608
- function makeTypedDB(schema, raw2) {
609
- const tables = {};
610
- for (const key of Object.keys(schema.tables)) {
611
- const tableDef = schema.tables[key];
612
- if (tableDef !== void 0) {
613
- tables[key] = makeTypedTable(tableDef.name, raw2);
614
- }
615
- }
616
- const result = {
617
- tables,
618
- transaction(fn) {
619
- const builder = new TxPlanBuilder();
620
- const planTables = {};
621
- for (const key of Object.keys(schema.tables)) {
622
- const tableDef = schema.tables[key];
623
- if (tableDef !== void 0) planTables[key] = builder.table(tableDef.name);
624
- }
625
- return runTxPlan(
626
- raw2,
627
- planTables,
628
- builder,
629
- fn
630
- );
631
- }
632
- };
633
- return result;
634
- }
635
-
636
- export {
637
- PolicyBuilder,
638
- policy,
639
- TABLE_META,
640
- defineTable,
641
- defineSchema,
642
- PALBASE_EXTENSIONS,
643
- EXTENSION_DEPENDENCIES,
644
- isPalbaseExtension,
645
- uuid,
646
- text,
647
- integer,
648
- bigint,
649
- numeric,
650
- boolean,
651
- timestamp,
652
- jsonb,
653
- enumType,
654
- vector,
655
- ownedByUser,
656
- userRef,
657
- installationRef,
658
- raw,
659
- openai,
660
- makeTypedDB
661
- };
662
- //# sourceMappingURL=chunk-G4R6BTLV.js.map