turbine-orm 0.29.0 → 0.31.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 +47 -6
- 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 +42 -136
- package/dist/cjs/mysql.js +16 -129
- package/dist/cjs/optional-peer-import.cjs +122 -0
- package/dist/cjs/powdb.js +579 -89
- package/dist/cjs/powql.js +56 -26
- package/dist/cjs/query/builder.js +601 -86
- package/dist/cjs/query/filters.js +80 -2
- 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 +19 -2
- package/dist/client.js +47 -6
- package/dist/generate.d.ts +16 -4
- package/dist/generate.js +71 -25
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -0
- package/dist/introspect.d.ts +94 -1
- package/dist/introspect.js +345 -120
- package/dist/mssql.js +40 -104
- 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 +118 -23
- package/dist/powdb.js +574 -88
- package/dist/powql.d.ts +6 -0
- package/dist/powql.js +58 -28
- package/dist/query/builder.d.ts +145 -8
- package/dist/query/builder.js +602 -87
- package/dist/query/deferred.d.ts +7 -2
- package/dist/query/filters.d.ts +46 -1
- package/dist/query/filters.js +76 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/types.d.ts +85 -11
- 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,21 +978,34 @@ 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 };
|
|
969
|
-
|
|
988
|
+
// Plant the single-writer re-entrancy marker for the implicit tx's
|
|
989
|
+
// subtree (same seam TurbineClient.$transaction uses) — user code that
|
|
990
|
+
// fires db.$transaction from inside (e.g. $use middleware around a
|
|
991
|
+
// nested-write child op) must fast-fail E017, not queue into deadlock.
|
|
992
|
+
const wrap = client
|
|
993
|
+
.wrapTransactionCallback;
|
|
994
|
+
const result = await (wrap ? wrap(() => fn(ctx)) : fn(ctx));
|
|
970
995
|
await client.query(d?.commitStatement?.() ?? 'commit');
|
|
971
996
|
return result;
|
|
972
997
|
}
|
|
973
998
|
catch (err) {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
999
|
+
// Only roll back a transaction we actually opened — a failed BEGIN
|
|
1000
|
+
// (queue timeout, re-entrancy E017) must not emit a stray ROLLBACK that
|
|
1001
|
+
// could land inside another transaction on a shared engine handle.
|
|
1002
|
+
if (began) {
|
|
1003
|
+
try {
|
|
1004
|
+
await client.query(d?.rollbackStatement?.() ?? 'rollback');
|
|
1005
|
+
}
|
|
1006
|
+
catch {
|
|
1007
|
+
/* best-effort — the connection may be gone */
|
|
1008
|
+
}
|
|
979
1009
|
}
|
|
980
1010
|
throw err;
|
|
981
1011
|
}
|
|
@@ -998,7 +1028,7 @@ class PowqlInterface {
|
|
|
998
1028
|
const where = this.buildWhere(resolvedWhere, params);
|
|
999
1029
|
this.assertCompiledWhere(where, false, 'delete');
|
|
1000
1030
|
// `returning` hands back the deleted row(s) — no separate pre-image reselect needed.
|
|
1001
|
-
const { rows } = await this.exec(`${this.
|
|
1031
|
+
const { rows } = await this.exec(`${this.qt} filter ${where} delete returning`, params, args.timeout);
|
|
1002
1032
|
const row = rows.length ? this.shape(rows)[0] : null;
|
|
1003
1033
|
if (!row)
|
|
1004
1034
|
throw new errors_js_1.NotFoundError({ table: this.table, where: args.where });
|
|
@@ -1012,7 +1042,7 @@ class PowqlInterface {
|
|
|
1012
1042
|
const where = this.buildWhere(resolvedWhere, params);
|
|
1013
1043
|
this.assertCompiledWhere(where, args.allowFullTableScan, 'deleteMany');
|
|
1014
1044
|
const filter = where ? ` filter ${where}` : '';
|
|
1015
|
-
const { rowCount } = await this.exec(`${this.
|
|
1045
|
+
const { rowCount } = await this.exec(`${this.qt}${filter} delete`, params, args.timeout);
|
|
1016
1046
|
return { count: rowCount };
|
|
1017
1047
|
});
|
|
1018
1048
|
}
|
|
@@ -1027,14 +1057,14 @@ class PowqlInterface {
|
|
|
1027
1057
|
}
|
|
1028
1058
|
const params = [];
|
|
1029
1059
|
const createBody = this.scalarData(createData)
|
|
1030
|
-
.map((a) => `${a.col.name} := ${this.writeRef(a.value, a.col, params)}`)
|
|
1060
|
+
.map((a) => `${(0, powdb_js_1.quotePowqlIdent)(a.col.name)} := ${this.writeRef(a.value, a.col, params)}`)
|
|
1031
1061
|
.join(', ');
|
|
1032
1062
|
const updateBody = this.buildUpdateAssignments(args.update, params);
|
|
1033
1063
|
// PowDB 0.7.0's `upsert` statement does NOT accept a trailing `returning`
|
|
1034
1064
|
// (verified: "unexpected trailing token … 'returning'"), because it is one
|
|
1035
1065
|
// atomic insert-or-update, not two branches. So upsert alone keeps the
|
|
1036
1066
|
// reselect-by-PK fetch; create/update/delete all use `returning`.
|
|
1037
|
-
await this.exec(`upsert ${this.
|
|
1067
|
+
await this.exec(`upsert ${this.qt} on .${pkCol} { ${createBody} } on conflict { ${updateBody} }`, params, args.timeout);
|
|
1038
1068
|
const pkField = this.meta.reverseColumnMap[pkCol] ?? pkCol;
|
|
1039
1069
|
const row = await this.reselectByPk(createData[pkField], args.timeout);
|
|
1040
1070
|
if (!row)
|
|
@@ -1079,7 +1109,7 @@ class PowqlInterface {
|
|
|
1079
1109
|
const resolvedWhere = await this.resolveRelationFilters(args.where, args.timeout);
|
|
1080
1110
|
const where = this.buildWhere(resolvedWhere, params);
|
|
1081
1111
|
const filter = where ? ` filter ${where}` : '';
|
|
1082
|
-
const { rows } = await this.exec(`count(${this.
|
|
1112
|
+
const { rows } = await this.exec(`count(${this.qt}${filter})`, params, args.timeout);
|
|
1083
1113
|
return Number((rows[0]?.value ?? rows[0]?.count ?? 0));
|
|
1084
1114
|
});
|
|
1085
1115
|
}
|
|
@@ -1099,12 +1129,12 @@ class PowqlInterface {
|
|
|
1099
1129
|
};
|
|
1100
1130
|
if (args._count) {
|
|
1101
1131
|
if (args._count === true) {
|
|
1102
|
-
result._count = (await scalar(`count(${this.
|
|
1132
|
+
result._count = (await scalar(`count(${this.qt}${filter})`)) ?? 0;
|
|
1103
1133
|
}
|
|
1104
1134
|
else {
|
|
1105
1135
|
const counts = {};
|
|
1106
1136
|
for (const field of Object.keys(args._count).filter((f) => args._count[f])) {
|
|
1107
|
-
counts[field] = (await scalar(`count(${this.
|
|
1137
|
+
counts[field] = (await scalar(`count(${this.qt}${filter} { ${this.ref(field)} })`)) ?? 0;
|
|
1108
1138
|
}
|
|
1109
1139
|
result._count = counts;
|
|
1110
1140
|
}
|
|
@@ -1116,7 +1146,7 @@ class PowqlInterface {
|
|
|
1116
1146
|
const acc = {};
|
|
1117
1147
|
for (const field of Object.keys(spec).filter((f) => spec[f])) {
|
|
1118
1148
|
const powfn = fn.slice(1); // sum/avg/min/max
|
|
1119
|
-
acc[field] = await scalar(`${powfn}(${this.
|
|
1149
|
+
acc[field] = await scalar(`${powfn}(${this.qt}${filter} { ${this.ref(field)} })`);
|
|
1120
1150
|
}
|
|
1121
1151
|
result[fn] = acc;
|
|
1122
1152
|
}
|
|
@@ -1150,7 +1180,7 @@ class PowqlInterface {
|
|
|
1150
1180
|
}
|
|
1151
1181
|
const having = this.buildHaving(args.having, params);
|
|
1152
1182
|
const order = this.buildOrder(args.orderBy);
|
|
1153
|
-
const powql = `${this.
|
|
1183
|
+
const powql = `${this.qt}${filter} group ${groupKeys.join(', ')}${having}${order} { ${proj.join(', ')} }`;
|
|
1154
1184
|
const { rows } = await this.exec(powql, params, args.timeout);
|
|
1155
1185
|
// Reshape: group keys → camel fields + coerced; aggregates → nested {_sum:{field}}.
|
|
1156
1186
|
return rows.map((raw) => {
|