turbine-orm 0.28.3 → 0.30.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 (47) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/cli/index.js +5 -0
  3. package/dist/cjs/cli/mcp.js +22 -92
  4. package/dist/cjs/client.js +69 -5
  5. package/dist/cjs/generate.js +71 -25
  6. package/dist/cjs/index.js +4 -1
  7. package/dist/cjs/introspect.js +350 -120
  8. package/dist/cjs/mssql.js +18 -133
  9. package/dist/cjs/mysql.js +16 -129
  10. package/dist/cjs/optional-peer-import.cjs +122 -0
  11. package/dist/cjs/powdb.js +440 -81
  12. package/dist/cjs/powql.js +49 -25
  13. package/dist/cjs/query/builder.js +290 -23
  14. package/dist/cjs/query/filters.js +32 -1
  15. package/dist/cjs/schema-metadata.js +316 -0
  16. package/dist/cjs/sqlite.js +8 -89
  17. package/dist/cli/index.d.ts +2 -0
  18. package/dist/cli/index.js +5 -0
  19. package/dist/cli/mcp.d.ts +18 -0
  20. package/dist/cli/mcp.js +22 -93
  21. package/dist/client.d.ts +44 -6
  22. package/dist/client.js +69 -5
  23. package/dist/generate.d.ts +16 -4
  24. package/dist/generate.js +71 -25
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +2 -0
  27. package/dist/introspect.d.ts +94 -1
  28. package/dist/introspect.js +345 -120
  29. package/dist/mssql.js +16 -101
  30. package/dist/mysql.js +14 -97
  31. package/dist/optional-peer-import.cjs +89 -0
  32. package/dist/optional-peer-import.d.cts +53 -0
  33. package/dist/powdb.d.ts +94 -26
  34. package/dist/powdb.js +435 -80
  35. package/dist/powql.d.ts +6 -0
  36. package/dist/powql.js +51 -27
  37. package/dist/query/builder.d.ts +60 -3
  38. package/dist/query/builder.js +291 -24
  39. package/dist/query/deferred.d.ts +7 -2
  40. package/dist/query/filters.d.ts +18 -0
  41. package/dist/query/filters.js +30 -0
  42. package/dist/query/types.d.ts +19 -0
  43. package/dist/schema-metadata.d.ts +77 -0
  44. package/dist/schema-metadata.js +313 -0
  45. package/dist/schema.d.ts +10 -0
  46. package/dist/sqlite.js +9 -90
  47. package/package.json +3 -3
package/dist/cjs/powql.js CHANGED
@@ -142,7 +142,14 @@ class PowqlInterface {
142
142
  }
143
143
  this.meta = meta;
144
144
  this.defaultLimit = options.defaultLimit;
145
- this.warnOnUnlimited = options.warnOnUnlimited !== false;
145
+ // Same per-table resolution as QueryInterface: an object map accepts BOTH
146
+ // the snake_case table name and the camelCase accessor as keys (snake_case
147
+ // wins on conflict); unlisted tables keep the default (warn on).
148
+ const warnOpt = options.warnOnUnlimited;
149
+ this.warnOnUnlimited =
150
+ typeof warnOpt === 'object' && warnOpt !== null
151
+ ? (warnOpt[table] ?? warnOpt[(0, schema_js_1.snakeToCamel)(table)]) !== false
152
+ : warnOpt !== false;
146
153
  this.onQuery = options._onQuery;
147
154
  }
148
155
  // -------------------------------------------------------------------------
