@atscript/db-sqlite 0.1.161 → 0.1.163
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 +97 -43
- package/dist/index.d.cts +23 -3
- package/dist/index.d.mts +23 -3
- package/dist/index.mjs +99 -45
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -310,6 +310,7 @@ const sqliteDialect = {
|
|
|
310
310
|
return `"${esc(name)}"`;
|
|
311
311
|
},
|
|
312
312
|
unlimitedLimit: "-1",
|
|
313
|
+
stringLiteral: _atscript_db_sql_tools.sqlStringLiteral,
|
|
313
314
|
toValue: _atscript_db_sql_tools.toSqlValue,
|
|
314
315
|
toParam(value) {
|
|
315
316
|
if (value === void 0) return null;
|
|
@@ -801,6 +802,21 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
801
802
|
supportsNullsPlacement() {
|
|
802
803
|
return true;
|
|
803
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* Locking reads are accepted as a no-op (since 0.1.162): every transaction
|
|
807
|
+
* starts with `BEGIN IMMEDIATE`, which holds the database write lock, so
|
|
808
|
+
* reads inside it are current and no other writer can run until it ends.
|
|
809
|
+
*/
|
|
810
|
+
supportsReadLocks() {
|
|
811
|
+
return true;
|
|
812
|
+
}
|
|
813
|
+
/** Every level — a `BEGIN IMMEDIATE` transaction is serializable. @since 0.1.162 */
|
|
814
|
+
isolationLevels() {
|
|
815
|
+
return _atscript_db.ALL_ISOLATION_LEVELS;
|
|
816
|
+
}
|
|
817
|
+
_inherentIsolation() {
|
|
818
|
+
return "serializable";
|
|
819
|
+
}
|
|
804
820
|
/** Computed view columns and first-row joins. */
|
|
805
821
|
viewCapabilities() {
|
|
806
822
|
return _atscript_db.ALL_VIEW_CAPABILITIES;
|
|
@@ -1153,8 +1169,25 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1153
1169
|
modifiedCount: result.changes
|
|
1154
1170
|
};
|
|
1155
1171
|
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Bounded writes (since 0.1.162) through an ordered, limited rowid subquery
|
|
1174
|
+
* (`rowid IN (SELECT rowid … ORDER BY … LIMIT n)`) — no
|
|
1175
|
+
* `SQLITE_ENABLE_UPDATE_DELETE_LIMIT` build needed.
|
|
1176
|
+
*/
|
|
1177
|
+
supportsWriteLimit() {
|
|
1178
|
+
return true;
|
|
1179
|
+
}
|
|
1180
|
+
/** One writer at a time: the rowid pick and the write run as one statement, never interleaved. */
|
|
1181
|
+
writeLimitIsAtomic() {
|
|
1182
|
+
return true;
|
|
1183
|
+
}
|
|
1184
|
+
/** `where` narrowed to a bounded write's rows, or `where` itself when unbounded. */
|
|
1185
|
+
_boundedWhere(where, bound) {
|
|
1186
|
+
if (!bound) return where;
|
|
1187
|
+
return (0, _atscript_db_sql_tools.writeLimitWhere)(sqliteDialect, `"${esc(this.resolveTableName())}"`, ["rowid"], where, bound);
|
|
1188
|
+
}
|
|
1156
1189
|
async updateMany(filter, data, ops, opts) {
|
|
1157
|
-
const where = buildWhere(filter);
|
|
1190
|
+
const where = this._boundedWhere(buildWhere(filter), opts?.limit);
|
|
1158
1191
|
const versionColumn = this._versionColumnFor(opts);
|
|
1159
1192
|
const { sql, params } = buildUpdate(this.resolveTableName(), data, where, ops, versionColumn);
|
|
1160
1193
|
this._log(sql, params);
|
|
@@ -1168,10 +1201,10 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1168
1201
|
const where = buildWhere(filter);
|
|
1169
1202
|
const tableName = this.resolveTableName();
|
|
1170
1203
|
const versionColumn = this._table.versionColumnPhysical;
|
|
1171
|
-
const { sql, params } = buildUpdate(tableName, (0, _atscript_db_sql_tools.fillReplacePayload)(data, (0, _atscript_db_sql_tools.replaceColumnsFor)(this._table.fieldDescriptors, this.nativeDefaultFns()), versionColumn), {
|
|
1204
|
+
const { sql, params } = buildUpdate(tableName, (0, _atscript_db_sql_tools.fillReplacePayload)(data, (0, _atscript_db_sql_tools.replaceColumnsFor)(this._table.fieldDescriptors, this.nativeDefaultFns()), versionColumn, this._table.onUpdateIncPhysical), {
|
|
1172
1205
|
sql: `rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`,
|
|
1173
1206
|
params: where.params
|
|
1174
|
-
},
|
|
1207
|
+
}, this._onUpdateIncOps(), versionColumn, expectedVersion);
|
|
1175
1208
|
this._log(sql, params);
|
|
1176
1209
|
const result = await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)));
|
|
1177
1210
|
return {
|
|
@@ -1182,7 +1215,7 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1182
1215
|
async replaceMany(filter, data) {
|
|
1183
1216
|
const where = buildWhere(filter);
|
|
1184
1217
|
const versionColumn = this._table.versionColumnPhysical;
|
|
1185
|
-
const { sql, params } = buildUpdate(this.resolveTableName(), data, where,
|
|
1218
|
+
const { sql, params } = buildUpdate(this.resolveTableName(), data, where, this._onUpdateIncOps(), versionColumn);
|
|
1186
1219
|
this._log(sql, params);
|
|
1187
1220
|
const result = await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)));
|
|
1188
1221
|
return {
|
|
@@ -1197,8 +1230,8 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1197
1230
|
this._log(sql, where.params);
|
|
1198
1231
|
return { deletedCount: (await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, where.params)))).changes };
|
|
1199
1232
|
}
|
|
1200
|
-
async deleteMany(filter) {
|
|
1201
|
-
const where = buildWhere(filter);
|
|
1233
|
+
async deleteMany(filter, opts) {
|
|
1234
|
+
const where = this._boundedWhere(buildWhere(filter), opts?.limit);
|
|
1202
1235
|
const { sql, params } = buildDelete(this.resolveTableName(), where);
|
|
1203
1236
|
this._log(sql, params);
|
|
1204
1237
|
return { deletedCount: (await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)))).changes };
|
|
@@ -1494,30 +1527,33 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1494
1527
|
});
|
|
1495
1528
|
}
|
|
1496
1529
|
async syncIndexes() {
|
|
1497
|
-
return this._withExclusiveConnection(
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1530
|
+
return this._withExclusiveConnection(() => this._syncIndexes(false));
|
|
1531
|
+
}
|
|
1532
|
+
async _syncIndexes(dryRun) {
|
|
1533
|
+
const tableName = this.resolveTableName();
|
|
1534
|
+
const changes = await this.syncIndexesWithDiff({
|
|
1535
|
+
dryRun,
|
|
1536
|
+
listExisting: async () => this.driver.all(`PRAGMA index_list("${esc(tableName)}")`).filter((i) => !i.name.startsWith("sqlite_")).map((i) => ({
|
|
1537
|
+
name: i.name,
|
|
1538
|
+
columns: this.driver.all(`PRAGMA index_info("${esc(i.name)}")`).map((c) => c.name).filter((n) => n !== null)
|
|
1539
|
+
})),
|
|
1540
|
+
createIndex: async (index) => {
|
|
1541
|
+
const unique = index.type === "unique" ? "UNIQUE " : "";
|
|
1542
|
+
const cols = index.fields.map((f) => `"${esc(f.name)}" ${f.sort === "desc" ? "DESC" : "ASC"}`).join(", ");
|
|
1543
|
+
const sql = `CREATE ${unique}INDEX IF NOT EXISTS "${esc(index.key)}" ON "${esc(tableName)}" (${cols})`;
|
|
1544
|
+
this._log(sql);
|
|
1545
|
+
this.driver.exec(sql);
|
|
1546
|
+
},
|
|
1547
|
+
dropIndex: async (name) => {
|
|
1548
|
+
const sql = `DROP INDEX IF EXISTS "${esc(name)}"`;
|
|
1549
|
+
this._log(sql);
|
|
1550
|
+
this.driver.exec(sql);
|
|
1551
|
+
},
|
|
1552
|
+
skipIndex: (index) => index.type === "fulltext" || index.type === "geo" ? null : void 0
|
|
1520
1553
|
});
|
|
1554
|
+
changes.push(...await this._syncFtsIndexes(tableName, dryRun));
|
|
1555
|
+
changes.push(...await this._syncVecIndexes(tableName, dryRun));
|
|
1556
|
+
return changes;
|
|
1521
1557
|
}
|
|
1522
1558
|
getSearchIndexes() {
|
|
1523
1559
|
const indexes = [];
|
|
@@ -1686,20 +1722,31 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1686
1722
|
/**
|
|
1687
1723
|
* Creates/drops FTS5 virtual tables and sync triggers to match desired fulltext indexes.
|
|
1688
1724
|
*/
|
|
1689
|
-
_syncFtsIndexes(tableName) {
|
|
1725
|
+
async _syncFtsIndexes(tableName, dryRun) {
|
|
1726
|
+
const { changes, apply } = (0, _atscript_db.createChangeRecorder)(dryRun);
|
|
1690
1727
|
const ftIndexes = this._getFulltextIndexes().filter((idx) => (0, _atscript_db.splitFulltextFields)(idx).text.length > 0);
|
|
1691
1728
|
const desiredFtsTables = new Set(ftIndexes.map((idx) => this._ftsTableName(idx.name)));
|
|
1692
|
-
const existingFts = this.
|
|
1693
|
-
for (const name of existingFts) if (!desiredFtsTables.has(name))
|
|
1729
|
+
const existingFts = this._listShadowTables(tableName, "fts");
|
|
1730
|
+
for (const name of existingFts) if (!desiredFtsTables.has(name)) await apply({
|
|
1731
|
+
name,
|
|
1732
|
+
action: "drop"
|
|
1733
|
+
}, name, () => this._dropFtsTable(name));
|
|
1694
1734
|
const existingSet = new Set(existingFts);
|
|
1695
1735
|
for (const index of ftIndexes) {
|
|
1696
1736
|
const ftsTable = this._ftsTableName(index.name);
|
|
1697
|
-
if (!existingSet.has(ftsTable))
|
|
1698
|
-
|
|
1737
|
+
if (!existingSet.has(ftsTable)) await apply({
|
|
1738
|
+
name: ftsTable,
|
|
1739
|
+
action: "add"
|
|
1740
|
+
}, ftsTable, () => this._createFtsTable(tableName, ftsTable, index));
|
|
1741
|
+
else if (!this._ftsColumnsMatch(ftsTable, index)) await apply({
|
|
1742
|
+
name: ftsTable,
|
|
1743
|
+
action: "rebuild"
|
|
1744
|
+
}, ftsTable, () => {
|
|
1699
1745
|
this._dropFtsTable(ftsTable);
|
|
1700
1746
|
this._createFtsTable(tableName, ftsTable, index);
|
|
1701
|
-
}
|
|
1747
|
+
});
|
|
1702
1748
|
}
|
|
1749
|
+
return changes;
|
|
1703
1750
|
}
|
|
1704
1751
|
/** Whether an existing FTS5 table has exactly the index's text columns, in order. */
|
|
1705
1752
|
_ftsColumnsMatch(ftsTable, index) {
|
|
@@ -1930,21 +1977,29 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
|
|
|
1930
1977
|
/**
|
|
1931
1978
|
* Creates/drops vec0 virtual shadow tables and sync triggers to match desired vector fields.
|
|
1932
1979
|
*/
|
|
1933
|
-
_syncVecIndexes(tableName) {
|
|
1934
|
-
|
|
1980
|
+
async _syncVecIndexes(tableName, dryRun) {
|
|
1981
|
+
const { changes, apply } = (0, _atscript_db.createChangeRecorder)(dryRun);
|
|
1982
|
+
if (this._vectorFields.size === 0) return changes;
|
|
1935
1983
|
if (!this._detectVectorSupport()) {
|
|
1936
1984
|
this._log("[atscript-db-sqlite] sqlite-vec not available, skipping vec0 shadow table sync (vector fields stored as JSON)");
|
|
1937
|
-
return;
|
|
1985
|
+
return changes;
|
|
1938
1986
|
}
|
|
1939
1987
|
const desiredVecTables = /* @__PURE__ */ new Map();
|
|
1940
1988
|
for (const [fieldPath, meta] of this._vectorFields.entries()) desiredVecTables.set(this._vecTableName(meta.indexName), {
|
|
1941
1989
|
field: fieldPath,
|
|
1942
1990
|
meta
|
|
1943
1991
|
});
|
|
1944
|
-
const existingVec = this.
|
|
1945
|
-
for (const name of existingVec) if (!desiredVecTables.has(name))
|
|
1992
|
+
const existingVec = this._listShadowTables(tableName, "vec");
|
|
1993
|
+
for (const name of existingVec) if (!desiredVecTables.has(name)) await apply({
|
|
1994
|
+
name,
|
|
1995
|
+
action: "drop"
|
|
1996
|
+
}, name, () => this._dropVecTable(name));
|
|
1946
1997
|
const existingSet = new Set(existingVec);
|
|
1947
|
-
for (const [vecTable, { field, meta }] of desiredVecTables.entries()) if (!existingSet.has(vecTable))
|
|
1998
|
+
for (const [vecTable, { field, meta }] of desiredVecTables.entries()) if (!existingSet.has(vecTable)) await apply({
|
|
1999
|
+
name: vecTable,
|
|
2000
|
+
action: "add"
|
|
2001
|
+
}, vecTable, () => this._createVecTable(tableName, vecTable, field, meta));
|
|
2002
|
+
return changes;
|
|
1948
2003
|
}
|
|
1949
2004
|
/** Creates a vec0 virtual shadow table with sync triggers and seeds it from existing rows. */
|
|
1950
2005
|
_createVecTable(tableName, vecTable, field, vec) {
|
|
@@ -2034,8 +2089,7 @@ function andWhere(left, right) {
|
|
|
2034
2089
|
* PRAGMA returns `'active'` (SQL-quoted), we store `active` (raw). */
|
|
2035
2090
|
function normalizeSqliteDefault(value) {
|
|
2036
2091
|
if (value === null) return;
|
|
2037
|
-
|
|
2038
|
-
return value;
|
|
2092
|
+
return (0, _atscript_db_sql_tools.unquoteSqlStringLiteral)(value) ?? value;
|
|
2039
2093
|
}
|
|
2040
2094
|
//#endregion
|
|
2041
2095
|
//#region src/index.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateOptions, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TJsonCopyTarget, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
|
|
1
|
+
import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteManyOptions, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbIsolationLevel, TDbObjectKind, TDbUpdateOptions, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TIndexChange, TJsonCopyTarget, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
|
|
2
2
|
import { TMetadataMap } from "@atscript/typescript/utils";
|
|
3
3
|
import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
|
|
4
4
|
import { TFilterVisitorOptions, TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
|
|
@@ -299,6 +299,15 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
299
299
|
supportsAggregateExpressions(): boolean;
|
|
300
300
|
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
301
301
|
supportsNullsPlacement(): boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Locking reads are accepted as a no-op (since 0.1.162): every transaction
|
|
304
|
+
* starts with `BEGIN IMMEDIATE`, which holds the database write lock, so
|
|
305
|
+
* reads inside it are current and no other writer can run until it ends.
|
|
306
|
+
*/
|
|
307
|
+
supportsReadLocks(): boolean;
|
|
308
|
+
/** Every level — a `BEGIN IMMEDIATE` transaction is serializable. @since 0.1.162 */
|
|
309
|
+
isolationLevels(): ReadonlySet<TDbIsolationLevel>;
|
|
310
|
+
protected _inherentIsolation(): TDbIsolationLevel;
|
|
302
311
|
/** Computed view columns and first-row joins. */
|
|
303
312
|
viewCapabilities(): ReadonlySet<TViewCapability>;
|
|
304
313
|
/** INSERT text per column signature (rows of one table share a handful of shapes). */
|
|
@@ -406,11 +415,21 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
406
415
|
count(query: DbQuery): Promise<number>;
|
|
407
416
|
aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
|
|
408
417
|
updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
|
418
|
+
/**
|
|
419
|
+
* Bounded writes (since 0.1.162) through an ordered, limited rowid subquery
|
|
420
|
+
* (`rowid IN (SELECT rowid … ORDER BY … LIMIT n)`) — no
|
|
421
|
+
* `SQLITE_ENABLE_UPDATE_DELETE_LIMIT` build needed.
|
|
422
|
+
*/
|
|
423
|
+
supportsWriteLimit(): boolean;
|
|
424
|
+
/** One writer at a time: the rowid pick and the write run as one statement, never interleaved. */
|
|
425
|
+
writeLimitIsAtomic(): boolean;
|
|
426
|
+
/** `where` narrowed to a bounded write's rows, or `where` itself when unbounded. */
|
|
427
|
+
private _boundedWhere;
|
|
409
428
|
updateMany(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
|
410
429
|
replaceOne(filter: FilterExpr, data: Record<string, unknown>, expectedVersion?: number): Promise<TDbUpdateResult>;
|
|
411
430
|
replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
412
431
|
deleteOne(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
413
|
-
deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
432
|
+
deleteMany(filter: FilterExpr, opts?: TDbDeleteManyOptions): Promise<TDbDeleteResult>;
|
|
414
433
|
/**
|
|
415
434
|
* SQLite accepts forward FK references, so a foreign-key cycle is created
|
|
416
435
|
* inline in any order — `opts.deferForeignKeysTo` is accepted and ignored.
|
|
@@ -462,7 +481,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
462
481
|
* sync). A virtual table's hidden columns (`hidden` 1) are skipped.
|
|
463
482
|
*/
|
|
464
483
|
getExistingColumnsForTable(tableName: string): Promise<TExistingColumn[]>;
|
|
465
|
-
syncIndexes(): Promise<
|
|
484
|
+
syncIndexes(): Promise<TIndexChange[]>;
|
|
485
|
+
protected _syncIndexes(dryRun: boolean): Promise<TIndexChange[]>;
|
|
466
486
|
getSearchIndexes(): TSearchIndexInfo[];
|
|
467
487
|
search(text: string, query: DbQuery, indexName?: string): Promise<Array<Record<string, unknown>>>;
|
|
468
488
|
searchWithCount(text: string, query: DbQuery, indexName?: string): Promise<{
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateOptions, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TJsonCopyTarget, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
|
|
1
|
+
import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteManyOptions, TDbDeleteResult, TDbFieldMeta, TDbInsertIgnoreSlot, TDbInsertManyResult, TDbInsertResult, TDbIsolationLevel, TDbObjectKind, TDbUpdateOptions, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TIndexChange, TJsonCopyTarget, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair, TViewCapability } from "@atscript/db";
|
|
2
2
|
import { TFilterVisitorOptions, TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
|
|
3
3
|
import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
|
|
4
4
|
import { TMetadataMap } from "@atscript/typescript/utils";
|
|
@@ -299,6 +299,15 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
299
299
|
supportsAggregateExpressions(): boolean;
|
|
300
300
|
/** `$nulls` / `@db.sort.nulls` NULL placement — `NULLS FIRST` / `NULLS LAST`. */
|
|
301
301
|
supportsNullsPlacement(): boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Locking reads are accepted as a no-op (since 0.1.162): every transaction
|
|
304
|
+
* starts with `BEGIN IMMEDIATE`, which holds the database write lock, so
|
|
305
|
+
* reads inside it are current and no other writer can run until it ends.
|
|
306
|
+
*/
|
|
307
|
+
supportsReadLocks(): boolean;
|
|
308
|
+
/** Every level — a `BEGIN IMMEDIATE` transaction is serializable. @since 0.1.162 */
|
|
309
|
+
isolationLevels(): ReadonlySet<TDbIsolationLevel>;
|
|
310
|
+
protected _inherentIsolation(): TDbIsolationLevel;
|
|
302
311
|
/** Computed view columns and first-row joins. */
|
|
303
312
|
viewCapabilities(): ReadonlySet<TViewCapability>;
|
|
304
313
|
/** INSERT text per column signature (rows of one table share a handful of shapes). */
|
|
@@ -406,11 +415,21 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
406
415
|
count(query: DbQuery): Promise<number>;
|
|
407
416
|
aggregate(query: DbQuery): Promise<Array<Record<string, unknown>>>;
|
|
408
417
|
updateOne(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, expectedVersion?: number, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
|
418
|
+
/**
|
|
419
|
+
* Bounded writes (since 0.1.162) through an ordered, limited rowid subquery
|
|
420
|
+
* (`rowid IN (SELECT rowid … ORDER BY … LIMIT n)`) — no
|
|
421
|
+
* `SQLITE_ENABLE_UPDATE_DELETE_LIMIT` build needed.
|
|
422
|
+
*/
|
|
423
|
+
supportsWriteLimit(): boolean;
|
|
424
|
+
/** One writer at a time: the rowid pick and the write run as one statement, never interleaved. */
|
|
425
|
+
writeLimitIsAtomic(): boolean;
|
|
426
|
+
/** `where` narrowed to a bounded write's rows, or `where` itself when unbounded. */
|
|
427
|
+
private _boundedWhere;
|
|
409
428
|
updateMany(filter: FilterExpr, data: Record<string, unknown>, ops?: TFieldOps, opts?: TDbUpdateOptions): Promise<TDbUpdateResult>;
|
|
410
429
|
replaceOne(filter: FilterExpr, data: Record<string, unknown>, expectedVersion?: number): Promise<TDbUpdateResult>;
|
|
411
430
|
replaceMany(filter: FilterExpr, data: Record<string, unknown>): Promise<TDbUpdateResult>;
|
|
412
431
|
deleteOne(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
413
|
-
deleteMany(filter: FilterExpr): Promise<TDbDeleteResult>;
|
|
432
|
+
deleteMany(filter: FilterExpr, opts?: TDbDeleteManyOptions): Promise<TDbDeleteResult>;
|
|
414
433
|
/**
|
|
415
434
|
* SQLite accepts forward FK references, so a foreign-key cycle is created
|
|
416
435
|
* inline in any order — `opts.deferForeignKeysTo` is accepted and ignored.
|
|
@@ -462,7 +481,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
|
|
|
462
481
|
* sync). A virtual table's hidden columns (`hidden` 1) are skipped.
|
|
463
482
|
*/
|
|
464
483
|
getExistingColumnsForTable(tableName: string): Promise<TExistingColumn[]>;
|
|
465
|
-
syncIndexes(): Promise<
|
|
484
|
+
syncIndexes(): Promise<TIndexChange[]>;
|
|
485
|
+
protected _syncIndexes(dryRun: boolean): Promise<TIndexChange[]>;
|
|
466
486
|
getSearchIndexes(): TSearchIndexInfo[];
|
|
467
487
|
search(text: string, query: DbQuery, indexName?: string): Promise<Array<Record<string, unknown>>>;
|
|
468
488
|
searchWithCount(text: string, query: DbQuery, indexName?: string): Promise<{
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, BaseDbAdapter, DbError, DbSpace, defaultFulltextIndex, describeFulltext, fkColumns, searchIndexNotFoundMessage, searchTermInteger, splitFulltextFields, vectorIndexNotFoundMessage } from "@atscript/db";
|
|
2
|
+
import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_ISOLATION_LEVELS, ALL_VIEW_CAPABILITIES, BaseDbAdapter, DbError, DbSpace, createChangeRecorder, defaultFulltextIndex, describeFulltext, fkColumns, searchIndexNotFoundMessage, searchTermInteger, splitFulltextFields, vectorIndexNotFoundMessage } from "@atscript/db";
|
|
3
3
|
import { resolveAggregateSearch } from "@atscript/db/agg";
|
|
4
|
-
import { EMPTY_AND, InsertSqlCache, SEARCH_SOURCE_ALIAS, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildJsonColumnCopy, buildJsonifyText, buildKeyViolationCount, buildPartitionedSelect, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, fromSourceSql, geoWindowFromControls, jsonDollarPath, orFragment, orderByList, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, viewReadSource } from "@atscript/db-sql-tools";
|
|
4
|
+
import { EMPTY_AND, InsertSqlCache, SEARCH_SOURCE_ALIAS, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildJsonColumnCopy, buildJsonifyText, buildKeyViolationCount, buildPartitionedSelect, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, fromSourceSql, geoWindowFromControls, jsonDollarPath, orFragment, orderByList, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlStringLiteral, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, unquoteSqlStringLiteral, viewReadSource, writeLimitWhere } from "@atscript/db-sql-tools";
|
|
5
5
|
import { bucketer } from "@uniqu/core";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
//#region src/better-sqlite3-driver.ts
|
|
@@ -309,6 +309,7 @@ const sqliteDialect = {
|
|
|
309
309
|
return `"${esc(name)}"`;
|
|
310
310
|
},
|
|
311
311
|
unlimitedLimit: "-1",
|
|
312
|
+
stringLiteral: sqlStringLiteral,
|
|
312
313
|
toValue: toSqlValue,
|
|
313
314
|
toParam(value) {
|
|
314
315
|
if (value === void 0) return null;
|
|
@@ -800,6 +801,21 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
800
801
|
supportsNullsPlacement() {
|
|
801
802
|
return true;
|
|
802
803
|
}
|
|
804
|
+
/**
|
|
805
|
+
* Locking reads are accepted as a no-op (since 0.1.162): every transaction
|
|
806
|
+
* starts with `BEGIN IMMEDIATE`, which holds the database write lock, so
|
|
807
|
+
* reads inside it are current and no other writer can run until it ends.
|
|
808
|
+
*/
|
|
809
|
+
supportsReadLocks() {
|
|
810
|
+
return true;
|
|
811
|
+
}
|
|
812
|
+
/** Every level — a `BEGIN IMMEDIATE` transaction is serializable. @since 0.1.162 */
|
|
813
|
+
isolationLevels() {
|
|
814
|
+
return ALL_ISOLATION_LEVELS;
|
|
815
|
+
}
|
|
816
|
+
_inherentIsolation() {
|
|
817
|
+
return "serializable";
|
|
818
|
+
}
|
|
803
819
|
/** Computed view columns and first-row joins. */
|
|
804
820
|
viewCapabilities() {
|
|
805
821
|
return ALL_VIEW_CAPABILITIES;
|
|
@@ -1152,8 +1168,25 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1152
1168
|
modifiedCount: result.changes
|
|
1153
1169
|
};
|
|
1154
1170
|
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Bounded writes (since 0.1.162) through an ordered, limited rowid subquery
|
|
1173
|
+
* (`rowid IN (SELECT rowid … ORDER BY … LIMIT n)`) — no
|
|
1174
|
+
* `SQLITE_ENABLE_UPDATE_DELETE_LIMIT` build needed.
|
|
1175
|
+
*/
|
|
1176
|
+
supportsWriteLimit() {
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
/** One writer at a time: the rowid pick and the write run as one statement, never interleaved. */
|
|
1180
|
+
writeLimitIsAtomic() {
|
|
1181
|
+
return true;
|
|
1182
|
+
}
|
|
1183
|
+
/** `where` narrowed to a bounded write's rows, or `where` itself when unbounded. */
|
|
1184
|
+
_boundedWhere(where, bound) {
|
|
1185
|
+
if (!bound) return where;
|
|
1186
|
+
return writeLimitWhere(sqliteDialect, `"${esc(this.resolveTableName())}"`, ["rowid"], where, bound);
|
|
1187
|
+
}
|
|
1155
1188
|
async updateMany(filter, data, ops, opts) {
|
|
1156
|
-
const where = buildWhere(filter);
|
|
1189
|
+
const where = this._boundedWhere(buildWhere(filter), opts?.limit);
|
|
1157
1190
|
const versionColumn = this._versionColumnFor(opts);
|
|
1158
1191
|
const { sql, params } = buildUpdate$1(this.resolveTableName(), data, where, ops, versionColumn);
|
|
1159
1192
|
this._log(sql, params);
|
|
@@ -1167,10 +1200,10 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1167
1200
|
const where = buildWhere(filter);
|
|
1168
1201
|
const tableName = this.resolveTableName();
|
|
1169
1202
|
const versionColumn = this._table.versionColumnPhysical;
|
|
1170
|
-
const { sql, params } = buildUpdate$1(tableName, fillReplacePayload(data, replaceColumnsFor(this._table.fieldDescriptors, this.nativeDefaultFns()), versionColumn), {
|
|
1203
|
+
const { sql, params } = buildUpdate$1(tableName, fillReplacePayload(data, replaceColumnsFor(this._table.fieldDescriptors, this.nativeDefaultFns()), versionColumn, this._table.onUpdateIncPhysical), {
|
|
1171
1204
|
sql: `rowid = (SELECT rowid FROM "${esc(tableName)}" WHERE ${where.sql} LIMIT 1)`,
|
|
1172
1205
|
params: where.params
|
|
1173
|
-
},
|
|
1206
|
+
}, this._onUpdateIncOps(), versionColumn, expectedVersion);
|
|
1174
1207
|
this._log(sql, params);
|
|
1175
1208
|
const result = await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)));
|
|
1176
1209
|
return {
|
|
@@ -1181,7 +1214,7 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1181
1214
|
async replaceMany(filter, data) {
|
|
1182
1215
|
const where = buildWhere(filter);
|
|
1183
1216
|
const versionColumn = this._table.versionColumnPhysical;
|
|
1184
|
-
const { sql, params } = buildUpdate$1(this.resolveTableName(), data, where,
|
|
1217
|
+
const { sql, params } = buildUpdate$1(this.resolveTableName(), data, where, this._onUpdateIncOps(), versionColumn);
|
|
1185
1218
|
this._log(sql, params);
|
|
1186
1219
|
const result = await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)));
|
|
1187
1220
|
return {
|
|
@@ -1196,8 +1229,8 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1196
1229
|
this._log(sql, where.params);
|
|
1197
1230
|
return { deletedCount: (await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, where.params)))).changes };
|
|
1198
1231
|
}
|
|
1199
|
-
async deleteMany(filter) {
|
|
1200
|
-
const where = buildWhere(filter);
|
|
1232
|
+
async deleteMany(filter, opts) {
|
|
1233
|
+
const where = this._boundedWhere(buildWhere(filter), opts?.limit);
|
|
1201
1234
|
const { sql, params } = buildDelete$1(this.resolveTableName(), where);
|
|
1202
1235
|
this._log(sql, params);
|
|
1203
1236
|
return { deletedCount: (await this._stmt(() => this._wrapConstraintError(() => this.driver.run(sql, params)))).changes };
|
|
@@ -1493,30 +1526,33 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1493
1526
|
});
|
|
1494
1527
|
}
|
|
1495
1528
|
async syncIndexes() {
|
|
1496
|
-
return this._withExclusiveConnection(
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1529
|
+
return this._withExclusiveConnection(() => this._syncIndexes(false));
|
|
1530
|
+
}
|
|
1531
|
+
async _syncIndexes(dryRun) {
|
|
1532
|
+
const tableName = this.resolveTableName();
|
|
1533
|
+
const changes = await this.syncIndexesWithDiff({
|
|
1534
|
+
dryRun,
|
|
1535
|
+
listExisting: async () => this.driver.all(`PRAGMA index_list("${esc(tableName)}")`).filter((i) => !i.name.startsWith("sqlite_")).map((i) => ({
|
|
1536
|
+
name: i.name,
|
|
1537
|
+
columns: this.driver.all(`PRAGMA index_info("${esc(i.name)}")`).map((c) => c.name).filter((n) => n !== null)
|
|
1538
|
+
})),
|
|
1539
|
+
createIndex: async (index) => {
|
|
1540
|
+
const unique = index.type === "unique" ? "UNIQUE " : "";
|
|
1541
|
+
const cols = index.fields.map((f) => `"${esc(f.name)}" ${f.sort === "desc" ? "DESC" : "ASC"}`).join(", ");
|
|
1542
|
+
const sql = `CREATE ${unique}INDEX IF NOT EXISTS "${esc(index.key)}" ON "${esc(tableName)}" (${cols})`;
|
|
1543
|
+
this._log(sql);
|
|
1544
|
+
this.driver.exec(sql);
|
|
1545
|
+
},
|
|
1546
|
+
dropIndex: async (name) => {
|
|
1547
|
+
const sql = `DROP INDEX IF EXISTS "${esc(name)}"`;
|
|
1548
|
+
this._log(sql);
|
|
1549
|
+
this.driver.exec(sql);
|
|
1550
|
+
},
|
|
1551
|
+
skipIndex: (index) => index.type === "fulltext" || index.type === "geo" ? null : void 0
|
|
1519
1552
|
});
|
|
1553
|
+
changes.push(...await this._syncFtsIndexes(tableName, dryRun));
|
|
1554
|
+
changes.push(...await this._syncVecIndexes(tableName, dryRun));
|
|
1555
|
+
return changes;
|
|
1520
1556
|
}
|
|
1521
1557
|
getSearchIndexes() {
|
|
1522
1558
|
const indexes = [];
|
|
@@ -1685,20 +1721,31 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1685
1721
|
/**
|
|
1686
1722
|
* Creates/drops FTS5 virtual tables and sync triggers to match desired fulltext indexes.
|
|
1687
1723
|
*/
|
|
1688
|
-
_syncFtsIndexes(tableName) {
|
|
1724
|
+
async _syncFtsIndexes(tableName, dryRun) {
|
|
1725
|
+
const { changes, apply } = createChangeRecorder(dryRun);
|
|
1689
1726
|
const ftIndexes = this._getFulltextIndexes().filter((idx) => splitFulltextFields(idx).text.length > 0);
|
|
1690
1727
|
const desiredFtsTables = new Set(ftIndexes.map((idx) => this._ftsTableName(idx.name)));
|
|
1691
|
-
const existingFts = this.
|
|
1692
|
-
for (const name of existingFts) if (!desiredFtsTables.has(name))
|
|
1728
|
+
const existingFts = this._listShadowTables(tableName, "fts");
|
|
1729
|
+
for (const name of existingFts) if (!desiredFtsTables.has(name)) await apply({
|
|
1730
|
+
name,
|
|
1731
|
+
action: "drop"
|
|
1732
|
+
}, name, () => this._dropFtsTable(name));
|
|
1693
1733
|
const existingSet = new Set(existingFts);
|
|
1694
1734
|
for (const index of ftIndexes) {
|
|
1695
1735
|
const ftsTable = this._ftsTableName(index.name);
|
|
1696
|
-
if (!existingSet.has(ftsTable))
|
|
1697
|
-
|
|
1736
|
+
if (!existingSet.has(ftsTable)) await apply({
|
|
1737
|
+
name: ftsTable,
|
|
1738
|
+
action: "add"
|
|
1739
|
+
}, ftsTable, () => this._createFtsTable(tableName, ftsTable, index));
|
|
1740
|
+
else if (!this._ftsColumnsMatch(ftsTable, index)) await apply({
|
|
1741
|
+
name: ftsTable,
|
|
1742
|
+
action: "rebuild"
|
|
1743
|
+
}, ftsTable, () => {
|
|
1698
1744
|
this._dropFtsTable(ftsTable);
|
|
1699
1745
|
this._createFtsTable(tableName, ftsTable, index);
|
|
1700
|
-
}
|
|
1746
|
+
});
|
|
1701
1747
|
}
|
|
1748
|
+
return changes;
|
|
1702
1749
|
}
|
|
1703
1750
|
/** Whether an existing FTS5 table has exactly the index's text columns, in order. */
|
|
1704
1751
|
_ftsColumnsMatch(ftsTable, index) {
|
|
@@ -1929,21 +1976,29 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
|
|
|
1929
1976
|
/**
|
|
1930
1977
|
* Creates/drops vec0 virtual shadow tables and sync triggers to match desired vector fields.
|
|
1931
1978
|
*/
|
|
1932
|
-
_syncVecIndexes(tableName) {
|
|
1933
|
-
|
|
1979
|
+
async _syncVecIndexes(tableName, dryRun) {
|
|
1980
|
+
const { changes, apply } = createChangeRecorder(dryRun);
|
|
1981
|
+
if (this._vectorFields.size === 0) return changes;
|
|
1934
1982
|
if (!this._detectVectorSupport()) {
|
|
1935
1983
|
this._log("[atscript-db-sqlite] sqlite-vec not available, skipping vec0 shadow table sync (vector fields stored as JSON)");
|
|
1936
|
-
return;
|
|
1984
|
+
return changes;
|
|
1937
1985
|
}
|
|
1938
1986
|
const desiredVecTables = /* @__PURE__ */ new Map();
|
|
1939
1987
|
for (const [fieldPath, meta] of this._vectorFields.entries()) desiredVecTables.set(this._vecTableName(meta.indexName), {
|
|
1940
1988
|
field: fieldPath,
|
|
1941
1989
|
meta
|
|
1942
1990
|
});
|
|
1943
|
-
const existingVec = this.
|
|
1944
|
-
for (const name of existingVec) if (!desiredVecTables.has(name))
|
|
1991
|
+
const existingVec = this._listShadowTables(tableName, "vec");
|
|
1992
|
+
for (const name of existingVec) if (!desiredVecTables.has(name)) await apply({
|
|
1993
|
+
name,
|
|
1994
|
+
action: "drop"
|
|
1995
|
+
}, name, () => this._dropVecTable(name));
|
|
1945
1996
|
const existingSet = new Set(existingVec);
|
|
1946
|
-
for (const [vecTable, { field, meta }] of desiredVecTables.entries()) if (!existingSet.has(vecTable))
|
|
1997
|
+
for (const [vecTable, { field, meta }] of desiredVecTables.entries()) if (!existingSet.has(vecTable)) await apply({
|
|
1998
|
+
name: vecTable,
|
|
1999
|
+
action: "add"
|
|
2000
|
+
}, vecTable, () => this._createVecTable(tableName, vecTable, field, meta));
|
|
2001
|
+
return changes;
|
|
1947
2002
|
}
|
|
1948
2003
|
/** Creates a vec0 virtual shadow table with sync triggers and seeds it from existing rows. */
|
|
1949
2004
|
_createVecTable(tableName, vecTable, field, vec) {
|
|
@@ -2033,8 +2088,7 @@ function andWhere(left, right) {
|
|
|
2033
2088
|
* PRAGMA returns `'active'` (SQL-quoted), we store `active` (raw). */
|
|
2034
2089
|
function normalizeSqliteDefault(value) {
|
|
2035
2090
|
if (value === null) return;
|
|
2036
|
-
|
|
2037
|
-
return value;
|
|
2091
|
+
return unquoteSqlStringLiteral(value) ?? value;
|
|
2038
2092
|
}
|
|
2039
2093
|
//#endregion
|
|
2040
2094
|
//#region src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db-sqlite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.163",
|
|
4
4
|
"description": "SQLite adapter for @atscript/db with swappable driver support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -36,21 +36,21 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@atscript/core": "^0.1.
|
|
40
|
-
"@atscript/typescript": "^0.1.
|
|
39
|
+
"@atscript/core": "^0.1.109",
|
|
40
|
+
"@atscript/typescript": "^0.1.109",
|
|
41
41
|
"@types/better-sqlite3": "^7.6.13",
|
|
42
42
|
"@uniqu/core": "^0.1.15",
|
|
43
43
|
"better-sqlite3": "^12.6.2",
|
|
44
44
|
"sqlite-vec": "^0.1.9",
|
|
45
|
-
"unplugin-atscript": "^0.1.
|
|
45
|
+
"unplugin-atscript": "^0.1.109"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@atscript/core": "^0.1.
|
|
49
|
-
"@atscript/typescript": "^0.1.
|
|
48
|
+
"@atscript/core": "^0.1.109",
|
|
49
|
+
"@atscript/typescript": "^0.1.109",
|
|
50
50
|
"@uniqu/core": "^0.1.15",
|
|
51
51
|
"better-sqlite3": ">=11.0.0",
|
|
52
|
-
"@atscript/db
|
|
53
|
-
"@atscript/db": "^0.1.
|
|
52
|
+
"@atscript/db": "^0.1.163",
|
|
53
|
+
"@atscript/db-sql-tools": "^0.1.163"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
56
|
"better-sqlite3": {
|