@palbase/backend 38.0.16 → 39.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 (58) hide show
  1. package/dist/bin/palbase-backend.cjs +46 -1
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +5 -5
  4. package/dist/{chunk-LFUNRWUE.js → chunk-4J6I4KVQ.js} +67 -3
  5. package/dist/{chunk-LFUNRWUE.js.map → chunk-4J6I4KVQ.js.map} +1 -1
  6. package/dist/{chunk-7WAGQ3VR.js → chunk-AR2I4M7I.js} +497 -17
  7. package/dist/chunk-AR2I4M7I.js.map +1 -0
  8. package/dist/{chunk-YANGWAIM.js → chunk-H7EKL6HC.js} +2 -2
  9. package/dist/{chunk-EHKEMHB4.js → chunk-JJSR4BUX.js} +49 -5
  10. package/dist/chunk-JJSR4BUX.js.map +1 -0
  11. package/dist/{chunk-CS6NQ6PO.js → chunk-JPTFYHP3.js} +2 -2
  12. package/dist/{chunk-CS6NQ6PO.js.map → chunk-JPTFYHP3.js.map} +1 -1
  13. package/dist/{chunk-X7UR3VXA.js → chunk-XZWOMPD3.js} +3 -2
  14. package/dist/chunk-XZWOMPD3.js.map +1 -0
  15. package/dist/{chunk-PDD55QWN.js → chunk-ZNQDL466.js} +2 -2
  16. package/dist/db/index.cjs +378 -14
  17. package/dist/db/index.cjs.map +1 -1
  18. package/dist/db/index.d.cts +1 -1
  19. package/dist/db/index.d.ts +1 -1
  20. package/dist/db/index.js +3 -3
  21. package/dist/engine/index.cjs +46 -1
  22. package/dist/engine/index.cjs.map +1 -1
  23. package/dist/engine/index.d.cts +3 -3
  24. package/dist/engine/index.d.ts +3 -3
  25. package/dist/engine/index.js +5 -5
  26. package/dist/{index-CI7S0Wqv.d.cts → index-B0mjUnxy.d.cts} +25 -2
  27. package/dist/{index-CUy50OLU.d.ts → index-eN4KzGa5.d.ts} +555 -29
  28. package/dist/{index-DRx880KY.d.cts → index-pK2At5Yc.d.cts} +555 -29
  29. package/dist/{index-Ogi30dbt.d.ts → index-yDno9Ju9.d.ts} +25 -2
  30. package/dist/index.cjs +628 -17
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +183 -8
  33. package/dist/index.d.ts +183 -8
  34. package/dist/index.js +74 -6
  35. package/dist/index.js.map +1 -1
  36. package/dist/openapi/index.cjs.map +1 -1
  37. package/dist/openapi/index.d.cts +2 -2
  38. package/dist/openapi/index.d.ts +2 -2
  39. package/dist/openapi/index.js +2 -2
  40. package/dist/{registry-C7UCkQf0.d.cts → registry-9dNeVN5d.d.cts} +1 -1
  41. package/dist/{registry-DJcvbomD.d.ts → registry-B8ddZiMY.d.ts} +1 -1
  42. package/dist/test/index.cjs +19 -0
  43. package/dist/test/index.cjs.map +1 -1
  44. package/dist/test/index.d.cts +1 -1
  45. package/dist/test/index.d.ts +1 -1
  46. package/dist/test/index.js +20 -2
  47. package/dist/test/index.js.map +1 -1
  48. package/docs/README.md +1 -1
  49. package/docs/database.md +79 -0
  50. package/docs/llms-full.txt +462 -33
  51. package/docs/schema.md +382 -32
  52. package/package.json +1 -1
  53. package/template/package.json +1 -1
  54. package/dist/chunk-7WAGQ3VR.js.map +0 -1
  55. package/dist/chunk-EHKEMHB4.js.map +0 -1
  56. package/dist/chunk-X7UR3VXA.js.map +0 -1
  57. /package/dist/{chunk-YANGWAIM.js.map → chunk-H7EKL6HC.js.map} +0 -0
  58. /package/dist/{chunk-PDD55QWN.js.map → chunk-ZNQDL466.js.map} +0 -0
@@ -4,17 +4,312 @@ import {
4
4
  qualifiedTableKey,
5
5
  retryBudget,
6
6
  runTxPlan
7
- } from "./chunk-LFUNRWUE.js";
7
+ } from "./chunk-4J6I4KVQ.js";
8
8
  import {
9
9
  isRetryable
10
- } from "./chunk-CS6NQ6PO.js";
10
+ } from "./chunk-JPTFYHP3.js";
11
11
  import {
12
12
  __name
13
13
  } from "./chunk-VXPNPVAG.js";