@@ -447,7 +454,7 @@ class PowqlInterface {
447
454
  const chunk = targetPks.slice(i, i + MAX_RELATION_KEYS);
448
455
  const params = [];
449
456
  const ph = chunk.map((v) => this.param(v, params)).join(', ');
450
- const { rows } = await this.exec(`${through.table} filter .${targetJCol} in (${ph}) { .${sourceJCol} }`, params, timeout);
457
+ const { rows } = await this.exec(`${(0, powdb_js_1.quotePowqlIdent)(through.table)} filter .${targetJCol} in (${ph}) { .${sourceJCol} }`, params, timeout);
451
458
  for (const r of rows) {
452
459
  const v = r[sourceJCol];
453
460
  if (v != null)
@@ -599,7 +606,7 @@ class PowqlInterface {
599
606
  }
600
607
  const limitClause = limit !== undefined ? ` limit ${this.param(limit, params)}` : '';
601
608
  const offsetClause = args.offset ? ` offset ${this.param(args.offset, params)}` : '';
602
- const powql = `${this.table}${distinct}${filter}${order}${limitClause}${offsetClause} ${this.projection(cols)}`;
609
+ const powql = `${this.qt}${distinct}${filter}${order}${limitClause}${offsetClause} ${this.projection(cols)}`;
603
610
  const { rows } = await this.exec(powql, params, args.timeout);
604
611
  return rows;
605
612
  }
@@ -748,7 +755,7 @@ class PowqlInterface {
748
755
  const chunk = parentKeys.slice(i, i + MAX_RELATION_KEYS);
749
756
  const params = [];
750
757
  const placeholders = chunk.map((v) => this.param(v, params)).join(', ');
751
- const powql = `${through.table} filter .${sourceJCol} in (${placeholders}) { .${sourceJCol}, .${targetJCol} }`;
758
+ const powql = `${(0, powdb_js_1.quotePowqlIdent)(through.table)} filter .${sourceJCol} in (${placeholders}) { .${sourceJCol}, .${targetJCol} }`;
752
759
  const { rows } = await this.exec(powql, params, timeout);
753
760
  for (const row of rows) {
754
761
  const sv = String(row[sourceJCol]);
@@ -830,6 +837,14 @@ class PowqlInterface {
830
837
  }
831
838
  return out;
832
839
  }
840
+ /**
841
+ * The table name as a PowQL type reference — backtick-quoted when it is a
842
+ * reserved word (e.g. a table named `order`). Used in every emitted
843
+ * statement; plain `this.table` stays in error messages.
844
+ */
845
+ get qt() {
846
+ return (0, powdb_js_1.quotePowqlIdent)(this.table);
847
+ }
833
848
  async create(args) {
834
849
  return this.withMiddleware('create', args, async () => {
835
850
  if ((0, nested_write_js_1.hasRelationFields)(args.data, this.meta)) {
@@ -838,9 +853,11 @@ class PowqlInterface {
838
853
  const data = this.applyPkDefault(args.data);
839
854
  const assigns = this.scalarData(data);
840
855
  const params = [];
841
- const body = assigns.map((a) => `${a.col.name} := ${this.writeRef(a.value, a.col, params)}`).join(', ');
856
+ const body = assigns
857
+ .map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
858
+ .join(', ');
842
859
  // `returning` surfaces the inserted row (all columns, schema order) in one round-trip.
843
- const { rows } = await this.exec(`insert ${this.table} { ${body} } returning`, params, args.timeout);
860
+ const { rows } = await this.exec(`insert ${this.qt} { ${body} } returning`, params, args.timeout);
844
861
  const row = rows.length ? this.shape(rows)[0] : null;
845
862
  if (!row)
846
863
  throw new errors_js_1.NotFoundError({ table: this.table, where: data });
@@ -855,10 +872,10 @@ class PowqlInterface {
855
872
  const params = [];
856
873
  const tuples = inputs.map((d) => {
857
874
  const assigns = this.scalarData(d);
858
- return `{ ${assigns.map((a) => `${a.col.name} := ${this.writeRef(a.value, a.col, params)}`).join(', ')} }`;
875
+ return `{ ${assigns.map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`).join(', ')} }`;
859
876
  });
860
877
  // Multi-row insert with `returning` hands back every inserted row in one round-trip.
861
- const { rows } = await this.exec(`insert ${this.table} ${tuples.join(', ')} returning`, params, args.timeout);
878
+ const { rows } = await this.exec(`insert ${this.qt} ${tuples.join(', ')} returning`, params, args.timeout);
862
879
  return this.shape(rows);
863
880
  });
864
881
  }
@@ -873,7 +890,7 @@ class PowqlInterface {
873
890
  this.assertCompiledWhere(where, false, 'update');
874
891
  const setClause = this.buildUpdateAssignments(args.data, params);
875
892
  // `returning` hands back the post-update row(s); take the first (single-row contract).
876
- const { rows } = await this.exec(`${this.table} filter ${where} update { ${setClause} } returning`, params, args.timeout);
893
+ const { rows } = await this.exec(`${this.qt} filter ${where} update { ${setClause} } returning`, params, args.timeout);
877
894
  const row = rows.length ? this.shape(rows)[0] : null;
878
895
  if (!row)
879
896
  throw new errors_js_1.NotFoundError({ table: this.table, where: args.where });
@@ -888,7 +905,7 @@ class PowqlInterface {
888
905
  this.assertCompiledWhere(where, args.allowFullTableScan, 'updateMany');
889
906
  const setClause = this.buildUpdateAssignments(args.data, params);
890
907
  const filter = where ? ` filter ${where}` : '';
891
- const { rowCount } = await this.exec(`${this.table}${filter} update { ${setClause} }`, params, args.timeout);
908
+ const { rowCount } = await this.exec(`${this.qt}${filter} update { ${setClause} }`, params, args.timeout);
892
909
  return { count: rowCount };
893
910
  });
894
911
  }
@@ -903,7 +920,7 @@ class PowqlInterface {
903
920
  }
904
921
  const colMeta = this.column(field);
905
922
  const ref = this.ref(field);
906
- const col = colMeta.name;
923
+ const col = (0, powdb_js_1.quotePowqlIdent)(colMeta.name);
907
924
  if (value !== null && typeof value === 'object' && !(value instanceof Date)) {
908
925
  const opObj = value;
909
926
  if ('set' in opObj)
@@ -961,8 +978,10 @@ class PowqlInterface {
961
978
  // drifts from `powdbDialect`; falls back to the literal lowercase keywords.
962
979
  const d = this.options.dialect;
963
980
  const client = await this.pool.connect();
981
+ let began = false;
964
982
  try {
965
983
  await client.query(d?.beginStatement?.() ?? 'begin');
984
+ began = true;
966
985
  const { TransactionClient } = await Promise.resolve().then(() => __importStar(require('./client.js')));
967
986
  const tx = new TransactionClient(client, this.schema, this.middlewares, this.options);
968
987
  const ctx = { schema: this.schema, tx: tx };
@@ -971,11 +990,16 @@ class PowqlInterface {
971
990
  return result;
972
991
  }
973
992
  catch (err) {
974
- try {
975
- await client.query(d?.rollbackStatement?.() ?? 'rollback');
976
- }
977
- catch {
978
- /* best-effort — the connection may be gone */
993
+ // Only roll back a transaction we actually opened — a failed BEGIN
994
+ // (queue timeout, re-entrancy E017) must not emit a stray ROLLBACK that
995
+ // could land inside another transaction on a shared engine handle.
996
+ if (began) {
997
+ try {
998
+ await client.query(d?.rollbackStatement?.() ?? 'rollback');
999
+ }
1000
+ catch {
1001
+ /* best-effort — the connection may be gone */
1002
+ }
979
1003
  }
980
1004
  throw err;
981
1005
  }
@@ -998,7 +1022,7 @@ class PowqlInterface {
998
1022
  const where = this.buildWhere(resolvedWhere, params);
999
1023
  this.assertCompiledWhere(where, false, 'delete');
1000
1024
  // `returning` hands back the deleted row(s) — no separate pre-image reselect needed.
1001
- const { rows } = await this.exec(`${this.table} filter ${where} delete returning`, params, args.timeout);
1025
+ const { rows } = await this.exec(`${this.qt} filter ${where} delete returning`, params, args.timeout);
1002
1026
  const row = rows.length ? this.shape(rows)[0] : null;
1003
1027
  if (!row)
1004
1028
  throw new errors_js_1.NotFoundError({ table: this.table, where: args.where });
@@ -1012,7 +1036,7 @@ class PowqlInterface {
1012
1036
  const where = this.buildWhere(resolvedWhere, params);
1013
1037
  this.assertCompiledWhere(where, args.allowFullTableScan, 'deleteMany');
1014
1038
  const filter = where ? ` filter ${where}` : '';
1015
- const { rowCount } = await this.exec(`${this.table}${filter} delete`, params, args.timeout);
1039
+ const { rowCount } = await this.exec(`${this.qt}${filter} delete`, params, args.timeout);
1016
1040
  return { count: rowCount };
1017
1041
  });
1018
1042
  }
@@ -1027,14 +1051,14 @@ class PowqlInterface {
1027
1051
  }
1028
1052
  const params = [];
1029
1053
  const createBody = this.scalarData(createData)
1030
- .map((a) => `${a.col.name} := ${this.writeRef(a.value, a.col, params)}`)
1054
+ .map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
1031
1055
  .join(', ');
1032
1056
  const updateBody = this.buildUpdateAssignments(args.update, params);
1033
1057
  // PowDB 0.7.0's `upsert` statement does NOT accept a trailing `returning`
1034
1058
  // (verified: "unexpected trailing token … 'returning'"), because it is one
1035
1059
  // atomic insert-or-update, not two branches. So upsert alone keeps the
1036
1060
  // reselect-by-PK fetch; create/update/delete all use `returning`.
1037
- await this.exec(`upsert ${this.table} on .${pkCol} { ${createBody} } on conflict { ${updateBody} }`, params, args.timeout);
1061
+ await this.exec(`upsert ${this.qt} on .${pkCol} { ${createBody} } on conflict { ${updateBody} }`, params, args.timeout);
1038
1062
  const pkField = this.meta.reverseColumnMap[pkCol] ?? pkCol;
1039
1063
  const row = await this.reselectByPk(createData[pkField], args.timeout);
1040
1064
  if (!row)
@@ -1079,7 +1103,7 @@ class PowqlInterface {
1079
1103
  const resolvedWhere = await this.resolveRelationFilters(args.where, args.timeout);
1080
1104
  const where = this.buildWhere(resolvedWhere, params);
1081
1105
  const filter = where ? ` filter ${where}` : '';
1082
- const { rows } = await this.exec(`count(${this.table}${filter})`, params, args.timeout);
1106
+ const { rows } = await this.exec(`count(${this.qt}${filter})`, params, args.timeout);
1083
1107
  return Number((rows[0]?.value ?? rows[0]?.count ?? 0));
1084
1108
  });
1085
1109
  }
@@ -1099,12 +1123,12 @@ class PowqlInterface {
1099
1123
  };
1100
1124
  if (args._count) {
1101
1125
  if (args._count === true) {
1102
- result._count = (await scalar(`count(${this.table}${filter})`)) ?? 0;
1126
+ result._count = (await scalar(`count(${this.qt}${filter})`)) ?? 0;
1103
1127
  }
1104
1128
  else {
1105
1129
  const counts = {};
1106
1130
  for (const field of Object.keys(args._count).filter((f) => args._count[f])) {
1107
- counts[field] = (await scalar(`count(${this.table}${filter} { ${this.ref(field)} })`)) ?? 0;
1131
+ counts[field] = (await scalar(`count(${this.qt}${filter} { ${this.ref(field)} })`)) ?? 0;
1108
1132
  }
1109
1133
  result._count = counts;
1110
1134
  }
@@ -1116,7 +1140,7 @@ class PowqlInterface {
1116
1140
  const acc = {};
1117
1141
  for (const field of Object.keys(spec).filter((f) => spec[f])) {
1118
1142
  const powfn = fn.slice(1); // sum/avg/min/max
1119
- acc[field] = await scalar(`${powfn}(${this.table}${filter} { ${this.ref(field)} })`);
1143
+ acc[field] = await scalar(`${powfn}(${this.qt}${filter} { ${this.ref(field)} })`);
1120
1144
  }
1121
1145
  result[fn] = acc;
1122
1146
  }
@@ -1150,7 +1174,7 @@ class PowqlInterface {
1150
1174
  }
1151
1175
  const having = this.buildHaving(args.having, params);
1152
1176
  const order = this.buildOrder(args.orderBy);
1153
- const powql = `${this.table}${filter} group ${groupKeys.join(', ')}${having}${order} { ${proj.join(', ')} }`;
1177
+ const powql = `${this.qt}${filter} group ${groupKeys.join(', ')}${having}${order} { ${proj.join(', ')} }`;
1154
1178
  const { rows } = await this.exec(powql, params, args.timeout);
1155
1179
  // Reshape: group keys → camel fields + coerced; aggregates → nested {_sum:{field}}.
1156
1180
  return rows.map((raw) => {