uql-orm 0.54.0 → 0.56.0
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/README.md +2 -2
- package/dist/browser/uql-browser.min.js +2 -2
- package/dist/browser/uql-browser.min.js.map +4 -4
- package/dist/bunSql/bunSql.util.d.ts +3 -14
- package/dist/bunSql/bunSql.util.js +33 -56
- package/dist/bunSql/bunSqlQuerier.d.ts +3 -6
- package/dist/bunSql/bunSqlQuerier.js +7 -13
- package/dist/bunSql/bunSqlQuerierPool.d.ts +10 -5
- package/dist/bunSql/bunSqlQuerierPool.js +25 -10
- package/dist/cockroachdb/crdbQuerierPool.d.ts +1 -3
- package/dist/cockroachdb/crdbQuerierPool.js +0 -4
- package/dist/cockroachdb/index.d.ts +0 -1
- package/dist/cockroachdb/index.js +0 -1
- package/dist/d1/d1SqliteDialect.d.ts +5 -0
- package/dist/d1/d1SqliteDialect.js +7 -0
- package/dist/dialect/abstractSqlDialect.d.ts +9 -9
- package/dist/dialect/abstractSqlDialect.js +38 -51
- package/dist/dialect/hydrateColumn.js +2 -2
- package/dist/dialect/mergeSqlDialect.d.ts +2 -2
- package/dist/dialect/mergeSqlDialect.js +0 -4
- package/dist/dialect/mysqlLikeSqlDialect.js +2 -3
- package/dist/dialect/pgLikeSqlDialect.d.ts +5 -0
- package/dist/dialect/pgLikeSqlDialect.js +14 -4
- package/dist/dialect/queryJoins.js +2 -4
- package/dist/entity/index.d.ts +1 -1
- package/dist/entity/index.js +1 -1
- package/dist/entity/metadata/definition.d.ts +5 -1
- package/dist/entity/metadata/definition.js +32 -26
- package/dist/libsql/index.d.ts +0 -1
- package/dist/libsql/index.js +0 -1
- package/dist/libsql/libsqlQuerierPool.d.ts +3 -5
- package/dist/libsql/libsqlQuerierPool.js +2 -5
- package/dist/maria/mariadbQuerier.d.ts +0 -3
- package/dist/maria/mariadbQuerier.js +6 -7
- package/dist/maria/mariadbQuerierPool.js +4 -7
- package/dist/migrate/builder/splitSqlStatements.js +2 -2
- package/dist/migrate/cli.js +2 -9
- package/dist/migrate/codegen/fieldOptionsSource.js +1 -1
- package/dist/migrate/ddl/index.d.ts +3 -3
- package/dist/migrate/ddl/index.js +3 -3
- package/dist/migrate/ddl/pgIndexDdl.d.ts +5 -0
- package/dist/migrate/ddl/pgIndexDdl.js +9 -0
- package/dist/migrate/drift/driftDetector.js +21 -8
- package/dist/migrate/generator/mongoSchemaGenerator.js +1 -1
- package/dist/migrate/introspection/baseSqlIntrospector.d.ts +1 -1
- package/dist/migrate/introspection/baseSqlIntrospector.js +65 -76
- package/dist/migrate/introspection/mssqlIntrospector.js +2 -1
- package/dist/migrate/introspection/mysqlIntrospector.js +5 -8
- package/dist/migrate/introspection/sqliteIntrospector.js +2 -5
- package/dist/migrate/migrator.d.ts +5 -2
- package/dist/migrate/migrator.js +9 -14
- package/dist/migrate/schemaGenerator.js +2 -6
- package/dist/mongo/index.d.ts +0 -1
- package/dist/mongo/index.js +0 -1
- package/dist/mongo/mongoDialect.d.ts +1 -2
- package/dist/mongo/mongoDialect.js +7 -21
- package/dist/mongo/mongodbQuerier.js +12 -11
- package/dist/mongo/mongodbQuerierPool.d.ts +2 -2
- package/dist/mongo/mongodbQuerierPool.js +2 -2
- package/dist/mssql/mssqlDialect.d.ts +3 -5
- package/dist/mssql/mssqlDialect.js +9 -8
- package/dist/mssql/mssqlQuerier.d.ts +13 -6
- package/dist/mssql/mssqlQuerier.js +30 -75
- package/dist/mssql/mssqlQuerierPool.js +2 -0
- package/dist/mssql/mssqlWireTypes.d.ts +3 -4
- package/dist/mssql/mssqlWireTypes.js +5 -8
- package/dist/mysql/index.d.ts +0 -1
- package/dist/mysql/index.js +0 -1
- package/dist/mysql/mysql2Querier.d.ts +1 -4
- package/dist/mysql/mysql2Querier.js +0 -3
- package/dist/mysql/mysql2QuerierPool.d.ts +2 -2
- package/dist/mysql/mysql2QuerierPool.js +5 -3
- package/dist/neon/index.d.ts +0 -2
- package/dist/neon/index.js +0 -2
- package/dist/neon/neonQuerierPool.d.ts +2 -4
- package/dist/neon/neonQuerierPool.js +2 -6
- package/dist/pglite/index.d.ts +0 -1
- package/dist/pglite/index.js +0 -1
- package/dist/pglite/pgliteQuerier.d.ts +3 -3
- package/dist/pglite/pgliteQuerier.js +1 -1
- package/dist/pglite/pgliteQuerierPool.d.ts +7 -2
- package/dist/pglite/pgliteQuerierPool.js +16 -6
- package/dist/postgres/abstractPgQuerierPool.d.ts +8 -12
- package/dist/postgres/abstractPgQuerierPool.js +8 -6
- package/dist/postgres/index.d.ts +0 -1
- package/dist/postgres/index.js +0 -1
- package/dist/postgres/pgNumericTypes.d.ts +5 -5
- package/dist/postgres/pgNumericTypes.js +11 -7
- package/dist/postgres/pgQuerier.d.ts +22 -4
- package/dist/postgres/pgQuerier.js +29 -2
- package/dist/postgres/pgQuerierPool.d.ts +2 -4
- package/dist/postgres/pgQuerierPool.js +2 -6
- package/dist/postgres/postgresDialect.d.ts +5 -5
- package/dist/postgres/postgresDialect.js +5 -5
- package/dist/postgres/postgresWireDriverCapabilities.d.ts +2 -2
- package/dist/postgres/postgresWireDriverCapabilities.js +2 -2
- package/dist/querier/abstractPoolQuerier.d.ts +1 -1
- package/dist/querier/abstractPoolQuerier.js +1 -1
- package/dist/querier/abstractQuerier.js +17 -22
- package/dist/querier/abstractSqlQuerier.d.ts +21 -12
- package/dist/querier/abstractSqlQuerier.js +61 -43
- package/dist/schema/canonicalType.js +0 -2
- package/dist/schema/dependencyGraph.js +2 -4
- package/dist/schema/indexDifferences.js +2 -2
- package/dist/schema/schemaASTBuilder.js +3 -10
- package/dist/schema/schemaASTDiffer.d.ts +10 -2
- package/dist/schema/schemaASTDiffer.js +12 -11
- package/dist/schema/types.d.ts +1 -1
- package/dist/sqlite/hranaQuerier.d.ts +6 -8
- package/dist/sqlite/hranaQuerier.js +13 -30
- package/dist/sqlite/hranaQuerierPool.d.ts +3 -4
- package/dist/sqlite/hranaQuerierPool.js +2 -1
- package/dist/sqlite/localSqliteQuerierPool.d.ts +3 -3
- package/dist/sqlite/localSqliteQuerierPool.js +4 -2
- package/dist/sqlite/nodeSqliteAdapter.d.ts +0 -1
- package/dist/sqlite/nodeSqliteQuerierPool.js +0 -2
- package/dist/sqlite/sqliteDialect.js +2 -1
- package/dist/sqlite/sqlitePragmas.d.ts +12 -0
- package/dist/sqlite/sqlitePragmas.js +15 -0
- package/dist/sqlite/sqliteQuerierPool.d.ts +0 -5
- package/dist/sqlite/sqliteQuerierPool.js +2 -13
- package/dist/turso/index.d.ts +0 -1
- package/dist/turso/index.js +0 -1
- package/dist/turso/tursoLocalQuerier.d.ts +0 -1
- package/dist/turso/tursoLocalQuerierPool.js +2 -2
- package/dist/turso/tursoQuerierPool.d.ts +1 -3
- package/dist/turso/tursoQuerierPool.js +0 -4
- package/dist/type/dialect.d.ts +1 -1
- package/dist/util/dialect.util.d.ts +8 -2
- package/dist/util/dialect.util.js +20 -1
- package/dist/util/logger.d.ts +17 -9
- package/dist/util/logger.js +36 -11
- package/dist/util/object.util.d.ts +2 -0
- package/dist/util/object.util.js +4 -0
- package/dist/util/raw.js +3 -3
- package/dist/util/relationQuery.util.d.ts +3 -3
- package/dist/util/relationQuery.util.js +8 -2
- package/dist/util/sqlLiteral.js +3 -8
- package/dist/util/string.util.js +2 -6
- package/dist/util/wideNumber.d.ts +14 -0
- package/dist/util/wideNumber.js +24 -0
- package/package.json +1 -1
- package/dist/cockroachdb/crdbQuerier.d.ts +0 -8
- package/dist/cockroachdb/crdbQuerier.js +0 -6
- package/dist/libsql/libsqlQuerier.d.ts +0 -10
- package/dist/libsql/libsqlQuerier.js +0 -10
- package/dist/mongo/mongodbNativeDialect.d.ts +0 -9
- package/dist/mongo/mongodbNativeDialect.js +0 -9
- package/dist/mysql/mysql2Dialect.d.ts +0 -9
- package/dist/mysql/mysql2Dialect.js +0 -9
- package/dist/neon/neonDialect.d.ts +0 -10
- package/dist/neon/neonDialect.js +0 -10
- package/dist/neon/neonQuerier.d.ts +0 -5
- package/dist/neon/neonQuerier.js +0 -3
- package/dist/pglite/pgliteDialect.d.ts +0 -14
- package/dist/pglite/pgliteDialect.js +0 -14
- package/dist/postgres/abstractPgQuerier.d.ts +0 -24
- package/dist/postgres/abstractPgQuerier.js +0 -32
- package/dist/postgres/pgDialect.d.ts +0 -10
- package/dist/postgres/pgDialect.js +0 -10
- package/dist/turso/tursoQuerier.d.ts +0 -10
- package/dist/turso/tursoQuerier.js +0 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { COUNT_ALIAS, TOTAL_ALIAS } from '../dialect/aliases.js';
|
|
2
2
|
import { decodeColumn } from '../dialect/hydrateColumn.js';
|
|
3
3
|
import { getMeta, idOf, namesKey } from '../entity/index.js';
|
|
4
|
-
import { buildUpdateResult, cascadesOnDelete, clone, getInsertFieldKeys, insertShapeOf, getRelationRequestSummary,
|
|
4
|
+
import { buildUpdateResult, cascadesOnDelete, clone, getInsertFieldKeys, insertShapeOf, getRelationRequestSummary, idOnlyQuery, isAutoIncrement, isPagedQuery, obtainAttrsPaths, throwNoPendingTransaction, throwPendingTransaction, unflatObject, unflatObjects, whereIds, withoutSoftDeleteFilter, } from '../util/index.js';
|
|
5
5
|
import { AbstractQuerier } from './abstractQuerier.js';
|
|
6
6
|
import { enrichError } from './queryError.js';
|
|
7
7
|
/**
|
|
@@ -223,8 +223,11 @@ export class AbstractSqlQuerier extends AbstractQuerier {
|
|
|
223
223
|
return this.all(ctx.sql, ctx.values);
|
|
224
224
|
}
|
|
225
225
|
async hydrateRows(entity, q, rows) {
|
|
226
|
-
const founds = unflatObjects(rows)
|
|
227
|
-
|
|
226
|
+
const founds = unflatObjects(rows);
|
|
227
|
+
this.hydrateAll(entity, founds);
|
|
228
|
+
if (q.$populate) {
|
|
229
|
+
await this.fillToManyRelations(entity, founds, q.$populate);
|
|
230
|
+
}
|
|
228
231
|
return founds;
|
|
229
232
|
}
|
|
230
233
|
async *internalFindManyStream(entity, q, opts) {
|
|
@@ -241,18 +244,22 @@ export class AbstractSqlQuerier extends AbstractQuerier {
|
|
|
241
244
|
// The one path that does not go through `all`/`run`, so it connects on its own: streaming first on
|
|
242
245
|
// a freshly acquired querier used to reach `getConn()` with nothing acquired.
|
|
243
246
|
await this.lazyConnect();
|
|
247
|
+
// No `normalizeValues` here, unlike `all`/`run`: those also take raw SQL, while every value a
|
|
248
|
+
// context holds was normalized as it was bound.
|
|
244
249
|
const ctx = this.dialect.createContext();
|
|
245
250
|
this.dialect.find(ctx, entity, q, opts);
|
|
246
|
-
const
|
|
251
|
+
const fields = this.dialect.hydratableFields(entity);
|
|
247
252
|
let attrsPaths;
|
|
248
253
|
try {
|
|
249
|
-
for await (const row of this.internalStream(ctx.sql,
|
|
254
|
+
for await (const row of this.internalStream(ctx.sql, ctx.values)) {
|
|
250
255
|
attrsPaths ??= obtainAttrsPaths(row);
|
|
251
|
-
|
|
256
|
+
const found = unflatObject(row, attrsPaths);
|
|
257
|
+
this.hydrateFields(meta, fields, found);
|
|
258
|
+
yield found;
|
|
252
259
|
}
|
|
253
260
|
}
|
|
254
261
|
catch (err) {
|
|
255
|
-
throw enrichError(err, this.logger, ctx.sql,
|
|
262
|
+
throw enrichError(err, this.logger, ctx.sql, ctx.values);
|
|
256
263
|
}
|
|
257
264
|
}
|
|
258
265
|
/**
|
|
@@ -261,37 +268,38 @@ export class AbstractSqlQuerier extends AbstractQuerier {
|
|
|
261
268
|
* Drivers with native cursor/streaming APIs (SQLite, Pg) should override this.
|
|
262
269
|
*/
|
|
263
270
|
async *internalStream(query, values) {
|
|
264
|
-
|
|
265
|
-
yield* rows;
|
|
271
|
+
yield* await this.internalAll(query, values);
|
|
266
272
|
}
|
|
267
273
|
/**
|
|
268
|
-
* Turn what a driver returned back into the types the entity declares, for
|
|
269
|
-
* populated under
|
|
270
|
-
* `decodeColumn`. Both live with the dialect, because a `sparsevec` is
|
|
271
|
-
*
|
|
272
|
-
* `visited` guards a populated graph that points back at itself, and makes a node two paths reach
|
|
273
|
-
* decode once. Only a relation can lead the walk back somewhere it has been, so an entity that
|
|
274
|
-
* declares none skips the guard rather than allocating a set per row to hold a single object -
|
|
275
|
-
* which cost more than the decoding it guards, on a flat read.
|
|
274
|
+
* Turn what a driver returned back into the types the entity declares, for every row and everything
|
|
275
|
+
* populated under them. Which columns, and as what, is `hydratableFields`, resolved once for all the
|
|
276
|
+
* rows; the per-cell decode is `decodeColumn`. Both live with the dialect, because a `sparsevec` is
|
|
277
|
+
* only sparse on Postgres.
|
|
276
278
|
*/
|
|
277
|
-
|
|
279
|
+
hydrateAll(entity, dtos, visited) {
|
|
280
|
+
const meta = getMeta(entity);
|
|
281
|
+
const fields = this.dialect.hydratableFields(entity);
|
|
282
|
+
for (const dto of dtos) {
|
|
283
|
+
this.hydrateFields(meta, fields, dto, visited);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* One row of {@link hydrateAll}. `visited` guards a populated graph that points back at itself, and
|
|
288
|
+
* makes a node two paths reach decode once. Only a populated relation can lead the walk back, so the
|
|
289
|
+
* guard is created at the first one a row carries: rows that populated nothing never allocate one.
|
|
290
|
+
*/
|
|
291
|
+
hydrateFields(meta, fields, dto, visited) {
|
|
278
292
|
if (!dto || typeof dto !== 'object' || visited?.has(dto)) {
|
|
279
|
-
return
|
|
293
|
+
return;
|
|
280
294
|
}
|
|
281
|
-
|
|
295
|
+
visited?.add(dto);
|
|
282
296
|
const row = dto;
|
|
283
|
-
for (const [key, kind] of
|
|
297
|
+
for (const [key, kind] of fields) {
|
|
284
298
|
const value = row[key];
|
|
285
299
|
if (value != null) {
|
|
286
300
|
row[key] = decodeColumn(value, kind);
|
|
287
301
|
}
|
|
288
302
|
}
|
|
289
|
-
// Allocated only where the walk can continue: an entity declaring no relation cannot lead back
|
|
290
|
-
// to a node already decoded, and the loop below is a no-op for it anyway.
|
|
291
|
-
if (hasKeys(meta.relations)) {
|
|
292
|
-
visited ??= new WeakSet();
|
|
293
|
-
}
|
|
294
|
-
visited?.add(dto);
|
|
295
303
|
// The value is read before the relation's target is resolved: a query that populated nothing
|
|
296
304
|
// still walks every relation the entity declares, and `rel.entity()` is a call per row per
|
|
297
305
|
// relation that only the populated ones need.
|
|
@@ -302,16 +310,14 @@ export class AbstractSqlQuerier extends AbstractQuerier {
|
|
|
302
310
|
const rel = meta.relations[key];
|
|
303
311
|
if (!rel)
|
|
304
312
|
continue;
|
|
313
|
+
visited ??= new WeakSet([dto]);
|
|
305
314
|
const relEntity = rel.entity();
|
|
306
315
|
if (Array.isArray(value)) {
|
|
307
|
-
|
|
308
|
-
this.hydrateFields(relEntity, it, visited);
|
|
309
|
-
}
|
|
316
|
+
this.hydrateAll(relEntity, value, visited);
|
|
310
317
|
continue;
|
|
311
318
|
}
|
|
312
|
-
this.hydrateFields(relEntity, value, visited);
|
|
319
|
+
this.hydrateFields(getMeta(relEntity), this.dialect.hydratableFields(relEntity), value, visited);
|
|
313
320
|
}
|
|
314
|
-
return dto;
|
|
315
321
|
}
|
|
316
322
|
/**
|
|
317
323
|
* Runs a statement whose one row carries a {@link COUNT_ALIAS} column. `Number` because `COUNT(*)` is BIGINT and
|
|
@@ -504,35 +510,47 @@ export class AbstractSqlQuerier extends AbstractQuerier {
|
|
|
504
510
|
throwPendingTransaction();
|
|
505
511
|
}
|
|
506
512
|
await this.lazyConnect();
|
|
507
|
-
|
|
508
|
-
await this.runTransactionCommand(sql);
|
|
509
|
-
}
|
|
513
|
+
await this.internalBegin(opts);
|
|
510
514
|
this.hasPendingTransaction = true;
|
|
511
515
|
});
|
|
512
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Only an end that succeeded ends the transaction. A `COMMIT` that fails can leave it open (SQLite
|
|
519
|
+
* answers `SQLITE_BUSY` and keeps it), so the flag has to stay set for the `catch` in
|
|
520
|
+
* {@link AbstractQuerier.transaction} or {@link AbstractQuerier.release} to roll it back.
|
|
521
|
+
*/
|
|
513
522
|
async commitTransaction() {
|
|
514
523
|
return this.serialize(async () => {
|
|
515
524
|
if (!this.hasPendingTransaction) {
|
|
516
525
|
throwNoPendingTransaction();
|
|
517
526
|
}
|
|
518
|
-
await this.
|
|
527
|
+
await this.internalCommit();
|
|
528
|
+
this.hasPendingTransaction = false;
|
|
519
529
|
});
|
|
520
530
|
}
|
|
521
531
|
async rollbackTransaction() {
|
|
522
532
|
return this.serialize(async () => {
|
|
523
533
|
if (this.hasPendingTransaction) {
|
|
524
|
-
await this.
|
|
534
|
+
await this.internalRollback();
|
|
535
|
+
this.hasPendingTransaction = false;
|
|
525
536
|
}
|
|
526
537
|
});
|
|
527
538
|
}
|
|
528
539
|
/**
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
540
|
+
* How this driver opens, commits and rolls back: the dialect's statements, unless its transactions
|
|
541
|
+
* are objects rather than statements - Hrana's session handle, `mssql`'s `Transaction` - in which
|
|
542
|
+
* case it overrides all three. The bookkeeping around them stays above, written once.
|
|
532
543
|
*/
|
|
533
|
-
async
|
|
534
|
-
|
|
535
|
-
|
|
544
|
+
async internalBegin(opts) {
|
|
545
|
+
for (const sql of this.dialect.getBeginTransactionStatements(opts?.isolationLevel)) {
|
|
546
|
+
await this.runTransactionCommand(sql);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
internalCommit() {
|
|
550
|
+
return this.runTransactionCommand(this.dialect.commitTransactionCommand);
|
|
551
|
+
}
|
|
552
|
+
internalRollback() {
|
|
553
|
+
return this.runTransactionCommand(this.dialect.rollbackTransactionCommand);
|
|
536
554
|
}
|
|
537
555
|
/** Transaction statements skip `timed()`, so they attach their own query context to a failure. */
|
|
538
556
|
async runTransactionCommand(sql) {
|
|
@@ -38,11 +38,9 @@ export function findCycles(nodes, dependenciesOf) {
|
|
|
38
38
|
const visited = new Set();
|
|
39
39
|
const onPath = new Set();
|
|
40
40
|
const visit = (node, path) => {
|
|
41
|
+
// A node on the walk was handed down in `path` too, so the cycle closes where it first appears.
|
|
41
42
|
if (onPath.has(node)) {
|
|
42
|
-
|
|
43
|
-
if (start !== -1) {
|
|
44
|
-
cycles.push(path.slice(start));
|
|
45
|
-
}
|
|
43
|
+
cycles.push(path.slice(path.indexOf(node)));
|
|
46
44
|
return;
|
|
47
45
|
}
|
|
48
46
|
if (visited.has(node)) {
|
|
@@ -64,8 +64,8 @@ export function describeIndexDifferences(source, target, facets) {
|
|
|
64
64
|
differences.push(`columns: (${targetColumns}) → (${sourceColumns})`);
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
-
if (
|
|
68
|
-
differences.push(`unique: ${target.unique
|
|
67
|
+
if (source.unique !== target.unique) {
|
|
68
|
+
differences.push(`unique: ${target.unique} → ${source.unique}`);
|
|
69
69
|
}
|
|
70
70
|
if (facets.has('accessMethod') && (source.type ?? 'btree') !== (target.type ?? 'btree')) {
|
|
71
71
|
differences.push(`type: ${target.type ?? 'btree'} → ${source.type ?? 'btree'}`);
|
|
@@ -10,6 +10,7 @@ import { ddlText } from '../util/ddlExpression.util.js';
|
|
|
10
10
|
import { isInlinedExpression } from '../util/field.util.js';
|
|
11
11
|
import { isSoleIdField } from '../util/field.util.js';
|
|
12
12
|
import { isAutoIncrement } from '../util/field.util.js';
|
|
13
|
+
import { definedEntries } from '../util/object.util.js';
|
|
13
14
|
import { derivedForeignKeyName, derivedIndexName, qualifyName } from '../util/sql.util.js';
|
|
14
15
|
import { fieldOptionsToCanonical } from './canonicalType.js';
|
|
15
16
|
import { createTableNode, SchemaAST } from './schemaAST.js';
|
|
@@ -79,11 +80,7 @@ function addTableFromEntity(ctx, meta) {
|
|
|
79
80
|
const { columns, primaryKey } = table;
|
|
80
81
|
table.checks?.push(...(meta.checks ?? []));
|
|
81
82
|
// Add columns from fields
|
|
82
|
-
const
|
|
83
|
-
for (const key of Object.keys(fields)) {
|
|
84
|
-
const field = fields[key];
|
|
85
|
-
if (!field)
|
|
86
|
-
continue;
|
|
83
|
+
for (const [key, field] of definedEntries(meta.fields)) {
|
|
87
84
|
// An inlined expression has no column; a stored one is a column like any other.
|
|
88
85
|
if (isInlinedExpression(field))
|
|
89
86
|
continue;
|
|
@@ -126,11 +123,7 @@ function addRelationshipsFromEntity(ctx, meta) {
|
|
|
126
123
|
const table = tableOf(ctx, meta);
|
|
127
124
|
if (!table)
|
|
128
125
|
return;
|
|
129
|
-
const
|
|
130
|
-
for (const key of Object.keys(relations)) {
|
|
131
|
-
const relation = relations[key];
|
|
132
|
-
if (!relation)
|
|
133
|
-
continue;
|
|
126
|
+
for (const [key, relation] of definedEntries(meta.relations)) {
|
|
134
127
|
const relatedMeta = getMeta(relation.entity());
|
|
135
128
|
const relatedTable = tableOf(ctx, relatedMeta);
|
|
136
129
|
if (!relatedTable)
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { type IndexFacet } from './indexDifferences.js';
|
|
11
11
|
import type { SchemaAST } from './schemaAST.js';
|
|
12
12
|
import type { CanonicalType } from './types.js';
|
|
13
|
-
import type { RelationshipDiff, RelationshipNode, SchemaDiffResult, TableDiff, TableNode } from './types.js';
|
|
13
|
+
import type { ColumnDiff, ForeignKeyAction, IndexDiff, RelationshipDiff, RelationshipNode, SchemaDiffResult, TableDiff, TableNode } from './types.js';
|
|
14
14
|
/**
|
|
15
15
|
* Options for schema diffing.
|
|
16
16
|
*/
|
|
@@ -59,7 +59,10 @@ export declare function diffSchemas(source: SchemaAST, target: SchemaAST, option
|
|
|
59
59
|
* against the one the database reported, then projects the result into a `SchemaDiff`. One
|
|
60
60
|
* comparison serves both, so drift and migrations can no longer disagree about what has changed.
|
|
61
61
|
*/
|
|
62
|
-
export declare function diffTable(source: TableNode, target: TableNode, options?: DiffOptions): TableDiff
|
|
62
|
+
export declare function diffTable(source: TableNode, target: TableNode, options?: DiffOptions): (TableDiff & {
|
|
63
|
+
readonly columnDiffs: ColumnDiff[];
|
|
64
|
+
readonly indexDiffs: IndexDiff[];
|
|
65
|
+
}) | undefined;
|
|
63
66
|
/**
|
|
64
67
|
* Compare two lists of relationships.
|
|
65
68
|
*
|
|
@@ -70,3 +73,8 @@ export declare function diffTable(source: TableNode, target: TableNode, options?
|
|
|
70
73
|
* pairing on names would report every hand-named one as a drop and an add.
|
|
71
74
|
*/
|
|
72
75
|
export declare function diffRelationshipNodes(source: readonly RelationshipNode[], target: readonly RelationshipNode[], opts?: DiffOptions): RelationshipDiff[];
|
|
76
|
+
/** A relationship's `ON DELETE` and `ON UPDATE`, an unstated one read as the action the database applies. */
|
|
77
|
+
export declare function referentialActions(rel: RelationshipNode): {
|
|
78
|
+
readonly onDelete: ForeignKeyAction;
|
|
79
|
+
readonly onUpdate: ForeignKeyAction;
|
|
80
|
+
};
|
|
@@ -61,8 +61,8 @@ export function diffSchemas(source, target, options = {}) {
|
|
|
61
61
|
const tablesToAlter = matched
|
|
62
62
|
.map(([sourceTable, targetTable]) => diffTable(sourceTable, targetTable, opts))
|
|
63
63
|
.filter((tableDiff) => tableDiff !== undefined);
|
|
64
|
-
const columnDiffs = tablesToAlter.flatMap((tableDiff) => tableDiff.columnDiffs
|
|
65
|
-
const indexDiffs = tablesToAlter.flatMap((tableDiff) => tableDiff.indexDiffs
|
|
64
|
+
const columnDiffs = tablesToAlter.flatMap((tableDiff) => tableDiff.columnDiffs);
|
|
65
|
+
const indexDiffs = tablesToAlter.flatMap((tableDiff) => tableDiff.indexDiffs);
|
|
66
66
|
const primaryKeyDiffs = tablesToAlter.flatMap((tableDiff) => tableDiff.primaryKeyDiff ?? []);
|
|
67
67
|
// Relationships span tables, so they are compared over the whole schema rather than per table.
|
|
68
68
|
const relationshipDiffs = opts.compareRelationships
|
|
@@ -265,16 +265,17 @@ export function diffRelationshipNodes(source, target, opts = {}) {
|
|
|
265
265
|
.filter((diff) => diff !== undefined),
|
|
266
266
|
];
|
|
267
267
|
}
|
|
268
|
-
/**
|
|
269
|
-
|
|
270
|
-
|
|
268
|
+
/** A relationship's `ON DELETE` and `ON UPDATE`, an unstated one read as the action the database applies. */
|
|
269
|
+
export function referentialActions(rel) {
|
|
270
|
+
return {
|
|
271
|
+
onDelete: rel.onDelete ?? DEFAULT_FOREIGN_KEY_ACTION,
|
|
272
|
+
onUpdate: rel.onUpdate ?? DEFAULT_FOREIGN_KEY_ACTION,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/** Two relationships over the same columns differ only in what they do when the row they point at goes. */
|
|
271
276
|
function diffRelationship(source, target) {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
const tDelete = target.onDelete ?? DEFAULT_FOREIGN_KEY_ACTION;
|
|
275
|
-
const sUpdate = source.onUpdate ?? DEFAULT_FOREIGN_KEY_ACTION;
|
|
276
|
-
const tUpdate = target.onUpdate ?? DEFAULT_FOREIGN_KEY_ACTION;
|
|
277
|
-
if (sDelete !== tDelete || sUpdate !== tUpdate) {
|
|
277
|
+
const [expected, actual] = [referentialActions(source), referentialActions(target)];
|
|
278
|
+
if (expected.onDelete !== actual.onDelete || expected.onUpdate !== actual.onUpdate) {
|
|
278
279
|
return { ...relationEnds(source), type: 'alter', expected: source, actual: target };
|
|
279
280
|
}
|
|
280
281
|
return undefined;
|
package/dist/schema/types.d.ts
CHANGED
|
@@ -342,7 +342,7 @@ export type DriftSeverity = 'critical' | 'warning' | 'info';
|
|
|
342
342
|
/**
|
|
343
343
|
* Type of schema drift.
|
|
344
344
|
*/
|
|
345
|
-
export type DriftType = 'missing_table' | 'unexpected_table' | 'missing_column' | 'unexpected_column' | 'type_mismatch' | 'constraint_mismatch' | 'missing_index' | 'unexpected_index' | 'index_mismatch' | 'missing_relationship' | 'unexpected_relationship';
|
|
345
|
+
export type DriftType = 'missing_table' | 'unexpected_table' | 'missing_column' | 'unexpected_column' | 'type_mismatch' | 'constraint_mismatch' | 'missing_index' | 'unexpected_index' | 'index_mismatch' | 'missing_relationship' | 'unexpected_relationship' | 'relationship_mismatch';
|
|
346
346
|
/**
|
|
347
347
|
* A single schema drift issue.
|
|
348
348
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtraOptions
|
|
1
|
+
import type { ExtraOptions } from '../type/index.js';
|
|
2
2
|
import { AbstractSqliteQuerier, type SqliteBindValue } from './abstractSqliteQuerier.js';
|
|
3
3
|
import type { SqliteDialect } from './sqliteDialect.js';
|
|
4
4
|
/**
|
|
@@ -46,14 +46,12 @@ export declare class HranaQuerier extends AbstractSqliteQuerier {
|
|
|
46
46
|
constructor(client: HranaClient, dialect: SqliteDialect, extra?: ExtraOptions | undefined, connection?: HranaQuerierConnectionOptions);
|
|
47
47
|
internalAll<T>(query: string, values?: unknown[]): Promise<T[]>;
|
|
48
48
|
internalRun(query: string, values?: unknown[]): Promise<import("../type/query.js").QueryUpdateResult>;
|
|
49
|
-
|
|
50
|
-
beginTransaction(_opts?: TransactionOptions): Promise<void>;
|
|
49
|
+
protected internalBegin(): Promise<void>;
|
|
51
50
|
/**
|
|
52
|
-
* Both drop the handle before the call, not after: one that outlived a failed commit
|
|
53
|
-
*
|
|
54
|
-
* there is nothing open.
|
|
51
|
+
* Both drop the handle before the call, not after: one that outlived a failed commit would carry
|
|
52
|
+
* every later statement into a transaction the server may already have ended.
|
|
55
53
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
protected internalCommit(): Promise<void>;
|
|
55
|
+
protected internalRollback(): Promise<void>;
|
|
58
56
|
internalRelease(): Promise<void>;
|
|
59
57
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { throwNoPendingTransaction, throwPendingTransaction } from '../util/index.js';
|
|
2
1
|
import { AbstractSqliteQuerier } from './abstractSqliteQuerier.js';
|
|
3
2
|
/**
|
|
4
3
|
* Querier for SQLite databases reached through a Hrana client.
|
|
@@ -30,38 +29,22 @@ export class HranaQuerier extends AbstractSqliteQuerier {
|
|
|
30
29
|
// the actual row count when rows were returned.
|
|
31
30
|
return this.buildUpdateResult({ rows, changes: rows.length || res.rowsAffected, id: res.lastInsertRowid });
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
async beginTransaction(_opts) {
|
|
37
|
-
return this.serialize(async () => {
|
|
38
|
-
if (this.tx) {
|
|
39
|
-
throwPendingTransaction();
|
|
40
|
-
}
|
|
41
|
-
this.tx = await this.client.transaction('write');
|
|
42
|
-
});
|
|
32
|
+
async internalBegin() {
|
|
33
|
+
this.tx = await this.client.transaction('write');
|
|
43
34
|
}
|
|
44
35
|
/**
|
|
45
|
-
* Both drop the handle before the call, not after: one that outlived a failed commit
|
|
46
|
-
*
|
|
47
|
-
* there is nothing open.
|
|
36
|
+
* Both drop the handle before the call, not after: one that outlived a failed commit would carry
|
|
37
|
+
* every later statement into a transaction the server may already have ended.
|
|
48
38
|
*/
|
|
49
|
-
async
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
async rollbackTransaction() {
|
|
60
|
-
return this.serialize(async () => {
|
|
61
|
-
const tx = this.tx;
|
|
62
|
-
this.tx = undefined;
|
|
63
|
-
await tx?.rollback();
|
|
64
|
-
});
|
|
39
|
+
async internalCommit() {
|
|
40
|
+
const tx = this.tx;
|
|
41
|
+
this.tx = undefined;
|
|
42
|
+
await tx?.commit();
|
|
43
|
+
}
|
|
44
|
+
async internalRollback() {
|
|
45
|
+
const tx = this.tx;
|
|
46
|
+
this.tx = undefined;
|
|
47
|
+
await tx?.rollback();
|
|
65
48
|
}
|
|
66
49
|
async internalRelease() {
|
|
67
50
|
await super.internalRelease();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type HranaClient, HranaQuerier } from './hranaQuerier.js';
|
|
3
3
|
import type { SqliteDialect } from './sqliteDialect.js';
|
|
4
4
|
/**
|
|
5
5
|
* Pool for SQLite databases reached over the Hrana wire protocol (`@libsql/client`,
|
|
@@ -10,12 +10,11 @@ import type { SqliteDialect } from './sqliteDialect.js';
|
|
|
10
10
|
* constructor, so building a pool never throws when the optional driver peer is absent, which is what
|
|
11
11
|
* lets a Workers bundle construct one at module scope.
|
|
12
12
|
*/
|
|
13
|
-
export declare abstract class AbstractHranaQuerierPool<
|
|
13
|
+
export declare abstract class AbstractHranaQuerierPool<D extends SqliteDialect> extends AbstractSqlQuerierPool<HranaQuerier, D> {
|
|
14
14
|
private client?;
|
|
15
15
|
/** False when the caller injected their own client, in which case they own its lifecycle. */
|
|
16
16
|
protected readonly ownsClient: boolean;
|
|
17
17
|
protected abstract openClient(): Promise<HranaClient>;
|
|
18
|
-
|
|
19
|
-
getQuerier(): Promise<Q>;
|
|
18
|
+
getQuerier(): Promise<HranaQuerier>;
|
|
20
19
|
end(): Promise<void>;
|
|
21
20
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
2
|
+
import { HranaQuerier } from './hranaQuerier.js';
|
|
2
3
|
/**
|
|
3
4
|
* Pool for SQLite databases reached over the Hrana wire protocol (`@libsql/client`,
|
|
4
5
|
* `@tursodatabase/serverless/compat`).
|
|
@@ -14,7 +15,7 @@ export class AbstractHranaQuerierPool extends AbstractSqlQuerierPool {
|
|
|
14
15
|
ownsClient = true;
|
|
15
16
|
async getQuerier() {
|
|
16
17
|
this.client ??= await this.openClient();
|
|
17
|
-
return this.
|
|
18
|
+
return new HranaQuerier(this.client, this.dialect, this.extra);
|
|
18
19
|
}
|
|
19
20
|
async end() {
|
|
20
21
|
if (this.ownsClient) {
|
|
@@ -15,13 +15,13 @@ export type LocalSqlitePoolOptions = {
|
|
|
15
15
|
* Pool for a SQLite database opened in this process, whichever driver provides it. SQLite gives one
|
|
16
16
|
* connection per file, so the shared-handle lifecycle is {@link AbstractSharedHandleQuerierPool}'s.
|
|
17
17
|
*
|
|
18
|
-
* Subclasses supply only {@link createDb}:
|
|
19
|
-
* `better-sqlite3`, `bun:sqlite` and `node:sqlite
|
|
18
|
+
* Subclasses supply only {@link createDb}: configuring the connection on the way up - the pragmas,
|
|
19
|
+
* then the extensions - is the same for `better-sqlite3`, `bun:sqlite` and `node:sqlite`.
|
|
20
20
|
*/
|
|
21
21
|
export declare abstract class AbstractLocalSqliteQuerierPool<O extends LocalSqlitePoolOptions> extends AbstractSharedHandleQuerierPool<SqliteDatabase, SqliteQuerier, SqliteDialect> {
|
|
22
22
|
readonly opts?: O | undefined;
|
|
23
23
|
constructor(opts?: O | undefined, extra?: ExtraOptions);
|
|
24
|
-
/** Opens the driver's database
|
|
24
|
+
/** Opens the driver's database, and nothing more: the caller configures it. */
|
|
25
25
|
protected abstract createDb(): Promise<SqliteDatabase>;
|
|
26
26
|
protected openDb(): Promise<SqliteDatabase>;
|
|
27
27
|
protected buildQuerier(db: SqliteDatabase): SqliteQuerier;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
|
|
2
2
|
import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
|
|
3
3
|
import { SqliteDialect } from './sqliteDialect.js';
|
|
4
|
+
import { applySqlitePragmas } from './sqlitePragmas.js';
|
|
4
5
|
import { SqliteQuerier } from './sqliteQuerier.js';
|
|
5
6
|
/**
|
|
6
7
|
* Pool for a SQLite database opened in this process, whichever driver provides it. SQLite gives one
|
|
7
8
|
* connection per file, so the shared-handle lifecycle is {@link AbstractSharedHandleQuerierPool}'s.
|
|
8
9
|
*
|
|
9
|
-
* Subclasses supply only {@link createDb}:
|
|
10
|
-
* `better-sqlite3`, `bun:sqlite` and `node:sqlite
|
|
10
|
+
* Subclasses supply only {@link createDb}: configuring the connection on the way up - the pragmas,
|
|
11
|
+
* then the extensions - is the same for `better-sqlite3`, `bun:sqlite` and `node:sqlite`.
|
|
11
12
|
*/
|
|
12
13
|
export class AbstractLocalSqliteQuerierPool extends AbstractSharedHandleQuerierPool {
|
|
13
14
|
opts;
|
|
@@ -17,6 +18,7 @@ export class AbstractLocalSqliteQuerierPool extends AbstractSharedHandleQuerierP
|
|
|
17
18
|
}
|
|
18
19
|
async openDb() {
|
|
19
20
|
const db = await this.createDb();
|
|
21
|
+
await applySqlitePragmas(db);
|
|
20
22
|
for (const extension of this.opts?.extensions ?? []) {
|
|
21
23
|
db.loadExtension(extension);
|
|
22
24
|
}
|
|
@@ -23,8 +23,6 @@ export class NodeSqliteQuerierPool extends AbstractLocalSqliteQuerierPool {
|
|
|
23
23
|
// `node:sqlite` refuses `loadExtension` unless the database was opened with this on.
|
|
24
24
|
...(extensions?.length ? { allowExtension: true } : undefined),
|
|
25
25
|
});
|
|
26
|
-
nodeDb.exec('PRAGMA journal_mode = WAL');
|
|
27
|
-
nodeDb.exec('PRAGMA foreign_keys = ON');
|
|
28
26
|
return adaptNodeSqlite(nodeDb);
|
|
29
27
|
}
|
|
30
28
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AbstractSqlDialect } from '../dialect/abstractSqlDialect.js';
|
|
2
2
|
import { JSON_ELEM_ALIAS_PREFIX, JSON_PULL_ALIAS } from '../dialect/aliases.js';
|
|
3
3
|
import { jsonAssignCall, jsonElemExists, jsonPath, jsonRemoveCall, jsonSetTarget } from '../dialect/jsonSql.js';
|
|
4
|
+
import { textSearchFields } from '../util/dialect.util.js';
|
|
4
5
|
export class SqliteDialect extends AbstractSqlDialect {
|
|
5
6
|
/** Default {@link DialectFeatures} for SQLite and SQLite-derived dialects. */
|
|
6
7
|
featureDefaults = {
|
|
@@ -86,7 +87,7 @@ export class SqliteDialect extends AbstractSqlDialect {
|
|
|
86
87
|
* FTS5 virtual table (UQL does not create those; declare it outside your entities).
|
|
87
88
|
*/
|
|
88
89
|
appendTextSearch(ctx, entity, meta, search) {
|
|
89
|
-
const columns = search
|
|
90
|
+
const columns = textSearchFields(meta, search).map((key) => this.escapeId(this.resolveColumnName(key, meta.fields[key])));
|
|
90
91
|
ctx.append(`${this.escapedTableName(meta)} MATCH {${columns.join(' ')}} : `);
|
|
91
92
|
ctx.addValue(search.$value);
|
|
92
93
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SqlitePreparedStatement } from './abstractSqliteQuerier.js';
|
|
2
|
+
/**
|
|
3
|
+
* How every local SQLite connection opens. WAL, so a reader does not wait on the writer, and
|
|
4
|
+
* `foreign_keys`, which SQLite ships off per connection for backward compatibility: without it the
|
|
5
|
+
* constraints uql's own DDL declares are decorative - a declared `onDelete: 'CASCADE'` silently does
|
|
6
|
+
* nothing and a dangling reference is accepted.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SQLITE_PRAGMAS: readonly ['journal_mode = WAL', 'foreign_keys = ON'];
|
|
9
|
+
/** Runs {@link SQLITE_PRAGMAS} through a driver's own statements, whether it answers now or later. */
|
|
10
|
+
export declare function applySqlitePragmas(db: {
|
|
11
|
+
prepare(sql: string): SqlitePreparedStatement | Promise<SqlitePreparedStatement>;
|
|
12
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How every local SQLite connection opens. WAL, so a reader does not wait on the writer, and
|
|
3
|
+
* `foreign_keys`, which SQLite ships off per connection for backward compatibility: without it the
|
|
4
|
+
* constraints uql's own DDL declares are decorative - a declared `onDelete: 'CASCADE'` silently does
|
|
5
|
+
* nothing and a dangling reference is accepted.
|
|
6
|
+
*/
|
|
7
|
+
export const SQLITE_PRAGMAS = ['journal_mode = WAL', 'foreign_keys = ON'];
|
|
8
|
+
/** Runs {@link SQLITE_PRAGMAS} through a driver's own statements, whether it answers now or later. */
|
|
9
|
+
export async function applySqlitePragmas(db) {
|
|
10
|
+
for (const pragma of SQLITE_PRAGMAS) {
|
|
11
|
+
const stmt = await db.prepare(`PRAGMA ${pragma}`);
|
|
12
|
+
// `journal_mode` answers with a row and `foreign_keys` with none; `reader` picks the call for each.
|
|
13
|
+
await (stmt.reader ? stmt.all() : stmt.run());
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -11,10 +11,5 @@ export type Sqlite3PoolOptions = Options & LocalSqlitePoolOptions;
|
|
|
11
11
|
export declare class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool<Sqlite3PoolOptions> {
|
|
12
12
|
readonly filename: string | Buffer;
|
|
13
13
|
constructor(filename?: string | Buffer, opts?: Sqlite3PoolOptions, extra?: ExtraOptions);
|
|
14
|
-
/**
|
|
15
|
-
* SQLite ships with foreign keys unenforced, per connection, for backward compatibility. UQL emits the
|
|
16
|
-
* constraints in its DDL, so leaving them off means a declared `onDelete: 'CASCADE'` silently does
|
|
17
|
-
* nothing and a dangling reference is accepted. Enabled here on every driver, as TypeORM also does.
|
|
18
|
-
*/
|
|
19
14
|
protected createDb(): Promise<SqliteDatabase>;
|
|
20
15
|
}
|
|
@@ -10,11 +10,6 @@ export class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool {
|
|
|
10
10
|
super(opts, extra);
|
|
11
11
|
this.filename = filename;
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
* SQLite ships with foreign keys unenforced, per connection, for backward compatibility. UQL emits the
|
|
15
|
-
* constraints in its DDL, so leaving them off means a declared `onDelete: 'CASCADE'` silently does
|
|
16
|
-
* nothing and a dangling reference is accepted. Enabled here on every driver, as TypeORM also does.
|
|
17
|
-
*/
|
|
18
13
|
async createDb() {
|
|
19
14
|
// `bun:sqlite` rejects option keys it does not know, and rejects an options object carrying no
|
|
20
15
|
// open flags, so `extensions` is stripped out and what remains of it collapses back to nothing.
|
|
@@ -23,15 +18,9 @@ export class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool {
|
|
|
23
18
|
if (typeof Bun !== 'undefined') {
|
|
24
19
|
const { Database: BunDatabase } = await import('bun:sqlite');
|
|
25
20
|
const { adaptBunSqlite } = await import('./bunSqliteAdapter.bun.js');
|
|
26
|
-
|
|
27
|
-
bunDb.run('PRAGMA journal_mode = WAL');
|
|
28
|
-
bunDb.run('PRAGMA foreign_keys = ON');
|
|
29
|
-
return adaptBunSqlite(bunDb);
|
|
21
|
+
return adaptBunSqlite(new BunDatabase(this.filename, opts));
|
|
30
22
|
}
|
|
31
23
|
const { default: BetterSqlite3 } = await import('better-sqlite3');
|
|
32
|
-
|
|
33
|
-
db.pragma('journal_mode = WAL');
|
|
34
|
-
db.pragma('foreign_keys = ON');
|
|
35
|
-
return db;
|
|
24
|
+
return new BetterSqlite3(this.filename, opts);
|
|
36
25
|
}
|
|
37
26
|
}
|
package/dist/turso/index.d.ts
CHANGED
package/dist/turso/index.js
CHANGED