@blackglory/sqlite3-migrations 0.1.0 → 0.2.1
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 +22 -7
- package/lib/migrate.d.ts +6 -1
- package/lib/migrate.js +25 -19
- package/lib/migrate.js.map +1 -1
- package/package.json +24 -22
- package/src/migrate.ts +41 -20
package/README.md
CHANGED
|
@@ -28,15 +28,30 @@ You may need [migration-files].
|
|
|
28
28
|
|
|
29
29
|
### migrate
|
|
30
30
|
```ts
|
|
31
|
-
function migrate(
|
|
31
|
+
function migrate(
|
|
32
|
+
db: Database
|
|
33
|
+
, migrations: IMigration[]
|
|
34
|
+
, options?: {
|
|
35
|
+
targetVersion?: number
|
|
36
|
+
throwOnNewerVersion?: boolean = false
|
|
37
|
+
}
|
|
38
|
+
): Promise<void>
|
|
32
39
|
```
|
|
33
40
|
|
|
34
|
-
If targetVersion is `undefined`,
|
|
41
|
+
If `options.targetVersion` is `undefined`,
|
|
42
|
+
the maximum version of the `migrations` is used.
|
|
35
43
|
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
When the maximum known migration version is less than the `user_version`,
|
|
45
|
+
it means the current instance is outdated.
|
|
46
|
+
- When `options.throwOnNewerVersion` is `false` (default),
|
|
47
|
+
it will skip the migration,
|
|
48
|
+
so your outdated instance continues to run.
|
|
49
|
+
- When `options.throwOnNewerVersion` is `true`,
|
|
50
|
+
it will throw an error,
|
|
51
|
+
so your outdated instance fails immediately.
|
|
52
|
+
|
|
53
|
+
#### Can multiple instances migrate in parallel?
|
|
38
54
|
Yes, the `user_version` update is visible to every database connection.
|
|
39
|
-
When the maximum migration version is less than the `user_version` (which means it is an obsolete instance), it will skip the migration.
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
Each migration uses `BEGIN IMMEDIATE` to ensure that parallel write transactions fail early.
|
|
57
|
+
Therefore, you may need a proper retry strategy.
|
package/lib/migrate.d.ts
CHANGED
|
@@ -4,4 +4,9 @@ export interface IMigration {
|
|
|
4
4
|
up: string | ((db: Database) => PromiseLike<void>);
|
|
5
5
|
down: string | ((db: Database) => PromiseLike<void>);
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
interface IMigrateOptions {
|
|
8
|
+
targetVersion?: number;
|
|
9
|
+
throwOnNewerVersion?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function migrate(db: Database, migrations: IMigration[], { targetVersion, throwOnNewerVersion }?: IMigrateOptions): Promise<void>;
|
|
12
|
+
export {};
|
package/lib/migrate.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
import { assert, isFunction } from '@blackglory/prelude';
|
|
2
2
|
import { promisify } from 'extra-promise';
|
|
3
|
-
|
|
3
|
+
import { max } from 'extra-utils';
|
|
4
|
+
export async function migrate(db, migrations, { targetVersion = getMaximumVersion(migrations), throwOnNewerVersion = false } = {}) {
|
|
4
5
|
const run = promisify(db.run.bind(db));
|
|
5
6
|
const exec = promisify(db.exec.bind(db));
|
|
6
7
|
const get = promisify(db.get.bind(db));
|
|
7
8
|
const maxVersion = getMaximumVersion(migrations);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
while (true) {
|
|
10
|
+
await run('BEGIN IMMEDIATE');
|
|
11
|
+
try {
|
|
11
12
|
const done = await migrate(targetVersion, maxVersion);
|
|
13
|
+
await run('COMMIT');
|
|
12
14
|
if (done)
|
|
13
15
|
break;
|
|
14
16
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
throw e;
|
|
17
|
+
catch (e) {
|
|
18
|
+
await run('ROLLBACK');
|
|
19
|
+
throw e;
|
|
20
|
+
}
|
|
20
21
|
}
|
|
21
22
|
async function migrate(targetVersion, maxVersion) {
|
|
22
23
|
const currentVersion = await getDatabaseVersion();
|
|
23
24
|
if (maxVersion < currentVersion) {
|
|
24
|
-
|
|
25
|
+
if (throwOnNewerVersion) {
|
|
26
|
+
throw new Error(`Database version ${currentVersion} is higher than the maximum known migration version.`);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
25
31
|
}
|
|
26
32
|
else {
|
|
27
33
|
if (currentVersion === targetVersion) {
|
|
@@ -41,7 +47,7 @@ export async function migrate(db, migrations, targetVersion = getMaximumVersion(
|
|
|
41
47
|
const currentVersion = await getDatabaseVersion();
|
|
42
48
|
const targetVersion = currentVersion + 1;
|
|
43
49
|
const migration = migrations.find(x => x.version === targetVersion);
|
|
44
|
-
assert(migration, `Cannot find migration for version ${targetVersion}
|
|
50
|
+
assert(migration, `Cannot find a migration for version ${targetVersion}.`);
|
|
45
51
|
try {
|
|
46
52
|
if (isFunction(migration.up)) {
|
|
47
53
|
await migration.up(db);
|
|
@@ -51,8 +57,7 @@ export async function migrate(db, migrations, targetVersion = getMaximumVersion(
|
|
|
51
57
|
}
|
|
52
58
|
}
|
|
53
59
|
catch (e) {
|
|
54
|
-
|
|
55
|
-
throw e;
|
|
60
|
+
throw new Error(`Upgrade from version ${currentVersion} to version ${targetVersion} failed.`, { cause: e });
|
|
56
61
|
}
|
|
57
62
|
await setDatabaseVersion(targetVersion);
|
|
58
63
|
}
|
|
@@ -60,7 +65,7 @@ export async function migrate(db, migrations, targetVersion = getMaximumVersion(
|
|
|
60
65
|
const currentVersion = await getDatabaseVersion();
|
|
61
66
|
const targetVersion = currentVersion - 1;
|
|
62
67
|
const migration = migrations.find(x => x.version === currentVersion);
|
|
63
|
-
assert(migration, `Cannot find migration for version ${targetVersion}`);
|
|
68
|
+
assert(migration, `Cannot find a migration for version ${targetVersion}`);
|
|
64
69
|
try {
|
|
65
70
|
if (isFunction(migration.down)) {
|
|
66
71
|
await migration.down(db);
|
|
@@ -70,20 +75,21 @@ export async function migrate(db, migrations, targetVersion = getMaximumVersion(
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
catch (e) {
|
|
73
|
-
|
|
74
|
-
throw e;
|
|
78
|
+
throw new Error(`Downgrade from version ${currentVersion} to version ${targetVersion} failed.`, { cause: e });
|
|
75
79
|
}
|
|
76
80
|
await setDatabaseVersion(targetVersion);
|
|
77
81
|
}
|
|
78
82
|
async function getDatabaseVersion() {
|
|
79
|
-
const row = await get('PRAGMA user_version
|
|
80
|
-
return row
|
|
83
|
+
const row = await get('PRAGMA user_version');
|
|
84
|
+
return row['user_version'];
|
|
81
85
|
}
|
|
82
86
|
async function setDatabaseVersion(version) {
|
|
83
87
|
await run(`PRAGMA user_version = ${version}`);
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
function getMaximumVersion(migrations) {
|
|
87
|
-
return migrations
|
|
91
|
+
return migrations
|
|
92
|
+
.map(x => x.version)
|
|
93
|
+
.reduce(max);
|
|
88
94
|
}
|
|
89
95
|
//# sourceMappingURL=migrate.js.map
|
package/lib/migrate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blackglory/sqlite3-migrations",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A utility for database migrations with sqlite3",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"migration",
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"sideEffects": false,
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=22"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"prepare": "ts-patch install -s",
|
|
29
29
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src __tests__",
|
|
30
|
-
"test": "
|
|
30
|
+
"test": "vitest run",
|
|
31
31
|
"prepublishOnly": "run-s prepare clean build",
|
|
32
32
|
"clean": "rimraf lib",
|
|
33
33
|
"build": "tsc --project tsconfig.build.json",
|
|
@@ -40,30 +40,32 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@
|
|
44
|
-
"@commitlint/
|
|
45
|
-
"@
|
|
46
|
-
"@types/
|
|
47
|
-
"@
|
|
48
|
-
"@typescript-eslint/
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"eslint": "^8.55.0",
|
|
43
|
+
"@commitlint/cli": "^20.4.1",
|
|
44
|
+
"@commitlint/config-conventional": "^20.4.1",
|
|
45
|
+
"@eslint/js": "^10.0.1",
|
|
46
|
+
"@types/node": "22",
|
|
47
|
+
"@typescript-eslint/eslint-plugin": "^8.55.0",
|
|
48
|
+
"@typescript-eslint/parser": "^8.55.0",
|
|
49
|
+
"cross-env": "^10.1.0",
|
|
50
|
+
"eslint": "^10.0.0",
|
|
52
51
|
"husky": "4",
|
|
53
|
-
"jest": "^29.7.0",
|
|
54
|
-
"jest-resolve": "^29.7.0",
|
|
55
52
|
"npm-run-all": "^4.1.5",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
53
|
+
"return-style": "^3.0.1",
|
|
54
|
+
"rimraf": "^6.1.2",
|
|
55
|
+
"sqlite3": "^5.1.7",
|
|
58
56
|
"standard-version": "^9.5.0",
|
|
59
|
-
"ts-
|
|
60
|
-
"
|
|
61
|
-
"typescript": "^
|
|
62
|
-
"typescript-transform-paths": "^3.
|
|
57
|
+
"ts-patch": "^3.3.0",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"typescript-eslint": "^8.55.0",
|
|
60
|
+
"typescript-transform-paths": "^3.5.6",
|
|
61
|
+
"vite": "^7.3.1",
|
|
62
|
+
"vite-tsconfig-paths": "^6.1.0",
|
|
63
|
+
"vitest": "^4.0.18"
|
|
63
64
|
},
|
|
64
65
|
"dependencies": {
|
|
65
|
-
"@blackglory/prelude": "^0.
|
|
66
|
-
"extra-promise": "^
|
|
66
|
+
"@blackglory/prelude": "^0.4.0",
|
|
67
|
+
"extra-promise": "^7.0.1",
|
|
68
|
+
"extra-utils": "^5.20.0"
|
|
67
69
|
},
|
|
68
70
|
"peerDependencies": {
|
|
69
71
|
"sqlite3": "^5.1.6"
|
package/src/migrate.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Database } from 'sqlite3'
|
|
2
2
|
import { assert, isFunction } from '@blackglory/prelude'
|
|
3
3
|
import { promisify } from 'extra-promise'
|
|
4
|
+
import { max } from 'extra-utils'
|
|
4
5
|
|
|
5
6
|
export interface IMigration {
|
|
6
7
|
version: number
|
|
@@ -8,10 +9,18 @@ export interface IMigration {
|
|
|
8
9
|
down: string | ((db: Database) => PromiseLike<void>)
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
interface IMigrateOptions {
|
|
13
|
+
targetVersion?: number
|
|
14
|
+
throwOnNewerVersion?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
export async function migrate(
|
|
12
18
|
db: Database
|
|
13
19
|
, migrations: IMigration[]
|
|
14
|
-
,
|
|
20
|
+
, {
|
|
21
|
+
targetVersion = getMaximumVersion(migrations)
|
|
22
|
+
, throwOnNewerVersion = false
|
|
23
|
+
}: IMigrateOptions = {}
|
|
15
24
|
): Promise<void> {
|
|
16
25
|
const run = promisify(db.run.bind(db))
|
|
17
26
|
const exec = promisify(db.exec.bind(db))
|
|
@@ -19,17 +28,19 @@ export async function migrate(
|
|
|
19
28
|
|
|
20
29
|
const maxVersion = getMaximumVersion(migrations)
|
|
21
30
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
while (true) {
|
|
32
|
+
await run('BEGIN IMMEDIATE')
|
|
33
|
+
try {
|
|
25
34
|
const done = await migrate(targetVersion, maxVersion)
|
|
35
|
+
|
|
36
|
+
await run('COMMIT')
|
|
37
|
+
|
|
26
38
|
if (done) break
|
|
27
|
-
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
await run('ROLLBACK')
|
|
28
41
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
await run('ROLLBACK')
|
|
32
|
-
throw e
|
|
42
|
+
throw e
|
|
43
|
+
}
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
async function migrate(
|
|
@@ -38,7 +49,11 @@ export async function migrate(
|
|
|
38
49
|
): Promise<boolean> {
|
|
39
50
|
const currentVersion = await getDatabaseVersion()
|
|
40
51
|
if (maxVersion < currentVersion) {
|
|
41
|
-
|
|
52
|
+
if (throwOnNewerVersion) {
|
|
53
|
+
throw new Error(`Database version ${currentVersion} is higher than the maximum known migration version.`)
|
|
54
|
+
} else {
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
42
57
|
} else {
|
|
43
58
|
if (currentVersion === targetVersion) {
|
|
44
59
|
return true
|
|
@@ -57,7 +72,7 @@ export async function migrate(
|
|
|
57
72
|
const targetVersion = currentVersion + 1
|
|
58
73
|
|
|
59
74
|
const migration = migrations.find(x => x.version === targetVersion)
|
|
60
|
-
assert(migration, `Cannot find migration for version ${targetVersion}
|
|
75
|
+
assert(migration, `Cannot find a migration for version ${targetVersion}.`)
|
|
61
76
|
|
|
62
77
|
try {
|
|
63
78
|
if (isFunction(migration.up)) {
|
|
@@ -66,8 +81,10 @@ export async function migrate(
|
|
|
66
81
|
await exec(migration.up)
|
|
67
82
|
}
|
|
68
83
|
} catch (e) {
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Upgrade from version ${currentVersion} to version ${targetVersion} failed.`
|
|
86
|
+
, { cause: e }
|
|
87
|
+
)
|
|
71
88
|
}
|
|
72
89
|
await setDatabaseVersion(targetVersion)
|
|
73
90
|
}
|
|
@@ -77,7 +94,7 @@ export async function migrate(
|
|
|
77
94
|
const targetVersion = currentVersion - 1
|
|
78
95
|
|
|
79
96
|
const migration = migrations.find(x => x.version === currentVersion)
|
|
80
|
-
assert(migration, `Cannot find migration for version ${targetVersion}`)
|
|
97
|
+
assert(migration, `Cannot find a migration for version ${targetVersion}`)
|
|
81
98
|
|
|
82
99
|
try {
|
|
83
100
|
if (isFunction(migration.down)) {
|
|
@@ -86,26 +103,30 @@ export async function migrate(
|
|
|
86
103
|
await exec(migration.down)
|
|
87
104
|
}
|
|
88
105
|
} catch (e) {
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Downgrade from version ${currentVersion} to version ${targetVersion} failed.`
|
|
108
|
+
, { cause: e }
|
|
109
|
+
)
|
|
91
110
|
}
|
|
92
111
|
await setDatabaseVersion(targetVersion)
|
|
93
112
|
}
|
|
94
113
|
|
|
95
114
|
async function getDatabaseVersion(): Promise<number> {
|
|
96
|
-
const row = await get('PRAGMA user_version
|
|
115
|
+
const row = await get('PRAGMA user_version') as {
|
|
97
116
|
user_version: number
|
|
98
117
|
}
|
|
99
118
|
|
|
100
|
-
return row
|
|
119
|
+
return row['user_version']
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
async function setDatabaseVersion(version: number): Promise<void> {
|
|
104
123
|
// PRAGMA不支持变量
|
|
105
|
-
await run(`PRAGMA user_version = ${
|
|
124
|
+
await run(`PRAGMA user_version = ${version}`)
|
|
106
125
|
}
|
|
107
126
|
}
|
|
108
127
|
|
|
109
128
|
function getMaximumVersion(migrations: IMigration[]): number {
|
|
110
|
-
return migrations
|
|
129
|
+
return migrations
|
|
130
|
+
.map(x => x.version)
|
|
131
|
+
.reduce(max)
|
|
111
132
|
}
|