@atscript/db-sqlite 0.1.39 → 0.1.41

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.mjs CHANGED
@@ -1,19 +1,39 @@
1
- import { AtscriptDbView, BaseDbAdapter, DbError, DbSpace } from "@atscript/db";
2
1
  import { createRequire } from "node:module";
2
+ import { AtscriptDbView, BaseDbAdapter, DbError, DbSpace } from "@atscript/db";
3
3
  import { buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildInsert, buildSelect, buildUpdate, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, refActionToSql, toSqlValue } from "@atscript/db-sql-tools";
4
-
5
- //#region packages/db-sqlite/src/better-sqlite3-driver.ts
6
- function _define_property$1(obj, key, value) {
7
- if (key in obj) Object.defineProperty(obj, key, {
8
- value,
9
- enumerable: true,
10
- configurable: true,
11
- writable: true
12
- });
13
- else obj[key] = value;
14
- return obj;
15
- }
4
+ //#region src/better-sqlite3-driver.ts
5
+ /**
6
+ * {@link TSqliteDriver} implementation backed by `better-sqlite3`.
7
+ *
8
+ * Accepts either a file path (opens a new database) or a pre-created
9
+ * `Database` instance from `better-sqlite3`.
10
+ *
11
+ * ```typescript
12
+ * import { BetterSqlite3Driver } from '@atscript/db-sqlite'
13
+ *
14
+ * // In-memory database
15
+ * const driver = new BetterSqlite3Driver(':memory:')
16
+ *
17
+ * // File-based database
18
+ * const driver = new BetterSqlite3Driver('./my-data.db')
19
+ *
20
+ * // Pre-created instance
21
+ * import Database from 'better-sqlite3'
22
+ * const db = new Database(':memory:', { verbose: console.log })
23
+ * const driver = new BetterSqlite3Driver(db)
24
+ * ```
25
+ *
26
+ * Requires `better-sqlite3` to be installed:
27
+ * ```bash
28
+ * pnpm add better-sqlite3
29
+ * ```
30
+ */
16
31
  var BetterSqlite3Driver = class {
32
+ db;
33
+ constructor(pathOrDb, options) {
34
+ if (typeof pathOrDb === "string") this.db = new (createRequire(import.meta.url)("better-sqlite3"))(pathOrDb, options);
35
+ else this.db = pathOrDb;
36
+ }
17
37
  run(sql, params) {
18
38
  const stmt = this.db.prepare(sql);
19
39
  const result = params ? stmt.run(...params) : stmt.run();
@@ -36,18 +56,9 @@ var BetterSqlite3Driver = class {
36
56
  close() {
37
57
  this.db.close();
38
58
  }
39
- constructor(pathOrDb, options) {
40
- _define_property$1(this, "db", void 0);
41
- if (typeof pathOrDb === "string") {
42
- const req = createRequire(import.meta.url);
43
- const Database = req("better-sqlite3");
44
- this.db = new Database(pathOrDb, options);
45
- } else this.db = pathOrDb;
46
- }
47
59
  };
48
-
49
60
  //#endregion
50
- //#region packages/db-sqlite/src/sql-builder.ts
61
+ //#region src/sql-builder.ts
51
62
  function esc(name) {
52
63
  return name.replace(/"/g, "\"\"");
53
64
  }
@@ -57,7 +68,8 @@ function esc(name) {
57
68
  * - `abc$` → `%abc`
58
69
  * - `^abc$` → `abc`
59
70
  * - `abc` → `%abc%`
60
- */ function regexToLike(pattern) {
71
+ */
72
+ function regexToLike(pattern) {
61
73
  const hasStart = pattern.startsWith("^");
62
74
  const hasEnd = pattern.endsWith("$");
63
75
  let core = pattern;
@@ -80,7 +92,7 @@ const sqliteDialect = {
80
92
  unlimitedLimit: "-1",
81
93
  toValue: toSqlValue,
82
94
  toParam(value) {
83
- if (value === undefined) return null;
95
+ if (value === void 0) return null;
84
96
  return typeof value === "boolean" ? value ? 1 : 0 : value;
85
97
  },
86
98
  regex(quotedCol, value) {
@@ -92,27 +104,60 @@ const sqliteDialect = {
92
104
  },
93
105
  createViewPrefix: "CREATE VIEW IF NOT EXISTS"
94
106
  };
107
+ /**
108
+ * Builds an INSERT statement.
109
+ *
110
+ * @param table - Table name.
111
+ * @param data - Column→value map.
112
+ * @returns `{ sql, params }` ready for `driver.run()`.
113
+ */
95
114
  function buildInsert$1(table, data) {
96
115
  return buildInsert(sqliteDialect, table, data);
97
116
  }
117
+ /**
118
+ * Builds a SELECT statement with optional sort, limit, offset, projection.
119
+ */
98
120
  function buildSelect$1(table, where, controls) {
99
121
  return buildSelect(sqliteDialect, table, where, controls);
100
122
  }
101
- function buildUpdate$1(table, data, where) {
102
- return buildUpdate(sqliteDialect, table, data, where);
123
+ /**
124
+ * Builds an UPDATE ... SET ... WHERE statement.
125
+ */
126
+ function buildUpdate$1(table, data, where, ops) {
127
+ return buildUpdate(sqliteDialect, table, data, where, void 0, ops);
103
128
  }
129
+ /**
130
+ * Builds a DELETE ... WHERE statement.
131
+ */
104
132
  function buildDelete$1(table, where) {
105
133
  return buildDelete(sqliteDialect, table, where);
106
134
  }
135
+ /**
136
+ * Builds a CREATE VIEW IF NOT EXISTS statement from a view plan and column mappings.
137
+ *
138
+ * @param viewName - The view name.
139
+ * @param plan - Resolved view plan (entry table, joins, filter).
140
+ * @param columns - Column mappings (view column → source table.column).
141
+ * @param resolveFieldRef - Resolves a query field ref to `"table"."column"` SQL.
142
+ */
107
143
  function buildCreateView$1(viewName, plan, columns, resolveFieldRef) {
108
144
  return buildCreateView(sqliteDialect, viewName, plan, columns, resolveFieldRef);
109
145
  }
146
+ /**
147
+ * Builds a SELECT ... GROUP BY statement with aggregate functions.
148
+ */
110
149
  function buildAggregateSelect$1(table, where, controls) {
111
150
  return buildAggregateSelect(sqliteDialect, table, where, controls);
112
151
  }
152
+ /**
153
+ * Builds a COUNT query for the number of distinct groups.
154
+ */
113
155
  function buildAggregateCount$1(table, where, controls) {
114
156
  return buildAggregateCount(sqliteDialect, table, where, controls);
115
157
  }
158
+ /**
159
+ * Maps Atscript design types to SQLite storage types.
160
+ */
116
161
  function sqliteTypeFromDesignType(designType) {
117
162
  switch (designType) {
118
163
  case "number":
@@ -123,6 +168,10 @@ function sqliteTypeFromDesignType(designType) {
123
168
  default: return "TEXT";
124
169
  }
125
170
  }
171
+ /**
172
+ * Builds a CREATE TABLE IF NOT EXISTS statement from field descriptors.
173
+ * Uses pre-computed {@link TDbFieldMeta} — no raw type introspection needed.
174
+ */
126
175
  function buildCreateTable(table, fields, foreignKeys) {
127
176
  const colDefs = [];
128
177
  const primaryKeys = fields.filter((f) => f.isPrimaryKey);
@@ -153,12 +202,21 @@ function buildCreateTable(table, fields, foreignKeys) {
153
202
  }
154
203
  return `CREATE TABLE IF NOT EXISTS "${esc(table)}" (${colDefs.join(", ")})`;
155
204
  }
156
-
157
205
  //#endregion
158
- //#region packages/db-sqlite/src/filter-builder.ts
206
+ //#region src/filter-builder.ts
207
+ /**
208
+ * Translates a uniqu filter expression into a parameterized SQL WHERE clause.
209
+ *
210
+ * @returns `{ sql, params }` — the WHERE clause (without "WHERE") and bound params.
211
+ * Returns `{ sql: '1=1', params: [] }` for empty/null filters.
212
+ */
159
213
  function buildWhere(filter) {
160
214
  return buildWhere$1(sqliteDialect, filter);
161
215
  }
216
+ /**
217
+ * Like {@link buildWhere} but prefixes all column references with a table alias.
218
+ * Produces `alias."col"` instead of `"col"` — needed for JOINed queries (e.g. FTS5 search).
219
+ */
162
220
  function buildPrefixedWhere(alias, filter) {
163
221
  return buildWhere$1({
164
222
  ...sqliteDialect,
@@ -167,27 +225,35 @@ function buildPrefixedWhere(alias, filter) {
167
225
  }
168
226
  }, filter);
169
227
  }
170
-
171
228
  //#endregion
172
- //#region packages/db-sqlite/src/sqlite-adapter.ts
173
- function _define_property(obj, key, value) {
174
- if (key in obj) Object.defineProperty(obj, key, {
175
- value,
176
- enumerable: true,
177
- configurable: true,
178
- writable: true
179
- });
180
- else obj[key] = value;
181
- return obj;
182
- }
229
+ //#region src/sqlite-adapter.ts
230
+ /**
231
+ * SQLite adapter for {@link AtscriptDbTable}.
232
+ *
233
+ * Accepts any {@link TSqliteDriver} implementation — the actual SQLite engine
234
+ * is fully swappable (better-sqlite3, node:sqlite, sql.js, etc.).
235
+ *
236
+ * Usage:
237
+ * ```typescript
238
+ * import { BetterSqlite3Driver } from '@atscript/db-sqlite'
239
+ *
240
+ * const driver = new BetterSqlite3Driver(':memory:')
241
+ * const adapter = new SqliteAdapter(driver)
242
+ * const users = new AtscriptDbTable(UsersType, adapter)
243
+ * ```
244
+ */
183
245
  var SqliteAdapter = class extends BaseDbAdapter {
184
246
  supportsNativeValueDefaults() {
185
247
  return true;
186
248
  }
249
+ constructor(driver) {
250
+ super();
251
+ this.driver = driver;
252
+ this.driver.exec("PRAGMA foreign_keys = ON");
253
+ }
187
254
  async _beginTransaction() {
188
255
  this._log("BEGIN");
189
256
  this.driver.exec("BEGIN");
190
- return undefined;
191
257
  }
192
258
  async _commitTransaction() {
193
259
  this._log("COMMIT");
@@ -197,10 +263,12 @@ var SqliteAdapter = class extends BaseDbAdapter {
197
263
  this._log("ROLLBACK");
198
264
  this.driver.exec("ROLLBACK");
199
265
  }
200
- /** SQLite does not use schemas — override to always exclude schema. */ resolveTableName() {
266
+ /** SQLite does not use schemas — override to always exclude schema. */
267
+ resolveTableName() {
201
268
  return super.resolveTableName(false);
202
269
  }
203
- /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */ supportsNativeForeignKeys() {
270
+ /** SQLite enforces FK constraints natively via PRAGMA foreign_keys. */
271
+ supportsNativeForeignKeys() {
204
272
  return true;
205
273
  }
206
274
  prepareId(id, _fieldType) {
@@ -209,7 +277,8 @@ var SqliteAdapter = class extends BaseDbAdapter {
209
277
  /**
210
278
  * Wraps a write operation to catch native SQLite constraint errors
211
279
  * and rethrow as structured `DbError`.
212
- */ _wrapConstraintError(fn) {
280
+ */
281
+ _wrapConstraintError(fn) {
213
282
  try {
214
283
  return fn();
215
284
  } catch (error) {
@@ -270,46 +339,39 @@ var SqliteAdapter = class extends BaseDbAdapter {
270
339
  }
271
340
  async count(query) {
272
341
  const where = buildWhere(query.filter);
273
- const tableName = this.resolveTableName();
274
- const sql = `SELECT COUNT(*) as cnt FROM "${esc(tableName)}" WHERE ${where.sql}`;
342
+ const sql = `SELECT COUNT(*) as cnt FROM "${esc(this.resolveTableName())}" WHERE ${where.sql}`;
275
343
  this._log(sql, where.params);
276
- const row = this.driver.get(sql, where.params);
277
- return row?.cnt ?? 0;
344
+ return this.driver.get(sql, where.params)?.cnt ?? 0;
278
345
  }
279
346
  async aggregate(query) {
280
347
  const where = buildWhere(query.filter);
281
348
  const tableName = this.resolveTableName();
282
349
  if (query.controls.$count) {
283
- const { sql: sql$1, params: params$1 } = buildAggregateCount$1(tableName, where, query.controls);
284
- this._log(sql$1, params$1);
285
- const row = this.driver.get(sql$1, params$1);
286
- return [{ count: row?.count ?? 0 }];
350
+ const { sql, params } = buildAggregateCount$1(tableName, where, query.controls);
351
+ this._log(sql, params);
352
+ return [{ count: this.driver.get(sql, params)?.count ?? 0 }];
287
353
  }
288
354
  const { sql, params } = buildAggregateSelect$1(tableName, where, query.controls);
289
355
  this._log(sql, params);
290
356
  return this.driver.all(sql, params);
291
357
  }
292
- async updateOne(filter, data) {
358
+ async updateOne(filter, data, ops) {
293
359
  const where = buildWhere(filter);
294
360
  const tableName = this.resolveTableName();
295
- const setClauses = [];
296
- const setParams = [];
297
- for (const [key, value] of Object.entries(data)) {
298
- setClauses.push(`"${esc(key)}" = ?`);
299
- setParams.push(toSqlValue(value));
300
- }
301
- const sql = `UPDATE "${esc(tableName)}" SET ${setClauses.join(", ")} WHERE rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`;
302
- const allParams = [...setParams, ...where.params];
303
- this._log(sql, allParams);
304
- const result = this._wrapConstraintError(() => this.driver.run(sql, allParams));
361
+ const { sql, params } = buildUpdate$1(tableName, data, {
362
+ sql: `rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`,
363
+ params: where.params
364
+ }, ops);
365
+ this._log(sql, params);
366
+ const result = this._wrapConstraintError(() => this.driver.run(sql, params));
305
367
  return {
306
368
  matchedCount: result.changes,
307
369
  modifiedCount: result.changes
308
370
  };
309
371
  }
310
- async updateMany(filter, data) {
372
+ async updateMany(filter, data, ops) {
311
373
  const where = buildWhere(filter);
312
- const { sql, params } = buildUpdate$1(this.resolveTableName(), data, where);
374
+ const { sql, params } = buildUpdate$1(this.resolveTableName(), data, where, ops);
313
375
  this._log(sql, params);
314
376
  const result = this._wrapConstraintError(() => this.driver.run(sql, params));
315
377
  return {
@@ -320,11 +382,10 @@ var SqliteAdapter = class extends BaseDbAdapter {
320
382
  async replaceOne(filter, data) {
321
383
  const where = buildWhere(filter);
322
384
  const tableName = this.resolveTableName();
323
- const limitedWhere = {
385
+ const { sql, params } = buildUpdate$1(tableName, data, {
324
386
  sql: `rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`,
325
387
  params: where.params
326
- };
327
- const { sql, params } = buildUpdate$1(tableName, data, limitedWhere);
388
+ });
328
389
  this._log(sql, params);
329
390
  const result = this._wrapConstraintError(() => this.driver.run(sql, params));
330
391
  return {
@@ -347,15 +408,13 @@ var SqliteAdapter = class extends BaseDbAdapter {
347
408
  const tableName = this.resolveTableName();
348
409
  const sql = `DELETE FROM "${esc(tableName)}" WHERE rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`;
349
410
  this._log(sql, where.params);
350
- const result = this._wrapConstraintError(() => this.driver.run(sql, where.params));
351
- return { deletedCount: result.changes };
411
+ return { deletedCount: this._wrapConstraintError(() => this.driver.run(sql, where.params)).changes };
352
412
  }
353
413
  async deleteMany(filter) {
354
414
  const where = buildWhere(filter);
355
415
  const { sql, params } = buildDelete$1(this.resolveTableName(), where);
356
416
  this._log(sql, params);
357
- const result = this._wrapConstraintError(() => this.driver.run(sql, params));
358
- return { deletedCount: result.changes };
417
+ return { deletedCount: this._wrapConstraintError(() => this.driver.run(sql, params)).changes };
359
418
  }
360
419
  async ensureTable() {
361
420
  if (this._table instanceof AtscriptDbView) return this.ensureView();
@@ -364,10 +423,12 @@ var SqliteAdapter = class extends BaseDbAdapter {
364
423
  this.driver.exec(sql);
365
424
  this._seedIncrementStart();
366
425
  }
426
+ _incrementSeeded = false;
367
427
  /**
368
428
  * Seeds the sqlite_sequence table for auto-increment fields that have a start value.
369
429
  * Only applies once per adapter instance (idempotent via INSERT OR IGNORE + flag).
370
- */ _seedIncrementStart() {
430
+ */
431
+ _seedIncrementStart() {
371
432
  if (this._incrementSeeded) return;
372
433
  this._incrementSeeded = true;
373
434
  const tableName = this.resolveTableName();
@@ -403,7 +464,7 @@ var SqliteAdapter = class extends BaseDbAdapter {
403
464
  let ddl = `ALTER TABLE "${esc(tableName)}" ADD COLUMN "${esc(field.physicalName)}" ${sqlType}`;
404
465
  if (!field.optional && !field.isPrimaryKey) ddl += " NOT NULL";
405
466
  if (field.defaultValue?.kind === "value") ddl += ` DEFAULT ${defaultValueToSqlLiteral(field.designType, field.defaultValue.value)}`;
406
- else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValueForType(field.designType)}`;
467
+ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValueForType(field.designType)}`;
407
468
  if (field.collate) ddl += ` COLLATE ${field.collate.toUpperCase()}`;
408
469
  this._log(ddl);
409
470
  this.driver.exec(ddl);
@@ -491,8 +552,7 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
491
552
  return sqliteTypeFromDesignType(field.designType);
492
553
  }
493
554
  async getExistingColumnsForTable(tableName) {
494
- const rows = this.driver.all(`PRAGMA table_info("${esc(tableName)}")`);
495
- return rows.map((r) => ({
555
+ return this.driver.all(`PRAGMA table_info("${esc(tableName)}")`).map((r) => ({
496
556
  name: r.name,
497
557
  type: r.type,
498
558
  notnull: r.notnull === 1,
@@ -540,12 +600,12 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
540
600
  for (const [col, dir] of Object.entries(controls.$sort)) orderParts.push(`t."${esc(col)}" ${dir === -1 ? "DESC" : "ASC"}`);
541
601
  if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
542
602
  }
543
- if (controls.$limit !== undefined) {
603
+ if (controls.$limit !== void 0) {
544
604
  sql += ` LIMIT ?`;
545
605
  params.push(controls.$limit);
546
606
  }
547
- if (controls.$skip !== undefined) {
548
- if (controls.$limit === undefined) sql += ` LIMIT -1`;
607
+ if (controls.$skip !== void 0) {
608
+ if (controls.$limit === void 0) sql += ` LIMIT -1`;
549
609
  sql += ` OFFSET ?`;
550
610
  params.push(controls.$skip);
551
611
  }
@@ -561,21 +621,23 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
561
621
  const base = this._buildFtsBase(text, query.filter, indexName);
562
622
  const countSql = `SELECT COUNT(*) as cnt ${base.fromWhere}`;
563
623
  this._log(countSql, base.params);
564
- const row = this.driver.get(countSql, base.params);
565
624
  return {
566
625
  data,
567
- count: row?.cnt ?? 0
626
+ count: this.driver.get(countSql, base.params)?.cnt ?? 0
568
627
  };
569
628
  }
570
- /** Builds FTS table name from index name: `<table>__fts__<indexName>`. */ _ftsTableName(indexName) {
629
+ /** Builds FTS table name from index name: `<table>__fts__<indexName>`. */
630
+ _ftsTableName(indexName) {
571
631
  return `${this.resolveTableName()}__fts__${indexName}`;
572
632
  }
573
- /** Returns fulltext indexes from table metadata. */ _getFulltextIndexes() {
633
+ /** Returns fulltext indexes from table metadata. */
634
+ _getFulltextIndexes() {
574
635
  const result = [];
575
636
  for (const index of this._table.indexes.values()) if (index.type === "fulltext") result.push(index);
576
637
  return result;
577
638
  }
578
- /** Resolves a fulltext index by name, or returns the first available. */ _resolveFtsIndex(indexName) {
639
+ /** Resolves a fulltext index by name, or returns the first available. */
640
+ _resolveFtsIndex(indexName) {
579
641
  const ftIndexes = this._getFulltextIndexes();
580
642
  if (ftIndexes.length === 0) throw new Error("No search index available");
581
643
  if (indexName) {
@@ -588,7 +650,8 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
588
650
  /**
589
651
  * Builds the shared FROM+JOIN+WHERE fragment for FTS5 queries.
590
652
  * Both data and count queries reuse this to avoid duplicating index resolution and filter translation.
591
- */ _buildFtsBase(text, filter, indexName) {
653
+ */
654
+ _buildFtsBase(text, filter, indexName) {
592
655
  const ftsIndex = this._resolveFtsIndex(indexName);
593
656
  const ftsTable = this._ftsTableName(ftsIndex.name);
594
657
  const tableName = this.resolveTableName();
@@ -608,7 +671,8 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
608
671
  }
609
672
  /**
610
673
  * Creates/drops FTS5 virtual tables and sync triggers to match desired fulltext indexes.
611
- */ _syncFtsIndexes(tableName) {
674
+ */
675
+ _syncFtsIndexes(tableName) {
612
676
  const ftIndexes = this._getFulltextIndexes();
613
677
  const desiredFtsTables = new Set(ftIndexes.map((idx) => this._ftsTableName(idx.name)));
614
678
  const existingFts = this.driver.all(`SELECT name, sql FROM sqlite_master WHERE type='table' AND name LIKE ?`, [`${tableName}__fts__%`]).filter((r) => r.sql.startsWith("CREATE VIRTUAL TABLE")).map((r) => r.name);
@@ -619,9 +683,9 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
619
683
  if (!existingSet.has(ftsTable)) this._createFtsTable(tableName, ftsTable, index);
620
684
  }
621
685
  }
622
- /** Creates an FTS5 virtual table with sync triggers and rebuilds the index. */ _createFtsTable(tableName, ftsTable, index) {
623
- const fieldNames = index.fields.map((f) => `"${esc(f.name)}"`);
624
- const fieldList = fieldNames.join(", ");
686
+ /** Creates an FTS5 virtual table with sync triggers and rebuilds the index. */
687
+ _createFtsTable(tableName, ftsTable, index) {
688
+ const fieldList = index.fields.map((f) => `"${esc(f.name)}"`).join(", ");
625
689
  const createSql = `CREATE VIRTUAL TABLE IF NOT EXISTS "${esc(ftsTable)}" USING fts5(${fieldList}, content='${tableName.replace(/'/g, "''")}', content_rowid='rowid')`;
626
690
  this._log(createSql);
627
691
  this.driver.exec(createSql);
@@ -641,7 +705,8 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
641
705
  this._log(rebuildSql);
642
706
  this.driver.exec(rebuildSql);
643
707
  }
644
- /** Drops an FTS5 virtual table and its sync triggers. */ _dropFtsTable(ftsTable) {
708
+ /** Drops an FTS5 virtual table and its sync triggers. */
709
+ _dropFtsTable(ftsTable) {
645
710
  for (const suffix of [
646
711
  "__ai",
647
712
  "__ad",
@@ -651,28 +716,24 @@ else if (!field.optional && !field.isPrimaryKey) ddl += ` DEFAULT ${defaultValue
651
716
  this._log(sql);
652
717
  this.driver.exec(sql);
653
718
  }
654
- /** Drops all FTS virtual tables and triggers for a content table. */ _dropAllFtsTables(tableName) {
719
+ /** Drops all FTS virtual tables and triggers for a content table. */
720
+ _dropAllFtsTables(tableName) {
655
721
  const ftsTables = this.driver.all(`SELECT name, sql FROM sqlite_master WHERE type='table' AND name LIKE ?`, [`${tableName}__fts__%`]).filter((r) => r.sql.startsWith("CREATE VIRTUAL TABLE"));
656
722
  for (const { name } of ftsTables) this._dropFtsTable(name);
657
723
  }
658
- constructor(driver) {
659
- super(), _define_property(this, "driver", void 0), _define_property(this, "_incrementSeeded", void 0), this.driver = driver, this._incrementSeeded = false;
660
- this.driver.exec("PRAGMA foreign_keys = ON");
661
- }
662
724
  };
663
725
  /** Normalizes SQLite PRAGMA dflt_value to match serialized format.
664
- * PRAGMA returns `'active'` (SQL-quoted), we store `active` (raw). */ function normalizeSqliteDefault(value) {
665
- if (value === null) return undefined;
726
+ * PRAGMA returns `'active'` (SQL-quoted), we store `active` (raw). */
727
+ function normalizeSqliteDefault(value) {
728
+ if (value === null) return;
666
729
  if (value.startsWith("'") && value.endsWith("'")) return value.slice(1, -1);
667
730
  return value;
668
731
  }
669
-
670
732
  //#endregion
671
- //#region packages/db-sqlite/src/index.ts
733
+ //#region src/index.ts
672
734
  function createAdapter(connection, options) {
673
735
  const driver = new BetterSqlite3Driver(connection, options);
674
736
  return new DbSpace(() => new SqliteAdapter(driver));
675
737
  }
676
-
677
738
  //#endregion
678
- export { BetterSqlite3Driver, SqliteAdapter, buildWhere, createAdapter };
739
+ export { BetterSqlite3Driver, SqliteAdapter, buildWhere, createAdapter };
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@atscript/db-sqlite",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "SQLite adapter for @atscript/db with swappable driver support.",
5
5
  "keywords": [
6
6
  "atscript",
7
7
  "database",
8
8
  "sqlite"
9
9
  ],
10
- "homepage": "https://github.com/moostjs/atscript/tree/main/packages/db-sqlite#readme",
10
+ "homepage": "https://github.com/moostjs/atscript-db/tree/main/packages/db-sqlite#readme",
11
11
  "bugs": {
12
- "url": "https://github.com/moostjs/atscript/issues"
12
+ "url": "https://github.com/moostjs/atscript-db/issues"
13
13
  },
14
14
  "license": "MIT",
15
15
  "author": "Artem Maltsev",
16
16
  "repository": {
17
17
  "type": "git",
18
- "url": "git+https://github.com/moostjs/atscript.git",
18
+ "url": "git+https://github.com/moostjs/atscript-db.git",
19
19
  "directory": "packages/db-sqlite"
20
20
  },
21
21
  "files": [
@@ -23,27 +23,33 @@
23
23
  ],
24
24
  "type": "module",
25
25
  "main": "dist/index.mjs",
26
- "types": "dist/index.d.ts",
26
+ "types": "dist/index.d.mts",
27
27
  "exports": {
28
28
  ".": {
29
- "types": "./dist/index.d.ts",
29
+ "types": "./dist/index.d.mts",
30
30
  "import": "./dist/index.mjs",
31
31
  "require": "./dist/index.cjs"
32
32
  },
33
33
  "./package.json": "./package.json"
34
34
  },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
35
38
  "devDependencies": {
36
- "better-sqlite3": "^12.6.2",
39
+ "@atscript/core": "^0.1.39",
40
+ "@atscript/typescript": "^0.1.39",
37
41
  "@types/better-sqlite3": "^7.6.13",
38
- "vitest": "3.2.4"
42
+ "@uniqu/core": "^0.1.2",
43
+ "better-sqlite3": "^12.6.2",
44
+ "unplugin-atscript": "^0.1.39"
39
45
  },
40
46
  "peerDependencies": {
47
+ "@atscript/core": "^0.1.39",
48
+ "@atscript/typescript": "^0.1.39",
41
49
  "@uniqu/core": "^0.1.2",
42
50
  "better-sqlite3": ">=11.0.0",
43
- "@atscript/db-sql-tools": "^0.1.39",
44
- "@atscript/core": "^0.1.39",
45
- "@atscript/db": "^0.1.39",
46
- "@atscript/typescript": "^0.1.39"
51
+ "@atscript/db-sql-tools": "^0.1.41",
52
+ "@atscript/db": "^0.1.41"
47
53
  },
48
54
  "peerDependenciesMeta": {
49
55
  "better-sqlite3": {
@@ -51,7 +57,10 @@
51
57
  }
52
58
  },
53
59
  "scripts": {
54
- "pub": "pnpm publish --access public",
55
- "test": "vitest"
60
+ "postinstall": "asc -f dts",
61
+ "build": "vp pack",
62
+ "dev": "vp pack --watch",
63
+ "test": "vp test",
64
+ "check": "vp check"
56
65
  }
57
66
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025-present Artem Maltsev
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.