@sqb/migrator 4.11.3 → 4.12.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 +9 -24
- package/cjs/adapters/pg-migration-adapter.js +23 -18
- package/cjs/db-migrator.js +14 -13
- package/cjs/migration-package.js +8 -14
- package/cjs/utils/get-calling-filename.js +1 -2
- package/esm/adapters/pg-migration-adapter.js +24 -19
- package/esm/db-migrator.js +14 -13
- package/esm/migration-package.js +8 -14
- package/esm/utils/get-calling-filename.js +1 -2
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -20,12 +20,12 @@ SQB is an extensible, multi-dialect SQL query builder and Database connection wr
|
|
|
20
20
|
|
|
21
21
|
## Main goals
|
|
22
22
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
23
|
+
- Single code base for any sql based database
|
|
24
|
+
- Powerful and simplified query coding scheme
|
|
25
|
+
- Fast applications with low memory requirements
|
|
26
|
+
- Let applications work with large data tables efficiently
|
|
27
|
+
- Support latest JavaScript language standards
|
|
28
|
+
- Lightweight and extensible framework.
|
|
29
29
|
|
|
30
30
|
You can report bugs and discuss features on the [GitHub issues](https://github.com/sqbjs/sqb/issues) page
|
|
31
31
|
|
|
@@ -41,40 +41,25 @@ $ npm install @sqb/migrator --save
|
|
|
41
41
|
|
|
42
42
|
## Node Compatibility
|
|
43
43
|
|
|
44
|
-
-
|
|
44
|
+
- node >= 16.x
|
|
45
45
|
|
|
46
46
|
### License
|
|
47
47
|
|
|
48
48
|
SQB is available under [MIT](LICENSE) license.
|
|
49
49
|
|
|
50
50
|
[npm-image]: https://img.shields.io/npm/v/@sqb/migrator.svg
|
|
51
|
-
|
|
52
51
|
[npm-url]: https://npmjs.org/package/@sqb/migrator
|
|
53
|
-
|
|
54
52
|
[travis-image]: https://img.shields.io/travis/sqbjs/@sqb/migrator/master.svg
|
|
55
|
-
|
|
56
53
|
[travis-url]: https://travis-ci.org/sqbjs/@sqb/migrator
|
|
57
|
-
|
|
58
54
|
[coveralls-image]: https://img.shields.io/coveralls/sqbjs/@sqb/migrator/master.svg
|
|
59
|
-
|
|
60
55
|
[coveralls-url]: https://coveralls.io/r/sqbjs/@sqb/migrator
|
|
61
|
-
|
|
62
56
|
[downloads-image]: https://img.shields.io/npm/dm/@sqb/migrator.svg
|
|
63
|
-
|
|
64
57
|
[downloads-url]: https://npmjs.org/package/@sqb/migrator
|
|
65
|
-
|
|
66
58
|
[gitter-image]: https://badges.gitter.im/sqbjs/@sqb/migrator.svg
|
|
67
|
-
|
|
68
59
|
[gitter-url]: https://gitter.im/sqbjs/@sqb/migrator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
|
69
|
-
|
|
70
60
|
[dependencies-image]: https://david-dm.org/sqbjs/@sqb/migrator/status.svg
|
|
71
|
-
|
|
72
|
-
[dependencies-url]:https://david-dm.org/sqbjs/@sqb/migrator
|
|
73
|
-
|
|
61
|
+
[dependencies-url]: https://david-dm.org/sqbjs/@sqb/migrator
|
|
74
62
|
[devdependencies-image]: https://david-dm.org/sqbjs/@sqb/migrator/dev-status.svg
|
|
75
|
-
|
|
76
|
-
[devdependencies-url]:https://david-dm.org/sqbjs/@sqb/migrator?type=dev
|
|
77
|
-
|
|
63
|
+
[devdependencies-url]: https://david-dm.org/sqbjs/@sqb/migrator?type=dev
|
|
78
64
|
[quality-image]: http://npm.packagequality.com/shield/@sqb/migrator.png
|
|
79
|
-
|
|
80
65
|
[quality-url]: http://packagequality.com/#?package=@sqb/migrator
|
|
@@ -18,7 +18,7 @@ class PgMigrationAdapter extends migration_adapter_js_1.MigrationAdapter {
|
|
|
18
18
|
this.defaultVariables = {
|
|
19
19
|
tablespace: 'pg_default',
|
|
20
20
|
schema: 'public',
|
|
21
|
-
owner: 'postgres'
|
|
21
|
+
owner: 'postgres',
|
|
22
22
|
};
|
|
23
23
|
this.summaryTable = 'migration_summary';
|
|
24
24
|
this.eventTable = 'migration_events';
|
|
@@ -52,7 +52,7 @@ class PgMigrationAdapter extends migration_adapter_js_1.MigrationAdapter {
|
|
|
52
52
|
adapter.defaultVariables.schema = options.connection.schema || '';
|
|
53
53
|
if (!adapter.defaultVariables.schema) {
|
|
54
54
|
const r = await connection.query('SELECT CURRENT_SCHEMA ', { objectRows: true });
|
|
55
|
-
adapter.defaultVariables.schema =
|
|
55
|
+
adapter.defaultVariables.schema = r.rows?.[0]?.current_schema || 'public';
|
|
56
56
|
}
|
|
57
57
|
// Check if migration schema
|
|
58
58
|
await connection.query(`CREATE SCHEMA IF NOT EXISTS ${adapter.infoSchema} AUTHORIZATION postgres;`);
|
|
@@ -83,10 +83,14 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
83
83
|
CONSTRAINT pk_${adapter.eventTable} PRIMARY KEY (id)
|
|
84
84
|
)`);
|
|
85
85
|
// Insert summary record if not exists
|
|
86
|
-
const r = await connection.query(`SELECT status FROM ${adapter.summaryTableFull} WHERE package_name = $1`, {
|
|
86
|
+
const r = await connection.query(`SELECT status FROM ${adapter.summaryTableFull} WHERE package_name = $1`, {
|
|
87
|
+
params: [adapter.packageName],
|
|
88
|
+
objectRows: true,
|
|
89
|
+
});
|
|
87
90
|
if (!(r && r.rows?.length)) {
|
|
88
|
-
await connection.query(`insert into ${adapter.summaryTableFull} ` +
|
|
89
|
-
|
|
91
|
+
await connection.query(`insert into ${adapter.summaryTableFull} ` + '(package_name, status) values ($1, $2)', {
|
|
92
|
+
params: [adapter.packageName, types_js_1.MigrationStatus.idle],
|
|
93
|
+
});
|
|
90
94
|
}
|
|
91
95
|
await adapter.refresh();
|
|
92
96
|
return adapter;
|
|
@@ -100,7 +104,10 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
100
104
|
await this._connection.close();
|
|
101
105
|
}
|
|
102
106
|
async refresh() {
|
|
103
|
-
const r = await this._connection.query(`SELECT * FROM ${this.summaryTableFull} WHERE package_name = $1`, {
|
|
107
|
+
const r = await this._connection.query(`SELECT * FROM ${this.summaryTableFull} WHERE package_name = $1`, {
|
|
108
|
+
params: [this.packageName],
|
|
109
|
+
objectRows: true,
|
|
110
|
+
});
|
|
104
111
|
const row = r.rows && r.rows[0];
|
|
105
112
|
if (!row)
|
|
106
113
|
throw new Error('Summary record did not created');
|
|
@@ -112,16 +119,19 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
112
119
|
const params = [];
|
|
113
120
|
if (info.status && info.status !== this.status) {
|
|
114
121
|
params.push(info.status);
|
|
115
|
-
sql += ',\n status = $' +
|
|
122
|
+
sql += ',\n status = $' + params.length;
|
|
116
123
|
}
|
|
117
124
|
if (info.version && info.version !== this.version) {
|
|
118
125
|
params.push(info.version);
|
|
119
|
-
sql += ',\n current_version = $' +
|
|
126
|
+
sql += ',\n current_version = $' + params.length;
|
|
120
127
|
}
|
|
121
128
|
if (sql) {
|
|
122
129
|
params.push(this.packageName);
|
|
123
|
-
sql =
|
|
124
|
-
|
|
130
|
+
sql =
|
|
131
|
+
`update ${this.summaryTableFull} set updated_at = current_timestamp` +
|
|
132
|
+
sql +
|
|
133
|
+
`\n where package_name =$` +
|
|
134
|
+
params.length;
|
|
125
135
|
await this._connection.query(sql, { params });
|
|
126
136
|
if (info.status)
|
|
127
137
|
this._status = info.status;
|
|
@@ -134,16 +144,13 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
134
144
|
'(package_name, version, event, event_time, title, message, filename, details) ' +
|
|
135
145
|
'values ($1, $2, $3, CURRENT_TIMESTAMP, $4, $5, $6, $7)';
|
|
136
146
|
await this._connection.query(sql, {
|
|
137
|
-
params: [
|
|
138
|
-
this.packageName, event.version, event.event,
|
|
139
|
-
event.title, event.message, event.filename, event.details
|
|
140
|
-
]
|
|
147
|
+
params: [this.packageName, event.version, event.event, event.title, event.message, event.filename, event.details],
|
|
141
148
|
});
|
|
142
149
|
}
|
|
143
150
|
async executeTask(migrationPackage, migration, task, variables) {
|
|
144
151
|
variables = {
|
|
145
152
|
...this.defaultVariables,
|
|
146
|
-
...variables
|
|
153
|
+
...variables,
|
|
147
154
|
};
|
|
148
155
|
if ((0, migration_package_js_1.isSqlScriptMigrationTask)(task)) {
|
|
149
156
|
try {
|
|
@@ -180,9 +187,7 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
180
187
|
}
|
|
181
188
|
if ((0, migration_package_js_1.isInsertDataMigrationTask)(task)) {
|
|
182
189
|
const tableName = this.replaceVariables(task.tableName, variables);
|
|
183
|
-
const script = task.rows
|
|
184
|
-
.map(row => this.rowToSql(tableName, row))
|
|
185
|
-
.join('\n');
|
|
190
|
+
const script = task.rows.map(row => this.rowToSql(tableName, row)).join('\n');
|
|
186
191
|
await this._connection.execute(script);
|
|
187
192
|
}
|
|
188
193
|
}
|
package/cjs/db-migrator.js
CHANGED
|
@@ -11,14 +11,13 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
11
11
|
if (!options.connection.dialect)
|
|
12
12
|
throw new TypeError(`You must provide connection.dialect`);
|
|
13
13
|
const migrationPackage = await migration_package_js_1.MigrationPackage.load(options.migrationPackage);
|
|
14
|
-
let minVersion = migrationPackage.migrations
|
|
15
|
-
.reduce((a, m) => Math.min(a, m.version), Number.MAX_SAFE_INTEGER);
|
|
14
|
+
let minVersion = migrationPackage.migrations.reduce((a, m) => Math.min(a, m.version), Number.MAX_SAFE_INTEGER);
|
|
16
15
|
if (minVersion === Number.MAX_SAFE_INTEGER)
|
|
17
16
|
minVersion = 0;
|
|
18
|
-
const maxVersion = migrationPackage.migrations
|
|
19
|
-
.reduce((a, m) => Math.max(a, m.version), 0);
|
|
17
|
+
const maxVersion = migrationPackage.migrations.reduce((a, m) => Math.max(a, m.version), 0);
|
|
20
18
|
const targetVersion = Math.min(options?.targetVersion || Number.MAX_SAFE_INTEGER, maxVersion);
|
|
21
|
-
if (targetVersion && targetVersion < minVersion) {
|
|
19
|
+
if (targetVersion && targetVersion < minVersion) {
|
|
20
|
+
// noinspection ExceptionCaughtLocallyJS
|
|
22
21
|
throw new Error(`Version mismatch. Target schema version (${targetVersion}) is lower than ` +
|
|
23
22
|
`migration package min version (${minVersion})`);
|
|
24
23
|
}
|
|
@@ -33,13 +32,13 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
33
32
|
}
|
|
34
33
|
let needBackup = false;
|
|
35
34
|
try {
|
|
36
|
-
if (migrationAdapter.version && migrationAdapter.version < minVersion - 1) {
|
|
35
|
+
if (migrationAdapter.version && migrationAdapter.version < minVersion - 1) {
|
|
36
|
+
// noinspection ExceptionCaughtLocallyJS
|
|
37
37
|
throw new Error(`This package can migrate starting from ${minVersion - 1} but current version is ${migrationAdapter.version}`);
|
|
38
38
|
}
|
|
39
39
|
const { migrations } = migrationPackage;
|
|
40
40
|
// calculate total scripts;
|
|
41
|
-
const total = migrations
|
|
42
|
-
.reduce((i, x) => i + x.tasks.length, 0);
|
|
41
|
+
const total = migrations.reduce((i, x) => i + x.tasks.length, 0);
|
|
43
42
|
needBackup = !!migrations.find(x => !!x.backup);
|
|
44
43
|
await this.emitAsync('start');
|
|
45
44
|
let task;
|
|
@@ -57,7 +56,7 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
57
56
|
await this.emitAsync('migration-start', {
|
|
58
57
|
migration,
|
|
59
58
|
total: migrations.length,
|
|
60
|
-
index: migrationIndex
|
|
59
|
+
index: migrationIndex,
|
|
61
60
|
});
|
|
62
61
|
for (let index = 0; index < migration.tasks.length; index++) {
|
|
63
62
|
task = migration.tasks[index];
|
|
@@ -68,7 +67,7 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
68
67
|
version: migration.version,
|
|
69
68
|
title: task.title,
|
|
70
69
|
filename: task.filename,
|
|
71
|
-
message: `Task "${task.title}" started
|
|
70
|
+
message: `Task "${task.title}" started`,
|
|
72
71
|
});
|
|
73
72
|
try {
|
|
74
73
|
await migrationAdapter.executeTask(migrationPackage, migration, task, {
|
|
@@ -90,10 +89,12 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
90
89
|
title: task.title,
|
|
91
90
|
filename: task.filename,
|
|
92
91
|
message: String(e),
|
|
93
|
-
details: e.message +
|
|
92
|
+
details: e.message +
|
|
93
|
+
'\n\n' +
|
|
94
94
|
Object.keys(e)
|
|
95
95
|
.filter(k => e[k] != null)
|
|
96
|
-
.map(k => k + ': ' + e[k])
|
|
96
|
+
.map(k => k + ': ' + e[k])
|
|
97
|
+
.join('\n'),
|
|
97
98
|
});
|
|
98
99
|
// noinspection ExceptionCaughtLocallyJS
|
|
99
100
|
throw e;
|
|
@@ -104,7 +105,7 @@ class DbMigrator extends strict_typed_events_1.AsyncEventEmitter {
|
|
|
104
105
|
await this.emitAsync('migration-finish', {
|
|
105
106
|
migration,
|
|
106
107
|
total: migrations.length,
|
|
107
|
-
index: migrationIndex
|
|
108
|
+
index: migrationIndex,
|
|
108
109
|
});
|
|
109
110
|
}
|
|
110
111
|
}
|
package/cjs/migration-package.js
CHANGED
|
@@ -7,19 +7,15 @@ const promises_1 = tslib_1.__importDefault(require("fs/promises"));
|
|
|
7
7
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
8
8
|
const get_calling_filename_js_1 = require("./utils/get-calling-filename.js");
|
|
9
9
|
function isSqlScriptMigrationTask(x) {
|
|
10
|
-
return typeof x === 'object' &&
|
|
11
|
-
(typeof x.script === 'string' || typeof x.script === 'function');
|
|
10
|
+
return typeof x === 'object' && (typeof x.script === 'string' || typeof x.script === 'function');
|
|
12
11
|
}
|
|
13
12
|
exports.isSqlScriptMigrationTask = isSqlScriptMigrationTask;
|
|
14
13
|
function isInsertDataMigrationTask(x) {
|
|
15
|
-
return typeof x === 'object' &&
|
|
16
|
-
typeof x.tableName === 'string' &&
|
|
17
|
-
Array.isArray(x.rows);
|
|
14
|
+
return typeof x === 'object' && typeof x.tableName === 'string' && Array.isArray(x.rows);
|
|
18
15
|
}
|
|
19
16
|
exports.isInsertDataMigrationTask = isInsertDataMigrationTask;
|
|
20
17
|
function isCustomMigrationTask(x) {
|
|
21
|
-
return typeof x === 'object' &&
|
|
22
|
-
typeof x.fn === 'function';
|
|
18
|
+
return typeof x === 'object' && typeof x.fn === 'function';
|
|
23
19
|
}
|
|
24
20
|
exports.isCustomMigrationTask = isCustomMigrationTask;
|
|
25
21
|
var MigrationPackage;
|
|
@@ -29,7 +25,7 @@ var MigrationPackage;
|
|
|
29
25
|
const out = {
|
|
30
26
|
...asyncConfig,
|
|
31
27
|
baseDir,
|
|
32
|
-
migrations: []
|
|
28
|
+
migrations: [],
|
|
33
29
|
};
|
|
34
30
|
if (!Array.isArray(asyncConfig.migrations))
|
|
35
31
|
throw new TypeError('You must provide array of MigrationConfig in "migrations" property');
|
|
@@ -43,7 +39,7 @@ var MigrationPackage;
|
|
|
43
39
|
if (typeof x === 'object' && x.tasks)
|
|
44
40
|
srcMigrations.push(x);
|
|
45
41
|
else if (typeof x === 'string') {
|
|
46
|
-
srcMigrations.push(...await loadMigrations(baseDir, x.replace(/\\/g, '/')));
|
|
42
|
+
srcMigrations.push(...(await loadMigrations(baseDir, x.replace(/\\/g, '/'))));
|
|
47
43
|
}
|
|
48
44
|
}
|
|
49
45
|
srcMigrations.sort((a, b) => a.version - b.version);
|
|
@@ -61,7 +57,7 @@ var MigrationPackage;
|
|
|
61
57
|
pattern = path_1.default.resolve(path_1.default.join(baseDir, trgMigration.baseDir, pattern));
|
|
62
58
|
const files = await (0, fast_glob_1.default)(pattern, {
|
|
63
59
|
absolute: true,
|
|
64
|
-
onlyFiles: true
|
|
60
|
+
onlyFiles: true,
|
|
65
61
|
});
|
|
66
62
|
files.sort();
|
|
67
63
|
for (const filename of files) {
|
|
@@ -73,14 +69,12 @@ var MigrationPackage;
|
|
|
73
69
|
trgMigration.tasks.push({
|
|
74
70
|
title: path_1.default.basename(filename, ext),
|
|
75
71
|
filename,
|
|
76
|
-
script
|
|
72
|
+
script,
|
|
77
73
|
});
|
|
78
74
|
}
|
|
79
75
|
else if (['.json', '.js', '.ts', '.cjs', '.mjs'].includes(ext)) {
|
|
80
76
|
try {
|
|
81
|
-
let json = ext === '.json'
|
|
82
|
-
? JSON.parse(await promises_1.default.readFile(filename, 'utf-8'))
|
|
83
|
-
: await Promise.resolve(`${filename}`).then(s => tslib_1.__importStar(require(s)));
|
|
77
|
+
let json = ext === '.json' ? JSON.parse(await promises_1.default.readFile(filename, 'utf-8')) : await Promise.resolve(`${filename}`).then(s => tslib_1.__importStar(require(s)));
|
|
84
78
|
if (typeof json !== 'object')
|
|
85
79
|
continue;
|
|
86
80
|
if (json.__esModule)
|
|
@@ -13,8 +13,7 @@ function getCallingFilename(position = 0) {
|
|
|
13
13
|
if (stack !== null && typeof stack === 'object') {
|
|
14
14
|
// stack[0] holds this file
|
|
15
15
|
// stack[1] holds where this function was called
|
|
16
|
-
const s = stack[position] ?
|
|
17
|
-
stack[position].getFileName() : undefined;
|
|
16
|
+
const s = stack[position] ? stack[position].getFileName() : undefined;
|
|
18
17
|
const m = s ? PATH_PATTERN.exec(s) : undefined;
|
|
19
18
|
return m ? m[1] : '';
|
|
20
19
|
}
|
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
import { stringifyValueForSQL } from 'postgresql-client';
|
|
3
3
|
import { PgAdapter } from '@sqb/postgres';
|
|
4
4
|
import { MigrationAdapter } from '../migration-adapter.js';
|
|
5
|
-
import { isCustomMigrationTask, isInsertDataMigrationTask, isSqlScriptMigrationTask } from '../migration-package.js';
|
|
5
|
+
import { isCustomMigrationTask, isInsertDataMigrationTask, isSqlScriptMigrationTask, } from '../migration-package.js';
|
|
6
6
|
import { MigrationStatus } from '../types.js';
|
|
7
7
|
const pgAdapter = new PgAdapter();
|
|
8
8
|
export class PgMigrationAdapter extends MigrationAdapter {
|
|
@@ -14,7 +14,7 @@ export class PgMigrationAdapter extends MigrationAdapter {
|
|
|
14
14
|
this.defaultVariables = {
|
|
15
15
|
tablespace: 'pg_default',
|
|
16
16
|
schema: 'public',
|
|
17
|
-
owner: 'postgres'
|
|
17
|
+
owner: 'postgres',
|
|
18
18
|
};
|
|
19
19
|
this.summaryTable = 'migration_summary';
|
|
20
20
|
this.eventTable = 'migration_events';
|
|
@@ -48,7 +48,7 @@ export class PgMigrationAdapter extends MigrationAdapter {
|
|
|
48
48
|
adapter.defaultVariables.schema = options.connection.schema || '';
|
|
49
49
|
if (!adapter.defaultVariables.schema) {
|
|
50
50
|
const r = await connection.query('SELECT CURRENT_SCHEMA ', { objectRows: true });
|
|
51
|
-
adapter.defaultVariables.schema =
|
|
51
|
+
adapter.defaultVariables.schema = r.rows?.[0]?.current_schema || 'public';
|
|
52
52
|
}
|
|
53
53
|
// Check if migration schema
|
|
54
54
|
await connection.query(`CREATE SCHEMA IF NOT EXISTS ${adapter.infoSchema} AUTHORIZATION postgres;`);
|
|
@@ -79,10 +79,14 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
79
79
|
CONSTRAINT pk_${adapter.eventTable} PRIMARY KEY (id)
|
|
80
80
|
)`);
|
|
81
81
|
// Insert summary record if not exists
|
|
82
|
-
const r = await connection.query(`SELECT status FROM ${adapter.summaryTableFull} WHERE package_name = $1`, {
|
|
82
|
+
const r = await connection.query(`SELECT status FROM ${adapter.summaryTableFull} WHERE package_name = $1`, {
|
|
83
|
+
params: [adapter.packageName],
|
|
84
|
+
objectRows: true,
|
|
85
|
+
});
|
|
83
86
|
if (!(r && r.rows?.length)) {
|
|
84
|
-
await connection.query(`insert into ${adapter.summaryTableFull} ` +
|
|
85
|
-
|
|
87
|
+
await connection.query(`insert into ${adapter.summaryTableFull} ` + '(package_name, status) values ($1, $2)', {
|
|
88
|
+
params: [adapter.packageName, MigrationStatus.idle],
|
|
89
|
+
});
|
|
86
90
|
}
|
|
87
91
|
await adapter.refresh();
|
|
88
92
|
return adapter;
|
|
@@ -96,7 +100,10 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
96
100
|
await this._connection.close();
|
|
97
101
|
}
|
|
98
102
|
async refresh() {
|
|
99
|
-
const r = await this._connection.query(`SELECT * FROM ${this.summaryTableFull} WHERE package_name = $1`, {
|
|
103
|
+
const r = await this._connection.query(`SELECT * FROM ${this.summaryTableFull} WHERE package_name = $1`, {
|
|
104
|
+
params: [this.packageName],
|
|
105
|
+
objectRows: true,
|
|
106
|
+
});
|
|
100
107
|
const row = r.rows && r.rows[0];
|
|
101
108
|
if (!row)
|
|
102
109
|
throw new Error('Summary record did not created');
|
|
@@ -108,16 +115,19 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
108
115
|
const params = [];
|
|
109
116
|
if (info.status && info.status !== this.status) {
|
|
110
117
|
params.push(info.status);
|
|
111
|
-
sql += ',\n status = $' +
|
|
118
|
+
sql += ',\n status = $' + params.length;
|
|
112
119
|
}
|
|
113
120
|
if (info.version && info.version !== this.version) {
|
|
114
121
|
params.push(info.version);
|
|
115
|
-
sql += ',\n current_version = $' +
|
|
122
|
+
sql += ',\n current_version = $' + params.length;
|
|
116
123
|
}
|
|
117
124
|
if (sql) {
|
|
118
125
|
params.push(this.packageName);
|
|
119
|
-
sql =
|
|
120
|
-
|
|
126
|
+
sql =
|
|
127
|
+
`update ${this.summaryTableFull} set updated_at = current_timestamp` +
|
|
128
|
+
sql +
|
|
129
|
+
`\n where package_name =$` +
|
|
130
|
+
params.length;
|
|
121
131
|
await this._connection.query(sql, { params });
|
|
122
132
|
if (info.status)
|
|
123
133
|
this._status = info.status;
|
|
@@ -130,16 +140,13 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
130
140
|
'(package_name, version, event, event_time, title, message, filename, details) ' +
|
|
131
141
|
'values ($1, $2, $3, CURRENT_TIMESTAMP, $4, $5, $6, $7)';
|
|
132
142
|
await this._connection.query(sql, {
|
|
133
|
-
params: [
|
|
134
|
-
this.packageName, event.version, event.event,
|
|
135
|
-
event.title, event.message, event.filename, event.details
|
|
136
|
-
]
|
|
143
|
+
params: [this.packageName, event.version, event.event, event.title, event.message, event.filename, event.details],
|
|
137
144
|
});
|
|
138
145
|
}
|
|
139
146
|
async executeTask(migrationPackage, migration, task, variables) {
|
|
140
147
|
variables = {
|
|
141
148
|
...this.defaultVariables,
|
|
142
|
-
...variables
|
|
149
|
+
...variables,
|
|
143
150
|
};
|
|
144
151
|
if (isSqlScriptMigrationTask(task)) {
|
|
145
152
|
try {
|
|
@@ -176,9 +183,7 @@ CREATE TABLE IF NOT EXISTS ${adapter.eventTableFull}
|
|
|
176
183
|
}
|
|
177
184
|
if (isInsertDataMigrationTask(task)) {
|
|
178
185
|
const tableName = this.replaceVariables(task.tableName, variables);
|
|
179
|
-
const script = task.rows
|
|
180
|
-
.map(row => this.rowToSql(tableName, row))
|
|
181
|
-
.join('\n');
|
|
186
|
+
const script = task.rows.map(row => this.rowToSql(tableName, row)).join('\n');
|
|
182
187
|
await this._connection.execute(script);
|
|
183
188
|
}
|
|
184
189
|
}
|
package/esm/db-migrator.js
CHANGED
|
@@ -8,14 +8,13 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
8
8
|
if (!options.connection.dialect)
|
|
9
9
|
throw new TypeError(`You must provide connection.dialect`);
|
|
10
10
|
const migrationPackage = await MigrationPackage.load(options.migrationPackage);
|
|
11
|
-
let minVersion = migrationPackage.migrations
|
|
12
|
-
.reduce((a, m) => Math.min(a, m.version), Number.MAX_SAFE_INTEGER);
|
|
11
|
+
let minVersion = migrationPackage.migrations.reduce((a, m) => Math.min(a, m.version), Number.MAX_SAFE_INTEGER);
|
|
13
12
|
if (minVersion === Number.MAX_SAFE_INTEGER)
|
|
14
13
|
minVersion = 0;
|
|
15
|
-
const maxVersion = migrationPackage.migrations
|
|
16
|
-
.reduce((a, m) => Math.max(a, m.version), 0);
|
|
14
|
+
const maxVersion = migrationPackage.migrations.reduce((a, m) => Math.max(a, m.version), 0);
|
|
17
15
|
const targetVersion = Math.min(options?.targetVersion || Number.MAX_SAFE_INTEGER, maxVersion);
|
|
18
|
-
if (targetVersion && targetVersion < minVersion) {
|
|
16
|
+
if (targetVersion && targetVersion < minVersion) {
|
|
17
|
+
// noinspection ExceptionCaughtLocallyJS
|
|
19
18
|
throw new Error(`Version mismatch. Target schema version (${targetVersion}) is lower than ` +
|
|
20
19
|
`migration package min version (${minVersion})`);
|
|
21
20
|
}
|
|
@@ -30,13 +29,13 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
30
29
|
}
|
|
31
30
|
let needBackup = false;
|
|
32
31
|
try {
|
|
33
|
-
if (migrationAdapter.version && migrationAdapter.version < minVersion - 1) {
|
|
32
|
+
if (migrationAdapter.version && migrationAdapter.version < minVersion - 1) {
|
|
33
|
+
// noinspection ExceptionCaughtLocallyJS
|
|
34
34
|
throw new Error(`This package can migrate starting from ${minVersion - 1} but current version is ${migrationAdapter.version}`);
|
|
35
35
|
}
|
|
36
36
|
const { migrations } = migrationPackage;
|
|
37
37
|
// calculate total scripts;
|
|
38
|
-
const total = migrations
|
|
39
|
-
.reduce((i, x) => i + x.tasks.length, 0);
|
|
38
|
+
const total = migrations.reduce((i, x) => i + x.tasks.length, 0);
|
|
40
39
|
needBackup = !!migrations.find(x => !!x.backup);
|
|
41
40
|
await this.emitAsync('start');
|
|
42
41
|
let task;
|
|
@@ -54,7 +53,7 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
54
53
|
await this.emitAsync('migration-start', {
|
|
55
54
|
migration,
|
|
56
55
|
total: migrations.length,
|
|
57
|
-
index: migrationIndex
|
|
56
|
+
index: migrationIndex,
|
|
58
57
|
});
|
|
59
58
|
for (let index = 0; index < migration.tasks.length; index++) {
|
|
60
59
|
task = migration.tasks[index];
|
|
@@ -65,7 +64,7 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
65
64
|
version: migration.version,
|
|
66
65
|
title: task.title,
|
|
67
66
|
filename: task.filename,
|
|
68
|
-
message: `Task "${task.title}" started
|
|
67
|
+
message: `Task "${task.title}" started`,
|
|
69
68
|
});
|
|
70
69
|
try {
|
|
71
70
|
await migrationAdapter.executeTask(migrationPackage, migration, task, {
|
|
@@ -87,10 +86,12 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
87
86
|
title: task.title,
|
|
88
87
|
filename: task.filename,
|
|
89
88
|
message: String(e),
|
|
90
|
-
details: e.message +
|
|
89
|
+
details: e.message +
|
|
90
|
+
'\n\n' +
|
|
91
91
|
Object.keys(e)
|
|
92
92
|
.filter(k => e[k] != null)
|
|
93
|
-
.map(k => k + ': ' + e[k])
|
|
93
|
+
.map(k => k + ': ' + e[k])
|
|
94
|
+
.join('\n'),
|
|
94
95
|
});
|
|
95
96
|
// noinspection ExceptionCaughtLocallyJS
|
|
96
97
|
throw e;
|
|
@@ -101,7 +102,7 @@ export class DbMigrator extends AsyncEventEmitter {
|
|
|
101
102
|
await this.emitAsync('migration-finish', {
|
|
102
103
|
migration,
|
|
103
104
|
total: migrations.length,
|
|
104
|
-
index: migrationIndex
|
|
105
|
+
index: migrationIndex,
|
|
105
106
|
});
|
|
106
107
|
}
|
|
107
108
|
}
|
package/esm/migration-package.js
CHANGED
|
@@ -3,17 +3,13 @@ import fs from 'fs/promises';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { getCallingFilename } from './utils/get-calling-filename.js';
|
|
5
5
|
export function isSqlScriptMigrationTask(x) {
|
|
6
|
-
return typeof x === 'object' &&
|
|
7
|
-
(typeof x.script === 'string' || typeof x.script === 'function');
|
|
6
|
+
return typeof x === 'object' && (typeof x.script === 'string' || typeof x.script === 'function');
|
|
8
7
|
}
|
|
9
8
|
export function isInsertDataMigrationTask(x) {
|
|
10
|
-
return typeof x === 'object' &&
|
|
11
|
-
typeof x.tableName === 'string' &&
|
|
12
|
-
Array.isArray(x.rows);
|
|
9
|
+
return typeof x === 'object' && typeof x.tableName === 'string' && Array.isArray(x.rows);
|
|
13
10
|
}
|
|
14
11
|
export function isCustomMigrationTask(x) {
|
|
15
|
-
return typeof x === 'object' &&
|
|
16
|
-
typeof x.fn === 'function';
|
|
12
|
+
return typeof x === 'object' && typeof x.fn === 'function';
|
|
17
13
|
}
|
|
18
14
|
export var MigrationPackage;
|
|
19
15
|
(function (MigrationPackage) {
|
|
@@ -22,7 +18,7 @@ export var MigrationPackage;
|
|
|
22
18
|
const out = {
|
|
23
19
|
...asyncConfig,
|
|
24
20
|
baseDir,
|
|
25
|
-
migrations: []
|
|
21
|
+
migrations: [],
|
|
26
22
|
};
|
|
27
23
|
if (!Array.isArray(asyncConfig.migrations))
|
|
28
24
|
throw new TypeError('You must provide array of MigrationConfig in "migrations" property');
|
|
@@ -36,7 +32,7 @@ export var MigrationPackage;
|
|
|
36
32
|
if (typeof x === 'object' && x.tasks)
|
|
37
33
|
srcMigrations.push(x);
|
|
38
34
|
else if (typeof x === 'string') {
|
|
39
|
-
srcMigrations.push(...await loadMigrations(baseDir, x.replace(/\\/g, '/')));
|
|
35
|
+
srcMigrations.push(...(await loadMigrations(baseDir, x.replace(/\\/g, '/'))));
|
|
40
36
|
}
|
|
41
37
|
}
|
|
42
38
|
srcMigrations.sort((a, b) => a.version - b.version);
|
|
@@ -54,7 +50,7 @@ export var MigrationPackage;
|
|
|
54
50
|
pattern = path.resolve(path.join(baseDir, trgMigration.baseDir, pattern));
|
|
55
51
|
const files = await glob(pattern, {
|
|
56
52
|
absolute: true,
|
|
57
|
-
onlyFiles: true
|
|
53
|
+
onlyFiles: true,
|
|
58
54
|
});
|
|
59
55
|
files.sort();
|
|
60
56
|
for (const filename of files) {
|
|
@@ -66,14 +62,12 @@ export var MigrationPackage;
|
|
|
66
62
|
trgMigration.tasks.push({
|
|
67
63
|
title: path.basename(filename, ext),
|
|
68
64
|
filename,
|
|
69
|
-
script
|
|
65
|
+
script,
|
|
70
66
|
});
|
|
71
67
|
}
|
|
72
68
|
else if (['.json', '.js', '.ts', '.cjs', '.mjs'].includes(ext)) {
|
|
73
69
|
try {
|
|
74
|
-
let json = ext === '.json'
|
|
75
|
-
? JSON.parse(await fs.readFile(filename, 'utf-8'))
|
|
76
|
-
: await import(filename);
|
|
70
|
+
let json = ext === '.json' ? JSON.parse(await fs.readFile(filename, 'utf-8')) : await import(filename);
|
|
77
71
|
if (typeof json !== 'object')
|
|
78
72
|
continue;
|
|
79
73
|
if (json.__esModule)
|
|
@@ -10,8 +10,7 @@ export function getCallingFilename(position = 0) {
|
|
|
10
10
|
if (stack !== null && typeof stack === 'object') {
|
|
11
11
|
// stack[0] holds this file
|
|
12
12
|
// stack[1] holds where this function was called
|
|
13
|
-
const s = stack[position] ?
|
|
14
|
-
stack[position].getFileName() : undefined;
|
|
13
|
+
const s = stack[position] ? stack[position].getFileName() : undefined;
|
|
15
14
|
const m = s ? PATH_PATTERN.exec(s) : undefined;
|
|
16
15
|
return m ? m[1] : '';
|
|
17
16
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqb/migrator",
|
|
3
3
|
"description": "Database migrator for SQB",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.12.1",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"Eray Hanoglu <e.hanoglu@panates.com>",
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
"build:esm": "tsc -b tsconfig-build-esm.json",
|
|
26
26
|
"postbuild": "cp README.md package.json ../../LICENSE ../../build/migrator && cp ../../package.cjs.json ../../build/migrator/cjs/package.json",
|
|
27
27
|
"lint": "eslint . --max-warnings=0",
|
|
28
|
+
"lint:fix": "eslint . --max-warnings=0 --fix",
|
|
29
|
+
"format": "prettier . --write --log-level=warn",
|
|
28
30
|
"test": "jest",
|
|
29
31
|
"cover": "jest --collect-coverage",
|
|
30
32
|
"clean": "npm run clean:src | npm run clean:dist | npm run clean:cover",
|
|
@@ -33,12 +35,12 @@
|
|
|
33
35
|
"clean:cover": "rimraf ../../coverage/migrator"
|
|
34
36
|
},
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"ts-gems": "^3.
|
|
38
|
+
"ts-gems": "^3.4.0"
|
|
37
39
|
},
|
|
38
40
|
"peerDependencies": {
|
|
39
|
-
"@sqb/builder": "^4.
|
|
40
|
-
"@sqb/connect": "^4.
|
|
41
|
-
"@sqb/postgres": "^4.
|
|
41
|
+
"@sqb/builder": "^4.12.1",
|
|
42
|
+
"@sqb/connect": "^4.12.1",
|
|
43
|
+
"@sqb/postgres": "^4.12.1"
|
|
42
44
|
},
|
|
43
45
|
"engines": {
|
|
44
46
|
"node": ">=16.0",
|