@zukhruf/sqlite-drift 0.3.30 → 0.3.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,9 +26,12 @@ using database = new DatabaseSync(join(scratch.path, 'app.sqlite'));
26
26
  database.exec(`CREATE TABLE failures (directory TEXT PRIMARY KEY, error TEXT NOT NULL);
27
27
  INSERT INTO failures VALUES ('/data/notes', 'denied')`);
28
28
 
29
- const failures = new Declaration([
30
- 'CREATE TABLE failures (directory TEXT PRIMARY KEY, error TEXT NOT NULL, failed_at TEXT NOT NULL)',
31
- ]);
29
+ const failures = new Declaration(
30
+ [
31
+ 'CREATE TABLE failures (directory TEXT PRIMARY KEY, error TEXT NOT NULL, failed_at TEXT NOT NULL)',
32
+ ],
33
+ { rows: 'replace' },
34
+ );
32
35
  console.log(failures.drift(database));
33
36
  failures.apply(database);
34
37
  console.log(failures.drift(database));
@@ -45,7 +48,8 @@ fits
45
48
 
46
49
  ## A declaration compares the text that SQLite stores
47
50
 
48
- - `new Declaration(statements)` makes the objects once in an empty database in memory, and keeps the text that SQLite stores for each one. [ADR 0001](./docs/adr/0001-compare-the-text-that-sqlite-stores.md) tells why.
51
+ - `new Declaration(statements, { rows })` makes the objects once in an empty database in memory, and keeps the text that SQLite stores for each one. [ADR 0001](./docs/adr/0001-compare-the-text-that-sqlite-stores.md) tells why.
52
+ - `rows` is `'replace'` or `'keep'`. It tells `apply` what to do with the rows of a stale table. It has no default, so no caller loses rows because it forgot an option.
49
53
  - `drift(database)` gives `missing` when the database stores none of the objects, `fits` when it stores each one as declared, and `stale` for all other cases. It only reads, so it also works on a database opened read-only.
50
54
  - Each change to a CREATE statement is drift: a column, a type, a CHECK, STRICT, the query of a view.
51
55
  - A change of meaning with no change of text is not drift. When the meaning of a column changes, change its name too.
@@ -55,39 +59,103 @@ fits
55
59
 
56
60
  - `apply(database)` does nothing when the drift is `fits`.
57
61
  - When no stored object is stale, `apply` makes each missing object, and the other objects keep their rows.
