@palbase/backend 24.3.0 → 25.0.1
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 +103 -60
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +17 -13
- package/dist/bin/palbase-backend.js.map +1 -1
- package/dist/{chunk-EIXCY4SS.js → chunk-34I4GB7D.js} +82 -49
- package/dist/chunk-34I4GB7D.js.map +1 -0
- package/dist/{chunk-UWSYTUGM.js → chunk-35PNTIRN.js} +48 -1
- package/dist/chunk-35PNTIRN.js.map +1 -0
- package/dist/chunk-HBOJLP2Z.js +840 -0
- package/dist/chunk-HBOJLP2Z.js.map +1 -0
- package/dist/{chunk-7Z6MGMXQ.js → chunk-XJ2RSHEU.js} +11 -5
- package/dist/chunk-XJ2RSHEU.js.map +1 -0
- package/dist/{chunk-ERDL5VAE.js → chunk-YOY5DFQS.js} +2 -2
- package/dist/db/env.cjs.map +1 -1
- package/dist/db/env.d.cts +31 -14
- package/dist/db/env.d.ts +31 -14
- package/dist/db/index.cjs +226 -111
- 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 +11 -1
- package/dist/engine/index.cjs +89 -50
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +2 -2
- package/dist/engine/index.d.ts +2 -2
- package/dist/engine/index.js +3 -3
- package/dist/{index-BTMYod_l.d.ts → index-B4CcpqLb.d.ts} +224 -75
- package/dist/{index-DEneI8Mn.d.ts → index-B8v6hVyU.d.ts} +5 -2
- package/dist/{index-BLAbr9ZH.d.cts → index-DmVyY6N7.d.cts} +224 -75
- package/dist/{index-C-ALG22n.d.cts → index-VsjBQ4Kw.d.cts} +5 -2
- package/dist/index.cjs +580 -301
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +125 -22
- package/dist/index.d.ts +125 -22
- package/dist/index.js +173 -217
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +100 -36
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.js +59 -2
- package/dist/openapi/index.js.map +1 -1
- package/docs/README.md +64 -31
- package/docs/endpoints.md +25 -28
- package/docs/llms-full.txt +430 -153
- package/docs/schema.md +303 -91
- package/docs/services.md +39 -4
- package/package.json +1 -1
- package/template/AGENTS.md +119 -314
- package/template/CLAUDE.md +13 -0
- package/template/controllers/notes.controller.ts +6 -13
- package/template/db/public.ts +38 -0
- package/template/models/notes/create.ts +38 -0
- package/template/package.json +6 -3
- package/template/services/note.service.test.ts +45 -0
- package/template/services/note.service.ts +2 -2
- package/dist/chunk-7Z6MGMXQ.js.map +0 -1
- package/dist/chunk-D5CQES25.js +0 -556
- package/dist/chunk-D5CQES25.js.map +0 -1
- package/dist/chunk-EIXCY4SS.js.map +0 -1
- package/dist/chunk-UWSYTUGM.js.map +0 -1
- package/template/db/schema.ts +0 -35
- /package/dist/{chunk-ERDL5VAE.js.map → chunk-YOY5DFQS.js.map} +0 -0
package/dist/db/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef,
|
|
1
|
+
export { A as AnyColumn, C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, g as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, j as PalbaseExtension, k as PolicyBuilder, l as PolicyCommand, m as PolicyDef, n as PolicyMode, R as RawConstraintDef, o as RowShape, S as SchemaDef, T as TABLE_META, p as TableDef, q as TableHandle, r as TableInput, s as TxPlan, t as TxTables, u as TypedDB, v as TypedTable, w as TypedTx, x as bigint, y as boolean, z as defineSchema, B as defineTable, D as enumType, F as installationRef, G as integer, H as isPalbaseExtension, J as jsonb, K as makeTypedDB, M as openai, N as ownedByUser, Q as policy, U as raw, V as text, W as timestamp, X as userRef, Y as uuid, Z as vector } from '../index-DmVyY6N7.cjs';
|
|
2
2
|
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection, g as TxPlanResponse, bb as TxRefError, bc as TxRow, bd as TxRows, be as TxSelectOptions, bf as TxSetShape, bh as TxTable, bi as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-BSGw1pTu.cjs';
|
|
3
3
|
import './env.cjs';
|
|
4
4
|
import '../stack.cjs';
|
package/dist/db/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef,
|
|
1
|
+
export { A as AnyColumn, C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, g as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, j as PalbaseExtension, k as PolicyBuilder, l as PolicyCommand, m as PolicyDef, n as PolicyMode, R as RawConstraintDef, o as RowShape, S as SchemaDef, T as TABLE_META, p as TableDef, q as TableHandle, r as TableInput, s as TxPlan, t as TxTables, u as TypedDB, v as TypedTable, w as TypedTx, x as bigint, y as boolean, z as defineSchema, B as defineTable, D as enumType, F as installationRef, G as integer, H as isPalbaseExtension, J as jsonb, K as makeTypedDB, M as openai, N as ownedByUser, Q as policy, U as raw, V as text, W as timestamp, X as userRef, Y as uuid, Z as vector } from '../index-B4CcpqLb.js';
|
|
2
2
|
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection, g as TxPlanResponse, bb as TxRefError, bc as TxRow, bd as TxRows, be as TxSelectOptions, bf as TxSetShape, bh as TxTable, bi as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-DMwJjEHQ.js';
|
|
3
3
|
import './env.js';
|
|
4
4
|
import '../stack.js';
|
package/dist/db/index.js
CHANGED
|
@@ -2,22 +2,27 @@ import {
|
|
|
2
2
|
EXTENSION_DEPENDENCIES,
|
|
3
3
|
PALBASE_EXTENSIONS,
|
|
4
4
|
PolicyBuilder,
|
|
5
|
+
TABLE_META,
|
|
5
6
|
bigint,
|
|
6
7
|
boolean,
|
|
7
8
|
defineSchema,
|
|
9
|
+
defineTable,
|
|
8
10
|
enumType,
|
|
11
|
+
installationRef,
|
|
9
12
|
integer,
|
|
10
13
|
isPalbaseExtension,
|
|
11
14
|
jsonb,
|
|
12
15
|
makeTypedDB,
|
|
13
16
|
openai,
|
|
17
|
+
ownedByUser,
|
|
14
18
|
policy,
|
|
15
19
|
raw,
|
|
16
20
|
text,
|
|
17
21
|
timestamp,
|
|
22
|
+
userRef,
|
|
18
23
|
uuid,
|
|
19
24
|
vector
|
|
20
|
-
} from "../chunk-
|
|
25
|
+
} from "../chunk-HBOJLP2Z.js";
|
|
21
26
|
import {
|
|
22
27
|
TxPlanError,
|
|
23
28
|
TxRefError,
|
|
@@ -30,24 +35,29 @@ export {
|
|
|
30
35
|
EXTENSION_DEPENDENCIES,
|
|
31
36
|
PALBASE_EXTENSIONS,
|
|
32
37
|
PolicyBuilder,
|
|
38
|
+
TABLE_META,
|
|
33
39
|
TxPlanError,
|
|
34
40
|
TxRefError,
|
|
35
41
|
bigint,
|
|
36
42
|
boolean,
|
|
37
43
|
dec,
|
|
38
44
|
defineSchema,
|
|
45
|
+
defineTable,
|
|
39
46
|
enumType,
|
|
40
47
|
inc,
|
|
48
|
+
installationRef,
|
|
41
49
|
integer,
|
|
42
50
|
isPalbaseExtension,
|
|
43
51
|
jsonb,
|
|
44
52
|
makeTypedDB,
|
|
45
53
|
now,
|
|
46
54
|
openai,
|
|
55
|
+
ownedByUser,
|
|
47
56
|
policy,
|
|
48
57
|
raw,
|
|
49
58
|
text,
|
|
50
59
|
timestamp,
|
|
60
|
+
userRef,
|
|
51
61
|
uuid,
|
|
52
62
|
vector
|
|
53
63
|
};
|
package/dist/engine/index.cjs
CHANGED
|
@@ -512,13 +512,13 @@ function makeServiceProxy(key) {
|
|
|
512
512
|
};
|
|
513
513
|
return new Proxy({}, handler);
|
|
514
514
|
}
|
|
515
|
-
function
|
|
516
|
-
|
|
515
|
+
function makeTableProxy(ops, prefix) {
|
|
516
|
+
return new Proxy(
|
|
517
517
|
{},
|
|
518
518
|
{
|
|
519
519
|
get(_t, prop) {
|
|
520
520
|
if (typeof prop !== "string") return void 0;
|
|
521
|
-
const name = prop
|
|
521
|
+
const name = `${prefix}${prop}`;
|
|
522
522
|
return {
|
|
523
523
|
insert: (data) => ops().insert(name, data),
|
|
524
524
|
update: (id, data) => ops().update(name, id, data),
|
|
@@ -535,7 +535,12 @@ function makeTablesAccessor(ops) {
|
|
|
535
535
|
}
|
|
536
536
|
}
|
|
537
537
|
);
|
|
538
|
-
|
|
538
|
+
}
|
|
539
|
+
function makeTablesAccessor(ops) {
|
|
540
|
+
return makeTableProxy(ops, "");
|
|
541
|
+
}
|
|
542
|
+
function makeSchemaAccessor(ops, schema) {
|
|
543
|
+
return { tables: makeTableProxy(ops, `${String(schema)}.`) };
|
|
539
544
|
}
|
|
540
545
|
var rawDatabase = makeServiceProxy("Database");
|
|
541
546
|
function makeTypedSurface(raw) {
|
|
@@ -562,6 +567,7 @@ function makeTypedSurface(raw) {
|
|
|
562
567
|
// as one on the request's, and each is bound to its own connection.
|
|
563
568
|
attempt: (fn) => raw.attempt(fn),
|
|
564
569
|
tables: makeTablesAccessor(() => reco),
|
|
570
|
+
schema: (name) => makeSchemaAccessor(() => reco, name),
|
|
565
571
|
transaction(fn) {
|
|
566
572
|
const builder = new TxPlanBuilder();
|
|
567
573
|
return runTxPlan(raw, makeTxTablesAccessor(builder), builder, fn);
|
|
@@ -1125,6 +1131,11 @@ function assertUsableWriteValues(caller, table, cols, data) {
|
|
|
1125
1131
|
function quoteIdent(name) {
|
|
1126
1132
|
return `"${name.replace(/"/g, '""')}"`;
|
|
1127
1133
|
}
|
|
1134
|
+
function quoteTable(key) {
|
|
1135
|
+
const dot = key.indexOf(".");
|
|
1136
|
+
if (dot === -1) return quoteIdent(key);
|
|
1137
|
+
return `${quoteIdent(key.slice(0, dot))}.${quoteIdent(key.slice(dot + 1))}`;
|
|
1138
|
+
}
|
|
1128
1139
|
function encodePgArray(value) {
|
|
1129
1140
|
const element = (x) => {
|
|
1130
1141
|
if (x === null || x === void 0) return "NULL";
|
|
@@ -1197,8 +1208,8 @@ function toVectorLiteral(v) {
|
|
|
1197
1208
|
}
|
|
1198
1209
|
function vectorColumnsOf(schema, table) {
|
|
1199
1210
|
const out = /* @__PURE__ */ new Set();
|
|
1200
|
-
|
|
1201
|
-
|
|
1211
|
+
const def = tableDefOf(table, schema);
|
|
1212
|
+
if (def) {
|
|
1202
1213
|
for (const [col, c] of Object.entries(def.columns ?? {})) {
|
|
1203
1214
|
const d = c !== null && typeof c === "object" && "_def" in c ? c._def : c;
|
|
1204
1215
|
if (d !== null && typeof d === "object" && d.type === "vector") out.add(col);
|
|
@@ -1206,6 +1217,9 @@ function vectorColumnsOf(schema, table) {
|
|
|
1206
1217
|
}
|
|
1207
1218
|
return out;
|
|
1208
1219
|
}
|
|
1220
|
+
function tableDefOf(key, schema = currentSchema) {
|
|
1221
|
+
return schema.tables?.[key] ?? null;
|
|
1222
|
+
}
|
|
1209
1223
|
function reviveVectors(row, vectorCols) {
|
|
1210
1224
|
if (row === null || typeof row !== "object" || vectorCols.size === 0) return row;
|
|
1211
1225
|
const out = row;
|
|
@@ -1217,8 +1231,8 @@ function reviveVectors(row, vectorCols) {
|
|
|
1217
1231
|
}
|
|
1218
1232
|
function transformsOf(schema, table) {
|
|
1219
1233
|
const out = /* @__PURE__ */ new Map();
|
|
1220
|
-
|
|
1221
|
-
|
|
1234
|
+
const def = tableDefOf(table, schema);
|
|
1235
|
+
if (def) {
|
|
1222
1236
|
for (const [col, c] of Object.entries(def.columns ?? {})) {
|
|
1223
1237
|
const d = c !== null && typeof c === "object" && "_def" in c ? c._def : c;
|
|
1224
1238
|
const t = d?.transform;
|
|
@@ -1267,7 +1281,7 @@ var METRIC_OPERATOR = {
|
|
|
1267
1281
|
inner_product: "<#>"
|
|
1268
1282
|
};
|
|
1269
1283
|
function searchConfigFor(table) {
|
|
1270
|
-
const t =
|
|
1284
|
+
const t = tableDefOf(table);
|
|
1271
1285
|
if (!t) return null;
|
|
1272
1286
|
const columns = t.columns ?? {};
|
|
1273
1287
|
const defOf = (c) => c !== null && typeof c === "object" && "_def" in c ? c._def : c ?? {};
|
|
@@ -1404,7 +1418,7 @@ async function fetchFacets(live, table, colSet, facets, where, extraWhere = () =
|
|
|
1404
1418
|
};
|
|
1405
1419
|
const whereSql = compileWhere(table, colSet, where, add) + extraWhere(add);
|
|
1406
1420
|
const parts = facets.map(
|
|
1407
|
-
(col) => `(SELECT '${col.replace(/'/g, "''")}' AS f, t.${quoteIdent(col)}::text AS v, count(*) AS n FROM ${
|
|
1421
|
+
(col) => `(SELECT '${col.replace(/'/g, "''")}' AS f, t.${quoteIdent(col)}::text AS v, count(*) AS n FROM ${quoteTable(table)} t WHERE true${whereSql} GROUP BY 2 ORDER BY 3 DESC LIMIT 20)`
|
|
1408
1422
|
);
|
|
1409
1423
|
const rows = await live.unsafe(parts.join(" UNION ALL "), bind);
|
|
1410
1424
|
const out = {};
|
|
@@ -1430,7 +1444,7 @@ function excludeSql(pk, ids, add) {
|
|
|
1430
1444
|
return ` AND t.${quoteIdent(pk)}::text <> ALL(ARRAY[${ids.map((x) => add(x)).join(", ")}])`;
|
|
1431
1445
|
}
|
|
1432
1446
|
function schemaColumns(table) {
|
|
1433
|
-
const t =
|
|
1447
|
+
const t = tableDefOf(table);
|
|
1434
1448
|
const cols = t?.columns ? Object.keys(t.columns) : [];
|
|
1435
1449
|
return cols.length > 0 ? new Set(cols) : null;
|
|
1436
1450
|
}
|
|
@@ -1591,7 +1605,7 @@ function createOps(tx) {
|
|
|
1591
1605
|
const cols = Object.keys(data);
|
|
1592
1606
|
if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);
|
|
1593
1607
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
1594
|
-
const sql = `INSERT INTO ${
|
|
1608
|
+
const sql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`;
|
|
1595
1609
|
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "insert"));
|
|
1596
1610
|
const inserted = rows[0];
|
|
1597
1611
|
if (!inserted) {
|
|
@@ -1624,7 +1638,7 @@ function createOps(tx) {
|
|
|
1624
1638
|
if (cols.length === 0) throw new Error(`upsert into ${table}: no columns given`);
|
|
1625
1639
|
if (searchConfigFor(table)?.validity) {
|
|
1626
1640
|
const ph = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
1627
|
-
const insertSql = `INSERT INTO ${
|
|
1641
|
+
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 *`;
|
|
1628
1642
|
const live = await at();
|
|
1629
1643
|
const bindData = asBindParams(table, cols, data, "upsert");
|
|
1630
1644
|
const first = await live.unsafe(insertSql, bindData);
|
|
@@ -1632,7 +1646,7 @@ function createOps(tx) {
|
|
|
1632
1646
|
const condSql = conflict.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(" AND ");
|
|
1633
1647
|
const condBind = conflict.map((c) => data[c]);
|
|
1634
1648
|
const cur = await live.unsafe(
|
|
1635
|
-
`SELECT * FROM ${
|
|
1649
|
+
`SELECT * FROM ${quoteTable(table)} WHERE ${condSql} AND "valid_to" IS NULL`,
|
|
1636
1650
|
condBind
|
|
1637
1651
|
);
|
|
1638
1652
|
const old = cur[0];
|
|
@@ -1641,7 +1655,7 @@ function createOps(tx) {
|
|
|
1641
1655
|
}
|
|
1642
1656
|
const pk = Object.keys(old).includes("id") ? "id" : Object.keys(old)[0];
|
|
1643
1657
|
await live.unsafe(
|
|
1644
|
-
`UPDATE ${
|
|
1658
|
+
`UPDATE ${quoteTable(table)} SET "valid_to" = now() WHERE ${quoteIdent(pk)} = $1 AND "valid_to" IS NULL`,
|
|
1645
1659
|
[old[pk]]
|
|
1646
1660
|
);
|
|
1647
1661
|
const second = await live.unsafe(insertSql, bindData);
|
|
@@ -1650,7 +1664,7 @@ function createOps(tx) {
|
|
|
1650
1664
|
}
|
|
1651
1665
|
const fresh = second[0];
|
|
1652
1666
|
await live.unsafe(
|
|
1653
|
-
`UPDATE ${
|
|
1667
|
+
`UPDATE ${quoteTable(table)} SET "superseded_by" = $2 WHERE ${quoteIdent(pk)} = $1`,
|
|
1654
1668
|
[old[pk], fresh[pk]]
|
|
1655
1669
|
);
|
|
1656
1670
|
return asTableRow(table, second[0]);
|
|
@@ -1659,7 +1673,7 @@ function createOps(tx) {
|
|
|
1659
1673
|
const conflictSet = new Set(conflict);
|
|
1660
1674
|
const assignments = cols.filter((c) => !conflictSet.has(c)).map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`);
|
|
1661
1675
|
const action = assignments.length ? `DO UPDATE SET ${assignments.join(", ")}` : `DO UPDATE SET ${quoteIdent(conflict[0])} = EXCLUDED.${quoteIdent(conflict[0])}`;
|
|
1662
|
-
const sql = `INSERT INTO ${
|
|
1676
|
+
const sql = `INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) ${action} RETURNING *`;
|
|
1663
1677
|
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "upsert"));
|
|
1664
1678
|
const row = rows[0];
|
|
1665
1679
|
if (!row) {
|
|
@@ -1673,12 +1687,12 @@ function createOps(tx) {
|
|
|
1673
1687
|
const cols = Object.keys(data);
|
|
1674
1688
|
if (cols.length === 0) return ops.findById(table, id);
|
|
1675
1689
|
const assignments = cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(", ");
|
|
1676
|
-
const sql = `UPDATE ${
|
|
1690
|
+
const sql = `UPDATE ${quoteTable(table)} SET ${assignments} WHERE id = $${cols.length + 1} RETURNING *`;
|
|
1677
1691
|
const rows = await (await at()).unsafe(sql, [...asBindParams(table, cols, data, "update"), id]);
|
|
1678
1692
|
return rows[0] ? asTableRow(table, rows[0]) : null;
|
|
1679
1693
|
},
|
|
1680
1694
|
async delete(table, id) {
|
|
1681
|
-
await (await at()).unsafe(`DELETE FROM ${
|
|
1695
|
+
await (await at()).unsafe(`DELETE FROM ${quoteTable(table)} WHERE id = $1`, [id]);
|
|
1682
1696
|
},
|
|
1683
1697
|
/**
|
|
1684
1698
|
* Update every row the filter matches, in ONE statement.
|
|
@@ -1721,7 +1735,7 @@ function createOps(tx) {
|
|
|
1721
1735
|
const assignments = cols.map((c) => `${quoteIdent(c)} = ${add(asBindParams(table, [c], set, "updateMany")[0])}`).join(", ");
|
|
1722
1736
|
const whereSql = compileWhere(table, known, where, add, "updateMany");
|
|
1723
1737
|
assertHasPredicate(whereSql, "updateMany", table);
|
|
1724
|
-
const sql = `UPDATE ${
|
|
1738
|
+
const sql = `UPDATE ${quoteTable(table)} AS t SET ${assignments} WHERE true${whereSql} RETURNING *`;
|
|
1725
1739
|
return asTableRows(table, await (await at()).unsafe(sql, params));
|
|
1726
1740
|
},
|
|
1727
1741
|
/**
|
|
@@ -1738,7 +1752,7 @@ function createOps(tx) {
|
|
|
1738
1752
|
const known = schemaColumns(table);
|
|
1739
1753
|
const whereSql = compileWhere(table, known, where, add, "deleteMany");
|
|
1740
1754
|
assertHasPredicate(whereSql, "deleteMany", table);
|
|
1741
|
-
const sql = `DELETE FROM ${
|
|
1755
|
+
const sql = `DELETE FROM ${quoteTable(table)} AS t WHERE true${whereSql} RETURNING 1`;
|
|
1742
1756
|
const rows = await (await at()).unsafe(sql, params);
|
|
1743
1757
|
return rows.length;
|
|
1744
1758
|
},
|
|
@@ -1759,13 +1773,13 @@ function createOps(tx) {
|
|
|
1759
1773
|
};
|
|
1760
1774
|
const known = schemaColumns(table);
|
|
1761
1775
|
const whereSql = compileWhere(table, known, where, add, "count");
|
|
1762
|
-
const sql = `SELECT count(*) AS n FROM ${
|
|
1776
|
+
const sql = `SELECT count(*) AS n FROM ${quoteTable(table)} t WHERE true${whereSql}`;
|
|
1763
1777
|
const rows = await (await at()).unsafe(sql, params);
|
|
1764
1778
|
return Number(rows[0]?.n ?? 0);
|
|
1765
1779
|
},
|
|
1766
1780
|
async findById(table, id) {
|
|
1767
1781
|
const rows = await (await at()).unsafe(
|
|
1768
|
-
`SELECT * FROM ${
|
|
1782
|
+
`SELECT * FROM ${quoteTable(table)} WHERE id = $1`,
|
|
1769
1783
|
[id]
|
|
1770
1784
|
);
|
|
1771
1785
|
return rows[0] ? asTableRow(table, rows[0]) : null;
|
|
@@ -1781,7 +1795,7 @@ function createOps(tx) {
|
|
|
1781
1795
|
const order = orderClause(table, known, opts.orderBy);
|
|
1782
1796
|
const limit = limitClause(opts.limit);
|
|
1783
1797
|
const offset = offsetClause(opts.offset, opts.limit);
|
|
1784
|
-
const sql = `SELECT * FROM ${
|
|
1798
|
+
const sql = `SELECT * FROM ${quoteTable(table)} t WHERE true${whereSql}${order}${limit}${offset}`;
|
|
1785
1799
|
return asTableRows(table, await (await at()).unsafe(sql, params));
|
|
1786
1800
|
},
|
|
1787
1801
|
/**
|
|
@@ -1866,7 +1880,7 @@ function createOps(tx) {
|
|
|
1866
1880
|
};
|
|
1867
1881
|
const userWhereC = compileWhere(table, cfg.colSet, params.where ?? {}, addC);
|
|
1868
1882
|
const whereC = userWhereC + excludeSql(cfg.pk, excl, addC) + validityFor(addC);
|
|
1869
|
-
const parentJoinC = ` JOIN ${
|
|
1883
|
+
const parentJoinC = ` JOIN ${quoteTable(table)} t ON t.${quoteIdent(cfg.pk)} = c.${pidQ} WHERE true${whereC} AND `;
|
|
1870
1884
|
const liveC = await at();
|
|
1871
1885
|
const K2 = 50;
|
|
1872
1886
|
const cpool = Math.max(limit * 9, 90);
|
|
@@ -1910,7 +1924,7 @@ function createOps(tx) {
|
|
|
1910
1924
|
} else {
|
|
1911
1925
|
fusedSrc = `WITH kw AS (${kwIn}), fused AS (SELECT kw.pid, kw.chunk_seq, (1.0/(${K2} + kw.r))::float8 AS cscore FROM kw)`;
|
|
1912
1926
|
}
|
|
1913
|
-
const inner = `${fusedSrc}, ranked AS (SELECT f.pid, f.chunk_seq, f.cscore, ROW_NUMBER() OVER (PARTITION BY f.pid ORDER BY f.cscore DESC, f.chunk_seq) AS rn FROM fused f), grouped AS (SELECT r.pid, MAX(r.cscore) AS _score, json_agg(json_build_object('content', c.content, 'score', r.cscore, 'chunkSeq', r.chunk_seq, 'charStart', c.char_start) ORDER BY r.cscore DESC, r.chunk_seq) FILTER (WHERE r.rn <= ${bpr}) AS blocks FROM ranked r JOIN ${quoteIdent(ck.table)} c ON c.${pidQ} = r.pid AND c.chunk_seq = r.chunk_seq GROUP BY r.pid) SELECT ${colListC}, ${scoreC}::float8 AS _score, g.blocks AS blocks${kwnCol} FROM grouped g JOIN ${
|
|
1927
|
+
const inner = `${fusedSrc}, ranked AS (SELECT f.pid, f.chunk_seq, f.cscore, ROW_NUMBER() OVER (PARTITION BY f.pid ORDER BY f.cscore DESC, f.chunk_seq) AS rn FROM fused f), grouped AS (SELECT r.pid, MAX(r.cscore) AS _score, json_agg(json_build_object('content', c.content, 'score', r.cscore, 'chunkSeq', r.chunk_seq, 'charStart', c.char_start) ORDER BY r.cscore DESC, r.chunk_seq) FILTER (WHERE r.rn <= ${bpr}) AS blocks FROM ranked r JOIN ${quoteIdent(ck.table)} c ON c.${pidQ} = r.pid AND c.chunk_seq = r.chunk_seq GROUP BY r.pid) SELECT ${colListC}, ${scoreC}::float8 AS _score, g.blocks AS blocks${kwnCol} FROM grouped g JOIN ${quoteTable(table)} t ON t.${quoteIdent(cfg.pk)} = g.pid`;
|
|
1914
1928
|
return msC === "" ? `SELECT * FROM (${inner}) q ORDER BY q._score DESC, q.${quoteIdent(cfg.pk)} LIMIT ${limit}` : `SELECT * FROM (${inner}) q WHERE q._score >= ${msC} ORDER BY q._score DESC, q.${quoteIdent(cfg.pk)} LIMIT ${limit}`;
|
|
1915
1929
|
};
|
|
1916
1930
|
let rowsC = await liveC.unsafe(assembleC(kwC, kwC !== ""), bindC);
|
|
@@ -1967,7 +1981,7 @@ function createOps(tx) {
|
|
|
1967
1981
|
let exactOrder = "";
|
|
1968
1982
|
if (userWhere !== "") {
|
|
1969
1983
|
const probeRows = await live.unsafe(
|
|
1970
|
-
`SELECT count(*)::int AS n FROM (SELECT 1 FROM ${
|
|
1984
|
+
`SELECT count(*)::int AS n FROM (SELECT 1 FROM ${quoteTable(table)} t WHERE t.${quoteIdent(leg.column)} IS NOT NULL${whereSql} LIMIT ${SELECTIVITY_EXACT_THRESHOLD + 1}) s`,
|
|
1971
1985
|
bind.slice()
|
|
1972
1986
|
);
|
|
1973
1987
|
const n = probeRows?.[0]?.n;
|
|
@@ -1976,7 +1990,7 @@ function createOps(tx) {
|
|
|
1976
1990
|
}
|
|
1977
1991
|
}
|
|
1978
1992
|
const vp = add(toVectorLiteral(qv));
|
|
1979
|
-
semSql = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY (t.${quoteIdent(leg.column)} OPERATOR(${quoteIdent(sch)}.${op}) ${vp}::${quoteIdent(sch)}.vector)${exactOrder}) AS r FROM ${
|
|
1993
|
+
semSql = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY (t.${quoteIdent(leg.column)} OPERATOR(${quoteIdent(sch)}.${op}) ${vp}::${quoteIdent(sch)}.vector)${exactOrder}) AS r FROM ${quoteTable(table)} t WHERE t.${quoteIdent(leg.column)} IS NOT NULL${whereSql} ORDER BY r LIMIT ${pool}`;
|
|
1980
1994
|
}
|
|
1981
1995
|
let qpRef = "";
|
|
1982
1996
|
let qpIdx = -1;
|
|
@@ -1985,7 +1999,7 @@ function createOps(tx) {
|
|
|
1985
1999
|
const qp = add(qText);
|
|
1986
2000
|
qpIdx = bind.length - 1;
|
|
1987
2001
|
qpRef = qp;
|
|
1988
|
-
kwSql = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(t.palbase_fts, websearch_to_tsquery('simple', ${qp})) DESC) AS r FROM ${
|
|
2002
|
+
kwSql = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY ts_rank_cd(t.palbase_fts, websearch_to_tsquery('simple', ${qp})) DESC) AS r FROM ${quoteTable(table)} t WHERE t.palbase_fts @@ websearch_to_tsquery('simple', ${qp})${whereSql} ORDER BY r LIMIT ${pool}`;
|
|
1989
2003
|
}
|
|
1990
2004
|
const colList = cfg.cols.map((c) => `t.${quoteIdent(c)}`).join(", ");
|
|
1991
2005
|
const msP = params.minScore === void 0 ? "" : add(params.minScore);
|
|
@@ -1996,14 +2010,14 @@ function createOps(tx) {
|
|
|
1996
2010
|
let orderScore;
|
|
1997
2011
|
if (semSql !== "" && kwIn !== "") {
|
|
1998
2012
|
const score = scoreMul === "" ? "fused._score" : `(fused._score)${scoreMul}`;
|
|
1999
|
-
inner = `WITH sem AS (${semSql}), kw AS (${kwIn}), fused AS (SELECT COALESCE(sem.id, kw.id) AS id, (COALESCE(1.0/(${K} + sem.r), 0) + COALESCE(1.0/(${K} + kw.r), 0))::float8 AS _score FROM sem FULL OUTER JOIN kw ON sem.id = kw.id) SELECT ${colList}, ${score} AS _score${hlCol}${kwnCol} FROM fused JOIN ${
|
|
2013
|
+
inner = `WITH sem AS (${semSql}), kw AS (${kwIn}), fused AS (SELECT COALESCE(sem.id, kw.id) AS id, (COALESCE(1.0/(${K} + sem.r), 0) + COALESCE(1.0/(${K} + kw.r), 0))::float8 AS _score FROM sem FULL OUTER JOIN kw ON sem.id = kw.id) SELECT ${colList}, ${score} AS _score${hlCol}${kwnCol} FROM fused JOIN ${quoteTable(table)} t ON t.${quoteIdent(cfg.pk)} = fused.id`;
|
|
2000
2014
|
orderScore = scoreMul === "" ? "fused._score" : "_score";
|
|
2001
2015
|
} else {
|
|
2002
2016
|
const single = semSql !== "" ? `sem AS (${semSql})` : `kw AS (${kwIn})`;
|
|
2003
2017
|
const alias = semSql !== "" ? "sem" : "kw";
|
|
2004
2018
|
const base = `(1.0/(${K} + ${alias}.r))::float8`;
|
|
2005
2019
|
const score = scoreMul === "" ? base : `(${base})${scoreMul}`;
|
|
2006
|
-
inner = `WITH ${single} SELECT ${colList}, ${score} AS _score${hlCol}${semSql !== "" ? "" : kwnCol} FROM ${alias} JOIN ${
|
|
2020
|
+
inner = `WITH ${single} SELECT ${colList}, ${score} AS _score${hlCol}${semSql !== "" ? "" : kwnCol} FROM ${alias} JOIN ${quoteTable(table)} t ON t.${quoteIdent(cfg.pk)} = ${alias}.id`;
|
|
2007
2021
|
orderScore = "_score";
|
|
2008
2022
|
}
|
|
2009
2023
|
return msP === "" ? `${inner} ORDER BY ${orderScore} DESC, t.${quoteIdent(cfg.pk)} LIMIT ${limit}` : `SELECT * FROM (${inner}) q WHERE q._score >= ${msP} ORDER BY q._score DESC, q.${quoteIdent(cfg.pk)} LIMIT ${limit}`;
|
|
@@ -2012,7 +2026,7 @@ function createOps(tx) {
|
|
|
2012
2026
|
if (wantText && kwSql !== "" && (rows.length === 0 || rows[0]._kwn === 0)) {
|
|
2013
2027
|
const tsch = await trgmSchemaOf(live);
|
|
2014
2028
|
const expr = ftsExprOf(cfg.ftsCols);
|
|
2015
|
-
const trgmKw = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY ${quoteIdent(tsch)}.word_similarity(${qpRef}, ${expr}) DESC) AS r FROM ${
|
|
2029
|
+
const trgmKw = `SELECT t.${quoteIdent(cfg.pk)} AS id, ROW_NUMBER() OVER (ORDER BY ${quoteIdent(tsch)}.word_similarity(${qpRef}, ${expr}) DESC) AS r FROM ${quoteTable(table)} t WHERE ${quoteIdent(tsch)}.word_similarity(${qpRef}, ${expr}) > 0.3${whereSql} ORDER BY r LIMIT ${pool}`;
|
|
2016
2030
|
const retryBind = bind.slice();
|
|
2017
2031
|
if (qpIdx >= 0) retryBind[qpIdx] = params.query;
|
|
2018
2032
|
rows = await live.unsafe(assemble(trgmKw, false), retryBind);
|
|
@@ -2074,7 +2088,7 @@ function createOps(tx) {
|
|
|
2074
2088
|
throw new Error(`similar(${table}): tabloda vekt\xF6r kolonu yok \u2014 benzerlik semantik vekt\xF6r ister (FR-022)`);
|
|
2075
2089
|
}
|
|
2076
2090
|
const rows = await live.unsafe(
|
|
2077
|
-
`SELECT t.${quoteIdent(leg.column)} AS v FROM ${
|
|
2091
|
+
`SELECT t.${quoteIdent(leg.column)} AS v FROM ${quoteTable(table)} t WHERE t.${quoteIdent(cfg.pk)} = $1`,
|
|
2078
2092
|
[id]
|
|
2079
2093
|
);
|
|
2080
2094
|
v = rows?.[0]?.v;
|
|
@@ -2131,7 +2145,7 @@ function createOps(tx) {
|
|
|
2131
2145
|
};
|
|
2132
2146
|
const avgSel = (ids) => {
|
|
2133
2147
|
const inList = ids.map((x) => add(x)).join(", ");
|
|
2134
|
-
return cfg.chunk !== void 0 ? `SELECT ${quoteIdent(sch)}.avg(c.embedding) AS v FROM ${quoteIdent(cfg.chunk.table)} c WHERE c.${quoteIdent(`parent_${cfg.pk}`)} IN (${inList}) AND c.embedding IS NOT NULL` : `SELECT ${quoteIdent(sch)}.avg(t.${quoteIdent(leg.column)}) AS v FROM ${
|
|
2148
|
+
return cfg.chunk !== void 0 ? `SELECT ${quoteIdent(sch)}.avg(c.embedding) AS v FROM ${quoteIdent(cfg.chunk.table)} c WHERE c.${quoteIdent(`parent_${cfg.pk}`)} IN (${inList}) AND c.embedding IS NOT NULL` : `SELECT ${quoteIdent(sch)}.avg(t.${quoteIdent(leg.column)}) AS v FROM ${quoteTable(table)} t WHERE t.${quoteIdent(cfg.pk)} IN (${inList}) AND t.${quoteIdent(leg.column)} IS NOT NULL`;
|
|
2135
2149
|
};
|
|
2136
2150
|
const targetSql = negative.length === 0 ? `WITH pos AS (${avgSel(positive)}) SELECT pos.v AS v, (pos.v IS NULL) AS pos_missing FROM pos` : `WITH pos AS (${avgSel(positive)}), neg AS (${avgSel(negative)}) SELECT (pos.v OPERATOR(${quoteIdent(sch)}.+) (pos.v OPERATOR(${quoteIdent(sch)}.-) neg.v)) AS v, (pos.v IS NULL) AS pos_missing, (neg.v IS NULL) AS neg_missing FROM pos, neg`;
|
|
2137
2151
|
const rows = await live.unsafe(targetSql, bind);
|
|
@@ -2179,7 +2193,7 @@ function createOps(tx) {
|
|
|
2179
2193
|
return live.savepoint(async (sp) => {
|
|
2180
2194
|
const newId = row[cfg.pk] ?? crypto.randomUUID();
|
|
2181
2195
|
const closed = await sp.unsafe(
|
|
2182
|
-
`UPDATE ${
|
|
2196
|
+
`UPDATE ${quoteTable(table)} SET "valid_to" = now(), "superseded_by" = $1 WHERE ${quoteIdent(cfg.pk)} = $2 AND "valid_to" IS NULL RETURNING ${quoteIdent(cfg.pk)}`,
|
|
2183
2197
|
[newId, id]
|
|
2184
2198
|
);
|
|
2185
2199
|
if (closed.length === 0) {
|
|
@@ -2189,7 +2203,7 @@ function createOps(tx) {
|
|
|
2189
2203
|
const cols = Object.keys(data);
|
|
2190
2204
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
2191
2205
|
const rows = await sp.unsafe(
|
|
2192
|
-
`INSERT INTO ${
|
|
2206
|
+
`INSERT INTO ${quoteTable(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`,
|
|
2193
2207
|
asBindParams(table, cols, data, "supersede")
|
|
2194
2208
|
);
|
|
2195
2209
|
if (!rows[0]) {
|
|
@@ -2261,27 +2275,50 @@ function createOps(tx) {
|
|
|
2261
2275
|
return ops;
|
|
2262
2276
|
}
|
|
2263
2277
|
var currentSchema = {};
|
|
2264
|
-
function setSchema(
|
|
2278
|
+
function setSchema(schemas) {
|
|
2265
2279
|
cachedVectorSchema = null;
|
|
2266
2280
|
cachedTrgmSchema = null;
|
|
2267
|
-
const
|
|
2268
|
-
|
|
2281
|
+
const tables = {};
|
|
2282
|
+
for (const entry of schemas) {
|
|
2283
|
+
const mod = entry;
|
|
2284
|
+
const def = (mod && "default" in mod ? mod.default : mod) ?? {};
|
|
2285
|
+
const schemaName = def.name ?? "public";
|
|
2286
|
+
for (const [key, table] of Object.entries(def.tables ?? {})) {
|
|
2287
|
+
tables[qualifiedTableKey(schemaName, table.name ?? key)] = table;
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
currentSchema = { tables };
|
|
2291
|
+
}
|
|
2292
|
+
function qualifiedTableKey(schema, table) {
|
|
2293
|
+
return schema === "" || schema === "public" ? table : `${schema}.${table}`;
|
|
2269
2294
|
}
|
|
2270
2295
|
function withTables(ops, schema = currentSchema) {
|
|
2296
|
+
const bind = (key) => ({
|
|
2297
|
+
insert: (data) => ops.insert(key, data),
|
|
2298
|
+
update: (id, data) => ops.update(key, id, data),
|
|
2299
|
+
delete: (id) => ops.delete(key, id),
|
|
2300
|
+
findById: (id) => ops.findById(key, id),
|
|
2301
|
+
findMany: (query, opts) => ops.findMany(key, query ?? {}, opts),
|
|
2302
|
+
upsert: (data, opts) => ops.upsert(key, data, opts)
|
|
2303
|
+
});
|
|
2271
2304
|
const tables = {};
|
|
2272
2305
|
for (const key of Object.keys(schema.tables ?? {})) {
|
|
2273
|
-
|
|
2274
|
-
tables[key] = {
|
|
2275
|
-
insert: (data) => ops.insert(name, data),
|
|
2276
|
-
update: (id, data) => ops.update(name, id, data),
|
|
2277
|
-
delete: (id) => ops.delete(name, id),
|
|
2278
|
-
findById: (id) => ops.findById(name, id),
|
|
2279
|
-
findMany: (query, opts) => ops.findMany(name, query ?? {}, opts),
|
|
2280
|
-
upsert: (data, opts) => ops.upsert(name, data, opts)
|
|
2281
|
-
};
|
|
2306
|
+
if (!key.includes(".")) tables[key] = bind(key);
|
|
2282
2307
|
}
|
|
2308
|
+
const schemaOf = (name) => {
|
|
2309
|
+
const out = {};
|
|
2310
|
+
const prefix = `${name}.`;
|
|
2311
|
+
for (const key of Object.keys(schema.tables ?? {})) {
|
|
2312
|
+
if (name === "public") {
|
|
2313
|
+
if (!key.includes(".")) out[key] = bind(key);
|
|
2314
|
+
} else if (key.startsWith(prefix)) {
|
|
2315
|
+
out[key.slice(prefix.length)] = bind(key);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
return { tables: out };
|
|
2319
|
+
};
|
|
2283
2320
|
const base = /* @__PURE__ */ Object.create(null);
|
|
2284
|
-
return Object.assign(base, ops, { tables });
|
|
2321
|
+
return Object.assign(base, ops, { tables, schema: schemaOf });
|
|
2285
2322
|
}
|
|
2286
2323
|
var SERVICE_LOCK_TIMEOUT = "5s";
|
|
2287
2324
|
function isAbortedTransaction(e) {
|
|
@@ -2573,6 +2610,7 @@ function assertZeroArgConstructor(Ctrl, kind) {
|
|
|
2573
2610
|
}
|
|
2574
2611
|
|
|
2575
2612
|
// src/engine/router.ts
|
|
2613
|
+
var ROOM_META = /* @__PURE__ */ Symbol.for("palbase.backend.room");
|
|
2576
2614
|
var CONTROLLER_META = /* @__PURE__ */ Symbol.for("palbase.backend.controllerMeta");
|
|
2577
2615
|
function toSegments(path) {
|
|
2578
2616
|
return path.split("/").filter(Boolean).map((s) => s.startsWith("{") && s.endsWith("}") ? `:${s.slice(1, -1)}` : s);
|
|
@@ -2580,6 +2618,7 @@ function toSegments(path) {
|
|
|
2580
2618
|
function buildRouteTable(controllers) {
|
|
2581
2619
|
const table = [];
|
|
2582
2620
|
for (const Ctrl of controllers) {
|
|
2621
|
+
if (Ctrl[ROOM_META] !== void 0) continue;
|
|
2583
2622
|
const ctor = Ctrl;
|
|
2584
2623
|
const meta = ctor[CONTROLLER_META];
|
|
2585
2624
|
const basePath = meta?.basePath ?? "";
|
|
@@ -2838,7 +2877,7 @@ async function defaultSqlDriver(config) {
|
|
|
2838
2877
|
var AUTHOR_ANSWERED = /* @__PURE__ */ new Set([400, 401, 403, 404, 409, 429]);
|
|
2839
2878
|
async function createApp(opts) {
|
|
2840
2879
|
const { config, controllers } = opts;
|
|
2841
|
-
setSchema(opts.
|
|
2880
|
+
setSchema(opts.schemas ?? []);
|
|
2842
2881
|
setSecretReader(opts.secretReader ?? null);
|
|
2843
2882
|
const routes = buildRouteTable(controllers);
|
|
2844
2883
|
if (routes.length === 0) {
|