@dbcube/query-builder 5.1.6 → 5.2.1
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 +122 -1700
- package/dist/index.cjs +61 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +80 -47
- package/dist/index.d.ts +80 -47
- package/dist/index.js +61 -17
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/.npmignore +0 -51
- package/CONTRIBUTING.md +0 -9
- package/bun.lockb +0 -0
- package/pnpm-workspace.yaml +0 -2
- package/tsup.config.ts +0 -14
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
39
39
|
// src/lib/Database.ts
|
|
40
40
|
var import_fs = __toESM(require("fs"));
|
|
41
41
|
var import_path2 = __toESM(require("path"));
|
|
42
|
+
var import_crypto = require("crypto");
|
|
42
43
|
var import_core2 = require("@dbcube/core");
|
|
43
44
|
|
|
44
45
|
// src/lib/Trigger.ts
|
|
@@ -75,7 +76,10 @@ var Trigger = class {
|
|
|
75
76
|
const pathFile = import_path.default.resolve(process.cwd(), "dbcube", "triggers", `${trigger.database_ref}_${trigger.table_ref}_${trigger.type}.js`);
|
|
76
77
|
const requireUrl = typeof __filename !== "undefined" ? __filename : process.cwd();
|
|
77
78
|
const require2 = (0, import_module.createRequire)(requireUrl);
|
|
78
|
-
|
|
79
|
+
try {
|
|
80
|
+
delete require2.cache[require2.resolve(pathFile)];
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
79
83
|
const triggerModule = require2(pathFile);
|
|
80
84
|
const dataProcess = triggerModule.default || triggerModule;
|
|
81
85
|
await dataProcess({ db: this.instance, oldData: row, newData: row });
|
|
@@ -143,7 +147,10 @@ var Database = class _Database {
|
|
|
143
147
|
} catch (error) {
|
|
144
148
|
try {
|
|
145
149
|
await this.engine.rollbackTransaction(txId);
|
|
146
|
-
} catch {
|
|
150
|
+
} catch (rollbackError) {
|
|
151
|
+
console.error(
|
|
152
|
+
`[dbcube] Rollback of transaction ${txId} failed: ${rollbackError?.message ?? rollbackError}`
|
|
153
|
+
);
|
|
147
154
|
}
|
|
148
155
|
throw error;
|
|
149
156
|
}
|
|
@@ -168,10 +175,9 @@ var Database = class _Database {
|
|
|
168
175
|
if (response.status != 200) {
|
|
169
176
|
returnFormattedError(response.status, response.message);
|
|
170
177
|
}
|
|
171
|
-
return response.data;
|
|
172
178
|
}
|
|
173
179
|
async disconnect() {
|
|
174
|
-
|
|
180
|
+
await this.engine.run("query_engine", [
|
|
175
181
|
"--action",
|
|
176
182
|
"disconnect"
|
|
177
183
|
]);
|
|
@@ -232,8 +238,12 @@ var Table = class _Table {
|
|
|
232
238
|
triggers;
|
|
233
239
|
txId = null;
|
|
234
240
|
relations = [];
|
|
235
|
-
|
|
241
|
+
/** Builders de grupo mutan en sitio (ver clone()) */
|
|
242
|
+
_mutable = false;
|
|
243
|
+
instance;
|
|
244
|
+
constructor(instance, databaseName, tableName, engine, computedFields = [], triggers = [], txId = null) {
|
|
236
245
|
this.engine = engine;
|
|
246
|
+
this.instance = instance;
|
|
237
247
|
this.computedFields = computedFields;
|
|
238
248
|
this.triggers = triggers;
|
|
239
249
|
this.trigger = new Trigger(instance, databaseName, triggers);
|
|
@@ -310,7 +320,8 @@ var Table = class _Table {
|
|
|
310
320
|
*/
|
|
311
321
|
whereGroup(callback) {
|
|
312
322
|
const clone = this.clone();
|
|
313
|
-
const groupQuery = new _Table(this, clone.dml.database, clone.dml.table, clone.engine);
|
|
323
|
+
const groupQuery = new _Table(this.instance, clone.dml.database, clone.dml.table, clone.engine);
|
|
324
|
+
groupQuery._mutable = true;
|
|
314
325
|
callback(groupQuery);
|
|
315
326
|
clone.dml.where.push({
|
|
316
327
|
type: clone.nextType,
|
|
@@ -857,11 +868,10 @@ var Table = class _Table {
|
|
|
857
868
|
* console.log(user); // { id: 1, name: 'John' }
|
|
858
869
|
*/
|
|
859
870
|
async find(value, column = "id") {
|
|
860
|
-
const clone = this.clone();
|
|
871
|
+
const clone = this.clone().where(column, "=", value);
|
|
861
872
|
clone.dml.type = "select";
|
|
862
873
|
clone.dml.data = null;
|
|
863
874
|
clone.dml.aggregation = null;
|
|
864
|
-
clone.where(column, "=", value);
|
|
865
875
|
clone.dml.limit = 1;
|
|
866
876
|
try {
|
|
867
877
|
const result = await clone.getResponse();
|
|
@@ -918,8 +928,7 @@ var Table = class _Table {
|
|
|
918
928
|
}
|
|
919
929
|
clone.dml.type = "update";
|
|
920
930
|
clone.dml.data = data;
|
|
921
|
-
|
|
922
|
-
return data;
|
|
931
|
+
return clone.getResponse(clone.dml, "Update");
|
|
923
932
|
}
|
|
924
933
|
/**
|
|
925
934
|
* Deletes rows from the table based on the defined conditions.
|
|
@@ -1139,12 +1148,37 @@ var Table = class _Table {
|
|
|
1139
1148
|
throw new Error("The upsert method requires at least one conflict key column.");
|
|
1140
1149
|
}
|
|
1141
1150
|
const motor = this.engine?.getConfig?.()?.type ?? "mysql";
|
|
1142
|
-
if (motor === "mongodb") {
|
|
1143
|
-
throw new Error("upsert() is not supported for MongoDB yet. Use update() + insert() or raw commands.");
|
|
1144
|
-
}
|
|
1145
1151
|
const table = this.dml.table;
|
|
1146
1152
|
const columns = Object.keys(data[0]);
|
|
1147
1153
|
const targets = updateColumns ?? columns.filter((c) => !conflictKeys.includes(c));
|
|
1154
|
+
assertValidIdentifier(table, "table");
|
|
1155
|
+
for (const c of columns) assertValidIdentifier(c, "column");
|
|
1156
|
+
for (const c of conflictKeys) assertValidIdentifier(c, "conflict key");
|
|
1157
|
+
for (const c of targets) assertValidIdentifier(c, "update column");
|
|
1158
|
+
if (motor === "mongodb") {
|
|
1159
|
+
const updates = data.map((row) => {
|
|
1160
|
+
const q = {};
|
|
1161
|
+
for (const k of conflictKeys) q[k] = row[k];
|
|
1162
|
+
const set = {};
|
|
1163
|
+
for (const c of targets) if (c in row) set[c] = row[c];
|
|
1164
|
+
const setOnInsert = {};
|
|
1165
|
+
for (const c of columns) {
|
|
1166
|
+
if (!targets.includes(c) && !conflictKeys.includes(c)) setOnInsert[c] = row[c];
|
|
1167
|
+
}
|
|
1168
|
+
if (!("uuid" in row)) setOnInsert["uuid"] = (0, import_crypto.randomUUID)();
|
|
1169
|
+
const u = {};
|
|
1170
|
+
if (Object.keys(set).length) u["$set"] = set;
|
|
1171
|
+
if (Object.keys(setOnInsert).length) u["$setOnInsert"] = setOnInsert;
|
|
1172
|
+
return { q, u, upsert: true, multi: false };
|
|
1173
|
+
});
|
|
1174
|
+
const command = JSON.stringify({ update: table, updates });
|
|
1175
|
+
const response2 = await this.engine.rawQuery(command, [], this.txId ?? void 0);
|
|
1176
|
+
if (response2.status != 200) {
|
|
1177
|
+
returnFormattedError(response2.status, response2.message);
|
|
1178
|
+
throw new Error(response2.message);
|
|
1179
|
+
}
|
|
1180
|
+
return response2.data;
|
|
1181
|
+
}
|
|
1148
1182
|
const quote = (id) => motor === "mysql" ? `\`${id}\`` : `"${id}"`;
|
|
1149
1183
|
const params = [];
|
|
1150
1184
|
const placeholder = () => motor === "postgres" || motor === "postgresql" ? `$${params.length}` : "?";
|
|
@@ -1165,6 +1199,9 @@ var Table = class _Table {
|
|
|
1165
1199
|
const updates = targets.map((c) => `${quote(c)} = excluded.${quote(c)}`).join(", ");
|
|
1166
1200
|
sql = `INSERT INTO ${quote(table)} (${colsSql}) VALUES ${rowsSql} ON CONFLICT (${conflict}) DO UPDATE SET ${updates}`;
|
|
1167
1201
|
}
|
|
1202
|
+
if (motor === "sqlite") {
|
|
1203
|
+
await this.engine.rawQuery("SELECT name FROM sqlite_master LIMIT 1", [], this.txId ?? void 0);
|
|
1204
|
+
}
|
|
1168
1205
|
const response = await this.engine.rawQuery(sql, params, this.txId ?? void 0);
|
|
1169
1206
|
if (response.status != 200) {
|
|
1170
1207
|
returnFormattedError(response.status, response.message);
|
|
@@ -1219,7 +1256,7 @@ var Table = class _Table {
|
|
|
1219
1256
|
foreignKey = foreignKey ?? `${singularize(this.dml.table)}_id`;
|
|
1220
1257
|
}
|
|
1221
1258
|
}
|
|
1222
|
-
const relatedQuery = new _Table(this, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);
|
|
1259
|
+
const relatedQuery = new _Table(this.instance, this.dml.database, relatedTable, this.engine, this.computedFields, this.triggers, this.txId);
|
|
1223
1260
|
if (type === "one") {
|
|
1224
1261
|
const fkValues = [...new Set(rows.map((r) => r[foreignKey]).filter((v) => v !== null && v !== void 0))];
|
|
1225
1262
|
const related = fkValues.length > 0 ? await relatedQuery.whereIn(localKey, fkValues).get() : [];
|
|
@@ -1274,10 +1311,10 @@ var Table = class _Table {
|
|
|
1274
1311
|
const interceptor = await this.trigger.execute("before" + type, data);
|
|
1275
1312
|
const response = await this.engine.executeDml(newDML, this.txId ?? void 0);
|
|
1276
1313
|
if (response.status != 200) {
|
|
1277
|
-
interceptor
|
|
1314
|
+
interceptor?.discard();
|
|
1278
1315
|
returnFormattedError(response.status, response.message);
|
|
1279
1316
|
}
|
|
1280
|
-
await interceptor
|
|
1317
|
+
await interceptor?.commit();
|
|
1281
1318
|
arrayResult = response.data;
|
|
1282
1319
|
}
|
|
1283
1320
|
if (after) {
|
|
@@ -1286,7 +1323,7 @@ var Table = class _Table {
|
|
|
1286
1323
|
returnFormattedError(response.status, response.message);
|
|
1287
1324
|
}
|
|
1288
1325
|
const interceptor = await this.trigger.execute("after" + type, data);
|
|
1289
|
-
await interceptor
|
|
1326
|
+
await interceptor?.commit();
|
|
1290
1327
|
}
|
|
1291
1328
|
}
|
|
1292
1329
|
} else {
|
|
@@ -1315,8 +1352,10 @@ var Table = class _Table {
|
|
|
1315
1352
|
return arrayResult;
|
|
1316
1353
|
}
|
|
1317
1354
|
clone() {
|
|
1355
|
+
if (this._mutable) return this;
|
|
1318
1356
|
const cloned = Object.create(Object.getPrototypeOf(this));
|
|
1319
1357
|
cloned.engine = this.engine;
|
|
1358
|
+
cloned.instance = this.instance;
|
|
1320
1359
|
cloned.nextType = this.nextType;
|
|
1321
1360
|
cloned.computedFields = this.computedFields;
|
|
1322
1361
|
cloned.trigger = this.trigger;
|
|
@@ -1384,6 +1423,11 @@ function loadCubeRelations() {
|
|
|
1384
1423
|
cubeRelationsCache = result;
|
|
1385
1424
|
return result;
|
|
1386
1425
|
}
|
|
1426
|
+
function assertValidIdentifier(name, kind) {
|
|
1427
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
|
|
1428
|
+
throw new Error(`Invalid ${kind} name: '${name}'. Only letters, numbers and underscore are allowed.`);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1387
1431
|
function singularize(word) {
|
|
1388
1432
|
if (word.endsWith("ies")) return word.slice(0, -3) + "y";
|
|
1389
1433
|
if (word.endsWith("ses")) return word.slice(0, -2);
|