@palbase/backend 24.0.1 → 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.
Files changed (44) hide show
  1. package/dist/bin/palbase-backend.cjs +75 -18
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +2 -2
  4. package/dist/{chunk-T5IOSOE5.js → chunk-ERDL5VAE.js} +2 -2
  5. package/dist/{chunk-YSQBC2VL.js → chunk-HPUSV4AZ.js} +71 -20
  6. package/dist/chunk-HPUSV4AZ.js.map +1 -0
  7. package/dist/{chunk-H3JAISUY.js → chunk-UWSYTUGM.js} +11 -1
  8. package/dist/{chunk-H3JAISUY.js.map → chunk-UWSYTUGM.js.map} +1 -1
  9. package/dist/db/index.d.cts +2 -2
  10. package/dist/db/index.d.ts +2 -2
  11. package/dist/engine/index.cjs +75 -18
  12. package/dist/engine/index.cjs.map +1 -1
  13. package/dist/engine/index.d.cts +4 -4
  14. package/dist/engine/index.d.ts +4 -4
  15. package/dist/engine/index.js +2 -2
  16. package/dist/{index-BOS_rFBO.d.ts → index-ByBMibIJ.d.ts} +1 -1
  17. package/dist/{index-dJNhDZ7j.d.ts → index-C0PMn5jl.d.ts} +3 -3
  18. package/dist/{index-MoQ31B6M.d.cts → index-D4rts8T7.d.cts} +1 -1
  19. package/dist/{index-C84bLgeO.d.cts → index-DAwHMppB.d.cts} +3 -3
  20. package/dist/index.cjs +8 -0
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +23 -9
  23. package/dist/index.d.ts +23 -9
  24. package/dist/index.js +5 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/openapi/index.cjs.map +1 -1
  27. package/dist/openapi/index.d.cts +2 -2
  28. package/dist/openapi/index.d.ts +2 -2
  29. package/dist/openapi/index.js +2 -2
  30. package/dist/{registry-CEod_5sz.d.ts → registry-B8pld3fj.d.ts} +1 -1
  31. package/dist/{registry-1X-skBNu.d.cts → registry-CgJvDYUW.d.cts} +1 -1
  32. package/dist/test/index.cjs.map +1 -1
  33. package/dist/test/index.d.cts +1 -1
  34. package/dist/test/index.d.ts +1 -1
  35. package/dist/test/index.js.map +1 -1
  36. package/docs/README.md +5 -1
  37. package/docs/llms-full.txt +5 -1
  38. package/package.json +1 -1
  39. package/template/AGENTS.md +34 -22
  40. package/template/tsconfig.json +6 -0
  41. package/dist/chunk-YSQBC2VL.js.map +0 -1
  42. package/dist/{chunk-T5IOSOE5.js.map → chunk-ERDL5VAE.js.map} +0 -0
  43. package/dist/{endpoint-CcQ1a36a.d.cts → endpoint-BSGw1pTu.d.cts} +16 -16
  44. package/dist/{endpoint-0_DGBajf.d.ts → endpoint-DMwJjEHQ.d.ts} +16 -16
@@ -3,12 +3,12 @@ import {
3
3
  BootRefused,
4
4
  createApp,
5
5
  loadConfig
6
- } from "../chunk-YSQBC2VL.js";
6
+ } from "../chunk-HPUSV4AZ.js";
7
7
  import "../chunk-7Z6MGMXQ.js";
8
8
  import "../chunk-P2Q27SGP.js";
9
9
  import {
10
10
  getRegisteredControllers
11
- } from "../chunk-H3JAISUY.js";
11
+ } from "../chunk-UWSYTUGM.js";
12
12
  import "../chunk-7D4SUZUM.js";
13
13
 
14
14
  // src/bin/palbase-backend.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HttpError
3
- } from "./chunk-H3JAISUY.js";
3
+ } from "./chunk-UWSYTUGM.js";
4
4
 
5
5
  // src/error-registry.ts