58
- - When one stored object is stale, `apply` replaces every object of the declaration, and their rows are gone. [ADR 0002](./docs/adr/0002-a-stale-object-replaces-the-whole-declaration.md) tells why.
62
+ - With `rows: 'replace'`, when one stored object is stale, `apply` replaces every object of the declaration, and their rows are gone. [ADR 0002](./docs/adr/0002-a-stale-object-replaces-the-whole-declaration.md) tells why.
63
+ - With `rows: 'keep'`, `apply` rebuilds each stale table and keeps its rows. See [Keep the rows](#keep-the-rows).
59
64
  - `apply` does not drop an object that the declaration does not name.
60
- - In a transaction of the caller, `apply` works in a savepoint, and a rollback of the caller removes its changes. With no transaction, `apply` writes in its own `BEGIN IMMEDIATE` transaction.
61
- - A caller that must keep the rows of a stale table asks `drift`, and changes the table itself.
65
+ - In a transaction of the caller, `apply` works in a savepoint, and a rollback of the caller removes its changes. With no transaction, `apply` writes in its own `BEGIN IMMEDIATE` transaction. [`@zukhruf/sqlite-transaction`](../transaction) does this work, so when SQLite ends the transaction itself, `apply` throws the original error.
66
+
67
+ ## Keep the rows
68
+
69
+ With `rows: 'keep'`, `apply` keeps the rows of each stale table. It replaces a stale index, trigger or view, because these have no rows. It rebuilds each stale table, in the order of the declaration:
70
+
71
+ 1. It renames the stored table to a temporary name, with `PRAGMA legacy_alter_table` on. Thus the references of other tables, views and triggers stay on the name of the table.
72
+ 2. It makes the table from its declared text, so SQLite stores the declared text.
73
+ 3. It copies the columns that both tables have, by name. SQLite takes names that are different only in ASCII case as one name.
74
+ 4. It drops the old table, and makes again the indexes and triggers on the table that the declaration does not name.
75
+ 5. It runs `PRAGMA foreign_key_check`. When a kept row breaks a foreign key, `apply` fails.
76
+
77
+ [ADR 0003](./docs/adr/0003-keep-rows-rebuilds-a-table-and-keeps-its-references.md) tells why.
78
+
79
+ ```ts
80
+ import { mkdtempDisposable } from 'node:fs/promises';
81
+ import { tmpdir } from 'node:os';
82
+ import { join } from 'node:path';
83
+ import { DatabaseSync } from 'node:sqlite';
84
+
85
+ import { Declaration } from '@zukhruf/sqlite-drift';
86
+
87
+ await using scratch = await mkdtempDisposable(join(tmpdir(), 'drift-'));
88
+ using database = new DatabaseSync(join(scratch.path, 'app.sqlite'));
89
+ // An earlier version made runs without status. Cases refer to runs.
90
+ database.exec(`CREATE TABLE runs (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
91
+ CREATE TABLE cases (run INTEGER NOT NULL REFERENCES runs (id) ON DELETE CASCADE);
92
+ INSERT INTO runs VALUES (1, 'nightly');
93
+ INSERT INTO cases VALUES (1)`);
94
+
95
+ const runs = new Declaration(
96
+ [
97
+ "CREATE TABLE runs (id INTEGER PRIMARY KEY, name TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'done')",
98
+ ],
99
+ { rows: 'keep' },
100
+ );
101
+ console.log(runs.drift(database));
102
+ runs.apply(database);
103
+ console.log(runs.drift(database));
104
+ console.log(database.prepare('SELECT * FROM runs').all());
105
+ console.log(database.prepare('SELECT count(*) AS cases FROM cases').get());
106
+ ```
107
+
108
+ Output:
109
+
110
+ ```
111
+ stale
112
+ fits
113
+ [ [Object: null prototype] { id: 1, name: 'nightly', status: 'done' } ]
114
+ [Object: null prototype] { cases: 1 }
115
+ ```
116
+
117
+ - A column that only the declaration has gets its default.
118
+ - A column that only the stored table has is discarded, with its values.
119
+ - `apply` does not find a renamed column. A new name reads as one column dropped and one column added, so the values of the old column are discarded. To keep them, copy them yourself before `apply`.
120
+ - `apply` does not fill values and does not remove rows. When a stored row does not fit the declaration (NOT NULL, CHECK, a foreign key, STRICT), `apply` fails with the error of SQLite, and the table and its rows stay as they were. To keep such rows, change them with your own SQL before `apply`.
121
+ - When foreign keys are on and a table refers to a stale table (also the stale table to itself), `apply` must turn foreign keys off. SQLite ignores `PRAGMA foreign_keys` in a transaction. Thus `apply` turns foreign keys off before its own transaction, and on again after it. In a transaction of the caller, `apply` fails before it changes the database. Call `apply` outside a transaction, or turn foreign keys off before it.
122
+ - When no table refers to the stale table, `apply` also works in a transaction of the caller, with foreign keys on.
123
+ - After a rebuild, `PRAGMA legacy_alter_table` has its old value again, also when `apply` fails.
62
124
 
63
125
  ## Write a declaration
64
126
 
65
127
  - List a table before the tables that refer to it.
66
128
  - A declaration must stand alone in an empty database. Do not declare a trigger or an index on a table that the declaration does not name, and do not use a function that only your connection registers.
67
- - Give each table its own declaration when it must keep its rows while another table changes.
129
+ - With `rows: 'replace'`, give each table its own declaration when it must keep its rows while another table changes.
68
130
 
69
131
  ## Errors
70
132
 
71
- | Error | When |
72
- | ------------------------ | ------------------------------------------------------------------------------------- |
73
- | The error of SQLite | `new Declaration` fails when a statement does not run in an empty database. |
74
- | `database is locked` | `apply` with no transaction waits for the busy timeout of the connection, then fails. |
75
- | The error of a statement | `apply` fails, and the database stays as it was. |
133
+ | Error | When |
134
+ | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
135
+ | The error of SQLite | `new Declaration` fails when a statement does not run in an empty database. |
136
+ | `database is locked` | `apply` with no transaction waits for the busy timeout of the connection, then fails. |
137
+ | The error of a statement | `apply` fails, and the database stays as it was. |
138
+ | `Keeping the rows of a table that other tables reference needs foreign keys off, …` | `rows: 'keep'`, in a transaction of the caller, with foreign keys on, and another table refers to a stale table. Nothing changes. |
139
+ | The error of SQLite, for example `NOT NULL constraint failed: runs.name` | `rows: 'keep'`, and a stored row does not fit the declared table. The table and its rows stay as they were. |
140
+ | `The kept rows break a foreign key: …` | `rows: 'keep'`, and `PRAGMA foreign_key_check` finds a kept row that refers to no row. The database stays as it was. |
76
141
 
77
142
  ## The same concepts in other systems
78
143
 
79
- | System | What it does |
80
- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
81
- | Röthlisberger's SQLite migrator | It makes the declaration in memory and compares `sqlite_schema`. It changes a stale table with the 12 steps of SQLite and keeps the rows. |
82
- | Airbyte destinations | Each sync compares the final table with the stream (`existingSchemaMatchesStreamConfig`), and a soft reset makes a stale table again. |
83
- | Drizzle Kit `push`, Prisma `db push` | They compare a declaration in TypeScript or in the Prisma language with the database, and change the database. |
84
- | Android Room | It keeps a version number for migrations, and a hash of the declaration that finds a number that a person forgot to raise. |
85
- | Kubernetes controllers | Each loop compares the desired state with the state that exists, and changes what is different. |
144
+ | System | What it does |
145
+ | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
146
+ | Röthlisberger's SQLite migrator | It makes the declaration in memory and compares `sqlite_schema`. It changes a stale table with the 12 steps of SQLite and keeps the rows. |
147
+ | SQLite's 12 steps | "Making Other Kinds Of Table Schema Changes" in [the ALTER TABLE page](https://www.sqlite.org/lang_altertable.html): make a new table, copy the rows, drop the old table, rename the new one. `rows: 'keep'` renames the old table first instead. ADR 0003 tells why. |
148
+ | sqlite-utils `table.transform()` | It rebuilds a table with the 12 steps and keeps the rows. A caller gives a map of renamed columns. `rows: 'keep'` has no such map. |
149
+ | Airbyte destinations | Each sync compares the final table with the stream (`existingSchemaMatchesStreamConfig`), and a soft reset makes a stale table again. |
150
+ | Drizzle Kit `push`, Prisma `db push` | They compare a declaration in TypeScript or in the Prisma language with the database, and change the database. |
151
+ | Android Room | It keeps a version number for migrations, and a hash of the declaration that finds a number that a person forgot to raise. |
152
+ | Kubernetes controllers | Each loop compares the desired state with the state that exists, and changes what is different. |
86
153
 
87
154
  ## Documentation
88
155
 
89
156
  - [0001 Compare the text that SQLite stores](./docs/adr/0001-compare-the-text-that-sqlite-stores.md)
90
157
  - [0002 A stale object replaces the whole declaration](./docs/adr/0002-a-stale-object-replaces-the-whole-declaration.md)
158
+ - [0003 Keep rows rebuilds a table and keeps its references](./docs/adr/0003-keep-rows-rebuilds-a-table-and-keeps-its-references.md)
91
159
 
92
160
  ## Development
93
161
 
@@ -1,8 +1,11 @@
1
1
  import { DatabaseSync } from 'node:sqlite';
2
2
  export type Drift = 'missing' | 'stale' | 'fits';
3
+ export type Rows = 'replace' | 'keep';
3
4
  export declare class Declaration {
4
5
  #private;
5
- constructor(statements: readonly string[]);
6
+ constructor(statements: readonly string[], options: {
7
+ readonly rows: Rows;
8
+ });
6
9
  drift(database: DatabaseSync): Drift;
7
10
  apply(database: DatabaseSync): void;
8
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../src/declaration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAajD,qBAAa,WAAW;;gBAGV,UAAU,EAAE,SAAS,MAAM,EAAE;IAezC,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK;IAgBpC,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;CAiCpC"}
1
+ {"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../src/declaration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAIjD,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC;AAgBtC,qBAAa,WAAW;;gBAIV,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;KAAE;IAgB3E,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,KAAK;IAkBpC,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI;CAuHpC"}
@@ -1,4 +1,6 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { DatabaseSync } from 'node:sqlite';
3
+ import { transaction } from '@zukhruf/sqlite-transaction';
2
4
  // The tables, indexes, views and triggers a caller owns in a SQLite database,
3
5
  // by the CREATE statements that make them. SQLite keeps the text of each
4
6
  // CREATE in sqlite_schema. A declaration makes its objects once in an empty
@@ -6,7 +8,8 @@ import { DatabaseSync } from 'node:sqlite';
6
8
  // SQLite, and they compare as they are.
7
9
  export class Declaration {
8
10
  #objects;
9
- constructor(statements) {
11
+ #rows;
12
+ constructor(statements, options) {
10
13
  using blank = new DatabaseSync(':memory:');
11
14
  for (const statement of statements)
12
15
  blank.exec(statement);
@@ -18,6 +21,7 @@ export class Declaration {
18
21
  name: String(name),
19
22
  sql: String(sql),
20
23
  }));
24
+ this.#rows = options.rows;
21
25
  }
22
26
  drift(database) {
23
27
  const pairs = this.#objects.map((object) => ({
@@ -31,42 +35,109 @@ export class Declaration {
31
35
  : 'stale';
32
36
  }
33
37
  // Creates the objects the database does not store. When any stored object
34
- // differs from its declaration, replaces every object of the declaration,
35
- // with its rows: a table can refer to another, and SQLite drops a table only
36
- // after nothing refers to its rows. Works inside the caller's transaction,
37
- // or in a write of its own. Objects the declaration does not name stay.
38
+ // differs from its declaration, rows 'replace' replaces every object of the
39
+ // declaration, with its rows: a table can refer to another, and SQLite drops
40
+ // a table only after nothing refers to its rows. Rows 'keep' makes each stale
41
+ // object again, and moves the rows of a stale table into the new one (ADR
42
+ // 0003). Works inside the caller's transaction, or in a write of its own.
43
+ // Objects the declaration does not name stay.
38
44
  apply(database) {
39
45
  if (this.drift(database) === 'fits')
40
46
  return;
41
- const ownsTransaction = !database.isTransaction;
42
- database.exec(ownsTransaction ? 'BEGIN IMMEDIATE' : 'SAVEPOINT sqlite_drift');
47
+ // SQLite ignores PRAGMA foreign_keys in a transaction. With foreign keys
48
+ // on, the rename of a referenced table changes the references to the old
49
+ // table, and its drop then deletes the rows that refer to it.
50
+ const unchecked = this.#rows === 'keep' &&
51
+ Number(database.prepare('PRAGMA foreign_keys').get()?.foreign_keys) ===
52
+ 1 &&
53
+ this.#stale(database).some(({ object, found }) => object.type === 'table' &&
54
+ found.type === 'table' &&
55
+ referenced(database, found.name));
56
+ if (unchecked) {
57
+ if (database.isTransaction)
58
+ throw new Error('Keeping the rows of a table that other tables reference needs foreign keys off, which SQLite cannot change inside a transaction. Call apply outside a transaction, or turn foreign keys off before it.');
59
+ database.exec('PRAGMA foreign_keys = OFF');
60
+ }
43
61
  try {
44
- const stale = this.#objects.some((object) => {
45
- const found = stored(database, object.name);
46
- return found !== undefined && found.sql !== object.sql;
47
- });
48
- if (stale)
49
- for (const object of this.#objects.toReversed()) {
50
- const found = stored(database, object.name);
51
- if (found !== undefined)
52
- database.exec(`DROP ${found.type.toUpperCase()} ${quote(found.name)}`);
53
- }
54
- for (const object of this.#objects)
55
- if (stored(database, object.name) === undefined)
56
- database.exec(object.sql);
57
- database.exec(ownsTransaction ? 'COMMIT' : 'RELEASE sqlite_drift');
62
+ transaction(database, () => {
63
+ const stale = this.#stale(database);
64
+ if (this.#rows === 'keep')
65
+ this.#keep(database, stale);
66
+ else if (stale.length > 0)
67
+ for (const object of this.#objects.toReversed()) {
68
+ const found = stored(database, object.name);
69
+ if (found !== undefined)
70
+ drop(database, found);
71
+ }
72
+ for (const object of this.#objects)
73
+ if (stored(database, object.name) === undefined)
74
+ database.exec(object.sql);
75
+ }, { mode: 'immediate' });
58
76
  }
59
- catch (error) {
60
- if (!ownsTransaction) {
61
- database.exec('ROLLBACK TO sqlite_drift');
62
- database.exec('RELEASE sqlite_drift');
63
- }
64
- else if (database.isTransaction) {
65
- database.exec('ROLLBACK');
66
- }
67
- throw error;
77
+ finally {
78
+ if (unchecked)
79
+ database.exec('PRAGMA foreign_keys = ON');
68
80
  }
69
81
  }
82
+ #stale(database) {
83
+ return this.#objects.flatMap((object) => {
84
+ const found = stored(database, object.name);
85
+ return found !== undefined && found.sql !== object.sql
86
+ ? [{ object, found }]
87
+ : [];
88
+ });
89
+ }
90
+ // Drops each stale index, trigger and view, and rebuilds each stale table.
91
+ // SQLite keeps PRAGMA legacy_alter_table after a rollback, so the old value
92
+ // comes back in any case.
93
+ #keep(database, stale) {
94
+ const tables = stale.filter(({ object, found }) => object.type === 'table' && found.type === 'table');
95
+ for (const entry of stale)
96
+ if (!tables.includes(entry))
97
+ drop(database, entry.found);
98
+ if (tables.length === 0)
99
+ return;
100
+ const legacy = Number(database.prepare('PRAGMA legacy_alter_table').get()?.legacy_alter_table);
101
+ database.exec('PRAGMA legacy_alter_table = ON');
102
+ try {
103
+ for (const { object, found } of tables)
104
+ this.#rebuild(database, object, found);
105
+ }
106
+ finally {
107
+ database.exec(`PRAGMA legacy_alter_table = ${legacy}`);
108
+ }
109
+ const broken = database.prepare('PRAGMA foreign_key_check').get();
110
+ if (broken !== undefined)
111
+ throw new Error(`The kept rows break a foreign key: row ${String(broken.rowid)} of ${String(broken.table)} refers to a row of ${String(broken.parent)} that does not exist.`);
112
+ }
113
+ // Renames the stored table away, makes it from its declared text, and copies
114
+ // the columns that both have, by name. With legacy_alter_table on, the
115
+ // rename leaves the references of other tables, views and triggers to the
116
+ // name. A column only the declaration has gets its default, and a column
117
+ // only the stored table has is discarded. The indexes and triggers on the
118
+ // table go with the old table, so those the declaration does not name are
119
+ // made again here, and the others when apply makes the missing objects.
120
+ #rebuild(database, object, found) {
121
+ const declared = new Set(this.#objects.map(({ name }) => name.toLowerCase()));
122
+ const undeclared = database
123
+ .prepare(`SELECT "name", "sql" FROM sqlite_schema WHERE lower("tbl_name") = lower(?) AND "type" IN ('index', 'trigger') AND "sql" IS NOT NULL`)
124
+ .all(found.name)
125
+ .filter(({ name }) => !declared.has(String(name).toLowerCase()))
126
+ .map(({ sql }) => String(sql));
127
+ const old = `${found.name}_${randomUUID().replaceAll('-', '')}`;
128
+ database.exec(`ALTER TABLE ${quote(found.name)} RENAME TO ${quote(old)}`);
129
+ database.exec(object.sql);
130
+ const columns = new Set(names(database, object.name).map((name) => name.toLowerCase()));
131
+ const shared = names(database, old)
132
+ .filter((name) => columns.has(name.toLowerCase()))
133
+ .map(quote)
134
+ .join(', ');
135
+ if (shared !== '')
136
+ database.exec(`INSERT INTO ${quote(object.name)} (${shared}) SELECT ${shared} FROM ${quote(old)}`);
137
+ database.exec(`DROP TABLE ${quote(old)}`);
138
+ for (const sql of undeclared)
139
+ database.exec(sql);
140
+ }
70
141
  }
