@type32/tauri-sqlite-orm 0.1.20 → 0.2.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 +76 -0
- package/dist/index.d.mts +135 -10
- package/dist/index.d.ts +135 -10
- package/dist/index.js +577 -90
- package/dist/index.mjs +548 -91
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -33,6 +33,9 @@ var BaseQueryBuilder = class {
|
|
|
33
33
|
params: this.params
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
|
+
toSQL() {
|
|
37
|
+
return this.build();
|
|
38
|
+
}
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
// src/operators.ts
|
|
@@ -43,6 +46,13 @@ var eq = (column, value, tableAlias) => {
|
|
|
43
46
|
params: [value]
|
|
44
47
|
};
|
|
45
48
|
};
|
|
49
|
+
var ne = (column, value, tableAlias) => {
|
|
50
|
+
const columnName = tableAlias ? `${tableAlias}.${column._.name}` : column._.name;
|
|
51
|
+
return {
|
|
52
|
+
sql: `${columnName} != ?`,
|
|
53
|
+
params: [value]
|
|
54
|
+
};
|
|
55
|
+
};
|
|
46
56
|
var and = (...conditions) => ({
|
|
47
57
|
sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
|
|
48
58
|
params: conditions.flatMap((c) => c.params)
|
|
@@ -75,6 +85,22 @@ var like = (column, pattern) => ({
|
|
|
75
85
|
sql: `${column._.name} LIKE ?`,
|
|
76
86
|
params: [pattern]
|
|
77
87
|
});
|
|
88
|
+
var ilike = (column, pattern) => ({
|
|
89
|
+
sql: `${column._.name} LIKE ? COLLATE NOCASE`,
|
|
90
|
+
params: [pattern]
|
|
91
|
+
});
|
|
92
|
+
var startsWith = (column, value) => ({
|
|
93
|
+
sql: `${column._.name} LIKE ?`,
|
|
94
|
+
params: [`${value}%`]
|
|
95
|
+
});
|
|
96
|
+
var endsWith = (column, value) => ({
|
|
97
|
+
sql: `${column._.name} LIKE ?`,
|
|
98
|
+
params: [`%${value}`]
|
|
99
|
+
});
|
|
100
|
+
var contains = (column, value) => ({
|
|
101
|
+
sql: `${column._.name} LIKE ?`,
|
|
102
|
+
params: [`%${value}%`]
|
|
103
|
+
});
|
|
78
104
|
var isNull = (column) => ({
|
|
79
105
|
sql: `${column._.name} IS NULL`,
|
|
80
106
|
params: []
|
|
@@ -83,33 +109,65 @@ var isNotNull = (column) => ({
|
|
|
83
109
|
sql: `${column._.name} IS NOT NULL`,
|
|
84
110
|
params: []
|
|
85
111
|
});
|
|
86
|
-
var
|
|
87
|
-
sql:
|
|
88
|
-
params:
|
|
112
|
+
var exists = (subquery2) => ({
|
|
113
|
+
sql: `EXISTS (${subquery2.sql})`,
|
|
114
|
+
params: subquery2.params
|
|
89
115
|
});
|
|
90
|
-
var
|
|
91
|
-
sql: `
|
|
92
|
-
params:
|
|
116
|
+
var notExists = (subquery2) => ({
|
|
117
|
+
sql: `NOT EXISTS (${subquery2.sql})`,
|
|
118
|
+
params: subquery2.params
|
|
93
119
|
});
|
|
94
|
-
var
|
|
95
|
-
sql:
|
|
96
|
-
params:
|
|
120
|
+
var eqSubquery = (column, subquery2) => ({
|
|
121
|
+
sql: `${column._.name} = ${subquery2.sql}`,
|
|
122
|
+
params: subquery2.params
|
|
97
123
|
});
|
|
98
|
-
var
|
|
99
|
-
sql:
|
|
100
|
-
params:
|
|
124
|
+
var neSubquery = (column, subquery2) => ({
|
|
125
|
+
sql: `${column._.name} != ${subquery2.sql}`,
|
|
126
|
+
params: subquery2.params
|
|
101
127
|
});
|
|
102
|
-
var
|
|
103
|
-
sql:
|
|
104
|
-
params:
|
|
128
|
+
var gtSubquery = (column, subquery2) => ({
|
|
129
|
+
sql: `${column._.name} > ${subquery2.sql}`,
|
|
130
|
+
params: subquery2.params
|
|
105
131
|
});
|
|
106
|
-
var
|
|
107
|
-
sql:
|
|
108
|
-
params:
|
|
132
|
+
var gteSubquery = (column, subquery2) => ({
|
|
133
|
+
sql: `${column._.name} >= ${subquery2.sql}`,
|
|
134
|
+
params: subquery2.params
|
|
109
135
|
});
|
|
110
|
-
var
|
|
111
|
-
sql:
|
|
112
|
-
params:
|
|
136
|
+
var ltSubquery = (column, subquery2) => ({
|
|
137
|
+
sql: `${column._.name} < ${subquery2.sql}`,
|
|
138
|
+
params: subquery2.params
|
|
139
|
+
});
|
|
140
|
+
var lteSubquery = (column, subquery2) => ({
|
|
141
|
+
sql: `${column._.name} <= ${subquery2.sql}`,
|
|
142
|
+
params: subquery2.params
|
|
143
|
+
});
|
|
144
|
+
var inArray = (column, values) => {
|
|
145
|
+
if ("_isSubquery" in values && values._isSubquery) {
|
|
146
|
+
return {
|
|
147
|
+
sql: `${column._.name} IN ${values.sql}`,
|
|
148
|
+
params: values.params
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
|
|
153
|
+
params: values
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
var notIn = (column, values) => {
|
|
157
|
+
if ("_isSubquery" in values && values._isSubquery) {
|
|
158
|
+
return {
|
|
159
|
+
sql: `${column._.name} NOT IN ${values.sql}`,
|
|
160
|
+
params: values.params
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
sql: `${column._.name} NOT IN (${values.map(() => "?").join(",")})`,
|
|
165
|
+
params: values
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
var between = (column, min2, max2) => ({
|
|
169
|
+
sql: `${column._.name} BETWEEN ? AND ?`,
|
|
170
|
+
params: [min2, max2]
|
|
113
171
|
});
|
|
114
172
|
|
|
115
173
|
// src/builders/select.ts
|
|
@@ -175,42 +233,30 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
175
233
|
sql2 += ` ${join.type} JOIN ${join.table._.name} ${join.alias} ON ${join.condition.sql}`;
|
|
176
234
|
params.push(...join.condition.params);
|
|
177
235
|
}
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
console.warn(
|
|
183
|
-
`[Tauri-ORM] Relation "${relationName}" not found on table "${this.table._.name}". Skipping include.`
|
|
184
|
-
);
|
|
185
|
-
continue;
|
|
236
|
+
const processRelations = (parentTable, parentAlias, relations2, depth = 0) => {
|
|
237
|
+
if (depth > 10) {
|
|
238
|
+
console.warn("[Tauri-ORM] Maximum relation depth (10) exceeded. Skipping deeper relations.");
|
|
239
|
+
return;
|
|
186
240
|
}
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
};
|
|
201
|
-
});
|
|
202
|
-
const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
|
|
203
|
-
sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
|
|
204
|
-
params.push(...condition.params);
|
|
205
|
-
} else if (relation.type === "many") {
|
|
206
|
-
const refRelation = Object.entries(foreignTable.relations).find(
|
|
207
|
-
([_, r]) => r.foreignTable === this.table
|
|
241
|
+
for (const [relationName, include] of Object.entries(relations2)) {
|
|
242
|
+
if (!include) continue;
|
|
243
|
+
const relation = parentTable.relations[relationName];
|
|
244
|
+
if (!relation) {
|
|
245
|
+
console.warn(
|
|
246
|
+
`[Tauri-ORM] Relation "${relationName}" not found on table "${parentTable._.name}". Skipping include.`
|
|
247
|
+
);
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
const foreignTable = relation.foreignTable;
|
|
251
|
+
const foreignAlias = `${parentAlias}_${relationName}`;
|
|
252
|
+
const aliasedColumns = Object.values(foreignTable._.columns).map(
|
|
253
|
+
(col) => `${foreignAlias}.${col._.name} AS "${foreignAlias}.${col._.name}"`
|
|
208
254
|
);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const conditions =
|
|
212
|
-
const localColumn = `${
|
|
213
|
-
const foreignColumn = `${
|
|
255
|
+
this.selectedColumns.push(...aliasedColumns);
|
|
256
|
+
if (relation.type === "one" && relation.fields && relation.references) {
|
|
257
|
+
const conditions = relation.fields.map((field, i) => {
|
|
258
|
+
const localColumn = `${parentAlias}.${field._.name}`;
|
|
259
|
+
const foreignColumn = `${foreignAlias}.${relation.references[i]._.name}`;
|
|
214
260
|
return {
|
|
215
261
|
sql: `${localColumn} = ${foreignColumn}`,
|
|
216
262
|
params: []
|
|
@@ -219,9 +265,64 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
219
265
|
const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
|
|
220
266
|
sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
|
|
221
267
|
params.push(...condition.params);
|
|
268
|
+
} else if (relation.type === "many") {
|
|
269
|
+
const refRelation = Object.entries(foreignTable.relations).find(
|
|
270
|
+
([_, r]) => r.foreignTable === parentTable
|
|
271
|
+
);
|
|
272
|
+
if (refRelation && refRelation[1].fields && refRelation[1].references) {
|
|
273
|
+
const [_, relationConfig] = refRelation;
|
|
274
|
+
const conditions = relationConfig.fields.map((field, i) => {
|
|
275
|
+
const localColumn = `${foreignAlias}.${field._.name}`;
|
|
276
|
+
const foreignColumn = `${parentAlias}.${relationConfig.references[i]._.name}`;
|
|
277
|
+
return {
|
|
278
|
+
sql: `${localColumn} = ${foreignColumn}`,
|
|
279
|
+
params: []
|
|
280
|
+
};
|
|
281
|
+
});
|
|
282
|
+
const condition = conditions.length > 1 ? and(...conditions) : conditions[0];
|
|
283
|
+
sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${condition.sql}`;
|
|
284
|
+
params.push(...condition.params);
|
|
285
|
+
}
|
|
286
|
+
} else if (relation.type === "manyToMany" && relation.junctionTable && relation.junctionFields && relation.junctionReferences) {
|
|
287
|
+
const junctionTable = relation.junctionTable;
|
|
288
|
+
const junctionAlias = `${foreignAlias}_junction`;
|
|
289
|
+
const parentTablePks = Object.values(parentTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
|
|
290
|
+
if (parentTablePks.length > 0 && relation.junctionFields.length > 0) {
|
|
291
|
+
const junctionConditions = relation.junctionFields.map((field, i) => {
|
|
292
|
+
const parentPk = parentTablePks[i] || parentTablePks[0];
|
|
293
|
+
const localColumn = `${parentAlias}.${parentPk}`;
|
|
294
|
+
const junctionColumn = `${junctionAlias}.${field._.name}`;
|
|
295
|
+
return {
|
|
296
|
+
sql: `${localColumn} = ${junctionColumn}`,
|
|
297
|
+
params: []
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
const junctionCondition = junctionConditions.length > 1 ? and(...junctionConditions) : junctionConditions[0];
|
|
301
|
+
sql2 += ` LEFT JOIN ${junctionTable._.name} ${junctionAlias} ON ${junctionCondition.sql}`;
|
|
302
|
+
params.push(...junctionCondition.params);
|
|
303
|
+
const foreignTablePks = Object.values(foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
|
|
304
|
+
if (foreignTablePks.length > 0 && relation.junctionReferences.length > 0) {
|
|
305
|
+
const foreignConditions = relation.junctionReferences.map((field, i) => {
|
|
306
|
+
const foreignPk = foreignTablePks[i] || foreignTablePks[0];
|
|
307
|
+
const junctionColumn = `${junctionAlias}.${field._.name}`;
|
|
308
|
+
const foreignColumn = `${foreignAlias}.${foreignPk}`;
|
|
309
|
+
return {
|
|
310
|
+
sql: `${junctionColumn} = ${foreignColumn}`,
|
|
311
|
+
params: []
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
const foreignCondition = foreignConditions.length > 1 ? and(...foreignConditions) : foreignConditions[0];
|
|
315
|
+
sql2 += ` LEFT JOIN ${foreignTable._.name} ${foreignAlias} ON ${foreignCondition.sql}`;
|
|
316
|
+
params.push(...foreignCondition.params);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (typeof include === "object" && include.with) {
|
|
321
|
+
processRelations(foreignTable, foreignAlias, include.with, depth + 1);
|
|
222
322
|
}
|
|
223
323
|
}
|
|
224
|
-
}
|
|
324
|
+
};
|
|
325
|
+
processRelations(this.table, this.selectedTableAlias, this.includeRelations, 0);
|
|
225
326
|
return { sql: sql2, params };
|
|
226
327
|
}
|
|
227
328
|
// Enhanced execute method that handles relation data mapping
|
|
@@ -232,7 +333,6 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
232
333
|
this.query += joinSql;
|
|
233
334
|
this.params.push(...joinParams);
|
|
234
335
|
const { sql: sql2, params } = this.build();
|
|
235
|
-
console.log("Executing SQL:", sql2, "with params:", params);
|
|
236
336
|
const rawResults = await this.db.select(sql2, params);
|
|
237
337
|
const hasIncludes = Object.values(this.includeRelations).some((i) => i);
|
|
238
338
|
if (hasIncludes) {
|
|
@@ -262,6 +362,36 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
262
362
|
return rawResults;
|
|
263
363
|
}
|
|
264
364
|
const groupedResults = /* @__PURE__ */ new Map();
|
|
365
|
+
const parseRelationPath = (tableAlias, baseAlias) => {
|
|
366
|
+
if (!tableAlias.startsWith(baseAlias + "_")) {
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
const path = tableAlias.substring(baseAlias.length + 1);
|
|
370
|
+
return path.split("_");
|
|
371
|
+
};
|
|
372
|
+
const setNestedValue = (obj, path, value, columnName) => {
|
|
373
|
+
let current = obj;
|
|
374
|
+
for (let i = 0; i < path.length; i++) {
|
|
375
|
+
const key = path[i];
|
|
376
|
+
if (i === path.length - 1) {
|
|
377
|
+
if (!current[key]) current[key] = {};
|
|
378
|
+
current[key][columnName] = value;
|
|
379
|
+
} else {
|
|
380
|
+
if (!current[key]) current[key] = {};
|
|
381
|
+
current = current[key];
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
const getNestedRelation = (table, path) => {
|
|
386
|
+
let currentTable = table;
|
|
387
|
+
let currentRelation = null;
|
|
388
|
+
for (const relationName of path) {
|
|
389
|
+
currentRelation = currentTable.relations[relationName];
|
|
390
|
+
if (!currentRelation) return null;
|
|
391
|
+
currentTable = currentRelation.foreignTable;
|
|
392
|
+
}
|
|
393
|
+
return currentRelation;
|
|
394
|
+
};
|
|
265
395
|
for (const row of rawResults) {
|
|
266
396
|
const mainTableKey = mainTablePks.map((pk) => row[`${this.selectedTableAlias}.${pk}`] ?? row[pk]).join("_");
|
|
267
397
|
if (!groupedResults.has(mainTableKey)) {
|
|
@@ -275,11 +405,9 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
275
405
|
if (tableAlias === this.selectedTableAlias) {
|
|
276
406
|
result[columnName] = value;
|
|
277
407
|
} else {
|
|
278
|
-
const
|
|
279
|
-
if (
|
|
280
|
-
|
|
281
|
-
if (!relations2[relationName]) relations2[relationName] = {};
|
|
282
|
-
relations2[relationName][columnName] = value;
|
|
408
|
+
const relationPath = parseRelationPath(tableAlias, this.selectedTableAlias);
|
|
409
|
+
if (relationPath.length > 0) {
|
|
410
|
+
setNestedValue(relations2, relationPath, value, columnName);
|
|
283
411
|
} else {
|
|
284
412
|
if (!result[tableAlias]) result[tableAlias] = {};
|
|
285
413
|
result[tableAlias][columnName] = value;
|
|
@@ -289,24 +417,72 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
289
417
|
result[key] = value;
|
|
290
418
|
}
|
|
291
419
|
}
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (!
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
420
|
+
const attachRelations = (target, relationsData, table, pathPrefix = []) => {
|
|
421
|
+
for (const [relName, relData] of Object.entries(relationsData)) {
|
|
422
|
+
const currentPath = [...pathPrefix, relName];
|
|
423
|
+
const relationConfig = getNestedRelation(table, currentPath);
|
|
424
|
+
if (!relationConfig) continue;
|
|
425
|
+
const hasDirectData = typeof relData === "object" && relData !== null && Object.entries(relData).some(([k, v]) => {
|
|
426
|
+
return typeof v !== "object" && v !== null && v !== void 0 && v !== "";
|
|
427
|
+
});
|
|
428
|
+
if (!hasDirectData && typeof relData === "object" && relData !== null) {
|
|
429
|
+
const hasNestedData = Object.values(relData).some(
|
|
430
|
+
(v) => typeof v === "object" && v !== null && Object.keys(v).length > 0
|
|
431
|
+
);
|
|
432
|
+
if (!hasNestedData) continue;
|
|
433
|
+
}
|
|
434
|
+
if (relationConfig.type === "many" || relationConfig.type === "manyToMany") {
|
|
435
|
+
if (!target[relName]) target[relName] = [];
|
|
436
|
+
const directData = {};
|
|
437
|
+
const nestedData = {};
|
|
438
|
+
if (typeof relData === "object" && relData !== null) {
|
|
439
|
+
for (const [k, v] of Object.entries(relData)) {
|
|
440
|
+
if (typeof v === "object" && v !== null) {
|
|
441
|
+
nestedData[k] = v;
|
|
442
|
+
} else {
|
|
443
|
+
directData[k] = v;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const hasData = Object.values(directData).some(
|
|
448
|
+
(v) => v !== null && v !== void 0 && v !== ""
|
|
449
|
+
);
|
|
450
|
+
if (hasData) {
|
|
451
|
+
const relatedPks = Object.values(relationConfig.foreignTable._.columns).filter((c) => c.options.primaryKey).map((c) => c._.name);
|
|
452
|
+
const relDataKey = relatedPks.map((pk) => directData[pk]).join("_");
|
|
453
|
+
if (relatedPks.length === 0 || !target[relName].some((r) => relatedPks.map((pk) => r[pk]).join("_") === relDataKey)) {
|
|
454
|
+
const newItem = { ...directData };
|
|
455
|
+
if (Object.keys(nestedData).length > 0) {
|
|
456
|
+
attachRelations(newItem, nestedData, relationConfig.foreignTable, []);
|
|
457
|
+
}
|
|
458
|
+
target[relName].push(newItem);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
} else {
|
|
462
|
+
const directData = {};
|
|
463
|
+
const nestedData = {};
|
|
464
|
+
if (typeof relData === "object" && relData !== null) {
|
|
465
|
+
for (const [k, v] of Object.entries(relData)) {
|
|
466
|
+
if (typeof v === "object" && v !== null) {
|
|
467
|
+
nestedData[k] = v;
|
|
468
|
+
} else {
|
|
469
|
+
directData[k] = v;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const hasData = Object.values(directData).some(
|
|
474
|
+
(v) => v !== null && v !== void 0 && v !== ""
|
|
475
|
+
);
|
|
476
|
+
if (hasData || Object.keys(nestedData).length > 0) {
|
|
477
|
+
target[relName] = { ...directData };
|
|
478
|
+
if (Object.keys(nestedData).length > 0) {
|
|
479
|
+
attachRelations(target[relName], nestedData, relationConfig.foreignTable, []);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
305
482
|
}
|
|
306
|
-
} else {
|
|
307
|
-
result[relName] = relData;
|
|
308
483
|
}
|
|
309
|
-
}
|
|
484
|
+
};
|
|
485
|
+
attachRelations(result, relations2, this.table);
|
|
310
486
|
}
|
|
311
487
|
return Array.from(groupedResults.values());
|
|
312
488
|
}
|
|
@@ -319,6 +495,82 @@ var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
|
319
495
|
const result = await this.execute();
|
|
320
496
|
return result[0];
|
|
321
497
|
}
|
|
498
|
+
toSQL() {
|
|
499
|
+
const { sql: joinSql, params: joinParams } = this.buildJoins();
|
|
500
|
+
const distinct = this.isDistinct ? "DISTINCT " : "";
|
|
501
|
+
const finalQuery = `SELECT ${distinct}${this.selectedColumns.join(", ")} ${this.query}${joinSql}`;
|
|
502
|
+
return {
|
|
503
|
+
sql: finalQuery,
|
|
504
|
+
params: [...this.params, ...joinParams]
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// src/errors.ts
|
|
510
|
+
var TauriORMError = class extends Error {
|
|
511
|
+
constructor(message) {
|
|
512
|
+
super(message);
|
|
513
|
+
this.name = "TauriORMError";
|
|
514
|
+
if (Error.captureStackTrace) {
|
|
515
|
+
Error.captureStackTrace(this, this.constructor);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
var QueryBuilderError = class extends TauriORMError {
|
|
520
|
+
constructor(message) {
|
|
521
|
+
super(message);
|
|
522
|
+
this.name = "QueryBuilderError";
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
var MissingWhereClauseError = class extends QueryBuilderError {
|
|
526
|
+
constructor(operation, tableName) {
|
|
527
|
+
super(
|
|
528
|
+
`${operation} operation on table "${tableName}" requires a WHERE clause to prevent accidental data loss. Use .where() to specify conditions, or use .allowGlobalOperation() to explicitly allow operations without WHERE.`
|
|
529
|
+
);
|
|
530
|
+
this.name = "MissingWhereClauseError";
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
var ValidationError = class extends TauriORMError {
|
|
534
|
+
constructor(message) {
|
|
535
|
+
super(message);
|
|
536
|
+
this.name = "ValidationError";
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
var InsertValidationError = class extends ValidationError {
|
|
540
|
+
constructor(message) {
|
|
541
|
+
super(message);
|
|
542
|
+
this.name = "InsertValidationError";
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
var UpdateValidationError = class extends ValidationError {
|
|
546
|
+
constructor(message) {
|
|
547
|
+
super(message);
|
|
548
|
+
this.name = "UpdateValidationError";
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
var MigrationError = class extends TauriORMError {
|
|
552
|
+
constructor(message) {
|
|
553
|
+
super(message);
|
|
554
|
+
this.name = "MigrationError";
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
var RelationError = class extends TauriORMError {
|
|
558
|
+
constructor(message) {
|
|
559
|
+
super(message);
|
|
560
|
+
this.name = "RelationError";
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
var ColumnNotFoundError = class extends TauriORMError {
|
|
564
|
+
constructor(columnName, tableName) {
|
|
565
|
+
super(`Column "${columnName}" does not exist on table "${tableName}"`);
|
|
566
|
+
this.name = "ColumnNotFoundError";
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
var TableNotFoundError = class extends TauriORMError {
|
|
570
|
+
constructor(tableName) {
|
|
571
|
+
super(`Table "${tableName}" not found in schema`);
|
|
572
|
+
this.name = "TableNotFoundError";
|
|
573
|
+
}
|
|
322
574
|
};
|
|
323
575
|
|
|
324
576
|
// src/builders/update.ts
|
|
@@ -330,10 +582,37 @@ var UpdateQueryBuilder = class extends BaseQueryBuilder {
|
|
|
330
582
|
}
|
|
331
583
|
updateData = {};
|
|
332
584
|
returningColumns = [];
|
|
585
|
+
hasWhereClause = false;
|
|
586
|
+
allowGlobal = false;
|
|
587
|
+
incrementDecrementOps = [];
|
|
333
588
|
set(data) {
|
|
334
589
|
this.updateData = { ...this.updateData, ...data };
|
|
335
590
|
return this;
|
|
336
591
|
}
|
|
592
|
+
where(condition) {
|
|
593
|
+
this.hasWhereClause = true;
|
|
594
|
+
return super.where(condition);
|
|
595
|
+
}
|
|
596
|
+
increment(column, value = 1) {
|
|
597
|
+
const col = this.table._.columns[column];
|
|
598
|
+
if (!col) {
|
|
599
|
+
throw new ColumnNotFoundError(String(column), this.table._.name);
|
|
600
|
+
}
|
|
601
|
+
this.incrementDecrementOps.push({ column: col._.name, op: "increment", value });
|
|
602
|
+
return this;
|
|
603
|
+
}
|
|
604
|
+
decrement(column, value = 1) {
|
|
605
|
+
const col = this.table._.columns[column];
|
|
606
|
+
if (!col) {
|
|
607
|
+
throw new ColumnNotFoundError(String(column), this.table._.name);
|
|
608
|
+
}
|
|
609
|
+
this.incrementDecrementOps.push({ column: col._.name, op: "decrement", value });
|
|
610
|
+
return this;
|
|
611
|
+
}
|
|
612
|
+
allowGlobalOperation() {
|
|
613
|
+
this.allowGlobal = true;
|
|
614
|
+
return this;
|
|
615
|
+
}
|
|
337
616
|
returning(...columns) {
|
|
338
617
|
this.returningColumns.push(...columns);
|
|
339
618
|
return this;
|
|
@@ -356,24 +635,37 @@ var UpdateQueryBuilder = class extends BaseQueryBuilder {
|
|
|
356
635
|
whereClause = baseQuery.substring(whereIndex);
|
|
357
636
|
}
|
|
358
637
|
const entries = Object.entries(finalUpdateData);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
638
|
+
const hasSetData = entries.length > 0;
|
|
639
|
+
const hasIncrementDecrement = this.incrementDecrementOps.length > 0;
|
|
640
|
+
if (!hasSetData && !hasIncrementDecrement) {
|
|
641
|
+
throw new UpdateValidationError("Cannot execute an update query without a .set(), .increment(), or .decrement() call.");
|
|
642
|
+
}
|
|
643
|
+
const setClauses = [];
|
|
644
|
+
const setParams = [];
|
|
645
|
+
if (hasSetData) {
|
|
646
|
+
for (const [key, value] of entries) {
|
|
647
|
+
const column = this.table._.columns[key];
|
|
648
|
+
if (!column) {
|
|
649
|
+
throw new ColumnNotFoundError(key, this.table._.name);
|
|
650
|
+
}
|
|
651
|
+
setClauses.push(`${column._.name} = ?`);
|
|
652
|
+
setParams.push(value);
|
|
368
653
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
654
|
+
}
|
|
655
|
+
for (const op of this.incrementDecrementOps) {
|
|
656
|
+
const sign = op.op === "increment" ? "+" : "-";
|
|
657
|
+
setClauses.push(`${op.column} = ${op.column} ${sign} ?`);
|
|
658
|
+
setParams.push(op.value);
|
|
659
|
+
}
|
|
660
|
+
const setClause = setClauses.join(", ");
|
|
372
661
|
const sql2 = `${tablePart} SET ${setClause}${whereClause}`;
|
|
373
662
|
const params = [...setParams, ...whereParams];
|
|
374
663
|
return { sql: sql2, params };
|
|
375
664
|
}
|
|
376
665
|
async execute() {
|
|
666
|
+
if (!this.hasWhereClause && !this.allowGlobal) {
|
|
667
|
+
throw new MissingWhereClauseError("UPDATE", this.table._.name);
|
|
668
|
+
}
|
|
377
669
|
const { sql: updateSql, params } = this.buildUpdateClause();
|
|
378
670
|
if (this.returningColumns.length > 0) {
|
|
379
671
|
const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
|
|
@@ -390,6 +682,17 @@ var UpdateQueryBuilder = class extends BaseQueryBuilder {
|
|
|
390
682
|
);
|
|
391
683
|
return this.returning(...allColumns).execute();
|
|
392
684
|
}
|
|
685
|
+
toSQL() {
|
|
686
|
+
const { sql: updateSql, params } = this.buildUpdateClause();
|
|
687
|
+
if (this.returningColumns.length > 0) {
|
|
688
|
+
const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
|
|
689
|
+
return {
|
|
690
|
+
sql: `${updateSql} RETURNING ${returningNames}`,
|
|
691
|
+
params
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
return { sql: updateSql, params };
|
|
695
|
+
}
|
|
393
696
|
};
|
|
394
697
|
|
|
395
698
|
// src/builders/insert.ts
|
|
@@ -458,7 +761,7 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
|
|
|
458
761
|
}
|
|
459
762
|
async execute() {
|
|
460
763
|
if (this.dataSets.length === 0) {
|
|
461
|
-
throw new
|
|
764
|
+
throw new InsertValidationError("No data provided for insert. Use .values() to provide data.");
|
|
462
765
|
}
|
|
463
766
|
const processedDataSets = this.dataSets.map(
|
|
464
767
|
(data) => this.processDefaultValues(data)
|
|
@@ -516,6 +819,42 @@ var InsertQueryBuilder = class extends BaseQueryBuilder {
|
|
|
516
819
|
);
|
|
517
820
|
return this.returning(...allColumns).execute();
|
|
518
821
|
}
|
|
822
|
+
toSQL() {
|
|
823
|
+
if (this.dataSets.length === 0) {
|
|
824
|
+
throw new InsertValidationError("No data provided for insert. Use .values() to provide data.");
|
|
825
|
+
}
|
|
826
|
+
const processedDataSets = this.dataSets.map(
|
|
827
|
+
(data) => this.processDefaultValues(data)
|
|
828
|
+
);
|
|
829
|
+
const dataSet = processedDataSets[0];
|
|
830
|
+
const columns = Object.keys(dataSet);
|
|
831
|
+
const columnNames = columns.map(
|
|
832
|
+
(key) => this.table._.columns[key]._.name
|
|
833
|
+
);
|
|
834
|
+
const placeholders = `(${columns.map(() => "?").join(", ")})`;
|
|
835
|
+
const valuesSql = processedDataSets.map(() => placeholders).join(", ");
|
|
836
|
+
const conflictClause = this.buildConflictClause();
|
|
837
|
+
const finalQuery = `${this.query} (${columnNames.join(
|
|
838
|
+
", "
|
|
839
|
+
)}) VALUES ${valuesSql}${conflictClause}`;
|
|
840
|
+
const params = processedDataSets.flatMap(
|
|
841
|
+
(data) => columns.map((col) => data[col] ?? null)
|
|
842
|
+
);
|
|
843
|
+
if (this.onConflictAction === "update") {
|
|
844
|
+
const setValues = Object.entries(this.updateSet).map(
|
|
845
|
+
([, value]) => value
|
|
846
|
+
);
|
|
847
|
+
params.push(...setValues);
|
|
848
|
+
}
|
|
849
|
+
if (this.returningColumns.length > 0) {
|
|
850
|
+
const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
|
|
851
|
+
return {
|
|
852
|
+
sql: `${finalQuery} RETURNING ${returningNames}`,
|
|
853
|
+
params
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
return { sql: finalQuery, params };
|
|
857
|
+
}
|
|
519
858
|
};
|
|
520
859
|
|
|
521
860
|
// src/builders/delete.ts
|
|
@@ -526,11 +865,24 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
|
|
|
526
865
|
this.query = `DELETE FROM ${table._.name}`;
|
|
527
866
|
}
|
|
528
867
|
returningColumns = [];
|
|
868
|
+
hasWhereClause = false;
|
|
869
|
+
allowGlobal = false;
|
|
870
|
+
where(condition) {
|
|
871
|
+
this.hasWhereClause = true;
|
|
872
|
+
return super.where(condition);
|
|
873
|
+
}
|
|
874
|
+
allowGlobalOperation() {
|
|
875
|
+
this.allowGlobal = true;
|
|
876
|
+
return this;
|
|
877
|
+
}
|
|
529
878
|
returning(...columns) {
|
|
530
879
|
this.returningColumns.push(...columns);
|
|
531
880
|
return this;
|
|
532
881
|
}
|
|
533
882
|
async execute() {
|
|
883
|
+
if (!this.hasWhereClause && !this.allowGlobal) {
|
|
884
|
+
throw new MissingWhereClauseError("DELETE", this.table._.name);
|
|
885
|
+
}
|
|
534
886
|
const { sql: sql2, params } = this.build();
|
|
535
887
|
if (this.returningColumns.length > 0) {
|
|
536
888
|
const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
|
|
@@ -545,6 +897,17 @@ var DeleteQueryBuilder = class extends BaseQueryBuilder {
|
|
|
545
897
|
const allColumns = Object.keys(this.table._.columns);
|
|
546
898
|
return this.returning(...allColumns).execute();
|
|
547
899
|
}
|
|
900
|
+
toSQL() {
|
|
901
|
+
const { sql: sql2, params } = this.build();
|
|
902
|
+
if (this.returningColumns.length > 0) {
|
|
903
|
+
const returningNames = this.returningColumns.map((col) => this.table._.columns[col]._.name).join(", ");
|
|
904
|
+
return {
|
|
905
|
+
sql: `${sql2} RETURNING ${returningNames}`,
|
|
906
|
+
params
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
return { sql: sql2, params };
|
|
910
|
+
}
|
|
548
911
|
};
|
|
549
912
|
|
|
550
913
|
// src/builders/with.ts
|
|
@@ -926,6 +1289,12 @@ var ManyRelation = class extends Relation {
|
|
|
926
1289
|
super(foreignTable);
|
|
927
1290
|
}
|
|
928
1291
|
};
|
|
1292
|
+
var ManyToManyRelation = class extends Relation {
|
|
1293
|
+
constructor(foreignTable, config) {
|
|
1294
|
+
super(foreignTable);
|
|
1295
|
+
this.config = config;
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
929
1298
|
var relations = (table, relationsCallback) => {
|
|
930
1299
|
const builtRelations = relationsCallback({
|
|
931
1300
|
one: (foreignTable, config) => {
|
|
@@ -933,6 +1302,9 @@ var relations = (table, relationsCallback) => {
|
|
|
933
1302
|
},
|
|
934
1303
|
many: (foreignTable) => {
|
|
935
1304
|
return new ManyRelation(foreignTable);
|
|
1305
|
+
},
|
|
1306
|
+
manyToMany: (foreignTable, config) => {
|
|
1307
|
+
return new ManyToManyRelation(foreignTable, config);
|
|
936
1308
|
}
|
|
937
1309
|
});
|
|
938
1310
|
for (const [name, relation] of Object.entries(builtRelations)) {
|
|
@@ -948,6 +1320,14 @@ var relations = (table, relationsCallback) => {
|
|
|
948
1320
|
type: "many",
|
|
949
1321
|
foreignTable: relation.foreignTable
|
|
950
1322
|
};
|
|
1323
|
+
} else if (relation instanceof ManyToManyRelation) {
|
|
1324
|
+
table.relations[name] = {
|
|
1325
|
+
type: "manyToMany",
|
|
1326
|
+
foreignTable: relation.foreignTable,
|
|
1327
|
+
junctionTable: relation.config.junctionTable,
|
|
1328
|
+
junctionFields: relation.config.junctionFields,
|
|
1329
|
+
junctionReferences: relation.config.junctionReferences
|
|
1330
|
+
};
|
|
951
1331
|
}
|
|
952
1332
|
}
|
|
953
1333
|
return builtRelations;
|
|
@@ -959,6 +1339,53 @@ var alias = (table, alias2) => {
|
|
|
959
1339
|
return table;
|
|
960
1340
|
};
|
|
961
1341
|
|
|
1342
|
+
// src/aggregates.ts
|
|
1343
|
+
var count = (column) => ({
|
|
1344
|
+
sql: `COUNT(${column ? column._.name : "*"})`,
|
|
1345
|
+
params: []
|
|
1346
|
+
});
|
|
1347
|
+
var countDistinct = (column) => ({
|
|
1348
|
+
sql: `COUNT(DISTINCT ${column._.name})`,
|
|
1349
|
+
params: []
|
|
1350
|
+
});
|
|
1351
|
+
var sum = (column) => ({
|
|
1352
|
+
sql: `SUM(${column._.name})`,
|
|
1353
|
+
params: []
|
|
1354
|
+
});
|
|
1355
|
+
var avg = (column) => ({
|
|
1356
|
+
sql: `AVG(${column._.name})`,
|
|
1357
|
+
params: []
|
|
1358
|
+
});
|
|
1359
|
+
var max = (column) => ({
|
|
1360
|
+
sql: `MAX(${column._.name})`,
|
|
1361
|
+
params: []
|
|
1362
|
+
});
|
|
1363
|
+
var min = (column) => ({
|
|
1364
|
+
sql: `MIN(${column._.name})`,
|
|
1365
|
+
params: []
|
|
1366
|
+
});
|
|
1367
|
+
var groupConcat = (column, separator = ",") => ({
|
|
1368
|
+
sql: `GROUP_CONCAT(${column._.name}, ?)`,
|
|
1369
|
+
params: [separator]
|
|
1370
|
+
});
|
|
1371
|
+
var as = (aggregate, alias2) => ({
|
|
1372
|
+
...aggregate,
|
|
1373
|
+
alias: alias2
|
|
1374
|
+
});
|
|
1375
|
+
|
|
1376
|
+
// src/subquery.ts
|
|
1377
|
+
var subquery = (query) => {
|
|
1378
|
+
const { sql: sql2, params } = query.toSQL();
|
|
1379
|
+
return {
|
|
1380
|
+
sql: `(${sql2})`,
|
|
1381
|
+
params,
|
|
1382
|
+
_isSubquery: true
|
|
1383
|
+
};
|
|
1384
|
+
};
|
|
1385
|
+
var scalarSubquery = (query) => {
|
|
1386
|
+
return subquery(query);
|
|
1387
|
+
};
|
|
1388
|
+
|
|
962
1389
|
// src/column-helpers.ts
|
|
963
1390
|
var text = (name, config) => new SQLiteColumn(name, "TEXT", config, config?.mode);
|
|
964
1391
|
var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
|
|
@@ -969,47 +1396,77 @@ var numeric = (name, config) => new SQLiteColumn(name, "NUMERIC", {}, config?.mo
|
|
|
969
1396
|
var enumType = (name, values) => text(name, { enum: values });
|
|
970
1397
|
export {
|
|
971
1398
|
BaseQueryBuilder,
|
|
1399
|
+
ColumnNotFoundError,
|
|
972
1400
|
DeleteQueryBuilder,
|
|
973
1401
|
InsertQueryBuilder,
|
|
1402
|
+
InsertValidationError,
|
|
974
1403
|
ManyRelation,
|
|
1404
|
+
ManyToManyRelation,
|
|
1405
|
+
MigrationError,
|
|
1406
|
+
MissingWhereClauseError,
|
|
975
1407
|
OneRelation,
|
|
1408
|
+
QueryBuilderError,
|
|
976
1409
|
Relation,
|
|
1410
|
+
RelationError,
|
|
977
1411
|
SQLiteColumn,
|
|
978
1412
|
SelectQueryBuilder,
|
|
979
1413
|
Table,
|
|
1414
|
+
TableNotFoundError,
|
|
980
1415
|
TauriORM,
|
|
1416
|
+
TauriORMError,
|
|
981
1417
|
UpdateQueryBuilder,
|
|
1418
|
+
UpdateValidationError,
|
|
1419
|
+
ValidationError,
|
|
982
1420
|
WithQueryBuilder,
|
|
983
1421
|
alias,
|
|
984
1422
|
and,
|
|
1423
|
+
as,
|
|
985
1424
|
asc,
|
|
986
1425
|
avg,
|
|
1426
|
+
between,
|
|
987
1427
|
blob,
|
|
988
1428
|
boolean,
|
|
1429
|
+
contains,
|
|
989
1430
|
count,
|
|
990
1431
|
countDistinct,
|
|
991
1432
|
desc,
|
|
1433
|
+
endsWith,
|
|
992
1434
|
enumType,
|
|
993
1435
|
eq,
|
|
1436
|
+
eqSubquery,
|
|
1437
|
+
exists,
|
|
994
1438
|
getTableColumns,
|
|
1439
|
+
groupConcat,
|
|
995
1440
|
gt,
|
|
1441
|
+
gtSubquery,
|
|
996
1442
|
gte,
|
|
1443
|
+
gteSubquery,
|
|
1444
|
+
ilike,
|
|
997
1445
|
inArray,
|
|
998
1446
|
integer,
|
|
999
1447
|
isNotNull,
|
|
1000
1448
|
isNull,
|
|
1001
1449
|
like,
|
|
1002
1450
|
lt,
|
|
1451
|
+
ltSubquery,
|
|
1003
1452
|
lte,
|
|
1453
|
+
lteSubquery,
|
|
1004
1454
|
max,
|
|
1005
1455
|
min,
|
|
1456
|
+
ne,
|
|
1457
|
+
neSubquery,
|
|
1006
1458
|
not,
|
|
1459
|
+
notExists,
|
|
1460
|
+
notIn,
|
|
1007
1461
|
numeric,
|
|
1008
1462
|
or,
|
|
1009
1463
|
real,
|
|
1010
1464
|
relations,
|
|
1465
|
+
scalarSubquery,
|
|
1011
1466
|
sql,
|
|
1012
1467
|
sqliteTable,
|
|
1468
|
+
startsWith,
|
|
1469
|
+
subquery,
|
|
1013
1470
|
sum,
|
|
1014
1471
|
text
|
|
1015
1472
|
};
|