14
14
 
15
+ // src/db/foreign-key.ts
16
+ var TABLE_META = /* @__PURE__ */ Symbol.for("palbase.table.meta");
17
+ var REF_TARGET = /* @__PURE__ */ Symbol.for("palbase.ref.target");
18
+ var ForeignKeyBuilder = class {
19
+ static {
20
+ __name(this, "ForeignKeyBuilder");
21
+ }
22
+ _def;
23
+ constructor(name) {
24
+ if (name.trim() === "") {
25
+ throw new Error("foreignKey(ad): foreign key'in ad\u0131 bo\u015F olamaz \u2014 Palbase k\u0131s\u0131tlar\u0131 ADA g\xF6re uzla\u015Ft\u0131r\u0131r.");
26
+ }
27
+ this._def = {
28
+ name,
29
+ columns: [],
30
+ refTable: "",
31
+ refColumns: []
32
+ };
33
+ }
34
+ /** Yerel sütunlar. SIRA KORUNUR — hedef sütunlarla birebir eşleşir. */
35
+ on(...cols) {
36
+ this._def.columns = cols.map((c) => {
37
+ const e = c.expr;
38
+ if (e.kind !== "col") {
39
+ throw new Error(`foreignKey(${this._def.name}).on(): yaln\u0131z kolon referans\u0131 al\u0131r \u2014 ifade bir FK'n\u0131n par\xE7as\u0131 olamaz.`);
40
+ }
41
+ return e.name;
42
+ });
43
+ return this;
44
+ }
45
+ /**
46
+ * Hedef tablo ve sütunları. Sütun sayısı `.on()`'unkiyle eşit OLMALI ve bu
47
+ * burada, bildirim yazılırken kontrol edilir — bozuk bir FK wire'a hiç çıkmaz.
48
+ */
49
+ references(table, ...cols) {
50
+ if (cols.length === 0) {
51
+ throw new Error(`foreignKey(${this._def.name}).references(): en az bir hedef s\xFCtun gerekir.`);
52
+ }
53
+ this._def.refTable = table[TABLE_META].name;
54
+ this._def.refColumns = [
55
+ ...cols
56
+ ];
57
+ Object.defineProperty(this._def, REF_TARGET, {
58
+ value: table[TABLE_META],
59
+ enumerable: false,
60
+ configurable: true
61
+ });
62
+ return this;
63
+ }
64
+ onUpdate(action) {
65
+ this._def.onUpdate = action;
66
+ return this;
67
+ }
68
+ onDelete(action) {
69
+ this._def.onDelete = action;
70
+ return this;
71
+ }
72
+ /**
73
+ * `MATCH FULL`: referans veren sütunların HEPSİ NULL olmadıkça kısıt
74
+ * değerlendirilir. Varsayılan `MATCH SIMPLE`'da tek bir NULL kısıtı atlatır —
75
+ * `freeze` bunu bilerek kullanır, sıradan bir FK'da genelde istenmez.
76
+ */
77
+ match(m) {
78
+ this._def.match = m;
79
+ return this;
80
+ }
81
+ };
82
+ function foreignKey(name) {
83
+ return new ForeignKeyBuilder(name);
84
+ }
85
+ __name(foreignKey, "foreignKey");
86
+ function toForeignKeyDef(b) {
87
+ const def = b instanceof ForeignKeyBuilder ? b._def : b;
88
+ if (def.columns.length === 0) {
89
+ throw new Error(`foreignKey(${def.name}): en az bir yerel s\xFCtun gerekir \u2014 .on(...) \xE7a\u011F\u0131r\u0131n.`);
90
+ }
91
+ if (def.refColumns.length === 0 || def.refTable === "") {
92
+ throw new Error(`foreignKey(${def.name}): hedef tablo ve s\xFCtunlar gerekir \u2014 .references(...) \xE7a\u011F\u0131r\u0131n.`);
93
+ }
94
+ if (def.columns.length !== def.refColumns.length) {
95
+ throw new Error(`foreignKey(${def.name}): ${def.columns.length} yerel s\xFCtun (${def.columns.join(", ")}) ama ${def.refColumns.length} hedef s\xFCtun (${def.refColumns.join(", ")}) \u2014 iki liste e\u015Fit uzunlukta olmal\u0131.`);
96
+ }
97
+ return def;
98
+ }
99
+ __name(toForeignKeyDef, "toForeignKeyDef");
100
+ var FreezeBuilder = class {
101
+ static {
102
+ __name(this, "FreezeBuilder");
103
+ }
104
+ _def;
105
+ constructor(name) {
106
+ if (name.trim() === "") {
107
+ throw new Error("freeze(ad): freeze k\u0131s\u0131t\u0131n\u0131n ad\u0131 bo\u015F olamaz \u2014 Palbase k\u0131s\u0131tlar\u0131 ADA g\xF6re uzla\u015Ft\u0131r\u0131r.");
108
+ }
109
+ this._def = {
110
+ name,
111
+ columns: [],
112
+ refTable: "",
113
+ refColumns: []
114
+ };
115
+ }
116
+ /**
117
+ * DONMA KOŞULU — çocuk satırının kendi kolonları üzerinde bir yüklem.
118
+ *
119
+ * Generated sütunlara `CASE WHEN <koşul> THEN <sütun> END` olarak iner; yani
120
+ * koşul yanlışken sütunlar NULL olur ve FK o satır için hiç değerlendirilmez.
121
+ */
122
+ when(pred) {
123
+ this._def.when = pred.expr;
124
+ return this;
125
+ }
126
+ /** Çocuğun DONAN sütunları. SIRA KORUNUR — hedef sütunlarla birebir eşleşir. */
127
+ columns(...cols) {
128
+ if (cols.length === 0) {
129
+ throw new Error(`freeze(${this._def.name}).columns(): en az bir donan s\xFCtun gerekir \u2014 hi\xE7birini vermeyen bir freeze hi\xE7bir \u015Feyi dondurmaz.`);
130
+ }
131
+ this._def.columns = [
132
+ ...cols
133
+ ];
134
+ return this;
135
+ }
136
+ /**
137
+ * Ebeveyn tablo ve donan demetin ORADAKİ karşılığı. Zincirin SON halkası:
138
+ * bildirim burada tamamlanır ve tutarlılığı burada doğrulanır, yani
139
+ * `.references()`'ı unutmuş bir freeze `FreezeDef` üretmediği için tabloya
140
+ * hiç giremez.
141
+ */
142
+ references(table, ...cols) {
143
+ if (cols.length === 0) {
144
+ throw new Error(`freeze(${this._def.name}).references(): en az bir hedef s\xFCtun gerekir.`);
145
+ }
146
+ this._def.refTable = table[TABLE_META].name;
147
+ this._def.refColumns = [
148
+ ...cols
149
+ ];
150
+ Object.defineProperty(this._def, REF_TARGET, {
151
+ value: table[TABLE_META],
152
+ enumerable: false,
153
+ configurable: true
154
+ });
155
+ return toFreezeDef(this);
156
+ }
157
+ };
158
+ function freeze(name) {
159
+ return new FreezeBuilder(name);
160
+ }
161
+ __name(freeze, "freeze");
162
+ function toFreezeDef(b) {
163
+ const def = b instanceof FreezeBuilder ? b._def : b;
164
+ if (def.columns.length === 0) {
165
+ throw new Error(`freeze(${def.name}): en az bir donan s\xFCtun gerekir \u2014 .columns(...) \xE7a\u011F\u0131r\u0131n.`);
166
+ }
167
+ if (def.refColumns.length === 0 || def.refTable === "") {
168
+ throw new Error(`freeze(${def.name}): hedef tablo ve s\xFCtunlar gerekir \u2014 .references(...) \xE7a\u011F\u0131r\u0131n.`);
169
+ }
170
+ if (def.columns.length !== def.refColumns.length) {
171
+ throw new Error(`freeze(${def.name}): ${def.columns.length} donan s\xFCtun (${def.columns.join(", ")}) ama ${def.refColumns.length} hedef s\xFCtun (${def.refColumns.join(", ")}) \u2014 iki liste e\u015Fit uzunlukta olmal\u0131.`);
172
+ }
173
+ if (def.when === void 0) {
174
+ throw new Error(`freeze(${def.name}): donma ko\u015Fulu gerekir \u2014 .when(...) \xE7a\u011F\u0131r\u0131n. Ko\u015Fulsuz bir freeze s\u0131radan bir FK'd\u0131r; onun i\xE7in foreignKey(...) var.`);
175
+ }
176
+ const out = {
177
+ name: def.name,
178
+ when: def.when,
179
+ columns: [
180
+ ...def.columns
181
+ ],
182
+ refTable: def.refTable,
183
+ refColumns: [
184
+ ...def.refColumns
185
+ ]
186
+ };
187
+ const target = def[REF_TARGET];
188
+ if (target !== void 0) {
189
+ Object.defineProperty(out, REF_TARGET, {
190
+ value: target,
191
+ enumerable: false,
192
+ configurable: true
193
+ });
194
+ }
195
+ return out;
196
+ }
197
+ __name(toFreezeDef, "toFreezeDef");
198
+
15
199
  // src/db/policy.ts
