@type32/tauri-sqlite-orm 0.1.3 → 0.1.5
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/LICENSE +21 -21
- package/README.md +247 -210
- package/dist/index.d.mts +194 -34
- package/dist/index.d.ts +194 -34
- package/dist/index.js +781 -158
- package/dist/index.mjs +758 -154
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -31,53 +31,58 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
TauriORM: () => TauriORM,
|
|
34
|
+
and: () => and,
|
|
34
35
|
asc: () => asc,
|
|
36
|
+
between: () => between,
|
|
35
37
|
blob: () => blob,
|
|
36
38
|
boolean: () => boolean,
|
|
37
|
-
|
|
39
|
+
check: () => check,
|
|
38
40
|
defineTable: () => defineTable,
|
|
39
41
|
desc: () => desc,
|
|
40
42
|
eq: () => eq,
|
|
41
|
-
|
|
43
|
+
exists: () => exists,
|
|
44
|
+
foreignKey: () => foreignKey,
|
|
45
|
+
getQualifiedName: () => getQualifiedName,
|
|
42
46
|
gt: () => gt,
|
|
43
47
|
gte: () => gte,
|
|
44
|
-
|
|
48
|
+
ilike: () => ilike,
|
|
49
|
+
inArray: () => inArray,
|
|
50
|
+
increments: () => increments,
|
|
51
|
+
index: () => index,
|
|
45
52
|
integer: () => integer,
|
|
53
|
+
isNotNull: () => isNotNull,
|
|
54
|
+
isNull: () => isNull,
|
|
46
55
|
like: () => like,
|
|
47
56
|
lt: () => lt,
|
|
48
57
|
lte: () => lte,
|
|
49
58
|
makeQueryAPI: () => makeQueryAPI,
|
|
50
59
|
ne: () => ne,
|
|
60
|
+
not: () => not,
|
|
61
|
+
notBetween: () => notBetween,
|
|
62
|
+
notExists: () => notExists,
|
|
63
|
+
notIlike: () => notIlike,
|
|
64
|
+
notInArray: () => notInArray,
|
|
51
65
|
numeric: () => numeric,
|
|
66
|
+
or: () => or,
|
|
67
|
+
primaryKey: () => primaryKey,
|
|
68
|
+
raw: () => raw,
|
|
52
69
|
real: () => real,
|
|
53
70
|
relations: () => relations,
|
|
54
71
|
sql: () => sql,
|
|
55
72
|
text: () => text,
|
|
56
|
-
timestamp: () => timestamp
|
|
73
|
+
timestamp: () => timestamp,
|
|
74
|
+
unique: () => unique,
|
|
75
|
+
uniqueIndex: () => uniqueIndex
|
|
57
76
|
});
|
|
58
77
|
module.exports = __toCommonJS(index_exports);
|
|
59
78
|
|
|
60
|
-
// src/connection.ts
|
|
61
|
-
var import_plugin_sql = __toESM(require("@tauri-apps/plugin-sql"));
|
|
62
|
-
var db = null;
|
|
63
|
-
async function initDb(dbPath) {
|
|
64
|
-
db = await import_plugin_sql.default.load(dbPath);
|
|
65
|
-
return db;
|
|
66
|
-
}
|
|
67
|
-
function getDb() {
|
|
68
|
-
if (!db) {
|
|
69
|
-
throw new Error("Database not initialized. Please call initDb() first.");
|
|
70
|
-
}
|
|
71
|
-
return db;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
79
|
// src/schema-builder.ts
|
|
75
80
|
function sql(strings, ...values) {
|
|
76
|
-
const
|
|
81
|
+
const raw2 = strings.reduce(
|
|
77
82
|
(acc, part, idx) => acc + part + (idx < values.length ? String(values[idx]) : ""),
|
|
78
83
|
""
|
|
79
84
|
);
|
|
80
|
-
return { raw };
|
|
85
|
+
return { raw: raw2 };
|
|
81
86
|
}
|
|
82
87
|
function createColumn(params) {
|
|
83
88
|
const col = { ...params };
|
|
@@ -99,6 +104,18 @@ function createColumn(params) {
|
|
|
99
104
|
col.defaultFn = fn;
|
|
100
105
|
return col;
|
|
101
106
|
};
|
|
107
|
+
col.$default = (fn) => {
|
|
108
|
+
col.defaultFn = fn;
|
|
109
|
+
return col;
|
|
110
|
+
};
|
|
111
|
+
col.$onUpdate = (fn) => {
|
|
112
|
+
col.onUpdateFn = fn;
|
|
113
|
+
return col;
|
|
114
|
+
};
|
|
115
|
+
col.$onUpdateFn = (fn) => {
|
|
116
|
+
col.onUpdateFn = fn;
|
|
117
|
+
return col;
|
|
118
|
+
};
|
|
102
119
|
col.references = (target, actions) => {
|
|
103
120
|
const t = target();
|
|
104
121
|
col.references = {
|
|
@@ -111,34 +128,43 @@ function createColumn(params) {
|
|
|
111
128
|
};
|
|
112
129
|
return col;
|
|
113
130
|
}
|
|
114
|
-
function text(
|
|
131
|
+
function text(nameOrConfig, maybeConfig) {
|
|
132
|
+
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
133
|
+
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
115
134
|
const col = createColumn({
|
|
116
135
|
name,
|
|
117
136
|
type: "TEXT",
|
|
118
|
-
isPrimaryKey: config?.isPrimaryKey,
|
|
119
137
|
_dataType: ""
|
|
120
138
|
});
|
|
121
139
|
if (config?.enum) col.enumValues = config.enum;
|
|
140
|
+
if (config?.mode) col.mode = config.mode;
|
|
122
141
|
return col;
|
|
123
142
|
}
|
|
124
|
-
function integer(
|
|
143
|
+
function integer(nameOrConfig, maybeConfig) {
|
|
144
|
+
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
145
|
+
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
125
146
|
let dt = 0;
|
|
126
147
|
if (config?.mode === "boolean") dt = false;
|
|
127
|
-
if (config?.mode === "timestamp"
|
|
148
|
+
if (config?.mode === "timestamp" || config?.mode === "timestamp_ms")
|
|
149
|
+
dt = /* @__PURE__ */ new Date();
|
|
128
150
|
const col = createColumn({
|
|
129
151
|
name,
|
|
130
152
|
type: "INTEGER",
|
|
131
|
-
isPrimaryKey: config?.isPrimaryKey,
|
|
132
|
-
autoIncrement: config?.autoIncrement,
|
|
133
153
|
mode: config?.mode ?? "number",
|
|
134
154
|
_dataType: dt
|
|
135
155
|
});
|
|
136
156
|
return col;
|
|
137
157
|
}
|
|
138
158
|
function real(name) {
|
|
139
|
-
return createColumn({
|
|
159
|
+
return createColumn({
|
|
160
|
+
name: name ?? "",
|
|
161
|
+
type: "REAL",
|
|
162
|
+
_dataType: 0
|
|
163
|
+
});
|
|
140
164
|
}
|
|
141
|
-
function blob(
|
|
165
|
+
function blob(nameOrConfig, maybeConfig) {
|
|
166
|
+
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
167
|
+
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
142
168
|
let dt = new Uint8Array();
|
|
143
169
|
if (config?.mode === "bigint") dt = 0n;
|
|
144
170
|
if (config?.mode === "json") dt = void 0;
|
|
@@ -149,7 +175,9 @@ function blob(name, config) {
|
|
|
149
175
|
_dataType: dt
|
|
150
176
|
});
|
|
151
177
|
}
|
|
152
|
-
function numeric(
|
|
178
|
+
function numeric(nameOrConfig, maybeConfig) {
|
|
179
|
+
const name = typeof nameOrConfig === "string" ? nameOrConfig : "";
|
|
180
|
+
const config = typeof nameOrConfig === "string" ? maybeConfig : nameOrConfig;
|
|
153
181
|
let dt = "";
|
|
154
182
|
if (config?.mode === "number") dt = 0;
|
|
155
183
|
if (config?.mode === "bigint") dt = 0n;
|
|
@@ -160,59 +188,346 @@ function numeric(name, config) {
|
|
|
160
188
|
_dataType: dt
|
|
161
189
|
});
|
|
162
190
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
function boolean(name) {
|
|
192
|
+
return createColumn({
|
|
193
|
+
name: name ?? "",
|
|
194
|
+
type: "INTEGER",
|
|
195
|
+
_dataType: false,
|
|
196
|
+
mode: "boolean"
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function timestamp(name) {
|
|
200
|
+
return createColumn({
|
|
201
|
+
name: name ?? "",
|
|
202
|
+
type: "INTEGER",
|
|
203
|
+
_dataType: /* @__PURE__ */ new Date(),
|
|
204
|
+
mode: "timestamp"
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function increments(name) {
|
|
208
|
+
return integer(name ?? "").primaryKey({
|
|
209
|
+
autoIncrement: true
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function unique(name) {
|
|
213
|
+
return {
|
|
214
|
+
on: (...cols) => ({ name, columns: cols.map((c) => c.name) })
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function primaryKey(opts) {
|
|
218
|
+
return { name: opts.name, columns: opts.columns.map((c) => c.name) };
|
|
219
|
+
}
|
|
220
|
+
function check(name, expr) {
|
|
221
|
+
return { name, expr };
|
|
222
|
+
}
|
|
223
|
+
function foreignKey(opts) {
|
|
224
|
+
const first = opts.columns[0];
|
|
225
|
+
return {
|
|
226
|
+
name: opts.name,
|
|
227
|
+
columns: opts.columns.map((c) => c.name),
|
|
228
|
+
foreignTable: first?.tableName || opts.foreignColumns[0]?.tableName || "",
|
|
229
|
+
foreignColumns: opts.foreignColumns.map((c) => c.name),
|
|
230
|
+
onDelete: opts.onDelete,
|
|
231
|
+
onUpdate: opts.onUpdate
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function index(name) {
|
|
235
|
+
return {
|
|
236
|
+
on: (...cols) => ({ name, columns: cols.map((c) => c.name) }),
|
|
237
|
+
where: (expr) => ({ name, columns: [], where: expr })
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function uniqueIndex(name) {
|
|
241
|
+
return {
|
|
242
|
+
on: (...cols) => ({ name, columns: cols.map((c) => c.name), unique: true }),
|
|
243
|
+
where: (expr) => ({ name, columns: [], unique: true, where: expr })
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function defineTable(tableName, schema, extras) {
|
|
176
247
|
const finalizedSchema = { ...schema };
|
|
177
248
|
for (const key of Object.keys(finalizedSchema)) {
|
|
178
249
|
const col = finalizedSchema[key];
|
|
250
|
+
if (!col.name || col.name === "") col.name = key;
|
|
179
251
|
col.tableName = tableName;
|
|
180
252
|
}
|
|
181
253
|
const table = {
|
|
182
254
|
_tableName: tableName,
|
|
183
255
|
_schema: finalizedSchema,
|
|
256
|
+
_constraints: [],
|
|
257
|
+
_indexes: [],
|
|
184
258
|
// The Drizzle-like type inference properties
|
|
185
259
|
$inferSelect: {},
|
|
186
260
|
$inferInsert: {}
|
|
187
|
-
//
|
|
261
|
+
// omit PK columns
|
|
188
262
|
};
|
|
189
263
|
for (const [key, col] of Object.entries(finalizedSchema)) {
|
|
190
264
|
table[key] = col;
|
|
191
265
|
}
|
|
266
|
+
if (extras) {
|
|
267
|
+
const specs = extras(table) || [];
|
|
268
|
+
for (const s of specs) {
|
|
269
|
+
if (s.columns && s.unique !== void 0) {
|
|
270
|
+
table._indexes.push(s);
|
|
271
|
+
} else if (s.columns && s.foreignColumns) {
|
|
272
|
+
table._constraints.push(s);
|
|
273
|
+
} else if (s.columns && (s.name || s.name === void 0)) {
|
|
274
|
+
if (s.columns && s.name !== void 0 && s.columns.length > 0) {
|
|
275
|
+
const pk = s;
|
|
276
|
+
if (pk.columns.length > 1 || pk.name && pk.name.length > 0) {
|
|
277
|
+
table._constraints.push(s);
|
|
278
|
+
} else {
|
|
279
|
+
table._constraints.push(s);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
table._constraints.push(s);
|
|
283
|
+
}
|
|
284
|
+
} else if (s.expr) {
|
|
285
|
+
table._constraints.push(s);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
192
289
|
return table;
|
|
193
290
|
}
|
|
194
291
|
|
|
292
|
+
// src/orm.ts
|
|
293
|
+
var import_plugin_sql = __toESM(require("@tauri-apps/plugin-sql"));
|
|
294
|
+
|
|
295
|
+
// src/sql-helpers.ts
|
|
296
|
+
function raw(strings, ...values) {
|
|
297
|
+
return {
|
|
298
|
+
toSQL: () => {
|
|
299
|
+
let clause = "";
|
|
300
|
+
const bindings = [];
|
|
301
|
+
for (let i = 0; i < strings.length; i++) {
|
|
302
|
+
clause += strings[i];
|
|
303
|
+
if (i < values.length) {
|
|
304
|
+
const v = values[i];
|
|
305
|
+
if (v && typeof v === "object" && typeof v.toSQL === "function") {
|
|
306
|
+
const s = v.toSQL();
|
|
307
|
+
clause += s.clause;
|
|
308
|
+
bindings.push(...s.bindings);
|
|
309
|
+
} else if (v && typeof v === "object" && "_dataType" in v) {
|
|
310
|
+
clause += getQualifiedName(v);
|
|
311
|
+
} else {
|
|
312
|
+
clause += "?";
|
|
313
|
+
bindings.push(v);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return { clause, bindings };
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function isColumn(value) {
|
|
322
|
+
return typeof value === "object" && value !== null && "_dataType" in value;
|
|
323
|
+
}
|
|
324
|
+
function getQualifiedName(column) {
|
|
325
|
+
if (column.tableName) return `${column.tableName}.${column.name}`;
|
|
326
|
+
return column.name;
|
|
327
|
+
}
|
|
328
|
+
function comparison(operator, column, value) {
|
|
329
|
+
return {
|
|
330
|
+
toSQL: () => {
|
|
331
|
+
if (isColumn(value)) {
|
|
332
|
+
return {
|
|
333
|
+
clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
|
|
334
|
+
value
|
|
335
|
+
)}`,
|
|
336
|
+
bindings: []
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
clause: `${getQualifiedName(column)} ${operator} ?`,
|
|
341
|
+
bindings: [value]
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
var and = (...conditions) => ({
|
|
347
|
+
toSQL: () => {
|
|
348
|
+
const parts = [];
|
|
349
|
+
const bindings = [];
|
|
350
|
+
for (const c of conditions) {
|
|
351
|
+
const s = c.toSQL();
|
|
352
|
+
parts.push(`(${s.clause})`);
|
|
353
|
+
bindings.push(...s.bindings);
|
|
354
|
+
}
|
|
355
|
+
return { clause: parts.join(" AND "), bindings };
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
var or = (...conditions) => ({
|
|
359
|
+
toSQL: () => {
|
|
360
|
+
const parts = [];
|
|
361
|
+
const bindings = [];
|
|
362
|
+
for (const c of conditions) {
|
|
363
|
+
const s = c.toSQL();
|
|
364
|
+
parts.push(`(${s.clause})`);
|
|
365
|
+
bindings.push(...s.bindings);
|
|
366
|
+
}
|
|
367
|
+
return { clause: parts.join(" OR "), bindings };
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
var not = (condition) => ({
|
|
371
|
+
toSQL: () => {
|
|
372
|
+
const s = condition.toSQL();
|
|
373
|
+
return { clause: `NOT (${s.clause})`, bindings: s.bindings };
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
var eq = (column, value) => comparison("=", column, value);
|
|
377
|
+
var ne = (column, value) => comparison("!=", column, value);
|
|
378
|
+
var gt = (column, value) => comparison(">", column, value);
|
|
379
|
+
var gte = (column, value) => comparison(">=", column, value);
|
|
380
|
+
var lt = (column, value) => comparison("<", column, value);
|
|
381
|
+
var lte = (column, value) => comparison("<=", column, value);
|
|
382
|
+
var like = (column, value) => comparison("LIKE", column, value);
|
|
383
|
+
var ilike = (column, value) => ({
|
|
384
|
+
toSQL: () => {
|
|
385
|
+
const colExpr = `LOWER(${getQualifiedName(column)})`;
|
|
386
|
+
if (isColumn(value)) {
|
|
387
|
+
return {
|
|
388
|
+
clause: `${colExpr} LIKE LOWER(${getQualifiedName(value)})`,
|
|
389
|
+
bindings: []
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return { clause: `${colExpr} LIKE LOWER(?)`, bindings: [value] };
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
var notIlike = (column, value) => ({
|
|
396
|
+
toSQL: () => {
|
|
397
|
+
const colExpr = `LOWER(${getQualifiedName(column)})`;
|
|
398
|
+
if (isColumn(value)) {
|
|
399
|
+
return {
|
|
400
|
+
clause: `${colExpr} NOT LIKE LOWER(${getQualifiedName(value)})`,
|
|
401
|
+
bindings: []
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
return { clause: `${colExpr} NOT LIKE LOWER(?)`, bindings: [value] };
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
var isNull = (column) => ({
|
|
408
|
+
toSQL: () => ({
|
|
409
|
+
clause: `${getQualifiedName(column)} IS NULL`,
|
|
410
|
+
bindings: []
|
|
411
|
+
})
|
|
412
|
+
});
|
|
413
|
+
var isNotNull = (column) => ({
|
|
414
|
+
toSQL: () => ({
|
|
415
|
+
clause: `${getQualifiedName(column)} IS NOT NULL`,
|
|
416
|
+
bindings: []
|
|
417
|
+
})
|
|
418
|
+
});
|
|
419
|
+
var between = (column, from, to) => ({
|
|
420
|
+
toSQL: () => {
|
|
421
|
+
const left = getQualifiedName(column);
|
|
422
|
+
const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
|
|
423
|
+
const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
|
|
424
|
+
return {
|
|
425
|
+
clause: `${left} BETWEEN ${fromClause} AND ${toClause}`,
|
|
426
|
+
bindings: [...fromBindings, ...toBindings]
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
var notBetween = (column, from, to) => ({
|
|
431
|
+
toSQL: () => {
|
|
432
|
+
const left = getQualifiedName(column);
|
|
433
|
+
const [fromClause, fromBindings] = isColumn(from) ? [getQualifiedName(from), []] : ["?", [from]];
|
|
434
|
+
const [toClause, toBindings] = isColumn(to) ? [getQualifiedName(to), []] : ["?", [to]];
|
|
435
|
+
return {
|
|
436
|
+
clause: `${left} NOT BETWEEN ${fromClause} AND ${toClause}`,
|
|
437
|
+
bindings: [...fromBindings, ...toBindings]
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
var inArray = (column, valuesOrQuery) => ({
|
|
442
|
+
toSQL: () => {
|
|
443
|
+
const left = getQualifiedName(column);
|
|
444
|
+
if (Array.isArray(valuesOrQuery)) {
|
|
445
|
+
const placeholders = valuesOrQuery.map(() => "?").join(", ");
|
|
446
|
+
return {
|
|
447
|
+
clause: `${left} IN (${placeholders})`,
|
|
448
|
+
bindings: valuesOrQuery
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
|
|
452
|
+
return { clause: `${left} IN (${sq.clause})`, bindings: sq.bindings };
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
var notInArray = (column, valuesOrQuery) => ({
|
|
456
|
+
toSQL: () => {
|
|
457
|
+
const left = getQualifiedName(column);
|
|
458
|
+
if (Array.isArray(valuesOrQuery)) {
|
|
459
|
+
const placeholders = valuesOrQuery.map(() => "?").join(", ");
|
|
460
|
+
return {
|
|
461
|
+
clause: `${left} NOT IN (${placeholders})`,
|
|
462
|
+
bindings: valuesOrQuery
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
const sq = valuesOrQuery.toSQL ? valuesOrQuery.toSQL() : valuesOrQuery.toSQL();
|
|
466
|
+
return { clause: `${left} NOT IN (${sq.clause})`, bindings: sq.bindings };
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
var exists = (subquery) => ({
|
|
470
|
+
toSQL: () => {
|
|
471
|
+
const sq = subquery.toSQL ? subquery.toSQL() : subquery.toSQL();
|
|
472
|
+
return { clause: `EXISTS (${sq.clause})`, bindings: sq.bindings };
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
var notExists = (subquery) => ({
|
|
476
|
+
toSQL: () => {
|
|
477
|
+
const sq = subquery.toSQL ? subquery.toSQL() : subquery.toSQL();
|
|
478
|
+
return { clause: `NOT EXISTS (${sq.clause})`, bindings: sq.bindings };
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
var asc = (column) => `${getQualifiedName(column)} ASC`;
|
|
482
|
+
var desc = (column) => `${getQualifiedName(column)} DESC`;
|
|
483
|
+
|
|
195
484
|
// src/orm.ts
|
|
196
485
|
var SelectQueryBuilder = class {
|
|
197
486
|
_table = null;
|
|
198
|
-
_selectedColumns = [
|
|
487
|
+
_selectedColumns = [];
|
|
199
488
|
_joins = [];
|
|
200
489
|
_where = [];
|
|
201
490
|
_orderBy = [];
|
|
202
491
|
_limit = null;
|
|
203
492
|
_offset = null;
|
|
204
|
-
|
|
205
|
-
|
|
493
|
+
_groupBy = [];
|
|
494
|
+
_having = [];
|
|
495
|
+
_distinct = false;
|
|
496
|
+
_dbProvider;
|
|
497
|
+
constructor(dbProvider, fields) {
|
|
498
|
+
this._dbProvider = dbProvider;
|
|
206
499
|
if (fields) {
|
|
207
|
-
|
|
500
|
+
for (const [alias, col] of Object.entries(fields)) {
|
|
501
|
+
const sql2 = getQualifiedName(col);
|
|
502
|
+
this._selectedColumns.push({ sql: sql2, alias });
|
|
503
|
+
}
|
|
208
504
|
}
|
|
209
505
|
}
|
|
506
|
+
distinct() {
|
|
507
|
+
this._distinct = true;
|
|
508
|
+
return this;
|
|
509
|
+
}
|
|
510
|
+
select(fields) {
|
|
511
|
+
this._selectedColumns = [];
|
|
512
|
+
for (const [alias, expr] of Object.entries(fields)) {
|
|
513
|
+
if (typeof expr.toSQL === "function") {
|
|
514
|
+
const s = expr.toSQL();
|
|
515
|
+
this._selectedColumns.push({ sql: s.clause, alias });
|
|
516
|
+
} else {
|
|
517
|
+
this._selectedColumns.push({
|
|
518
|
+
sql: getQualifiedName(expr),
|
|
519
|
+
alias
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return this;
|
|
524
|
+
}
|
|
210
525
|
from(table) {
|
|
211
526
|
this._table = table;
|
|
212
527
|
return this;
|
|
213
528
|
}
|
|
214
529
|
where(...conditions) {
|
|
215
|
-
this._where.push(...conditions);
|
|
530
|
+
this._where.push(...conditions.filter(Boolean));
|
|
216
531
|
return this;
|
|
217
532
|
}
|
|
218
533
|
leftJoin(otherTable, on) {
|
|
@@ -221,8 +536,26 @@ var SelectQueryBuilder = class {
|
|
|
221
536
|
this._joins.push(joinClause);
|
|
222
537
|
return this;
|
|
223
538
|
}
|
|
539
|
+
groupBy(...exprs) {
|
|
540
|
+
for (const e of exprs) {
|
|
541
|
+
if (!e) continue;
|
|
542
|
+
if (typeof e === "string") this._groupBy.push(e);
|
|
543
|
+
else this._groupBy.push(getQualifiedName(e));
|
|
544
|
+
}
|
|
545
|
+
return this;
|
|
546
|
+
}
|
|
547
|
+
having(...conditions) {
|
|
548
|
+
this._having.push(...conditions);
|
|
549
|
+
return this;
|
|
550
|
+
}
|
|
224
551
|
orderBy(...clauses) {
|
|
225
|
-
|
|
552
|
+
for (const c of clauses) {
|
|
553
|
+
if (!c) continue;
|
|
554
|
+
if (typeof c === "string") this._orderBy.push(c);
|
|
555
|
+
else if (typeof c.toSQL === "function")
|
|
556
|
+
this._orderBy.push(c);
|
|
557
|
+
else this._orderBy.push(getQualifiedName(c));
|
|
558
|
+
}
|
|
226
559
|
return this;
|
|
227
560
|
}
|
|
228
561
|
limit(value) {
|
|
@@ -233,17 +566,15 @@ var SelectQueryBuilder = class {
|
|
|
233
566
|
this._offset = value;
|
|
234
567
|
return this;
|
|
235
568
|
}
|
|
236
|
-
// The final execution step
|
|
237
569
|
async execute() {
|
|
238
570
|
if (!this._table) {
|
|
239
571
|
throw new Error("Cannot execute select query without a 'from' table.");
|
|
240
572
|
}
|
|
241
|
-
const
|
|
573
|
+
const db = await this._dbProvider();
|
|
242
574
|
const bindings = [];
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
575
|
+
const selectList = this._selectedColumns.length > 0 ? this._selectedColumns.map((c) => c.alias ? `${c.sql} AS ${c.alias}` : c.sql).join(", ") : Object.values(this._table._schema).map((c) => `${this._table._tableName}.${c.name}`).join(", ");
|
|
576
|
+
let query = `SELECT ${this._distinct ? "DISTINCT " : ""}${selectList} FROM ${this._table._tableName}`;
|
|
577
|
+
if (this._joins.length > 0) query += ` ${this._joins.join(" ")}`;
|
|
247
578
|
if (this._where.length > 0) {
|
|
248
579
|
const whereClauses = this._where.map((condition) => {
|
|
249
580
|
const sql2 = condition.toSQL();
|
|
@@ -252,21 +583,46 @@ var SelectQueryBuilder = class {
|
|
|
252
583
|
});
|
|
253
584
|
query += ` WHERE ${whereClauses.join(" AND ")}`;
|
|
254
585
|
}
|
|
586
|
+
if (this._groupBy.length > 0) {
|
|
587
|
+
query += ` GROUP BY ${this._groupBy.join(", ")}`;
|
|
588
|
+
}
|
|
589
|
+
if (this._having.length > 0) {
|
|
590
|
+
const havingClauses = this._having.map((h) => {
|
|
591
|
+
const sql2 = h.toSQL();
|
|
592
|
+
bindings.push(...sql2.bindings);
|
|
593
|
+
return `(${sql2.clause})`;
|
|
594
|
+
});
|
|
595
|
+
query += ` HAVING ${havingClauses.join(" AND ")}`;
|
|
596
|
+
}
|
|
255
597
|
if (this._orderBy.length > 0) {
|
|
256
|
-
|
|
598
|
+
const ordParts = [];
|
|
599
|
+
for (const ob of this._orderBy) {
|
|
600
|
+
if (typeof ob === "string") ordParts.push(ob);
|
|
601
|
+
else {
|
|
602
|
+
const s = ob.toSQL();
|
|
603
|
+
ordParts.push(s.clause);
|
|
604
|
+
bindings.push(...s.bindings);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
257
608
|
}
|
|
258
609
|
if (this._limit !== null) {
|
|
259
610
|
query += ` LIMIT ?`;
|
|
260
611
|
bindings.push(this._limit);
|
|
261
612
|
}
|
|
262
613
|
if (this._offset !== null) {
|
|
263
|
-
if (this._limit === null)
|
|
264
|
-
query += ` LIMIT -1`;
|
|
265
|
-
}
|
|
614
|
+
if (this._limit === null) query += ` LIMIT -1`;
|
|
266
615
|
query += ` OFFSET ?`;
|
|
267
616
|
bindings.push(this._offset);
|
|
268
617
|
}
|
|
269
|
-
return
|
|
618
|
+
return db.select(query, bindings);
|
|
619
|
+
}
|
|
620
|
+
async iterator() {
|
|
621
|
+
const rows = await this.execute();
|
|
622
|
+
async function* gen() {
|
|
623
|
+
for (const r of rows) yield r;
|
|
624
|
+
}
|
|
625
|
+
return gen();
|
|
270
626
|
}
|
|
271
627
|
};
|
|
272
628
|
var TauriORM = class {
|
|
@@ -274,48 +630,154 @@ var TauriORM = class {
|
|
|
274
630
|
query = {};
|
|
275
631
|
_tables = null;
|
|
276
632
|
_relations = null;
|
|
633
|
+
_dbPromise;
|
|
634
|
+
constructor(dbUri) {
|
|
635
|
+
this._dbPromise = import_plugin_sql.default.load(dbUri);
|
|
636
|
+
}
|
|
637
|
+
async getDb() {
|
|
638
|
+
return this._dbPromise;
|
|
639
|
+
}
|
|
277
640
|
// Deprecated: use configure()
|
|
278
641
|
configureQuery(tables, relations2) {
|
|
279
642
|
this.configure(tables, relations2);
|
|
280
643
|
}
|
|
281
644
|
select(fields) {
|
|
282
|
-
return new SelectQueryBuilder(fields);
|
|
645
|
+
return new SelectQueryBuilder(this.getDb.bind(this), fields);
|
|
646
|
+
}
|
|
647
|
+
selectDistinct(fields) {
|
|
648
|
+
const qb = new SelectQueryBuilder(this.getDb.bind(this), fields);
|
|
649
|
+
qb.distinct();
|
|
650
|
+
return qb;
|
|
283
651
|
}
|
|
284
652
|
// --- Drizzle-style CRUD builders ---
|
|
285
653
|
insert(table) {
|
|
654
|
+
const self = this;
|
|
286
655
|
return new class InsertBuilder {
|
|
287
656
|
_table = table;
|
|
288
657
|
_rows = [];
|
|
658
|
+
_selectSql = null;
|
|
659
|
+
_conflict = null;
|
|
660
|
+
_returning = null;
|
|
289
661
|
values(rowOrRows) {
|
|
290
662
|
this._rows = Array.isArray(rowOrRows) ? rowOrRows : [rowOrRows];
|
|
291
663
|
return this;
|
|
292
664
|
}
|
|
665
|
+
select(qb) {
|
|
666
|
+
if (qb.toSQL) this._selectSql = qb.toSQL();
|
|
667
|
+
else this._selectSql = qb.toSQL();
|
|
668
|
+
return this;
|
|
669
|
+
}
|
|
670
|
+
returning(fields) {
|
|
671
|
+
this._returning = fields ?? {};
|
|
672
|
+
return this;
|
|
673
|
+
}
|
|
674
|
+
$returningId() {
|
|
675
|
+
this._returning = "__RETURNING_ID__";
|
|
676
|
+
return this;
|
|
677
|
+
}
|
|
678
|
+
onConflictDoNothing(opts) {
|
|
679
|
+
const target = opts?.target ? Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name : void 0;
|
|
680
|
+
this._conflict = {
|
|
681
|
+
kind: "doNothing",
|
|
682
|
+
target,
|
|
683
|
+
where: opts?.where
|
|
684
|
+
};
|
|
685
|
+
return this;
|
|
686
|
+
}
|
|
687
|
+
onConflictDoUpdate(opts) {
|
|
688
|
+
const target = Array.isArray(opts.target) ? opts.target.map((c) => c.name) : opts.target.name;
|
|
689
|
+
this._conflict = {
|
|
690
|
+
kind: "doUpdate",
|
|
691
|
+
target,
|
|
692
|
+
targetWhere: opts.targetWhere,
|
|
693
|
+
set: opts.set,
|
|
694
|
+
setWhere: opts.setWhere
|
|
695
|
+
};
|
|
696
|
+
return this;
|
|
697
|
+
}
|
|
293
698
|
async execute() {
|
|
294
|
-
const
|
|
699
|
+
const db = await self.getDb();
|
|
700
|
+
if (this._selectSql) {
|
|
701
|
+
const cols = Object.keys(this._table._schema);
|
|
702
|
+
let query = `INSERT INTO ${this._table._tableName} (${cols.join(", ")}) ${this._selectSql.clause}`;
|
|
703
|
+
const bindings = [...this._selectSql.bindings];
|
|
704
|
+
query += this._buildConflictClause();
|
|
705
|
+
const ret = await this._executeWithReturning(db, query, bindings);
|
|
706
|
+
return ret;
|
|
707
|
+
}
|
|
295
708
|
for (const data of this._rows) {
|
|
296
709
|
const finalData = { ...data };
|
|
297
710
|
const schema = this._table._schema;
|
|
298
711
|
for (const [key, col] of Object.entries(schema)) {
|
|
299
|
-
if (finalData[key] === void 0
|
|
300
|
-
|
|
712
|
+
if (finalData[key] === void 0) {
|
|
713
|
+
if (col.defaultFn) {
|
|
714
|
+
finalData[key] = col.defaultFn();
|
|
715
|
+
} else if (col.onUpdateFn) {
|
|
716
|
+
finalData[key] = col.onUpdateFn();
|
|
717
|
+
}
|
|
301
718
|
}
|
|
302
719
|
}
|
|
303
720
|
const keys = Object.keys(finalData);
|
|
304
721
|
const values = Object.values(finalData);
|
|
305
722
|
const placeholders = values.map(() => "?").join(", ");
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
await
|
|
723
|
+
let query = `INSERT INTO ${this._table._tableName} (${keys.join(", ")}) VALUES (${placeholders})`;
|
|
724
|
+
const bindings = [...values];
|
|
725
|
+
query += this._buildConflictClause();
|
|
726
|
+
const ret = await this._executeWithReturning(db, query, bindings);
|
|
727
|
+
if (ret !== void 0) return ret;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
_buildConflictClause() {
|
|
731
|
+
if (!this._conflict) return "";
|
|
732
|
+
if (this._conflict.kind === "doNothing") {
|
|
733
|
+
const tgt2 = this._conflict.target ? Array.isArray(this._conflict.target) ? `(${this._conflict.target.join(", ")})` : `(${this._conflict.target})` : "";
|
|
734
|
+
const where = this._conflict.where ? ` WHERE ${this._conflict.where.toSQL().clause}` : "";
|
|
735
|
+
return ` ON CONFLICT ${tgt2} DO NOTHING${where}`;
|
|
310
736
|
}
|
|
737
|
+
const c = this._conflict;
|
|
738
|
+
const tgt = Array.isArray(c.target) ? `(${c.target.join(", ")})` : `(${c.target})`;
|
|
739
|
+
const setKeys = Object.keys(c.set ?? {});
|
|
740
|
+
const setClause = setKeys.map((k) => {
|
|
741
|
+
const v = c.set[k];
|
|
742
|
+
return `${k} = ${typeof v === "object" && v && typeof v.toSQL === "function" ? v.toSQL().clause : "?"}`;
|
|
743
|
+
}).join(", ");
|
|
744
|
+
const targetWhere = c.targetWhere ? ` WHERE ${c.targetWhere.toSQL().clause}` : "";
|
|
745
|
+
const setWhere = c.setWhere ? ` WHERE ${c.setWhere.toSQL().clause}` : "";
|
|
746
|
+
return ` ON CONFLICT ${tgt}${targetWhere} DO UPDATE SET ${setClause}${setWhere}`;
|
|
747
|
+
}
|
|
748
|
+
async _executeWithReturning(db, query, bindings) {
|
|
749
|
+
if (this._returning === null) {
|
|
750
|
+
await db.execute(query, bindings);
|
|
751
|
+
return void 0;
|
|
752
|
+
}
|
|
753
|
+
if (this._returning === "__RETURNING_ID__") {
|
|
754
|
+
const rows = await db.select(`SELECT last_insert_rowid() as id`);
|
|
755
|
+
return rows.map((r) => ({ id: r.id }));
|
|
756
|
+
}
|
|
757
|
+
if (typeof this._returning === "object") {
|
|
758
|
+
const cols = Object.entries(
|
|
759
|
+
this._returning
|
|
760
|
+
).map(
|
|
761
|
+
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
762
|
+
).join(", ");
|
|
763
|
+
const retSql = `${query} RETURNING ${cols}`;
|
|
764
|
+
const res = await db.select(retSql, bindings);
|
|
765
|
+
return res;
|
|
766
|
+
}
|
|
767
|
+
return void 0;
|
|
311
768
|
}
|
|
312
769
|
}();
|
|
313
770
|
}
|
|
314
771
|
update(table) {
|
|
772
|
+
const self = this;
|
|
315
773
|
return new class UpdateBuilder {
|
|
316
774
|
_table = table;
|
|
317
775
|
_data = null;
|
|
318
776
|
_where = null;
|
|
777
|
+
_orderBy = [];
|
|
778
|
+
_limit = null;
|
|
779
|
+
_from = null;
|
|
780
|
+
_returning = null;
|
|
319
781
|
set(data) {
|
|
320
782
|
this._data = data;
|
|
321
783
|
return this;
|
|
@@ -324,14 +786,54 @@ var TauriORM = class {
|
|
|
324
786
|
this._where = cond;
|
|
325
787
|
return this;
|
|
326
788
|
}
|
|
789
|
+
orderBy(...clauses) {
|
|
790
|
+
for (const c of clauses) {
|
|
791
|
+
if (!c) continue;
|
|
792
|
+
if (typeof c === "string") this._orderBy.push(c);
|
|
793
|
+
else if (typeof c.toSQL === "function")
|
|
794
|
+
this._orderBy.push(c);
|
|
795
|
+
else this._orderBy.push(getQualifiedName(c));
|
|
796
|
+
}
|
|
797
|
+
return this;
|
|
798
|
+
}
|
|
799
|
+
limit(n) {
|
|
800
|
+
this._limit = n;
|
|
801
|
+
return this;
|
|
802
|
+
}
|
|
803
|
+
from(tbl) {
|
|
804
|
+
this._from = tbl;
|
|
805
|
+
return this;
|
|
806
|
+
}
|
|
807
|
+
returning(fields) {
|
|
808
|
+
this._returning = fields ?? {};
|
|
809
|
+
return this;
|
|
810
|
+
}
|
|
327
811
|
async execute() {
|
|
328
812
|
if (!this._data)
|
|
329
813
|
throw new Error("Update requires set() before execute()");
|
|
330
|
-
const
|
|
331
|
-
const
|
|
332
|
-
const
|
|
333
|
-
const
|
|
334
|
-
|
|
814
|
+
const db = await self.getDb();
|
|
815
|
+
const schema = this._table._schema;
|
|
816
|
+
const dataToSet = { ...this._data };
|
|
817
|
+
for (const [key, col] of Object.entries(schema)) {
|
|
818
|
+
if (!(key in dataToSet) && col.onUpdateFn) {
|
|
819
|
+
dataToSet[key] = col.onUpdateFn();
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
const setParts = [];
|
|
823
|
+
const bindings = [];
|
|
824
|
+
for (const [k, v] of Object.entries(dataToSet)) {
|
|
825
|
+
if (v === void 0) continue;
|
|
826
|
+
if (v && typeof v === "object" && typeof v.toSQL === "function") {
|
|
827
|
+
const s = v.toSQL();
|
|
828
|
+
setParts.push(`${k} = ${s.clause}`);
|
|
829
|
+
bindings.push(...s.bindings);
|
|
830
|
+
} else {
|
|
831
|
+
setParts.push(`${k} = ?`);
|
|
832
|
+
bindings.push(v);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
let query = `UPDATE ${this._table._tableName} SET ${setParts.join(", ")}`;
|
|
836
|
+
if (this._from) query += ` FROM ${this._from._tableName}`;
|
|
335
837
|
if (this._where) {
|
|
336
838
|
if (typeof this._where.toSQL === "function") {
|
|
337
839
|
const sql2 = this._where.toSQL();
|
|
@@ -345,20 +847,67 @@ var TauriORM = class {
|
|
|
345
847
|
}
|
|
346
848
|
}
|
|
347
849
|
}
|
|
348
|
-
|
|
850
|
+
if (this._orderBy.length > 0) {
|
|
851
|
+
const ordParts = [];
|
|
852
|
+
for (const ob of this._orderBy) {
|
|
853
|
+
if (typeof ob === "string") ordParts.push(ob);
|
|
854
|
+
else {
|
|
855
|
+
const s = ob.toSQL();
|
|
856
|
+
ordParts.push(s.clause);
|
|
857
|
+
bindings.push(...s.bindings);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
861
|
+
}
|
|
862
|
+
if (this._limit !== null) {
|
|
863
|
+
query += ` LIMIT ?`;
|
|
864
|
+
bindings.push(this._limit);
|
|
865
|
+
}
|
|
866
|
+
if (this._returning) {
|
|
867
|
+
const cols = Object.entries(
|
|
868
|
+
this._returning
|
|
869
|
+
).map(
|
|
870
|
+
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
871
|
+
).join(", ");
|
|
872
|
+
const retSql = `${query} RETURNING ${cols}`;
|
|
873
|
+
return await db.select(retSql, bindings);
|
|
874
|
+
}
|
|
875
|
+
await db.execute(query, bindings);
|
|
349
876
|
}
|
|
350
877
|
}();
|
|
351
878
|
}
|
|
352
879
|
delete(table) {
|
|
880
|
+
const self = this;
|
|
353
881
|
return new class DeleteBuilder {
|
|
354
882
|
_table = table;
|
|
355
883
|
_where = null;
|
|
884
|
+
_orderBy = [];
|
|
885
|
+
_limit = null;
|
|
886
|
+
_returning = null;
|
|
356
887
|
where(cond) {
|
|
357
888
|
this._where = cond;
|
|
358
889
|
return this;
|
|
359
890
|
}
|
|
891
|
+
orderBy(...clauses) {
|
|
892
|
+
for (const c of clauses) {
|
|
893
|
+
if (!c) continue;
|
|
894
|
+
if (typeof c === "string") this._orderBy.push(c);
|
|
895
|
+
else if (typeof c.toSQL === "function")
|
|
896
|
+
this._orderBy.push(c);
|
|
897
|
+
else this._orderBy.push(getQualifiedName(c));
|
|
898
|
+
}
|
|
899
|
+
return this;
|
|
900
|
+
}
|
|
901
|
+
limit(n) {
|
|
902
|
+
this._limit = n;
|
|
903
|
+
return this;
|
|
904
|
+
}
|
|
905
|
+
returning(fields) {
|
|
906
|
+
this._returning = fields ?? {};
|
|
907
|
+
return this;
|
|
908
|
+
}
|
|
360
909
|
async execute() {
|
|
361
|
-
const
|
|
910
|
+
const db = await self.getDb();
|
|
362
911
|
let query = `DELETE FROM ${this._table._tableName}`;
|
|
363
912
|
const bindings = [];
|
|
364
913
|
if (this._where) {
|
|
@@ -374,7 +923,32 @@ var TauriORM = class {
|
|
|
374
923
|
}
|
|
375
924
|
}
|
|
376
925
|
}
|
|
377
|
-
|
|
926
|
+
if (this._orderBy.length > 0) {
|
|
927
|
+
const ordParts = [];
|
|
928
|
+
for (const ob of this._orderBy) {
|
|
929
|
+
if (typeof ob === "string") ordParts.push(ob);
|
|
930
|
+
else {
|
|
931
|
+
const s = ob.toSQL();
|
|
932
|
+
ordParts.push(s.clause);
|
|
933
|
+
bindings.push(...s.bindings);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
query += ` ORDER BY ${ordParts.join(", ")}`;
|
|
937
|
+
}
|
|
938
|
+
if (this._limit !== null) {
|
|
939
|
+
query += ` LIMIT ?`;
|
|
940
|
+
bindings.push(this._limit);
|
|
941
|
+
}
|
|
942
|
+
if (this._returning) {
|
|
943
|
+
const cols = Object.entries(
|
|
944
|
+
this._returning
|
|
945
|
+
).map(
|
|
946
|
+
([alias, col]) => `${col.tableName}.${col.name} AS ${alias}`
|
|
947
|
+
).join(", ");
|
|
948
|
+
const retSql = `${query} RETURNING ${cols}`;
|
|
949
|
+
return await db.select(retSql, bindings);
|
|
950
|
+
}
|
|
951
|
+
await db.execute(query, bindings);
|
|
378
952
|
}
|
|
379
953
|
}();
|
|
380
954
|
}
|
|
@@ -382,8 +956,8 @@ var TauriORM = class {
|
|
|
382
956
|
// legacy direct methods removed in favor of builder APIs
|
|
383
957
|
// legacy direct methods removed in favor of builder APIs
|
|
384
958
|
async run(query, bindings = []) {
|
|
385
|
-
const
|
|
386
|
-
await
|
|
959
|
+
const db = await this.getDb();
|
|
960
|
+
await db.execute(query, bindings);
|
|
387
961
|
}
|
|
388
962
|
// --- Migrations API ---
|
|
389
963
|
generateCreateTableSql(table) {
|
|
@@ -433,16 +1007,16 @@ var TauriORM = class {
|
|
|
433
1007
|
);
|
|
434
1008
|
}
|
|
435
1009
|
async hasMigration(name) {
|
|
436
|
-
const
|
|
437
|
-
const rows = await
|
|
1010
|
+
const db = await this.getDb();
|
|
1011
|
+
const rows = await db.select(
|
|
438
1012
|
`SELECT name FROM _migrations WHERE name = ?`,
|
|
439
1013
|
[name]
|
|
440
1014
|
);
|
|
441
1015
|
return Array.isArray(rows) && rows.length > 0;
|
|
442
1016
|
}
|
|
443
1017
|
async recordMigration(name) {
|
|
444
|
-
const
|
|
445
|
-
await
|
|
1018
|
+
const db = await this.getDb();
|
|
1019
|
+
await db.execute(
|
|
446
1020
|
`INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`,
|
|
447
1021
|
[name, Date.now()]
|
|
448
1022
|
);
|
|
@@ -464,7 +1038,7 @@ var TauriORM = class {
|
|
|
464
1038
|
configure(tables, relDefs) {
|
|
465
1039
|
this._tables = tables;
|
|
466
1040
|
this._relations = relDefs ?? {};
|
|
467
|
-
this.query = makeQueryAPI(tables, this._relations);
|
|
1041
|
+
this.query = makeQueryAPI(tables, this._relations, this.getDb.bind(this));
|
|
468
1042
|
return this;
|
|
469
1043
|
}
|
|
470
1044
|
// Convenience: migrate from configured tables
|
|
@@ -476,7 +1050,7 @@ var TauriORM = class {
|
|
|
476
1050
|
// --- Schema diff and CLI-like helpers ---
|
|
477
1051
|
async diffSchema() {
|
|
478
1052
|
if (!this._tables) throw new Error("No tables configured.");
|
|
479
|
-
const dbi = getDb();
|
|
1053
|
+
const dbi = await this.getDb();
|
|
480
1054
|
const configuredNames = Object.values(this._tables).map(
|
|
481
1055
|
(t) => t._tableName
|
|
482
1056
|
);
|
|
@@ -551,7 +1125,7 @@ var TauriORM = class {
|
|
|
551
1125
|
return this.pullSchema();
|
|
552
1126
|
}
|
|
553
1127
|
async studio() {
|
|
554
|
-
const dbi = getDb();
|
|
1128
|
+
const dbi = await this.getDb();
|
|
555
1129
|
return { driver: "sqlite", path: dbi.path };
|
|
556
1130
|
}
|
|
557
1131
|
// --- Schema detection / signature ---
|
|
@@ -561,7 +1135,7 @@ var TauriORM = class {
|
|
|
561
1135
|
);
|
|
562
1136
|
}
|
|
563
1137
|
async getSchemaMeta(key) {
|
|
564
|
-
const dbi = getDb();
|
|
1138
|
+
const dbi = await this.getDb();
|
|
565
1139
|
await this.ensureSchemaMeta();
|
|
566
1140
|
const rows = await dbi.select(
|
|
567
1141
|
`SELECT value FROM _schema_meta WHERE key = ?`,
|
|
@@ -570,7 +1144,7 @@ var TauriORM = class {
|
|
|
570
1144
|
return rows?.[0]?.value ?? null;
|
|
571
1145
|
}
|
|
572
1146
|
async setSchemaMeta(key, value) {
|
|
573
|
-
const dbi = getDb();
|
|
1147
|
+
const dbi = await this.getDb();
|
|
574
1148
|
await this.ensureSchemaMeta();
|
|
575
1149
|
await dbi.execute(
|
|
576
1150
|
`INSERT INTO _schema_meta(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`,
|
|
@@ -619,7 +1193,7 @@ var TauriORM = class {
|
|
|
619
1193
|
// Pull current DB schema (minimal) for configured tables
|
|
620
1194
|
async pullSchema() {
|
|
621
1195
|
if (!this._tables) throw new Error("No tables configured.");
|
|
622
|
-
const dbi = getDb();
|
|
1196
|
+
const dbi = await this.getDb();
|
|
623
1197
|
const result = {};
|
|
624
1198
|
for (const tbl of Object.values(this._tables)) {
|
|
625
1199
|
const name = tbl._tableName;
|
|
@@ -638,7 +1212,7 @@ var TauriORM = class {
|
|
|
638
1212
|
return this.generateCreateTableSql(table);
|
|
639
1213
|
}
|
|
640
1214
|
async tableExists(name) {
|
|
641
|
-
const dbi = getDb();
|
|
1215
|
+
const dbi = await this.getDb();
|
|
642
1216
|
const rows = await dbi.select(
|
|
643
1217
|
`SELECT name FROM sqlite_master WHERE type='table' AND name = ?`,
|
|
644
1218
|
[name]
|
|
@@ -648,12 +1222,12 @@ var TauriORM = class {
|
|
|
648
1222
|
// Force push model to DB: add missing tables/columns, rebuild tables if incompatible
|
|
649
1223
|
async forcePush(options) {
|
|
650
1224
|
if (!this._tables) throw new Error("No tables configured.");
|
|
651
|
-
const dbi = getDb();
|
|
1225
|
+
const dbi = await this.getDb();
|
|
652
1226
|
const preserve = options?.preserveData !== false;
|
|
653
1227
|
for (const tbl of Object.values(this._tables)) {
|
|
654
1228
|
const tableName = tbl._tableName;
|
|
655
|
-
const
|
|
656
|
-
if (!
|
|
1229
|
+
const exists2 = await this.tableExists(tableName);
|
|
1230
|
+
if (!exists2) {
|
|
657
1231
|
await this.run(this.buildCreateTableSQL(tbl));
|
|
658
1232
|
continue;
|
|
659
1233
|
}
|
|
@@ -718,7 +1292,6 @@ var TauriORM = class {
|
|
|
718
1292
|
await this.setSchemaMeta("schema_signature", this.computeModelSignature());
|
|
719
1293
|
}
|
|
720
1294
|
};
|
|
721
|
-
var db2 = new TauriORM();
|
|
722
1295
|
function relations(baseTable, builder) {
|
|
723
1296
|
const ctx = {
|
|
724
1297
|
one: (table, cfg) => ({ kind: "one", table, cfg }),
|
|
@@ -744,10 +1317,29 @@ function guessChildFk(child, base, rel) {
|
|
|
744
1317
|
];
|
|
745
1318
|
return childCols.find((c) => guessNames.includes(c.name)) || childCols.find((c) => /.*_id$/i.test(c.name)) || null;
|
|
746
1319
|
}
|
|
1320
|
+
function guessOneRelationJoin(base, rel) {
|
|
1321
|
+
const child = rel.table;
|
|
1322
|
+
const basePk = getPrimaryKey(base);
|
|
1323
|
+
const childCols = Object.values(child._schema);
|
|
1324
|
+
if (rel.cfg?.fields && rel.cfg?.references && rel.cfg.fields[0] && rel.cfg.references[0]) {
|
|
1325
|
+
const fk = rel.cfg.fields[0];
|
|
1326
|
+
const ref = rel.cfg.references[0];
|
|
1327
|
+
if (childCols.some((c) => c.name === fk.name)) {
|
|
1328
|
+
return { lhsTable: child, lhsCol: fk, rhsTable: base, rhsCol: ref };
|
|
1329
|
+
}
|
|
1330
|
+
const baseCols = Object.values(base._schema);
|
|
1331
|
+
if (baseCols.some((c) => c.name === fk.name)) {
|
|
1332
|
+
return { lhsTable: base, lhsCol: fk, rhsTable: child, rhsCol: ref };
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
const childFk = guessChildFk(child, base, rel);
|
|
1336
|
+
if (!childFk) return null;
|
|
1337
|
+
return { lhsTable: child, lhsCol: childFk, rhsTable: base, rhsCol: basePk };
|
|
1338
|
+
}
|
|
747
1339
|
function isFlatWith(spec) {
|
|
748
1340
|
return Object.values(spec).every((v) => typeof v === "boolean");
|
|
749
1341
|
}
|
|
750
|
-
function makeQueryAPI(tables, relDefs) {
|
|
1342
|
+
function makeQueryAPI(tables, relDefs, dbProvider) {
|
|
751
1343
|
const api = {};
|
|
752
1344
|
const tableKeyByName = {};
|
|
753
1345
|
for (const [k, t] of Object.entries(tables)) tableKeyByName[t._tableName] = k;
|
|
@@ -756,7 +1348,7 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
756
1348
|
async findMany(opts) {
|
|
757
1349
|
const base = tbl;
|
|
758
1350
|
const withSpec = opts?.with ?? {};
|
|
759
|
-
const dbi =
|
|
1351
|
+
const dbi = await dbProvider();
|
|
760
1352
|
const rels = relDefs[tblKey] ?? {};
|
|
761
1353
|
if (opts?.join && isFlatWith(withSpec)) {
|
|
762
1354
|
const baseCols = Object.values(base._schema);
|
|
@@ -782,23 +1374,43 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
782
1374
|
const child = rel.table;
|
|
783
1375
|
const childCols = Object.values(child._schema);
|
|
784
1376
|
const childPk = childCols.find((c) => c.isPrimaryKey) || childCols.find((c) => c.name === "id") || null;
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1377
|
+
if (rel.kind === "one") {
|
|
1378
|
+
const mapping = guessOneRelationJoin(base, rel);
|
|
1379
|
+
if (!mapping) continue;
|
|
1380
|
+
if (mapping.lhsTable._tableName === child._tableName) {
|
|
1381
|
+
fkMap[relName] = { childFk: mapping.lhsCol, childPk };
|
|
1382
|
+
joins.push(
|
|
1383
|
+
`LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
|
|
1384
|
+
);
|
|
1385
|
+
} else {
|
|
1386
|
+
fkMap[relName] = { childFk: mapping.rhsCol, childPk };
|
|
1387
|
+
joins.push(
|
|
1388
|
+
`LEFT JOIN ${child._tableName} ON ${mapping.lhsTable._tableName}.${mapping.lhsCol.name} = ${mapping.rhsTable._tableName}.${mapping.rhsCol.name}`
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
} else {
|
|
1392
|
+
const childFk = guessChildFk(child, base, rel);
|
|
1393
|
+
if (!childFk) continue;
|
|
1394
|
+
fkMap[relName] = { childFk, childPk };
|
|
1395
|
+
joins.push(
|
|
1396
|
+
`LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
788
1399
|
const selected = typeof enabled === "object" && enabled.columns?.length ? enabled.columns : childCols.map((c) => c.name);
|
|
789
1400
|
relColsMap[relName] = selected;
|
|
790
1401
|
for (const name of selected)
|
|
791
1402
|
selectParts.push(
|
|
792
1403
|
`${child._tableName}.${name} AS __rel_${relName}_${name}`
|
|
793
1404
|
);
|
|
794
|
-
joins.push(
|
|
795
|
-
`LEFT JOIN ${child._tableName} ON ${child._tableName}.${childFk.name} = ${base._tableName}.${basePk.name}`
|
|
796
|
-
);
|
|
797
1405
|
}
|
|
798
1406
|
let sqlText = `SELECT ${selectParts.join(", ")} FROM ${base._tableName}${joins.length ? " " + joins.join(" ") : ""}`;
|
|
799
1407
|
const bindings = [];
|
|
800
1408
|
if (opts?.where) {
|
|
801
|
-
if (typeof opts.where
|
|
1409
|
+
if (typeof opts.where === "function") {
|
|
1410
|
+
const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
|
|
1411
|
+
sqlText += ` WHERE ${w.clause}`;
|
|
1412
|
+
bindings.push(...w.bindings);
|
|
1413
|
+
} else if (typeof opts.where.toSQL === "function") {
|
|
802
1414
|
const w = opts.where.toSQL();
|
|
803
1415
|
sqlText += ` WHERE ${w.clause}`;
|
|
804
1416
|
bindings.push(...w.bindings);
|
|
@@ -810,8 +1422,9 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
810
1422
|
}
|
|
811
1423
|
}
|
|
812
1424
|
}
|
|
813
|
-
|
|
814
|
-
|
|
1425
|
+
const orderByClauses = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
|
|
1426
|
+
if (orderByClauses?.length)
|
|
1427
|
+
sqlText += ` ORDER BY ${orderByClauses.join(", ")}`;
|
|
815
1428
|
if (typeof opts?.limit === "number")
|
|
816
1429
|
sqlText += ` LIMIT ${opts.limit}`;
|
|
817
1430
|
if (typeof opts?.offset === "number")
|
|
@@ -851,10 +1464,10 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
851
1464
|
const childPk = fkMap[relName].childPk;
|
|
852
1465
|
if (childPk) {
|
|
853
1466
|
if (!acc[relName]) acc[relName] = [];
|
|
854
|
-
const
|
|
1467
|
+
const exists2 = acc[relName].some(
|
|
855
1468
|
(r) => r[childPk.name] === childObj[childPk.name]
|
|
856
1469
|
);
|
|
857
|
-
if (!
|
|
1470
|
+
if (!exists2) acc[relName].push(childObj);
|
|
858
1471
|
} else {
|
|
859
1472
|
acc[relName].push(childObj);
|
|
860
1473
|
}
|
|
@@ -878,7 +1491,11 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
878
1491
|
let baseSql = `SELECT ${baseSelected.join(", ")} FROM ${base._tableName}`;
|
|
879
1492
|
const baseBindings = [];
|
|
880
1493
|
if (opts?.where) {
|
|
881
|
-
if (typeof opts.where
|
|
1494
|
+
if (typeof opts.where === "function") {
|
|
1495
|
+
const w = opts.where(base, { eq, ne, gt, gte, lt, lte, like }).toSQL();
|
|
1496
|
+
baseSql += ` WHERE ${w.clause}`;
|
|
1497
|
+
baseBindings.push(...w.bindings);
|
|
1498
|
+
} else if (typeof opts.where.toSQL === "function") {
|
|
882
1499
|
const w = opts.where.toSQL();
|
|
883
1500
|
baseSql += ` WHERE ${w.clause}`;
|
|
884
1501
|
baseBindings.push(...w.bindings);
|
|
@@ -890,8 +1507,9 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
890
1507
|
}
|
|
891
1508
|
}
|
|
892
1509
|
}
|
|
893
|
-
|
|
894
|
-
|
|
1510
|
+
const orderByClauses2 = typeof opts?.orderBy === "function" ? opts.orderBy(base, { asc, desc }) : opts?.orderBy;
|
|
1511
|
+
if (orderByClauses2?.length)
|
|
1512
|
+
baseSql += ` ORDER BY ${orderByClauses2.join(", ")}`;
|
|
895
1513
|
if (typeof opts?.limit === "number") baseSql += ` LIMIT ${opts.limit}`;
|
|
896
1514
|
if (typeof opts?.offset === "number")
|
|
897
1515
|
baseSql += ` OFFSET ${opts.offset}`;
|
|
@@ -910,9 +1528,9 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
910
1528
|
const child = rel.table;
|
|
911
1529
|
const childCols = Object.values(child._schema);
|
|
912
1530
|
const selectCols = enabled?.columns && enabled.columns.length > 0 ? enabled.columns : childCols.map((c) => c.name);
|
|
913
|
-
const fkCol = guessChildFk(child, parentTable, rel);
|
|
914
|
-
if (!fkCol) continue;
|
|
915
1531
|
if (rel.kind === "many") {
|
|
1532
|
+
const fkCol = guessChildFk(child, parentTable, rel);
|
|
1533
|
+
if (!fkCol) continue;
|
|
916
1534
|
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${fkCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
|
|
917
1535
|
const rows = await dbi.select(sql2, parentIds);
|
|
918
1536
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -931,14 +1549,32 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
931
1549
|
await loadRelationsFor(children, child, enabled.with);
|
|
932
1550
|
}
|
|
933
1551
|
} else {
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1552
|
+
const mapping = guessOneRelationJoin(parentTable, rel);
|
|
1553
|
+
if (!mapping) continue;
|
|
1554
|
+
if (mapping.lhsTable._tableName === child._tableName) {
|
|
1555
|
+
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${mapping.lhsCol.name} IN (${parentIds.map(() => "?").join(", ")})`;
|
|
1556
|
+
const rows = await dbi.select(sql2, parentIds);
|
|
1557
|
+
const mapOne = /* @__PURE__ */ new Map();
|
|
1558
|
+
for (const r of rows) mapOne.set(r[mapping.lhsCol.name], r);
|
|
1559
|
+
for (const p of parents)
|
|
1560
|
+
p[relName] = mapOne.get(p[parentPk.name]) ?? null;
|
|
1561
|
+
} else {
|
|
1562
|
+
const parentFkName = mapping.lhsCol.name;
|
|
1563
|
+
const childPkName = mapping.rhsCol.name;
|
|
1564
|
+
const childIds = parents.map((p) => p[parentFkName]).filter((v2) => v2 !== void 0 && v2 !== null);
|
|
1565
|
+
if (childIds.length === 0) {
|
|
1566
|
+
for (const p of parents) p[relName] = null;
|
|
1567
|
+
} else {
|
|
1568
|
+
const sql2 = `SELECT ${selectCols.join(", ")} FROM ${child._tableName} WHERE ${childPkName} IN (${childIds.map(() => "?").join(", ")})`;
|
|
1569
|
+
const rows = await dbi.select(sql2, childIds);
|
|
1570
|
+
const mapOne = /* @__PURE__ */ new Map();
|
|
1571
|
+
for (const r of rows) mapOne.set(r[childPkName], r);
|
|
1572
|
+
for (const p of parents)
|
|
1573
|
+
p[relName] = mapOne.get(p[parentFkName]) ?? null;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
940
1576
|
if (enabled?.with) {
|
|
941
|
-
const children = parents.map((p) => p[relName]).filter(Boolean);
|
|
1577
|
+
const children = parents.map((p) => p[relName]).filter((x) => Boolean(x));
|
|
942
1578
|
if (children.length > 0)
|
|
943
1579
|
await loadRelationsFor(children, child, enabled.with);
|
|
944
1580
|
}
|
|
@@ -949,71 +1585,58 @@ function makeQueryAPI(tables, relDefs) {
|
|
|
949
1585
|
await loadRelationsFor(result, base, withSpec);
|
|
950
1586
|
}
|
|
951
1587
|
return result;
|
|
1588
|
+
},
|
|
1589
|
+
async findFirst(opts) {
|
|
1590
|
+
const rows = await api[tblKey].findMany({ ...opts, limit: 1 });
|
|
1591
|
+
return rows?.[0] ?? null;
|
|
952
1592
|
}
|
|
953
1593
|
};
|
|
954
1594
|
}
|
|
955
1595
|
return api;
|
|
956
1596
|
}
|
|
957
|
-
|
|
958
|
-
// src/sql-helpers.ts
|
|
959
|
-
function isColumn(value) {
|
|
960
|
-
return typeof value === "object" && value !== null && "_dataType" in value;
|
|
961
|
-
}
|
|
962
|
-
function getQualifiedName(column) {
|
|
963
|
-
if (column.tableName) return `${column.tableName}.${column.name}`;
|
|
964
|
-
return column.name;
|
|
965
|
-
}
|
|
966
|
-
function comparison(operator, column, value) {
|
|
967
|
-
return {
|
|
968
|
-
toSQL: () => {
|
|
969
|
-
if (isColumn(value)) {
|
|
970
|
-
return {
|
|
971
|
-
clause: `${getQualifiedName(column)} ${operator} ${getQualifiedName(
|
|
972
|
-
value
|
|
973
|
-
)}`,
|
|
974
|
-
bindings: []
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
return {
|
|
978
|
-
clause: `${getQualifiedName(column)} ${operator} ?`,
|
|
979
|
-
bindings: [value]
|
|
980
|
-
};
|
|
981
|
-
}
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
var eq = (column, value) => comparison("=", column, value);
|
|
985
|
-
var ne = (column, value) => comparison("!=", column, value);
|
|
986
|
-
var gt = (column, value) => comparison(">", column, value);
|
|
987
|
-
var gte = (column, value) => comparison(">=", column, value);
|
|
988
|
-
var lt = (column, value) => comparison("<", column, value);
|
|
989
|
-
var lte = (column, value) => comparison("<=", column, value);
|
|
990
|
-
var like = (column, value) => comparison("LIKE", column, value);
|
|
991
|
-
var asc = (column) => `${column.name} ASC`;
|
|
992
|
-
var desc = (column) => `${column.name} DESC`;
|
|
993
1597
|
// Annotate the CommonJS export names for ESM import in node:
|
|
994
1598
|
0 && (module.exports = {
|
|
995
1599
|
TauriORM,
|
|
1600
|
+
and,
|
|
996
1601
|
asc,
|
|
1602
|
+
between,
|
|
997
1603
|
blob,
|
|
998
1604
|
boolean,
|
|
999
|
-
|
|
1605
|
+
check,
|
|
1000
1606
|
defineTable,
|
|
1001
1607
|
desc,
|
|
1002
1608
|
eq,
|
|
1003
|
-
|
|
1609
|
+
exists,
|
|
1610
|
+
foreignKey,
|
|
1611
|
+
getQualifiedName,
|
|
1004
1612
|
gt,
|
|
1005
1613
|
gte,
|
|
1006
|
-
|
|
1614
|
+
ilike,
|
|
1615
|
+
inArray,
|
|
1616
|
+
increments,
|
|
1617
|
+
index,
|
|
1007
1618
|
integer,
|
|
1619
|
+
isNotNull,
|
|
1620
|
+
isNull,
|
|
1008
1621
|
like,
|
|
1009
1622
|
lt,
|
|
1010
1623
|
lte,
|
|
1011
1624
|
makeQueryAPI,
|
|
1012
1625
|
ne,
|
|
1626
|
+
not,
|
|
1627
|
+
notBetween,
|
|
1628
|
+
notExists,
|
|
1629
|
+
notIlike,
|
|
1630
|
+
notInArray,
|
|
1013
1631
|
numeric,
|
|
1632
|
+
or,
|
|
1633
|
+
primaryKey,
|
|
1634
|
+
raw,
|
|
1014
1635
|
real,
|
|
1015
1636
|
relations,
|
|
1016
1637
|
sql,
|
|
1017
1638
|
text,
|
|
1018
|
-
timestamp
|
|
1639
|
+
timestamp,
|
|
1640
|
+
unique,
|
|
1641
|
+
uniqueIndex
|
|
1019
1642
|
});
|