@palbase/backend 27.1.0 → 29.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.
Files changed (52) hide show
  1. package/dist/bin/palbase-backend.cjs +284 -50
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +4 -4
  4. package/dist/{chunk-JVZQCC77.js → chunk-3TUJWHC2.js} +8 -3
  5. package/dist/chunk-3TUJWHC2.js.map +1 -0
  6. package/dist/{chunk-EB3TUX5J.js → chunk-DHJ3SYAE.js} +251 -50
  7. package/dist/chunk-DHJ3SYAE.js.map +1 -0
  8. package/dist/{chunk-XABHGMUT.js → chunk-ENZ2RFFJ.js} +2 -2
  9. package/dist/{chunk-BQN723PL.js → chunk-ESSQ3YML.js} +73 -7
  10. package/dist/chunk-ESSQ3YML.js.map +1 -0
  11. package/dist/{chunk-OZKSM3JW.js → chunk-SG4UTNOP.js} +7 -3
  12. package/dist/chunk-SG4UTNOP.js.map +1 -0
  13. package/dist/db/index.cjs +8 -2
  14. package/dist/db/index.cjs.map +1 -1
  15. package/dist/db/index.d.cts +1 -1
  16. package/dist/db/index.d.ts +1 -1
  17. package/dist/db/index.js +3 -3
  18. package/dist/engine/index.cjs +294 -50
  19. package/dist/engine/index.cjs.map +1 -1
  20. package/dist/engine/index.d.cts +3 -3
  21. package/dist/engine/index.d.ts +3 -3
  22. package/dist/engine/index.js +11 -4
  23. package/dist/{index-V7QRh1wg.d.ts → index-BOe82fsK.d.ts} +256 -19
  24. package/dist/{index-CAKOgAlP.d.ts → index-BYDUKexK.d.ts} +139 -10
  25. package/dist/{index-H-0qv5d4.d.cts → index-BZfmdRmh.d.cts} +139 -10
  26. package/dist/{index-CgE4sVhg.d.cts → index-ChvoVczS.d.cts} +256 -19
  27. package/dist/index.cjs +81 -6
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +6 -22
  30. package/dist/index.d.ts +6 -22
  31. package/dist/index.js +10 -4
  32. package/dist/index.js.map +1 -1
  33. package/dist/openapi/index.d.cts +2 -2
  34. package/dist/openapi/index.d.ts +2 -2
  35. package/dist/{registry-DHsPDY0_.d.cts → registry-B2KfKWv1.d.cts} +1 -1
  36. package/dist/{registry-4EI8aaFs.d.ts → registry-DaqHsOq8.d.ts} +1 -1
  37. package/dist/test/index.cjs +129 -6
  38. package/dist/test/index.cjs.map +1 -1
  39. package/dist/test/index.d.cts +1 -1
  40. package/dist/test/index.d.ts +1 -1
  41. package/dist/test/index.js +126 -6
  42. package/dist/test/index.js.map +1 -1
  43. package/docs/README.md +1 -1
  44. package/docs/database.md +118 -1
  45. package/docs/llms-full.txt +119 -2
  46. package/package.json +1 -1
  47. package/template/package.json +1 -1
  48. package/dist/chunk-BQN723PL.js.map +0 -1
  49. package/dist/chunk-EB3TUX5J.js.map +0 -1
  50. package/dist/chunk-JVZQCC77.js.map +0 -1
  51. package/dist/chunk-OZKSM3JW.js.map +0 -1
  52. /package/dist/{chunk-XABHGMUT.js.map → chunk-ENZ2RFFJ.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi';
2
2
  import { ZodTypeAny } from 'zod';
3
- import { A as AuthSpec, R as RateLimitConfig } from '../index-CgE4sVhg.cjs';
4
- import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-DHsPDY0_.cjs';
3
+ import { A as AuthSpec, R as RateLimitConfig } from '../index-ChvoVczS.cjs';
4
+ import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-B2KfKWv1.cjs';
5
5
  import '../db/env.cjs';
6
6
  import '../stack.cjs';
7
7
  import 'node:async_hooks';
@@ -1,7 +1,7 @@
1
1
  import { OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi';
2
2
  import { ZodTypeAny } from 'zod';
3
- import { A as AuthSpec, R as RateLimitConfig } from '../index-V7QRh1wg.js';
4
- import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-4EI8aaFs.js';
3
+ import { A as AuthSpec, R as RateLimitConfig } from '../index-BOe82fsK.js';
4
+ import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-DaqHsOq8.js';
5
5
  import '../db/env.js';
6
6
  import '../stack.js';
7
7
  import 'node:async_hooks';
@@ -1,4 +1,4 @@
1
- import { A as AuthSpec, R as RateLimitConfig } from './index-CgE4sVhg.cjs';
1
+ import { A as AuthSpec, R as RateLimitConfig } from './index-ChvoVczS.cjs';
2
2
  import { ZodTypeAny } from 'zod';
3
3
  import { PalbaseBucketName } from './stack.cjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { A as AuthSpec, R as RateLimitConfig } from './index-V7QRh1wg.js';
1
+ import { A as AuthSpec, R as RateLimitConfig } from './index-BOe82fsK.js';
2
2
  import { ZodTypeAny } from 'zod';
3
3
  import { PalbaseBucketName } from './stack.js';
4
4
 
@@ -389,8 +389,11 @@ __name(isColumnExpr, "isColumnExpr");
389
389
  function assertNoExpressionHandles(caller, table, cols, data) {
390
390
  for (const c of cols) {
391
391
  const v = data[c];
392
+ if (isNowExpr(v)) {
393
+ 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() }).`);
394
+ }
392
395
  if (isColumnExpr(v)) {
393
- throw new Error(`${caller}(${table}): "${c}" bir ifade tutama\u011F\u0131 ald\u0131 (increment()/decrement()/now()). Bu yolda de\u011Fer beklenir. Saya\xE7 art\u0131\u015F\u0131 i\xE7in updateMany(where, { ${c}: increment(n) }) ya da $transaction i\xE7inde tx.tables.${table}.updateWhere(where, { ${c}: increment(n) }) kullan\u0131n.`);
396
+ 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.`);
394
397
  }
395
398
  if (isColRef(v)) {
396
399
  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.`);
@@ -804,6 +807,22 @@ function createMockDB() {
804
807
  ]);
805
808
  }
806
809
  __name(track, "track");
810
+ function resolveInsertValues(caller, table, data) {
811
+ const out = {};
812
+ for (const [k, v] of Object.entries(data)) {
813
+ const expr = columnExprOf(v);
814
+ if (expr !== null && expr.fn === "now") {
815
+ out[k] = (/* @__PURE__ */ new Date()).toISOString();
816
+ continue;
817
+ }
818
+ if (expr !== null) {
819
+ throw new Error(`${caller}(${table}): "${k}" ${expr.fn === "inc" ? "increment()" : "decrement()"} ald\u0131 \u2014 sat\u0131r HEN\xDCZ YOK, yani "kolonun \u015Fu anki de\u011Feri" diye bir \u015Fey yok.`);
820
+ }
821
+ out[k] = v;
822
+ }
823
+ return out;
824
+ }
825
+ __name(resolveInsertValues, "resolveInsertValues");
807
826
  const ops = {
808
827
  // The bulk ops and count run against the SAME in-memory store the direct
809
828
  // ops write to, so a test that writes three rows and counts them gets 3 —
@@ -866,7 +885,8 @@ function createMockDB() {
866
885
  async query(_sql, _params) {
867
886
  return [];
868
887
  },
869
- async insert(table, data) {
888
+ async insert(table, raw) {
889
+ const data = resolveInsertValues("insert", table, raw);
870
890
  assertUsableWriteValues("insert", table, Object.keys(data), data);
871
891
  assertNoExpressionHandles("insert", table, Object.keys(data), data);
872
892
  const record = {
@@ -878,6 +898,94 @@ function createMockDB() {
878
898
  return record;
879
899
  },
880
900
  /**
901
+ * `insertMany` — motorla PARİTE, ANAHTAR KÜMESİ kuralı dahil.
902
+ *
903
+ * Fake bu kuralı bilmeseydi farklı şekilli satırları kabul eder, test yeşil
904
+ * kalır, üretimde motor adıyla reddederdi — yani fake, sürüm atlamayı
905
+ * kolaylaştırmak yerine gizlerdi.
906
+ */
907
+ /**
908
+ * `aggregate` — motorla PARİTE, PARA KESİNLİĞİ dahil.
909
+ *
910
+ * Fake toplamayı JS `number` ile yapsaydı test yeşil kalır ve üretimde
911
+ * `numeric` kesinliği kaybolurdu — yani fake tam da korunması gereken şeyi
912
+ * gizlerdi. `addDecimal` BigInt ölçekli toplama yapıyor, motorun
913
+ * `sum(numeric)::text`'inin karşılığı.
914
+ */
915
+ async aggregate(table, q) {
916
+ const rows = (store.get(table) ?? []).filter((r) => q.where === void 0 || rowMatchesFilter("aggregate", table, r, q.where));
917
+ const groups = q.groupBy ?? [];
918
+ const shape = /* @__PURE__ */ __name((bucket) => {
919
+ const out = {};
920
+ for (const c of q.sum ?? []) {
921
+ const vals = bucket.map((r) => r[c]).filter((v) => v !== null && v !== void 0);
922
+ (out["sum"] ??= {})[c] = vals.length === 0 ? null : String(vals.reduce((a, v) => addDecimal(a, v, 1), "0"));
923
+ }
924
+ for (const c of q.avg ?? []) {
925
+ const vals = bucket.map((r) => r[c]).filter((v) => v !== null && v !== void 0);
926
+ (out["avg"] ??= {})[c] = vals.length === 0 ? null : String(Number(vals.reduce((a, v) => addDecimal(a, v, 1), "0")) / vals.length);
927
+ }
928
+ for (const [fn, pick] of [
929
+ [
930
+ "min",
931
+ -1
932
+ ],
933
+ [
934
+ "max",
935
+ 1
936
+ ]
937
+ ]) {
938
+ for (const c of q[fn] ?? []) {
939
+ const vals = bucket.map((r) => r[c]).filter((v) => v !== null && v !== void 0);
940
+ (out[fn] ??= {})[c] = vals.length === 0 ? null : vals.reduce((a, v) => cmp(v, a, pick === 1 ? "gt" : "lt") ? v : a);
941
+ }
942
+ }
943
+ if (q.count === true) out["count"] = bucket.length;
944
+ return out;
945
+ }, "shape");
946
+ if (groups.length === 0) return shape(rows);
947
+ const byKey = /* @__PURE__ */ new Map();
948
+ for (const r of rows) {
949
+ const k = JSON.stringify(groups.map((c) => r[c]));
950
+ byKey.set(k, [
951
+ ...byKey.get(k) ?? [],
952
+ r
953
+ ]);
954
+ }
955
+ return [
956
+ ...byKey.values()
957
+ ].map((bucket) => {
958
+ const out = shape(bucket);
959
+ for (const c of groups) out[c] = bucket[0][c];
960
+ return out;
961
+ });
962
+ },
963
+ async insertMany(table, rows) {
964
+ if (rows.length === 0) return [];
965
+ const cols = Object.keys(rows[0]);
966
+ for (let i = 1; i < rows.length; i++) {
967
+ const missing = cols.filter((c) => !(c in rows[i]));
968
+ const extra = Object.keys(rows[i]).filter((k) => !cols.includes(k));
969
+ if (missing.length > 0 || extra.length > 0) {
970
+ 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(", ")})` : "") + `. Eksikler i\xE7in null yaz\u0131n, ya da farkl\u0131 \u015Fekilli sat\u0131rlar\u0131 ayr\u0131 \xE7a\u011Fr\u0131larda ekleyin.`);
971
+ }
972
+ }
973
+ const out = [];
974
+ for (const rawRow of rows) {
975
+ const data = resolveInsertValues("insertMany", table, rawRow);
976
+ assertUsableWriteValues("insertMany", table, cols, data);
977
+ assertNoExpressionHandles("insertMany", table, cols, data);
978
+ const record = {
979
+ id: crypto.randomUUID(),
980
+ ...data
981
+ };
982
+ rowsOf(table).push(record);
983
+ track(tracked.inserted, table, record);
984
+ out.push(record);
985
+ }
986
+ return out;
987
+ },
988
+ /**
881
989
  * `claim` — motorla PARİTE (FR-033).
882
990
  *
883
991
  * Fake bunu sunmasaydı `claim` ile yazılmış bir servis, iskelenin yazarlara
@@ -936,10 +1044,11 @@ function createMockDB() {
936
1044
  },
937
1045
  // Same semantics the engine's SQL has: match on the conflict columns, update
938
1046
  // everything else, and return the resulting row either way.
939
- async put(table, data, opts) {
1047
+ async put(table, rawData, opts) {
940
1048
  if (opts.onConflict.length === 0) {
941
1049
  throw new Error(`put into ${table}: onConflict en az bir kolon ad\u0131 ister`);
942
1050
  }
1051
+ const data = resolveInsertValues("put", table, rawData);
943
1052
  assertUsableWriteValues("upsert", table, Object.keys(data), data);
944
1053
  assertNoExpressionHandles("upsert", table, Object.keys(data), data);
945
1054
  const rows = rowsOf(table);
@@ -960,15 +1069,29 @@ function createMockDB() {
960
1069
  },
961
1070
  async update(table, id, data) {
962
1071
  assertUsableWriteValues("update", table, Object.keys(data), data);
963
- assertNoExpressionHandles("update", table, Object.keys(data), data);
964
1072
  const rows = store.get(table) ?? [];
965
1073
  const idx = rows.findIndex((r) => r["id"] === id);
1074
+ const current = idx >= 0 ? rows[idx] : {};
1075
+ const applied = {};
1076
+ for (const [k, v] of Object.entries(data)) {
1077
+ const expr = columnExprOf(v);
1078
+ if (expr !== null && expr.fn === "now") {
1079
+ applied[k] = /* @__PURE__ */ new Date();
1080
+ continue;
1081
+ }
1082
+ if (expr !== null) {
1083
+ applied[k] = addDecimal(current[k], expr.by, expr.fn === "inc" ? 1 : -1);
1084
+ continue;
1085
+ }
1086
+ applied[k] = v;
1087
+ }
1088
+ assertNoExpressionHandles("update", table, Object.keys(applied), applied);
966
1089
  const updated = idx >= 0 ? {
967
1090
  ...rows[idx],
968
- ...data
1091
+ ...applied
969
1092
  } : {
970
1093
  id,
971
- ...data
1094
+ ...applied
972
1095
  };
973
1096
  if (idx >= 0) {
974
1097
  rows[idx] = updated;