@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.
- package/dist/bin/palbase-backend.cjs +2401 -1039
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +87 -51
- package/dist/bin/palbase-backend.js.map +1 -1
- package/dist/chunk-CGNN2PUH.js +213 -0
- package/dist/chunk-CGNN2PUH.js.map +1 -0
- package/dist/chunk-DRZFQRJI.js +370 -0
- package/dist/chunk-DRZFQRJI.js.map +1 -0
- package/dist/chunk-GYK6QYS4.js +708 -0
- package/dist/chunk-GYK6QYS4.js.map +1 -0
- package/dist/chunk-I3C4PFIW.js +930 -0
- package/dist/chunk-I3C4PFIW.js.map +1 -0
- package/dist/{chunk-VDF2T4AS.js → chunk-OO7R25AI.js} +1213 -591
- package/dist/chunk-OO7R25AI.js.map +1 -0
- package/dist/chunk-TS4U7NBD.js +885 -0
- package/dist/chunk-TS4U7NBD.js.map +1 -0
- package/dist/{chunk-YOY5DFQS.js → chunk-TWX6JTGJ.js} +76 -34
- package/dist/{chunk-YOY5DFQS.js.map → chunk-TWX6JTGJ.js.map} +1 -1
- package/dist/{chunk-35PNTIRN.js → chunk-VVMJEVQP.js} +63 -162
- package/dist/chunk-VVMJEVQP.js.map +1 -0
- package/dist/{chunk-7D4SUZUM.js → chunk-VXPNPVAG.js} +3 -1
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +2 -2
- package/dist/db/env.d.ts +2 -2
- package/dist/db/index.cjs +754 -344
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +7 -4
- package/dist/engine/index.cjs +2339 -1006
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +6 -6
- package/dist/engine/index.d.ts +6 -6
- package/dist/engine/index.js +7 -6
- package/dist/index-BrvvxSpn.d.ts +4844 -0
- package/dist/index-Bve7BBTL.d.cts +4844 -0
- package/dist/{index-CUomTA3e.d.ts → index-NuzRCuxe.d.ts} +171 -296
- package/dist/{index-ClpDeSos.d.cts → index-VtToZmUm.d.cts} +171 -296
- package/dist/index.cjs +2694 -1169
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -19
- package/dist/index.d.ts +165 -19
- package/dist/index.js +738 -477
- package/dist/index.js.map +1 -1
- package/dist/module-Dl1KFVtc.d.cts +54 -0
- package/dist/module-Dl1KFVtc.d.ts +54 -0
- package/dist/openapi/index.cjs +1330 -484
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +4 -2
- package/dist/openapi/index.d.ts +4 -2
- package/dist/openapi/index.js +1264 -474
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-dZZ5JKYg.d.ts → registry-B0eyOF9x.d.ts} +1 -1
- package/dist/{registry-CC0WBQq6.d.cts → registry-Bk9_rbNd.d.cts} +1 -1
- package/dist/stack.cjs.map +1 -1
- package/dist/test/index.cjs +705 -141
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +30 -4
- package/dist/test/index.d.ts +30 -4
- package/dist/test/index.js +472 -124
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +33 -18
- package/docs/auth.md +1 -1
- package/docs/background.md +2 -2
- package/docs/database.md +221 -50
- package/docs/endpoints.md +3 -4
- package/docs/events.md +3 -3
- package/docs/getting-started.md +1 -1
- package/docs/llms-full.txt +401 -117
- package/docs/migrations.md +2 -2
- package/docs/schema.md +19 -10
- package/docs/services.md +116 -26
- package/package.json +8 -4
- package/stager/generics.js +205 -0
- package/stager/stage.js +39 -3
- package/template/AGENTS.md +110 -72
- package/template/db/public.ts +1 -1
- package/template/{controllers → modules/health}/health.controller.ts +1 -1
- package/template/modules/health/health.module.ts +24 -0
- package/template/modules/notes/note.service.test.ts +49 -0
- package/template/modules/notes/note.service.ts +108 -0
- package/template/{controllers → modules/notes}/notes.controller.ts +17 -11
- package/template/modules/notes/notes.module.ts +37 -0
- package/template/package.json +5 -3
- package/template/scripts/test.sh +33 -0
- package/template/tsconfig.json +29 -30
- package/dist/chunk-35PNTIRN.js.map +0 -1
- package/dist/chunk-CJSKYY76.js +0 -627
- package/dist/chunk-CJSKYY76.js.map +0 -1
- package/dist/chunk-CRQKCRGF.js +0 -276
- package/dist/chunk-CRQKCRGF.js.map +0 -1
- package/dist/chunk-G4R6BTLV.js +0 -662
- package/dist/chunk-G4R6BTLV.js.map +0 -1
- package/dist/chunk-VDF2T4AS.js.map +0 -1
- package/dist/chunk-XABBC7JP.js +0 -55
- package/dist/chunk-XABBC7JP.js.map +0 -1
- package/dist/endpoint-CTEHhb7A.d.ts +0 -2386
- package/dist/endpoint-DYHMo6cC.d.cts +0 -2386
- package/dist/index-CW21M9Z3.d.ts +0 -1222
- package/dist/index-CmBK76nx.d.cts +0 -1222
- package/template/services/note.service.test.ts +0 -45
- package/template/services/note.service.ts +0 -76
- /package/dist/{chunk-7D4SUZUM.js.map → chunk-VXPNPVAG.js.map} +0 -0
- /package/template/{models/notes → modules/notes/dto}/create.ts +0 -0
package/dist/db/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
7
|
var __export = (target, all) => {
|
|
7
8
|
for (var name in all)
|
|
8
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -55,18 +56,149 @@ module.exports = __toCommonJS(db_exports);
|
|
|
55
56
|
function qualifiedTableKey(schemaName, tableName) {
|
|
56
57
|
return schemaName === "" || schemaName === "public" ? tableName : `${schemaName}.${tableName}`;
|
|
57
58
|
}
|
|
59
|
+
__name(qualifiedTableKey, "qualifiedTableKey");
|
|
58
60
|
|
|
59
61
|
// src/db/policy.ts
|
|
62
|
+
var PolicyExprRef = class _PolicyExprRef {
|
|
63
|
+
static {
|
|
64
|
+
__name(this, "PolicyExprRef");
|
|
65
|
+
}
|
|
66
|
+
expr;
|
|
67
|
+
constructor(expr) {
|
|
68
|
+
this.expr = expr;
|
|
69
|
+
}
|
|
70
|
+
bin(op, other) {
|
|
71
|
+
return new _PolicyExprRef({
|
|
72
|
+
kind: "binop",
|
|
73
|
+
op,
|
|
74
|
+
left: this.expr,
|
|
75
|
+
right: toExpr(other)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
eq(other) {
|
|
79
|
+
return this.bin("eq", other);
|
|
80
|
+
}
|
|
81
|
+
neq(other) {
|
|
82
|
+
return this.bin("neq", other);
|
|
83
|
+
}
|
|
84
|
+
gt(other) {
|
|
85
|
+
return this.bin("gt", other);
|
|
86
|
+
}
|
|
87
|
+
gte(other) {
|
|
88
|
+
return this.bin("gte", other);
|
|
89
|
+
}
|
|
90
|
+
lt(other) {
|
|
91
|
+
return this.bin("lt", other);
|
|
92
|
+
}
|
|
93
|
+
lte(other) {
|
|
94
|
+
return this.bin("lte", other);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* `IS NULL` / `IS NOT NULL` — `= NULL` SQL'de her zaman UNKNOWN'dır, o yüzden
|
|
98
|
+
* niyet ayrı bir düğümle yazılır. Partial index'in en sık koşulu
|
|
99
|
+
* (`WHERE deleted_at IS NULL`) tam olarak bu.
|
|
100
|
+
*/
|
|
101
|
+
isNull(negated = false) {
|
|
102
|
+
return new _PolicyExprRef({
|
|
103
|
+
kind: "isNull",
|
|
104
|
+
expr: this.expr,
|
|
105
|
+
negated
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
and(...others) {
|
|
109
|
+
return new _PolicyExprRef({
|
|
110
|
+
kind: "and",
|
|
111
|
+
parts: [
|
|
112
|
+
this.expr,
|
|
113
|
+
...others.map((o) => o.expr)
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
or(...others) {
|
|
118
|
+
return new _PolicyExprRef({
|
|
119
|
+
kind: "or",
|
|
120
|
+
parts: [
|
|
121
|
+
this.expr,
|
|
122
|
+
...others.map((o) => o.expr)
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
not() {
|
|
127
|
+
return new _PolicyExprRef({
|
|
128
|
+
kind: "not",
|
|
129
|
+
expr: this.expr
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
function toExpr(v) {
|
|
134
|
+
return v instanceof PolicyExprRef ? v.expr : {
|
|
135
|
+
kind: "lit",
|
|
136
|
+
value: v
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
__name(toExpr, "toExpr");
|
|
140
|
+
function exprCtx(_columns, depth = 0, ownTable = "") {
|
|
141
|
+
const alias = `pb_e${depth}`;
|
|
142
|
+
return {
|
|
143
|
+
col: /* @__PURE__ */ __name((name) => new PolicyExprRef(depth === 0 ? {
|
|
144
|
+
kind: "col",
|
|
145
|
+
name
|
|
146
|
+
} : {
|
|
147
|
+
kind: "col",
|
|
148
|
+
name,
|
|
149
|
+
alias
|
|
150
|
+
}), "col"),
|
|
151
|
+
auth: {
|
|
152
|
+
uid: /* @__PURE__ */ __name(() => new PolicyExprRef({
|
|
153
|
+
kind: "authUid"
|
|
154
|
+
}), "uid")
|
|
155
|
+
},
|
|
156
|
+
lit: /* @__PURE__ */ __name((v) => new PolicyExprRef({
|
|
157
|
+
kind: "lit",
|
|
158
|
+
value: v
|
|
159
|
+
}), "lit"),
|
|
160
|
+
and: /* @__PURE__ */ __name((...parts) => new PolicyExprRef({
|
|
161
|
+
kind: "and",
|
|
162
|
+
parts: parts.map((p) => p.expr)
|
|
163
|
+
}), "and"),
|
|
164
|
+
or: /* @__PURE__ */ __name((...parts) => new PolicyExprRef({
|
|
165
|
+
kind: "or",
|
|
166
|
+
parts: parts.map((p) => p.expr)
|
|
167
|
+
}), "or"),
|
|
168
|
+
not: /* @__PURE__ */ __name((part) => new PolicyExprRef({
|
|
169
|
+
kind: "not",
|
|
170
|
+
expr: part.expr
|
|
171
|
+
}), "not"),
|
|
172
|
+
existsIn: /* @__PURE__ */ __name((table, predicate) => {
|
|
173
|
+
const meta = table[TABLE_META];
|
|
174
|
+
const inner = exprCtx(Object.keys(meta.columns), depth + 1, ownTable);
|
|
175
|
+
return new PolicyExprRef({
|
|
176
|
+
kind: "exists",
|
|
177
|
+
table: meta.name,
|
|
178
|
+
alias: `pb_e${depth + 1}`,
|
|
179
|
+
outer: ownTable,
|
|
180
|
+
predicate: predicate(inner).expr
|
|
181
|
+
});
|
|
182
|
+
}, "existsIn")
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
__name(exprCtx, "exprCtx");
|
|
60
186
|
function quote(name) {
|
|
61
187
|
return `"${name.replace(/"/g, '""')}"`;
|
|
62
188
|
}
|
|
189
|
+
__name(quote, "quote");
|
|
63
190
|
var PolicyBuilder = class {
|
|
191
|
+
static {
|
|
192
|
+
__name(this, "PolicyBuilder");
|
|
193
|
+
}
|
|
64
194
|
_def;
|
|
65
195
|
constructor(name) {
|
|
66
196
|
this._def = {
|
|
67
197
|
name,
|
|
68
198
|
command: "all",
|
|
69
|
-
roles: [
|
|
199
|
+
roles: [
|
|
200
|
+
"authenticated"
|
|
201
|
+
],
|
|
70
202
|
using: null,
|
|
71
203
|
withCheck: null,
|
|
72
204
|
permissive: true
|
|
@@ -78,65 +210,78 @@ var PolicyBuilder = class {
|
|
|
78
210
|
return this;
|
|
79
211
|
}
|
|
80
212
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
213
|
+
* Set the DB roles the policy applies to (the `TO` clause), replacing any
|
|
214
|
+
* previously-set roles. Call with no arguments to target PUBLIC (all roles).
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* policy("p").to("authenticated")
|
|
218
|
+
* policy("p").to("authenticated", "service_role")
|
|
219
|
+
* policy("p").to() // PUBLIC
|
|
220
|
+
*/
|
|
89
221
|
to(...roles) {
|
|
90
222
|
this._def.roles = roles;
|
|
91
223
|
return this;
|
|
92
224
|
}
|
|
93
|
-
/**
|
|
94
|
-
|
|
95
|
-
|
|
225
|
+
/**
|
|
226
|
+
* `USING (...)` satır görünürlüğü ifadesi.
|
|
227
|
+
*
|
|
228
|
+
* Tercih edilen biçim YAPI'dır (FR-022) — `policies` callback'inin verdiği
|
|
229
|
+
* bağlamla kurulur ve kolon adları derlemede doğrulanır:
|
|
230
|
+
*
|
|
231
|
+
* ```ts
|
|
232
|
+
* policies: (p) => [
|
|
233
|
+
* policy("owner_read").for("select").using(p.col("owner").eq(p.auth.uid())),
|
|
234
|
+
* ]
|
|
235
|
+
* ```
|
|
236
|
+
*
|
|
237
|
+
* Ham string KAÇIŞ KAPAĞI olarak kalır (FR-028): yapının ifade edemediği bir
|
|
238
|
+
* şey gerektiğinde yol kapanmaz. Ama o yolda kolon adı doğrulaması yoktur ve
|
|
239
|
+
* hata deploy anında Postgres'ten gelir.
|
|
240
|
+
*/
|
|
241
|
+
using(expr) {
|
|
242
|
+
this._def.using = expr instanceof PolicyExprRef ? expr.expr : expr;
|
|
96
243
|
return this;
|
|
97
244
|
}
|
|
98
245
|
/**
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
246
|
+
* "Rows of THIS table whose owner the caller is a member of" — the membership
|
|
247
|
+
* pattern, written so it cannot recurse.
|
|
248
|
+
*
|
|
249
|
+
* THE TRAP IT EXISTS FOR. Written by hand, membership policies point at each
|
|
250
|
+
* other: `channels` is visible to members, so its policy reads
|
|
251
|
+
* `channel_members`; `channel_members` is visible to members, so its policy
|
|
252
|
+
* reads `channels`. Postgres refuses the pair at query time with `infinite
|
|
253
|
+
* recursion detected in policy for relation ...`, and the error names the
|
|
254
|
+
* relation but not the cycle. The way out is asymmetry — the MEMBERSHIP table
|
|
255
|
+
* is protected by `user_id = auth.uid()` and nothing else, and every other
|
|
256
|
+
* table subqueries INTO it. That shape was in the platform's own schema and
|
|
257
|
+
* written down nowhere; a customer recovered it by reading that schema.
|
|
258
|
+
*
|
|
259
|
+
* `(select auth.uid())` rather than a bare call: the scalar subquery is
|
|
260
|
+
* evaluated ONCE per statement instead of per row.
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* // channels: visible to members. The membership table gets the simple one.
|
|
264
|
+
* policy("member_read").for("select").to("authenticated")
|
|
265
|
+
* .memberOf("channel_members", "channel_id")
|
|
266
|
+
* // → id IN (SELECT "channel_id" FROM "channel_members"
|
|
267
|
+
* // WHERE "user_id" = (select auth.uid()))
|
|
268
|
+
*/
|
|
122
269
|
memberOf(membershipTable, foreignKey, options = {}) {
|
|
123
270
|
if (this._def.using !== null) {
|
|
124
|
-
throw new Error(
|
|
125
|
-
`policy(${this._def.name}).memberOf(): this policy already has a using() expression. Write one or the other \u2014 memberOf IS the using expression.`
|
|
126
|
-
);
|
|
271
|
+
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.`);
|
|
127
272
|
}
|
|
128
273
|
const column = options.column ?? "id";
|
|
129
274
|
const userColumn = options.userColumn ?? "user_id";
|
|
130
275
|
this._def.using = `${quote(column)} IN (SELECT ${quote(foreignKey)} FROM ${quote(membershipTable)} WHERE ${quote(userColumn)} = (select auth.uid()))`;
|
|
131
276
|
return this;
|
|
132
277
|
}
|
|
133
|
-
/**
|
|
134
|
-
withCheck(
|
|
135
|
-
this._def.withCheck =
|
|
278
|
+
/** `WITH CHECK (...)` yazma doğrulaması — `using` ile aynı iki biçim. */
|
|
279
|
+
withCheck(expr) {
|
|
280
|
+
this._def.withCheck = expr instanceof PolicyExprRef ? expr.expr : expr;
|
|
136
281
|
return this;
|
|
137
282
|
}
|
|
138
283
|
/** Set the policy mode: `"permissive"` (default, OR-combined) or
|
|
139
|
-
|
|
284
|
+
* `"restrictive"` (AND-combined). */
|
|
140
285
|
as(mode) {
|
|
141
286
|
this._def.permissive = mode === "permissive";
|
|
142
287
|
return this;
|
|
@@ -145,23 +290,93 @@ var PolicyBuilder = class {
|
|
|
145
290
|
function policy(name) {
|
|
146
291
|
return new PolicyBuilder(name);
|
|
147
292
|
}
|
|
293
|
+
__name(policy, "policy");
|
|
148
294
|
|
|
149
295
|
// src/db/schema.ts
|
|
296
|
+
var IndexBuilder = class {
|
|
297
|
+
static {
|
|
298
|
+
__name(this, "IndexBuilder");
|
|
299
|
+
}
|
|
300
|
+
_def;
|
|
301
|
+
constructor(name) {
|
|
302
|
+
if (name.trim() === "") {
|
|
303
|
+
throw new Error("index(ad): index'in ad\u0131 bo\u015F olamaz \u2014 Palbase index'leri ADA g\xF6re uzla\u015Ft\u0131r\u0131r.");
|
|
304
|
+
}
|
|
305
|
+
this._def = {
|
|
306
|
+
name
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/** Index'in kolonları. SIRA KORUNUR — çok kolonlu bir index'in anlamı sırasıdır. */
|
|
310
|
+
on(...cols) {
|
|
311
|
+
this._def.columns = cols.map((c) => {
|
|
312
|
+
const e = c.expr;
|
|
313
|
+
if (e.kind !== "col") {
|
|
314
|
+
throw new Error(`index(${this._def.name}).on(): yaln\u0131z kolon referans\u0131 al\u0131r \u2014 ifade i\xE7in onExpression("\u2026") kullan\u0131n.`);
|
|
315
|
+
}
|
|
316
|
+
return e.name;
|
|
317
|
+
});
|
|
318
|
+
return this;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* İfade index'i (`lower(email)`), kolon yerine.
|
|
322
|
+
*
|
|
323
|
+
* Metin VERBATIM emit ediliyor — `policy().using("…")` ile aynı güven duruşu.
|
|
324
|
+
* Tipli yapı bunu ifade edemiyor ve kaçış kapağını kapatmak, yazarı elle
|
|
325
|
+
* migration yazmaya iterdi.
|
|
326
|
+
*/
|
|
327
|
+
onExpression(expr) {
|
|
328
|
+
this._def.expression = expr;
|
|
329
|
+
return this;
|
|
330
|
+
}
|
|
331
|
+
/** Partial index koşulu — politika ifade dilinin ta kendisi. */
|
|
332
|
+
where(expr) {
|
|
333
|
+
this._def.where = expr.expr;
|
|
334
|
+
return this;
|
|
335
|
+
}
|
|
336
|
+
/** Sıra. Tek yönlü index'te sıra genelde önemsizdir; ORDER BY ile eşleşen
|
|
337
|
+
* bir index arandığında değildir. */
|
|
338
|
+
desc() {
|
|
339
|
+
this._def.sort = "desc";
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
342
|
+
asc() {
|
|
343
|
+
this._def.sort = "asc";
|
|
344
|
+
return this;
|
|
345
|
+
}
|
|
346
|
+
/** NULL'ların yeri — `ORDER BY … NULLS LAST` ile eşleşmesi için. */
|
|
347
|
+
nulls(where) {
|
|
348
|
+
this._def.nulls = where;
|
|
349
|
+
return this;
|
|
350
|
+
}
|
|
351
|
+
/** Covering index (`INCLUDE`): index-only scan için taşınan ama
|
|
352
|
+
* ARANMAYAN kolonlar. */
|
|
353
|
+
include(cols) {
|
|
354
|
+
this._def.include = cols;
|
|
355
|
+
return this;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
150
358
|
function toPolicyDef(p) {
|
|
151
359
|
return p instanceof PolicyBuilder ? p._def : p;
|
|
152
360
|
}
|
|
361
|
+
__name(toPolicyDef, "toPolicyDef");
|
|
153
362
|
var TABLE_META = /* @__PURE__ */ Symbol.for("palbase.table.meta");
|
|
154
363
|
function defineTable(name, input) {
|
|
155
364
|
if (name.trim() === "") {
|
|
156
365
|
throw new Error("defineTable(name, \u2026): name must not be empty");
|
|
157
366
|
}
|
|
158
|
-
const policies = (input.policies ?? []).map(toPolicyDef);
|
|
367
|
+
const policies = (input.policies?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(toPolicyDef);
|
|
159
368
|
const rls = policies.length > 0 || input.rls !== false;
|
|
160
369
|
const owned = {};
|
|
161
370
|
for (const [colName, b] of Object.entries(input.columns)) {
|
|
162
371
|
const builder = b;
|
|
163
372
|
const clone = Object.create(Object.getPrototypeOf(builder));
|
|
164
|
-
Object.defineProperty(clone, "_def", {
|
|
373
|
+
Object.defineProperty(clone, "_def", {
|
|
374
|
+
value: {
|
|
375
|
+
...builder._def
|
|
376
|
+
},
|
|
377
|
+
enumerable: true,
|
|
378
|
+
writable: true
|
|
379
|
+
});
|
|
165
380
|
owned[colName] = clone;
|
|
166
381
|
}
|
|
167
382
|
const def = {
|
|
@@ -174,22 +389,20 @@ function defineTable(name, input) {
|
|
|
174
389
|
if (input.unique !== void 0) def.unique = input.unique;
|
|
175
390
|
if (input.raw !== void 0 && input.raw.length > 0) def.raw = input.raw.slice();
|
|
176
391
|
if (input.checks !== void 0 && input.checks.length > 0) def.checks = input.checks.slice();
|
|
177
|
-
|
|
392
|
+
const declaredIndexes = (input.indexes?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map((i) => i instanceof IndexBuilder ? i._def : i);
|
|
393
|
+
if (declaredIndexes.length > 0) def.indexes = declaredIndexes;
|
|
394
|
+
if (input.appendOnly === true) def.appendOnly = true;
|
|
178
395
|
if (input.search !== void 0) {
|
|
179
396
|
const s = input.search;
|
|
180
397
|
if (s.from !== void 0) {
|
|
181
398
|
if (s.vector !== void 0) {
|
|
182
|
-
throw new Error(
|
|
183
|
-
`table ${name}: search beyan\u0131nda tek bi\xE7im kullan\u0131n \u2014 'from' (yeni) ile 'vector' (eski) birlikte olamaz`
|
|
184
|
-
);
|
|
399
|
+
throw new Error(`table ${name}: search beyan\u0131nda tek bi\xE7im kullan\u0131n \u2014 'from' (yeni) ile 'vector' (eski) birlikte olamaz`);
|
|
185
400
|
}
|
|
186
401
|
if (s.from.length === 0) {
|
|
187
402
|
throw new Error(`table ${name}: search.from bo\u015F olamaz`);
|
|
188
403
|
}
|
|
189
404
|
if (s.model === void 0) {
|
|
190
|
-
throw new Error(
|
|
191
|
-
`table ${name}: search.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin (BYO i\xE7in eski 'vector' bi\xE7imini kullan\u0131n)`
|
|
192
|
-
);
|
|
405
|
+
throw new Error(`table ${name}: search.from model'siz anlams\u0131z \u2014 auto-embed i\xE7in model verin (BYO i\xE7in eski 'vector' bi\xE7imini kullan\u0131n)`);
|
|
193
406
|
}
|
|
194
407
|
if (Array.isArray(s.text) && s.text.length === 0) {
|
|
195
408
|
throw new Error(`table ${name}: search.text bo\u015F dizi olamaz \u2014 FTS istemiyorsan text: false yaz\u0131n`);
|
|
@@ -199,14 +412,14 @@ function defineTable(name, input) {
|
|
|
199
412
|
throw new Error(`table ${name}: text:${String(s.text)} yaln\u0131z yeni bi\xE7imde ('from' ile) ge\xE7erli`);
|
|
200
413
|
}
|
|
201
414
|
if (s.text === void 0 && s.vector === void 0) {
|
|
202
|
-
throw new Error(
|
|
203
|
-
`table ${name}: search beyan\u0131 bo\u015F \u2014 en az bir kol (text ya da vector) verin, yoksa alan\u0131 hi\xE7 yazmay\u0131n`
|
|
204
|
-
);
|
|
415
|
+
throw new Error(`table ${name}: search beyan\u0131 bo\u015F \u2014 en az bir kol (text ya da vector) verin, yoksa alan\u0131 hi\xE7 yazmay\u0131n`);
|
|
205
416
|
}
|
|
206
417
|
if (s.text !== void 0 && s.text.length === 0) {
|
|
207
418
|
throw new Error(`table ${name}: search.text bo\u015F olamaz \u2014 FTS kolu istemiyorsan alan\u0131 hi\xE7 yazma`);
|
|
208
419
|
}
|
|
209
|
-
const legs = s.vector === void 0 ? [] : Array.isArray(s.vector) ? s.vector : [
|
|
420
|
+
const legs = s.vector === void 0 ? [] : Array.isArray(s.vector) ? s.vector : [
|
|
421
|
+
s.vector
|
|
422
|
+
];
|
|
210
423
|
for (const leg of legs) {
|
|
211
424
|
if (leg.model !== void 0 && (leg.from === void 0 || leg.from.length === 0)) {
|
|
212
425
|
throw new Error(`table ${name}: search.vector.model beyan edildi ama 'from' yok \u2014 embed kayna\u011F\u0131 kolonlar zorunlu (C-2)`);
|
|
@@ -227,10 +440,16 @@ function defineTable(name, input) {
|
|
|
227
440
|
for (const b of Object.values(owned)) {
|
|
228
441
|
b._def.ownerTable = def;
|
|
229
442
|
}
|
|
230
|
-
const handle = {
|
|
231
|
-
|
|
443
|
+
const handle = {
|
|
444
|
+
...owned
|
|
445
|
+
};
|
|
446
|
+
Object.defineProperty(handle, TABLE_META, {
|
|
447
|
+
value: def,
|
|
448
|
+
enumerable: false
|
|
449
|
+
});
|
|
232
450
|
return handle;
|
|
233
451
|
}
|
|
452
|
+
__name(defineTable, "defineTable");
|
|
234
453
|
var declaringSchemaOf = /* @__PURE__ */ new WeakMap();
|
|
235
454
|
function resolveReferences(tables, schemaName) {
|
|
236
455
|
for (const table of Object.values(tables)) {
|
|
@@ -238,9 +457,7 @@ function resolveReferences(tables, schemaName) {
|
|
|
238
457
|
const def = builder._def;
|
|
239
458
|
if (def.selfRefColumn !== void 0) {
|
|
240
459
|
if (!(def.selfRefColumn in table.columns)) {
|
|
241
|
-
throw new Error(
|
|
242
|
-
`table "${table.name}" column "${colName}": selfReferences("${def.selfRefColumn}") \u2014 no such column on this table`
|
|
243
|
-
);
|
|
460
|
+
throw new Error(`table "${table.name}" column "${colName}": selfReferences("${def.selfRefColumn}") \u2014 no such column on this table`);
|
|
244
461
|
}
|
|
245
462
|
def.references = {
|
|
246
463
|
table: qualifiedTableKey(schemaName, table.name),
|
|
@@ -252,23 +469,15 @@ function resolveReferences(tables, schemaName) {
|
|
|
252
469
|
const target = def.referencesThunk();
|
|
253
470
|
const owner = target?._def?.ownerTable;
|
|
254
471
|
if (owner === void 0) {
|
|
255
|
-
throw new Error(
|
|
256
|
-
`table "${table.name}" column "${colName}": references(() => \u2026) must point at a column of a table declared with defineTable(...)`
|
|
257
|
-
);
|
|
472
|
+
throw new Error(`table "${table.name}" column "${colName}": references(() => \u2026) must point at a column of a table declared with defineTable(...)`);
|
|
258
473
|
}
|
|
259
|
-
const targetColumn = Object.entries(owner.columns).find(
|
|
260
|
-
([, b]) => b._def === target._def
|
|
261
|
-
)?.[0];
|
|
474
|
+
const targetColumn = Object.entries(owner.columns).find(([, b]) => b._def === target._def)?.[0];
|
|
262
475
|
if (targetColumn === void 0) {
|
|
263
|
-
throw new Error(
|
|
264
|
-
`table "${table.name}" column "${colName}": the referenced column was not found on table "${owner.name}"`
|
|
265
|
-
);
|
|
476
|
+
throw new Error(`table "${table.name}" column "${colName}": the referenced column was not found on table "${owner.name}"`);
|
|
266
477
|
}
|
|
267
478
|
const targetSchema = declaringSchemaOf.get(owner);
|
|
268
479
|
if (targetSchema === void 0) {
|
|
269
|
-
throw new Error(
|
|
270
|
-
`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).`
|
|
271
|
-
);
|
|
480
|
+
throw new Error(`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).`);
|
|
272
481
|
}
|
|
273
482
|
def.references = {
|
|
274
483
|
table: qualifiedTableKey(targetSchema, owner.name),
|
|
@@ -277,11 +486,10 @@ function resolveReferences(tables, schemaName) {
|
|
|
277
486
|
}
|
|
278
487
|
}
|
|
279
488
|
}
|
|
489
|
+
__name(resolveReferences, "resolveReferences");
|
|
280
490
|
function defineSchema(name, input) {
|
|
281
491
|
if (typeof name !== "string") {
|
|
282
|
-
throw new Error(
|
|
283
|
-
`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.`
|
|
284
|
-
);
|
|
492
|
+
throw new Error(`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.`);
|
|
285
493
|
}
|
|
286
494
|
if (name.trim() === "") {
|
|
287
495
|
throw new Error("defineSchema(name, \u2026): name must not be empty");
|
|
@@ -290,9 +498,7 @@ function defineSchema(name, input) {
|
|
|
290
498
|
for (const handle of input.tables) {
|
|
291
499
|
const table = handle[TABLE_META];
|
|
292
500
|
if (tables[table.name] !== void 0) {
|
|
293
|
-
throw new Error(
|
|
294
|
-
`defineSchema("${name}"): two tables declare the name "${table.name}" \u2014 table names must be unique within a schema`
|
|
295
|
-
);
|
|
501
|
+
throw new Error(`defineSchema("${name}"): two tables declare the name "${table.name}" \u2014 table names must be unique within a schema`);
|
|
296
502
|
}
|
|
297
503
|
tables[table.name] = table;
|
|
298
504
|
declaringSchemaOf.set(table, name);
|
|
@@ -323,7 +529,9 @@ function defineSchema(name, input) {
|
|
|
323
529
|
}
|
|
324
530
|
}
|
|
325
531
|
}
|
|
326
|
-
const extensions = [
|
|
532
|
+
const extensions = [
|
|
533
|
+
...new Set(input.extensions ?? [])
|
|
534
|
+
];
|
|
327
535
|
return {
|
|
328
536
|
name,
|
|
329
537
|
tables,
|
|
@@ -331,46 +539,39 @@ function defineSchema(name, input) {
|
|
|
331
539
|
exposed: input.exposed ?? name === "public"
|
|
332
540
|
};
|
|
333
541
|
}
|
|
542
|
+
__name(defineSchema, "defineSchema");
|
|
334
543
|
|
|
335
544
|
// src/db/extensions.ts
|
|
336
545
|
var PALBASE_EXTENSIONS = [
|
|
337
546
|
// Search & text
|
|
338
547
|
"vector",
|
|
339
|
-
// pgvector: AI embeddings + vector similarity search (semantic search / RAG).
|
|
340
548
|
// NB: the Postgres extension is named "vector", not "pgvector" — declare "vector".
|
|
341
549
|
"pg_trgm",
|
|
342
|
-
// trigram fuzzy / typo-tolerant text search
|
|
343
550
|
"unaccent",
|
|
344
|
-
// accent-insensitive text search
|
|
345
551
|
"citext",
|
|
346
|
-
// case-insensitive text type
|
|
347
552
|
// Geospatial / location
|
|
348
553
|
"cube",
|
|
349
|
-
// multi-dimensional cubes (dependency of earthdistance)
|
|
350
554
|
"earthdistance",
|
|
351
|
-
// great-circle distance (needs cube)
|
|
352
555
|
// Data types & structures
|
|
353
556
|
"hstore",
|
|
354
|
-
// key/value pairs in a single column
|
|
355
557
|
"ltree",
|
|
356
|
-
// hierarchical tree-structured labels
|
|
357
558
|
// Indexing & constraints
|
|
358
559
|
"btree_gist",
|
|
359
|
-
// GiST operator classes for scalar types — needed for EXCLUDE
|
|
360
560
|
// constraints that mix "=" with a range/&& overlap (e.g. no-double-booking).
|
|
361
561
|
// Scheduling
|
|
362
562
|
// Crypto / ids (also installed by default; listable for explicitness)
|
|
363
563
|
"pgcrypto",
|
|
364
|
-
// cryptographic functions (hashing, encryption)
|
|
365
564
|
"uuid-ossp"
|
|
366
|
-
// UUID generation functions
|
|
367
565
|
];
|
|
368
566
|
var EXTENSION_DEPENDENCIES = {
|
|
369
|
-
earthdistance: [
|
|
567
|
+
earthdistance: [
|
|
568
|
+
"cube"
|
|
569
|
+
]
|
|
370
570
|
};
|
|
371
571
|
function isPalbaseExtension(name) {
|
|
372
572
|
return PALBASE_EXTENSIONS.includes(name);
|
|
373
573
|
}
|
|
574
|
+
__name(isPalbaseExtension, "isPalbaseExtension");
|
|
374
575
|
|
|
375
576
|
// src/db/columns.ts
|
|
376
577
|
function refuseOnVector(def, modifier) {
|
|
@@ -378,7 +579,11 @@ function refuseOnVector(def, modifier) {
|
|
|
378
579
|
throw new Error(`vector column: .${modifier}() is not supported (FR-002 \u2014 allowed: nullable()/notNull())`);
|
|
379
580
|
}
|
|
380
581
|
}
|
|
582
|
+
__name(refuseOnVector, "refuseOnVector");
|
|
381
583
|
var ColumnBuilder = class _ColumnBuilder {
|
|
584
|
+
static {
|
|
585
|
+
__name(this, "ColumnBuilder");
|
|
586
|
+
}
|
|
382
587
|
_def;
|
|
383
588
|
constructor(type, existingDef) {
|
|
384
589
|
this._def = existingDef ?? {
|
|
@@ -422,52 +627,52 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
422
627
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
423
628
|
}
|
|
424
629
|
/**
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
630
|
+
* The DATABASE assigns this column's value — a trigger, a rule, an identity.
|
|
631
|
+
*
|
|
632
|
+
* The column becomes optional on INSERT (the author has nothing to send) while
|
|
633
|
+
* the DDL stays free of a DEFAULT this schema would not honour. It is NOT
|
|
634
|
+
* `default()`: that declares a value the schema promises to write.
|
|
635
|
+
*
|
|
636
|
+
* Naming: deliberately not `generated()`. Postgres has GENERATED columns and
|
|
637
|
+
* they are a different thing; borrowing the word would send a reader — or a
|
|
638
|
+
* model writing a schema — to the wrong feature.
|
|
639
|
+
*/
|
|
435
640
|
dbAssigned() {
|
|
436
641
|
this._def.dbAssigned = true;
|
|
437
642
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
438
643
|
}
|
|
439
644
|
/** Add a foreign key reference. */
|
|
440
645
|
/**
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
646
|
+
* Declares that this column used to be called `previous`.
|
|
647
|
+
*
|
|
648
|
+
* A schema diff sees one name gone and another present; it cannot know whether
|
|
649
|
+
* you renamed a column or dropped one and added another, and the two are very
|
|
650
|
+
* different — the second loses every value. Saying so here turns the plan into
|
|
651
|
+
* `ALTER TABLE … RENAME COLUMN` instead.
|
|
652
|
+
*
|
|
653
|
+
* Once the rename has been applied the annotation is inert (the old name is no
|
|
654
|
+
* longer there to rename), so it can be deleted at your leisure.
|
|
655
|
+
*/
|
|
451
656
|
renamedFrom(previous) {
|
|
452
657
|
this._def.renamedFrom = previous;
|
|
453
658
|
return this;
|
|
454
659
|
}
|
|
455
660
|
/**
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
661
|
+
* See {@link ColumnDef.ignored}.
|
|
662
|
+
*
|
|
663
|
+
* COPIES the def rather than mutating it. The constructor takes an existing
|
|
664
|
+
* def BY REFERENCE, so every builder derived from another shares one object —
|
|
665
|
+
* `const a = slug.unique()` leaves `a._def === slug._def`. An in-place
|
|
666
|
+
* `ignored = true` therefore marks every column sharing that def, including
|
|
667
|
+
* one another table actively reads, and the gate would let THAT column be
|
|
668
|
+
* dropped. Measured before this copy existed.
|
|
669
|
+
*
|
|
670
|
+
* The aliasing is older than this method and other fields leak through it too.
|
|
671
|
+
* The reason this one cannot wait: every other leak produces a VISIBLE schema
|
|
672
|
+
* difference — the plan shows it, the DDL shows it. This one is invisible by
|
|
673
|
+
* design (no DDL, no diff, no plan line), so its only effect is to disarm a
|
|
674
|
+
* safety gate in silence.
|
|
675
|
+
*/
|
|
471
676
|
ignored() {
|
|
472
677
|
return new _ColumnBuilder(this._def.type, {
|
|
473
678
|
...this._def,
|
|
@@ -475,47 +680,67 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
475
680
|
});
|
|
476
681
|
}
|
|
477
682
|
/**
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
683
|
+
* Foreign key onto another table's column.
|
|
684
|
+
*
|
|
685
|
+
* The target is a THUNK, not a direct reference. In a cycle (`x → y`, `y → x`)
|
|
686
|
+
* the second table does not exist yet when the first is built; a direct
|
|
687
|
+
* reference makes TypeScript chase its own tail (TS7022 — measured, and making
|
|
688
|
+
* the return type independent of the target does NOT help). The thunk is
|
|
689
|
+
* invoked in `defineSchema`, where every binding exists and every table
|
|
690
|
+
* already knows its name.
|
|
691
|
+
*
|
|
692
|
+
* In a cycle, ONE side needs an explicit return type:
|
|
693
|
+
* `references((): AnyColumn => y.id)`. One side is enough — measured.
|
|
694
|
+
* For a self-reference use `selfReferences(column)`: no thunk, no annotation.
|
|
695
|
+
*
|
|
696
|
+
* `as` names the FORWARD relation (`author_id` → `author` by default);
|
|
697
|
+
* `reverseAs` names the REVERSE one on the parent, whose default is this
|
|
698
|
+
* table's own name (`users.posts`). Two foreign keys from one table onto one
|
|
699
|
+
* parent therefore need a `reverseAs` on at least one of them — the reverse
|
|
700
|
+
* names would otherwise both be this table's name.
|
|
701
|
+
*/
|
|
497
702
|
references(target, opts) {
|
|
498
703
|
refuseOnVector(this._def, "references");
|
|
499
704
|
if (typeof target !== "function") {
|
|
500
|
-
throw new Error(
|
|
501
|
-
`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.`
|
|
502
|
-
);
|
|
705
|
+
throw new Error(`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.`);
|
|
503
706
|
}
|
|
504
707
|
this._def.referencesThunk = target;
|
|
505
708
|
if (opts?.as !== void 0) this._def.refAs = opts.as;
|
|
506
709
|
if (opts?.reverseAs !== void 0) this._def.reverseAs = opts.reverseAs;
|
|
507
710
|
if (opts?.onDelete !== void 0) this._def.onDeleteAction = opts.onDelete;
|
|
711
|
+
if (opts?.index === false) this._def.index = false;
|
|
712
|
+
return new _ColumnBuilder(this._def.type, this._def);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Bu kolon `increment()` / `decrement()` ile güncelleniyor (FR-049).
|
|
716
|
+
*
|
|
717
|
+
* Deploy kontrolcü kodunu OKUMAZ, o yüzden bildirimin söylemesi gerekiyor —
|
|
718
|
+
* ve söylediği anda plan bir şeyi görebiliyor: aynı kolon hem sayaç hem
|
|
719
|
+
* indeksliyse her güncelleme HOT'u kaybeder.
|
|
720
|
+
*
|
|
721
|
+
* ZİNCİR (D-028+D-030): HOT kaybı → ölü tuple → autovacuum yükü → ve
|
|
722
|
+
* autovacuum worker'ları KÜME GENELİNDE bir kaynak, yani bedeli başka
|
|
723
|
+
* kiracıların tabloları da öder.
|
|
724
|
+
*
|
|
725
|
+
* Sektörde çare "dokümana uyarı yaz"dır, çünkü index'i ekleyen kişi
|
|
726
|
+
* `increment()`'i yazan kişi değildir. Bu bildirimde ikisi de YAN YANA
|
|
727
|
+
* duruyor.
|
|
728
|
+
*
|
|
729
|
+
* Uyarı, HATA DEĞİL: sayaç kolonunu indekslemek bazen doğru karardır.
|
|
730
|
+
*/
|
|
731
|
+
counter() {
|
|
732
|
+
this._def.counter = true;
|
|
508
733
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
509
734
|
}
|
|
510
735
|
/**
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
736
|
+
* Foreign key onto THIS table (`parent_id → id`) — category trees, comment
|
|
737
|
+
* replies, org charts.
|
|
738
|
+
*
|
|
739
|
+
* No thunk and no type annotation: the target table is the one being declared,
|
|
740
|
+
* so there is nothing to defer and nothing for TypeScript to chase in a circle.
|
|
741
|
+
* Drizzle forces an explicit `(): AnyPgColumn =>` here because its reference
|
|
742
|
+
* always goes through a callback; measured, we do not need one.
|
|
743
|
+
*/
|
|
519
744
|
selfReferences(column, opts) {
|
|
520
745
|
refuseOnVector(this._def, "selfReferences");
|
|
521
746
|
this._def.selfRefColumn = column;
|
|
@@ -535,23 +760,23 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
535
760
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
536
761
|
}
|
|
537
762
|
/**
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
763
|
+
* Declare how this column's value is projected in and out of the process.
|
|
764
|
+
*
|
|
765
|
+
* The DDL does not move: `numeric` stays `numeric`, and the driver still hands
|
|
766
|
+
* back what Postgres sent. What changes is the type the row surface exposes —
|
|
767
|
+
* it becomes `Target`:
|
|
768
|
+
*
|
|
769
|
+
* amount: numeric().transform<number>({ fromDb: Number, toDb: String })
|
|
770
|
+
*
|
|
771
|
+
* `numeric` surfacing as `string` is CORRECT (a JS number cannot hold
|
|
772
|
+
* arbitrary precision), and that is exactly why this exists: application code
|
|
773
|
+
* that does arithmetic on the column otherwise rewrites the same
|
|
774
|
+
* `Number(row.amount)` / `String(x)` pair in every controller that touches it,
|
|
775
|
+
* and each rewrite is a place the two directions can drift apart.
|
|
776
|
+
*
|
|
777
|
+
* A transform is a PROJECTION, never a constraint: it lives only in this
|
|
778
|
+
* process, so it can neither validate nor migrate what is stored.
|
|
779
|
+
*/
|
|
555
780
|
transform(fns) {
|
|
556
781
|
this._def.transform = fns;
|
|
557
782
|
return new _ColumnBuilder(this._def.type, this._def);
|
|
@@ -560,30 +785,40 @@ var ColumnBuilder = class _ColumnBuilder {
|
|
|
560
785
|
function uuid() {
|
|
561
786
|
return new ColumnBuilder("uuid");
|
|
562
787
|
}
|
|
788
|
+
__name(uuid, "uuid");
|
|
563
789
|
function text() {
|
|
564
790
|
return new ColumnBuilder("text");
|
|
565
791
|
}
|
|
792
|
+
__name(text, "text");
|
|
566
793
|
function integer() {
|
|
567
794
|
return new ColumnBuilder("integer");
|
|
568
795
|
}
|
|
796
|
+
__name(integer, "integer");
|
|
569
797
|
function bigint() {
|
|
570
798
|
return new ColumnBuilder("bigint");
|
|
571
799
|
}
|
|
800
|
+
__name(bigint, "bigint");
|
|
572
801
|
function boolean() {
|
|
573
802
|
return new ColumnBuilder("boolean");
|
|
574
803
|
}
|
|
804
|
+
__name(boolean, "boolean");
|
|
575
805
|
function timestamp() {
|
|
576
806
|
return new ColumnBuilder("timestamp");
|
|
577
807
|
}
|
|
808
|
+
__name(timestamp, "timestamp");
|
|
578
809
|
function jsonb() {
|
|
579
810
|
return new ColumnBuilder("jsonb");
|
|
580
811
|
}
|
|
812
|
+
__name(jsonb, "jsonb");
|
|
581
813
|
function enumType(name, values) {
|
|
582
814
|
const builder = new ColumnBuilder("enum");
|
|
583
815
|
builder._def.enumName = name;
|
|
584
|
-
builder._def.enumValues = [
|
|
816
|
+
builder._def.enumValues = [
|
|
817
|
+
...values
|
|
818
|
+
];
|
|
585
819
|
return builder;
|
|
586
820
|
}
|
|
821
|
+
__name(enumType, "enumType");
|
|
587
822
|
function vector(dimensions) {
|
|
588
823
|
if (!Number.isInteger(dimensions) || dimensions < 1 || dimensions > 2e3) {
|
|
589
824
|
throw new Error(`vector(): dimensions must be an integer in [1, 2000], got ${String(dimensions)}`);
|
|
@@ -592,33 +827,53 @@ function vector(dimensions) {
|
|
|
592
827
|
b._def.dimensions = dimensions;
|
|
593
828
|
return b;
|
|
594
829
|
}
|
|
830
|
+
__name(vector, "vector");
|
|
595
831
|
function ownedByUser() {
|
|
596
832
|
const b = new ColumnBuilder("text");
|
|
597
833
|
b._def.nullable = false;
|
|
598
|
-
b._def.references = {
|
|
834
|
+
b._def.references = {
|
|
835
|
+
table: "auth.users",
|
|
836
|
+
column: "id"
|
|
837
|
+
};
|
|
599
838
|
b._def.onDeleteAction = "cascade";
|
|
600
839
|
b._def.owns = true;
|
|
601
840
|
return b;
|
|
602
841
|
}
|
|
842
|
+
__name(ownedByUser, "ownedByUser");
|
|
603
843
|
function userRef(opts) {
|
|
604
844
|
const b = new ColumnBuilder("text");
|
|
605
|
-
b._def.references = {
|
|
845
|
+
b._def.references = {
|
|
846
|
+
table: "auth.users",
|
|
847
|
+
column: "id"
|
|
848
|
+
};
|
|
606
849
|
b._def.onDeleteAction = opts.onDelete;
|
|
607
850
|
if (opts.as !== void 0) b._def.refAs = opts.as;
|
|
608
851
|
return b;
|
|
609
852
|
}
|
|
853
|
+
__name(userRef, "userRef");
|
|
610
854
|
function installationRef(opts) {
|
|
611
855
|
const b = new ColumnBuilder("text");
|
|
612
|
-
b._def.references = {
|
|
856
|
+
b._def.references = {
|
|
857
|
+
table: "auth.installations",
|
|
858
|
+
column: "id"
|
|
859
|
+
};
|
|
613
860
|
b._def.onDeleteAction = opts.onDelete;
|
|
614
861
|
if (opts.as !== void 0) b._def.refAs = opts.as;
|
|
615
862
|
return b;
|
|
616
863
|
}
|
|
864
|
+
__name(installationRef, "installationRef");
|
|
617
865
|
|
|
618
866
|
// src/db/raw.ts
|
|
619
867
|
function raw(name, up, opts) {
|
|
620
|
-
return {
|
|
868
|
+
return {
|
|
869
|
+
name,
|
|
870
|
+
up,
|
|
871
|
+
...opts?.down != null ? {
|
|
872
|
+
down: opts.down
|
|
873
|
+
} : {}
|
|
874
|
+
};
|
|
621
875
|
}
|
|
876
|
+
__name(raw, "raw");
|
|
622
877
|
|
|
623
878
|
// src/db/embedding.ts
|
|
624
879
|
var openai = {
|
|
@@ -627,23 +882,62 @@ var openai = {
|
|
|
627
882
|
provider: "openai",
|
|
628
883
|
model,
|
|
629
884
|
apiKeyName: opts?.apiKeyName ?? "OPENAI_API_KEY",
|
|
630
|
-
...opts?.dimensions !== void 0 ? {
|
|
631
|
-
|
|
885
|
+
...opts?.dimensions !== void 0 ? {
|
|
886
|
+
dimensions: opts.dimensions
|
|
887
|
+
} : {},
|
|
888
|
+
...opts?.baseURL !== void 0 ? {
|
|
889
|
+
baseURL: opts.baseURL
|
|
890
|
+
} : {}
|
|
632
891
|
};
|
|
633
892
|
},
|
|
634
893
|
chat(model) {
|
|
635
|
-
return {
|
|
894
|
+
return {
|
|
895
|
+
provider: "openai",
|
|
896
|
+
model
|
|
897
|
+
};
|
|
636
898
|
}
|
|
637
899
|
};
|
|
638
900
|
|
|
901
|
+
// src/db/input-guards.ts
|
|
902
|
+
var REF_BRAND = /* @__PURE__ */ Symbol.for("palbase.db.ref");
|
|
903
|
+
function brandRef(v, kind) {
|
|
904
|
+
Object.defineProperty(v, REF_BRAND, {
|
|
905
|
+
value: kind,
|
|
906
|
+
enumerable: false
|
|
907
|
+
});
|
|
908
|
+
return v;
|
|
909
|
+
}
|
|
910
|
+
__name(brandRef, "brandRef");
|
|
911
|
+
function brandOf(v) {
|
|
912
|
+
if (typeof v !== "object" || v === null) return void 0;
|
|
913
|
+
return Object.hasOwn(v, REF_BRAND) ? v[REF_BRAND] : void 0;
|
|
914
|
+
}
|
|
915
|
+
__name(brandOf, "brandOf");
|
|
916
|
+
function isColRef(v) {
|
|
917
|
+
return brandOf(v) === "col" && typeof v.$col === "string";
|
|
918
|
+
}
|
|
919
|
+
__name(isColRef, "isColRef");
|
|
920
|
+
function isSqlFragment(v) {
|
|
921
|
+
if (brandOf(v) !== "sql") return false;
|
|
922
|
+
const f = v.$sql;
|
|
923
|
+
return f !== void 0 && Array.isArray(f.text) && Array.isArray(f.values);
|
|
924
|
+
}
|
|
925
|
+
__name(isSqlFragment, "isSqlFragment");
|
|
926
|
+
|
|
639
927
|
// src/db/tx-plan.ts
|
|
640
928
|
var TxRefError = class extends Error {
|
|
929
|
+
static {
|
|
930
|
+
__name(this, "TxRefError");
|
|
931
|
+
}
|
|
641
932
|
constructor(message) {
|
|
642
933
|
super(message);
|
|
643
934
|
this.name = "TxRefError";
|
|
644
935
|
}
|
|
645
936
|
};
|
|
646
937
|
var TxPlanError = class extends Error {
|
|
938
|
+
static {
|
|
939
|
+
__name(this, "TxPlanError");
|
|
940
|
+
}
|
|
647
941
|
constructor(message) {
|
|
648
942
|
super(message);
|
|
649
943
|
this.name = "TxPlanError";
|
|
@@ -662,126 +956,193 @@ var TRAPPED_PROPS = [
|
|
|
662
956
|
];
|
|
663
957
|
function trap(prop, what, hint) {
|
|
664
958
|
const name = typeof prop === "symbol" ? prop.description ?? String(prop) : prop;
|
|
665
|
-
throw new TxRefError(
|
|
666
|
-
`${what} was used as a value (via \`${name}\`). Nothing in a transaction callback has run yet, so there is no value to read. ${hint}`
|
|
667
|
-
);
|
|
959
|
+
throw new TxRefError(`${what} was used as a value (via \`${name}\`). Nothing in a transaction callback has run yet, so there is no value to read. ${hint}`);
|
|
668
960
|
}
|
|
961
|
+
__name(trap, "trap");
|
|
669
962
|
function now() {
|
|
670
|
-
return makeExpr({
|
|
963
|
+
return makeExpr({
|
|
964
|
+
fn: "now"
|
|
965
|
+
});
|
|
671
966
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
967
|
+
__name(now, "now");
|
|
968
|
+
function increment(by) {
|
|
969
|
+
assertAmount(by, "increment");
|
|
970
|
+
return makeExpr({
|
|
971
|
+
fn: "inc",
|
|
972
|
+
by
|
|
973
|
+
});
|
|
675
974
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
975
|
+
__name(increment, "increment");
|
|
976
|
+
var inc = increment;
|
|
977
|
+
function decrement(by) {
|
|
978
|
+
assertAmount(by, "decrement");
|
|
979
|
+
return makeExpr({
|
|
980
|
+
fn: "dec",
|
|
981
|
+
by
|
|
982
|
+
});
|
|
679
983
|
}
|
|
680
|
-
|
|
681
|
-
|
|
984
|
+
__name(decrement, "decrement");
|
|
985
|
+
var dec = decrement;
|
|
986
|
+
function assertAmount(by, fn) {
|
|
987
|
+
if (typeof by === "string") {
|
|
988
|
+
if (!/^-?\d+(\.\d+)?$/.test(by)) {
|
|
989
|
+
throw new TxPlanError(`${fn}() ondal\u0131k bir say\u0131 metni bekliyor, "${by}" ald\u0131 \u2014 kabul edilen bi\xE7im: "12", "-12", "12.50"`);
|
|
990
|
+
}
|
|
991
|
+
} else if (typeof by !== "number" || !Number.isFinite(by)) {
|
|
682
992
|
throw new TxPlanError(`${fn}() needs a finite number, got ${String(by)}`);
|
|
683
993
|
}
|
|
994
|
+
const negative = typeof by === "string" ? by.trimStart().startsWith("-") : by < 0;
|
|
995
|
+
if (negative) {
|
|
996
|
+
const other = fn === "increment" ? "decrement" : "increment";
|
|
997
|
+
throw new TxPlanError(`${fn}() negatif miktar almaz ("${String(by)}"). Ters y\xF6n i\xE7in ${other}() kullan\u0131n \u2014 i\u015Faretin miktarda saklanmas\u0131, y\xF6n\xFC okuyan hi\xE7bir kod taraf\u0131ndan g\xF6r\xFClmezdi.`);
|
|
998
|
+
}
|
|
684
999
|
}
|
|
1000
|
+
__name(assertAmount, "assertAmount");
|
|
685
1001
|
function makeExpr(expr) {
|
|
686
|
-
return new Proxy(
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
return void 0;
|
|
1002
|
+
return new Proxy({
|
|
1003
|
+
[EXPR]: expr
|
|
1004
|
+
}, {
|
|
1005
|
+
get(target, prop) {
|
|
1006
|
+
if (prop === EXPR) return target[EXPR];
|
|
1007
|
+
if (TRAPPED_PROPS.includes(prop)) {
|
|
1008
|
+
trap(prop, "A plan expression", "Write it into an operation instead.");
|
|
695
1009
|
}
|
|
1010
|
+
return void 0;
|
|
696
1011
|
}
|
|
697
|
-
);
|
|
1012
|
+
});
|
|
698
1013
|
}
|
|
1014
|
+
__name(makeExpr, "makeExpr");
|
|
699
1015
|
function makeRef(op, field) {
|
|
700
|
-
const target = {
|
|
1016
|
+
const target = {
|
|
1017
|
+
[REF]: {
|
|
1018
|
+
op,
|
|
1019
|
+
field
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
701
1022
|
return new Proxy(target, {
|
|
702
1023
|
get(t, prop) {
|
|
703
1024
|
if (prop === REF) return t[REF];
|
|
704
1025
|
if (TRAPPED_PROPS.includes(prop)) {
|
|
705
|
-
trap(
|
|
706
|
-
prop,
|
|
707
|
-
`\`${field}\` of a row this transaction has not written yet`,
|
|
708
|
-
"Pass it to another operation in the same plan, or return it from the callback and read it after `transaction()` resolves."
|
|
709
|
-
);
|
|
1026
|
+
trap(prop, `\`${field}\` of a row this transaction has not written yet`, "Pass it to another operation in the same plan, or return it from the callback and read it after `transaction()` resolves.");
|
|
710
1027
|
}
|
|
711
1028
|
return void 0;
|
|
712
1029
|
}
|
|
713
1030
|
});
|
|
714
1031
|
}
|
|
1032
|
+
__name(makeRef, "makeRef");
|
|
715
1033
|
function makeRowHandle(op) {
|
|
716
|
-
const target = {
|
|
1034
|
+
const target = {
|
|
1035
|
+
[ROW]: op
|
|
1036
|
+
};
|
|
717
1037
|
return new Proxy(target, {
|
|
718
1038
|
get(t, prop) {
|
|
719
1039
|
if (prop === ROW) return t[ROW];
|
|
720
1040
|
if (TRAPPED_PROPS.includes(prop)) {
|
|
721
|
-
trap(
|
|
722
|
-
prop,
|
|
723
|
-
"A row this transaction has not written yet",
|
|
724
|
-
"Read one of its columns to reference it, or return the row from the callback and read it after `transaction()` resolves."
|
|
725
|
-
);
|
|
1041
|
+
trap(prop, "A row this transaction has not written yet", "Read one of its columns to reference it, or return the row from the callback and read it after `transaction()` resolves.");
|
|
726
1042
|
}
|
|
727
1043
|
if (typeof prop === "symbol") return void 0;
|
|
728
1044
|
return makeRef(op, prop);
|
|
729
1045
|
}
|
|
730
1046
|
});
|
|
731
1047
|
}
|
|
1048
|
+
__name(makeRowHandle, "makeRowHandle");
|
|
732
1049
|
function refDescriptor(v) {
|
|
733
1050
|
if (typeof v !== "object" || v === null) return null;
|
|
734
1051
|
const d = v[REF];
|
|
735
1052
|
return isRefDescriptor(d) ? d : null;
|
|
736
1053
|
}
|
|
1054
|
+
__name(refDescriptor, "refDescriptor");
|
|
737
1055
|
function isRefDescriptor(d) {
|
|
738
1056
|
return typeof d === "object" && d !== null && typeof d.op === "number" && typeof d.field === "string";
|
|
739
1057
|
}
|
|
1058
|
+
__name(isRefDescriptor, "isRefDescriptor");
|
|
740
1059
|
function rowOpIndex(v) {
|
|
741
1060
|
if (typeof v !== "object" || v === null) return null;
|
|
742
1061
|
const op = v[ROW];
|
|
743
1062
|
return typeof op === "number" ? op : null;
|
|
744
1063
|
}
|
|
1064
|
+
__name(rowOpIndex, "rowOpIndex");
|
|
745
1065
|
function exprOf(v) {
|
|
746
1066
|
if (typeof v !== "object" || v === null) return null;
|
|
747
1067
|
const e = v[EXPR];
|
|
748
1068
|
return typeof e === "object" && e !== null ? e : null;
|
|
749
1069
|
}
|
|
1070
|
+
__name(exprOf, "exprOf");
|
|
750
1071
|
function isRowsHandle(v) {
|
|
751
1072
|
return typeof v === "object" && v !== null && v[ROWS] !== void 0;
|
|
752
1073
|
}
|
|
1074
|
+
__name(isRowsHandle, "isRowsHandle");
|
|
753
1075
|
function encodeValue(value, column, allowColumnExpr) {
|
|
754
1076
|
const ref = refDescriptor(value);
|
|
755
|
-
if (ref) return {
|
|
1077
|
+
if (ref) return brandRef({
|
|
1078
|
+
$ref: {
|
|
1079
|
+
op: ref.op,
|
|
1080
|
+
field: ref.field
|
|
1081
|
+
}
|
|
1082
|
+
}, "ref");
|
|
756
1083
|
const expr = exprOf(value);
|
|
757
1084
|
if (expr) {
|
|
758
1085
|
if (expr.fn !== "now" && !allowColumnExpr) {
|
|
759
|
-
throw new TxPlanError(
|
|
760
|
-
`\`${column}\`: ${expr.fn}() reads the column's current value, so it is only valid in updateWhere(where, set).`
|
|
761
|
-
);
|
|
1086
|
+
throw new TxPlanError(`\`${column}\`: ${expr.fn}() reads the column's current value, so it is only valid in updateWhere(where, set).`);
|
|
762
1087
|
}
|
|
763
|
-
return {
|
|
1088
|
+
return {
|
|
1089
|
+
$expr: expr
|
|
1090
|
+
};
|
|
764
1091
|
}
|
|
765
1092
|
if (rowOpIndex(value) !== null) {
|
|
766
|
-
throw new TxPlanError(
|
|
767
|
-
`\`${column}\`: a row handle is not a value. Read the column you meant (e.g. \`row.id\`).`
|
|
768
|
-
);
|
|
1093
|
+
throw new TxPlanError(`\`${column}\`: a row handle is not a value. Read the column you meant (e.g. \`row.id\`).`);
|
|
769
1094
|
}
|
|
770
1095
|
if (isRowsHandle(value)) {
|
|
771
|
-
throw new TxPlanError(
|
|
772
|
-
`\`${column}\`: an operation result is not a value. Declare an expectation first (\`.expectOne(err)\`) and read a column from the row.`
|
|
773
|
-
);
|
|
1096
|
+
throw new TxPlanError(`\`${column}\`: an operation result is not a value. Declare an expectation first (\`.expectOne(err)\`) and read a column from the row.`);
|
|
774
1097
|
}
|
|
775
1098
|
assertNoNestedHandles(value, column);
|
|
776
1099
|
return value;
|
|
777
1100
|
}
|
|
1101
|
+
__name(encodeValue, "encodeValue");
|
|
1102
|
+
function encodeFilterValue(value, column) {
|
|
1103
|
+
const ref = refDescriptor(value);
|
|
1104
|
+
if (ref) return brandRef({
|
|
1105
|
+
$ref: {
|
|
1106
|
+
op: ref.op,
|
|
1107
|
+
field: ref.field
|
|
1108
|
+
}
|
|
1109
|
+
}, "ref");
|
|
1110
|
+
const expr = exprOf(value);
|
|
1111
|
+
if (expr) {
|
|
1112
|
+
throw new TxPlanError(`\`${column}\`: ${expr.fn}() bir YAZMA ifadesi, kar\u015F\u0131la\u015Ft\u0131rma de\u011Fil \u2014 filtrede kullan\u0131lamaz. Kolonu bir de\u011Ferle ya da col() ile kar\u015F\u0131la\u015Ft\u0131r\u0131n.`);
|
|
1113
|
+
}
|
|
1114
|
+
if (rowOpIndex(value) !== null) {
|
|
1115
|
+
throw new TxPlanError(`\`${column}\`: a row handle is not a value. Read the column you meant (e.g. \`row.id\`).`);
|
|
1116
|
+
}
|
|
1117
|
+
if (isRowsHandle(value)) {
|
|
1118
|
+
throw new TxPlanError(`\`${column}\`: an operation result is not a value. Declare an expectation first (\`.expectOne(err)\`) and read a column from the row.`);
|
|
1119
|
+
}
|
|
1120
|
+
if (Array.isArray(value)) return value.map((v) => encodeFilterValue(v, column));
|
|
1121
|
+
if (value !== null && typeof value === "object" && !(value instanceof Date) && !isColRef(value) && !isSqlFragment(value)) {
|
|
1122
|
+
const out = {};
|
|
1123
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1124
|
+
out[k] = encodeFilterValue(v, column);
|
|
1125
|
+
}
|
|
1126
|
+
return out;
|
|
1127
|
+
}
|
|
1128
|
+
return value;
|
|
1129
|
+
}
|
|
1130
|
+
__name(encodeFilterValue, "encodeFilterValue");
|
|
1131
|
+
function encodeFilterMap(map) {
|
|
1132
|
+
const out = {};
|
|
1133
|
+
for (const key of Object.keys(map).sort()) {
|
|
1134
|
+
const value = map[key];
|
|
1135
|
+
if (value === void 0) continue;
|
|
1136
|
+
out[key] = encodeFilterValue(value, key);
|
|
1137
|
+
}
|
|
1138
|
+
return out;
|
|
1139
|
+
}
|
|
1140
|
+
__name(encodeFilterMap, "encodeFilterMap");
|
|
778
1141
|
function assertNoNestedHandles(value, column) {
|
|
779
1142
|
if (typeof value !== "object" || value === null) return;
|
|
780
1143
|
if (value instanceof Date) return;
|
|
781
1144
|
if (refDescriptor(value) || exprOf(value) || rowOpIndex(value) !== null || isRowsHandle(value)) {
|
|
782
|
-
throw new TxPlanError(
|
|
783
|
-
`\`${column}\`: a plan handle is nested inside a value. The server would store it as literal JSON, not resolve it. Put the reference directly in the column.`
|
|
784
|
-
);
|
|
1145
|
+
throw new TxPlanError(`\`${column}\`: a plan handle is nested inside a value. The server would store it as literal JSON, not resolve it. Put the reference directly in the column.`);
|
|
785
1146
|
}
|
|
786
1147
|
if (Array.isArray(value)) {
|
|
787
1148
|
for (const item of value) assertNoNestedHandles(item, column);
|
|
@@ -791,6 +1152,7 @@ function assertNoNestedHandles(value, column) {
|
|
|
791
1152
|
assertNoNestedHandles(item, column);
|
|
792
1153
|
}
|
|
793
1154
|
}
|
|
1155
|
+
__name(assertNoNestedHandles, "assertNoNestedHandles");
|
|
794
1156
|
function encodeMap(map, allowColumnExpr) {
|
|
795
1157
|
const out = {};
|
|
796
1158
|
for (const key of Object.keys(map).sort()) {
|
|
@@ -800,12 +1162,11 @@ function encodeMap(map, allowColumnExpr) {
|
|
|
800
1162
|
}
|
|
801
1163
|
return out;
|
|
802
1164
|
}
|
|
1165
|
+
__name(encodeMap, "encodeMap");
|
|
803
1166
|
var SKIPPED_OP = -1;
|
|
804
|
-
var TxRowsImpl = class {
|
|
805
|
-
|
|
806
|
-
this
|
|
807
|
-
this.opIndex = opIndex;
|
|
808
|
-
this.what = what;
|
|
1167
|
+
var TxRowsImpl = class TxRowsImpl2 {
|
|
1168
|
+
static {
|
|
1169
|
+
__name(this, "TxRowsImpl");
|
|
809
1170
|
}
|
|
810
1171
|
builder;
|
|
811
1172
|
opIndex;
|
|
@@ -813,12 +1174,15 @@ var TxRowsImpl = class {
|
|
|
813
1174
|
// Present so `isRowsHandle` recognises the object; never read for its value.
|
|
814
1175
|
[ROWS] = true;
|
|
815
1176
|
guarded = false;
|
|
1177
|
+
constructor(builder, opIndex, what) {
|
|
1178
|
+
this.builder = builder;
|
|
1179
|
+
this.opIndex = opIndex;
|
|
1180
|
+
this.what = what;
|
|
1181
|
+
}
|
|
816
1182
|
// The type-level `await` guard made real: TS rejects `await rows` at compile
|
|
817
1183
|
// time, and reaching this means someone called `.then(...)` by hand.
|
|
818
1184
|
then() {
|
|
819
|
-
throw new TxRefError(
|
|
820
|
-
`${this.what} cannot be awaited: a transaction callback builds a plan, it does not run statements. Remove the \`await\`.`
|
|
821
|
-
);
|
|
1185
|
+
throw new TxRefError(`${this.what} cannot be awaited: a transaction callback builds a plan, it does not run statements. Remove the \`await\`.`);
|
|
822
1186
|
}
|
|
823
1187
|
expectOne(error) {
|
|
824
1188
|
this.declareGuard("one", 1, error);
|
|
@@ -839,14 +1203,10 @@ var TxRowsImpl = class {
|
|
|
839
1203
|
}
|
|
840
1204
|
declareGuard(kind, n, error) {
|
|
841
1205
|
if (!(error instanceof Error)) {
|
|
842
|
-
throw new TxPlanError(
|
|
843
|
-
`${this.what}: an expectation needs the Error to throw when it does not hold (e.g. \`.expect\u2026(new Conflict("already accepted"))\`).`
|
|
844
|
-
);
|
|
1206
|
+
throw new TxPlanError(`${this.what}: an expectation needs the Error to throw when it does not hold (e.g. \`.expect\u2026(new Conflict("already accepted"))\`).`);
|
|
845
1207
|
}
|
|
846
1208
|
if (this.guarded) {
|
|
847
|
-
throw new TxPlanError(
|
|
848
|
-
`${this.what} already has an expectation. One operation carries one expectation; declare the second one on its own operation.`
|
|
849
|
-
);
|
|
1209
|
+
throw new TxPlanError(`${this.what} already has an expectation. One operation carries one expectation; declare the second one on its own operation.`);
|
|
850
1210
|
}
|
|
851
1211
|
this.guarded = true;
|
|
852
1212
|
if (this.opIndex === SKIPPED_OP) return;
|
|
@@ -858,115 +1218,119 @@ function assertGuardCount(n, fn) {
|
|
|
858
1218
|
throw new TxPlanError(`${fn}(n) needs a non-negative integer, got ${String(n)}`);
|
|
859
1219
|
}
|
|
860
1220
|
}
|
|
1221
|
+
__name(assertGuardCount, "assertGuardCount");
|
|
861
1222
|
var MAX_OPS = 1e3;
|
|
862
1223
|
var MAX_ROWS = 5e3;
|
|
863
1224
|
var TxPlanBuilder = class {
|
|
1225
|
+
static {
|
|
1226
|
+
__name(this, "TxPlanBuilder");
|
|
1227
|
+
}
|
|
864
1228
|
ops = [];
|
|
865
1229
|
/** Errors handed to expectations, indexed by the `slot` the server echoes. */
|
|
866
1230
|
slots = [];
|
|
867
1231
|
/** The table surface handed to the callback. Untyped here; the public
|
|
868
|
-
|
|
1232
|
+
* `transaction()` signatures put the schema types on top. */
|
|
869
1233
|
table(name) {
|
|
870
1234
|
return {
|
|
871
|
-
insert: (values) => {
|
|
1235
|
+
insert: /* @__PURE__ */ __name((values) => {
|
|
872
1236
|
const encoded = encodeMap(values, false);
|
|
873
1237
|
if (Object.keys(encoded).length === 0) {
|
|
874
1238
|
throw new TxPlanError(`${name}.insert() needs at least one column`);
|
|
875
1239
|
}
|
|
876
|
-
return this.push({
|
|
877
|
-
|
|
878
|
-
|
|
1240
|
+
return this.push({
|
|
1241
|
+
op: "insert",
|
|
1242
|
+
table: name,
|
|
1243
|
+
values: encoded
|
|
1244
|
+
}, `${name}.insert()`);
|
|
1245
|
+
}, "insert"),
|
|
1246
|
+
put: /* @__PURE__ */ __name((values, options) => {
|
|
879
1247
|
const encoded = encodeMap(values, false);
|
|
880
1248
|
if (Object.keys(encoded).length === 0) {
|
|
881
|
-
throw new TxPlanError(`${name}.
|
|
1249
|
+
throw new TxPlanError(`${name}.put() needs at least one column`);
|
|
882
1250
|
}
|
|
883
1251
|
if (options.onConflict.length === 0) {
|
|
884
|
-
throw new TxPlanError(`${name}.
|
|
1252
|
+
throw new TxPlanError(`${name}.put() needs at least one onConflict column`);
|
|
885
1253
|
}
|
|
886
|
-
return this.push(
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1254
|
+
return this.push({
|
|
1255
|
+
op: "upsert",
|
|
1256
|
+
table: name,
|
|
1257
|
+
values: encoded,
|
|
1258
|
+
onConflict: options.onConflict
|
|
1259
|
+
}, `${name}.upsert()`);
|
|
1260
|
+
}, "put"),
|
|
1261
|
+
insertMany: /* @__PURE__ */ __name((rows, opts) => {
|
|
892
1262
|
if (rows.length === 0) {
|
|
893
1263
|
return new TxRowsImpl(this, SKIPPED_OP, `${name}.insertMany()`);
|
|
894
1264
|
}
|
|
895
1265
|
if (rows.length > MAX_ROWS) {
|
|
896
|
-
throw new TxPlanError(
|
|
897
|
-
`${name}.insertMany() has ${rows.length} rows; the limit is ${MAX_ROWS}. Split the write across requests.`
|
|
898
|
-
);
|
|
1266
|
+
throw new TxPlanError(`${name}.insertMany() has ${rows.length} rows; the limit is ${MAX_ROWS}. Split the write across requests.`);
|
|
899
1267
|
}
|
|
900
1268
|
const encoded = rows.map((row) => encodeMap(row, false));
|
|
901
1269
|
assertUniformRows(encoded, name);
|
|
902
1270
|
if (opts !== void 0 && opts.onConflict.length === 0) {
|
|
903
|
-
throw new TxPlanError(
|
|
904
|
-
`${name}.insertMany() was given a conflict action with no onConflict columns. Postgres matches a collision on columns, so name them.`
|
|
905
|
-
);
|
|
1271
|
+
throw new TxPlanError(`${name}.insertMany() was given a conflict action with no onConflict columns. Postgres matches a collision on columns, so name them.`);
|
|
906
1272
|
}
|
|
907
|
-
return this.push(
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
);
|
|
919
|
-
},
|
|
920
|
-
updateWhere: (where, set) => {
|
|
921
|
-
const encodedWhere =
|
|
1273
|
+
return this.push({
|
|
1274
|
+
op: "insertMany",
|
|
1275
|
+
table: name,
|
|
1276
|
+
rows: encoded,
|
|
1277
|
+
// Omitted entirely when no options were given, so the op a plain
|
|
1278
|
+
// insertMany produces is byte-identical to the one it produced
|
|
1279
|
+
// before this option existed.
|
|
1280
|
+
...opts !== void 0 ? {
|
|
1281
|
+
onConflict: opts.onConflict,
|
|
1282
|
+
action: opts.action ?? "ignore"
|
|
1283
|
+
} : {}
|
|
1284
|
+
}, `${name}.insertMany()`);
|
|
1285
|
+
}, "insertMany"),
|
|
1286
|
+
updateWhere: /* @__PURE__ */ __name((where, set) => {
|
|
1287
|
+
const encodedWhere = encodeFilterMap(where);
|
|
922
1288
|
const encodedSet = encodeMap(set, true);
|
|
923
1289
|
if (Object.keys(encodedWhere).length === 0) {
|
|
924
|
-
throw new TxPlanError(
|
|
925
|
-
`${name}.updateWhere() needs a filter. An update with no filter rewrites the whole table.`
|
|
926
|
-
);
|
|
1290
|
+
throw new TxPlanError(`${name}.updateWhere() needs a filter. An update with no filter rewrites the whole table.`);
|
|
927
1291
|
}
|
|
928
1292
|
if (Object.keys(encodedSet).length === 0) {
|
|
929
1293
|
throw new TxPlanError(`${name}.updateWhere() needs at least one column to set`);
|
|
930
1294
|
}
|
|
931
|
-
return this.push(
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1295
|
+
return this.push({
|
|
1296
|
+
op: "update",
|
|
1297
|
+
table: name,
|
|
1298
|
+
set: encodedSet,
|
|
1299
|
+
where: encodedWhere
|
|
1300
|
+
}, `${name}.updateWhere()`);
|
|
1301
|
+
}, "updateWhere"),
|
|
1302
|
+
deleteWhere: /* @__PURE__ */ __name((where) => {
|
|
1303
|
+
const encodedWhere = encodeFilterMap(where);
|
|
938
1304
|
if (Object.keys(encodedWhere).length === 0) {
|
|
939
|
-
throw new TxPlanError(
|
|
940
|
-
`${name}.deleteWhere() needs a filter. A delete with no filter empties the table.`
|
|
941
|
-
);
|
|
1305
|
+
throw new TxPlanError(`${name}.deleteWhere() needs a filter. A delete with no filter empties the table.`);
|
|
942
1306
|
}
|
|
943
|
-
return this.push(
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const
|
|
1307
|
+
return this.push({
|
|
1308
|
+
op: "delete",
|
|
1309
|
+
table: name,
|
|
1310
|
+
where: encodedWhere
|
|
1311
|
+
}, `${name}.deleteWhere()`);
|
|
1312
|
+
}, "deleteWhere"),
|
|
1313
|
+
select: /* @__PURE__ */ __name((where, options) => {
|
|
1314
|
+
const op = {
|
|
1315
|
+
op: "select",
|
|
1316
|
+
table: name
|
|
1317
|
+
};
|
|
1318
|
+
const encodedWhere = encodeFilterMap(where ?? {});
|
|
951
1319
|
if (Object.keys(encodedWhere).length > 0) op.where = encodedWhere;
|
|
952
1320
|
if (options?.limit !== void 0) {
|
|
953
1321
|
if (!Number.isInteger(options.limit) || options.limit < 0) {
|
|
954
|
-
throw new TxPlanError(
|
|
955
|
-
`${name}.select(): limit needs a non-negative integer, got ${String(options.limit)}`
|
|
956
|
-
);
|
|
1322
|
+
throw new TxPlanError(`${name}.select(): limit needs a non-negative integer, got ${String(options.limit)}`);
|
|
957
1323
|
}
|
|
958
1324
|
op.limit = options.limit;
|
|
959
1325
|
}
|
|
960
1326
|
if (options?.lock !== void 0) op.lock = options.lock;
|
|
961
1327
|
return this.push(op, `${name}.select()`);
|
|
962
|
-
}
|
|
1328
|
+
}, "select")
|
|
963
1329
|
};
|
|
964
1330
|
}
|
|
965
1331
|
push(op, what) {
|
|
966
1332
|
if (this.ops.length >= MAX_OPS) {
|
|
967
|
-
throw new TxPlanError(
|
|
968
|
-
`this transaction has ${MAX_OPS} operations, which is the limit. Use insertMany() for bulk writes, or split the work across requests.`
|
|
969
|
-
);
|
|
1333
|
+
throw new TxPlanError(`this transaction has ${MAX_OPS} operations, which is the limit. Use insertMany() for bulk writes, or split the work across requests.`);
|
|
970
1334
|
}
|
|
971
1335
|
const index = this.ops.length;
|
|
972
1336
|
this.ops.push(op);
|
|
@@ -978,14 +1342,20 @@ var TxPlanBuilder = class {
|
|
|
978
1342
|
if (!op) throw new TxPlanError(`internal: expectation on unknown operation ${opIndex}`);
|
|
979
1343
|
const slot = this.slots.length;
|
|
980
1344
|
this.slots.push(error);
|
|
981
|
-
op.guard = {
|
|
1345
|
+
op.guard = {
|
|
1346
|
+
kind,
|
|
1347
|
+
n,
|
|
1348
|
+
slot
|
|
1349
|
+
};
|
|
982
1350
|
}
|
|
983
1351
|
/** The serialisable plan. Empty when the callback described no writes. */
|
|
984
1352
|
body() {
|
|
985
|
-
return {
|
|
1353
|
+
return {
|
|
1354
|
+
ops: this.ops
|
|
1355
|
+
};
|
|
986
1356
|
}
|
|
987
1357
|
/** The error the server's `slot` selects, or `null` when it names one this
|
|
988
|
-
|
|
1358
|
+
* plan never declared (a server/client disagreement, not a tenant error). */
|
|
989
1359
|
errorForSlot(slot) {
|
|
990
1360
|
return this.slots[slot] ?? null;
|
|
991
1361
|
}
|
|
@@ -998,29 +1368,24 @@ function assertUniformRows(rows, table) {
|
|
|
998
1368
|
for (let i = 1; i < rows.length; i++) {
|
|
999
1369
|
const got = Object.keys(rows[i]);
|
|
1000
1370
|
if (got.join(",") !== wantKey) {
|
|
1001
|
-
throw new TxPlanError(
|
|
1002
|
-
`${table}.insertMany(): every row must set the same columns. Row 0 sets [${want.join(", ")}] but row ${i} sets [${got.join(", ")}]. (A property set to \`undefined\` counts as absent \u2014 use \`null\`.)`
|
|
1003
|
-
);
|
|
1371
|
+
throw new TxPlanError(`${table}.insertMany(): every row must set the same columns. Row 0 sets [${want.join(", ")}] but row ${i} sets [${got.join(", ")}]. (A property set to \`undefined\` counts as absent \u2014 use \`null\`.)`);
|
|
1004
1372
|
}
|
|
1005
1373
|
}
|
|
1006
1374
|
}
|
|
1375
|
+
__name(assertUniformRows, "assertUniformRows");
|
|
1007
1376
|
function materializeResult(value, results) {
|
|
1008
1377
|
const ref = refDescriptor(value);
|
|
1009
1378
|
if (ref) {
|
|
1010
1379
|
const row = rowOf(results, ref.op, `\`${ref.field}\``);
|
|
1011
1380
|
if (!(ref.field in row)) {
|
|
1012
|
-
throw new TxPlanError(
|
|
1013
|
-
`the transaction's operation ${ref.op} returned no column \`${ref.field}\`.`
|
|
1014
|
-
);
|
|
1381
|
+
throw new TxPlanError(`the transaction's operation ${ref.op} returned no column \`${ref.field}\`.`);
|
|
1015
1382
|
}
|
|
1016
1383
|
return row[ref.field];
|
|
1017
1384
|
}
|
|
1018
1385
|
const rowOp = rowOpIndex(value);
|
|
1019
1386
|
if (rowOp !== null) return rowOf(results, rowOp, "a row");
|
|
1020
1387
|
if (isRowsHandle(value)) {
|
|
1021
|
-
throw new TxPlanError(
|
|
1022
|
-
"an operation result cannot be returned from a transaction callback: its row count is not known until the plan runs. Declare an expectation (`.expectOne(err)`) and return the row, or a column of it."
|
|
1023
|
-
);
|
|
1388
|
+
throw new TxPlanError("an operation result cannot be returned from a transaction callback: its row count is not known until the plan runs. Declare an expectation (`.expectOne(err)`) and return the row, or a column of it.");
|
|
1024
1389
|
}
|
|
1025
1390
|
if (Array.isArray(value)) return value.map((item) => materializeResult(item, results));
|
|
1026
1391
|
if (isPlainObject(value)) {
|
|
@@ -1030,28 +1395,27 @@ function materializeResult(value, results) {
|
|
|
1030
1395
|
}
|
|
1031
1396
|
return value;
|
|
1032
1397
|
}
|
|
1398
|
+
__name(materializeResult, "materializeResult");
|
|
1033
1399
|
function rowOf(results, opIndex, what) {
|
|
1034
1400
|
const result = results[opIndex];
|
|
1035
1401
|
if (!result) {
|
|
1036
|
-
throw new TxPlanError(
|
|
1037
|
-
`the transaction returned no result for operation ${opIndex}, so ${what} cannot be read.`
|
|
1038
|
-
);
|
|
1402
|
+
throw new TxPlanError(`the transaction returned no result for operation ${opIndex}, so ${what} cannot be read.`);
|
|
1039
1403
|
}
|
|
1040
1404
|
const row = result.rows[0];
|
|
1041
1405
|
if (!row) {
|
|
1042
|
-
throw new TxPlanError(
|
|
1043
|
-
`the transaction's operation ${opIndex} returned no row, so ${what} cannot be read.`
|
|
1044
|
-
);
|
|
1406
|
+
throw new TxPlanError(`the transaction's operation ${opIndex} returned no row, so ${what} cannot be read.`);
|
|
1045
1407
|
}
|
|
1046
1408
|
return row;
|
|
1047
1409
|
}
|
|
1410
|
+
__name(rowOf, "rowOf");
|
|
1048
1411
|
function isPlainObject(value) {
|
|
1049
1412
|
if (typeof value !== "object" || value === null) return false;
|
|
1050
1413
|
const proto = Object.getPrototypeOf(value);
|
|
1051
1414
|
return proto === Object.prototype || proto === null;
|
|
1052
1415
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1416
|
+
__name(isPlainObject, "isPlainObject");
|
|
1417
|
+
async function runTxPlan(transport, handle, builder, fn) {
|
|
1418
|
+
const returned = fn(handle);
|
|
1055
1419
|
const body = builder.body();
|
|
1056
1420
|
if (body.ops.length === 0) {
|
|
1057
1421
|
return materializeResult(returned, []);
|
|
@@ -1064,6 +1428,7 @@ async function runTxPlan(transport, tables, builder, fn) {
|
|
|
1064
1428
|
}
|
|
1065
1429
|
return materializeResult(returned, response.results);
|
|
1066
1430
|
}
|
|
1431
|
+
__name(runTxPlan, "runTxPlan");
|
|
1067
1432
|
function translateRejection(err, builder) {
|
|
1068
1433
|
if (typeof err !== "object" || err === null) return err;
|
|
1069
1434
|
const rejection = err;
|
|
@@ -1072,25 +1437,72 @@ function translateRejection(err, builder) {
|
|
|
1072
1437
|
}
|
|
1073
1438
|
return builder.errorForSlot(rejection.slot) ?? err;
|
|
1074
1439
|
}
|
|
1440
|
+
__name(translateRejection, "translateRejection");
|
|
1441
|
+
|
|
1442
|
+
// src/errors.ts
|
|
1443
|
+
var HTTP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("palbase.backend.httpError");
|
|
1444
|
+
var HttpError = class extends Error {
|
|
1445
|
+
static {
|
|
1446
|
+
__name(this, "HttpError");
|
|
1447
|
+
}
|
|
1448
|
+
status;
|
|
1449
|
+
error;
|
|
1450
|
+
errorDescription;
|
|
1451
|
+
data;
|
|
1452
|
+
/** See {@link HTTP_ERROR_BRAND} — how the engine recognises this across SDK copies. */
|
|
1453
|
+
[HTTP_ERROR_BRAND] = true;
|
|
1454
|
+
constructor(status, error, errorDescription, data) {
|
|
1455
|
+
super(errorDescription);
|
|
1456
|
+
this.name = "HttpError";
|
|
1457
|
+
this.status = status;
|
|
1458
|
+
this.error = error;
|
|
1459
|
+
this.errorDescription = errorDescription;
|
|
1460
|
+
if (data !== void 0) {
|
|
1461
|
+
this.data = data;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
/**
|
|
1465
|
+
* Serialize to the standard Palbase error response format.
|
|
1466
|
+
* The `requestId` is injected by the runtime layer from the request context.
|
|
1467
|
+
* When called without arguments (e.g. JSON.stringify), request_id is omitted.
|
|
1468
|
+
* When `data` is set, it is appended as a strict-superset field.
|
|
1469
|
+
*/
|
|
1470
|
+
toJSON(requestId) {
|
|
1471
|
+
const result = {
|
|
1472
|
+
error: this.error,
|
|
1473
|
+
error_description: this.errorDescription,
|
|
1474
|
+
status: this.status
|
|
1475
|
+
};
|
|
1476
|
+
if (requestId) {
|
|
1477
|
+
result.request_id = requestId;
|
|
1478
|
+
}
|
|
1479
|
+
if (this.data !== void 0) {
|
|
1480
|
+
result.data = this.data;
|
|
1481
|
+
}
|
|
1482
|
+
return result;
|
|
1483
|
+
}
|
|
1484
|
+
};
|
|
1075
1485
|
|
|
1076
1486
|
// src/db/typed-db.ts
|
|
1077
1487
|
function makeTypedTable(name, raw2) {
|
|
1078
1488
|
return {
|
|
1079
|
-
insert: (data) => raw2.insert(name, data),
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
where,
|
|
1088
|
-
|
|
1089
|
-
),
|
|
1090
|
-
|
|
1091
|
-
|
|
1489
|
+
insert: /* @__PURE__ */ __name((data) => raw2.insert(name, data), "insert"),
|
|
1490
|
+
put: /* @__PURE__ */ __name((q) => raw2.put(name, q.data, {
|
|
1491
|
+
onConflict: q.onConflict
|
|
1492
|
+
}), "put"),
|
|
1493
|
+
update: /* @__PURE__ */ __name((q) => raw2.update(name, q.where.id, q.set), "update"),
|
|
1494
|
+
delete: /* @__PURE__ */ __name((id) => raw2.delete(name, id), "delete"),
|
|
1495
|
+
findById: /* @__PURE__ */ __name((id) => raw2.findById(name, id), "findById"),
|
|
1496
|
+
findMany: /* @__PURE__ */ __name((q) => {
|
|
1497
|
+
const { where, ...opts } = q ?? {};
|
|
1498
|
+
return raw2.findMany(name, where, opts);
|
|
1499
|
+
}, "findMany"),
|
|
1500
|
+
updateMany: /* @__PURE__ */ __name((q) => raw2.updateMany(name, q.where, q.set), "updateMany"),
|
|
1501
|
+
deleteMany: /* @__PURE__ */ __name((q) => raw2.deleteMany(name, q.where), "deleteMany"),
|
|
1502
|
+
count: /* @__PURE__ */ __name((q) => raw2.count(name, q?.where), "count")
|
|
1092
1503
|
};
|
|
1093
1504
|
}
|
|
1505
|
+
__name(makeTypedTable, "makeTypedTable");
|
|
1094
1506
|
function makeTypedDB(schema, raw2) {
|
|
1095
1507
|
const tables = {};
|
|
1096
1508
|
for (const key of Object.keys(schema.tables)) {
|
|
@@ -1108,16 +1520,14 @@ function makeTypedDB(schema, raw2) {
|
|
|
1108
1520
|
const tableDef = schema.tables[key];
|
|
1109
1521
|
if (tableDef !== void 0) planTables[key] = builder.table(tableDef.name);
|
|
1110
1522
|
}
|
|
1111
|
-
return runTxPlan(
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
builder,
|
|
1115
|
-
fn
|
|
1116
|
-
);
|
|
1523
|
+
return runTxPlan(raw2, {
|
|
1524
|
+
tables: planTables
|
|
1525
|
+
}, builder, fn);
|
|
1117
1526
|
}
|
|
1118
1527
|
};
|
|
1119
1528
|
return result;
|
|
1120
1529
|
}
|
|
1530
|
+
__name(makeTypedDB, "makeTypedDB");
|
|
1121
1531
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1122
1532
|
0 && (module.exports = {
|
|
1123
1533
|
EXTENSION_DEPENDENCIES,
|