71
142
  // SQLite takes names that differ only in ASCII case for one object.
72
143
  function stored(database, name) {
@@ -80,4 +151,19 @@ function stored(database, name) {
80
151
  function quote(name) {
81
152
  return `"${name.replaceAll('"', '""')}"`;
82
153
  }
154
+ function drop(database, object) {
155
+ database.exec(`DROP ${object.type.toUpperCase()} ${quote(object.name)}`);
156
+ }
157
+ function names(database, table) {
158
+ return database
159
+ .prepare('SELECT "name" FROM pragma_table_info(?)')
160
+ .all(table)
161
+ .map(({ name }) => String(name));
162
+ }
163
+ // Whether a table, the same one too, has a foreign key to the table.
164
+ function referenced(database, table) {
165
+ return (database
166
+ .prepare(`SELECT 1 FROM sqlite_schema AS "s", pragma_foreign_key_list("s"."name") AS "f" WHERE "s"."type" = 'table' AND lower("f"."table") = lower(?)`)
167
+ .get(table) !== undefined);
168
+ }
83
169
  //# sourceMappingURL=declaration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"declaration.js","sourceRoot":"","sources":["../src/declaration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"declaration.js","sourceRoot":"","sources":["../src/declaration.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { Declaration, type Drift } from './declaration.ts';
1
+ export { Declaration, type Drift, type Rows } from './declaration.ts';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAyB,MAAM,kBAAkB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zukhruf/sqlite-drift",
3
- "version": "0.3.30",
3
+ "version": "0.3.32",
4
4
  "description": "Declarative schema management for SQLite. A declaration lists the CREATE statements of the tables, indexes, views and triggers that one caller owns. The package compares them with the text that SQLite stores, gives the drift (missing, fits or stale), and makes the database store each object as declared. No person keeps a version number.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,5 +40,8 @@
40
40
  ],
41
41
  "publishConfig": {
42
42
  "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "@zukhruf/sqlite-transaction": "^0.3.32"
43
46
  }
44
47
  }