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.
- package/README.md +1 -1
- package/dist/cjs/cli/index.js +5 -0
- package/dist/cjs/cli/mcp.js +22 -92
- package/dist/cjs/client.js +69 -5
- package/dist/cjs/generate.js +71 -25
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/introspect.js +350 -120
- package/dist/cjs/mssql.js +18 -133
- package/dist/cjs/mysql.js +16 -129
- package/dist/cjs/optional-peer-import.cjs +122 -0
- package/dist/cjs/powdb.js +440 -81
- package/dist/cjs/powql.js +49 -25
- package/dist/cjs/query/builder.js +290 -23
- package/dist/cjs/query/filters.js +32 -1
- package/dist/cjs/schema-metadata.js +316 -0
- package/dist/cjs/sqlite.js +8 -89
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +5 -0
- package/dist/cli/mcp.d.ts +18 -0
- package/dist/cli/mcp.js +22 -93
- package/dist/client.d.ts +44 -6
- package/dist/client.js +69 -5
- package/dist/generate.d.ts +16 -4
- package/dist/generate.js +71 -25
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/introspect.d.ts +94 -1
- package/dist/introspect.js +345 -120
- package/dist/mssql.js +16 -101
- package/dist/mysql.js +14 -97
- package/dist/optional-peer-import.cjs +89 -0
- package/dist/optional-peer-import.d.cts +53 -0
- package/dist/powdb.d.ts +94 -26
- package/dist/powdb.js +435 -80
- package/dist/powql.d.ts +6 -0
- package/dist/powql.js +51 -27
- package/dist/query/builder.d.ts +60 -3
- package/dist/query/builder.js +291 -24
- package/dist/query/deferred.d.ts +7 -2
- package/dist/query/filters.d.ts +18 -0
- package/dist/query/filters.js +30 -0
- package/dist/query/types.d.ts +19 -0
- package/dist/schema-metadata.d.ts +77 -0
- package/dist/schema-metadata.js +313 -0
- package/dist/schema.d.ts +10 -0
- package/dist/sqlite.js +9 -90
- 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
|
-
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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) => {
|