@blackglory/pg-migrations 0.1.3 → 0.2.2
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 +16 -7
- package/lib/es2015/index.js +5 -1
- package/lib/es2015/index.js.map +1 -1
- package/lib/es2015/migrate.d.ts +1 -1
- package/lib/es2015/migrate.js +75 -32
- package/lib/es2015/migrate.js.map +1 -1
- package/lib/es2018/index.js +5 -1
- package/lib/es2018/index.js.map +1 -1
- package/lib/es2018/migrate.d.ts +1 -1
- package/lib/es2018/migrate.js +71 -32
- package/lib/es2018/migrate.js.map +1 -1
- package/package.json +18 -17
- package/CHANGELOG.md +0 -16
package/README.md
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
# pg-migrations
|
|
2
2
|
A utility for database migrations with [pg].
|
|
3
3
|
|
|
4
|
-
The module
|
|
4
|
+
The module create a simple migrations table to record the schema version.
|
|
5
5
|
|
|
6
6
|
[pg]: https://www.npmjs.com/package/pg
|
|
7
|
-
[customized options]: https://www.postgresql.org/docs/current/runtime-config-custom.html
|
|
8
7
|
|
|
9
8
|
## Install
|
|
10
|
-
|
|
11
9
|
```sh
|
|
12
10
|
npm install --save @blackglory/pg-migrations
|
|
13
11
|
# or
|
|
@@ -15,7 +13,6 @@ yarn add @blackglory/pg-migrations
|
|
|
15
13
|
```
|
|
16
14
|
|
|
17
15
|
## API
|
|
18
|
-
|
|
19
16
|
```ts
|
|
20
17
|
interface IMigration {
|
|
21
18
|
version: number
|
|
@@ -25,9 +22,21 @@ interface IMigration {
|
|
|
25
22
|
```
|
|
26
23
|
|
|
27
24
|
### migrate
|
|
28
|
-
|
|
29
25
|
```ts
|
|
30
|
-
function migrate(
|
|
26
|
+
function migrate(
|
|
27
|
+
client: Client
|
|
28
|
+
, migrations: IMigration[]
|
|
29
|
+
, targetVersion = getMaximumVersion(migrations)
|
|
30
|
+
, migrationsTable: string = 'migrations'
|
|
31
|
+
, advisoryLockKey: bigint = BigInt('-9223372036854775808') // The smallest bigint for postgres
|
|
32
|
+
): Promise<void>
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
## FAQ
|
|
36
|
+
### Can multiple instances migrate in parallel?
|
|
37
|
+
Yes, it uses advisory lock to ensure that only one instance is migrating at a time.
|
|
38
|
+
When the maximum migration version is less than the database schema version (which means it is an obsolete instance), it will skip the migration.
|
|
39
|
+
|
|
40
|
+
### What if my migration requires more than one connection?
|
|
41
|
+
You can get all connection configurations through properties to create a new `pg.Client`.
|
|
42
|
+
It is important to note that the custom client you create is not part of the migration transaction.
|
package/lib/es2015/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/lib/es2015/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
|
package/lib/es2015/migrate.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export interface IMigration {
|
|
|
4
4
|
up: string | ((client: Client) => PromiseLike<void>);
|
|
5
5
|
down: string | ((client: Client) => PromiseLike<void>);
|
|
6
6
|
}
|
|
7
|
-
export declare function migrate(client: Client, migrations: IMigration[], targetVersion?: number): Promise<void>;
|
|
7
|
+
export declare function migrate(client: Client, migrations: IMigration[], targetVersion?: number, migrationsTable?: string, advisoryLockKey?: bigint): Promise<void>;
|
package/lib/es2015/migrate.js
CHANGED
|
@@ -12,57 +12,78 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.migrate = void 0;
|
|
13
13
|
const types_1 = require("@blackglory/types");
|
|
14
14
|
const errors_1 = require("@blackglory/errors");
|
|
15
|
-
function migrate(client, migrations, targetVersion = getMaximumVersion(migrations)) {
|
|
15
|
+
function migrate(client, migrations, targetVersion = getMaximumVersion(migrations), migrationsTable = 'migrations', advisoryLockKey = BigInt('-9223372036854775808')) {
|
|
16
16
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
const maxVersion = getMaximumVersion(migrations);
|
|
18
|
+
yield lock(client, advisoryLockKey);
|
|
19
|
+
try {
|
|
20
|
+
while (true) {
|
|
21
|
+
const currentVersion = yield getDatabaseVersion(client, migrationsTable);
|
|
22
|
+
if (maxVersion < currentVersion) {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
if (currentVersion === targetVersion) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
else if (currentVersion < targetVersion) {
|
|
30
|
+
yield upgrade();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
yield downgrade();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
24
36
|
}
|
|
25
37
|
}
|
|
38
|
+
finally {
|
|
39
|
+
yield unlock(client, advisoryLockKey);
|
|
40
|
+
}
|
|
26
41
|
function upgrade() {
|
|
27
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
|
|
43
|
+
yield client.query('BEGIN');
|
|
44
|
+
const currentVersion = yield getDatabaseVersion(client, migrationsTable);
|
|
29
45
|
const targetVersion = currentVersion + 1;
|
|
30
|
-
const migration = migrations.find(x => x.version === targetVersion);
|
|
31
|
-
errors_1.assert(migration, `Cannot find migration for version ${targetVersion}`);
|
|
32
46
|
try {
|
|
33
|
-
|
|
47
|
+
const migration = migrations.find(x => x.version === targetVersion);
|
|
48
|
+
(0, errors_1.assert)(migration, `Cannot find migration for version ${targetVersion}`);
|
|
49
|
+
if ((0, types_1.isFunction)(migration.up)) {
|
|
34
50
|
yield migration.up(client);
|
|
35
51
|
}
|
|
36
52
|
else {
|
|
37
53
|
yield client.query(migration.up);
|
|
38
54
|
}
|
|
55
|
+
yield setDatabaseVersion(client, migrationsTable, targetVersion);
|
|
56
|
+
yield client.query('COMMIT');
|
|
39
57
|
}
|
|
40
58
|
catch (e) {
|
|
41
59
|
console.error(`Upgrade from version ${currentVersion} to version ${targetVersion} failed.`);
|
|
60
|
+
yield client.query('ROLLBACK');
|
|
42
61
|
throw e;
|
|
43
62
|
}
|
|
44
|
-
yield setDatabaseVersion(client, targetVersion);
|
|
45
63
|
});
|
|
46
64
|
}
|
|
47
65
|
function downgrade() {
|
|
48
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
|
|
67
|
+
yield client.query('BEGIN');
|
|
68
|
+
const currentVersion = yield getDatabaseVersion(client, migrationsTable);
|
|
50
69
|
const targetVersion = currentVersion - 1;
|
|
51
|
-
const migration = migrations.find(x => x.version === currentVersion);
|
|
52
|
-
errors_1.assert(migration, `Cannot find migration for version ${targetVersion}`);
|
|
53
70
|
try {
|
|
54
|
-
|
|
71
|
+
const migration = migrations.find(x => x.version === currentVersion);
|
|
72
|
+
(0, errors_1.assert)(migration, `Cannot find migration for version ${targetVersion}`);
|
|
73
|
+
if ((0, types_1.isFunction)(migration.down)) {
|
|
55
74
|
yield migration.down(client);
|
|
56
75
|
}
|
|
57
76
|
else {
|
|
58
77
|
yield client.query(migration.down);
|
|
59
78
|
}
|
|
79
|
+
yield setDatabaseVersion(client, migrationsTable, targetVersion);
|
|
80
|
+
yield client.query('COMMIT');
|
|
60
81
|
}
|
|
61
82
|
catch (e) {
|
|
62
83
|
console.error(`Downgrade from version ${currentVersion} to version ${targetVersion} failed.`);
|
|
84
|
+
yield client.query('ROLLBACK');
|
|
63
85
|
throw e;
|
|
64
86
|
}
|
|
65
|
-
yield setDatabaseVersion(client, targetVersion);
|
|
66
87
|
});
|
|
67
88
|
}
|
|
68
89
|
});
|
|
@@ -71,32 +92,54 @@ exports.migrate = migrate;
|
|
|
71
92
|
function getMaximumVersion(migrations) {
|
|
72
93
|
return migrations.reduce((max, cur) => Math.max(cur.version, max), 0);
|
|
73
94
|
}
|
|
74
|
-
function getDatabaseVersion(client) {
|
|
95
|
+
function getDatabaseVersion(client, migrationTable) {
|
|
75
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
yield ensureMigrationsTable(client, migrationTable);
|
|
76
98
|
const result = yield client.query(`
|
|
77
|
-
SELECT
|
|
99
|
+
SELECT schema_version
|
|
100
|
+
FROM "${migrationTable}";
|
|
78
101
|
`);
|
|
79
|
-
|
|
102
|
+
if (result.rows.length) {
|
|
103
|
+
return result.rows[0].schema_version;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
yield client.query(`
|
|
107
|
+
INSERT INTO "${migrationTable}" (schema_version)
|
|
108
|
+
VALUES (0);
|
|
109
|
+
`);
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
80
112
|
});
|
|
81
113
|
}
|
|
82
|
-
function
|
|
114
|
+
function ensureMigrationsTable(client, migrationTable) {
|
|
83
115
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
-
const database = yield getCurrentDatabase(client);
|
|
85
116
|
yield client.query(`
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
SET migrations.schema_version
|
|
90
|
-
FROM current;
|
|
117
|
+
CREATE TABLE IF NOT EXISTS "${migrationTable}" (
|
|
118
|
+
schema_version INTEGER NOT NULL
|
|
119
|
+
);
|
|
91
120
|
`);
|
|
92
121
|
});
|
|
93
122
|
}
|
|
94
|
-
function
|
|
123
|
+
function setDatabaseVersion(client, migrationTable, version) {
|
|
95
124
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
-
|
|
97
|
-
|
|
125
|
+
yield client.query(`
|
|
126
|
+
UPDATE ${migrationTable}
|
|
127
|
+
SET schema_version = ${version};
|
|
128
|
+
`);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function lock(client, key) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
yield client.query(`
|
|
134
|
+
SELECT pg_advisory_lock(${key});
|
|
135
|
+
`);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function unlock(client, key) {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
yield client.query(`
|
|
141
|
+
SELECT pg_advisory_unlock(${key});
|
|
98
142
|
`);
|
|
99
|
-
return result.rows[0].database;
|
|
100
143
|
});
|
|
101
144
|
}
|
|
102
145
|
//# sourceMappingURL=migrate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,6CAA8C;AAC9C,+CAA2C;AAQ3C,SAAsB,OAAO,CAC3B,MAAc,EACd,UAAwB,EACxB,aAAa,GAAG,iBAAiB,CAAC,UAAU,CAAC;;
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":"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"}
|
package/lib/es2018/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
package/lib/es2018/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
|
package/lib/es2018/migrate.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export interface IMigration {
|
|
|
4
4
|
up: string | ((client: Client) => PromiseLike<void>);
|
|
5
5
|
down: string | ((client: Client) => PromiseLike<void>);
|
|
6
6
|
}
|
|
7
|
-
export declare function migrate(client: Client, migrations: IMigration[], targetVersion?: number): Promise<void>;
|
|
7
|
+
export declare function migrate(client: Client, migrations: IMigration[], targetVersion?: number, migrationsTable?: string, advisoryLockKey?: bigint): Promise<void>;
|
package/lib/es2018/migrate.js
CHANGED
|
@@ -3,79 +3,118 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.migrate = void 0;
|
|
4
4
|
const types_1 = require("@blackglory/types");
|
|
5
5
|
const errors_1 = require("@blackglory/errors");
|
|
6
|
-
async function migrate(client, migrations, targetVersion = getMaximumVersion(migrations)) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
async function migrate(client, migrations, targetVersion = getMaximumVersion(migrations), migrationsTable = 'migrations', advisoryLockKey = BigInt('-9223372036854775808')) {
|
|
7
|
+
const maxVersion = getMaximumVersion(migrations);
|
|
8
|
+
await lock(client, advisoryLockKey);
|
|
9
|
+
try {
|
|
10
|
+
while (true) {
|
|
11
|
+
const currentVersion = await getDatabaseVersion(client, migrationsTable);
|
|
12
|
+
if (maxVersion < currentVersion) {
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
if (currentVersion === targetVersion) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
else if (currentVersion < targetVersion) {
|
|
20
|
+
await upgrade();
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
await downgrade();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
14
26
|
}
|
|
15
27
|
}
|
|
28
|
+
finally {
|
|
29
|
+
await unlock(client, advisoryLockKey);
|
|
30
|
+
}
|
|
16
31
|
async function upgrade() {
|
|
17
|
-
|
|
32
|
+
await client.query('BEGIN');
|
|
33
|
+
const currentVersion = await getDatabaseVersion(client, migrationsTable);
|
|
18
34
|
const targetVersion = currentVersion + 1;
|
|
19
|
-
const migration = migrations.find(x => x.version === targetVersion);
|
|
20
|
-
errors_1.assert(migration, `Cannot find migration for version ${targetVersion}`);
|
|
21
35
|
try {
|
|
22
|
-
|
|
36
|
+
const migration = migrations.find(x => x.version === targetVersion);
|
|
37
|
+
(0, errors_1.assert)(migration, `Cannot find migration for version ${targetVersion}`);
|
|
38
|
+
if ((0, types_1.isFunction)(migration.up)) {
|
|
23
39
|
await migration.up(client);
|
|
24
40
|
}
|
|
25
41
|
else {
|
|
26
42
|
await client.query(migration.up);
|
|
27
43
|
}
|
|
44
|
+
await setDatabaseVersion(client, migrationsTable, targetVersion);
|
|
45
|
+
await client.query('COMMIT');
|
|
28
46
|
}
|
|
29
47
|
catch (e) {
|
|
30
48
|
console.error(`Upgrade from version ${currentVersion} to version ${targetVersion} failed.`);
|
|
49
|
+
await client.query('ROLLBACK');
|
|
31
50
|
throw e;
|
|
32
51
|
}
|
|
33
|
-
await setDatabaseVersion(client, targetVersion);
|
|
34
52
|
}
|
|
35
53
|
async function downgrade() {
|
|
36
|
-
|
|
54
|
+
await client.query('BEGIN');
|
|
55
|
+
const currentVersion = await getDatabaseVersion(client, migrationsTable);
|
|
37
56
|
const targetVersion = currentVersion - 1;
|
|
38
|
-
const migration = migrations.find(x => x.version === currentVersion);
|
|
39
|
-
errors_1.assert(migration, `Cannot find migration for version ${targetVersion}`);
|
|
40
57
|
try {
|
|
41
|
-
|
|
58
|
+
const migration = migrations.find(x => x.version === currentVersion);
|
|
59
|
+
(0, errors_1.assert)(migration, `Cannot find migration for version ${targetVersion}`);
|
|
60
|
+
if ((0, types_1.isFunction)(migration.down)) {
|
|
42
61
|
await migration.down(client);
|
|
43
62
|
}
|
|
44
63
|
else {
|
|
45
64
|
await client.query(migration.down);
|
|
46
65
|
}
|
|
66
|
+
await setDatabaseVersion(client, migrationsTable, targetVersion);
|
|
67
|
+
await client.query('COMMIT');
|
|
47
68
|
}
|
|
48
69
|
catch (e) {
|
|
49
70
|
console.error(`Downgrade from version ${currentVersion} to version ${targetVersion} failed.`);
|
|
71
|
+
await client.query('ROLLBACK');
|
|
50
72
|
throw e;
|
|
51
73
|
}
|
|
52
|
-
await setDatabaseVersion(client, targetVersion);
|
|
53
74
|
}
|
|
54
75
|
}
|
|
55
76
|
exports.migrate = migrate;
|
|
56
77
|
function getMaximumVersion(migrations) {
|
|
57
78
|
return migrations.reduce((max, cur) => Math.max(cur.version, max), 0);
|
|
58
79
|
}
|
|
59
|
-
async function getDatabaseVersion(client) {
|
|
80
|
+
async function getDatabaseVersion(client, migrationTable) {
|
|
81
|
+
await ensureMigrationsTable(client, migrationTable);
|
|
60
82
|
const result = await client.query(`
|
|
61
|
-
SELECT
|
|
83
|
+
SELECT schema_version
|
|
84
|
+
FROM "${migrationTable}";
|
|
62
85
|
`);
|
|
63
|
-
|
|
86
|
+
if (result.rows.length) {
|
|
87
|
+
return result.rows[0].schema_version;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
await client.query(`
|
|
91
|
+
INSERT INTO "${migrationTable}" (schema_version)
|
|
92
|
+
VALUES (0);
|
|
93
|
+
`);
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
64
96
|
}
|
|
65
|
-
async function
|
|
66
|
-
const database = await getCurrentDatabase(client);
|
|
97
|
+
async function ensureMigrationsTable(client, migrationTable) {
|
|
67
98
|
await client.query(`
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
SET migrations.schema_version
|
|
72
|
-
FROM current;
|
|
99
|
+
CREATE TABLE IF NOT EXISTS "${migrationTable}" (
|
|
100
|
+
schema_version INTEGER NOT NULL
|
|
101
|
+
);
|
|
73
102
|
`);
|
|
74
103
|
}
|
|
75
|
-
async function
|
|
76
|
-
|
|
77
|
-
|
|
104
|
+
async function setDatabaseVersion(client, migrationTable, version) {
|
|
105
|
+
await client.query(`
|
|
106
|
+
UPDATE ${migrationTable}
|
|
107
|
+
SET schema_version = ${version};
|
|
108
|
+
`);
|
|
109
|
+
}
|
|
110
|
+
async function lock(client, key) {
|
|
111
|
+
await client.query(`
|
|
112
|
+
SELECT pg_advisory_lock(${key});
|
|
113
|
+
`);
|
|
114
|
+
}
|
|
115
|
+
async function unlock(client, key) {
|
|
116
|
+
await client.query(`
|
|
117
|
+
SELECT pg_advisory_unlock(${key});
|
|
78
118
|
`);
|
|
79
|
-
return result.rows[0].database;
|
|
80
119
|
}
|
|
81
120
|
//# sourceMappingURL=migrate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/migrate.ts"],"names":[],"mappings":";;;AACA,6CAA8C;AAC9C,+CAA2C;AAQpC,KAAK,UAAU,OAAO,CAC3B,MAAc,EACd,UAAwB,EACxB,aAAa,GAAG,iBAAiB,CAAC,UAAU,CAAC;
|
|
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/pg-migrations",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A utility for database migrations with pg",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"migration",
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"repository": "git@github.com:BlackGlory/pg-migrations.git",
|
|
19
19
|
"author": "BlackGlory <woshenmedoubuzhidao@blackglory.me>",
|
|
20
20
|
"license": "MIT",
|
|
21
|
+
"sideEffects": false,
|
|
21
22
|
"scripts": {
|
|
22
23
|
"lint": "eslint --ext .js,.jsx,.ts,.tsx --quiet src __tests__",
|
|
23
|
-
"test": "jest --config jest.config.js",
|
|
24
|
+
"test": "jest --runInBand --config jest.config.js",
|
|
24
25
|
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
|
25
26
|
"test:coverage": "jest --coverage --config jest.config.js",
|
|
26
27
|
"prepublishOnly": "run-s clean build",
|
|
@@ -45,28 +46,28 @@
|
|
|
45
46
|
}
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@commitlint/cli": "^
|
|
49
|
-
"@commitlint/config-conventional": "^
|
|
50
|
-
"@types/jest": "^
|
|
51
|
-
"@types/pg": "^8.6.
|
|
52
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
53
|
-
"@typescript-eslint/parser": "^
|
|
54
|
-
"eslint": "^
|
|
49
|
+
"@commitlint/cli": "^17.0.3",
|
|
50
|
+
"@commitlint/config-conventional": "^17.0.3",
|
|
51
|
+
"@types/jest": "^27.4.0",
|
|
52
|
+
"@types/pg": "^8.6.5",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^5.32.0",
|
|
54
|
+
"@typescript-eslint/parser": "^5.32.0",
|
|
55
|
+
"eslint": "^8.21.0",
|
|
55
56
|
"husky": "^4.3.0",
|
|
56
|
-
"jest": "^27.
|
|
57
|
+
"jest": "^27.5.1",
|
|
57
58
|
"npm-run-all": "^4.1.5",
|
|
58
|
-
"pg": "^8.
|
|
59
|
+
"pg": "^8.7.3",
|
|
59
60
|
"rimraf": "^3.0.2",
|
|
60
|
-
"standard-version": "^9.
|
|
61
|
-
"ts-jest": "^27.
|
|
61
|
+
"standard-version": "^9.5.0",
|
|
62
|
+
"ts-jest": "^27.1.3",
|
|
62
63
|
"tscpaths": "^0.0.9",
|
|
63
|
-
"typescript": "^4.
|
|
64
|
+
"typescript": "^4.7.4"
|
|
64
65
|
},
|
|
65
66
|
"dependencies": {
|
|
66
|
-
"@blackglory/errors": "^
|
|
67
|
-
"@blackglory/types": "^
|
|
67
|
+
"@blackglory/errors": "^2.2.2",
|
|
68
|
+
"@blackglory/types": "^1.2.1"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
|
-
"pg": "8
|
|
71
|
+
"pg": "8"
|
|
71
72
|
}
|
|
72
73
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
-
|
|
5
|
-
### [0.1.3](https://github.com/BlackGlory/pg-migrations/compare/v0.1.2...v0.1.3) (2021-07-03)
|
|
6
|
-
|
|
7
|
-
### [0.1.2](https://github.com/BlackGlory/pg-migrations/compare/v0.1.1...v0.1.2) (2021-03-17)
|
|
8
|
-
|
|
9
|
-
### [0.1.1](https://github.com/BlackGlory/pg-migrations/compare/v0.1.0...v0.1.1) (2021-03-07)
|
|
10
|
-
|
|
11
|
-
## 0.1.0 (2021-02-20)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
### Features
|
|
15
|
-
|
|
16
|
-
* init ([f5fcf82](https://github.com/BlackGlory/pg-migrations/commit/f5fcf8206e11fa669b6f7b95c7f4ef718550898a))
|