@type32/tauri-sqlite-orm 0.1.20 → 0.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 +76 -0
- package/dist/index.d.mts +136 -11
- package/dist/index.d.ts +136 -11
- package/dist/index.js +580 -91
- package/dist/index.mjs +551 -92
- package/package.json +38 -36
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
|
|
@@ -630,6 +993,8 @@ var SQLiteColumn = class _SQLiteColumn {
|
|
|
630
993
|
return new _SQLiteColumn(this._.name, this.type, { ...this.options, unique: true }, this._.mode);
|
|
631
994
|
}
|
|
632
995
|
references(ref, column) {
|
|
996
|
+
const columnKey = typeof column === "string" ? column : column._.name;
|
|
997
|
+
const columnObj = typeof column === "string" ? ref._.columns[column] : column;
|
|
633
998
|
return new _SQLiteColumn(
|
|
634
999
|
this._.name,
|
|
635
1000
|
this.type,
|
|
@@ -637,7 +1002,7 @@ var SQLiteColumn = class _SQLiteColumn {
|
|
|
637
1002
|
...this.options,
|
|
638
1003
|
references: {
|
|
639
1004
|
table: ref,
|
|
640
|
-
column:
|
|
1005
|
+
column: columnObj
|
|
641
1006
|
}
|
|
642
1007
|
},
|
|
643
1008
|
this._.mode
|
|
@@ -926,6 +1291,12 @@ var ManyRelation = class extends Relation {
|
|
|
926
1291
|
super(foreignTable);
|
|
927
1292
|
}
|
|
928
1293
|
};
|
|
1294
|
+
var ManyToManyRelation = class extends Relation {
|
|
1295
|
+
constructor(foreignTable, config) {
|
|
1296
|
+
super(foreignTable);
|
|
1297
|
+
this.config = config;
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
929
1300
|
var relations = (table, relationsCallback) => {
|
|
930
1301
|
const builtRelations = relationsCallback({
|
|
931
1302
|
one: (foreignTable, config) => {
|
|
@@ -933,6 +1304,9 @@ var relations = (table, relationsCallback) => {
|
|
|
933
1304
|
},
|
|
934
1305
|
many: (foreignTable) => {
|
|
935
1306
|
return new ManyRelation(foreignTable);
|
|
1307
|
+
},
|
|
1308
|
+
manyToMany: (foreignTable, config) => {
|
|
1309
|
+
return new ManyToManyRelation(foreignTable, config);
|
|
936
1310
|
}
|
|
937
1311
|
});
|
|
938
1312
|
for (const [name, relation] of Object.entries(builtRelations)) {
|
|
@@ -948,6 +1322,14 @@ var relations = (table, relationsCallback) => {
|
|
|
948
1322
|
type: "many",
|
|
949
1323
|
foreignTable: relation.foreignTable
|
|
950
1324
|
};
|
|
1325
|
+
} else if (relation instanceof ManyToManyRelation) {
|
|
1326
|
+
table.relations[name] = {
|
|
1327
|
+
type: "manyToMany",
|
|
1328
|
+
foreignTable: relation.foreignTable,
|
|
1329
|
+
junctionTable: relation.config.junctionTable,
|
|
1330
|
+
junctionFields: relation.config.junctionFields,
|
|
1331
|
+
junctionReferences: relation.config.junctionReferences
|
|
1332
|
+
};
|
|
951
1333
|
}
|
|
952
1334
|
}
|
|
953
1335
|
return builtRelations;
|
|
@@ -959,6 +1341,53 @@ var alias = (table, alias2) => {
|
|
|
959
1341
|
return table;
|
|
960
1342
|
};
|
|
961
1343
|
|
|
1344
|
+
// src/aggregates.ts
|
|
1345
|
+
var count = (column) => ({
|
|
1346
|
+
sql: `COUNT(${column ? column._.name : "*"})`,
|
|
1347
|
+
params: []
|
|
1348
|
+
});
|
|
1349
|
+
var countDistinct = (column) => ({
|
|
1350
|
+
sql: `COUNT(DISTINCT ${column._.name})`,
|
|
1351
|
+
params: []
|
|
1352
|
+
});
|
|
1353
|
+
var sum = (column) => ({
|
|
1354
|
+
sql: `SUM(${column._.name})`,
|
|
1355
|
+
params: []
|
|
1356
|
+
});
|
|
1357
|
+
var avg = (column) => ({
|
|
1358
|
+
sql: `AVG(${column._.name})`,
|
|
1359
|
+
params: []
|
|
1360
|
+
});
|
|
1361
|
+
var max = (column) => ({
|
|
1362
|
+
sql: `MAX(${column._.name})`,
|
|
1363
|
+
params: []
|
|
1364
|
+
});
|
|
1365
|
+
var min = (column) => ({
|
|
1366
|
+
sql: `MIN(${column._.name})`,
|
|
1367
|
+
params: []
|
|
1368
|
+
});
|
|
1369
|
+
var groupConcat = (column, separator = ",") => ({
|
|
1370
|
+
sql: `GROUP_CONCAT(${column._.name}, ?)`,
|
|
1371
|
+
params: [separator]
|
|
1372
|
+
});
|
|
1373
|
+
var as = (aggregate, alias2) => ({
|
|
1374
|
+
...aggregate,
|
|
1375
|
+
alias: alias2
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
// src/subquery.ts
|
|
1379
|
+
var subquery = (query) => {
|
|
1380
|
+
const { sql: sql2, params } = query.toSQL();
|
|
1381
|
+
return {
|
|
1382
|
+
sql: `(${sql2})`,
|
|
1383
|
+
params,
|
|
1384
|
+
_isSubquery: true
|
|
1385
|
+
};
|
|
1386
|
+
};
|
|
1387
|
+
var scalarSubquery = (query) => {
|
|
1388
|
+
return subquery(query);
|
|
1389
|
+
};
|
|
1390
|
+
|
|
962
1391
|
// src/column-helpers.ts
|
|
963
1392
|
var text = (name, config) => new SQLiteColumn(name, "TEXT", config, config?.mode);
|
|
964
1393
|
var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
|
|
@@ -969,47 +1398,77 @@ var numeric = (name, config) => new SQLiteColumn(name, "NUMERIC", {}, config?.mo
|
|
|
969
1398
|
var enumType = (name, values) => text(name, { enum: values });
|
|
970
1399
|
export {
|
|
971
1400
|
BaseQueryBuilder,
|
|
1401
|
+
ColumnNotFoundError,
|
|
972
1402
|
DeleteQueryBuilder,
|
|
973
1403
|
InsertQueryBuilder,
|
|
1404
|
+
InsertValidationError,
|
|
974
1405
|
ManyRelation,
|
|
1406
|
+
ManyToManyRelation,
|
|
1407
|
+
MigrationError,
|
|
1408
|
+
MissingWhereClauseError,
|
|
975
1409
|
OneRelation,
|
|
1410
|
+
QueryBuilderError,
|
|
976
1411
|
Relation,
|
|
1412
|
+
RelationError,
|
|
977
1413
|
SQLiteColumn,
|
|
978
1414
|
SelectQueryBuilder,
|
|
979
1415
|
Table,
|
|
1416
|
+
TableNotFoundError,
|
|
980
1417
|
TauriORM,
|
|
1418
|
+
TauriORMError,
|
|
981
1419
|
UpdateQueryBuilder,
|
|
1420
|
+
UpdateValidationError,
|
|
1421
|
+
ValidationError,
|
|
982
1422
|
WithQueryBuilder,
|
|
983
1423
|
alias,
|
|
984
1424
|
and,
|
|
1425
|
+
as,
|
|
985
1426
|
asc,
|
|
986
1427
|
avg,
|
|
1428
|
+
between,
|
|
987
1429
|
blob,
|
|
988
1430
|
boolean,
|
|
1431
|
+
contains,
|
|
989
1432
|
count,
|
|
990
1433
|
countDistinct,
|
|
991
1434
|
desc,
|
|
1435
|
+
endsWith,
|
|
992
1436
|
enumType,
|
|
993
1437
|
eq,
|
|
1438
|
+
eqSubquery,
|
|
1439
|
+
exists,
|
|
994
1440
|
getTableColumns,
|
|
1441
|
+
groupConcat,
|
|
995
1442
|
gt,
|
|
1443
|
+
gtSubquery,
|
|
996
1444
|
gte,
|
|
1445
|
+
gteSubquery,
|
|
1446
|
+
ilike,
|
|
997
1447
|
inArray,
|
|
998
1448
|
integer,
|
|
999
1449
|
isNotNull,
|
|
1000
1450
|
isNull,
|
|
1001
1451
|
like,
|
|
1002
1452
|
lt,
|
|
1453
|
+
ltSubquery,
|
|
1003
1454
|
lte,
|
|
1455
|
+
lteSubquery,
|
|
1004
1456
|
max,
|
|
1005
1457
|
min,
|
|
1458
|
+
ne,
|
|
1459
|
+
neSubquery,
|
|
1006
1460
|
not,
|
|
1461
|
+
notExists,
|
|
1462
|
+
notIn,
|
|
1007
1463
|
numeric,
|
|
1008
1464
|
or,
|
|
1009
1465
|
real,
|
|
1010
1466
|
relations,
|
|
1467
|
+
scalarSubquery,
|
|
1011
1468
|
sql,
|
|
1012
1469
|
sqliteTable,
|
|
1470
|
+
startsWith,
|
|
1471
|
+
subquery,
|
|
1013
1472
|
sum,
|
|
1014
1473
|
text
|
|
1015
1474
|
};
|