@palbase/backend 27.0.0 → 28.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 +165 -39
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +4 -4
- package/dist/{chunk-GYK6QYS4.js → chunk-3TUJWHC2.js} +28 -3
- package/dist/chunk-3TUJWHC2.js.map +1 -0
- package/dist/{chunk-OO7R25AI.js → chunk-75YROPRZ.js} +118 -39
- package/dist/chunk-75YROPRZ.js.map +1 -0
- package/dist/{chunk-TS4U7NBD.js → chunk-IVZERLTM.js} +2 -2
- package/dist/{chunk-I3C4PFIW.js → chunk-RVP6BTEZ.js} +63 -6
- package/dist/chunk-RVP6BTEZ.js.map +1 -0
- package/dist/{chunk-DRZFQRJI.js → chunk-SNDXY565.js} +3 -2
- package/dist/chunk-SNDXY565.js.map +1 -0
- package/dist/db/index.cjs +30 -1
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +3 -3
- package/dist/engine/index.cjs +175 -39
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +3 -3
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +11 -4
- package/dist/{index-VtToZmUm.d.cts → index-9C3JHxg-.d.cts} +112 -5
- package/dist/{index-NuzRCuxe.d.ts → index-BbvOoZFr.d.ts} +112 -5
- package/dist/{index-Bve7BBTL.d.cts → index-DtISj9QX.d.cts} +125 -22
- package/dist/{index-BrvvxSpn.d.ts → index-dTTLlHIn.d.ts} +125 -22
- package/dist/index.cjs +93 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -22
- package/dist/index.d.ts +6 -22
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/{registry-B0eyOF9x.d.ts → registry-JQNIX-eA.d.ts} +1 -1
- package/dist/{registry-Bk9_rbNd.d.cts → registry-qIPM5BQe.d.cts} +1 -1
- package/dist/test/index.cjs +100 -6
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +88 -6
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +103 -1
- package/docs/llms-full.txt +104 -2
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/chunk-DRZFQRJI.js.map +0 -1
- package/dist/chunk-GYK6QYS4.js.map +0 -1
- package/dist/chunk-I3C4PFIW.js.map +0 -1
- package/dist/chunk-OO7R25AI.js.map +0 -1
- /package/dist/{chunk-TS4U7NBD.js.map → chunk-IVZERLTM.js.map} +0 -0
package/dist/db/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { f as AnyColumn, k as ColumnBuilder, l as ColumnDef, m as ColumnMap, n as ColumnType, E as EXTENSION_DEPENDENCIES, s as EmbeddingModelRef, u as EnvServiceDatabase, w as EnvTypedDatabase, N as InsertShape, V as Materialized, a0 as OnDeleteAction, a1 as PALBASE_EXTENSIONS, aA as PalbaseExtension, bx as PolicyBuilder, by as PolicyCommand, bz as PolicyDef, bC as PolicyMode, bE as RawConstraintDef, bG as Ref, bI as RowShape, S as SchemaDef, bR as TABLE_META, bS as TableDef, bT as TableHandle, bU as TableInput, bW as TxColumnExpr, bX as TxInsertShape, bZ as TxNow, b_ as TxPlan, T as TxPlanBody, b$ as TxPlanError, c0 as TxPlanHandle, c1 as TxPlanOpResult, c2 as TxPlanRejection, b as TxPlanResponse, c3 as TxRefError, c4 as TxRow, c5 as TxRows, c6 as TxSelectOptions, c7 as TxSetShape, c9 as TxTable, ca as TxTables, cb as TxWhere, ch as TypedDB, ci as TypedTable, cj as TypedTx, cs as bigint, ct as boolean, cv as dec, cy as defineSchema, cz as defineTable, cA as enumType, cC as inc, cF as installationRef, cG as integer, cH as isPalbaseExtension, cJ as jsonb, cK as makeTypedDB, cL as now, cP as openai, cQ as ownedByUser, cR as policy, cS as raw, cU as text, cV as timestamp, cW as userRef, cX as uuid, cY as vector } from '../index-
|
|
1
|
+
export { f as AnyColumn, k as ColumnBuilder, l as ColumnDef, m as ColumnMap, n as ColumnType, E as EXTENSION_DEPENDENCIES, s as EmbeddingModelRef, u as EnvServiceDatabase, w as EnvTypedDatabase, N as InsertShape, V as Materialized, a0 as OnDeleteAction, a1 as PALBASE_EXTENSIONS, aA as PalbaseExtension, bx as PolicyBuilder, by as PolicyCommand, bz as PolicyDef, bC as PolicyMode, bE as RawConstraintDef, bG as Ref, bI as RowShape, S as SchemaDef, bR as TABLE_META, bS as TableDef, bT as TableHandle, bU as TableInput, bW as TxColumnExpr, bX as TxInsertShape, bZ as TxNow, b_ as TxPlan, T as TxPlanBody, b$ as TxPlanError, c0 as TxPlanHandle, c1 as TxPlanOpResult, c2 as TxPlanRejection, b as TxPlanResponse, c3 as TxRefError, c4 as TxRow, c5 as TxRows, c6 as TxSelectOptions, c7 as TxSetShape, c9 as TxTable, ca as TxTables, cb as TxWhere, ch as TypedDB, ci as TypedTable, cj as TypedTx, cs as bigint, ct as boolean, cv as dec, cy as defineSchema, cz as defineTable, cA as enumType, cC as inc, cF as installationRef, cG as integer, cH as isPalbaseExtension, cJ as jsonb, cK as makeTypedDB, cL as now, cP as openai, cQ as ownedByUser, cR as policy, cS as raw, cU as text, cV as timestamp, cW as userRef, cX as uuid, cY as vector } from '../index-DtISj9QX.cjs';
|
|
2
2
|
import './env.cjs';
|
|
3
3
|
import '../stack.cjs';
|
|
4
4
|
import 'zod';
|
package/dist/db/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { f as AnyColumn, k as ColumnBuilder, l as ColumnDef, m as ColumnMap, n as ColumnType, E as EXTENSION_DEPENDENCIES, s as EmbeddingModelRef, u as EnvServiceDatabase, w as EnvTypedDatabase, N as InsertShape, V as Materialized, a0 as OnDeleteAction, a1 as PALBASE_EXTENSIONS, aA as PalbaseExtension, bx as PolicyBuilder, by as PolicyCommand, bz as PolicyDef, bC as PolicyMode, bE as RawConstraintDef, bG as Ref, bI as RowShape, S as SchemaDef, bR as TABLE_META, bS as TableDef, bT as TableHandle, bU as TableInput, bW as TxColumnExpr, bX as TxInsertShape, bZ as TxNow, b_ as TxPlan, T as TxPlanBody, b$ as TxPlanError, c0 as TxPlanHandle, c1 as TxPlanOpResult, c2 as TxPlanRejection, b as TxPlanResponse, c3 as TxRefError, c4 as TxRow, c5 as TxRows, c6 as TxSelectOptions, c7 as TxSetShape, c9 as TxTable, ca as TxTables, cb as TxWhere, ch as TypedDB, ci as TypedTable, cj as TypedTx, cs as bigint, ct as boolean, cv as dec, cy as defineSchema, cz as defineTable, cA as enumType, cC as inc, cF as installationRef, cG as integer, cH as isPalbaseExtension, cJ as jsonb, cK as makeTypedDB, cL as now, cP as openai, cQ as ownedByUser, cR as policy, cS as raw, cU as text, cV as timestamp, cW as userRef, cX as uuid, cY as vector } from '../index-
|
|
1
|
+
export { f as AnyColumn, k as ColumnBuilder, l as ColumnDef, m as ColumnMap, n as ColumnType, E as EXTENSION_DEPENDENCIES, s as EmbeddingModelRef, u as EnvServiceDatabase, w as EnvTypedDatabase, N as InsertShape, V as Materialized, a0 as OnDeleteAction, a1 as PALBASE_EXTENSIONS, aA as PalbaseExtension, bx as PolicyBuilder, by as PolicyCommand, bz as PolicyDef, bC as PolicyMode, bE as RawConstraintDef, bG as Ref, bI as RowShape, S as SchemaDef, bR as TABLE_META, bS as TableDef, bT as TableHandle, bU as TableInput, bW as TxColumnExpr, bX as TxInsertShape, bZ as TxNow, b_ as TxPlan, T as TxPlanBody, b$ as TxPlanError, c0 as TxPlanHandle, c1 as TxPlanOpResult, c2 as TxPlanRejection, b as TxPlanResponse, c3 as TxRefError, c4 as TxRow, c5 as TxRows, c6 as TxSelectOptions, c7 as TxSetShape, c9 as TxTable, ca as TxTables, cb as TxWhere, ch as TypedDB, ci as TypedTable, cj as TypedTx, cs as bigint, ct as boolean, cv as dec, cy as defineSchema, cz as defineTable, cA as enumType, cC as inc, cF as installationRef, cG as integer, cH as isPalbaseExtension, cJ as jsonb, cK as makeTypedDB, cL as now, cP as openai, cQ as ownedByUser, cR as policy, cS as raw, cU as text, cV as timestamp, cW as userRef, cX as uuid, cY as vector } from '../index-dTTLlHIn.js';
|
|
2
2
|
import './env.js';
|
|
3
3
|
import '../stack.js';
|
|
4
4
|
import 'zod';
|
package/dist/db/index.js
CHANGED
|
@@ -21,17 +21,17 @@ import {
|
|
|
21
21
|
userRef,
|
|
22
22
|
uuid,
|
|
23
23
|
vector
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-IVZERLTM.js";
|
|
25
25
|
import {
|
|
26
26
|
makeTypedDB
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-SNDXY565.js";
|
|
28
28
|
import {
|
|
29
29
|
TxPlanError,
|
|
30
30
|
TxRefError,
|
|
31
31
|
dec,
|
|
32
32
|
inc,
|
|
33
33
|
now
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-3TUJWHC2.js";
|
|
35
35
|
import "../chunk-CGNN2PUH.js";
|
|
36
36
|
import "../chunk-VXPNPVAG.js";
|
|
37
37
|
export {
|
package/dist/engine/index.cjs
CHANGED
|
@@ -23,6 +23,8 @@ var engine_exports = {};
|
|
|
23
23
|
__export(engine_exports, {
|
|
24
24
|
AuthVerifier: () => AuthVerifier,
|
|
25
25
|
BootRefused: () => BootRefused,
|
|
26
|
+
DECLARATION_REFUSAL: () => DECLARATION_REFUSAL,
|
|
27
|
+
DeclarationRefused: () => DeclarationRefused,
|
|
26
28
|
RateLimiter: () => RateLimiter,
|
|
27
29
|
buildRouteTable: () => buildRouteTable,
|
|
28
30
|
createApp: () => createApp,
|
|
@@ -32,6 +34,7 @@ __export(engine_exports, {
|
|
|
32
34
|
effectiveAuth: () => effectiveAuth,
|
|
33
35
|
hostAllowed: () => hostAllowed,
|
|
34
36
|
installEgressFence: () => installEgressFence,
|
|
37
|
+
isDeclarationRefused: () => isDeclarationRefused,
|
|
35
38
|
loadConfig: () => loadConfig,
|
|
36
39
|
makeMemoryCache: () => makeMemoryCache,
|
|
37
40
|
matchRoute: () => matchRoute,
|
|
@@ -62,9 +65,11 @@ __name(brandOf, "brandOf");
|
|
|
62
65
|
function looksLikeUnbrandedRef(v) {
|
|
63
66
|
if (typeof v !== "object" || v === null) return null;
|
|
64
67
|
if (brandOf(v) !== void 0) return null;
|
|
68
|
+
if (isColumnExpr(v)) return null;
|
|
65
69
|
const o = v;
|
|
66
70
|
if (typeof o.$col === "string") return "col";
|
|
67
71
|
if (o.$sql !== void 0 && typeof o.$sql === "object" && o.$sql !== null) return "sql";
|
|
72
|
+
if (o.$expr !== void 0 && typeof o.$expr === "object" && o.$expr !== null) return "expr";
|
|
68
73
|
return null;
|
|
69
74
|
}
|
|
70
75
|
__name(looksLikeUnbrandedRef, "looksLikeUnbrandedRef");
|
|
@@ -91,6 +96,16 @@ function isSqlFragment(v) {
|
|
|
91
96
|
}
|
|
92
97
|
__name(isSqlFragment, "isSqlFragment");
|
|
93
98
|
var TX_EXPR = /* @__PURE__ */ Symbol.for("palbase.tx.expr");
|
|
99
|
+
function isNowExpr(v) {
|
|
100
|
+
if (!isColumnExpr(v)) return false;
|
|
101
|
+
try {
|
|
102
|
+
const e = v[TX_EXPR];
|
|
103
|
+
return typeof e === "object" && e !== null && e.fn === "now";
|
|
104
|
+
} catch {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
__name(isNowExpr, "isNowExpr");
|
|
94
109
|
function isColumnExpr(v) {
|
|
95
110
|
if (typeof v !== "object" && typeof v !== "function") return false;
|
|
96
111
|
if (v === null) return false;
|
|
@@ -104,8 +119,11 @@ __name(isColumnExpr, "isColumnExpr");
|
|
|
104
119
|
function assertNoExpressionHandles(caller, table, cols, data) {
|
|
105
120
|
for (const c of cols) {
|
|
106
121
|
const v = data[c];
|
|
122
|
+
if (isNowExpr(v)) {
|
|
123
|
+
throw new Error(`${caller}(${table}): "${c}" now() ald\u0131 \u2014 bu yolda de\u011Fer beklenir. Sat\u0131r EKLEN\u0130RKEN sunucu saatini yazman\u0131n yolu kolonu defaultNow() ile bildirmek (varsay\u0131lan kolonun yan\u0131nda durur, her \xE7a\u011Fr\u0131da tekrarlanmaz); var olan bir sat\u0131r\u0131 damgalamak i\xE7in updateMany({ where, set: { ${c}: now() } }) ya da $transaction i\xE7inde tx.public.${table}.updateWhere(where, { ${c}: now() }).`);
|
|
124
|
+
}
|
|
107
125
|
if (isColumnExpr(v)) {
|
|
108
|
-
throw new Error(`${caller}(${table}): "${c}" bir ifade tutama\u011F\u0131 ald\u0131 (increment()/decrement()
|
|
126
|
+
throw new Error(`${caller}(${table}): "${c}" bir ifade tutama\u011F\u0131 ald\u0131 (increment()/decrement()). Bu yolda de\u011Fer beklenir. Saya\xE7 art\u0131\u015F\u0131 i\xE7in updateMany({ where, set: { ${c}: increment(n) } }) ya da $transaction i\xE7inde tx.public.${table}.updateWhere(where, { ${c}: increment(n) }) kullan\u0131n.`);
|
|
109
127
|
}
|
|
110
128
|
if (isColRef(v)) {
|
|
111
129
|
throw new Error(`${caller}(${table}): "${c}" bir col() ald\u0131. Kolon referans\u0131 yaln\u0131z F\u0130LTREDE durabilir; bir kolonun de\u011Ferini ba\u015Fka bir kolona yazmak i\xE7in $query kullan\u0131n.`);
|
|
@@ -173,6 +191,7 @@ function assertUsableFilter(caller, table, where) {
|
|
|
173
191
|
}
|
|
174
192
|
if (cond === null || typeof cond !== "object" || Array.isArray(cond)) continue;
|
|
175
193
|
if (isColRef(cond)) continue;
|
|
194
|
+
if (isNowExpr(cond)) continue;
|
|
176
195
|
const entries = Object.entries(cond);
|
|
177
196
|
if (entries.length === 0) {
|
|
178
197
|
throw new Error(`${caller}(${table}): where.${col} bo\u015F bir operat\xF6r nesnesi ({}) \u2014 hi\xE7bir ko\u015Ful \xFCretmez, yani bu alan filtreden sessizce D\xDC\u015EERD\u0130. Ko\u015Ful kurulmayacaksa anahtar\u0131 filtreye hi\xE7 koymay\u0131n (D-21).`);
|
|
@@ -314,6 +333,11 @@ function encodeValue(value, column, allowColumnExpr) {
|
|
|
314
333
|
field: ref.field
|
|
315
334
|
}
|
|
316
335
|
}, "ref");
|
|
336
|
+
if (isNowExpr(value)) return {
|
|
337
|
+
$expr: {
|
|
338
|
+
fn: "now"
|
|
339
|
+
}
|
|
340
|
+
};
|
|
317
341
|
const expr = exprOf(value);
|
|
318
342
|
if (expr) {
|
|
319
343
|
if (expr.fn !== "now" && !allowColumnExpr) {
|
|
@@ -391,7 +415,9 @@ function encodeMap(map, allowColumnExpr) {
|
|
|
391
415
|
const out = {};
|
|
392
416
|
for (const key of Object.keys(map).sort()) {
|
|
393
417
|
const value = map[key];
|
|
394
|
-
if (value === void 0)
|
|
418
|
+
if (value === void 0) {
|
|
419
|
+
throw new TxPlanError(`${key} de\u011Feri undefined \u2014 bu bir yazma de\u011Feri de\u011Fil. Anahtar duruyor ama de\u011Feri yok, yani kolon sessizce YAZILMAZDI (istek g\xF6vdesinden gelen bir alan\u0131n eksik olmas\u0131 bu \u015Fekilde g\xF6r\xFCn\xFCr). Kolon varsay\u0131lan\u0131n\u0131 istiyorsan\u0131z anahtar\u0131 hi\xE7 koymay\u0131n; NULL yazmak istiyorsan\u0131z a\xE7\u0131k\xE7a null yaz\u0131n.`);
|
|
420
|
+
}
|
|
395
421
|
out[key] = encodeValue(value, key, allowColumnExpr);
|
|
396
422
|
}
|
|
397
423
|
return out;
|
|
@@ -919,6 +945,10 @@ function makeTableProxy(ops, prefix) {
|
|
|
919
945
|
const name = `${prefix}${prop}`;
|
|
920
946
|
return {
|
|
921
947
|
insert: /* @__PURE__ */ __name((data) => ops().insert(name, data), "insert"),
|
|
948
|
+
// DÖRDÜNCÜ FİİL, aynı gerekçeyle: tip söz veriyor, ops katmanı
|
|
949
|
+
// uyguluyor, ve bir handler'ın gerçekten dokunduğu yer BURASI.
|
|
950
|
+
// `runtime-table-verbs` kapısı bunu adıyla saydı.
|
|
951
|
+
insertMany: /* @__PURE__ */ __name((rows, opts) => ops().insertMany(name, rows, opts), "insertMany"),
|
|
922
952
|
update: /* @__PURE__ */ __name((q) => ops().update(name, q.where.id, q.set), "update"),
|
|
923
953
|
delete: /* @__PURE__ */ __name((id) => ops().delete(name, id), "delete"),
|
|
924
954
|
findById: /* @__PURE__ */ __name((id) => ops().findById(name, id), "findById"),
|
|
@@ -975,6 +1005,7 @@ function makeTypedSurface(raw) {
|
|
|
975
1005
|
$claim: /* @__PURE__ */ __name((table, unique, extra) => reco.claim(table, unique, extra), "$claim"),
|
|
976
1006
|
$lockRows: /* @__PURE__ */ __name((table, ids) => reco.lockRows(table, ids), "$lockRows"),
|
|
977
1007
|
$advisoryXactLock: /* @__PURE__ */ __name((key) => reco.advisoryXactLock(key), "$advisoryXactLock"),
|
|
1008
|
+
$insertMany: /* @__PURE__ */ __name((table, rows, opts) => raw.insertMany(table, rows, opts), "$insertMany"),
|
|
978
1009
|
$supersede: /* @__PURE__ */ __name((table, id, row) => raw.supersede(table, id, row), "$supersede")
|
|
979
1010
|
};
|
|
980
1011
|
const base = Object.assign(ops, {
|
|
@@ -1164,6 +1195,24 @@ ${detail}`);
|
|
|
1164
1195
|
}
|
|
1165
1196
|
__name(loadConfig, "loadConfig");
|
|
1166
1197
|
|
|
1198
|
+
// src/refusals.ts
|
|
1199
|
+
var DECLARATION_REFUSAL = /* @__PURE__ */ Symbol.for("palbase.backend.declarationRefusal");
|
|
1200
|
+
var DeclarationRefused = class extends Error {
|
|
1201
|
+
static {
|
|
1202
|
+
__name(this, "DeclarationRefused");
|
|
1203
|
+
}
|
|
1204
|
+
/** @see DECLARATION_REFUSAL — realm-safe, unlike `instanceof`. */
|
|
1205
|
+
[DECLARATION_REFUSAL] = true;
|
|
1206
|
+
constructor(message) {
|
|
1207
|
+
super(message);
|
|
1208
|
+
this.name = "DeclarationRefused";
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
function isDeclarationRefused(e) {
|
|
1212
|
+
return typeof e === "object" && e !== null && e[DECLARATION_REFUSAL] === true;
|
|
1213
|
+
}
|
|
1214
|
+
__name(isDeclarationRefused, "isDeclarationRefused");
|
|
1215
|
+
|
|
1167
1216
|
// src/engine/auth.ts
|
|
1168
1217
|
function b64urlToBytes(s) {
|
|
1169
1218
|
const pad = s.replace(/-/g, "+").replace(/_/g, "/");
|
|
@@ -1486,12 +1535,12 @@ function buildRelations(schemas) {
|
|
|
1486
1535
|
const held = names.get(name);
|
|
1487
1536
|
if (held !== void 0) {
|
|
1488
1537
|
if (held.def.owns === true && origin.def.owns === true) {
|
|
1489
|
-
throw new
|
|
1538
|
+
throw new DeclarationRefused(`table "${tableKey}" declares TWO owner columns (${held.column}, ${origin.column}) \u2014 a table has at most ONE ownedByUser(). If the other column only POINTS at a user, declare it userRef({ onDelete: \u2026 }) instead.`);
|
|
1490
1539
|
}
|
|
1491
1540
|
const heldFix = renameCall(held);
|
|
1492
1541
|
const originFix = renameCall(origin);
|
|
1493
1542
|
const remedy = heldFix === originFix ? `rename one of them: ${heldFix}` : `rename one of them \u2014 "${held.table}.${held.column}": ${heldFix}; "${origin.table}.${origin.column}": ${originFix}`;
|
|
1494
|
-
throw new
|
|
1543
|
+
throw new DeclarationRefused(`table "${tableKey}": ${describeOrigin(held)} and ${describeOrigin(origin)} both resolve to the relation name "${name}" \u2014 ${remedy}.`);
|
|
1495
1544
|
}
|
|
1496
1545
|
names.set(name, origin);
|
|
1497
1546
|
out.get(tableKey)?.push(edge);
|
|
@@ -2069,7 +2118,7 @@ function compileWhereBare(table, colSet, where, add, caller = "search", alias =
|
|
|
2069
2118
|
const rel = rels.find((r) => r.name === relName);
|
|
2070
2119
|
if (rel === void 0) {
|
|
2071
2120
|
const known = rels.map((r) => r.name).sort();
|
|
2072
|
-
throw new Error(`${caller}(${table}): has.${relName} diye bir ili\u015Fki yok
|
|
2121
|
+
throw new Error(`${caller}(${table}): has.${relName} diye bir ili\u015Fki yok` + (known.length > 0 ? ` (bilinenler: ${known.join(", ")}). \u0130li\u015Fkiler yabanc\u0131 anahtarlardan T\xDCRET\u0130L\u0130R; ad\u0131n\u0131 de\u011Fi\u015Ftirmek i\xE7in references(..., { as, reverseAs }).` : `. Bu tablo H\u0130\xC7 yabanc\u0131 anahtar bildirmiyor, ve ili\u015Fkiler onlardan T\xDCRET\u0130L\u0130R. Var olan bir veritaban\u0131ndan introspect edilmi\u015F \u015Femalarda bu s\u0131k olur: kolon \`text()\`/\`uuid()\` olarak durur, \`references(() => <tablo>.<kolon>)\` yoktur. Bildirdi\u011Finiz anda ili\u015Fki iki tarafta da adland\u0131r\u0131l\u0131r \u2014 ama bu CANLI veritaban\u0131na giden bir k\u0131s\u0131tt\u0131r ve mevcut yetim sat\u0131rlar onu d\xFC\u015F\xFCr\xFCr; \xF6nce onlar\u0131 say\u0131n.`));
|
|
2073
2122
|
}
|
|
2074
2123
|
const ourCol = rel.kind === "many" ? primaryKeyOf(table) : rel.via;
|
|
2075
2124
|
const theirCol = rel.kind === "many" ? rel.via : primaryKeyOf(rel.to);
|
|
@@ -2096,6 +2145,10 @@ function compileWhereBare(table, colSet, where, add, caller = "search", alias =
|
|
|
2096
2145
|
parts.push(`${q} = ${colRefSql(table, colSet, cond, caller, alias)}`);
|
|
2097
2146
|
continue;
|
|
2098
2147
|
}
|
|
2148
|
+
if (isNowExpr(cond)) {
|
|
2149
|
+
parts.push(`${q} = now()`);
|
|
2150
|
+
continue;
|
|
2151
|
+
}
|
|
2099
2152
|
if (cond !== null && typeof cond === "object" && !Array.isArray(cond)) {
|
|
2100
2153
|
for (const [op, v] of Object.entries(cond)) {
|
|
2101
2154
|
if (op === "contains" || op === "icontains" || op === "startsWith" || op === "endsWith") {
|
|
@@ -2124,6 +2177,13 @@ function compileWhereBare(table, colSet, where, add, caller = "search", alias =
|
|
|
2124
2177
|
continue;
|
|
2125
2178
|
}
|
|
2126
2179
|
parts.push(`${q} IN (${v.map((x) => bind(x)).join(", ")})`);
|
|
2180
|
+
} else if (isNowExpr(v)) {
|
|
2181
|
+
if (!(op in WHERE_OPS)) {
|
|
2182
|
+
throw new Error(`${caller}(${table}): where.${col}.${op} now() ile kullan\u0131lamaz \u2014 e\u015Fitlik i\xE7in \xE7\u0131plak bi\xE7imi kullan\u0131n: { ${col}: now() }`);
|
|
2183
|
+
}
|
|
2184
|
+
parts.push(`${q} ${WHERE_OPS[op]} now()`);
|
|
2185
|
+
} else if (isColumnExpr(v)) {
|
|
2186
|
+
throw new Error(`${caller}(${table}): where.${col}.${op} bir YAZMA ifadesi ald\u0131 (increment/decrement) \u2014 kar\u015F\u0131la\u015Ft\u0131rma de\u011Feri de\u011Fil. Sunucu saati i\xE7in now() kullan\u0131n; say\u0131sal bir e\u015Fik i\xE7in de\u011Feri yaz\u0131n.`);
|
|
2127
2187
|
} else if (isColRef(v)) {
|
|
2128
2188
|
if (!(op in WHERE_OPS)) {
|
|
2129
2189
|
throw new Error(`${caller}(${table}): where.${col}.${op} col() ile kullan\u0131lamaz \u2014 e\u015Fitlik i\xE7in \xE7\u0131plak bi\xE7imi kullan\u0131n: { ${col}: col("\u2026") }`);
|
|
@@ -2131,7 +2191,9 @@ function compileWhereBare(table, colSet, where, add, caller = "search", alias =
|
|
|
2131
2191
|
parts.push(`${q} ${WHERE_OPS[op]} ${colRefSql(table, colSet, v, caller, alias)}`);
|
|
2132
2192
|
} else if (looksLikeUnbrandedRef(v) !== null) {
|
|
2133
2193
|
const kind = looksLikeUnbrandedRef(v);
|
|
2134
|
-
|
|
2194
|
+
const made = kind === "col" ? "col()" : kind === "sql" ? "sqlFragment" : "now()";
|
|
2195
|
+
const how = kind === "col" ? 'col("kolon_ad\u0131")' : kind === "sql" ? "sqlFragment`\u2026`" : "now()";
|
|
2196
|
+
throw new Error(`${caller}(${table}): where.${col}.${op} bir ${made} TAKL\u0130D\u0130 ald\u0131 \u2014 bu nesne bu s\xFCre\xE7te ${made} ile \xFCretilmemi\u015F. \u0130stek g\xF6vdesinden gelen bir filtre i\u015Faret\xE7i TA\u015EIYAMAZ; ko\u015Fulu kendi kodunuzda ${how} ile kurun.`);
|
|
2135
2197
|
} else if (op in WHERE_OPS) {
|
|
2136
2198
|
if (v === null && op === "neq") {
|
|
2137
2199
|
parts.push(`${q} IS NOT NULL`);
|
|
@@ -2236,6 +2298,37 @@ async function embedQuery(embed, text) {
|
|
|
2236
2298
|
}
|
|
2237
2299
|
}
|
|
2238
2300
|
__name(embedQuery, "embedQuery");
|
|
2301
|
+
function buildSetAssignments(table, cols, set, add, caller) {
|
|
2302
|
+
return cols.map((c) => {
|
|
2303
|
+
const expr = columnExprOf(set[c]);
|
|
2304
|
+
if (expr !== null && expr.fn === "now") {
|
|
2305
|
+
return `${quoteIdent(c)} = now()`;
|
|
2306
|
+
}
|
|
2307
|
+
if (expr !== null) {
|
|
2308
|
+
const operator = expr.fn === "inc" ? "+" : "-";
|
|
2309
|
+
const t = transformsOf(currentSchema, table).get(c);
|
|
2310
|
+
const amount = t?.toDb === void 0 || expr.by === null || expr.by === void 0 ? expr.by : t.toDb(expr.by);
|
|
2311
|
+
return `${quoteIdent(c)} = ${quoteIdent(c)} ${operator} ${add(amount)}`;
|
|
2312
|
+
}
|
|
2313
|
+
return `${quoteIdent(c)} = ${add(asBindParams(table, [
|
|
2314
|
+
c
|
|
2315
|
+
], set, caller)[0])}`;
|
|
2316
|
+
}).join(", ");
|
|
2317
|
+
}
|
|
2318
|
+
__name(buildSetAssignments, "buildSetAssignments");
|
|
2319
|
+
function buildValueTuple(table, cols, data, add, caller) {
|
|
2320
|
+
return cols.map((c) => {
|
|
2321
|
+
const expr = columnExprOf(data[c]);
|
|
2322
|
+
if (expr !== null && expr.fn === "now") return "now()";
|
|
2323
|
+
if (expr !== null) {
|
|
2324
|
+
throw new Error(`${caller}(${table}): "${c}" ${expr.fn === "inc" ? "increment()" : "decrement()"} ald\u0131 \u2014 sat\u0131r HEN\xDCZ YOK, yani "kolonun \u015Fu anki de\u011Feri" diye bir \u015Fey yok. Ba\u015Flang\u0131\xE7 de\u011Ferini yaz\u0131n; art\u0131rmak i\xE7in sat\u0131r olu\u015Ftuktan sonra updateMany({ where, set: { ${c}: ${expr.fn === "inc" ? "increment" : "decrement"}(n) } }).`);
|
|
2325
|
+
}
|
|
2326
|
+
return add(asBindParams(table, [
|
|
2327
|
+
c
|
|
2328
|
+
], data, caller)[0]);
|
|
2329
|
+
}).join(", ");
|
|
2330
|
+
}
|
|
2331
|
+
__name(buildValueTuple, "buildValueTuple");
|
|
2239
2332
|
function createOps(tx) {
|
|
2240
2333
|
const at = /* @__PURE__ */ __name(() => resolveTx(tx), "at");
|
|
2241
2334
|
const ops = {
|
|
@@ -2249,9 +2342,11 @@ function createOps(tx) {
|
|
|
2249
2342
|
async insert(table, data) {
|
|
2250
2343
|
const cols = Object.keys(data);
|
|
2251
2344
|
if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);
|
|
2252
|
-
const
|
|
2253
|
-
const
|
|
2254
|
-
const
|
|
2345
|
+
const params = [];
|
|
2346
|
+
const add = /* @__PURE__ */ __name((v) => `$${params.push(v)}`, "add");
|
|
2347
|
+
const tuple = buildValueTuple(table, cols, data, add, "insert");
|
|
2348
|
+
const sql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${tuple}) RETURNING *`;
|
|
2349
|
+
const rows = await (await at()).unsafe(sql, params);
|
|
2255
2350
|
const inserted = rows[0];
|
|
2256
2351
|
if (!inserted) {
|
|
2257
2352
|
throw new Error(`insert into ${table} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);
|
|
@@ -2259,6 +2354,41 @@ function createOps(tx) {
|
|
|
2259
2354
|
return asTableRow(table, inserted);
|
|
2260
2355
|
},
|
|
2261
2356
|
/**
|
|
2357
|
+
* Çok satırı TEK statement'la ekle.
|
|
2358
|
+
*
|
|
2359
|
+
* Motor bunu zaten yapıyordu ve yalnız PLAN yolundan erişilebiliyordu
|
|
2360
|
+
* (`tx.public.x.insertMany`). Dışarıda tek kapı `insert(row)` olduğu için
|
|
2361
|
+
* "şu 200 satırı yaz" ya 200 gidiş-dönüş ya da ham SQL oluyordu — ölçüldü:
|
|
2362
|
+
* bir müşteri projesinde bir seed rutini satırları tek tek siliyor
|
|
2363
|
+
* (`deleteMany` VARKEN) ve tek tek ekliyor.
|
|
2364
|
+
*
|
|
2365
|
+
* SATIRLARIN ANAHTAR KÜMESİ AYNI OLMAK ZORUNDA. Kolon listesi tek bir
|
|
2366
|
+
* statement'ta paylaşıldığı için ilk satırdan türer; farklı anahtar taşıyan
|
|
2367
|
+
* bir satırın fazla kolonu SESSİZCE YAZILMAZDI. Eksik kolon için `null`
|
|
2368
|
+
* yazın ya da varsayılanı istiyorsanız o satırları ayrı çağrıda ekleyin.
|
|
2369
|
+
*/
|
|
2370
|
+
async insertMany(table, rows, opts) {
|
|
2371
|
+
if (rows.length === 0) return [];
|
|
2372
|
+
const first = rows[0];
|
|
2373
|
+
const cols = Object.keys(first);
|
|
2374
|
+
if (cols.length === 0) throw new Error(`insertMany into ${table}: no columns given`);
|
|
2375
|
+
for (let i = 1; i < rows.length; i++) {
|
|
2376
|
+
const keys = Object.keys(rows[i]);
|
|
2377
|
+
const missing = cols.filter((c) => !(c in rows[i]));
|
|
2378
|
+
const extra = keys.filter((k) => !cols.includes(k));
|
|
2379
|
+
if (missing.length > 0 || extra.length > 0) {
|
|
2380
|
+
throw new Error(`insertMany(${table}): ${i}. sat\u0131r\u0131n kolonlar\u0131 ilk sat\u0131rla ayn\u0131 de\u011Fil` + (missing.length > 0 ? ` (eksik: ${missing.join(", ")})` : "") + (extra.length > 0 ? ` (fazla: ${extra.join(", ")})` : "") + `. Tek statement kolon listesini PAYLA\u015EIR, yani fazla kolon sessizce yaz\u0131lmaz ve eksik kolon yanl\u0131\u015F s\xFCtuna kayar. Eksikler i\xE7in null yaz\u0131n, ya da farkl\u0131 \u015Fekilli sat\u0131rlar\u0131 ayr\u0131 \xE7a\u011Fr\u0131larda ekleyin.`);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
const params = [];
|
|
2384
|
+
const add = /* @__PURE__ */ __name((v) => `$${params.push(v)}`, "add");
|
|
2385
|
+
const tuples = rows.map((r) => `(${buildValueTuple(table, cols, r, add, "insertMany")})`);
|
|
2386
|
+
const tail = opts !== void 0 && opts.onConflict.length > 0 ? ` ${onConflictTail(cols, opts.onConflict, opts.action ?? "ignore")}` : "";
|
|
2387
|
+
const sql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES ${tuples.join(", ")}${tail} RETURNING *`;
|
|
2388
|
+
const out = await (await at()).unsafe(sql, params);
|
|
2389
|
+
return out.map((r) => asTableRow(table, r));
|
|
2390
|
+
},
|
|
2391
|
+
/**
|
|
2262
2392
|
* Bir ADI kilitle — satırı değil (FR-054).
|
|
2263
2393
|
*
|
|
2264
2394
|
* "Aynı anda tek bir fatura kapanışı koşsun" gibi, kilitlenecek satırı
|
|
@@ -2344,8 +2474,10 @@ function createOps(tx) {
|
|
|
2344
2474
|
const live = await at();
|
|
2345
2475
|
try {
|
|
2346
2476
|
return await live.savepoint(async (sp) => {
|
|
2347
|
-
const
|
|
2348
|
-
const
|
|
2477
|
+
const params = [];
|
|
2478
|
+
const add = /* @__PURE__ */ __name((v) => `$${params.push(v)}`, "add");
|
|
2479
|
+
const tuple = buildValueTuple(table, cols, data, add, "claim");
|
|
2480
|
+
const rows = await sp.unsafe(`INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${tuple}) RETURNING *`, params);
|
|
2349
2481
|
if (!rows[0]) {
|
|
2350
2482
|
throw new Error(`claim(${table}): INSERT sat\u0131r d\xF6nd\xFCrmedi \u2014 yazma reddedildi (b\xFCy\xFCk olas\u0131l\u0131kla bir RLS policy'si).`);
|
|
2351
2483
|
}
|
|
@@ -2396,10 +2528,11 @@ function createOps(tx) {
|
|
|
2396
2528
|
const cols = Object.keys(data);
|
|
2397
2529
|
if (cols.length === 0) throw new Error(`upsert into ${table}: no columns given`);
|
|
2398
2530
|
if (searchConfigFor(table)?.validity) {
|
|
2399
|
-
const
|
|
2531
|
+
const bindData = [];
|
|
2532
|
+
const addPut = /* @__PURE__ */ __name((v) => `$${bindData.push(v)}`, "addPut");
|
|
2533
|
+
const ph = buildValueTuple(table, cols, data, addPut, "put");
|
|
2400
2534
|
const insertSql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${ph}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) WHERE "valid_to" IS NULL DO NOTHING RETURNING *`;
|
|
2401
2535
|
const live = await at();
|
|
2402
|
-
const bindData = asBindParams(table, cols, data, "put");
|
|
2403
2536
|
const first = await live.unsafe(insertSql, bindData);
|
|
2404
2537
|
if (first[0]) return asTableRow(table, first[0]);
|
|
2405
2538
|
const condSql = conflict.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(" AND ");
|
|
@@ -2424,12 +2557,14 @@ function createOps(tx) {
|
|
|
2424
2557
|
]);
|
|
2425
2558
|
return asTableRow(table, second[0]);
|
|
2426
2559
|
}
|
|
2427
|
-
const
|
|
2560
|
+
const params = [];
|
|
2561
|
+
const add = /* @__PURE__ */ __name((v) => `$${params.push(v)}`, "add");
|
|
2562
|
+
const placeholders = buildValueTuple(table, cols, data, add, "put");
|
|
2428
2563
|
const conflictSet = new Set(conflict);
|
|
2429
2564
|
const assignments = cols.filter((c) => !conflictSet.has(c)).map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`);
|
|
2430
2565
|
const action = assignments.length ? `DO UPDATE SET ${assignments.join(", ")}` : `DO UPDATE SET ${quoteIdent(conflict[0])} = EXCLUDED.${quoteIdent(conflict[0])}`;
|
|
2431
2566
|
const sql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) ${action} RETURNING *`;
|
|
2432
|
-
const rows = await (await at()).unsafe(sql,
|
|
2567
|
+
const rows = await (await at()).unsafe(sql, params);
|
|
2433
2568
|
const row = rows[0];
|
|
2434
2569
|
if (!row) {
|
|
2435
2570
|
throw new Error(`upsert into ${table} returned no row \u2014 the write was rejected (an RLS policy, most likely).`);
|
|
@@ -2440,12 +2575,14 @@ function createOps(tx) {
|
|
|
2440
2575
|
assertNotAppendOnly("update", table);
|
|
2441
2576
|
const cols = Object.keys(data);
|
|
2442
2577
|
if (cols.length === 0) return ops.findById(table, id);
|
|
2443
|
-
const
|
|
2444
|
-
const
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2578
|
+
const params = [];
|
|
2579
|
+
const add = /* @__PURE__ */ __name((v) => {
|
|
2580
|
+
params.push(v);
|
|
2581
|
+
return `$${params.length}`;
|
|
2582
|
+
}, "add");
|
|
2583
|
+
const assignments = buildSetAssignments(table, cols, data, add, "update");
|
|
2584
|
+
const sql = `UPDATE ${quoteTable(table)} SET ${assignments} WHERE id = ${add(id)} RETURNING *`;
|
|
2585
|
+
const rows = await (await at()).unsafe(sql, params);
|
|
2449
2586
|
return rows[0] ? asTableRow(table, rows[0]) : null;
|
|
2450
2587
|
},
|
|
2451
2588
|
async delete(table, id) {
|
|
@@ -2491,21 +2628,7 @@ function createOps(tx) {
|
|
|
2491
2628
|
params.push(v);
|
|
2492
2629
|
return `$${params.length}`;
|
|
2493
2630
|
}, "add");
|
|
2494
|
-
const assignments =
|
|
2495
|
-
const expr = columnExprOf(set[c]);
|
|
2496
|
-
if (expr !== null && expr.fn === "now") {
|
|
2497
|
-
return `${quoteIdent(c)} = now()`;
|
|
2498
|
-
}
|
|
2499
|
-
if (expr !== null) {
|
|
2500
|
-
const operator = expr.fn === "inc" ? "+" : "-";
|
|
2501
|
-
const t = transformsOf(currentSchema, table).get(c);
|
|
2502
|
-
const amount = t?.toDb === void 0 || expr.by === null || expr.by === void 0 ? expr.by : t.toDb(expr.by);
|
|
2503
|
-
return `${quoteIdent(c)} = ${quoteIdent(c)} ${operator} ${add(amount)}`;
|
|
2504
|
-
}
|
|
2505
|
-
return `${quoteIdent(c)} = ${add(asBindParams(table, [
|
|
2506
|
-
c
|
|
2507
|
-
], set, "updateMany")[0])}`;
|
|
2508
|
-
}).join(", ");
|
|
2631
|
+
const assignments = buildSetAssignments(table, cols, set, add, "updateMany");
|
|
2509
2632
|
const whereSql = compileWhere(table, known, where, add, "updateMany");
|
|
2510
2633
|
assertHasPredicate(whereSql, "updateMany", table);
|
|
2511
2634
|
const pk = primaryKeyOf(table);
|
|
@@ -2963,8 +3086,10 @@ function createOps(tx) {
|
|
|
2963
3086
|
[cfg.pk]: newId
|
|
2964
3087
|
};
|
|
2965
3088
|
const cols = Object.keys(data);
|
|
2966
|
-
const
|
|
2967
|
-
const
|
|
3089
|
+
const params = [];
|
|
3090
|
+
const add = /* @__PURE__ */ __name((v) => `$${params.push(v)}`, "add");
|
|
3091
|
+
const tuple = buildValueTuple(table, cols, data, add, "supersede");
|
|
3092
|
+
const rows = await sp.unsafe(`INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${tuple}) RETURNING *`, params);
|
|
2968
3093
|
if (!rows[0]) {
|
|
2969
3094
|
throw new Error(`supersede(${table}): INSERT sat\u0131r d\xF6nd\xFCrmedi \u2014 yazma reddedildi (b\xFCy\xFCk olas\u0131l\u0131kla bir RLS policy'si)`);
|
|
2970
3095
|
}
|
|
@@ -3906,6 +4031,14 @@ var DiError = class extends Error {
|
|
|
3906
4031
|
path;
|
|
3907
4032
|
at;
|
|
3908
4033
|
fixes;
|
|
4034
|
+
/**
|
|
4035
|
+
* EVERY `DiKind` IS A FACT ABOUT THE AUTHOR'S DECLARATIONS — an unresolvable
|
|
4036
|
+
* dependency, a cycle, a class no module owns. Not one of them is something
|
|
4037
|
+
* the environment could change, so restarting re-reads the same bytes and
|
|
4038
|
+
* fails identically. The cure is a new artifact, and the tag is how the
|
|
4039
|
+
* runtime learns that without matching on wording.
|
|
4040
|
+
*/
|
|
4041
|
+
[DECLARATION_REFUSAL] = true;
|
|
3909
4042
|
constructor(kind, path, at, detail, fixes) {
|
|
3910
4043
|
super(`
|
|
3911
4044
|
Kind: ${kind}
|
|
@@ -4389,7 +4522,7 @@ async function createApp(opts) {
|
|
|
4389
4522
|
assertNoOrphanEntryPoints(controllers, container.owned);
|
|
4390
4523
|
const routes = buildRouteTable(controllers, liveContainer);
|
|
4391
4524
|
if (routes.length === 0) {
|
|
4392
|
-
throw new
|
|
4525
|
+
throw new DeclarationRefused("boot refused: zero endpoints collected \u2014 nothing would answer.");
|
|
4393
4526
|
}
|
|
4394
4527
|
const sql = opts.sql ?? await defaultSqlDriver(config);
|
|
4395
4528
|
await sql.unsafe("select 1");
|
|
@@ -4900,6 +5033,8 @@ __name(closeDriver, "closeDriver");
|
|
|
4900
5033
|
0 && (module.exports = {
|
|
4901
5034
|
AuthVerifier,
|
|
4902
5035
|
BootRefused,
|
|
5036
|
+
DECLARATION_REFUSAL,
|
|
5037
|
+
DeclarationRefused,
|
|
4903
5038
|
RateLimiter,
|
|
4904
5039
|
buildRouteTable,
|
|
4905
5040
|
createApp,
|
|
@@ -4909,6 +5044,7 @@ __name(closeDriver, "closeDriver");
|
|
|
4909
5044
|
effectiveAuth,
|
|
4910
5045
|
hostAllowed,
|
|
4911
5046
|
installEgressFence,
|
|
5047
|
+
isDeclarationRefused,
|
|
4912
5048
|
loadConfig,
|
|
4913
5049
|
makeMemoryCache,
|
|
4914
5050
|
matchRoute,
|