@atscript/db-sqlite 0.1.30 → 0.1.32

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 CHANGED
@@ -40,45 +40,46 @@ const EMPTY_OR = {
40
40
  */ const sqlVisitor = {
41
41
  comparison(field, op, value) {
42
42
  const col = `"${escapeIdent(field)}"`;
43
+ const v = toSqliteParam(value);
43
44
  switch (op) {
44
45
  case "$eq": {
45
- if (value === null) return {
46
+ if (v === null) return {
46
47
  sql: `${col} IS NULL`,
47
48
  params: []
48
49
  };
49
50
  return {
50
51
  sql: `${col} = ?`,
51
- params: [value]
52
+ params: [v]
52
53
  };
53
54
  }
54
55
  case "$ne": {
55
- if (value === null) return {
56
+ if (v === null) return {
56
57
  sql: `${col} IS NOT NULL`,
57
58
  params: []
58
59
  };
59
60
  return {
60
61
  sql: `${col} != ?`,
61
- params: [value]
62
+ params: [v]
62
63
  };
63
64
  }
64
65
  case "$gt": return {
65
66
  sql: `${col} > ?`,
66
- params: [value]
67
+ params: [v]
67
68
  };
68
69
  case "$gte": return {
69
70
  sql: `${col} >= ?`,
70
- params: [value]
71
+ params: [v]
71
72
  };
72
73
  case "$lt": return {
73
74
  sql: `${col} < ?`,
74
- params: [value]
75
+ params: [v]
75
76
  };
76
77
  case "$lte": return {
77
78
  sql: `${col} <= ?`,
78
- params: [value]
79
+ params: [v]
79
80
  };
80
81
  case "$in": {
81
- const arr = value;
82
+ const arr = value.map(toSqliteParam);
82
83
  if (arr.length === 0) return EMPTY_OR;
83
84
  const placeholders = arr.map(() => "?").join(", ");
84
85
  return {
@@ -87,7 +88,7 @@ const EMPTY_OR = {
87
88
  };
88
89
  }
89
90
  case "$nin": {
90
- const arr = value;
91
+ const arr = value.map(toSqliteParam);
91
92
  if (arr.length === 0) return EMPTY_AND;
92
93
  const placeholders = arr.map(() => "?").join(", ");
93
94
  return {
@@ -162,6 +163,13 @@ function buildWhere(filter) {
162
163
  */ function escapeIdent(name) {
163
164
  return name.replace(/"/g, "\"\"");
164
165
  }
166
+ /**
167
+ * Converts a JS value to a SQLite-bindable parameter.
168
+ * SQLite cannot bind booleans — they must be 0/1.
169
+ */ function toSqliteParam(value) {
170
+ if (typeof value === "boolean") return value ? 1 : 0;
171
+ return value;
172
+ }
165
173
 
166
174
  //#endregion
167
175
  //#region packages/db-sqlite/src/sql-builder.ts
@@ -220,7 +228,7 @@ function buildCreateTable(table, fields) {
220
228
  const primaryKeys = fields.filter((f) => f.isPrimaryKey);
221
229
  for (const field of fields) {
222
230
  if (field.ignored) continue;
223
- const sqlType = sqliteTypeFromDesignType(field.designType);
231
+ const sqlType = field.isPrimaryKey && (field.designType === "number" || field.designType === "integer") ? "INTEGER" : sqliteTypeFromDesignType(field.designType);
224
232
  let def = `"${esc$1(field.physicalName)}" ${sqlType}`;
225
233
  if (field.isPrimaryKey && primaryKeys.length === 1) def += " PRIMARY KEY";
226
234
  if (!field.optional && !field.isPrimaryKey) def += " NOT NULL";
@@ -242,16 +250,14 @@ function sqliteTypeFromDesignType(designType) {
242
250
  }
243
251
  }
244
252
  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(", ");
249
- }
250
- const entries = Object.entries(select);
251
- if (entries.length === 0) return "*";
252
- const firstVal = entries[0][1];
253
- if (firstVal === 1) return entries.filter(([_, v]) => v === 1).map(([k]) => `"${esc$1(k)}"`).join(", ");
254
- return "*";
253
+ const fields = select?.asArray;
254
+ if (!fields) return "*";
255
+ let sql = "";
256
+ for (let i = 0; i < fields.length; i++) {
257
+ if (i > 0) sql += ", ";
258
+ sql += `"${esc$1(fields[i])}"`;
259
+ }
260
+ return sql || "*";
255
261
  }
256
262
  function esc$1(name) {
257
263
  return name.replace(/"/g, "\"\"");
@@ -405,15 +411,11 @@ var SqliteAdapter = class extends __atscript_utils_db.BaseDbAdapter {
405
411
  }
406
412
  async syncIndexes() {
407
413
  const tableName = this.resolveTableName();
408
- const columnMap = this._table.columnMap;
409
414
  await this.syncIndexesWithDiff({
410
415
  listExisting: async () => this.driver.all(`PRAGMA index_list("${esc(tableName)}")`).filter((i) => !i.name.startsWith("sqlite_")),
411
416
  createIndex: async (index) => {
412
417
  const unique = index.type === "unique" ? "UNIQUE " : "";
413
- const cols = index.fields.map((f) => {
414
- const physical = columnMap.get(f.name) ?? f.name;
415
- return `"${esc(physical)}" ${f.sort === "desc" ? "DESC" : "ASC"}`;
416
- }).join(", ");
418
+ const cols = index.fields.map((f) => `"${esc(f.name)}" ${f.sort === "desc" ? "DESC" : "ASC"}`).join(", ");
417
419
  this.driver.exec(`CREATE ${unique}INDEX IF NOT EXISTS "${esc(index.key)}" ON "${esc(tableName)}" (${cols})`);
418
420
  },
419
421
  dropIndex: async (name) => {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { TAtscriptAnnotatedType } from '@atscript/typescript/utils';
2
- import { BaseDbAdapter, TDbInsertResult, TDbInsertManyResult, TDbUpdateResult, TDbDeleteResult } from '@atscript/utils-db';
3
- import { Uniquery, FilterExpr } from '@uniqu/core';
2
+ import { BaseDbAdapter, TDbInsertResult, TDbInsertManyResult, DbQuery, FilterExpr, TDbUpdateResult, TDbDeleteResult } from '@atscript/utils-db';
4
3
  import * as better_sqlite3 from 'better-sqlite3';
4
+ import { FilterExpr as FilterExpr$1 } from '@uniqu/core';
5
5
 
6
6
  /**
7
7
  * Result of a SQL statement that modifies data (INSERT, UPDATE, DELETE).
@@ -71,9 +71,9 @@ declare class SqliteAdapter extends BaseDbAdapter {
71
71
  prepareId(id: unknown, _fieldType: TAtscriptAnnotatedType): unknown;
72
72
  insertOne(data: Record<string, unknown>): Promise<TDbInsertResult>;
73
73
  insertMany(data: Array<Record<string, unknown>>): Promise<TDbInsertManyResult>;
74
- findOne(query: Uniquery): Promise<Record<string, unknown> | null>;
75
- findMany(query: Uniquery): Promise<Array<Record<string, unknown>>>;
76
- count(query: Uniquery): Promise<number>;
74
+ findOne(query: DbQuery): Promise<Record<string, unknown> | null>;
75
+ findMany(query: DbQuery): Promise<Array<Record<string, unknown>>>;
76
+ count(query: DbQuery): Promise<number>;
77
77
  updateOne(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
78
78
  updateMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
79
79
  replaceOne(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
@@ -130,7 +130,7 @@ interface TSqlFragment {
130
130
  * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
131
131
  * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
132
132
  */
133
- declare function buildWhere(filter: FilterExpr): TSqlFragment;
133
+ declare function buildWhere(filter: FilterExpr$1): TSqlFragment;
134
134
 
135
135
  export { BetterSqlite3Driver, SqliteAdapter, buildWhere };
136
136
  export type { TSqlFragment, TSqliteDriver, TSqliteRunResult };
package/dist/index.mjs CHANGED
@@ -23,45 +23,46 @@ const EMPTY_OR = {
23
23
  */ const sqlVisitor = {
24
24
  comparison(field, op, value) {
25
25
  const col = `"${escapeIdent(field)}"`;
26
+ const v = toSqliteParam(value);
26
27
  switch (op) {
27
28
  case "$eq": {
28
- if (value === null) return {
29
+ if (v === null) return {
29
30
  sql: `${col} IS NULL`,
30
31
  params: []
31
32
  };
32
33
  return {
33
34
  sql: `${col} = ?`,
34
- params: [value]
35
+ params: [v]
35
36
  };
36
37
  }
37
38
  case "$ne": {
38
- if (value === null) return {
39
+ if (v === null) return {
39
40
  sql: `${col} IS NOT NULL`,
40
41
  params: []
41
42
  };
42
43
  return {
43
44
  sql: `${col} != ?`,
44
- params: [value]
45
+ params: [v]
45
46
  };
46
47
  }
47
48
  case "$gt": return {
48
49
  sql: `${col} > ?`,
49
- params: [value]
50
+ params: [v]
50
51
  };
51
52
  case "$gte": return {
52
53
  sql: `${col} >= ?`,
53
- params: [value]
54
+ params: [v]
54
55
  };
55
56
  case "$lt": return {
56
57
  sql: `${col} < ?`,
57
- params: [value]
58
+ params: [v]
58
59
  };
59
60
  case "$lte": return {
60
61
  sql: `${col} <= ?`,
61
- params: [value]
62
+ params: [v]
62
63
  };
63
64
  case "$in": {
64
- const arr = value;
65
+ const arr = value.map(toSqliteParam);
65
66
  if (arr.length === 0) return EMPTY_OR;
66
67
  const placeholders = arr.map(() => "?").join(", ");
67
68
  return {
@@ -70,7 +71,7 @@ const EMPTY_OR = {
70
71
  };
71
72
  }
72
73
  case "$nin": {
73
- const arr = value;
74
+ const arr = value.map(toSqliteParam);
74
75
  if (arr.length === 0) return EMPTY_AND;
75
76
  const placeholders = arr.map(() => "?").join(", ");
76
77
  return {
@@ -145,6 +146,13 @@ function buildWhere(filter) {
145
146
  */ function escapeIdent(name) {
146
147
  return name.replace(/"/g, "\"\"");
147
148
  }
149
+ /**
150
+ * Converts a JS value to a SQLite-bindable parameter.
151
+ * SQLite cannot bind booleans — they must be 0/1.
152
+ */ function toSqliteParam(value) {
153
+ if (typeof value === "boolean") return value ? 1 : 0;
154
+ return value;
155
+ }
148
156
 
149
157
  //#endregion
150
158
  //#region packages/db-sqlite/src/sql-builder.ts
@@ -203,7 +211,7 @@ function buildCreateTable(table, fields) {
203
211
  const primaryKeys = fields.filter((f) => f.isPrimaryKey);
204
212
  for (const field of fields) {
205
213
  if (field.ignored) continue;
206
- const sqlType = sqliteTypeFromDesignType(field.designType);
214
+ const sqlType = field.isPrimaryKey && (field.designType === "number" || field.designType === "integer") ? "INTEGER" : sqliteTypeFromDesignType(field.designType);
207
215
  let def = `"${esc$1(field.physicalName)}" ${sqlType}`;
208
216
  if (field.isPrimaryKey && primaryKeys.length === 1) def += " PRIMARY KEY";
209
217
  if (!field.optional && !field.isPrimaryKey) def += " NOT NULL";
@@ -225,16 +233,14 @@ function sqliteTypeFromDesignType(designType) {
225
233
  }
226
234
  }
227
235
  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(", ");
236
+ const fields = select?.asArray;
237
+ if (!fields) return "*";
238
+ let sql = "";
239
+ for (let i = 0; i < fields.length; i++) {
240
+ if (i > 0) sql += ", ";
241
+ sql += `"${esc$1(fields[i])}"`;
232
242
  }
233
- const entries = Object.entries(select);
234
- if (entries.length === 0) return "*";
235
- const firstVal = entries[0][1];
236
- if (firstVal === 1) return entries.filter(([_, v]) => v === 1).map(([k]) => `"${esc$1(k)}"`).join(", ");
237
- return "*";
243
+ return sql || "*";
238
244
  }
239
245
  function esc$1(name) {
240
246
  return name.replace(/"/g, "\"\"");
@@ -388,15 +394,11 @@ var SqliteAdapter = class extends BaseDbAdapter {
388
394
  }
389
395
  async syncIndexes() {
390
396
  const tableName = this.resolveTableName();
391
- const columnMap = this._table.columnMap;
392
397
  await this.syncIndexesWithDiff({
393
398
  listExisting: async () => this.driver.all(`PRAGMA index_list("${esc(tableName)}")`).filter((i) => !i.name.startsWith("sqlite_")),
394
399
  createIndex: async (index) => {
395
400
  const unique = index.type === "unique" ? "UNIQUE " : "";
396
- const cols = index.fields.map((f) => {
397
- const physical = columnMap.get(f.name) ?? f.name;
398
- return `"${esc(physical)}" ${f.sort === "desc" ? "DESC" : "ASC"}`;
399
- }).join(", ");
401
+ const cols = index.fields.map((f) => `"${esc(f.name)}" ${f.sort === "desc" ? "DESC" : "ASC"}`).join(", ");
400
402
  this.driver.exec(`CREATE ${unique}INDEX IF NOT EXISTS "${esc(index.key)}" ON "${esc(tableName)}" (${cols})`);
401
403
  },
402
404
  dropIndex: async (name) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-sqlite",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "SQLite adapter for @atscript/utils-db with swappable driver support.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -38,11 +38,11 @@
38
38
  "vitest": "3.2.4"
39
39
  },
40
40
  "peerDependencies": {
41
- "@uniqu/core": "^0.0.1",
41
+ "@uniqu/core": "^0.0.2",
42
42
  "better-sqlite3": ">=11.0.0",
43
- "@atscript/core": "^0.1.30",
44
- "@atscript/typescript": "^0.1.30",
45
- "@atscript/utils-db": "^0.1.30"
43
+ "@atscript/core": "^0.1.32",
44
+ "@atscript/typescript": "^0.1.32",
45
+ "@atscript/utils-db": "^0.1.32"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "better-sqlite3": {