16
200
  import { z } from "zod";
17
201
 
202
+ // src/db/guard.ts
203
+ var GuardBuilder = class {
204
+ static {
205
+ __name(this, "GuardBuilder");
206
+ }
207
+ _def;
208
+ constructor(name) {
209
+ if (name.trim() === "") {
210
+ throw new Error("guard(ad): guard'\u0131n ad\u0131 bo\u015F olamaz \u2014 Postgres ayn\u0131 olaydaki trigger'lar\u0131 ADA G\xD6RE alfabetik ko\u015Fuyor ve ba\u015Fka s\u0131ra tutamac\u0131 yok.");
211
+ }
212
+ this._def = {
213
+ name
214
+ };
215
+ }
216
+ /** Hangi yazma fiilinde bakılacak. */
217
+ on(event) {
218
+ this._def.event = event;
219
+ return this;
220
+ }
221
+ /**
222
+ * Satırın KENDİ kolonları üzerinde koşul — trigger'ın `WHEN` yan tümcesi.
223
+ *
224
+ * Emitter karşılaştırmaları `IS DISTINCT FROM` ile yazar (`<>` NULL'da yanlış
225
+ * cevap verir) ve geçen sütunlardan bir `UPDATE OF (…)` listesi türetir
226
+ * (FR-018).
227
+ */
228
+ when(pred) {
229
+ this._def.when = pred.expr;
230
+ return this;
231
+ }
232
+ /**
233
+ * ÇAPRAZ SATIR koşulu — gövdedeki `EXISTS` bloğuna iner, `WHEN`'e DEĞİL:
234
+ * Postgres trigger `WHEN`'inde alt sorgu kabul etmiyor (FR-019).
235
+ *
236
+ * Yüklem içinde takma adsız kalan kolon guard'ın KENDİ satırıdır (`NEW`/`OLD`);
237
+ * `r.col(...)` hedef tablonun kolonlarını verir ve ayrı nitelenir. Bu yüzden
238
+ * düğümün `outer` alanı BOŞ kalır: bir guard'ın "dış satır"ı bir tablo takma
239
+ * adı değildir.
240
+ */
241
+ exists(table, predicate) {
242
+ this._def.exists = exprCtx().existsIn(table, predicate).expr;
243
+ return this;
244
+ }
245
+ /**
246
+ * REDDİN KENDİSİ ve zincirin son halkası: mesaj olmadan bir guard tamamlanmaz.
247
+ *
248
+ * `detail`/`hint` Postgres'in aynı adlı alanlarına, `column` ise `COLUMN`
249
+ * alanına gider — istemci hangi alanın reddedildiğini mesajı parse etmeden
250
+ * okur.
251
+ */
252
+ refuse(message, opts) {
253
+ this._def.message = message;
254
+ if (opts?.detail !== void 0) this._def.detail = opts.detail;
255
+ if (opts?.hint !== void 0) this._def.hint = opts.hint;
256
+ if (opts?.column !== void 0) this._def.column = opts.column;
257
+ return toGuardDef(this);
258
+ }
259
+ };
260
+ function guard(name) {
261
+ return new GuardBuilder(name);
262
+ }
263
+ __name(guard, "guard");
264
+ function toGuardDef(b) {
265
+ const def = b instanceof GuardBuilder ? b._def : b;
266
+ if (def.event === void 0) {
267
+ throw new Error(`guard(${def.name}): hangi olayda bakaca\u011F\u0131 gerekir \u2014 .on("insert"|"update"|"delete") \xE7a\u011F\u0131r\u0131n.`);
268
+ }
269
+ if (def.when === void 0 && def.exists === void 0) {
270
+ throw new Error(`guard(${def.name}): bir ko\u015Ful gerekir \u2014 .when(...) ya da .exists(...) \xE7a\u011F\u0131r\u0131n. Ko\u015Fulsuz bir guard o olaydaki HER yazmay\u0131 reddeder.`);
271
+ }
272
+ if (def.message === void 0 || def.message.trim() === "") {
273
+ throw new Error(`guard(${def.name}): bo\u015F mesaj kabul edilmez \u2014 reddin mesaj\u0131 guard'\u0131n kullan\u0131c\u0131ya ula\u015Fan TEK \xE7\u0131kt\u0131s\u0131.`);
274
+ }
275
+ return {
276
+ name: def.name,
277
+ event: def.event,
278
+ ...def.when !== void 0 ? {
279
+ when: def.when
280
+ } : {},
281
+ ...def.exists !== void 0 ? {
282
+ exists: def.exists
283
+ } : {},
284
+ message: def.message,
285
+ ...def.detail !== void 0 ? {
286
+ detail: def.detail
287
+ } : {},
288
+ ...def.hint !== void 0 ? {
289
+ hint: def.hint
290
+ } : {},
291
+ ...def.column !== void 0 ? {
292
+ column: def.column
293
+ } : {}
294
+ };
295
+ }
296
+ __name(toGuardDef, "toGuardDef");
297
+
298
+ // src/db/backfill.ts
299
+ function backfill(name, sql) {
300
+ if (name.trim() === "") {
301
+ throw new Error("backfill(ad, sql): backfill'in ad\u0131 bo\u015F olamaz \u2014 'bir kez ko\u015Ftu' kayd\u0131 ADA g\xF6re tutuluyor.");
302
+ }
303
+ if (sql.trim() === "") {
304
+ throw new Error(`backfill(${name}): SQL bo\u015F olamaz \u2014 bo\u015F bir g\xF6vde ad\u0131 kayda ge\xE7irip KALICI olarak yakar; sonradan yaz\u0131lan ger\xE7ek SQL "zaten ko\u015Ftu" diye hi\xE7 \xE7al\u0131\u015Fmaz.`);
305
+ }
306
+ return {
307
+ name,
308
+ sql
309
+ };
310
+ }
311
+ __name(backfill, "backfill");
312
+
18
313
  // src/db/schema.ts
