@atscript/db-sqlite 0.1.28 → 0.1.30
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/dist/index.cjs +128 -119
- package/dist/index.d.ts +14 -22
- package/dist/index.mjs +128 -119
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -23,111 +23,119 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
25
25
|
const __atscript_utils_db = __toESM(require("@atscript/utils-db"));
|
|
26
|
+
const __uniqu_core = __toESM(require("@uniqu/core"));
|
|
26
27
|
|
|
27
28
|
//#region packages/db-sqlite/src/filter-builder.ts
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
sql: `${col} > ?`,
|
|
67
|
-
params: [value]
|
|
68
|
-
};
|
|
69
|
-
case "$gte": return {
|
|
70
|
-
sql: `${col} >= ?`,
|
|
71
|
-
params: [value]
|
|
72
|
-
};
|
|
73
|
-
case "$lt": return {
|
|
74
|
-
sql: `${col} < ?`,
|
|
75
|
-
params: [value]
|
|
76
|
-
};
|
|
77
|
-
case "$lte": return {
|
|
78
|
-
sql: `${col} <= ?`,
|
|
79
|
-
params: [value]
|
|
80
|
-
};
|
|
81
|
-
case "$ne": {
|
|
82
|
-
if (value === null) return {
|
|
83
|
-
sql: `${col} IS NOT NULL`,
|
|
84
|
-
params: []
|
|
29
|
+
const EMPTY_AND = {
|
|
30
|
+
sql: "1=1",
|
|
31
|
+
params: []
|
|
32
|
+
};
|
|
33
|
+
const EMPTY_OR = {
|
|
34
|
+
sql: "0=1",
|
|
35
|
+
params: []
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* SQL visitor for `walkFilter` — renders a filter expression tree
|
|
39
|
+
* into a parameterized SQL WHERE clause.
|
|
40
|
+
*/ const sqlVisitor = {
|
|
41
|
+
comparison(field, op, value) {
|
|
42
|
+
const col = `"${escapeIdent(field)}"`;
|
|
43
|
+
switch (op) {
|
|
44
|
+
case "$eq": {
|
|
45
|
+
if (value === null) return {
|
|
46
|
+
sql: `${col} IS NULL`,
|
|
47
|
+
params: []
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
sql: `${col} = ?`,
|
|
51
|
+
params: [value]
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
case "$ne": {
|
|
55
|
+
if (value === null) return {
|
|
56
|
+
sql: `${col} IS NOT NULL`,
|
|
57
|
+
params: []
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
sql: `${col} != ?`,
|
|
61
|
+
params: [value]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
case "$gt": return {
|
|
65
|
+
sql: `${col} > ?`,
|
|
66
|
+
params: [value]
|
|
85
67
|
};
|
|
86
|
-
return {
|
|
87
|
-
sql: `${col}
|
|
68
|
+
case "$gte": return {
|
|
69
|
+
sql: `${col} >= ?`,
|
|
88
70
|
params: [value]
|
|
89
71
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (arr.length === 0) return {
|
|
94
|
-
sql: "0=1",
|
|
95
|
-
params: []
|
|
72
|
+
case "$lt": return {
|
|
73
|
+
sql: `${col} < ?`,
|
|
74
|
+
params: [value]
|
|
96
75
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
params: [...arr]
|
|
76
|
+
case "$lte": return {
|
|
77
|
+
sql: `${col} <= ?`,
|
|
78
|
+
params: [value]
|
|
101
79
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
80
|
+
case "$in": {
|
|
81
|
+
const arr = value;
|
|
82
|
+
if (arr.length === 0) return EMPTY_OR;
|
|
83
|
+
const placeholders = arr.map(() => "?").join(", ");
|
|
84
|
+
return {
|
|
85
|
+
sql: `${col} IN (${placeholders})`,
|
|
86
|
+
params: [...arr]
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
case "$nin": {
|
|
90
|
+
const arr = value;
|
|
91
|
+
if (arr.length === 0) return EMPTY_AND;
|
|
92
|
+
const placeholders = arr.map(() => "?").join(", ");
|
|
93
|
+
return {
|
|
94
|
+
sql: `${col} NOT IN (${placeholders})`,
|
|
95
|
+
params: [...arr]
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
case "$exists": return value ? {
|
|
99
|
+
sql: `${col} IS NOT NULL`,
|
|
100
|
+
params: []
|
|
101
|
+
} : {
|
|
102
|
+
sql: `${col} IS NULL`,
|
|
107
103
|
params: []
|
|
108
104
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
case "$regex": {
|
|
106
|
+
const pattern = regexToLike(value instanceof RegExp ? value.source : String(value));
|
|
107
|
+
return {
|
|
108
|
+
sql: `${col} LIKE ?`,
|
|
109
|
+
params: [pattern]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
default: throw new Error(`Unsupported filter operator: ${op}`);
|
|
114
113
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
sql:
|
|
120
|
-
params:
|
|
114
|
+
},
|
|
115
|
+
and(children) {
|
|
116
|
+
if (children.length === 0) return EMPTY_AND;
|
|
117
|
+
return {
|
|
118
|
+
sql: children.map((c) => c.sql).join(" AND "),
|
|
119
|
+
params: children.flatMap((c) => c.params)
|
|
120
|
+
};
|
|
121
|
+
},
|
|
122
|
+
or(children) {
|
|
123
|
+
if (children.length === 0) return EMPTY_OR;
|
|
124
|
+
return {
|
|
125
|
+
sql: `(${children.map((c) => c.sql).join(" OR ")})`,
|
|
126
|
+
params: children.flatMap((c) => c.params)
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
not(child) {
|
|
130
|
+
return {
|
|
131
|
+
sql: `NOT (${child.sql})`,
|
|
132
|
+
params: child.params
|
|
121
133
|
};
|
|
122
|
-
case "$regex": {
|
|
123
|
-
const pattern = regexToLike(String(value));
|
|
124
|
-
return {
|
|
125
|
-
sql: `${col} LIKE ?`,
|
|
126
|
-
params: [pattern]
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
default: throw new Error(`Unsupported filter operator: ${op}`);
|
|
130
134
|
}
|
|
135
|
+
};
|
|
136
|
+
function buildWhere(filter) {
|
|
137
|
+
if (!filter || Object.keys(filter).length === 0) return EMPTY_AND;
|
|
138
|
+
return (0, __uniqu_core.walkFilter)(filter, sqlVisitor);
|
|
131
139
|
}
|
|
132
140
|
/**
|
|
133
141
|
* Basic regex-to-LIKE conversion.
|
|
@@ -166,23 +174,23 @@ function buildInsert(table, data) {
|
|
|
166
174
|
params: keys.map((k) => toSqliteValue$1(data[k]))
|
|
167
175
|
};
|
|
168
176
|
}
|
|
169
|
-
function buildSelect(table, where,
|
|
170
|
-
const cols = buildProjection(
|
|
177
|
+
function buildSelect(table, where, controls) {
|
|
178
|
+
const cols = buildProjection(controls?.$select);
|
|
171
179
|
let sql = `SELECT ${cols} FROM "${esc$1(table)}" WHERE ${where.sql}`;
|
|
172
180
|
const params = [...where.params];
|
|
173
|
-
if (
|
|
181
|
+
if (controls?.$sort) {
|
|
174
182
|
const orderParts = [];
|
|
175
|
-
for (const [col, dir] of Object.entries(
|
|
183
|
+
for (const [col, dir] of Object.entries(controls.$sort)) orderParts.push(`"${esc$1(col)}" ${dir === -1 ? "DESC" : "ASC"}`);
|
|
176
184
|
if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
|
|
177
185
|
}
|
|
178
|
-
if (
|
|
186
|
+
if (controls?.$limit !== undefined) {
|
|
179
187
|
sql += ` LIMIT ?`;
|
|
180
|
-
params.push(
|
|
188
|
+
params.push(controls.$limit);
|
|
181
189
|
}
|
|
182
|
-
if (
|
|
183
|
-
if (
|
|
190
|
+
if (controls?.$skip !== undefined) {
|
|
191
|
+
if (controls.$limit === undefined) sql += ` LIMIT -1`;
|
|
184
192
|
sql += ` OFFSET ?`;
|
|
185
|
-
params.push(
|
|
193
|
+
params.push(controls.$skip);
|
|
186
194
|
}
|
|
187
195
|
return {
|
|
188
196
|
sql,
|
|
@@ -233,13 +241,13 @@ function sqliteTypeFromDesignType(designType) {
|
|
|
233
241
|
default: return "TEXT";
|
|
234
242
|
}
|
|
235
243
|
}
|
|
236
|
-
function buildProjection(
|
|
237
|
-
if (!
|
|
238
|
-
if (Array.isArray(
|
|
239
|
-
if (
|
|
240
|
-
return
|
|
244
|
+
function buildProjection(select) {
|
|
245
|
+
if (!select) return "*";
|
|
246
|
+
if (Array.isArray(select)) {
|
|
247
|
+
if (select.length === 0) return "*";
|
|
248
|
+
return select.map((k) => `"${esc$1(k)}"`).join(", ");
|
|
241
249
|
}
|
|
242
|
-
const entries = Object.entries(
|
|
250
|
+
const entries = Object.entries(select);
|
|
243
251
|
if (entries.length === 0) return "*";
|
|
244
252
|
const firstVal = entries[0][1];
|
|
245
253
|
if (firstVal === 1) return entries.filter(([_, v]) => v === 1).map(([k]) => `"${esc$1(k)}"`).join(", ");
|
|
@@ -302,21 +310,22 @@ var SqliteAdapter = class extends __atscript_utils_db.BaseDbAdapter {
|
|
|
302
310
|
insertedIds: ids
|
|
303
311
|
};
|
|
304
312
|
}
|
|
305
|
-
async findOne(
|
|
306
|
-
const where = buildWhere(filter);
|
|
307
|
-
const
|
|
308
|
-
...
|
|
309
|
-
limit: 1
|
|
310
|
-
}
|
|
313
|
+
async findOne(query) {
|
|
314
|
+
const where = buildWhere(query.filter);
|
|
315
|
+
const controls = {
|
|
316
|
+
...query.controls,
|
|
317
|
+
$limit: 1
|
|
318
|
+
};
|
|
319
|
+
const { sql, params } = buildSelect(this.resolveTableName(), where, controls);
|
|
311
320
|
return this.driver.get(sql, params);
|
|
312
321
|
}
|
|
313
|
-
async findMany(
|
|
314
|
-
const where = buildWhere(filter);
|
|
315
|
-
const { sql, params } = buildSelect(this.resolveTableName(), where,
|
|
322
|
+
async findMany(query) {
|
|
323
|
+
const where = buildWhere(query.filter);
|
|
324
|
+
const { sql, params } = buildSelect(this.resolveTableName(), where, query.controls);
|
|
316
325
|
return this.driver.all(sql, params);
|
|
317
326
|
}
|
|
318
|
-
async count(
|
|
319
|
-
const where = buildWhere(filter);
|
|
327
|
+
async count(query) {
|
|
328
|
+
const where = buildWhere(query.filter);
|
|
320
329
|
const tableName = this.resolveTableName();
|
|
321
330
|
const sql = `SELECT COUNT(*) as cnt FROM "${esc(tableName)}" WHERE ${where.sql}`;
|
|
322
331
|
const row = this.driver.get(sql, where.params);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TAtscriptAnnotatedType } from '@atscript/typescript/utils';
|
|
2
|
-
import { BaseDbAdapter, TDbInsertResult, TDbInsertManyResult,
|
|
2
|
+
import { BaseDbAdapter, TDbInsertResult, TDbInsertManyResult, TDbUpdateResult, TDbDeleteResult } from '@atscript/utils-db';
|
|
3
|
+
import { Uniquery, FilterExpr } from '@uniqu/core';
|
|
3
4
|
import * as better_sqlite3 from 'better-sqlite3';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -70,15 +71,15 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
70
71
|
prepareId(id: unknown, _fieldType: TAtscriptAnnotatedType): unknown;
|
|
71
72
|
insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
|
|
72
73
|
insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
|
|
73
|
-
findOne(
|
|
74
|
-
findMany(
|
|
75
|
-
count(
|
|
76
|
-
updateOne(filter:
|
|
77
|
-
updateMany(filter:
|
|
78
|
-
replaceOne(filter:
|
|
79
|
-
replaceMany(filter:
|
|
80
|
-
deleteOne(filter:
|
|
81
|
-
deleteMany(filter:
|
|
74
|
+
findOne(query: Uniquery): Promise<Record<string, unknown> | null>;
|
|
75
|
+
findMany(query: Uniquery): Promise<Array<Record<string, unknown>>>;
|
|
76
|
+
count(query: Uniquery): Promise<number>;
|
|
77
|
+
updateOne(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
78
|
+
updateMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
79
|
+
replaceOne(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
80
|
+
replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
81
|
+
deleteOne(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
82
|
+
deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
82
83
|
ensureTable(): Promise<void>;
|
|
83
84
|
syncIndexes(): Promise<void>;
|
|
84
85
|
}
|
|
@@ -124,21 +125,12 @@ interface TSqlFragment {
|
|
|
124
125
|
params: unknown[];
|
|
125
126
|
}
|
|
126
127
|
/**
|
|
127
|
-
* Translates a
|
|
128
|
-
* with parameterized values.
|
|
129
|
-
*
|
|
130
|
-
* Supports:
|
|
131
|
-
* - Equality: `{ field: value }`
|
|
132
|
-
* - Comparison: `$gt`, `$gte`, `$lt`, `$lte`, `$ne`
|
|
133
|
-
* - Set: `$in`, `$nin`
|
|
134
|
-
* - Existence: `$exists`
|
|
135
|
-
* - Pattern: `$regex` (converted to LIKE)
|
|
136
|
-
* - Logical: `$and`, `$or`, `$not`
|
|
128
|
+
* Translates a uniqu filter expression into a parameterized SQL WHERE clause.
|
|
137
129
|
*
|
|
138
130
|
* @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
|
|
139
|
-
* Returns `{ sql: '1=1', params: [] }` for empty filters.
|
|
131
|
+
* Returns `{ sql: '1=1', params: [] }` for empty/null filters.
|
|
140
132
|
*/
|
|
141
|
-
declare function buildWhere(filter:
|
|
133
|
+
declare function buildWhere(filter: FilterExpr): TSqlFragment;
|
|
142
134
|
|
|
143
135
|
export { BetterSqlite3Driver, SqliteAdapter, buildWhere };
|
|
144
136
|
export type { TSqlFragment, TSqliteDriver, TSqliteRunResult };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseDbAdapter } from "@atscript/utils-db";
|
|
2
|
+
import { walkFilter } from "@uniqu/core";
|
|
2
3
|
|
|
3
4
|
//#region rolldown:runtime
|
|
4
5
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
@@ -8,109 +9,116 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
8
9
|
|
|
9
10
|
//#endregion
|
|
10
11
|
//#region packages/db-sqlite/src/filter-builder.ts
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
sql: `${col} > ?`,
|
|
50
|
-
params: [value]
|
|
51
|
-
};
|
|
52
|
-
case "$gte": return {
|
|
53
|
-
sql: `${col} >= ?`,
|
|
54
|
-
params: [value]
|
|
55
|
-
};
|
|
56
|
-
case "$lt": return {
|
|
57
|
-
sql: `${col} < ?`,
|
|
58
|
-
params: [value]
|
|
59
|
-
};
|
|
60
|
-
case "$lte": return {
|
|
61
|
-
sql: `${col} <= ?`,
|
|
62
|
-
params: [value]
|
|
63
|
-
};
|
|
64
|
-
case "$ne": {
|
|
65
|
-
if (value === null) return {
|
|
66
|
-
sql: `${col} IS NOT NULL`,
|
|
67
|
-
params: []
|
|
12
|
+
const EMPTY_AND = {
|
|
13
|
+
sql: "1=1",
|
|
14
|
+
params: []
|
|
15
|
+
};
|
|
16
|
+
const EMPTY_OR = {
|
|
17
|
+
sql: "0=1",
|
|
18
|
+
params: []
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* SQL visitor for `walkFilter` — renders a filter expression tree
|
|
22
|
+
* into a parameterized SQL WHERE clause.
|
|
23
|
+
*/ const sqlVisitor = {
|
|
24
|
+
comparison(field, op, value) {
|
|
25
|
+
const col = `"${escapeIdent(field)}"`;
|
|
26
|
+
switch (op) {
|
|
27
|
+
case "$eq": {
|
|
28
|
+
if (value === null) return {
|
|
29
|
+
sql: `${col} IS NULL`,
|
|
30
|
+
params: []
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
sql: `${col} = ?`,
|
|
34
|
+
params: [value]
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
case "$ne": {
|
|
38
|
+
if (value === null) return {
|
|
39
|
+
sql: `${col} IS NOT NULL`,
|
|
40
|
+
params: []
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
sql: `${col} != ?`,
|
|
44
|
+
params: [value]
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
case "$gt": return {
|
|
48
|
+
sql: `${col} > ?`,
|
|
49
|
+
params: [value]
|
|
68
50
|
};
|
|
69
|
-
return {
|
|
70
|
-
sql: `${col}
|
|
51
|
+
case "$gte": return {
|
|
52
|
+
sql: `${col} >= ?`,
|
|
71
53
|
params: [value]
|
|
72
54
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (arr.length === 0) return {
|
|
77
|
-
sql: "0=1",
|
|
78
|
-
params: []
|
|
55
|
+
case "$lt": return {
|
|
56
|
+
sql: `${col} < ?`,
|
|
57
|
+
params: [value]
|
|
79
58
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
params: [...arr]
|
|
59
|
+
case "$lte": return {
|
|
60
|
+
sql: `${col} <= ?`,
|
|
61
|
+
params: [value]
|
|
84
62
|
};
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
63
|
+
case "$in": {
|
|
64
|
+
const arr = value;
|
|
65
|
+
if (arr.length === 0) return EMPTY_OR;
|
|
66
|
+
const placeholders = arr.map(() => "?").join(", ");
|
|
67
|
+
return {
|
|
68
|
+
sql: `${col} IN (${placeholders})`,
|
|
69
|
+
params: [...arr]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
case "$nin": {
|
|
73
|
+
const arr = value;
|
|
74
|
+
if (arr.length === 0) return EMPTY_AND;
|
|
75
|
+
const placeholders = arr.map(() => "?").join(", ");
|
|
76
|
+
return {
|
|
77
|
+
sql: `${col} NOT IN (${placeholders})`,
|
|
78
|
+
params: [...arr]
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
case "$exists": return value ? {
|
|
82
|
+
sql: `${col} IS NOT NULL`,
|
|
83
|
+
params: []
|
|
84
|
+
} : {
|
|
85
|
+
sql: `${col} IS NULL`,
|
|
90
86
|
params: []
|
|
91
87
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
88
|
+
case "$regex": {
|
|
89
|
+
const pattern = regexToLike(value instanceof RegExp ? value.source : String(value));
|
|
90
|
+
return {
|
|
91
|
+
sql: `${col} LIKE ?`,
|
|
92
|
+
params: [pattern]
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
default: throw new Error(`Unsupported filter operator: ${op}`);
|
|
97
96
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
sql:
|
|
103
|
-
params:
|
|
97
|
+
},
|
|
98
|
+
and(children) {
|
|
99
|
+
if (children.length === 0) return EMPTY_AND;
|
|
100
|
+
return {
|
|
101
|
+
sql: children.map((c) => c.sql).join(" AND "),
|
|
102
|
+
params: children.flatMap((c) => c.params)
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
or(children) {
|
|
106
|
+
if (children.length === 0) return EMPTY_OR;
|
|
107
|
+
return {
|
|
108
|
+
sql: `(${children.map((c) => c.sql).join(" OR ")})`,
|
|
109
|
+
params: children.flatMap((c) => c.params)
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
not(child) {
|
|
113
|
+
return {
|
|
114
|
+
sql: `NOT (${child.sql})`,
|
|
115
|
+
params: child.params
|
|
104
116
|
};
|
|
105
|
-
case "$regex": {
|
|
106
|
-
const pattern = regexToLike(String(value));
|
|
107
|
-
return {
|
|
108
|
-
sql: `${col} LIKE ?`,
|
|
109
|
-
params: [pattern]
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
default: throw new Error(`Unsupported filter operator: ${op}`);
|
|
113
117
|
}
|
|
118
|
+
};
|
|
119
|
+
function buildWhere(filter) {
|
|
120
|
+
if (!filter || Object.keys(filter).length === 0) return EMPTY_AND;
|
|
121
|
+
return walkFilter(filter, sqlVisitor);
|
|
114
122
|
}
|
|
115
123
|
/**
|
|
116
124
|
* Basic regex-to-LIKE conversion.
|
|
@@ -149,23 +157,23 @@ function buildInsert(table, data) {
|
|
|
149
157
|
params: keys.map((k) => toSqliteValue$1(data[k]))
|
|
150
158
|
};
|
|
151
159
|
}
|
|
152
|
-
function buildSelect(table, where,
|
|
153
|
-
const cols = buildProjection(
|
|
160
|
+
function buildSelect(table, where, controls) {
|
|
161
|
+
const cols = buildProjection(controls?.$select);
|
|
154
162
|
let sql = `SELECT ${cols} FROM "${esc$1(table)}" WHERE ${where.sql}`;
|
|
155
163
|
const params = [...where.params];
|
|
156
|
-
if (
|
|
164
|
+
if (controls?.$sort) {
|
|
157
165
|
const orderParts = [];
|
|
158
|
-
for (const [col, dir] of Object.entries(
|
|
166
|
+
for (const [col, dir] of Object.entries(controls.$sort)) orderParts.push(`"${esc$1(col)}" ${dir === -1 ? "DESC" : "ASC"}`);
|
|
159
167
|
if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
|
|
160
168
|
}
|
|
161
|
-
if (
|
|
169
|
+
if (controls?.$limit !== undefined) {
|
|
162
170
|
sql += ` LIMIT ?`;
|
|
163
|
-
params.push(
|
|
171
|
+
params.push(controls.$limit);
|
|
164
172
|
}
|
|
165
|
-
if (
|
|
166
|
-
if (
|
|
173
|
+
if (controls?.$skip !== undefined) {
|
|
174
|
+
if (controls.$limit === undefined) sql += ` LIMIT -1`;
|
|
167
175
|
sql += ` OFFSET ?`;
|
|
168
|
-
params.push(
|
|
176
|
+
params.push(controls.$skip);
|
|
169
177
|
}
|
|
170
178
|
return {
|
|
171
179
|
sql,
|
|
@@ -216,13 +224,13 @@ function sqliteTypeFromDesignType(designType) {
|
|
|
216
224
|
default: return "TEXT";
|
|
217
225
|
}
|
|
218
226
|
}
|
|
219
|
-
function buildProjection(
|
|
220
|
-
if (!
|
|
221
|
-
if (Array.isArray(
|
|
222
|
-
if (
|
|
223
|
-
return
|
|
227
|
+
function buildProjection(select) {
|
|
228
|
+
if (!select) return "*";
|
|
229
|
+
if (Array.isArray(select)) {
|
|
230
|
+
if (select.length === 0) return "*";
|
|
231
|
+
return select.map((k) => `"${esc$1(k)}"`).join(", ");
|
|
224
232
|
}
|
|
225
|
-
const entries = Object.entries(
|
|
233
|
+
const entries = Object.entries(select);
|
|
226
234
|
if (entries.length === 0) return "*";
|
|
227
235
|
const firstVal = entries[0][1];
|
|
228
236
|
if (firstVal === 1) return entries.filter(([_, v]) => v === 1).map(([k]) => `"${esc$1(k)}"`).join(", ");
|
|
@@ -285,21 +293,22 @@ var SqliteAdapter = class extends BaseDbAdapter {
|
|
|
285
293
|
insertedIds: ids
|
|
286
294
|
};
|
|
287
295
|
}
|
|
288
|
-
async findOne(
|
|
289
|
-
const where = buildWhere(filter);
|
|
290
|
-
const
|
|
291
|
-
...
|
|
292
|
-
limit: 1
|
|
293
|
-
}
|
|
296
|
+
async findOne(query) {
|
|
297
|
+
const where = buildWhere(query.filter);
|
|
298
|
+
const controls = {
|
|
299
|
+
...query.controls,
|
|
300
|
+
$limit: 1
|
|
301
|
+
};
|
|
302
|
+
const { sql, params } = buildSelect(this.resolveTableName(), where, controls);
|
|
294
303
|
return this.driver.get(sql, params);
|
|
295
304
|
}
|
|
296
|
-
async findMany(
|
|
297
|
-
const where = buildWhere(filter);
|
|
298
|
-
const { sql, params } = buildSelect(this.resolveTableName(), where,
|
|
305
|
+
async findMany(query) {
|
|
306
|
+
const where = buildWhere(query.filter);
|
|
307
|
+
const { sql, params } = buildSelect(this.resolveTableName(), where, query.controls);
|
|
299
308
|
return this.driver.all(sql, params);
|
|
300
309
|
}
|
|
301
|
-
async count(
|
|
302
|
-
const where = buildWhere(filter);
|
|
310
|
+
async count(query) {
|
|
311
|
+
const where = buildWhere(query.filter);
|
|
303
312
|
const tableName = this.resolveTableName();
|
|
304
313
|
const sql = `SELECT COUNT(*) as cnt FROM "${esc(tableName)}" WHERE ${where.sql}`;
|
|
305
314
|
const row = this.driver.get(sql, where.params);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db-sqlite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"description": "SQLite adapter for @atscript/utils-db with swappable driver support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -38,10 +38,11 @@
|
|
|
38
38
|
"vitest": "3.2.4"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
+
"@uniqu/core": "^0.0.1",
|
|
41
42
|
"better-sqlite3": ">=11.0.0",
|
|
42
|
-
"@atscript/core": "^0.1.
|
|
43
|
-
"@atscript/
|
|
44
|
-
"@atscript/
|
|
43
|
+
"@atscript/core": "^0.1.30",
|
|
44
|
+
"@atscript/typescript": "^0.1.30",
|
|
45
|
+
"@atscript/utils-db": "^0.1.30"
|
|
45
46
|
},
|
|
46
47
|
"peerDependenciesMeta": {
|
|
47
48
|
"better-sqlite3": {
|