@palbase/backend 24.0.2 → 24.1.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 +61 -9
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +2 -2
- package/dist/{chunk-T5IOSOE5.js → chunk-ERDL5VAE.js} +2 -2
- package/dist/{chunk-RPZNHY7J.js → chunk-HPUSV4AZ.js} +57 -11
- package/dist/chunk-HPUSV4AZ.js.map +1 -0
- package/dist/{chunk-H3JAISUY.js → chunk-UWSYTUGM.js} +11 -1
- package/dist/{chunk-H3JAISUY.js.map → chunk-UWSYTUGM.js.map} +1 -1
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/engine/index.cjs +61 -9
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +4 -4
- package/dist/engine/index.d.ts +4 -4
- package/dist/engine/index.js +2 -2
- package/dist/{index-BOS_rFBO.d.ts → index-ByBMibIJ.d.ts} +1 -1
- package/dist/{index-dJNhDZ7j.d.ts → index-C0PMn5jl.d.ts} +3 -3
- package/dist/{index-MoQ31B6M.d.cts → index-D4rts8T7.d.cts} +1 -1
- package/dist/{index-C84bLgeO.d.cts → index-DAwHMppB.d.cts} +3 -3
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -9
- package/dist/index.d.ts +23 -9
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/openapi/index.js +2 -2
- package/dist/{registry-CEod_5sz.d.ts → registry-B8pld3fj.d.ts} +1 -1
- package/dist/{registry-1X-skBNu.d.cts → registry-CgJvDYUW.d.cts} +1 -1
- 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.map +1 -1
- package/docs/README.md +5 -1
- package/docs/llms-full.txt +5 -1
- package/package.json +1 -1
- package/template/AGENTS.md +34 -22
- package/dist/chunk-RPZNHY7J.js.map +0 -1
- package/dist/{chunk-T5IOSOE5.js.map → chunk-ERDL5VAE.js.map} +0 -0
- package/dist/{endpoint-CcQ1a36a.d.cts → endpoint-BSGw1pTu.d.cts} +16 -16
- package/dist/{endpoint-0_DGBajf.d.ts → endpoint-DMwJjEHQ.d.ts} +16 -16
|
@@ -635,6 +635,14 @@ var Realtime = makeServiceProxy("Realtime");
|
|
|
635
635
|
|
|
636
636
|
// src/errors.ts
|
|
637
637
|
var HTTP_ERROR_BRAND = /* @__PURE__ */ Symbol.for("palbase.backend.httpError");
|
|
638
|
+
var ENGINE_RAISED = /* @__PURE__ */ Symbol.for("palbase.backend.engineRaised");
|
|
639
|
+
function markEngineRaised(e) {
|
|
640
|
+
e[ENGINE_RAISED] = true;
|
|
641
|
+
return e;
|
|
642
|
+
}
|
|
643
|
+
function isEngineRaised(e) {
|
|
644
|
+
return typeof e === "object" && e !== null && e[ENGINE_RAISED] === true;
|
|
645
|
+
}
|
|
638
646
|
function isHttpError(err) {
|
|
639
647
|
if (typeof err !== "object" || err === null) return false;
|
|
640
648
|
const e = err;
|
|
@@ -1156,7 +1164,14 @@ function asTableRows(table, rows) {
|
|
|
1156
1164
|
const transforms = transformsOf(currentSchema, table);
|
|
1157
1165
|
return rows.map((row) => applyFromDb(reviveVectors(asWireRow(row), vectorCols), transforms));
|
|
1158
1166
|
}
|
|
1159
|
-
function asBindParams(table, cols, data) {
|
|
1167
|
+
function asBindParams(table, cols, data, caller) {
|
|
1168
|
+
for (const c of cols) {
|
|
1169
|
+
if (data[c] === void 0) {
|
|
1170
|
+
throw new Error(
|
|
1171
|
+
`${caller}(${table}): "${c}" de\u011Feri undefined \u2014 bu bir yazma de\u011Feri de\u011Fil. Kolonu bo\u015Faltmak istiyorsan null yaz; kolonu de\u011Fi\u015Ftirmek istemiyorsan nesneye hi\xE7 koyma (bir eksik istek alan\u0131 sessizce NULL yaz\u0131yordu \u2014 FR-016).`
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1160
1175
|
const vectorCols = vectorColumnsOf(currentSchema, table);
|
|
1161
1176
|
const transforms = transformsOf(currentSchema, table);
|
|
1162
1177
|
return cols.map((c) => {
|
|
@@ -1383,23 +1398,49 @@ function compileWhere(table, colSet, where, add, caller = "search") {
|
|
|
1383
1398
|
if (colSet !== null && !colSet.has(col)) {
|
|
1384
1399
|
throw new Error(`${caller}(${table}): where kolonu "${col}" tabloda yok (FR-016)`);
|
|
1385
1400
|
}
|
|
1401
|
+
if (cond === void 0) {
|
|
1402
|
+
throw new Error(
|
|
1403
|
+
`${caller}(${table}): where.${col} de\u011Feri undefined \u2014 bu bir filtre de\u011Feri de\u011Fil. Ba\u011Flan\u0131nca NULL olur ve '= NULL' hi\xE7bir sat\u0131ra uymaz, yani sorgu sessizce bo\u015F sonu\xE7 d\xF6nerdi. De\u011Fer yoksa anahtar\u0131 filtreye hi\xE7 koymay\u0131n.`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1386
1406
|
const q = `t.${quoteIdent(col)}`;
|
|
1387
1407
|
const bind = bindFor(col);
|
|
1388
1408
|
if (cond !== null && typeof cond === "object" && !Array.isArray(cond)) {
|
|
1409
|
+
if (Object.keys(cond).length === 0) {
|
|
1410
|
+
throw new Error(
|
|
1411
|
+
`${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).`
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1389
1414
|
for (const [op, v] of Object.entries(cond)) {
|
|
1390
1415
|
if (op === "in") {
|
|
1391
1416
|
if (!Array.isArray(v)) throw new Error(`${caller}(${table}): where.${col}.in bir dizi olmal\u0131`);
|
|
1417
|
+
if (v.some((x) => x === void 0)) {
|
|
1418
|
+
throw new Error(
|
|
1419
|
+
`${caller}(${table}): where.${col}.in listesinde undefined var \u2014 sessizce NULL'a ba\u011Flan\u0131r ve o eleman hi\xE7bir sat\u0131rla e\u015Fle\u015Fmez. Listeyi kurarken eleyin.`
|
|
1420
|
+
);
|
|
1421
|
+
}
|
|
1392
1422
|
if (v.length === 0) {
|
|
1393
1423
|
parts.push("false");
|
|
1394
1424
|
continue;
|
|
1395
1425
|
}
|
|
1396
1426
|
parts.push(`${q} IN (${v.map((x) => bind(x)).join(", ")})`);
|
|
1397
1427
|
} else if (op in WHERE_OPS) {
|
|
1428
|
+
if (v === void 0) {
|
|
1429
|
+
throw new Error(
|
|
1430
|
+
`${caller}(${table}): where.${col}.${op} de\u011Feri undefined \u2014 kar\u015F\u0131la\u015Ft\u0131rman\u0131n sa\u011F taraf\u0131 NULL olur ve sonu\xE7 hi\xE7bir sat\u0131ra uymaz. Ko\u015Fulu kurmay\u0131n.`
|
|
1431
|
+
);
|
|
1432
|
+
}
|
|
1433
|
+
if (v === null && (op === "neq" || op === "eq")) {
|
|
1434
|
+
parts.push(`${q} IS ${op === "neq" ? "NOT " : ""}NULL`);
|
|
1435
|
+
continue;
|
|
1436
|
+
}
|
|
1398
1437
|
parts.push(`${q} ${WHERE_OPS[op]} ${bind(v)}`);
|
|
1399
1438
|
} else {
|
|
1400
1439
|
throw new Error(`${caller}(${table}): where.${col} bilinmeyen operat\xF6r "${op}" (gt/gte/lt/lte/neq/in)`);
|
|
1401
1440
|
}
|
|
1402
1441
|
}
|
|
1442
|
+
} else if (cond === null) {
|
|
1443
|
+
parts.push(`${q} IS NULL`);
|
|
1403
1444
|
} else {
|
|
1404
1445
|
parts.push(`${q} = ${bind(cond)}`);
|
|
1405
1446
|
}
|
|
@@ -1492,7 +1533,7 @@ function createOps(tx) {
|
|
|
1492
1533
|
if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);
|
|
1493
1534
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
1494
1535
|
const sql = `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`;
|
|
1495
|
-
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data));
|
|
1536
|
+
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "insert"));
|
|
1496
1537
|
const inserted = rows[0];
|
|
1497
1538
|
if (!inserted) {
|
|
1498
1539
|
throw new Error(
|
|
@@ -1526,7 +1567,7 @@ function createOps(tx) {
|
|
|
1526
1567
|
const ph = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
1527
1568
|
const insertSql = `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${ph}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) WHERE "valid_to" IS NULL DO NOTHING RETURNING *`;
|
|
1528
1569
|
const live = await at();
|
|
1529
|
-
const bindData = asBindParams(table, cols, data);
|
|
1570
|
+
const bindData = asBindParams(table, cols, data, "upsert");
|
|
1530
1571
|
const first = await live.unsafe(insertSql, bindData);
|
|
1531
1572
|
if (first[0]) return asTableRow(table, first[0]);
|
|
1532
1573
|
const condSql = conflict.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(" AND ");
|
|
@@ -1560,7 +1601,7 @@ function createOps(tx) {
|
|
|
1560
1601
|
const assignments = cols.filter((c) => !conflictSet.has(c)).map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`);
|
|
1561
1602
|
const action = assignments.length ? `DO UPDATE SET ${assignments.join(", ")}` : `DO UPDATE SET ${quoteIdent(conflict[0])} = EXCLUDED.${quoteIdent(conflict[0])}`;
|
|
1562
1603
|
const sql = `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) ${action} RETURNING *`;
|
|
1563
|
-
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data));
|
|
1604
|
+
const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "upsert"));
|
|
1564
1605
|
const row = rows[0];
|
|
1565
1606
|
if (!row) {
|
|
1566
1607
|
throw new Error(
|
|
@@ -1574,7 +1615,7 @@ function createOps(tx) {
|
|
|
1574
1615
|
if (cols.length === 0) return ops.findById(table, id);
|
|
1575
1616
|
const assignments = cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(", ");
|
|
1576
1617
|
const sql = `UPDATE ${quoteIdent(table)} SET ${assignments} WHERE id = $${cols.length + 1} RETURNING *`;
|
|
1577
|
-
const rows = await (await at()).unsafe(sql, [...asBindParams(table, cols, data), id]);
|
|
1618
|
+
const rows = await (await at()).unsafe(sql, [...asBindParams(table, cols, data, "update"), id]);
|
|
1578
1619
|
return rows[0] ? asTableRow(table, rows[0]) : null;
|
|
1579
1620
|
},
|
|
1580
1621
|
async delete(table, id) {
|
|
@@ -1605,13 +1646,20 @@ function createOps(tx) {
|
|
|
1605
1646
|
`updateMany(${table}): nothing to set. An update with no columns is not a no-op worth pretending happened \u2014 pass the columns to write.`
|
|
1606
1647
|
);
|
|
1607
1648
|
}
|
|
1649
|
+
const known = schemaColumns(table);
|
|
1650
|
+
if (known !== null) {
|
|
1651
|
+
for (const c of cols) {
|
|
1652
|
+
if (!known.has(c)) {
|
|
1653
|
+
throw new Error(`updateMany(${table}): set kolonu "${c}" tabloda yok (FR-016)`);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1608
1657
|
const params = [];
|
|
1609
1658
|
const add = (v) => {
|
|
1610
1659
|
params.push(v);
|
|
1611
1660
|
return `$${params.length}`;
|
|
1612
1661
|
};
|
|
1613
|
-
const assignments = cols.map((c) => `${quoteIdent(c)} = ${add(asBindParams(table, [c], set)[0])}`).join(", ");
|
|
1614
|
-
const known = schemaColumns(table);
|
|
1662
|
+
const assignments = cols.map((c) => `${quoteIdent(c)} = ${add(asBindParams(table, [c], set, "updateMany")[0])}`).join(", ");
|
|
1615
1663
|
const whereSql = compileWhere(table, known, where, add, "updateMany");
|
|
1616
1664
|
assertHasPredicate(whereSql, "updateMany", table);
|
|
1617
1665
|
const sql = `UPDATE ${quoteIdent(table)} AS t SET ${assignments} WHERE true${whereSql} RETURNING *`;
|
|
@@ -2083,7 +2131,7 @@ function createOps(tx) {
|
|
|
2083
2131
|
const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
|
|
2084
2132
|
const rows = await sp.unsafe(
|
|
2085
2133
|
`INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`,
|
|
2086
|
-
asBindParams(table, cols, data)
|
|
2134
|
+
asBindParams(table, cols, data, "supersede")
|
|
2087
2135
|
);
|
|
2088
2136
|
if (!rows[0]) {
|
|
2089
2137
|
throw new Error(
|
|
@@ -2223,7 +2271,7 @@ function diagnosingDriver(sql, surface = "service") {
|
|
|
2223
2271
|
);
|
|
2224
2272
|
}
|
|
2225
2273
|
if (isUniqueViolation(e)) {
|
|
2226
|
-
return new UniqueViolation(constraintOf(e));
|
|
2274
|
+
return markEngineRaised(new UniqueViolation(constraintOf(e)));
|
|
2227
2275
|
}
|
|
2228
2276
|
if (surface === "service" && isForeignKeyViolation(e)) {
|
|
2229
2277
|
return new Error(
|
|
@@ -2679,6 +2727,7 @@ async function defaultSqlDriver(config) {
|
|
|
2679
2727
|
}
|
|
2680
2728
|
return new g.Bun.SQL({ url: config.databaseUrl, max: config.poolMax });
|
|
2681
2729
|
}
|
|
2730
|
+
var AUTHOR_ANSWERED = /* @__PURE__ */ new Set([400, 401, 403, 404, 409, 429]);
|
|
2682
2731
|
async function createApp(opts) {
|
|
2683
2732
|
const { config, controllers } = opts;
|
|
2684
2733
|
setSchema(opts.schema ?? {});
|
|
@@ -3064,6 +3113,9 @@ async function createApp(opts) {
|
|
|
3064
3113
|
} catch (err) {
|
|
3065
3114
|
await db.rollback(err);
|
|
3066
3115
|
if (isHttpError(err)) {
|
|
3116
|
+
if (isEngineRaised(err) || !AUTHOR_ANSWERED.has(err.status)) {
|
|
3117
|
+
log.error(`[engine] unhandled ${err.error} in ${hit.entry.id}`, err);
|
|
3118
|
+
}
|
|
3067
3119
|
return envelope(
|
|
3068
3120
|
err.error,
|
|
3069
3121
|
err.errorDescription,
|