19
314
  var IndexBuilder = class {
20
315
  static {
@@ -29,6 +324,15 @@ var IndexBuilder = class {
29
324
  name
30
325
  };
31
326
  }
327
+ /**
328
+ * `CREATE UNIQUE INDEX` (FR-007). `.where()` ile birlikte PARTIAL UNIQUE
329
+ * index verir (FR-007b) — "NULL'lar serbest, non-NULL'lar tekil" kalıbının
330
+ * tek bildirimsel yolu.
331
+ */
332
+ unique() {
333
+ this._def.unique = true;
334
+ return this;
335
+ }
32
336
  /** Index'in kolonları. SIRA KORUNUR — çok kolonlu bir index'in anlamı sırasıdır. */
33
337
  on(...cols) {
34
338
  this._def.columns = cols.map((c) => {
@@ -86,7 +390,7 @@ function toPolicyDef(p) {
86
390
  return p instanceof PolicyBuilder ? p._def : p;
87
391
  }
88
392
  __name(toPolicyDef, "toPolicyDef");
89
- var TABLE_META = /* @__PURE__ */ Symbol.for("palbase.table.meta");
393
+ var TABLE_META2 = /* @__PURE__ */ Symbol.for("palbase.table.meta");
90
394
  function defineTable(name, input) {
91
395
  if (name.trim() === "") {
92
396
  throw new Error("defineTable(name, \u2026): name must not be empty");
@@ -119,9 +423,46 @@ function defineTable(name, input) {
119
423
  if (input.primaryKey !== void 0) def.primaryKey = input.primaryKey;
120
424
  if (input.unique !== void 0) def.unique = input.unique;
121
425
  if (input.raw !== void 0 && input.raw.length > 0) def.raw = input.raw.slice();
122
- if (input.checks !== void 0 && input.checks.length > 0) def.checks = input.checks.slice();
426
+ const declaredChecks = typeof input.checks === "function" ? input.checks(exprCtx(Object.keys(input.columns), 0, name)) : input.checks?.slice() ?? [];
427
+ if (declaredChecks.length > 0) def.checks = declaredChecks;
123
428
  const declaredIndexes = (input.indexes?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map((i) => i instanceof IndexBuilder ? i._def : i);
124
429
  if (declaredIndexes.length > 0) def.indexes = declaredIndexes;
430
+ const declaredFKs = (input.foreignKeys?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(toForeignKeyDef);
431
+ if (declaredFKs.length > 0) def.foreignKeys = declaredFKs;
432
+ const declaredFreezes = (input.freeze?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(toFreezeDef);
433
+ if (declaredFreezes.length > 0) def.freeze = declaredFreezes;
434
+ for (const fz of declaredFreezes) {
435
+ for (const c of fz.columns) {
436
+ if (!(c in input.columns)) {
437
+ throw new Error(`table "${name}": freeze("${fz.name}").columns("${c}") \u2014 no such column on this table. Declared columns: ${Object.keys(input.columns).join(", ")}`);
438
+ }
439
+ }
440
+ }
441
+ const declaredGuards = (input.guards?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(toGuardDef);
442
+ if (declaredGuards.length > 0) def.guards = declaredGuards;
443
+ for (const g of declaredGuards) {
444
+ if (g.column !== void 0 && !(g.column in input.columns)) {
445
+ throw new Error(`table "${name}": guard("${g.name}").refuse(\u2026, { column: "${g.column}" }) \u2014 no such column on this table. Declared columns: ${Object.keys(input.columns).join(", ")}`);
446
+ }
447
+ }
448
+ if (input.backfills !== void 0 && input.backfills.length > 0) {
449
+ const seen = /* @__PURE__ */ new Set();
450
+ for (const b of input.backfills) {
451
+ if (seen.has(b.name)) {
452
+ throw new Error(`table ${name}: backfill ad\u0131 iki kez bildirildi: ${b.name} \u2014 kay\u0131t ADA g\xF6re tutuluyor, ikincisi hi\xE7 ko\u015Fmazd\u0131.`);
453
+ }
454
+ seen.add(b.name);
455
+ }
456
+ def.backfills = input.backfills.map((b) => ({
457
+ name: b.name,
458
+ sql: b.sql
459
+ }));
460
+ }
461
+ if (input.dropConstraints !== void 0 && input.dropConstraints.length > 0) {
462
+ def.dropConstraints = [
463
+ ...input.dropConstraints
464
+ ];
465
+ }
125
466
  if (input.appendOnly === true) def.appendOnly = true;
126
467
  if (input.ignored === true) def.ignored = true;
127
468
  if (input.search !== void 0) {
@@ -175,7 +516,7 @@ function defineTable(name, input) {
175
516
  const handle = {
176
517
  ...owned
177
518
  };
178
- Object.defineProperty(handle, TABLE_META, {
519
+ Object.defineProperty(handle, TABLE_META2, {
179
520
  value: def,
180
521
  enumerable: false
181
522
  });
@@ -184,6 +525,9 @@ function defineTable(name, input) {
184
525
  __name(defineTable, "defineTable");
185
526
  var declaringSchemaOf = /* @__PURE__ */ new WeakMap();
186
527
  function resolveReferences(tables, schemaName) {
528
+ for (const table of Object.values(tables)) {
529
+ qualifyRefTargets(table, `table "${table.name}"`);
530
+ }
187
531
  for (const table of Object.values(tables)) {
188
532
  for (const [colName, builder] of Object.entries(table.columns)) {
189
533
  const def = builder._def;
@@ -228,7 +572,7 @@ function defineSchema(name, input) {
228
572
  }
229
573
  const tables = {};
230
574
  for (const handle of input.tables) {
231
- const table = handle[TABLE_META];
575
+ const table = handle[TABLE_META2];
232
576
  if (tables[table.name] !== void 0) {
233
577
  throw new Error(`defineSchema("${name}"): two tables declare the name "${table.name}" \u2014 table names must be unique within a schema`);
234
578
  }
@@ -272,6 +616,48 @@ function defineSchema(name, input) {
272
616
  };
273
617
  }
274
618
  __name(defineSchema, "defineSchema");
619
+ function qualifyRefTargets(table, where) {
620
+ const qualify = /* @__PURE__ */ __name((holder, what) => {
621
+ const target = holder[REF_TARGET];
622
+ if (target === void 0) return;
623
+ const targetSchema = declaringSchemaOf.get(target);
624
+ if (targetSchema === void 0) {
625
+ throw new Error(`${where}: ${what} points at table "${target.name}", which no defineSchema(...) has claimed yet \u2014 a cross-table reference 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).`);
626
+ }
627
+ const qualified = qualifiedTableKey(targetSchema, target.name);
628
+ if (holder.refTable !== void 0) holder.refTable = qualified;
629
+ if (holder.table !== void 0) holder.table = qualified;
630
+ }, "qualify");
631
+ for (const fk of table.foreignKeys ?? []) qualify(fk, `foreignKey("${fk.name}")`);
632
+ for (const fz of table.freeze ?? []) qualify(fz, `freeze("${fz.name}")`);
633
+ for (const g of table.guards ?? []) {
634
+ if (g.exists !== void 0) {
635
+ qualifyExistsNodes(g.exists, `guard("${g.name}").exists(...)`, where);
636
+ }
637
+ }
638
+ }
639
+ __name(qualifyRefTargets, "qualifyRefTargets");
640
+ function qualifyExistsNodes(node, what, where) {
641
+ if (node === null || typeof node !== "object") return;
642
+ if (node.kind === "exists") {
643
+ const target = node[REF_TARGET];
644
+ if (target !== void 0) {
645
+ const targetSchema = declaringSchemaOf.get(target);
646
+ if (targetSchema === void 0) {
647
+ throw new Error(`${where}: ${what} points at table "${target.name}", which no defineSchema(...) has claimed yet \u2014 a guard body is parsed at RUN TIME under a pinned search_path, so an unqualified name never resolves.`);
648
+ }
649
+ node.table = qualifiedTableKey(targetSchema, target.name);
650
+ }
651
+ }
652
+ for (const v of Object.values(node)) {
653
+ if (Array.isArray(v)) {
654
+ for (const e of v) qualifyExistsNodes(e, what, where);
655
+ } else if (v !== null && typeof v === "object") {
656
+ qualifyExistsNodes(v, what, where);
657
+ }
658
+ }
659
+ }
660
+ __name(qualifyExistsNodes, "qualifyExistsNodes");
275
661
 
276
662
  // src/db/policy.ts
277
663
  var PolicyExprRef = class _PolicyExprRef {
@@ -385,15 +771,21 @@ function exprCtx(_columns, depth = 0, ownTable = "") {
385
771
  expr: part.expr
386
772
  }), "not"),
387
773
  existsIn: /* @__PURE__ */ __name((table, predicate) => {
388
- const meta = table[TABLE_META];
774
+ const meta = table[TABLE_META2];
389
775
  const inner = exprCtx(Object.keys(meta.columns), depth + 1, ownTable);
390
- return new PolicyExprRef({
776
+ const node = {
391
777
  kind: "exists",
392
778
  table: meta.name,
393
779
  alias: `pb_e${depth + 1}`,
394
780
  outer: ownTable,
395
781
  predicate: predicate(inner).expr
782
+ };
783
+ Object.defineProperty(node, REF_TARGET, {
784
+ value: meta,
785
+ enumerable: false,
786
+ configurable: true
396
787
  });
788
+ return new PolicyExprRef(node);
397
789
  }, "existsIn")
398
790
  };
399
791
  }
@@ -481,13 +873,13 @@ var PolicyBuilder = class {
481
873
  * // → id IN (SELECT "channel_id" FROM "channel_members"
482
874
  * // WHERE "user_id" = (select auth.uid()))
483
875
  */
484
- memberOf(membershipTable, foreignKey, options = {}) {
876
+ memberOf(membershipTable, foreignKey2, options = {}) {
485
877
  if (this._def.using !== null) {
486
878
  throw new Error(`policy(${this._def.name}).memberOf(): this policy already has a using() expression. Write one or the other \u2014 memberOf IS the using expression.`);
487
879
  }
488
880
  const column = options.column ?? "id";
489
881
  const userColumn = options.userColumn ?? "user_id";
490
- this._def.using = `${quote(column)} IN (SELECT ${quote(foreignKey)} FROM ${quote(membershipTable)} WHERE ${quote(userColumn)} = (select auth.uid()))`;
882
+ this._def.using = `${quote(column)} IN (SELECT ${quote(foreignKey2)} FROM ${quote(membershipTable)} WHERE ${quote(userColumn)} = (select auth.uid()))`;
491
883
  return this;
492
884
  }
493
885
  /** `WITH CHECK (...)` yazma doğrulaması — `using` ile aynı iki biçim. */
@@ -506,6 +898,92 @@ function policy(name) {
506
898
  return new PolicyBuilder(name);
507
899
  }
508
900
  __name(policy, "policy");
901
+ function assertCheckNode(node, name) {
902
+ switch (node.kind) {
903
+ case "exists":
904
+ throw new Error(`check(${name}): \`existsIn(...)\` is a subquery and PostgreSQL forbids subqueries in a CHECK constraint \u2014 express a cross-table rule as a composite FOREIGN KEY (foreignKeys), or as a guard.`);
905
+ case "authUid":
906
+ throw new Error(`check(${name}): \`auth.uid()\` renders as a subquery \`(SELECT auth.uid())\` and PostgreSQL forbids subqueries in a CHECK constraint \u2014 a caller-dependent rule belongs in an RLS policy, not a CHECK.`);
907
+ case "binop":
908
+ assertCheckNode(node.left, name);
909
+ assertCheckNode(node.right, name);
910
+ return;
911
+ case "and":
912
+ case "or":
913
+ for (const part of node.parts) assertCheckNode(part, name);
914
+ return;
915
+ case "not":
916
+ case "isNull":
917
+ assertCheckNode(node.expr, name);
918
+ return;
919
+ default:
920
+ return;
921
+ }
922
+ }
923
+ __name(assertCheckNode, "assertCheckNode");
924
+ var CHECK_BIN_OPS = {
925
+ eq: "=",
926
+ neq: "<>",
927
+ gt: ">",
928
+ gte: ">=",
929
+ lt: "<",
930
+ lte: "<="
931
+ };
932
+ function literalSQL(v) {
933
+ if (v === null) return "NULL";
934
+ if (typeof v === "boolean") return v ? "true" : "false";
935
+ if (typeof v === "number") {
936
+ if (!Number.isFinite(v)) {
937
+ throw new Error(`check(): ${v} bir SQL say\u0131 literali de\u011Fil.`);
938
+ }
939
+ return String(v);
940
+ }
941
+ return `'${v.replace(/'/g, "''")}'`;
942
+ }
943
+ __name(literalSQL, "literalSQL");
944
+ function checkNodeSQL(node, name) {
945
+ switch (node.kind) {
946
+ case "col":
947
+ return quote(node.name);
948
+ case "lit":
949
+ return literalSQL(node.value);
950
+ case "binop": {
951
+ const op = CHECK_BIN_OPS[node.op];
952
+ if (op === void 0) {
953
+ throw new Error(`check(${name}): \`${node.op}\` bir CHECK ifadesinde desteklenmiyor.`);
954
+ }
955
+ return `(${checkNodeSQL(node.left, name)} ${op} ${checkNodeSQL(node.right, name)})`;
956
+ }
957
+ case "and":
958
+ case "or": {
959
+ if (node.parts.length === 0) {
960
+ return node.kind === "and" ? "(true)" : "(false)";
961
+ }
962
+ const joiner = node.kind === "and" ? " AND " : " OR ";
963
+ return `(${node.parts.map((p) => checkNodeSQL(p, name)).join(joiner)})`;
964
+ }
965
+ case "not":
966
+ return `(NOT ${checkNodeSQL(node.expr, name)})`;
967
+ case "isNull":
968
+ return `(${checkNodeSQL(node.expr, name)} IS ${node.negated ? "NOT NULL" : "NULL"})`;
969
+ default: {
970
+ const kind = node.kind;
971
+ throw new Error(`check(${name}): \`${kind}\` d\xFC\u011F\xFCm\xFC bir CHECK ifadesinde tan\u0131nm\u0131yor.`);
972
+ }
973
+ }
974
+ }
975
+ __name(checkNodeSQL, "checkNodeSQL");
976
+ function check(name, expr) {
977
+ if (name.trim() === "") {
978
+ throw new Error("check(): k\u0131s\u0131t\u0131n ad\u0131 bo\u015F olamaz \u2014 CHECK'ler ADA g\xF6re uzla\u015Ft\u0131r\u0131l\u0131yor.");
979
+ }
980
+ assertCheckNode(expr.expr, name);
981
+ return {
982
+ name,
983
+ expr: checkNodeSQL(expr.expr, name)
984
+ };
985
+ }
986
+ __name(check, "check");
509
987
  function can(table) {
510
988
  if (table === void 0 || table === null) {
511
989
  throw new Error("can(<table>): received " + String(table) + " \u2014 the schema declares no such table (check the name against db/*.ts; can(publicSchema.tables.<name>))");
@@ -582,13 +1060,10 @@ function isPalbaseExtension(name) {
582
1060
  __name(isPalbaseExtension, "isPalbaseExtension");
583
1061
 
584
1062
  // src/db/raw.ts
585
- function raw(name, up, opts) {
1063
+ function raw(name, up) {
586
1064
  return {
587
1065
  name,
588
- up,
589
- ...opts?.down != null ? {
590
- down: opts.down
591
- } : {}
1066
+ up
592
1067
  };
593
1068
  }
594
1069
  __name(raw, "raw");
@@ -717,14 +1192,19 @@ function sqlFragment(strings, ...values) {
717
1192
  __name(sqlFragment, "sqlFragment");
718
1193
 
719
1194
  export {
1195
+ foreignKey,
1196
+ freeze,
720
1197
  PolicyExprRef,
721
1198
  exprCtx,
722
1199
  PolicyBuilder,
723
1200
  policy,
1201
+ check,
724
1202
  can,
1203
+ guard,
1204
+ backfill,
725
1205
  IndexBuilder,
726
1206
  index,
727
- TABLE_META,
1207
+ TABLE_META2 as TABLE_META,
728
1208
  defineTable,
729
1209
  defineSchema,
730
1210
  PALBASE_EXTENSIONS,
@@ -737,4 +1217,4 @@ export {
737
1217
  withRetry,
738
1218
  sqlFragment
739
1219
  };
740
- //# sourceMappingURL=chunk-7WAGQ3VR.js.map
1220
+ //# sourceMappingURL=chunk-AR2I4M7I.js.map