6
6
  import {
@@ -119,4 +119,4 @@ export {
119
119
  getErrorRegistry,
120
120
  defineError
121
121
  };
122
- //# sourceMappingURL=chunk-T5IOSOE5.js.map
122
+ //# sourceMappingURL=chunk-ERDL5VAE.js.map
@@ -7,9 +7,11 @@ import {
7
7
  UniqueViolation,
8
8
  assertZeroArgConstructor,
9
9
  getRoutes,
10
+ isEngineRaised,
10
11
  isHttpError,
12
+ markEngineRaised,
11
13
  resolveEffectiveAuth
12
- } from "./chunk-H3JAISUY.js";
14
+ } from "./chunk-UWSYTUGM.js";
13
15
 
14
16
  // src/engine/config.ts
15
17
  var BootRefused = class extends Error {
@@ -450,7 +452,14 @@ function asTableRows(table, rows) {
450
452
  const transforms = transformsOf(currentSchema, table);
451
453
  return rows.map((row) => applyFromDb(reviveVectors(asWireRow(row), vectorCols), transforms));
452
454
  }
453
- function asBindParams(table, cols, data) {
455
+ function asBindParams(table, cols, data, caller) {
456
+ for (const c of cols) {
457
+ if (data[c] === void 0) {
458
+ throw new Error(
459
+ `${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).`
460
+ );
461
+ }
462
+ }
454
463
  const vectorCols = vectorColumnsOf(currentSchema, table);
455
464
  const transforms = transformsOf(currentSchema, table);
456
465
  return cols.map((c) => {
@@ -677,23 +686,49 @@ function compileWhere(table, colSet, where, add, caller = "search") {
677
686
  if (colSet !== null && !colSet.has(col)) {
678
687
  throw new Error(`${caller}(${table}): where kolonu "${col}" tabloda yok (FR-016)`);
679
688
  }
689
+ if (cond === void 0) {
690
+ throw new Error(
691
+ `${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.`
692
+ );
693
+ }
680
694
  const q = `t.${quoteIdent(col)}`;
681
695
  const bind = bindFor(col);
682
696
  if (cond !== null && typeof cond === "object" && !Array.isArray(cond)) {
697
+ if (Object.keys(cond).length === 0) {
698
+ throw new Error(
699
+ `${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).`
700
+ );
701
+ }
683
702
  for (const [op, v] of Object.entries(cond)) {
684
703
  if (op === "in") {
685
704
  if (!Array.isArray(v)) throw new Error(`${caller}(${table}): where.${col}.in bir dizi olmal\u0131`);
705
+ if (v.some((x) => x === void 0)) {
706
+ throw new Error(
707
+ `${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.`
708
+ );
709
+ }
686
710
  if (v.length === 0) {
687
711
  parts.push("false");
688
712
  continue;
689
713
  }
690
714
  parts.push(`${q} IN (${v.map((x) => bind(x)).join(", ")})`);
691
715
  } else if (op in WHERE_OPS) {
716
+ if (v === void 0) {
717
+ throw new Error(
718
+ `${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.`
719
+ );
720
+ }
721
+ if (v === null && (op === "neq" || op === "eq")) {
722
+ parts.push(`${q} IS ${op === "neq" ? "NOT " : ""}NULL`);
723
+ continue;
724
+ }
692
725
  parts.push(`${q} ${WHERE_OPS[op]} ${bind(v)}`);
693
726
  } else {
694
727
  throw new Error(`${caller}(${table}): where.${col} bilinmeyen operat\xF6r "${op}" (gt/gte/lt/lte/neq/in)`);
695
728
  }
696
729
  }
730
+ } else if (cond === null) {
731
+ parts.push(`${q} IS NULL`);
697
732
  } else {
698
733
  parts.push(`${q} = ${bind(cond)}`);
699
734
  }
@@ -786,7 +821,7 @@ function createOps(tx) {
786
821
  if (cols.length === 0) throw new Error(`insert into ${table}: no columns given`);
787
822
  const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
788
823
  const sql = `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`;
789
- const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data));
824
+ const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "insert"));
790
825
  const inserted = rows[0];
791
826
  if (!inserted) {
792
827
  throw new Error(
@@ -820,7 +855,7 @@ function createOps(tx) {
820
855
  const ph = cols.map((_, i) => `$${i + 1}`).join(", ");
821
856
  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 *`;
822
857
  const live = await at();
823
- const bindData = asBindParams(table, cols, data);
858
+ const bindData = asBindParams(table, cols, data, "upsert");
824
859
  const first = await live.unsafe(insertSql, bindData);
825
860
  if (first[0]) return asTableRow(table, first[0]);
826
861
  const condSql = conflict.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(" AND ");
@@ -854,7 +889,7 @@ function createOps(tx) {
854
889
  const assignments = cols.filter((c) => !conflictSet.has(c)).map((c) => `${quoteIdent(c)} = EXCLUDED.${quoteIdent(c)}`);
855
890
  const action = assignments.length ? `DO UPDATE SET ${assignments.join(", ")}` : `DO UPDATE SET ${quoteIdent(conflict[0])} = EXCLUDED.${quoteIdent(conflict[0])}`;
856
891
  const sql = `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) ON CONFLICT (${conflict.map(quoteIdent).join(", ")}) ${action} RETURNING *`;
857
- const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data));
892
+ const rows = await (await at()).unsafe(sql, asBindParams(table, cols, data, "upsert"));
858
893
  const row = rows[0];
859
894
  if (!row) {
860
895
  throw new Error(
@@ -868,7 +903,7 @@ function createOps(tx) {
868
903
  if (cols.length === 0) return ops.findById(table, id);
869
904
  const assignments = cols.map((c, i) => `${quoteIdent(c)} = $${i + 1}`).join(", ");
870
905
  const sql = `UPDATE ${quoteIdent(table)} SET ${assignments} WHERE id = $${cols.length + 1} RETURNING *`;
871
- const rows = await (await at()).unsafe(sql, [...asBindParams(table, cols, data), id]);
906
+ const rows = await (await at()).unsafe(sql, [...asBindParams(table, cols, data, "update"), id]);
872
907
  return rows[0] ? asTableRow(table, rows[0]) : null;
873
908
  },
874
909
  async delete(table, id) {
@@ -899,13 +934,20 @@ function createOps(tx) {
899
934
  `updateMany(${table}): nothing to set. An update with no columns is not a no-op worth pretending happened \u2014 pass the columns to write.`
900
935
  );
901
936
  }
937
+ const known = schemaColumns(table);
938
+ if (known !== null) {
939
+ for (const c of cols) {
940
+ if (!known.has(c)) {
941
+ throw new Error(`updateMany(${table}): set kolonu "${c}" tabloda yok (FR-016)`);
942
+ }
943
+ }
944
+ }
902
945
  const params = [];
903
946
  const add = (v) => {
904
947
  params.push(v);
905
948
  return `$${params.length}`;
906
949
  };
907
- const assignments = cols.map((c) => `${quoteIdent(c)} = ${add(asBindParams(table, [c], set)[0])}`).join(", ");
908
- const known = schemaColumns(table);
950
+ const assignments = cols.map((c) => `${quoteIdent(c)} = ${add(asBindParams(table, [c], set, "updateMany")[0])}`).join(", ");
909
951
  const whereSql = compileWhere(table, known, where, add, "updateMany");
910
952
  assertHasPredicate(whereSql, "updateMany", table);
911
953
  const sql = `UPDATE ${quoteIdent(table)} AS t SET ${assignments} WHERE true${whereSql} RETURNING *`;
@@ -1377,7 +1419,7 @@ function createOps(tx) {
1377
1419
  const placeholders = cols.map((_, i) => `$${i + 1}`).join(", ");
1378
1420
  const rows = await sp.unsafe(
1379
1421
  `INSERT INTO ${quoteIdent(table)} (${cols.map(quoteIdent).join(", ")}) VALUES (${placeholders}) RETURNING *`,
1380
- asBindParams(table, cols, data)
1422
+ asBindParams(table, cols, data, "supersede")
1381
1423
  );
1382
1424
  if (!rows[0]) {
1383
1425
  throw new Error(
@@ -1517,7 +1559,7 @@ function diagnosingDriver(sql, surface = "service") {
1517
1559
  );
1518
1560
  }
1519
1561
  if (isUniqueViolation(e)) {
1520
- return new UniqueViolation(constraintOf(e));
1562
+ return markEngineRaised(new UniqueViolation(constraintOf(e)));
1521
1563
  }
1522
1564
  if (surface === "service" && isForeignKeyViolation(e)) {
1523
1565
  return new Error(
@@ -1589,7 +1631,7 @@ function isRef(v) {
1589
1631
  function isExpr(v) {
1590
1632
  return typeof v === "object" && v !== null && "$expr" in v;
1591
1633
  }
1592
- function renderValue(value, column, args, results, vectorCols) {
1634
+ function renderValue(value, column, args, results, vectorCols, transforms) {
1593
1635
  if (isRef(value)) {
1594
1636
  const source = results[value.$ref.op];
1595
1637
  const row = source?.rows[0];
@@ -1598,15 +1640,15 @@ function renderValue(value, column, args, results, vectorCols) {
1598
1640
  error_code: "tx_ref_unresolved"
1599
1641
  });
1600
1642
  }
1601
- return bindMaybeVector(args, column, vectorCols, row[value.$ref.field]);
1643
+ return bindMaybeVector(args, column, vectorCols, row[value.$ref.field], transforms);
1602
1644
  }
1603
1645
  if (isExpr(value)) {
1604
1646
  const fn = value.$expr;
1605
1647
  if (fn.fn === "now") return "now()";
1606
1648
  const operator = fn.fn === "inc" ? "+" : "-";
1607
- return `${quoteIdent(column)} ${operator} ${bindMaybeVector(args, column, vectorCols, fn.by)}`;
1649
+ return `${quoteIdent(column)} ${operator} ${bindMaybeVector(args, column, vectorCols, fn.by, transforms)}`;
1608
1650
  }
1609
- return bindMaybeVector(args, column, vectorCols, value);
1651
+ return bindMaybeVector(args, column, vectorCols, value, transforms);
1610
1652
  }
1611
1653
  function renderWhere(where, args, results) {
1612
1654
  const cols = Object.keys(where ?? {});
@@ -1618,21 +1660,26 @@ function renderWhere(where, args, results) {
1618
1660
  });
1619
1661
  return ` WHERE ${terms.join(" AND ")}`;
1620
1662
  }
1621
- function bindMaybeVector(args, column, vectorCols, value) {
1663
+ function bindMaybeVector(args, column, vectorCols, value, transforms) {
1622
1664
  if (column !== void 0 && vectorCols?.has(column) && Array.isArray(value)) {
1623
1665
  return args.bind(toVectorLiteral(value));
1624
1666
  }
1667
+ const t = column !== void 0 ? transforms?.get(column) : void 0;
1668
+ if (t?.toDb !== void 0 && value !== null && value !== void 0) {
1669
+ return args.bind(t.toDb(value));
1670
+ }
1625
1671
  return args.bind(value);
1626
1672
  }
1627
1673
  async function runPlanOp(sp, op, results) {
1628
1674
  const opVectorCols = vectorColumnsOf(currentSchema, op.table);
1675
+ const opTransforms = transformsOf(currentSchema, op.table);
1629
1676
  const args = new Args();
1630
1677
  const table = quoteIdent(op.table);
1631
1678
  let sql;
1632
1679
  switch (op.op) {
1633
1680
  case "insert": {
1634
1681
  const cols = Object.keys(op.values ?? {});
1635
- const rendered = cols.map((c) => renderValue(op.values[c], c, args, results, opVectorCols));
1682
+ const rendered = cols.map((c) => renderValue(op.values[c], c, args, results, opVectorCols, opTransforms));
1636
1683
  sql = cols.length ? `INSERT INTO ${table} (${cols.map(quoteIdent).join(", ")}) VALUES (${rendered.join(", ")}) RETURNING *` : `INSERT INTO ${table} DEFAULT VALUES RETURNING *`;
1637
1684
  break;
1638
1685
  }
@@ -1645,7 +1692,7 @@ async function runPlanOp(sp, op, results) {
1645
1692
  });
1646
1693
  }
1647
1694
  const rendered = cols.map(
1648
- (c) => renderValue(op.values[c], c, args, results, opVectorCols)
1695
+ (c) => renderValue(op.values[c], c, args, results, opVectorCols, opTransforms)
1649
1696
  );
1650
1697
  sql = `INSERT INTO ${table} (${cols.map(quoteIdent).join(", ")}) VALUES (${rendered.join(", ")}) ${onConflictTail(cols, conflict, "update")} RETURNING *`;
1651
1698
  break;
@@ -1655,7 +1702,7 @@ async function runPlanOp(sp, op, results) {
1655
1702
  if (rows.length === 0 || !rows[0]) return [];
1656
1703
  const cols = Object.keys(rows[0]);
1657
1704
  const tuples = rows.map(
1658
- (r) => `(${cols.map((c) => renderValue(r[c], c, args, results, opVectorCols)).join(", ")})`
1705
+ (r) => `(${cols.map((c) => renderValue(r[c], c, args, results, opVectorCols, opTransforms)).join(", ")})`
1659
1706
  );
1660
1707
  const conflictCols = op.onConflict ?? [];
1661
1708
  const tail = op.action !== void 0 && conflictCols.length > 0 ? ` ${onConflictTail(cols, conflictCols, op.action)}` : "";
@@ -1666,7 +1713,7 @@ async function runPlanOp(sp, op, results) {
1666
1713
  const cols = Object.keys(op.set ?? {});
1667
1714
  if (cols.length === 0) throw new Error(`update ${op.table}: nothing to set`);
1668
1715
  const assignments = cols.map(
1669
- (c) => `${quoteIdent(c)} = ${renderValue(op.set[c], c, args, results, opVectorCols)}`
1716
+ (c) => `${quoteIdent(c)} = ${renderValue(op.set[c], c, args, results, opVectorCols, opTransforms)}`
1670
1717
  );
1671
1718
  sql = `UPDATE ${table} SET ${assignments.join(", ")}${renderWhere(op.where, args, results)} RETURNING *`;
1672
1719
  break;
@@ -1961,6 +2008,7 @@ async function defaultSqlDriver(config) {
1961
2008
  }
1962
2009
  return new g.Bun.SQL({ url: config.databaseUrl, max: config.poolMax });
1963
2010
  }
2011
+ var AUTHOR_ANSWERED = /* @__PURE__ */ new Set([400, 401, 403, 404, 409, 429]);
1964
2012
  async function createApp(opts) {
1965
2013
  const { config, controllers } = opts;
1966
2014
  setSchema(opts.schema ?? {});
@@ -2346,6 +2394,9 @@ async function createApp(opts) {
2346
2394
  } catch (err) {
2347
2395
  await db.rollback(err);
2348
2396
  if (isHttpError(err)) {
2397
+ if (isEngineRaised(err) || !AUTHOR_ANSWERED.has(err.status)) {
2398
+ log.error(`[engine] unhandled ${err.error} in ${hit.entry.id}`, err);
2399
+ }
2349
2400
  return envelope(
2350
2401
  err.error,
2351
2402
  err.errorDescription,
@@ -2401,4 +2452,4 @@ export {
2401
2452
  installEgressFence,
2402
2453
  createApp
2403
2454
  };
2404
- //# sourceMappingURL=chunk-YSQBC2VL.js.map
2455
+ //# sourceMappingURL=chunk-HPUSV4AZ.js.map