@type32/tauri-sqlite-orm 0.1.16 → 0.1.18-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 +109 -190
- package/dist/index.d.mts +131 -431
- package/dist/index.d.ts +131 -431
- package/dist/index.js +308 -1665
- package/dist/index.mjs +298 -1627
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,1267 +1,354 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return { raw: raw2 };
|
|
8
|
-
}
|
|
9
|
-
function createColumn(params) {
|
|
10
|
-
const col = { ...params };
|
|
11
|
-
col.primaryKey = (opts) => {
|
|
12
|
-
col.isPrimaryKey = true;
|
|
13
|
-
if (opts?.autoIncrement) col.autoIncrement = true;
|
|
14
|
-
return col;
|
|
15
|
-
};
|
|
16
|
-
col.notNull = () => {
|
|
17
|
-
col.isNotNull = true;
|
|
18
|
-
return col;
|
|
19
|
-
};
|
|
20
|
-
col.default = (value) => {
|
|
21
|
-
col.defaultValue = value;
|
|
22
|
-
return col;
|
|
23
|
-
};
|
|
24
|
-
col.$type = () => col;
|
|
25
|
-
col.$defaultFn = (fn) => {
|
|
26
|
-
col.defaultFn = fn;
|
|
27
|
-
return col;
|
|
28
|
-
};
|
|
29
|
-
col.$default = (fn) => {
|
|
30
|
-
col.defaultFn = fn;
|
|
31
|
-
return col;
|
|
32
|
-
};
|
|
33
|
-
col.$onUpdate = (fn) => {
|
|
34
|
-
col.onUpdateFn = fn;
|
|
35
|
-
return col;
|
|
36
|
-
};
|
|
37
|
-
col.$onUpdateFn = (fn) => {
|
|
38
|
-
col.onUpdateFn = fn;
|
|
39
|
-
return col;
|
|
40
|
-
};
|
|
41
|
-
col.references = (target, actions) => {
|
|
42
|
-
const t = target();
|
|
43
|
-
col.references = {
|
|
44
|
-
table: t.tableName,
|
|
45
|
-
column: t.name,
|
|
46
|
-
onDelete: actions?.onDelete,
|
|
47
|
-
onUpdate: actions?.onUpdate
|
|
48
|
-
};
|
|
49
|
-
return col;
|
|
50
|
-
};
|
|
51
|
-
return col;
|
|
52
|
-
}
|
|
53
|
-
function text(nameOrConfig, maybeConfig) {
|
|
54
|
-
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
55
|
-
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
56
|
-
const col = createColumn({
|
|
57
|
-
name,
|
|
58
|
-
type: "TEXT",
|
|
59
|
-
_dataType: ""
|
|
60
|
-
});
|
|
61
|
-
if (config?.enum) col.enumValues = config.enum;
|
|
62
|
-
if (config?.mode) col.mode = config.mode;
|
|
63
|
-
return col;
|
|
64
|
-
}
|
|
65
|
-
function integer(nameOrConfig, maybeConfig) {
|
|
66
|
-
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
67
|
-
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
68
|
-
let dt = 0;
|
|
69
|
-
if (config?.mode === "boolean") dt = false;
|
|
70
|
-
if (config?.mode === "timestamp" || config?.mode === "timestamp_ms")
|
|
71
|
-
dt = /* @__PURE__ */ new Date();
|
|
72
|
-
const col = createColumn({
|
|
73
|
-
name,
|
|
74
|
-
type: "INTEGER",
|
|
75
|
-
mode: config?.mode ?? "number",
|
|
76
|
-
_dataType: dt
|
|
77
|
-
});
|
|
78
|
-
return col;
|
|
79
|
-
}
|
|
80
|
-
function real(name) {
|
|
81
|
-
return createColumn({
|
|
82
|
-
name: name ?? "",
|
|
83
|
-
type: "REAL",
|
|
84
|
-
_dataType: 0
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
function blob(nameOrConfig, maybeConfig) {
|
|
88
|
-
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
89
|
-
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
90
|
-
let dt = new Uint8Array();
|
|
91
|
-
if (config?.mode === "bigint") dt = 0n;
|
|
92
|
-
if (config?.mode === "json") dt = void 0;
|
|
93
|
-
return createColumn({
|
|
94
|
-
name,
|
|
95
|
-
type: "BLOB",
|
|
96
|
-
mode: config?.mode,
|
|
97
|
-
_dataType: dt
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
function numeric(nameOrConfig, maybeConfig) {
|
|
101
|
-
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
102
|
-
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
103
|
-
let dt = "";
|
|
104
|
-
if (config?.mode === "number") dt = 0;
|
|
105
|
-
if (config?.mode === "bigint") dt = 0n;
|
|
106
|
-
return createColumn({
|
|
107
|
-
name,
|
|
108
|
-
type: "NUMERIC",
|
|
109
|
-
mode: config?.mode,
|
|
110
|
-
_dataType: dt
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
function boolean(name) {
|
|
114
|
-
return createColumn({
|
|
115
|
-
name: name ?? "",
|
|
116
|
-
type: "INTEGER",
|
|
117
|
-
_dataType: false,
|
|
118
|
-
mode: "boolean"
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
function timestamp(name) {
|
|
122
|
-
return createColumn({
|
|
123
|
-
name: name ?? "",
|
|
124
|
-
type: "INTEGER",
|
|
125
|
-
_dataType: /* @__PURE__ */ new Date(),
|
|
126
|
-
mode: "timestamp"
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
function increments(name) {
|
|
130
|
-
return integer(name ?? "").primaryKey({
|
|
131
|
-
autoIncrement: true
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
function unique(name) {
|
|
135
|
-
return {
|
|
136
|
-
on: (...cols) => ({
|
|
137
|
-
name,
|
|
138
|
-
columns: cols.map((c) => c.name),
|
|
139
|
-
// runtime marker for DDL rendering
|
|
140
|
-
kind: "unique"
|
|
141
|
-
})
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
function primaryKey(opts) {
|
|
145
|
-
return {
|
|
146
|
-
name: opts.name,
|
|
147
|
-
columns: opts.columns.map((c) => c.name),
|
|
148
|
-
// runtime marker for DDL rendering
|
|
149
|
-
kind: "primaryKey"
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
function check(name, expr) {
|
|
153
|
-
return { name, expr };
|
|
154
|
-
}
|
|
155
|
-
function foreignKey(opts) {
|
|
156
|
-
const first = opts.columns[0];
|
|
157
|
-
return {
|
|
158
|
-
name: opts.name,
|
|
159
|
-
columns: opts.columns.map((c) => c.name),
|
|
160
|
-
foreignTable: first?.tableName || opts.foreignColumns[0]?.tableName || "",
|
|
161
|
-
foreignColumns: opts.foreignColumns.map((c) => c.name),
|
|
162
|
-
onDelete: opts.onDelete,
|
|
163
|
-
onUpdate: opts.onUpdate
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function index(name) {
|
|
167
|
-
return {
|
|
168
|
-
on: (...cols) => ({
|
|
169
|
-
name,
|
|
170
|
-
columns: cols.map((c) => c.name)
|
|
171
|
-
}),
|
|
172
|
-
where: (expr) => ({ name, columns: [], where: expr })
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function uniqueIndex(name) {
|
|
176
|
-
return {
|
|
177
|
-
on: (...cols) => ({
|
|
178
|
-
name,
|
|
179
|
-
columns: cols.map((c) => c.name),
|
|
180
|
-
unique: true
|
|
181
|
-
}),
|
|
182
|
-
where: (expr) => ({
|
|
1
|
+
// src/orm.ts
|
|
2
|
+
var SQLiteColumn = class _SQLiteColumn {
|
|
3
|
+
constructor(name, type, options = {}, mode) {
|
|
4
|
+
this.type = type;
|
|
5
|
+
this.options = options;
|
|
6
|
+
this._ = {
|
|
183
7
|
name,
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
function defineTable(tableName, schema, extras) {
|
|
191
|
-
const finalizedSchema = { ...schema };
|
|
192
|
-
for (const key of Object.keys(finalizedSchema)) {
|
|
193
|
-
const col = finalizedSchema[key];
|
|
194
|
-
if (!col.name || col.name === "") col.name = key;
|
|
195
|
-
col.tableName = tableName;
|
|
8
|
+
dataType: type,
|
|
9
|
+
mode: mode || "default",
|
|
10
|
+
notNull: options.notNull ?? false,
|
|
11
|
+
hasDefault: options.default !== void 0 || options.$defaultFn !== void 0,
|
|
12
|
+
autoincrement: options.autoincrement ?? false
|
|
13
|
+
};
|
|
196
14
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// omit PK columns
|
|
206
|
-
};
|
|
207
|
-
for (const [key, col] of Object.entries(finalizedSchema)) {
|
|
208
|
-
table[key] = col;
|
|
15
|
+
_;
|
|
16
|
+
notNull() {
|
|
17
|
+
return new _SQLiteColumn(
|
|
18
|
+
this._.name,
|
|
19
|
+
this.type,
|
|
20
|
+
{ ...this.options, notNull: true },
|
|
21
|
+
this._.mode
|
|
22
|
+
);
|
|
209
23
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
} else if (s.columns && (s.name || s.name === void 0)) {
|
|
218
|
-
if (s.columns && s.name !== void 0 && s.columns.length > 0) {
|
|
219
|
-
const pk = s;
|
|
220
|
-
if (pk.columns.length > 1 || pk.name && pk.name.length > 0) {
|
|
221
|
-
table._constraints.push(s);
|
|
222
|
-
} else {
|
|
223
|
-
table._constraints.push(s);
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
table._constraints.push(s);
|
|
227
|
-
}
|
|
228
|
-
} else if (s.expr) {
|
|
229
|
-
table._constraints.push(s);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
24
|
+
default(value) {
|
|
25
|
+
return new _SQLiteColumn(
|
|
26
|
+
this._.name,
|
|
27
|
+
this.type,
|
|
28
|
+
{ ...this.options, default: value },
|
|
29
|
+
this._.mode
|
|
30
|
+
);
|
|
232
31
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
32
|
+
$defaultFn(fn) {
|
|
33
|
+
return new _SQLiteColumn(
|
|
34
|
+
this._.name,
|
|
35
|
+
this.type,
|
|
36
|
+
{ ...this.options, $defaultFn: fn },
|
|
37
|
+
this._.mode
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
primaryKey() {
|
|
41
|
+
return new _SQLiteColumn(
|
|
42
|
+
this._.name,
|
|
43
|
+
this.type,
|
|
44
|
+
{ ...this.options, primaryKey: true },
|
|
45
|
+
this._.mode
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
autoincrement() {
|
|
49
|
+
return new _SQLiteColumn(
|
|
50
|
+
this._.name,
|
|
51
|
+
this.type,
|
|
52
|
+
{ ...this.options, autoincrement: true },
|
|
53
|
+
this._.mode
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
unique() {
|
|
57
|
+
return new _SQLiteColumn(
|
|
58
|
+
this._.name,
|
|
59
|
+
this.type,
|
|
60
|
+
{ ...this.options, unique: true },
|
|
61
|
+
this._.mode
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
references(ref, column) {
|
|
65
|
+
return new _SQLiteColumn(
|
|
66
|
+
this._.name,
|
|
67
|
+
this.type,
|
|
68
|
+
{
|
|
69
|
+
...this.options,
|
|
70
|
+
references: {
|
|
71
|
+
table: ref,
|
|
72
|
+
column: ref._.columns[column]
|
|
259
73
|
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
function isColumn(value) {
|
|
266
|
-
return typeof value === "object" && value !== null && "_dataType" in value;
|
|
267
|
-
}
|
|
268
|
-
function getQualifiedName(column) {
|
|
269
|
-
if (column.tableName) return `${column.tableName}.${column.name}`;
|
|
270
|
-
return column.name;
|
|
271
|
-
}
|
|
272
|
-
function comparison(operator, column, value) {
|
|
273
|
-
return {
|
|
274
|
-
toSQL: () => {
|
|
275
|
-
if (isColumn(value)) {
|
|
276
|
-
return {
|
|
277
|
-
clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
|
|
278
|
-
value
|
|
279
|
-
)}`,
|
|
280
|
-
bindings: []
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
clause: `${getQualifiedName(column)} ${operator} ?`,
|
|
285
|
-
bindings: [value]
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
var and = (...conditions) => ({
|
|
291
|
-
toSQL: () => {
|
|
292
|
-
const parts = [];
|
|
293
|
-
const bindings = [];
|
|
294
|
-
for (const c of conditions) {
|
|
295
|
-
const s = c.toSQL();
|
|
296
|
-
parts.push(`(${s.clause})`);
|
|
297
|
-
bindings.push(...s.bindings);
|
|
298
|
-
}
|
|
299
|
-
return { clause: parts.join(" AND "), bindings };
|
|
74
|
+
},
|
|
75
|
+
this._.mode
|
|
76
|
+
);
|
|
300
77
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
parts.push(`(${s.clause})`);
|
|
309
|
-
bindings.push(...s.bindings);
|
|
310
|
-
}
|
|
311
|
-
return { clause: parts.join(" OR "), bindings };
|
|
78
|
+
$onUpdateFn(fn) {
|
|
79
|
+
return new _SQLiteColumn(
|
|
80
|
+
this._.name,
|
|
81
|
+
this.type,
|
|
82
|
+
{ ...this.options, $onUpdateFn: fn },
|
|
83
|
+
this._.mode
|
|
84
|
+
);
|
|
312
85
|
}
|
|
313
|
-
}
|
|
314
|
-
var
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
86
|
+
};
|
|
87
|
+
var text = (name) => new SQLiteColumn(name, "TEXT");
|
|
88
|
+
var integer = (name, config) => new SQLiteColumn(name, "INTEGER", {}, config?.mode || "default");
|
|
89
|
+
var real = (name) => new SQLiteColumn(name, "REAL");
|
|
90
|
+
var blob = (name) => new SQLiteColumn(name, "BLOB");
|
|
91
|
+
var boolean = (name) => new SQLiteColumn(name, "BOOLEAN");
|
|
92
|
+
var Table = class {
|
|
93
|
+
_;
|
|
94
|
+
constructor(name, columns) {
|
|
95
|
+
this._ = {
|
|
96
|
+
name,
|
|
97
|
+
columns
|
|
98
|
+
};
|
|
318
99
|
}
|
|
100
|
+
};
|
|
101
|
+
var sqliteTable = (tableName, columns) => {
|
|
102
|
+
return new Table(tableName, columns);
|
|
103
|
+
};
|
|
104
|
+
var eq = (column, value) => ({
|
|
105
|
+
sql: `${column._.name} = ?`,
|
|
106
|
+
params: [value]
|
|
319
107
|
});
|
|
320
|
-
var
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
var gte = (column, value) => comparison(">=", column, value);
|
|
324
|
-
var lt = (column, value) => comparison("<", column, value);
|
|
325
|
-
var lte = (column, value) => comparison("<=", column, value);
|
|
326
|
-
var like = (column, value) => comparison("LIKE", column, value);
|
|
327
|
-
var ilike = (column, value) => ({
|
|
328
|
-
toSQL: () => {
|
|
329
|
-
const colExpr = `LOWER(${getQualifiedName(column)})`;
|
|
330
|
-
if (isColumn(value)) {
|
|
331
|
-
return {
|
|
332
|
-
clause: `${colExpr} LIKE LOWER(${getQualifiedName(value)})`,
|
|
333
|
-
bindings: []
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
return { clause: `${colExpr} LIKE LOWER(?)`, bindings: [value] };
|
|
337
|
-
}
|
|
108
|
+
var and = (...conditions) => ({
|
|
109
|
+
sql: conditions.map((c) => `(${c.sql})`).join(" AND "),
|
|
110
|
+
params: conditions.flatMap((c) => c.params)
|
|
338
111
|
});
|
|
339
|
-
var
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if (isColumn(value)) {
|
|
343
|
-
return {
|
|
344
|
-
clause: `${colExpr} NOT LIKE LOWER(${getQualifiedName(value)})`,
|
|
345
|
-
bindings: []
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
return { clause: `${colExpr} NOT LIKE LOWER(?)`, bindings: [value] };
|
|
349
|
-
}
|
|
112
|
+
var or = (...conditions) => ({
|
|
113
|
+
sql: conditions.map((c) => `(${c.sql})`).join(" OR "),
|
|
114
|
+
params: conditions.flatMap((c) => c.params)
|
|
350
115
|
});
|
|
351
|
-
var
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
bindings: []
|
|
355
|
-
})
|
|
116
|
+
var gt = (column, value) => ({
|
|
117
|
+
sql: `${column._.name} > ?`,
|
|
118
|
+
params: [value]
|
|
356
119
|
});
|
|
357
|
-
var
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
bindings: []
|
|
361
|
-
})
|
|
120
|
+
var gte = (column, value) => ({
|
|
121
|
+
sql: `${column._.name} >= ?`,
|
|
122
|
+
params: [value]
|
|
362
123
|
});
|
|
363
|
-
var
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
|
|
367
|
-
const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
|
|
368
|
-
return {
|
|
369
|
-
clause: `${left} BETWEEN ${fromClause} AND ${toClause}`,
|
|
370
|
-
bindings: [...fromBindings, ...toBindings]
|
|
371
|
-
};
|
|
372
|
-
}
|
|
124
|
+
var lt = (column, value) => ({
|
|
125
|
+
sql: `${column._.name} < ?`,
|
|
126
|
+
params: [value]
|
|
373
127
|
});
|
|
374
|
-
var
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
|
|
378
|
-
const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
|
|
379
|
-
return {
|
|
380
|
-
clause: `${left} NOT BETWEEN ${fromClause} AND ${toClause}`,
|
|
381
|
-
bindings: [...fromBindings, ...toBindings]
|
|
382
|
-
};
|
|
383
|
-
}
|
|
128
|
+
var lte = (column, value) => ({
|
|
129
|
+
sql: `${column._.name} <= ?`,
|
|
130
|
+
params: [value]
|
|
384
131
|
});
|
|
385
|
-
var
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if (Array.isArray(valuesOrQuery)) {
|
|
389
|
-
const placeholders = valuesOrQuery.map(() => "?").join(", ");
|
|
390
|
-
return {
|
|
391
|
-
clause: `${left} IN (${placeholders})`,
|
|
392
|
-
bindings: valuesOrQuery
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
|
|
396
|
-
return { clause: `${left} IN (${sq.clause})`, bindings: sq.bindings };
|
|
397
|
-
}
|
|
132
|
+
var like = (column, pattern) => ({
|
|
133
|
+
sql: `${column._.name} LIKE ?`,
|
|
134
|
+
params: [pattern]
|
|
398
135
|
});
|
|
399
|
-
var
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (Array.isArray(valuesOrQuery)) {
|
|
403
|
-
const placeholders = valuesOrQuery.map(() => "?").join(", ");
|
|
404
|
-
return {
|
|
405
|
-
clause: `${left} NOT IN (${placeholders})`,
|
|
406
|
-
bindings: valuesOrQuery
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
|
|
410
|
-
return { clause: `${left} NOT IN (${sq.clause})`, bindings: sq.bindings };
|
|
411
|
-
}
|
|
136
|
+
var isNull = (column) => ({
|
|
137
|
+
sql: `${column._.name} IS NULL`,
|
|
138
|
+
params: []
|
|
412
139
|
});
|
|
413
|
-
var
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return { clause: `EXISTS (${sq.clause})`, bindings: sq.bindings };
|
|
417
|
-
}
|
|
140
|
+
var isNotNull = (column) => ({
|
|
141
|
+
sql: `${column._.name} IS NOT NULL`,
|
|
142
|
+
params: []
|
|
418
143
|
});
|
|
419
|
-
var
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
return { clause: `NOT EXISTS (${sq.clause})`, bindings: sq.bindings };
|
|
423
|
-
}
|
|
144
|
+
var inArray = (column, values) => ({
|
|
145
|
+
sql: `${column._.name} IN (${values.map(() => "?").join(",")})`,
|
|
146
|
+
params: values
|
|
424
147
|
});
|
|
425
|
-
var
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
_table = null;
|
|
435
|
-
_selectedColumns = [];
|
|
436
|
-
_joins = [];
|
|
437
|
-
_where = [];
|
|
438
|
-
_orderBy = [];
|
|
439
|
-
_limit = null;
|
|
440
|
-
_offset = null;
|
|
441
|
-
_groupBy = [];
|
|
442
|
-
_having = [];
|
|
443
|
-
_distinct = false;
|
|
444
|
-
_dbProvider;
|
|
445
|
-
constructor(dbProvider, fields) {
|
|
446
|
-
this._dbProvider = dbProvider;
|
|
447
|
-
if (fields) {
|
|
448
|
-
for (const [alias, col] of Object.entries(fields)) {
|
|
449
|
-
const sql2 = getQualifiedName(col);
|
|
450
|
-
this._selectedColumns.push({ sql: sql2, alias });
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
distinct() {
|
|
455
|
-
this._distinct = true;
|
|
456
|
-
return this;
|
|
457
|
-
}
|
|
458
|
-
select(fields) {
|
|
459
|
-
this._selectedColumns = [];
|
|
460
|
-
for (const [alias, expr] of Object.entries(fields)) {
|
|
461
|
-
if (typeof expr.toSQL === "function") {
|
|
462
|
-
const s = expr.toSQL();
|
|
463
|
-
this._selectedColumns.push({ sql: s.clause, alias });
|
|
464
|
-
} else {
|
|
465
|
-
this._selectedColumns.push({
|
|
466
|
-
sql: getQualifiedName(expr),
|
|
467
|
-
alias
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
return this;
|
|
472
|
-
}
|
|
473
|
-
from(table) {
|
|
474
|
-
this._table = table;
|
|
148
|
+
var BaseQueryBuilder = class {
|
|
149
|
+
constructor(db) {
|
|
150
|
+
this.db = db;
|
|
151
|
+
}
|
|
152
|
+
query = "";
|
|
153
|
+
params = [];
|
|
154
|
+
where(condition) {
|
|
155
|
+
this.query += ` WHERE ${condition.sql}`;
|
|
156
|
+
this.params.push(...condition.params);
|
|
475
157
|
return this;
|
|
476
158
|
}
|
|
477
|
-
|
|
478
|
-
this.
|
|
159
|
+
orderBy(column, direction = "ASC") {
|
|
160
|
+
this.query += ` ORDER BY ${column._.name} ${direction}`;
|
|
479
161
|
return this;
|
|
480
162
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
const joinClause = `LEFT JOIN ${otherTable._tableName} ON ${onSql.clause}`;
|
|
484
|
-
this._joins.push(joinClause);
|
|
163
|
+
limit(count) {
|
|
164
|
+
this.query += ` LIMIT ${count}`;
|
|
485
165
|
return this;
|
|
486
166
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if (!e) continue;
|
|
490
|
-
if (typeof e === "string") this._groupBy.push(e);
|
|
491
|
-
else this._groupBy.push(getQualifiedName(e));
|
|
492
|
-
}
|
|
167
|
+
offset(count) {
|
|
168
|
+
this.query += ` OFFSET ${count}`;
|
|
493
169
|
return this;
|
|
494
170
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
171
|
+
build() {
|
|
172
|
+
return {
|
|
173
|
+
sql: this.query,
|
|
174
|
+
params: this.params
|
|
175
|
+
};
|
|
498
176
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
return this;
|
|
177
|
+
};
|
|
178
|
+
var SelectQueryBuilder = class extends BaseQueryBuilder {
|
|
179
|
+
constructor(db, table, columns) {
|
|
180
|
+
super(db);
|
|
181
|
+
this.table = table;
|
|
182
|
+
this.columns = columns;
|
|
183
|
+
const columnNames = columns ? columns.map((c) => table._.columns[c]._.name) : ["*"];
|
|
184
|
+
this.query = `SELECT ${columnNames.join(", ")} FROM ${table._.name}`;
|
|
508
185
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return this;
|
|
186
|
+
async execute() {
|
|
187
|
+
const { sql, params } = this.build();
|
|
188
|
+
return this.db.select(sql, ...params);
|
|
512
189
|
}
|
|
513
|
-
|
|
514
|
-
|
|
190
|
+
};
|
|
191
|
+
var InsertQueryBuilder = class extends BaseQueryBuilder {
|
|
192
|
+
constructor(db, table) {
|
|
193
|
+
super(db);
|
|
194
|
+
this.table = table;
|
|
195
|
+
this.query = `INSERT INTO ${table._.name}`;
|
|
196
|
+
}
|
|
197
|
+
dataSets = [];
|
|
198
|
+
values(data) {
|
|
199
|
+
const dataArray = Array.isArray(data) ? data : [data];
|
|
200
|
+
this.dataSets.push(...dataArray);
|
|
515
201
|
return this;
|
|
516
202
|
}
|
|
517
203
|
async execute() {
|
|
518
|
-
if (
|
|
519
|
-
throw new Error("
|
|
520
|
-
}
|
|
521
|
-
const db = await this._dbProvider();
|
|
522
|
-
const baseTableName = getTableName(this._table);
|
|
523
|
-
if (!baseTableName) {
|
|
524
|
-
throw new Error(
|
|
525
|
-
"Invalid table passed to select.from(): missing table name"
|
|
526
|
-
);
|
|
204
|
+
if (this.dataSets.length === 0) {
|
|
205
|
+
throw new Error("No data provided for insert");
|
|
527
206
|
}
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
if (this._having.length > 0) {
|
|
544
|
-
const havingClauses = this._having.map((h) => {
|
|
545
|
-
const sql2 = h.toSQL();
|
|
546
|
-
bindings.push(...sql2.bindings);
|
|
547
|
-
return `(${sql2.clause})`;
|
|
548
|
-
});
|
|
549
|
-
query += ` HAVING ${havingClauses.join(" AND ")}`;
|
|
550
|
-
}
|
|
551
|
-
if (this._orderBy.length > 0) {
|
|
552
|
-
const ordParts = [];
|
|
553
|
-
for (const ob of this._orderBy) {
|
|
554
|
-
if (typeof ob === "string") ordParts.push(ob);
|
|
555
|
-
else {
|
|
556
|
-
const s = ob.toSQL();
|
|
557
|
-
ordParts.push(s.clause);
|
|
558
|
-
bindings.push(...s.bindings);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
562
|
-
}
|
|
563
|
-
if (this._limit !== null) {
|
|
564
|
-
query += ` LIMIT ?`;
|
|
565
|
-
bindings.push(this._limit);
|
|
566
|
-
}
|
|
567
|
-
if (this._offset !== null) {
|
|
568
|
-
if (this._limit === null) query += ` LIMIT -1`;
|
|
569
|
-
query += ` OFFSET ?`;
|
|
570
|
-
bindings.push(this._offset);
|
|
571
|
-
}
|
|
572
|
-
return db.select(query, bindings);
|
|
573
|
-
}
|
|
574
|
-
async iterator() {
|
|
575
|
-
const rows = await this.execute();
|
|
576
|
-
async function* gen() {
|
|
577
|
-
for (const r of rows) yield r;
|
|
578
|
-
}
|
|
579
|
-
return gen();
|
|
207
|
+
const columns = Object.keys(
|
|
208
|
+
this.dataSets[0]
|
|
209
|
+
);
|
|
210
|
+
const columnNames = columns.map(
|
|
211
|
+
(c) => this.table._.columns[c]._.name
|
|
212
|
+
);
|
|
213
|
+
const placeholders = `(${columnNames.map(() => "?").join(", ")})`;
|
|
214
|
+
const valuesSql = this.dataSets.map(() => placeholders).join(", ");
|
|
215
|
+
this.query += ` (${columnNames.join(", ")}) VALUES ${valuesSql}`;
|
|
216
|
+
const params = this.dataSets.flatMap(
|
|
217
|
+
(data) => columns.map((col) => data[col])
|
|
218
|
+
);
|
|
219
|
+
const result = await this.db.execute(this.query, ...params);
|
|
220
|
+
return result.lastInsertId ?? 0;
|
|
580
221
|
}
|
|
581
222
|
};
|
|
582
|
-
var
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
async getDb() {
|
|
595
|
-
return this._dbPromise;
|
|
596
|
-
}
|
|
597
|
-
// Deprecated: use configure()
|
|
598
|
-
configureQuery(tables, relations2) {
|
|
599
|
-
this.configure(tables, relations2);
|
|
600
|
-
}
|
|
601
|
-
select(fields) {
|
|
602
|
-
return new SelectQueryBuilder(this.getDb.bind(this), fields);
|
|
223
|
+
var UpdateQueryBuilder = class extends BaseQueryBuilder {
|
|
224
|
+
constructor(db, table) {
|
|
225
|
+
super(db);
|
|
226
|
+
this.table = table;
|
|
227
|
+
this.query = `UPDATE ${table._.name}`;
|
|
228
|
+
}
|
|
229
|
+
updateData = {};
|
|
230
|
+
set(data) {
|
|
231
|
+
this.updateData = { ...this.updateData, ...data };
|
|
232
|
+
return this;
|
|
603
233
|
}
|
|
604
|
-
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
234
|
+
async execute() {
|
|
235
|
+
const entries = Object.entries(this.updateData);
|
|
236
|
+
const setClause = entries.map(([key]) => {
|
|
237
|
+
const column = this.table._.columns[key];
|
|
238
|
+
if (!column)
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Column ${key} does not exist on table ${this.table._.name}`
|
|
241
|
+
);
|
|
242
|
+
return `${column._.name} = ?`;
|
|
243
|
+
}).join(", ");
|
|
244
|
+
this.query += ` SET ${setClause}`;
|
|
245
|
+
this.params.push(...entries.map(([, value]) => value));
|
|
246
|
+
const { sql, params } = this.build();
|
|
247
|
+
const result = await this.db.execute(sql, ...params);
|
|
248
|
+
return result.rowsAffected;
|
|
608
249
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
_selectSql = null;
|
|
616
|
-
_conflict = null;
|
|
617
|
-
_returning = null;
|
|
618
|
-
values(rowOrRows) {
|
|
619
|
-
this._rows = Array.isArray(rowOrRows) ? rowOrRows : [rowOrRows];
|
|
620
|
-
return this;
|
|
621
|
-
}
|
|
622
|
-
select(qb) {
|
|
623
|
-
if (qb.toSQL) this._selectSql = qb.toSQL();
|
|
624
|
-
else this._selectSql = qb.toSQL();
|
|
625
|
-
return this;
|
|
626
|
-
}
|
|
627
|
-
returning(fields) {
|
|
628
|
-
this._returning = fields ?? {};
|
|
629
|
-
return this;
|
|
630
|
-
}
|
|
631
|
-
$returningId() {
|
|
632
|
-
this._returning = "__RETURNING_ID__";
|
|
633
|
-
return this;
|
|
634
|
-
}
|
|
635
|
-
onConflictDoNothing(opts) {
|
|
636
|
-
const target = opts?.target ? Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name : void 0;
|
|
637
|
-
this._conflict = {
|
|
638
|
-
kind: "doNothing",
|
|
639
|
-
target,
|
|
640
|
-
where: opts?.where
|
|
641
|
-
};
|
|
642
|
-
return this;
|
|
643
|
-
}
|
|
644
|
-
onConflictDoUpdate(opts) {
|
|
645
|
-
const target = Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name;
|
|
646
|
-
this._conflict = {
|
|
647
|
-
kind: "doUpdate",
|
|
648
|
-
target,
|
|
649
|
-
targetWhere: opts.targetWhere,
|
|
650
|
-
set: opts.set,
|
|
651
|
-
setWhere: opts.setWhere
|
|
652
|
-
};
|
|
653
|
-
return this;
|
|
654
|
-
}
|
|
655
|
-
async execute() {
|
|
656
|
-
const db = await self.getDb();
|
|
657
|
-
const tableName = getTableName(this._table);
|
|
658
|
-
if (!tableName)
|
|
659
|
-
throw new Error(
|
|
660
|
-
"Invalid table passed to insert(): missing table name"
|
|
661
|
-
);
|
|
662
|
-
if (this._selectSql) {
|
|
663
|
-
const cols = Object.keys(this._table._schema);
|
|
664
|
-
let query = `INSERT INTO ${tableName} (${cols.join(", ")}) ${this._selectSql.clause}`;
|
|
665
|
-
const bindings = [...this._selectSql.bindings];
|
|
666
|
-
query += this._buildConflictClause();
|
|
667
|
-
const ret = await this._executeWithReturning(db, query, bindings);
|
|
668
|
-
return ret;
|
|
669
|
-
}
|
|
670
|
-
for (const data of this._rows) {
|
|
671
|
-
let coerceValue2 = function(col, value) {
|
|
672
|
-
if (col && col.mode === "boolean") {
|
|
673
|
-
return value ? 1 : 0;
|
|
674
|
-
}
|
|
675
|
-
if (value instanceof Date) {
|
|
676
|
-
if (col && col.mode === "timestamp_ms")
|
|
677
|
-
return value.getTime();
|
|
678
|
-
if (col && col.mode === "timestamp")
|
|
679
|
-
return Math.floor(value.getTime() / 1e3);
|
|
680
|
-
}
|
|
681
|
-
return value;
|
|
682
|
-
};
|
|
683
|
-
var coerceValue = coerceValue2;
|
|
684
|
-
const finalData = Object.assign({}, data);
|
|
685
|
-
const schema = this._table._schema;
|
|
686
|
-
for (const [key, col] of Object.entries(schema)) {
|
|
687
|
-
if (finalData[key] === void 0) {
|
|
688
|
-
if (col.defaultFn) {
|
|
689
|
-
finalData[key] = coerceValue2(col, col.defaultFn());
|
|
690
|
-
} else if (col.onUpdateFn) {
|
|
691
|
-
finalData[key] = coerceValue2(col, col.onUpdateFn());
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
const entries = Object.entries(finalData);
|
|
696
|
-
const keys = entries.map(([k]) => schema[k]?.name ?? k);
|
|
697
|
-
const values = entries.map(([k, v]) => coerceValue2(schema[k], v));
|
|
698
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
699
|
-
let query = `INSERT INTO ${tableName} (${keys.join(
|
|
700
|
-
", "
|
|
701
|
-
)}) VALUES (${placeholders})`;
|
|
702
|
-
const bindings = [...values];
|
|
703
|
-
query += this._buildConflictClause();
|
|
704
|
-
const ret = await this._executeWithReturning(db, query, bindings);
|
|
705
|
-
if (ret !== void 0) return ret;
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
_buildConflictClause() {
|
|
709
|
-
if (!this._conflict) return "";
|
|
710
|
-
if (this._conflict.kind === "doNothing") {
|
|
711
|
-
const tgt2 = this._conflict.target ? Array.isArray(this._conflict.target) ? `(${this._conflict.target.join(", ")})` : `(${this._conflict.target})` : "";
|
|
712
|
-
const where = this._conflict.where ? ` WHERE ${this._conflict.where.toSQL().clause}` : "";
|
|
713
|
-
return ` ON CONFLICT ${tgt2} DO NOTHING${where}`;
|
|
714
|
-
}
|
|
715
|
-
const c = this._conflict;
|
|
716
|
-
const tgt = Array.isArray(c.target) ? `(${c.target.join(", ")})` : `(${c.target})`;
|
|
717
|
-
const setKeys = Object.keys(c.set ?? {});
|
|
718
|
-
const setClause = setKeys.map((k) => {
|
|
719
|
-
const v = c.set[k];
|
|
720
|
-
return `${k} = ${typeof v === "object" && v && typeof v.toSQL === "function" ? v.toSQL().clause : "?"}`;
|
|
721
|
-
}).join(", ");
|
|
722
|
-
const targetWhere = c.targetWhere ? ` WHERE ${c.targetWhere.toSQL().clause}` : "";
|
|
723
|
-
const setWhere = c.setWhere ? ` WHERE ${c.setWhere.toSQL().clause}` : "";
|
|
724
|
-
return ` ON CONFLICT ${tgt}${targetWhere} DO UPDATE SET ${setClause}${setWhere}`;
|
|
725
|
-
}
|
|
726
|
-
async _executeWithReturning(db, query, bindings) {
|
|
727
|
-
if (this._returning === null) {
|
|
728
|
-
await db.execute(query, bindings);
|
|
729
|
-
return void 0;
|
|
730
|
-
}
|
|
731
|
-
if (this._returning === "__RETURNING_ID__") {
|
|
732
|
-
const rows = await db.select(`SELECT last_insert_rowid() as id`);
|
|
733
|
-
return rows.map((r) => ({ id: r.id }));
|
|
734
|
-
}
|
|
735
|
-
if (typeof this._returning === "object") {
|
|
736
|
-
const cols = Object.entries(
|
|
737
|
-
this._returning
|
|
738
|
-
).map(
|
|
739
|
-
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
740
|
-
).join(", ");
|
|
741
|
-
const retSql = `${query} RETURNING ${cols}`;
|
|
742
|
-
const res = await db.select(retSql, bindings);
|
|
743
|
-
return res;
|
|
744
|
-
}
|
|
745
|
-
return void 0;
|
|
746
|
-
}
|
|
747
|
-
}();
|
|
250
|
+
};
|
|
251
|
+
var DeleteQueryBuilder = class extends BaseQueryBuilder {
|
|
252
|
+
constructor(db, table) {
|
|
253
|
+
super(db);
|
|
254
|
+
this.table = table;
|
|
255
|
+
this.query = `DELETE FROM ${table._.name}`;
|
|
748
256
|
}
|
|
749
|
-
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
_data = null;
|
|
754
|
-
_where = null;
|
|
755
|
-
_orderBy = [];
|
|
756
|
-
_limit = null;
|
|
757
|
-
_from = null;
|
|
758
|
-
_returning = null;
|
|
759
|
-
set(data) {
|
|
760
|
-
this._data = data;
|
|
761
|
-
return this;
|
|
762
|
-
}
|
|
763
|
-
where(cond) {
|
|
764
|
-
this._where = cond;
|
|
765
|
-
return this;
|
|
766
|
-
}
|
|
767
|
-
orderBy(...clauses) {
|
|
768
|
-
for (const c of clauses) {
|
|
769
|
-
if (!c) continue;
|
|
770
|
-
if (typeof c === "string") this._orderBy.push(c);
|
|
771
|
-
else if (typeof c.toSQL === "function")
|
|
772
|
-
this._orderBy.push(c);
|
|
773
|
-
else this._orderBy.push(getQualifiedName(c));
|
|
774
|
-
}
|
|
775
|
-
return this;
|
|
776
|
-
}
|
|
777
|
-
limit(n) {
|
|
778
|
-
this._limit = n;
|
|
779
|
-
return this;
|
|
780
|
-
}
|
|
781
|
-
from(tbl) {
|
|
782
|
-
this._from = tbl;
|
|
783
|
-
return this;
|
|
784
|
-
}
|
|
785
|
-
returning(fields) {
|
|
786
|
-
this._returning = fields ?? {};
|
|
787
|
-
return this;
|
|
788
|
-
}
|
|
789
|
-
async execute() {
|
|
790
|
-
if (!this._data)
|
|
791
|
-
throw new Error("Update requires set() before execute()");
|
|
792
|
-
const db = await self.getDb();
|
|
793
|
-
const tableName = getTableName(this._table);
|
|
794
|
-
if (!tableName)
|
|
795
|
-
throw new Error(
|
|
796
|
-
"Invalid table passed to update(): missing table name"
|
|
797
|
-
);
|
|
798
|
-
const schema = this._table._schema;
|
|
799
|
-
const dataToSet = { ...this._data };
|
|
800
|
-
for (const [key, col] of Object.entries(schema)) {
|
|
801
|
-
if (!(key in dataToSet) && col.onUpdateFn) {
|
|
802
|
-
const v = col.onUpdateFn();
|
|
803
|
-
if (col.mode === "boolean") dataToSet[key] = v ? 1 : 0;
|
|
804
|
-
else if (v instanceof Date) {
|
|
805
|
-
if (col.mode === "timestamp_ms")
|
|
806
|
-
dataToSet[key] = v.getTime();
|
|
807
|
-
else if (col.mode === "timestamp")
|
|
808
|
-
dataToSet[key] = Math.floor(v.getTime() / 1e3);
|
|
809
|
-
else dataToSet[key] = v;
|
|
810
|
-
} else dataToSet[key] = v;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
const setParts = [];
|
|
814
|
-
const bindings = [];
|
|
815
|
-
for (const [k, v] of Object.entries(dataToSet)) {
|
|
816
|
-
if (v === void 0) continue;
|
|
817
|
-
if (v && typeof v === "object" && typeof v.toSQL === "function") {
|
|
818
|
-
const s = v.toSQL();
|
|
819
|
-
const colName = schema[k]?.name ?? k;
|
|
820
|
-
setParts.push(`${colName} = ${s.clause}`);
|
|
821
|
-
bindings.push(...s.bindings);
|
|
822
|
-
} else {
|
|
823
|
-
const colName = schema[k]?.name ?? k;
|
|
824
|
-
let val = v;
|
|
825
|
-
const col = schema[k];
|
|
826
|
-
if (col && col.mode === "boolean") val = v ? 1 : 0;
|
|
827
|
-
else if (v instanceof Date) {
|
|
828
|
-
if (col && col.mode === "timestamp_ms")
|
|
829
|
-
val = v.getTime();
|
|
830
|
-
else if (col && col.mode === "timestamp")
|
|
831
|
-
val = Math.floor(v.getTime() / 1e3);
|
|
832
|
-
}
|
|
833
|
-
setParts.push(`${colName} = ?`);
|
|
834
|
-
bindings.push(val);
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
let query = `UPDATE ${tableName} SET ${setParts.join(", ")}`;
|
|
838
|
-
if (this._from) query += ` FROM ${this._from._tableName}`;
|
|
839
|
-
if (this._where) {
|
|
840
|
-
if (typeof this._where.toSQL === "function") {
|
|
841
|
-
const sql2 = this._where.toSQL();
|
|
842
|
-
query += ` WHERE ${sql2.clause}`;
|
|
843
|
-
bindings.push(...sql2.bindings);
|
|
844
|
-
} else {
|
|
845
|
-
const entries = Object.entries(this._where);
|
|
846
|
-
if (entries.length > 0) {
|
|
847
|
-
query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
|
|
848
|
-
bindings.push(...entries.map(([, v]) => v));
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
if (this._orderBy.length > 0) {
|
|
853
|
-
const ordParts = [];
|
|
854
|
-
for (const ob of this._orderBy) {
|
|
855
|
-
if (typeof ob === "string") ordParts.push(ob);
|
|
856
|
-
else {
|
|
857
|
-
const s = ob.toSQL();
|
|
858
|
-
ordParts.push(s.clause);
|
|
859
|
-
bindings.push(...s.bindings);
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
863
|
-
}
|
|
864
|
-
if (this._limit !== null) {
|
|
865
|
-
query += ` LIMIT ?`;
|
|
866
|
-
bindings.push(this._limit);
|
|
867
|
-
}
|
|
868
|
-
if (this._returning) {
|
|
869
|
-
const cols = Object.entries(
|
|
870
|
-
this._returning
|
|
871
|
-
).map(
|
|
872
|
-
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
873
|
-
).join(", ");
|
|
874
|
-
const retSql = `${query} RETURNING ${cols}`;
|
|
875
|
-
return await db.select(retSql, bindings);
|
|
876
|
-
}
|
|
877
|
-
await db.execute(query, bindings);
|
|
878
|
-
}
|
|
879
|
-
}();
|
|
257
|
+
async execute() {
|
|
258
|
+
const { sql, params } = this.build();
|
|
259
|
+
const result = await this.db.execute(sql, ...params);
|
|
260
|
+
return result.rowsAffected;
|
|
880
261
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
_returning = null;
|
|
889
|
-
where(cond) {
|
|
890
|
-
this._where = cond;
|
|
891
|
-
return this;
|
|
892
|
-
}
|
|
893
|
-
orderBy(...clauses) {
|
|
894
|
-
for (const c of clauses) {
|
|
895
|
-
if (!c) continue;
|
|
896
|
-
if (typeof c === "string") this._orderBy.push(c);
|
|
897
|
-
else if (typeof c.toSQL === "function")
|
|
898
|
-
this._orderBy.push(c);
|
|
899
|
-
else this._orderBy.push(getQualifiedName(c));
|
|
900
|
-
}
|
|
901
|
-
return this;
|
|
902
|
-
}
|
|
903
|
-
limit(n) {
|
|
904
|
-
this._limit = n;
|
|
905
|
-
return this;
|
|
906
|
-
}
|
|
907
|
-
returning(fields) {
|
|
908
|
-
this._returning = fields ?? {};
|
|
909
|
-
return this;
|
|
910
|
-
}
|
|
911
|
-
async execute() {
|
|
912
|
-
const db = await self.getDb();
|
|
913
|
-
const tableName = getTableName(this._table);
|
|
914
|
-
if (!tableName)
|
|
915
|
-
throw new Error(
|
|
916
|
-
"Invalid table passed to delete(): missing table name"
|
|
917
|
-
);
|
|
918
|
-
let query = `DELETE FROM ${tableName}`;
|
|
919
|
-
const bindings = [];
|
|
920
|
-
if (this._where) {
|
|
921
|
-
if (typeof this._where.toSQL === "function") {
|
|
922
|
-
const sql2 = this._where.toSQL();
|
|
923
|
-
query += ` WHERE ${sql2.clause}`;
|
|
924
|
-
bindings.push(...sql2.bindings);
|
|
925
|
-
} else {
|
|
926
|
-
const entries = Object.entries(this._where);
|
|
927
|
-
if (entries.length > 0) {
|
|
928
|
-
const schema = this._table._schema;
|
|
929
|
-
query += ` WHERE ${entries.map(([k]) => `${schema[k]?.name ?? k} = ?`).join(" AND ")}`;
|
|
930
|
-
bindings.push(...entries.map(([, v]) => v));
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
if (this._orderBy.length > 0) {
|
|
935
|
-
const ordParts = [];
|
|
936
|
-
for (const ob of this._orderBy) {
|
|
937
|
-
if (typeof ob === "string") ordParts.push(ob);
|
|
938
|
-
else {
|
|
939
|
-
const s = ob.toSQL();
|
|
940
|
-
ordParts.push(s.clause);
|
|
941
|
-
bindings.push(...s.bindings);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
945
|
-
}
|
|
946
|
-
if (this._limit !== null) {
|
|
947
|
-
query += ` LIMIT ?`;
|
|
948
|
-
bindings.push(this._limit);
|
|
949
|
-
}
|
|
950
|
-
if (this._returning) {
|
|
951
|
-
const cols = Object.entries(
|
|
952
|
-
this._returning
|
|
953
|
-
).map(
|
|
954
|
-
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
955
|
-
).join(", ");
|
|
956
|
-
const retSql = `${query} RETURNING ${cols}`;
|
|
957
|
-
return await db.select(retSql, bindings);
|
|
958
|
-
}
|
|
959
|
-
await db.execute(query, bindings);
|
|
262
|
+
};
|
|
263
|
+
var TauriORM = class {
|
|
264
|
+
constructor(db, schema = void 0) {
|
|
265
|
+
this.db = db;
|
|
266
|
+
if (schema) {
|
|
267
|
+
for (const table of Object.values(schema)) {
|
|
268
|
+
this.tables.set(table._.name, table);
|
|
960
269
|
}
|
|
961
|
-
}();
|
|
962
|
-
}
|
|
963
|
-
// legacy direct methods removed in favor of builder APIs
|
|
964
|
-
// legacy direct methods removed in favor of builder APIs
|
|
965
|
-
// legacy direct methods removed in favor of builder APIs
|
|
966
|
-
async run(query, bindings = []) {
|
|
967
|
-
const db = await this.getDb();
|
|
968
|
-
await db.execute(query, bindings);
|
|
969
|
-
}
|
|
970
|
-
// --- Migrations API ---
|
|
971
|
-
formatDefaultValue(col) {
|
|
972
|
-
const dv = col.defaultValue;
|
|
973
|
-
if (dv === void 0) return null;
|
|
974
|
-
if (dv && typeof dv === "object" && "raw" in dv) {
|
|
975
|
-
return dv.raw;
|
|
976
|
-
}
|
|
977
|
-
if (dv instanceof Date) {
|
|
978
|
-
const isMs = col.mode === "timestamp_ms";
|
|
979
|
-
const num = isMs ? dv.getTime() : Math.floor(dv.getTime() / 1e3);
|
|
980
|
-
return String(num);
|
|
981
|
-
}
|
|
982
|
-
if (col.mode === "boolean") {
|
|
983
|
-
return String(dv ? 1 : 0);
|
|
984
|
-
}
|
|
985
|
-
if (typeof dv === "string") {
|
|
986
|
-
return `'${dv.replace(/'/g, "''")}'`;
|
|
987
270
|
}
|
|
988
|
-
return String(dv);
|
|
989
271
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
const formatted = this.formatDefaultValue(col);
|
|
1003
|
-
if (formatted !== null) def += ` DEFAULT ${formatted}`;
|
|
1004
|
-
}
|
|
1005
|
-
if (col.references && !col.isPrimaryKey) {
|
|
1006
|
-
def += ` REFERENCES ${col.references.table} (${col.references.column})`;
|
|
1007
|
-
if (col.references.onDelete)
|
|
1008
|
-
def += ` ON DELETE ${col.references.onDelete.toUpperCase()}`;
|
|
1009
|
-
if (col.references.onUpdate)
|
|
1010
|
-
def += ` ON UPDATE ${col.references.onUpdate.toUpperCase()}`;
|
|
1011
|
-
}
|
|
1012
|
-
return def;
|
|
1013
|
-
});
|
|
1014
|
-
const tableConstraints = [];
|
|
1015
|
-
const constraints = table._constraints;
|
|
1016
|
-
if (constraints && constraints.length) {
|
|
1017
|
-
for (const spec of constraints) {
|
|
1018
|
-
if (spec.expr) {
|
|
1019
|
-
const name = spec.name;
|
|
1020
|
-
const expr = spec.expr.raw ?? spec.expr?.raw ?? String(spec.expr);
|
|
1021
|
-
tableConstraints.push(
|
|
1022
|
-
name ? `CONSTRAINT ${name} CHECK (${expr})` : `CHECK (${expr})`
|
|
1023
|
-
);
|
|
1024
|
-
continue;
|
|
272
|
+
tables = /* @__PURE__ */ new Map();
|
|
273
|
+
async migrate() {
|
|
274
|
+
for (const table of this.tables.values()) {
|
|
275
|
+
const columnsSql = Object.entries(table._.columns).map(([name, col]) => {
|
|
276
|
+
let sql = `${col._.name} ${col.type}`;
|
|
277
|
+
if (col.options.primaryKey) sql += " PRIMARY KEY";
|
|
278
|
+
if (col._.autoincrement) sql += " AUTOINCREMENT";
|
|
279
|
+
if (col._.notNull) sql += " NOT NULL";
|
|
280
|
+
if (col.options.unique) sql += " UNIQUE";
|
|
281
|
+
if (col.options.default !== void 0) {
|
|
282
|
+
const value = col.options.default;
|
|
283
|
+
sql += ` DEFAULT ${typeof value === "string" ? `'${value}'` : value}`;
|
|
1025
284
|
}
|
|
1026
|
-
if (
|
|
1027
|
-
|
|
1028
|
-
const cols = spec.columns.join(", ");
|
|
1029
|
-
const fTable = spec.foreignTable;
|
|
1030
|
-
const fCols = spec.foreignColumns.join(", ");
|
|
1031
|
-
let clause = `${name ? `CONSTRAINT ${name} ` : ""}FOREIGN KEY (${cols}) REFERENCES ${fTable} (${fCols})`;
|
|
1032
|
-
if (spec.onDelete)
|
|
1033
|
-
clause += ` ON DELETE ${String(
|
|
1034
|
-
spec.onDelete
|
|
1035
|
-
).toUpperCase()}`;
|
|
1036
|
-
if (spec.onUpdate)
|
|
1037
|
-
clause += ` ON UPDATE ${String(
|
|
1038
|
-
spec.onUpdate
|
|
1039
|
-
).toUpperCase()}`;
|
|
1040
|
-
tableConstraints.push(clause);
|
|
1041
|
-
continue;
|
|
285
|
+
if (col.options.references) {
|
|
286
|
+
sql += ` REFERENCES ${col.options.references.table._.name}(${col.options.references.column._.name})`;
|
|
1042
287
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
if (isPk) {
|
|
1048
|
-
tableConstraints.push(
|
|
1049
|
-
name ? `CONSTRAINT ${name} PRIMARY KEY (${cols})` : `PRIMARY KEY (${cols})`
|
|
1050
|
-
);
|
|
1051
|
-
} else {
|
|
1052
|
-
tableConstraints.push(
|
|
1053
|
-
name ? `CONSTRAINT ${name} UNIQUE (${cols})` : `UNIQUE (${cols})`
|
|
1054
|
-
);
|
|
1055
|
-
}
|
|
1056
|
-
continue;
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
288
|
+
return sql;
|
|
289
|
+
}).join(", ");
|
|
290
|
+
const createSql = `CREATE TABLE IF NOT EXISTS ${table._.name} (${columnsSql})`;
|
|
291
|
+
await this.db.execute(createSql);
|
|
1059
292
|
}
|
|
1060
|
-
const parts = [...columnDefs, ...tableConstraints];
|
|
1061
|
-
return `CREATE TABLE IF NOT EXISTS ${tableName} (${parts.join(", ")});`;
|
|
1062
|
-
}
|
|
1063
|
-
async createTableIfNotExists(table) {
|
|
1064
|
-
const sql2 = this.generateCreateTableSql(table);
|
|
1065
|
-
await this.run(sql2);
|
|
1066
|
-
await this.createIndexesForTable(table);
|
|
1067
|
-
}
|
|
1068
|
-
async createTablesIfNotExist(tables) {
|
|
1069
|
-
for (const t of tables) {
|
|
1070
|
-
await this.createTableIfNotExists(t);
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
generateCreateIndexSqls(table) {
|
|
1074
|
-
const tableName = table._tableName;
|
|
1075
|
-
const indexes = table._indexes || [];
|
|
1076
|
-
const stmts = [];
|
|
1077
|
-
for (const idx of indexes) {
|
|
1078
|
-
const unique2 = idx.unique ? "UNIQUE " : "";
|
|
1079
|
-
if (!idx.name) continue;
|
|
1080
|
-
const colList = Array.isArray(idx.columns) ? idx.columns : [];
|
|
1081
|
-
if (colList.length === 0) continue;
|
|
1082
|
-
const cols = `(${colList.join(", ")})`;
|
|
1083
|
-
const where = idx.where?.raw ? ` WHERE ${idx.where.raw}` : "";
|
|
1084
|
-
stmts.push(
|
|
1085
|
-
`CREATE ${unique2}INDEX IF NOT EXISTS ${idx.name} ON ${tableName} ${cols}${where};`
|
|
1086
|
-
);
|
|
1087
|
-
}
|
|
1088
|
-
return stmts;
|
|
1089
|
-
}
|
|
1090
|
-
async createIndexesForTable(table) {
|
|
1091
|
-
const stmts = this.generateCreateIndexSqls(table);
|
|
1092
|
-
for (const s of stmts) await this.run(s);
|
|
1093
|
-
}
|
|
1094
|
-
async ensureMigrationsTable() {
|
|
1095
|
-
await this.run(
|
|
1096
|
-
`CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)`
|
|
1097
|
-
);
|
|
1098
293
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
const rows = await db.select(
|
|
1102
|
-
`SELECT name FROM _migrations WHERE name = ?`,
|
|
1103
|
-
[name]
|
|
1104
|
-
);
|
|
1105
|
-
return Array.isArray(rows) && rows.length > 0;
|
|
1106
|
-
}
|
|
1107
|
-
async recordMigration(name) {
|
|
1108
|
-
const db = await this.getDb();
|
|
1109
|
-
await db.execute(
|
|
1110
|
-
`INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`,
|
|
1111
|
-
[name, Date.now()]
|
|
1112
|
-
);
|
|
294
|
+
select(table, columns) {
|
|
295
|
+
return new SelectQueryBuilder(this.db, table, columns);
|
|
1113
296
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
if (track) {
|
|
1117
|
-
await this.ensureMigrationsTable();
|
|
1118
|
-
}
|
|
1119
|
-
await this.forcePushForTables(tables, { preserveData: true });
|
|
1120
|
-
if (track) {
|
|
1121
|
-
const name = options?.name ?? `init:${tables.map((t) => t._tableName).join(",")}`;
|
|
1122
|
-
const already = await this.hasMigration(name);
|
|
1123
|
-
if (!already) await this.recordMigration(name);
|
|
1124
|
-
}
|
|
297
|
+
insert(table) {
|
|
298
|
+
return new InsertQueryBuilder(this.db, table);
|
|
1125
299
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
this._tables = tables;
|
|
1129
|
-
this._relations = relDefs ?? {};
|
|
1130
|
-
this.query = makeQueryAPI(
|
|
1131
|
-
tables,
|
|
1132
|
-
this._relations ?? {},
|
|
1133
|
-
this.getDb.bind(this)
|
|
1134
|
-
);
|
|
1135
|
-
return this;
|
|
300
|
+
update(table) {
|
|
301
|
+
return new UpdateQueryBuilder(this.db, table);
|
|
1136
302
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
if (!this._tables)
|
|
1140
|
-
throw new Error("No tables configured. Call db.configure({...}) first.");
|
|
1141
|
-
await this.migrate(Object.values(this._tables), options);
|
|
1142
|
-
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
|
303
|
+
delete(table) {
|
|
304
|
+
return new DeleteQueryBuilder(this.db, table);
|
|
1143
305
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
)
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
);
|
|
1154
|
-
const existingNames = existing.map((r) => r.name);
|
|
1155
|
-
const extraTables = existingNames.filter(
|
|
1156
|
-
(n) => !configuredNames.includes(n)
|
|
1157
|
-
);
|
|
1158
|
-
const missingTables = configuredNames.filter(
|
|
1159
|
-
(n) => !existingNames.includes(n)
|
|
1160
|
-
);
|
|
1161
|
-
const tables = {};
|
|
1162
|
-
for (const tbl of Object.values(this._tables)) {
|
|
1163
|
-
const tableName = getTableName(tbl);
|
|
1164
|
-
if (!existingNames.includes(tableName)) {
|
|
1165
|
-
tables[tableName] = {
|
|
1166
|
-
missingColumns: Object.keys(tbl._schema),
|
|
1167
|
-
extraColumns: [],
|
|
1168
|
-
changedColumns: []
|
|
1169
|
-
};
|
|
1170
|
-
continue;
|
|
1171
|
-
}
|
|
1172
|
-
const cols = await dbi.select(`PRAGMA table_info('${tableName}')`);
|
|
1173
|
-
const colMap = new Map(cols.map((c) => [c.name, c]));
|
|
1174
|
-
const modelCols = Object.values(
|
|
1175
|
-
tbl._schema
|
|
1176
|
-
);
|
|
1177
|
-
const missingColumns = [];
|
|
1178
|
-
const extraColumns = [];
|
|
1179
|
-
const changedColumns = [];
|
|
1180
|
-
const modelNamesSet = new Set(modelCols.map((c) => c.name));
|
|
1181
|
-
for (const m of modelCols) {
|
|
1182
|
-
const info = colMap.get(m.name);
|
|
1183
|
-
if (!info) {
|
|
1184
|
-
missingColumns.push(m.name);
|
|
1185
|
-
continue;
|
|
1186
|
-
}
|
|
1187
|
-
const diffs = {};
|
|
1188
|
-
if ((info.type || "").toUpperCase() !== m.type.toUpperCase())
|
|
1189
|
-
diffs.type = true;
|
|
1190
|
-
if (!!info.pk !== !!m.isPrimaryKey) diffs.pk = true;
|
|
1191
|
-
if (!!info.notnull !== !!m.isNotNull) diffs.notNull = true;
|
|
1192
|
-
const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
|
|
1193
|
-
if ((info.dflt_value ?? null) !== modelDv)
|
|
1194
|
-
diffs.default = true;
|
|
1195
|
-
if (Object.keys(diffs).length)
|
|
1196
|
-
changedColumns.push({ name: m.name, diffs });
|
|
1197
|
-
}
|
|
1198
|
-
for (const c of cols)
|
|
1199
|
-
if (!modelNamesSet.has(c.name)) extraColumns.push(c.name);
|
|
1200
|
-
tables[tableName] = { missingColumns, extraColumns, changedColumns };
|
|
306
|
+
async transaction(callback) {
|
|
307
|
+
await this.db.execute("BEGIN TRANSACTION");
|
|
308
|
+
try {
|
|
309
|
+
const result = await callback(this);
|
|
310
|
+
await this.db.execute("COMMIT");
|
|
311
|
+
return result;
|
|
312
|
+
} catch (error) {
|
|
313
|
+
await this.db.execute("ROLLBACK");
|
|
314
|
+
throw error;
|
|
1201
315
|
}
|
|
1202
|
-
return { extraTables, missingTables, tables };
|
|
1203
|
-
}
|
|
1204
|
-
async generate() {
|
|
1205
|
-
if (!this._tables) throw new Error("No tables configured.");
|
|
1206
|
-
return {
|
|
1207
|
-
statements: Object.values(this._tables).map(
|
|
1208
|
-
(t) => this.buildCreateTableSQL(t)
|
|
1209
|
-
)
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
async migrateCli(opts) {
|
|
1213
|
-
return this.migrateConfigured(opts);
|
|
1214
|
-
}
|
|
1215
|
-
async push(opts) {
|
|
1216
|
-
return this.forcePush(opts);
|
|
1217
|
-
}
|
|
1218
|
-
async pull() {
|
|
1219
|
-
return this.pullSchema();
|
|
1220
|
-
}
|
|
1221
|
-
async studio() {
|
|
1222
|
-
const dbi = await this.getDb();
|
|
1223
|
-
return { driver: "sqlite", path: dbi.path };
|
|
1224
316
|
}
|
|
1225
317
|
// --- Schema detection / signature ---
|
|
1226
318
|
async ensureSchemaMeta() {
|
|
1227
|
-
await this.
|
|
319
|
+
await this.db.execute(
|
|
1228
320
|
`CREATE TABLE IF NOT EXISTS _schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
|
|
1229
321
|
);
|
|
1230
322
|
}
|
|
1231
323
|
async getSchemaMeta(key) {
|
|
1232
|
-
const dbi = await this.getDb();
|
|
1233
324
|
await this.ensureSchemaMeta();
|
|
1234
|
-
const rows = await
|
|
325
|
+
const rows = await this.db.select(
|
|
1235
326
|
`SELECT value FROM _schema_meta WHERE key = ?`,
|
|
1236
327
|
[key]
|
|
1237
328
|
);
|
|
1238
329
|
return rows?.[0]?.value ?? null;
|
|
1239
330
|
}
|
|
1240
331
|
async setSchemaMeta(key, value) {
|
|
1241
|
-
const dbi = await this.getDb();
|
|
1242
332
|
await this.ensureSchemaMeta();
|
|
1243
|
-
await
|
|
333
|
+
await this.db.execute(
|
|
1244
334
|
`INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
|
|
1245
335
|
[key, value]
|
|
1246
336
|
);
|
|
1247
337
|
}
|
|
1248
338
|
normalizeColumn(col) {
|
|
1249
339
|
return {
|
|
1250
|
-
name: col.name,
|
|
340
|
+
name: col._.name,
|
|
1251
341
|
type: col.type,
|
|
1252
|
-
pk: !!col.
|
|
1253
|
-
ai: !!col.
|
|
1254
|
-
nn: !!col.
|
|
1255
|
-
dv: col.
|
|
342
|
+
pk: !!col.options.primaryKey,
|
|
343
|
+
ai: !!col._.autoincrement,
|
|
344
|
+
nn: !!col._.notNull,
|
|
345
|
+
dv: col.options.default && typeof col.options.default === "object" && col.options.default.raw ? { raw: col.options.default.raw } : col.options.default ?? null
|
|
1256
346
|
};
|
|
1257
347
|
}
|
|
1258
348
|
computeModelSignature() {
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
tbl._schema
|
|
1263
|
-
).map((c) => this.normalizeColumn(c)).sort((a, b) => a.name.localeCompare(b.name));
|
|
1264
|
-
return { table: tbl._tableName, columns: cols };
|
|
349
|
+
const entries = Array.from(this.tables.values()).map((tbl) => {
|
|
350
|
+
const cols = Object.values(tbl._.columns).map((c) => this.normalizeColumn(c)).sort((a, b) => a.name.localeCompare(b.name));
|
|
351
|
+
return { table: tbl._.name, columns: cols };
|
|
1265
352
|
});
|
|
1266
353
|
entries.sort((a, b) => a.table.localeCompare(b.table));
|
|
1267
354
|
return JSON.stringify(entries);
|
|
@@ -1269,22 +356,15 @@ var TauriORM = class {
|
|
|
1269
356
|
getSchemaSignature() {
|
|
1270
357
|
return this.computeModelSignature();
|
|
1271
358
|
}
|
|
1272
|
-
async printSchemaDiff() {
|
|
1273
|
-
const diff = await this.diffSchema();
|
|
1274
|
-
console.log("Schema diff:", JSON.stringify(diff, null, 2));
|
|
1275
|
-
}
|
|
1276
359
|
async isSchemaDirty() {
|
|
1277
360
|
const sig = this.computeModelSignature();
|
|
1278
361
|
const stored = await this.getSchemaMeta("schema_signature");
|
|
1279
362
|
return { dirty: sig !== stored, current: sig, stored };
|
|
1280
363
|
}
|
|
1281
|
-
async migrateIfDirty(
|
|
364
|
+
async migrateIfDirty() {
|
|
1282
365
|
const status = await this.isSchemaDirty();
|
|
1283
|
-
if (!this._tables) throw new Error("No tables configured.");
|
|
1284
366
|
if (status.dirty) {
|
|
1285
|
-
await this.
|
|
1286
|
-
preserveData: true
|
|
1287
|
-
});
|
|
367
|
+
await this.migrate();
|
|
1288
368
|
await this.setSchemaMeta(
|
|
1289
369
|
"schema_signature",
|
|
1290
370
|
this.computeModelSignature()
|
|
@@ -1293,454 +373,45 @@ var TauriORM = class {
|
|
|
1293
373
|
}
|
|
1294
374
|
return false;
|
|
1295
375
|
}
|
|
1296
|
-
// Pull current DB schema (minimal) for configured tables
|
|
1297
|
-
async pullSchema() {
|
|
1298
|
-
if (!this._tables) throw new Error("No tables configured.");
|
|
1299
|
-
const dbi = await this.getDb();
|
|
1300
|
-
const result = {};
|
|
1301
|
-
for (const tbl of Object.values(this._tables)) {
|
|
1302
|
-
const name = tbl._tableName;
|
|
1303
|
-
const cols = await dbi.select(`PRAGMA table_info('${name}')`);
|
|
1304
|
-
result[name] = cols.map((c) => ({
|
|
1305
|
-
name: c.name,
|
|
1306
|
-
type: c.type,
|
|
1307
|
-
notnull: !!c.notnull,
|
|
1308
|
-
pk: !!c.pk,
|
|
1309
|
-
dflt_value: c.dflt_value ?? null
|
|
1310
|
-
}));
|
|
1311
|
-
}
|
|
1312
|
-
return result;
|
|
1313
|
-
}
|
|
1314
|
-
buildCreateTableSQL(table) {
|
|
1315
|
-
return this.generateCreateTableSql(table);
|
|
1316
|
-
}
|
|
1317
|
-
async tableExists(name) {
|
|
1318
|
-
const dbi = await this.getDb();
|
|
1319
|
-
const rows = await dbi.select(
|
|
1320
|
-
`SELECT name FROM sqlite_master WHERE type='table' AND name = ?`,
|
|
1321
|
-
[name]
|
|
1322
|
-
);
|
|
1323
|
-
return rows.length > 0;
|
|
1324
|
-
}
|
|
1325
|
-
// Force push model to DB: add missing tables/columns, rebuild tables if incompatible
|
|
1326
|
-
async forcePush(options) {
|
|
1327
|
-
if (!this._tables) throw new Error("No tables configured.");
|
|
1328
|
-
await this.forcePushForTables(Object.values(this._tables), options);
|
|
1329
|
-
}
|
|
1330
|
-
async forcePushForTables(tables, options) {
|
|
1331
|
-
const dbi = await this.getDb();
|
|
1332
|
-
const preserve = options?.preserveData !== false;
|
|
1333
|
-
for (const tbl of tables) {
|
|
1334
|
-
const tableName = getTableName(tbl);
|
|
1335
|
-
const exists2 = await this.tableExists(tableName);
|
|
1336
|
-
if (!exists2) {
|
|
1337
|
-
await this.run(this.buildCreateTableSQL(tbl));
|
|
1338
|
-
await this.createIndexesForTable(tbl);
|
|
1339
|
-
continue;
|
|
1340
|
-
}
|
|
1341
|
-
const existingCols = await dbi.select(
|
|
1342
|
-
`PRAGMA table_info('${tableName}')`
|
|
1343
|
-
);
|
|
1344
|
-
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
1345
|
-
const modelCols = Object.values(
|
|
1346
|
-
tbl._schema
|
|
1347
|
-
);
|
|
1348
|
-
const missing = [];
|
|
1349
|
-
let requiresRebuild = false;
|
|
1350
|
-
for (const m of modelCols) {
|
|
1351
|
-
const info = existingMap.get(m.name);
|
|
1352
|
-
if (!info) {
|
|
1353
|
-
missing.push(m);
|
|
1354
|
-
continue;
|
|
1355
|
-
}
|
|
1356
|
-
const typeDiff = (info.type || "").toUpperCase() !== m.type.toUpperCase();
|
|
1357
|
-
const pkDiff = !!info.pk !== !!m.isPrimaryKey;
|
|
1358
|
-
const nnDiff = !!info.notnull !== !!m.isNotNull;
|
|
1359
|
-
const modelDv = m.defaultValue && typeof m.defaultValue === "object" && m.defaultValue.raw ? m.defaultValue.raw : m.defaultValue ?? null;
|
|
1360
|
-
const defDiff = (info.dflt_value ?? null) !== modelDv;
|
|
1361
|
-
if (typeDiff || pkDiff || nnDiff && !modelDv || defDiff) {
|
|
1362
|
-
requiresRebuild = true;
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
if (requiresRebuild) {
|
|
1366
|
-
const tmp = `_new_${tableName}`;
|
|
1367
|
-
await this.run(this.buildCreateTableSQL(tbl));
|
|
1368
|
-
await this.run(
|
|
1369
|
-
this.buildCreateTableSQL({ ...tbl, _tableName: tmp })
|
|
1370
|
-
);
|
|
1371
|
-
const existingNames = existingCols.map((c) => c.name);
|
|
1372
|
-
const modelNames = modelCols.map((c) => c.name);
|
|
1373
|
-
const shared = existingNames.filter((n) => modelNames.includes(n));
|
|
1374
|
-
if (preserve && shared.length > 0) {
|
|
1375
|
-
await this.run(
|
|
1376
|
-
`INSERT INTO ${tmp} (${shared.join(", ")}) SELECT ${shared.join(
|
|
1377
|
-
", "
|
|
1378
|
-
)} FROM ${tableName}`
|
|
1379
|
-
);
|
|
1380
|
-
}
|
|
1381
|
-
await this.run(`DROP TABLE ${tableName}`);
|
|
1382
|
-
await this.run(`ALTER TABLE ${tmp} RENAME TO ${tableName}`);
|
|
1383
|
-
await this.createIndexesForTable(tbl);
|
|
1384
|
-
} else {
|
|
1385
|
-
for (const m of missing) {
|
|
1386
|
-
let clause = `${m.name} ${m.type}`;
|
|
1387
|
-
if (m.isNotNull) clause += " NOT NULL";
|
|
1388
|
-
if (m.defaultValue !== void 0) {
|
|
1389
|
-
const formatted = this.formatDefaultValue(m);
|
|
1390
|
-
if (formatted !== null) clause += ` DEFAULT ${formatted}`;
|
|
1391
|
-
}
|
|
1392
|
-
await this.run(`ALTER TABLE ${tableName} ADD COLUMN ${clause}`);
|
|
1393
|
-
}
|
|
1394
|
-
await this.createIndexesForTable(tbl);
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
|
1398
|
-
}
|
|
1399
376
|
};
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
one: (
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
if (rel && rel.kind === "one" && rel.cfg?.fields?.[0])
|
|
1415
|
-
return rel.cfg.fields[0];
|
|
1416
|
-
const basePk = getPrimaryKey(base);
|
|
1417
|
-
const guessNames = [
|
|
1418
|
-
`${base._tableName}_id`,
|
|
1419
|
-
`${base._tableName}Id`,
|
|
1420
|
-
`${basePk.name}`,
|
|
1421
|
-
`${base._tableName.slice(0, -1)}Id`
|
|
1422
|
-
];
|
|
1423
|
-
return childCols.find((c) => guessNames.includes(c.name)) || childCols.find((c) => /.*_id$/i.test(c.name)) || null;
|
|
1424
|
-
}
|
|
1425
|
-
function guessOneRelationJoin(base, rel) {
|
|
1426
|
-
const child = rel.table;
|
|
1427
|
-
const basePk = getPrimaryKey(base);
|
|
1428
|
-
const childCols = Object.values(child._schema);
|
|
1429
|
-
if (rel.cfg?.fields && rel.cfg?.references && rel.cfg.fields[0] && rel.cfg.references[0]) {
|
|
1430
|
-
const fk = rel.cfg.fields[0];
|
|
1431
|
-
const ref = rel.cfg.references[0];
|
|
1432
|
-
if (childCols.some((c) => c.name === fk.name)) {
|
|
1433
|
-
return { lhsTable: child, lhsCol: fk, rhsTable: base, rhsCol: ref };
|
|
1434
|
-
}
|
|
1435
|
-
const baseCols = Object.values(base._schema);
|
|
1436
|
-
if (baseCols.some((c) => c.name === fk.name)) {
|
|
1437
|
-
return { lhsTable: base, lhsCol: fk, rhsTable: child, rhsCol: ref };
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
const childFk = guessChildFk(child, base, rel);
|
|
1441
|
-
if (!childFk) return null;
|
|
1442
|
-
return { lhsTable: child, lhsCol: childFk, rhsTable: base, rhsCol: basePk };
|
|
1443
|
-
}
|
|
1444
|
-
function isFlatWith(spec) {
|
|
1445
|
-
return Object.values(spec).every((v) => typeof v === "boolean");
|
|
1446
|
-
}
|
|
1447
|
-
function makeQueryAPI(tables, relDefs, dbProvider) {
|
|
1448
|
-
const api = {};
|
|
1449
|
-
const tableKeyByName = {};
|
|
1450
|
-
for (const [k, t] of Object.entries(tables)) tableKeyByName[t._tableName] = k;
|
|
1451
|
-
for (const [tblKey, tbl] of Object.entries(tables)) {
|
|
1452
|
-
api[tblKey] = {
|
|
1453
|
-
async findMany(opts) {
|
|
1454
|
-
const base = tbl;
|
|
1455
|
-
const withSpec = opts?.with ?? {};
|
|
1456
|
-
const dbi = await dbProvider();
|
|
1457
|
-
const rels = relDefs[tblKey] ?? {};
|
|
1458
|
-
if (opts?.join && isFlatWith(withSpec)) {
|
|
1459
|
-
const baseCols = Object.values(base._schema);
|
|
1460
|
-
const basePk = baseCols.find((c) => c.isPrimaryKey) || baseCols.find((c) => c.name === "id") || baseCols[0];
|
|
1461
|
-
const selectParts = [];
|
|
1462
|
-
let baseSelected2;
|
|
1463
|
-
if (opts?.columns && !Array.isArray(opts.columns)) {
|
|
1464
|
-
baseSelected2 = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
|
|
1465
|
-
} else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
|
|
1466
|
-
baseSelected2 = opts.columns;
|
|
1467
|
-
} else {
|
|
1468
|
-
baseSelected2 = baseCols.map((c) => c.name);
|
|
1469
|
-
}
|
|
1470
|
-
for (const name of baseSelected2)
|
|
1471
|
-
selectParts.push(`${base._tableName}.${name} AS __base_${name}`);
|
|
1472
|
-
const joins = [];
|
|
1473
|
-
const relColsMap = {};
|
|
1474
|
-
const fkMap = {};
|
|
1475
|
-
for (const [relName, enabled] of Object.entries(withSpec)) {
|
|
1476
|
-
if (!enabled) continue;
|
|
1477
|
-
const rel = rels[relName];
|
|
1478
|
-
if (!rel) continue;
|
|
1479
|
-
const child = rel.table;
|
|
1480
|
-
const childCols = Object.values(child._schema);
|
|
1481
|
-
const childPk = childCols.find((c) => c.isPrimaryKey) || childCols.find((c) => c.name === "id") || null;
|
|
1482
|
-
if (rel.kind === "one") {
|
|
1483
|
-
const mapping = guessOneRelationJoin(base, rel);
|
|
1484
|
-
if (!mapping) continue;
|
|
1485
|
-
if (mapping.lhsTable._tableName === child._tableName) {
|
|
1486
|
-
fkMap[relName] = { childFk: mapping.lhsCol, childPk };
|
|
1487
|
-
joins.push(
|
|
1488
|
-
`LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
|
|
1489
|
-
);
|
|
1490
|
-
} else {
|
|
1491
|
-
fkMap[relName] = { childFk: mapping.rhsCol, childPk };
|
|
1492
|
-
joins.push(
|
|
1493
|
-
`LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
} else {
|
|
1497
|
-
const childFk = guessChildFk(child, base, rel);
|
|
1498
|
-
if (!childFk) continue;
|
|
1499
|
-
fkMap[relName] = { childFk, childPk };
|
|
1500
|
-
joins.push(
|
|
1501
|
-
`LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
|
|
1502
|
-
);
|
|
1503
|
-
}
|
|
1504
|
-
const selected = typeof enabled === "object" && enabled.columns?.length ? enabled.columns : childCols.map((c) => c.name);
|
|
1505
|
-
relColsMap[relName] = selected;
|
|
1506
|
-
for (const name of selected)
|
|
1507
|
-
selectParts.push(
|
|
1508
|
-
`${child._tableName}.${name} AS __rel_${relName}_${name}`
|
|
1509
|
-
);
|
|
1510
|
-
}
|
|
1511
|
-
let sqlText = `SELECT ${selectParts.join(", ")} FROM ${base._tableName}${joins.length ? " " + joins.join(" ") : ""}`;
|
|
1512
|
-
const bindings = [];
|
|
1513
|
-
if (opts?.where) {
|
|
1514
|
-
if (typeof opts.where === "function") {
|
|
1515
|
-
const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
|
|
1516
|
-
sqlText += ` WHERE ${w.clause}`;
|
|
1517
|
-
bindings.push(...w.bindings);
|
|
1518
|
-
} else if (typeof opts.where.toSQL === "function") {
|
|
1519
|
-
const w = opts.where.toSQL();
|
|
1520
|
-
sqlText += ` WHERE ${w.clause}`;
|
|
1521
|
-
bindings.push(...w.bindings);
|
|
1522
|
-
} else {
|
|
1523
|
-
const entries = Object.entries(opts.where);
|
|
1524
|
-
if (entries.length > 0) {
|
|
1525
|
-
sqlText += ` WHERE ${entries.map(([k]) => `${base._tableName}.${k} = ?`).join(" AND ")}`;
|
|
1526
|
-
bindings.push(...entries.map(([, v]) => v));
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
const orderByClauses = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
|
|
1531
|
-
if (orderByClauses?.length)
|
|
1532
|
-
sqlText += ` ORDER BY ${orderByClauses.join(", ")}`;
|
|
1533
|
-
if (typeof opts?.limit === "number")
|
|
1534
|
-
sqlText += ` LIMIT ${opts.limit}`;
|
|
1535
|
-
if (typeof opts?.offset === "number")
|
|
1536
|
-
sqlText += ` OFFSET ${opts.offset}`;
|
|
1537
|
-
const rows = await dbi.select(sqlText, bindings);
|
|
1538
|
-
const groups = /* @__PURE__ */ new Map();
|
|
1539
|
-
for (const row of rows) {
|
|
1540
|
-
const baseObj = {};
|
|
1541
|
-
for (const name of baseSelected2)
|
|
1542
|
-
baseObj[name] = row[`__base_${name}`];
|
|
1543
|
-
const baseKey = baseObj[basePk.name];
|
|
1544
|
-
if (!groups.has(baseKey)) {
|
|
1545
|
-
const seed = { ...baseObj };
|
|
1546
|
-
for (const [relName, enabled] of Object.entries(withSpec)) {
|
|
1547
|
-
if (!enabled) continue;
|
|
1548
|
-
const rel = rels[relName];
|
|
1549
|
-
if (!rel) continue;
|
|
1550
|
-
seed[relName] = rel.kind === "many" ? [] : null;
|
|
1551
|
-
}
|
|
1552
|
-
groups.set(baseKey, seed);
|
|
1553
|
-
}
|
|
1554
|
-
const acc = groups.get(baseKey);
|
|
1555
|
-
for (const [relName, enabled] of Object.entries(withSpec)) {
|
|
1556
|
-
if (!enabled) continue;
|
|
1557
|
-
const rel = rels[relName];
|
|
1558
|
-
if (!rel) continue;
|
|
1559
|
-
const childCols = relColsMap[relName];
|
|
1560
|
-
const childObj = {};
|
|
1561
|
-
let allNull = true;
|
|
1562
|
-
for (const name of childCols) {
|
|
1563
|
-
const v = row[`__rel_${relName}_${name}`];
|
|
1564
|
-
childObj[name] = v;
|
|
1565
|
-
if (v !== null && v !== void 0) allNull = false;
|
|
1566
|
-
}
|
|
1567
|
-
if (allNull) continue;
|
|
1568
|
-
if (rel.kind === "many") {
|
|
1569
|
-
const childPk = fkMap[relName].childPk;
|
|
1570
|
-
if (childPk) {
|
|
1571
|
-
if (!acc[relName]) acc[relName] = [];
|
|
1572
|
-
const exists2 = acc[relName].some(
|
|
1573
|
-
(r) => r[childPk.name] === childObj[childPk.name]
|
|
1574
|
-
);
|
|
1575
|
-
if (!exists2) acc[relName].push(childObj);
|
|
1576
|
-
} else {
|
|
1577
|
-
acc[relName].push(childObj);
|
|
1578
|
-
}
|
|
1579
|
-
} else {
|
|
1580
|
-
acc[relName] = childObj;
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
1584
|
-
return Array.from(groups.values());
|
|
1585
|
-
}
|
|
1586
|
-
let baseSelected;
|
|
1587
|
-
if (opts?.columns && !Array.isArray(opts.columns)) {
|
|
1588
|
-
baseSelected = Object.entries(opts.columns).filter(([, v]) => !!v).map(([k]) => k);
|
|
1589
|
-
} else if (Array.isArray(opts?.columns) && opts.columns.length > 0) {
|
|
1590
|
-
baseSelected = opts.columns;
|
|
1591
|
-
} else {
|
|
1592
|
-
baseSelected = Object.values(base._schema).map(
|
|
1593
|
-
(c) => c.name
|
|
1594
|
-
);
|
|
1595
|
-
}
|
|
1596
|
-
let baseSql = `SELECT ${baseSelected.join(", ")} FROM ${base._tableName}`;
|
|
1597
|
-
const baseBindings = [];
|
|
1598
|
-
if (opts?.where) {
|
|
1599
|
-
if (typeof opts.where === "function") {
|
|
1600
|
-
const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
|
|
1601
|
-
baseSql += ` WHERE ${w.clause}`;
|
|
1602
|
-
baseBindings.push(...w.bindings);
|
|
1603
|
-
} else if (typeof opts.where.toSQL === "function") {
|
|
1604
|
-
const w = opts.where.toSQL();
|
|
1605
|
-
baseSql += ` WHERE ${w.clause}`;
|
|
1606
|
-
baseBindings.push(...w.bindings);
|
|
1607
|
-
} else {
|
|
1608
|
-
const entries = Object.entries(opts.where);
|
|
1609
|
-
if (entries.length > 0) {
|
|
1610
|
-
baseSql += ` WHERE ${entries.map(([k]) => `${k} = ?`).join(" AND ")}`;
|
|
1611
|
-
baseBindings.push(...entries.map(([, v]) => v));
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
const orderByClauses2 = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
|
|
1616
|
-
if (orderByClauses2?.length)
|
|
1617
|
-
baseSql += ` ORDER BY ${orderByClauses2.join(", ")}`;
|
|
1618
|
-
if (typeof opts?.limit === "number") baseSql += ` LIMIT ${opts.limit}`;
|
|
1619
|
-
if (typeof opts?.offset === "number")
|
|
1620
|
-
baseSql += ` OFFSET ${opts.offset}`;
|
|
1621
|
-
const baseRows = await dbi.select(baseSql, baseBindings);
|
|
1622
|
-
const result = baseRows.map((r) => ({ ...r }));
|
|
1623
|
-
async function loadRelationsFor(parents, parentTable, spec) {
|
|
1624
|
-
const parentPk = getPrimaryKey(parentTable);
|
|
1625
|
-
const parentIds = parents.map((p) => p[parentPk.name]);
|
|
1626
|
-
const relsMap = relDefs[Object.keys(tables).find(
|
|
1627
|
-
(k) => tables[k]._tableName === parentTable._tableName
|
|
1628
|
-
)] || {};
|
|
1629
|
-
for (const [relName, v] of Object.entries(spec)) {
|
|
1630
|
-
const enabled = v;
|
|
1631
|
-
const rel = relsMap[relName];
|
|
1632
|
-
if (!rel) continue;
|
|
1633
|
-
const child = rel.table;
|
|
1634
|
-
const childCols = Object.values(child._schema);
|
|
1635
|
-
const selectCols = enabled?.columns && enabled.columns.length > 0 ? enabled.columns : childCols.map((c) => c.name);
|
|
1636
|
-
if (rel.kind === "many") {
|
|
1637
|
-
const fkCol = guessChildFk(child, parentTable, rel);
|
|
1638
|
-
if (!fkCol) continue;
|
|
1639
|
-
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
|
|
1640
|
-
const rows = await dbi.select(sql2, parentIds);
|
|
1641
|
-
const buckets = /* @__PURE__ */ new Map();
|
|
1642
|
-
for (const r of rows) {
|
|
1643
|
-
const key = r[fkCol.name];
|
|
1644
|
-
if (!buckets.has(key)) buckets.set(key, []);
|
|
1645
|
-
buckets.get(key).push(r);
|
|
1646
|
-
}
|
|
1647
|
-
for (const p of parents)
|
|
1648
|
-
p[relName] = buckets.get(p[parentPk.name]) ?? [];
|
|
1649
|
-
if (enabled?.with) {
|
|
1650
|
-
const children = parents.flatMap(
|
|
1651
|
-
(p) => p[relName]
|
|
1652
|
-
);
|
|
1653
|
-
if (children.length > 0)
|
|
1654
|
-
await loadRelationsFor(children, child, enabled.with);
|
|
1655
|
-
}
|
|
1656
|
-
} else {
|
|
1657
|
-
const mapping = guessOneRelationJoin(parentTable, rel);
|
|
1658
|
-
if (!mapping) continue;
|
|
1659
|
-
if (mapping.lhsTable._tableName === child._tableName) {
|
|
1660
|
-
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${mapping.lhsCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
|
|
1661
|
-
const rows = await dbi.select(sql2, parentIds);
|
|
1662
|
-
const mapOne = /* @__PURE__ */ new Map();
|
|
1663
|
-
for (const r of rows) mapOne.set(r[mapping.lhsCol.name], r);
|
|
1664
|
-
for (const p of parents)
|
|
1665
|
-
p[relName] = mapOne.get(p[parentPk.name]) ?? null;
|
|
1666
|
-
} else {
|
|
1667
|
-
const parentFkName = mapping.lhsCol.name;
|
|
1668
|
-
const childPkName = mapping.rhsCol.name;
|
|
1669
|
-
const childIds = parents.map((p) => p[parentFkName]).filter((v2) => v2 !== void 0 && v2 !== null);
|
|
1670
|
-
if (childIds.length === 0) {
|
|
1671
|
-
for (const p of parents) p[relName] = null;
|
|
1672
|
-
} else {
|
|
1673
|
-
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${childPkName} IN (${childIds.map(() => "?").join(", ")})`;
|
|
1674
|
-
const rows = await dbi.select(sql2, childIds);
|
|
1675
|
-
const mapOne = /* @__PURE__ */ new Map();
|
|
1676
|
-
for (const r of rows) mapOne.set(r[childPkName], r);
|
|
1677
|
-
for (const p of parents)
|
|
1678
|
-
p[relName] = mapOne.get(p[parentFkName]) ?? null;
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
if (enabled?.with) {
|
|
1682
|
-
const children = parents.map((p) => p[relName]).filter((x) => Boolean(x));
|
|
1683
|
-
if (children.length > 0)
|
|
1684
|
-
await loadRelationsFor(children, child, enabled.with);
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
if (Object.keys(withSpec).length > 0) {
|
|
1690
|
-
await loadRelationsFor(result, base, withSpec);
|
|
1691
|
-
}
|
|
1692
|
-
return result;
|
|
1693
|
-
},
|
|
1694
|
-
async findFirst(opts) {
|
|
1695
|
-
const rows = await api[tblKey].findMany({ ...opts, limit: 1 });
|
|
1696
|
-
return rows?.[0] ?? null;
|
|
1697
|
-
}
|
|
1698
|
-
};
|
|
1699
|
-
}
|
|
1700
|
-
return api;
|
|
1701
|
-
}
|
|
377
|
+
var relations = (table, relationsCallback) => {
|
|
378
|
+
return relationsCallback({
|
|
379
|
+
one: (table2, config) => ({
|
|
380
|
+
table: table2,
|
|
381
|
+
type: "one",
|
|
382
|
+
foreignKey: config.fields[0],
|
|
383
|
+
localKey: config.references[0]
|
|
384
|
+
}),
|
|
385
|
+
many: (table2) => ({
|
|
386
|
+
table: table2,
|
|
387
|
+
type: "many"
|
|
388
|
+
})
|
|
389
|
+
});
|
|
390
|
+
};
|
|
1702
391
|
export {
|
|
392
|
+
DeleteQueryBuilder,
|
|
393
|
+
InsertQueryBuilder,
|
|
394
|
+
SQLiteColumn,
|
|
395
|
+
SelectQueryBuilder,
|
|
396
|
+
Table,
|
|
1703
397
|
TauriORM,
|
|
398
|
+
UpdateQueryBuilder,
|
|
1704
399
|
and,
|
|
1705
|
-
asc,
|
|
1706
|
-
between,
|
|
1707
400
|
blob,
|
|
1708
401
|
boolean,
|
|
1709
|
-
check,
|
|
1710
|
-
defineTable,
|
|
1711
|
-
desc,
|
|
1712
402
|
eq,
|
|
1713
|
-
exists,
|
|
1714
|
-
foreignKey,
|
|
1715
|
-
getQualifiedName,
|
|
1716
403
|
gt,
|
|
1717
404
|
gte,
|
|
1718
|
-
ilike,
|
|
1719
405
|
inArray,
|
|
1720
|
-
increments,
|
|
1721
|
-
index,
|
|
1722
406
|
integer,
|
|
1723
407
|
isNotNull,
|
|
1724
408
|
isNull,
|
|
1725
409
|
like,
|
|
1726
410
|
lt,
|
|
1727
411
|
lte,
|
|
1728
|
-
makeQueryAPI,
|
|
1729
|
-
ne,
|
|
1730
|
-
not,
|
|
1731
|
-
notBetween,
|
|
1732
|
-
notExists,
|
|
1733
|
-
notIlike,
|
|
1734
|
-
notInArray,
|
|
1735
|
-
numeric,
|
|
1736
412
|
or,
|
|
1737
|
-
primaryKey,
|
|
1738
|
-
raw,
|
|
1739
413
|
real,
|
|
1740
414
|
relations,
|
|
1741
|
-
|
|
1742
|
-
text
|
|
1743
|
-
timestamp,
|
|
1744
|
-
unique,
|
|
1745
|
-
uniqueIndex
|
|
415
|
+
sqliteTable,
|
|
416
|
+
text
|
|
1746
417
|
};
|