@webiny/data-migration 0.0.0-unstable.e3f4727c56 → 0.0.0-unstable.eb196ccd2f
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/MigrationRunner.d.ts +16 -9
- package/MigrationRunner.js +243 -62
- package/MigrationRunner.js.map +1 -1
- package/cli/CliMigrationRunReporter.d.ts +10 -0
- package/cli/CliMigrationRunReporter.js +55 -0
- package/cli/CliMigrationRunReporter.js.map +1 -0
- package/cli/InteractiveCliStatusReporter.d.ts +11 -0
- package/cli/InteractiveCliStatusReporter.js +74 -0
- package/cli/InteractiveCliStatusReporter.js.map +1 -0
- package/cli/LogReporter.d.ts +10 -0
- package/cli/LogReporter.js +43 -0
- package/cli/LogReporter.js.map +1 -0
- package/cli/LogStream.d.ts +10 -0
- package/cli/LogStream.js +58 -0
- package/cli/LogStream.js.map +1 -0
- package/cli/MigrationRunReporter.d.ts +4 -0
- package/cli/MigrationRunReporter.js +7 -0
- package/cli/MigrationRunReporter.js.map +1 -0
- package/cli/MigrationRunner.d.ts +45 -0
- package/cli/MigrationRunner.js +136 -0
- package/cli/MigrationRunner.js.map +1 -0
- package/cli/MigrationStatusReporter.d.ts +4 -0
- package/cli/MigrationStatusReporter.js +7 -0
- package/cli/MigrationStatusReporter.js.map +1 -0
- package/cli/NonInteractiveCliStatusReporter.d.ts +9 -0
- package/cli/NonInteractiveCliStatusReporter.js +42 -0
- package/cli/NonInteractiveCliStatusReporter.js.map +1 -0
- package/cli/VoidStatusReporter.d.ts +4 -0
- package/cli/VoidStatusReporter.js +14 -0
- package/cli/VoidStatusReporter.js.map +1 -0
- package/cli/getDuration.d.ts +5 -0
- package/cli/getDuration.js +23 -0
- package/cli/getDuration.js.map +1 -0
- package/cli/index.d.ts +10 -0
- package/cli/index.js +117 -0
- package/cli/index.js.map +1 -0
- package/createPinoLogger.d.ts +4 -7
- package/createPinoLogger.js +7 -3
- package/createPinoLogger.js.map +1 -1
- package/createTable.d.ts +4 -4
- package/createTable.js +8 -4
- package/createTable.js.map +1 -1
- package/handlers/createDdbEsProjectMigration.d.ts +9 -8
- package/handlers/createDdbEsProjectMigration.js +24 -7
- package/handlers/createDdbEsProjectMigration.js.map +1 -1
- package/handlers/createDdbProjectMigration.d.ts +7 -6
- package/handlers/createDdbProjectMigration.js +24 -7
- package/handlers/createDdbProjectMigration.js.map +1 -1
- package/handlers/createPatternMatcher.d.ts +1 -1
- package/handlers/createPatternMatcher.js +3 -1
- package/handlers/createPatternMatcher.js.map +1 -1
- package/handlers/devVersionErrorResponse.js +3 -1
- package/handlers/devVersionErrorResponse.js.map +1 -1
- package/index.d.ts +1 -1
- package/index.js +3 -12
- package/index.js.map +1 -1
- package/package.json +21 -30
- package/repository/createStandardEntity.d.ts +52 -0
- package/repository/{migrations.entity.js → createStandardEntity.js} +10 -7
- package/repository/createStandardEntity.js.map +1 -0
- package/repository/migrations.repository.d.ts +11 -4
- package/repository/migrations.repository.js +87 -15
- package/repository/migrations.repository.js.map +1 -1
- package/symbols.d.ts +1 -0
- package/symbols.js +10 -13
- package/symbols.js.map +1 -1
- package/types.d.ts +59 -33
- package/types.js +2 -7
- package/types.js.map +1 -1
- package/repository/migrations.entity.d.ts +0 -4
- package/repository/migrations.entity.js.map +0 -1
package/MigrationRunner.d.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { Logger } from "
|
|
2
|
-
import {
|
|
3
|
-
export
|
|
1
|
+
import type { Logger } from "@webiny/logger";
|
|
2
|
+
import type { MigrationRepository, DataMigration, ExecutionTimeLimiter, MigrationStatus } from "./types";
|
|
3
|
+
export type IsMigrationApplicable = (migration: DataMigration) => boolean;
|
|
4
4
|
export declare class MigrationRunner {
|
|
5
5
|
private readonly logger;
|
|
6
6
|
private readonly migrations;
|
|
7
7
|
private readonly repository;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
private readonly timeLimiter;
|
|
9
|
+
private context;
|
|
10
|
+
constructor(repository: MigrationRepository, timeLimiter: ExecutionTimeLimiter, migrations: DataMigration[], logger: Logger | undefined);
|
|
11
|
+
setContext(context: Record<string, any>): void;
|
|
12
|
+
execute(projectVersion: string, isApplicable?: IsMigrationApplicable, forceExecute?: boolean): Promise<void>;
|
|
13
|
+
getStatus(): Promise<MigrationStatus>;
|
|
14
14
|
private validateIds;
|
|
15
|
+
private createCheckpoint;
|
|
16
|
+
private getOrCreateRun;
|
|
17
|
+
private getOrCreateRunItem;
|
|
18
|
+
private setRunItem;
|
|
19
|
+
private setRunItemAndSave;
|
|
20
|
+
private printForceExecuteEnvVars;
|
|
21
|
+
private printSkipExecuteEnvVars;
|
|
15
22
|
}
|
package/MigrationRunner.js
CHANGED
|
@@ -1,29 +1,71 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
7
6
|
exports.MigrationRunner = void 0;
|
|
8
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
-
var _ioc = require("@webiny/ioc");
|
|
10
7
|
var _semver = require("semver");
|
|
8
|
+
var _ioc = require("@webiny/ioc");
|
|
9
|
+
var _utils = require("@webiny/utils");
|
|
11
10
|
var _symbols = require("./symbols");
|
|
12
11
|
var _createPinoLogger = require("./createPinoLogger");
|
|
12
|
+
const getCurrentISOTime = () => {
|
|
13
|
+
return new Date().toISOString();
|
|
14
|
+
};
|
|
15
|
+
const getRunItemDuration = runItem => {
|
|
16
|
+
if (!runItem.startedOn || !runItem.finishedOn) {
|
|
17
|
+
return "N/A";
|
|
18
|
+
}
|
|
19
|
+
return new Date(runItem.finishedOn).getTime() - new Date(runItem.startedOn).getTime();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* This allows us to force-execute a migration, even if it's not in the list of the applicable migrations.
|
|
24
|
+
* Example: WEBINY_MIGRATION_FORCE_EXECUTE_5_35_0_006=true
|
|
25
|
+
*/
|
|
26
|
+
const shouldForceExecute = mig => {
|
|
27
|
+
const key = `WEBINY_MIGRATION_FORCE_EXECUTE_${mig.getId().replace(/[\.\-]/g, "_")}`;
|
|
28
|
+
return process.env[key] === "true";
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This allows us to always skip a migration.
|
|
33
|
+
* Example: WEBINY_MIGRATION_SKIP_5_35_0_006=true
|
|
34
|
+
*/
|
|
35
|
+
const shouldSkip = mig => {
|
|
36
|
+
const key = `WEBINY_MIGRATION_SKIP_${mig.getId().replace(/[\.\-]/g, "_")}`;
|
|
37
|
+
return process.env[key] === "true";
|
|
38
|
+
};
|
|
39
|
+
class MigrationNotFinished extends Error {}
|
|
40
|
+
class MigrationInProgress extends Error {}
|
|
13
41
|
class MigrationRunner {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
(0, _defineProperty2.default)(this, "migrations", void 0);
|
|
17
|
-
(0, _defineProperty2.default)(this, "repository", void 0);
|
|
42
|
+
context = {};
|
|
43
|
+
constructor(repository, timeLimiter, migrations, logger) {
|
|
18
44
|
this.repository = repository;
|
|
45
|
+
this.timeLimiter = timeLimiter;
|
|
19
46
|
this.migrations = migrations || [];
|
|
20
47
|
if (!logger) {
|
|
21
48
|
logger = (0, _createPinoLogger.createPinoLogger)();
|
|
22
49
|
}
|
|
23
50
|
this.logger = logger;
|
|
24
51
|
}
|
|
25
|
-
|
|
26
|
-
this.
|
|
52
|
+
setContext(context) {
|
|
53
|
+
this.context = context;
|
|
54
|
+
}
|
|
55
|
+
async execute(projectVersion, isApplicable,
|
|
56
|
+
// Force execute applicable migrations.
|
|
57
|
+
forceExecute = false) {
|
|
58
|
+
const lastRun = await this.getOrCreateRun();
|
|
59
|
+
try {
|
|
60
|
+
this.validateIds(this.migrations);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
lastRun.status = "error";
|
|
63
|
+
lastRun.error = {
|
|
64
|
+
message: err.message
|
|
65
|
+
};
|
|
66
|
+
await this.repository.saveRun(lastRun);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
27
69
|
const [latestMigration] = await this.repository.listMigrations({
|
|
28
70
|
limit: 1
|
|
29
71
|
});
|
|
@@ -41,8 +83,8 @@ class MigrationRunner {
|
|
|
41
83
|
await this.repository.logMigration({
|
|
42
84
|
id: startingId,
|
|
43
85
|
description: "starting point for applicable migrations detection",
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
startedOn: getCurrentISOTime(),
|
|
87
|
+
finishedOn: getCurrentISOTime(),
|
|
46
88
|
reason: "initial migration"
|
|
47
89
|
});
|
|
48
90
|
} else {
|
|
@@ -53,84 +95,148 @@ class MigrationRunner {
|
|
|
53
95
|
} else {
|
|
54
96
|
this.logger.info(`Using migrations in the range of %s to %s.`, startingId, lastId);
|
|
55
97
|
}
|
|
56
|
-
const executed = [];
|
|
57
|
-
const skipped = [];
|
|
58
|
-
const notApplicable = [];
|
|
59
98
|
const defaultIsApplicable = mig => {
|
|
60
99
|
return mig.getId() > startingId && mig.getId() <= lastId;
|
|
61
100
|
};
|
|
62
101
|
const isMigrationApplicable = isApplicable || defaultIsApplicable;
|
|
102
|
+
this.printForceExecuteEnvVars();
|
|
103
|
+
this.printSkipExecuteEnvVars();
|
|
104
|
+
if (forceExecute) {
|
|
105
|
+
this.logger.info(`ALL APPLICABLE MIGRATIONS WILL BE FORCE-EXECUTED! (via --force flag)`);
|
|
106
|
+
}
|
|
63
107
|
const executableMigrations = this.migrations.filter(mig => {
|
|
108
|
+
if (shouldSkip(mig)) {
|
|
109
|
+
this.setRunItem(lastRun, {
|
|
110
|
+
id: mig.getId(),
|
|
111
|
+
status: "skipped"
|
|
112
|
+
});
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (shouldForceExecute(mig)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
64
118
|
if (!isMigrationApplicable(mig)) {
|
|
65
|
-
|
|
119
|
+
this.setRunItem(lastRun, {
|
|
66
120
|
id: mig.getId(),
|
|
67
|
-
|
|
68
|
-
reason: "not applicable"
|
|
121
|
+
status: "not-applicable"
|
|
69
122
|
});
|
|
70
123
|
return false;
|
|
71
124
|
}
|
|
72
125
|
return true;
|
|
73
126
|
}).sort((a, b) => a.getId() > b.getId() ? 1 : -1);
|
|
74
|
-
this.logger.info(`Found %s applicable migration(s).`, executableMigrations.length);
|
|
127
|
+
this.logger.info(`Found %s applicable out of %s available migration(s).`, executableMigrations.length, this.migrations.length);
|
|
128
|
+
|
|
129
|
+
// Are we're within the last 2 minutes of the execution time limit?
|
|
130
|
+
const shouldCreateCheckpoint = () => {
|
|
131
|
+
return this.timeLimiter() < 120000;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
//
|
|
75
135
|
for (const migration of executableMigrations) {
|
|
136
|
+
const runItem = this.getOrCreateRunItem(lastRun, migration);
|
|
137
|
+
const checkpoint = await this.repository.getCheckpoint(migration.getId());
|
|
76
138
|
const logger = (0, _createPinoLogger.getChildLogger)(this.logger, migration);
|
|
139
|
+
if (checkpoint) {
|
|
140
|
+
this.logger.info(checkpoint, `Found checkpoint ${migration.getId()}.`);
|
|
141
|
+
}
|
|
77
142
|
const context = {
|
|
78
143
|
projectVersion,
|
|
79
|
-
logger
|
|
144
|
+
logger,
|
|
145
|
+
checkpoint,
|
|
146
|
+
forceExecute: forceExecute || shouldForceExecute(migration),
|
|
147
|
+
runningOutOfTime: shouldCreateCheckpoint,
|
|
148
|
+
createCheckpoint: async data => {
|
|
149
|
+
await this.createCheckpoint(migration, data);
|
|
150
|
+
},
|
|
151
|
+
createCheckpointAndExit: async data => {
|
|
152
|
+
await this.createCheckpoint(migration, data);
|
|
153
|
+
// We throw an error to break out of the migration execution completely.
|
|
154
|
+
throw new MigrationNotFinished();
|
|
155
|
+
}
|
|
80
156
|
};
|
|
81
|
-
const shouldExecute = await migration.shouldExecute(context);
|
|
82
|
-
if (!shouldExecute) {
|
|
83
|
-
this.logger.info(`Skipping migration %s.`, migration.getId());
|
|
84
|
-
skipped.push({
|
|
85
|
-
id: migration.getId(),
|
|
86
|
-
description: migration.getDescription(),
|
|
87
|
-
reason: "migration already applied"
|
|
88
|
-
});
|
|
89
|
-
await this.repository.logMigration({
|
|
90
|
-
id: migration.getId(),
|
|
91
|
-
description: migration.getDescription(),
|
|
92
|
-
createdOn: new Date().toISOString(),
|
|
93
|
-
duration: 0,
|
|
94
|
-
reason: "skipped"
|
|
95
|
-
});
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
const result = {
|
|
99
|
-
duration: 0,
|
|
100
|
-
logs: [],
|
|
101
|
-
success: true
|
|
102
|
-
};
|
|
103
|
-
const start = Date.now();
|
|
104
157
|
try {
|
|
105
|
-
|
|
158
|
+
const shouldExecute = checkpoint || context.forceExecute ? true : await migration.shouldExecute(context);
|
|
159
|
+
if (!shouldExecute) {
|
|
160
|
+
this.logger.info(`Skipping migration %s.`, migration.getId());
|
|
161
|
+
runItem.status = "skipped";
|
|
162
|
+
await this.setRunItemAndSave(lastRun, runItem);
|
|
163
|
+
await this.repository.logMigration({
|
|
164
|
+
id: migration.getId(),
|
|
165
|
+
description: migration.getDescription(),
|
|
166
|
+
reason: "skipped"
|
|
167
|
+
});
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
lastRun.status = "running";
|
|
171
|
+
runItem.status = "running";
|
|
172
|
+
if (!runItem.startedOn) {
|
|
173
|
+
runItem.startedOn = getCurrentISOTime();
|
|
174
|
+
}
|
|
175
|
+
await this.setRunItemAndSave(lastRun, runItem);
|
|
176
|
+
this.logger.info(`Executing migration %s: %s`, migration.getId(), migration.getDescription());
|
|
106
177
|
await migration.execute(context);
|
|
178
|
+
runItem.status = "done";
|
|
107
179
|
} catch (err) {
|
|
108
|
-
|
|
180
|
+
// If `MigrationNotFinished` was thrown, we will need to resume the migration.
|
|
181
|
+
if (err instanceof MigrationNotFinished) {
|
|
182
|
+
lastRun.status = "pending";
|
|
183
|
+
runItem.status = "pending";
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
runItem.status = "error";
|
|
187
|
+
lastRun.status = "error";
|
|
188
|
+
lastRun.error = {
|
|
189
|
+
name: err.name || "Migration error",
|
|
190
|
+
message: err.message,
|
|
191
|
+
stack: err.stack,
|
|
192
|
+
data: err.data,
|
|
193
|
+
code: err.code
|
|
194
|
+
};
|
|
109
195
|
this.logger.error(err, err.message);
|
|
196
|
+
return;
|
|
110
197
|
} finally {
|
|
111
|
-
|
|
112
|
-
|
|
198
|
+
runItem.finishedOn = getCurrentISOTime();
|
|
199
|
+
|
|
200
|
+
// Update run stats.
|
|
201
|
+
await this.setRunItemAndSave(lastRun, runItem);
|
|
202
|
+
if (runItem.status === "pending") {
|
|
203
|
+
this.logger.info(`Pausing migration %s, awaiting continuation.`, migration.getId());
|
|
204
|
+
} else {
|
|
205
|
+
this.logger.info(`Finished executing migration %s in %sms.`, migration.getId(), getRunItemDuration(runItem));
|
|
206
|
+
}
|
|
113
207
|
}
|
|
114
|
-
|
|
208
|
+
await this.repository.logMigration({
|
|
115
209
|
id: migration.getId(),
|
|
116
210
|
description: migration.getDescription(),
|
|
117
|
-
|
|
211
|
+
startedOn: runItem.startedOn,
|
|
212
|
+
finishedOn: runItem.finishedOn,
|
|
213
|
+
reason: "executed"
|
|
118
214
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
id: migration.getId(),
|
|
122
|
-
description: migration.getDescription(),
|
|
123
|
-
createdOn: new Date().toISOString(),
|
|
124
|
-
duration: result.duration,
|
|
125
|
-
reason: "executed"
|
|
126
|
-
});
|
|
127
|
-
}
|
|
215
|
+
this.logger.info(`Deleting checkpoint ${migration.getId()}.`);
|
|
216
|
+
await this.repository.deleteCheckpoint(migration.getId());
|
|
128
217
|
}
|
|
218
|
+
lastRun.status = "done";
|
|
219
|
+
lastRun.finishedOn = getCurrentISOTime();
|
|
220
|
+
await this.repository.saveRun(lastRun);
|
|
129
221
|
this.logger.info(`Finished processing applicable migrations.`);
|
|
222
|
+
}
|
|
223
|
+
async getStatus() {
|
|
224
|
+
const lastRun = await this.repository.getLastRun();
|
|
225
|
+
if (!lastRun) {
|
|
226
|
+
throw new Error(`No migrations were ever executed!`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Since we don't store migration descriptions to DB, we need to fetch them from actual migration objects.
|
|
230
|
+
const withDescriptions = lastRun.migrations.map(mig => {
|
|
231
|
+
const dataMigration = this.migrations.find(dm => dm.getId() === mig.id);
|
|
232
|
+
return {
|
|
233
|
+
...mig,
|
|
234
|
+
description: dataMigration ? dataMigration.getDescription() : "N/A"
|
|
235
|
+
};
|
|
236
|
+
});
|
|
130
237
|
return {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
notApplicable
|
|
238
|
+
...lastRun,
|
|
239
|
+
migrations: withDescriptions
|
|
134
240
|
};
|
|
135
241
|
}
|
|
136
242
|
validateIds(migrations) {
|
|
@@ -150,11 +256,86 @@ class MigrationRunner {
|
|
|
150
256
|
ids.add(id);
|
|
151
257
|
}
|
|
152
258
|
}
|
|
259
|
+
async createCheckpoint(migration, checkpoint) {
|
|
260
|
+
this.logger.info(checkpoint, `Saving checkpoint ${migration.getId()}`);
|
|
261
|
+
const execute = () => this.repository.createCheckpoint(migration.getId(), checkpoint);
|
|
262
|
+
await (0, _utils.executeWithRetry)(execute);
|
|
263
|
+
}
|
|
264
|
+
async getOrCreateRun() {
|
|
265
|
+
const resolvedStatus = ["done", "error"];
|
|
266
|
+
const unresolvedStatus = ["init", "running"];
|
|
267
|
+
let lastRun = await this.repository.getLastRun();
|
|
268
|
+
if (lastRun && unresolvedStatus.includes(lastRun.status)) {
|
|
269
|
+
throw new MigrationInProgress(`Migration is already in progress (ID: ${lastRun.id})!`);
|
|
270
|
+
}
|
|
271
|
+
if (!lastRun || resolvedStatus.includes(lastRun.status)) {
|
|
272
|
+
lastRun = {
|
|
273
|
+
id: (0, _utils.mdbid)(),
|
|
274
|
+
status: "init",
|
|
275
|
+
startedOn: getCurrentISOTime(),
|
|
276
|
+
finishedOn: "",
|
|
277
|
+
migrations: [],
|
|
278
|
+
context: this.context
|
|
279
|
+
};
|
|
280
|
+
await this.repository.saveRun(lastRun);
|
|
281
|
+
}
|
|
282
|
+
return lastRun;
|
|
283
|
+
}
|
|
284
|
+
getOrCreateRunItem(run, migration) {
|
|
285
|
+
const existingItem = run.migrations.find(item => item.id === migration.getId());
|
|
286
|
+
if (existingItem) {
|
|
287
|
+
return {
|
|
288
|
+
...existingItem,
|
|
289
|
+
status: "running"
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
id: migration.getId(),
|
|
294
|
+
status: "running"
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
setRunItem(run, item) {
|
|
298
|
+
const index = run.migrations.findIndex(runItem => runItem.id === item.id);
|
|
299
|
+
if (index < 0) {
|
|
300
|
+
run.migrations.push(item);
|
|
301
|
+
} else {
|
|
302
|
+
run.migrations = [...run.migrations.slice(0, index), item, ...run.migrations.slice(index + 1)];
|
|
303
|
+
}
|
|
304
|
+
run.migrations = run.migrations.sort((a, b) => a.id > b.id ? 1 : -1);
|
|
305
|
+
}
|
|
306
|
+
async setRunItemAndSave(run, item) {
|
|
307
|
+
this.setRunItem(run, item);
|
|
308
|
+
await this.repository.saveRun(run);
|
|
309
|
+
}
|
|
310
|
+
printForceExecuteEnvVars() {
|
|
311
|
+
const forceKeys = Object.keys(process.env).filter(key => key.startsWith("WEBINY_MIGRATION_FORCE_EXECUTE_"));
|
|
312
|
+
if (!forceKeys.length) {
|
|
313
|
+
this.logger.info(`No migrations are enforced via WEBINY_MIGRATION_FORCE_EXECUTE environment variable.`);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
this.logger.info(`FORCED MIGRATIONS DETECTED!`);
|
|
317
|
+
for (const key of forceKeys) {
|
|
318
|
+
this.logger.info(`${key}=${process.env[key]}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
printSkipExecuteEnvVars() {
|
|
322
|
+
const skipKeys = Object.keys(process.env).filter(key => key.startsWith("WEBINY_MIGRATION_SKIP_"));
|
|
323
|
+
if (!skipKeys.length) {
|
|
324
|
+
this.logger.info(`No migrations are skipped via WEBINY_MIGRATION_SKIP environment variable.`);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
this.logger.info(`SKIPPED MIGRATIONS DETECTED!`);
|
|
328
|
+
for (const key of skipKeys) {
|
|
329
|
+
this.logger.info(`${key}=${process.env[key]}`);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
153
332
|
}
|
|
154
333
|
exports.MigrationRunner = MigrationRunner;
|
|
155
|
-
(0, _ioc.makeInjectable)(MigrationRunner, [(0, _ioc.inject)(_symbols.MigrationRepositorySymbol), (0, _ioc.inject)(_symbols.MigrationSymbol, {
|
|
334
|
+
(0, _ioc.makeInjectable)(MigrationRunner, [(0, _ioc.inject)(_symbols.MigrationRepositorySymbol), (0, _ioc.inject)(_symbols.ExecutionTimeLimiterSymbol), (0, _ioc.inject)(_symbols.MigrationSymbol, {
|
|
156
335
|
multi: true,
|
|
157
336
|
optional: true
|
|
158
337
|
}), (0, _ioc.inject)(_symbols.LoggerSymbol, {
|
|
159
338
|
optional: true
|
|
160
|
-
})]);
|
|
339
|
+
})]);
|
|
340
|
+
|
|
341
|
+
//# sourceMappingURL=MigrationRunner.js.map
|
package/MigrationRunner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["MigrationRunner","constructor","repository","migrations","logger","createPinoLogger","execute","projectVersion","isApplicable","validateIds","latestMigration","listMigrations","limit","info","currentVersion","coerce","startingId","id","lastId","logMigration","description","createdOn","Date","toISOString","duration","reason","executed","skipped","notApplicable","defaultIsApplicable","mig","getId","isMigrationApplicable","executableMigrations","filter","push","getDescription","sort","a","b","length","migration","getChildLogger","context","shouldExecute","result","logs","success","start","now","err","error","message","ids","Set","endsWith","Error","has","add","makeInjectable","inject","MigrationRepositorySymbol","MigrationSymbol","multi","optional","LoggerSymbol"],"sources":["MigrationRunner.ts"],"sourcesContent":["import { Logger } from \"pino\";\nimport { inject, makeInjectable } from \"@webiny/ioc\";\nimport { coerce } from \"semver\";\nimport { MigrationRepositorySymbol, LoggerSymbol, MigrationSymbol } from \"./symbols\";\nimport { createPinoLogger, getChildLogger } from \"./createPinoLogger\";\nimport {\n MigrationResult,\n ExecutedMigrationResponse,\n SkippedMigrationResponse,\n MigrationRepository,\n DataMigration,\n DataMigrationContext\n} from \"~/types\";\n\nexport type IsMigrationApplicable = (migration: DataMigration) => boolean;\n\nexport class MigrationRunner {\n private readonly logger: Logger;\n private readonly migrations: DataMigration[];\n private readonly repository: MigrationRepository;\n\n constructor(\n repository: MigrationRepository,\n migrations: DataMigration[],\n logger: Logger | undefined\n ) {\n this.repository = repository;\n this.migrations = migrations || [];\n\n if (!logger) {\n logger = createPinoLogger();\n }\n this.logger = logger;\n }\n\n async execute(projectVersion: string, isApplicable?: IsMigrationApplicable) {\n this.validateIds(this.migrations);\n const [latestMigration] = await this.repository.listMigrations({ limit: 1 });\n\n this.logger.info(`Project version is %s.`, projectVersion);\n\n // Get current version, and coerce it to a valid SemVer.\n // With this, we can run migrations targeted for stable versions, released under a preid tag (e.g., `beta`).\n const currentVersion = coerce(projectVersion) + \"\";\n const startingId = latestMigration ? latestMigration.id : `${currentVersion}-000`;\n const lastId = `${currentVersion}-999`;\n\n // Create initial migration record.\n if (!latestMigration) {\n this.logger.info(\n `No migrations were ever executed. Creating initial migration record %s.`,\n startingId\n );\n await this.repository.logMigration({\n id: startingId,\n description: \"starting point for applicable migrations detection\",\n createdOn: new Date().toISOString(),\n duration: 0,\n reason: \"initial migration\"\n });\n } else {\n this.logger.info(`Latest migration ID is %s.`, latestMigration.id);\n }\n\n if (isApplicable) {\n this.logger.info(`Using custom \"isApplicable\" function.`);\n } else {\n this.logger.info(`Using migrations in the range of %s to %s.`, startingId, lastId);\n }\n\n const executed: ExecutedMigrationResponse[] = [];\n const skipped: SkippedMigrationResponse[] = [];\n const notApplicable: SkippedMigrationResponse[] = [];\n\n const defaultIsApplicable: IsMigrationApplicable = mig => {\n return mig.getId() > startingId && mig.getId() <= lastId;\n };\n\n const isMigrationApplicable = isApplicable || defaultIsApplicable;\n\n const executableMigrations = this.migrations\n .filter(mig => {\n if (!isMigrationApplicable(mig)) {\n notApplicable.push({\n id: mig.getId(),\n description: mig.getDescription(),\n reason: \"not applicable\"\n });\n\n return false;\n }\n return true;\n })\n .sort((a, b) => (a.getId() > b.getId() ? 1 : -1));\n\n this.logger.info(`Found %s applicable migration(s).`, executableMigrations.length);\n\n for (const migration of executableMigrations) {\n const logger = getChildLogger(this.logger, migration);\n const context: DataMigrationContext = { projectVersion, logger };\n\n const shouldExecute = await migration.shouldExecute(context);\n\n if (!shouldExecute) {\n this.logger.info(`Skipping migration %s.`, migration.getId());\n skipped.push({\n id: migration.getId(),\n description: migration.getDescription(),\n reason: \"migration already applied\"\n });\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n createdOn: new Date().toISOString(),\n duration: 0,\n reason: \"skipped\"\n });\n\n continue;\n }\n\n const result: MigrationResult = {\n duration: 0,\n logs: [],\n success: true\n };\n\n const start = Date.now();\n try {\n this.logger.info(\n `Executing migration %s: %s.`,\n migration.getId(),\n migration.getDescription()\n );\n await migration.execute(context);\n } catch (err) {\n result.success = false;\n this.logger.error(err, err.message);\n } finally {\n result.duration = Date.now() - start;\n this.logger.info(\n `Finished executing migration %s in %sms.`,\n migration.getId(),\n result.duration\n );\n }\n\n executed.push({\n id: migration.getId(),\n description: migration.getDescription(),\n result\n });\n\n if (result.success) {\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n createdOn: new Date().toISOString(),\n duration: result.duration,\n reason: \"executed\"\n });\n }\n }\n\n this.logger.info(`Finished processing applicable migrations.`);\n\n return { executed, skipped, notApplicable };\n }\n\n private validateIds(migrations: DataMigration[]) {\n const ids = new Set();\n for (const mig of migrations) {\n const id = mig.getId();\n if (id.endsWith(\"-000\")) {\n const error = new Error(`Migration ID must not end with \"000\": ${id}`);\n this.logger.error(error);\n throw error;\n }\n\n if (ids.has(id)) {\n const error = new Error(`Duplicate migration ID found: ${id}`);\n this.logger.error(error);\n throw error;\n }\n ids.add(id);\n }\n }\n}\n\nmakeInjectable(MigrationRunner, [\n inject(MigrationRepositorySymbol),\n inject(MigrationSymbol, { multi: true, optional: true }),\n inject(LoggerSymbol, { optional: true })\n]);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["_semver","require","_ioc","_utils","_symbols","_createPinoLogger","getCurrentISOTime","Date","toISOString","getRunItemDuration","runItem","startedOn","finishedOn","getTime","shouldForceExecute","mig","key","getId","replace","process","env","shouldSkip","MigrationNotFinished","Error","MigrationInProgress","MigrationRunner","context","constructor","repository","timeLimiter","migrations","logger","createPinoLogger","setContext","execute","projectVersion","isApplicable","forceExecute","lastRun","getOrCreateRun","validateIds","err","status","error","message","saveRun","latestMigration","listMigrations","limit","info","currentVersion","coerce","startingId","id","lastId","logMigration","description","reason","defaultIsApplicable","isMigrationApplicable","printForceExecuteEnvVars","printSkipExecuteEnvVars","executableMigrations","filter","setRunItem","sort","a","b","length","shouldCreateCheckpoint","migration","getOrCreateRunItem","checkpoint","getCheckpoint","getChildLogger","runningOutOfTime","createCheckpoint","data","createCheckpointAndExit","shouldExecute","setRunItemAndSave","getDescription","name","stack","code","deleteCheckpoint","getStatus","getLastRun","withDescriptions","map","dataMigration","find","dm","ids","Set","endsWith","has","add","executeWithRetry","resolvedStatus","unresolvedStatus","includes","mdbid","run","existingItem","item","index","findIndex","push","slice","forceKeys","Object","keys","startsWith","skipKeys","exports","makeInjectable","inject","MigrationRepositorySymbol","ExecutionTimeLimiterSymbol","MigrationSymbol","multi","optional","LoggerSymbol"],"sources":["MigrationRunner.ts"],"sourcesContent":["import { coerce } from \"semver\";\nimport type { Logger } from \"@webiny/logger\";\nimport { inject, makeInjectable } from \"@webiny/ioc\";\nimport { executeWithRetry, mdbid } from \"@webiny/utils\";\nimport {\n MigrationRepositorySymbol,\n LoggerSymbol,\n MigrationSymbol,\n ExecutionTimeLimiterSymbol\n} from \"./symbols\";\nimport { createPinoLogger, getChildLogger } from \"./createPinoLogger\";\nimport type {\n MigrationRepository,\n DataMigration,\n DataMigrationContext,\n ExecutionTimeLimiter,\n MigrationRun,\n MigrationStatus,\n MigrationRunItem\n} from \"~/types\";\n\nexport type IsMigrationApplicable = (migration: DataMigration) => boolean;\n\nconst getCurrentISOTime = () => {\n return new Date().toISOString();\n};\n\nconst getRunItemDuration = (runItem: MigrationRunItem) => {\n if (!runItem.startedOn || !runItem.finishedOn) {\n return \"N/A\";\n }\n\n return new Date(runItem.finishedOn).getTime() - new Date(runItem.startedOn).getTime();\n};\n\n/**\n * This allows us to force-execute a migration, even if it's not in the list of the applicable migrations.\n * Example: WEBINY_MIGRATION_FORCE_EXECUTE_5_35_0_006=true\n */\nconst shouldForceExecute = (mig: DataMigration) => {\n const key = `WEBINY_MIGRATION_FORCE_EXECUTE_${mig.getId().replace(/[\\.\\-]/g, \"_\")}`;\n\n return process.env[key] === \"true\";\n};\n\n/**\n * This allows us to always skip a migration.\n * Example: WEBINY_MIGRATION_SKIP_5_35_0_006=true\n */\nconst shouldSkip = (mig: DataMigration) => {\n const key = `WEBINY_MIGRATION_SKIP_${mig.getId().replace(/[\\.\\-]/g, \"_\")}`;\n\n return process.env[key] === \"true\";\n};\n\nclass MigrationNotFinished extends Error {}\nclass MigrationInProgress extends Error {}\n\nexport class MigrationRunner {\n private readonly logger: Logger;\n private readonly migrations: DataMigration[];\n private readonly repository: MigrationRepository;\n private readonly timeLimiter: ExecutionTimeLimiter;\n private context: Record<string, any> = {};\n\n constructor(\n repository: MigrationRepository,\n timeLimiter: ExecutionTimeLimiter,\n migrations: DataMigration[],\n logger: Logger | undefined\n ) {\n this.repository = repository;\n this.timeLimiter = timeLimiter;\n this.migrations = migrations || [];\n\n if (!logger) {\n logger = createPinoLogger();\n }\n this.logger = logger;\n }\n\n setContext(context: Record<string, any>) {\n this.context = context;\n }\n\n async execute(\n projectVersion: string,\n isApplicable?: IsMigrationApplicable,\n // Force execute applicable migrations.\n forceExecute = false\n ) {\n const lastRun = await this.getOrCreateRun();\n\n try {\n this.validateIds(this.migrations);\n } catch (err) {\n lastRun.status = \"error\";\n lastRun.error = {\n message: err.message\n };\n await this.repository.saveRun(lastRun);\n return;\n }\n\n const [latestMigration] = await this.repository.listMigrations({ limit: 1 });\n\n this.logger.info(`Project version is %s.`, projectVersion);\n\n // Get current version, and coerce it to a valid SemVer.\n // With this, we can run migrations targeted for stable versions, released under a preid tag (e.g., `beta`).\n const currentVersion = coerce(projectVersion) + \"\";\n const startingId = latestMigration ? latestMigration.id : `${currentVersion}-000`;\n const lastId = `${currentVersion}-999`;\n\n // Create initial migration record.\n if (!latestMigration) {\n this.logger.info(\n `No migrations were ever executed. Creating initial migration record %s.`,\n startingId\n );\n await this.repository.logMigration({\n id: startingId,\n description: \"starting point for applicable migrations detection\",\n startedOn: getCurrentISOTime(),\n finishedOn: getCurrentISOTime(),\n reason: \"initial migration\"\n });\n } else {\n this.logger.info(`Latest migration ID is %s.`, latestMigration.id);\n }\n\n if (isApplicable) {\n this.logger.info(`Using custom \"isApplicable\" function.`);\n } else {\n this.logger.info(`Using migrations in the range of %s to %s.`, startingId, lastId);\n }\n\n const defaultIsApplicable: IsMigrationApplicable = mig => {\n return mig.getId() > startingId && mig.getId() <= lastId;\n };\n\n const isMigrationApplicable = isApplicable || defaultIsApplicable;\n\n this.printForceExecuteEnvVars();\n this.printSkipExecuteEnvVars();\n\n if (forceExecute) {\n this.logger.info(\n `ALL APPLICABLE MIGRATIONS WILL BE FORCE-EXECUTED! (via --force flag)`\n );\n }\n\n const executableMigrations = this.migrations\n .filter(mig => {\n if (shouldSkip(mig)) {\n this.setRunItem(lastRun, {\n id: mig.getId(),\n status: \"skipped\"\n });\n\n return false;\n }\n\n if (shouldForceExecute(mig)) {\n return true;\n }\n\n if (!isMigrationApplicable(mig)) {\n this.setRunItem(lastRun, {\n id: mig.getId(),\n status: \"not-applicable\"\n });\n\n return false;\n }\n return true;\n })\n .sort((a, b) => (a.getId() > b.getId() ? 1 : -1));\n\n this.logger.info(\n `Found %s applicable out of %s available migration(s).`,\n executableMigrations.length,\n this.migrations.length\n );\n\n // Are we're within the last 2 minutes of the execution time limit?\n const shouldCreateCheckpoint = () => {\n return this.timeLimiter() < 120000;\n };\n\n //\n for (const migration of executableMigrations) {\n const runItem = this.getOrCreateRunItem(lastRun, migration);\n const checkpoint = await this.repository.getCheckpoint(migration.getId());\n const logger = getChildLogger(this.logger, migration);\n\n if (checkpoint) {\n this.logger.info(checkpoint, `Found checkpoint ${migration.getId()}.`);\n }\n\n const context: DataMigrationContext = {\n projectVersion,\n logger,\n checkpoint,\n forceExecute: forceExecute || shouldForceExecute(migration),\n runningOutOfTime: shouldCreateCheckpoint,\n createCheckpoint: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n },\n createCheckpointAndExit: async (data: unknown) => {\n await this.createCheckpoint(migration, data);\n // We throw an error to break out of the migration execution completely.\n throw new MigrationNotFinished();\n }\n };\n try {\n const shouldExecute =\n checkpoint || context.forceExecute\n ? true\n : await migration.shouldExecute(context);\n\n if (!shouldExecute) {\n this.logger.info(`Skipping migration %s.`, migration.getId());\n runItem.status = \"skipped\";\n\n await this.setRunItemAndSave(lastRun, runItem);\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n reason: \"skipped\"\n });\n\n continue;\n }\n\n lastRun.status = \"running\";\n runItem.status = \"running\";\n if (!runItem.startedOn) {\n runItem.startedOn = getCurrentISOTime();\n }\n await this.setRunItemAndSave(lastRun, runItem);\n this.logger.info(\n `Executing migration %s: %s`,\n migration.getId(),\n migration.getDescription()\n );\n await migration.execute(context);\n runItem.status = \"done\";\n } catch (err) {\n // If `MigrationNotFinished` was thrown, we will need to resume the migration.\n if (err instanceof MigrationNotFinished) {\n lastRun.status = \"pending\";\n runItem.status = \"pending\";\n return;\n }\n\n runItem.status = \"error\";\n lastRun.status = \"error\";\n lastRun.error = {\n name: err.name || \"Migration error\",\n message: err.message,\n stack: err.stack,\n data: err.data,\n code: err.code\n };\n this.logger.error(err, err.message);\n return;\n } finally {\n runItem.finishedOn = getCurrentISOTime();\n\n // Update run stats.\n await this.setRunItemAndSave(lastRun, runItem);\n\n if (runItem.status === \"pending\") {\n this.logger.info(\n `Pausing migration %s, awaiting continuation.`,\n migration.getId()\n );\n } else {\n this.logger.info(\n `Finished executing migration %s in %sms.`,\n migration.getId(),\n getRunItemDuration(runItem)\n );\n }\n }\n\n await this.repository.logMigration({\n id: migration.getId(),\n description: migration.getDescription(),\n startedOn: runItem.startedOn,\n finishedOn: runItem.finishedOn,\n reason: \"executed\"\n });\n\n this.logger.info(`Deleting checkpoint ${migration.getId()}.`);\n await this.repository.deleteCheckpoint(migration.getId());\n }\n\n lastRun.status = \"done\";\n lastRun.finishedOn = getCurrentISOTime();\n await this.repository.saveRun(lastRun);\n\n this.logger.info(`Finished processing applicable migrations.`);\n }\n\n async getStatus(): Promise<MigrationStatus> {\n const lastRun = await this.repository.getLastRun();\n if (!lastRun) {\n throw new Error(`No migrations were ever executed!`);\n }\n\n // Since we don't store migration descriptions to DB, we need to fetch them from actual migration objects.\n const withDescriptions = lastRun.migrations.map(mig => {\n const dataMigration = this.migrations.find(dm => dm.getId() === mig.id);\n return {\n ...mig,\n description: dataMigration ? dataMigration.getDescription() : \"N/A\"\n };\n });\n\n return { ...lastRun, migrations: withDescriptions };\n }\n\n private validateIds(migrations: DataMigration[]) {\n const ids = new Set();\n for (const mig of migrations) {\n const id = mig.getId();\n if (id.endsWith(\"-000\")) {\n const error = new Error(`Migration ID must not end with \"000\": ${id}`);\n this.logger.error(error);\n throw error;\n }\n\n if (ids.has(id)) {\n const error = new Error(`Duplicate migration ID found: ${id}`);\n this.logger.error(error);\n throw error;\n }\n ids.add(id);\n }\n }\n\n private async createCheckpoint(migration: DataMigration, checkpoint: unknown) {\n this.logger.info(checkpoint, `Saving checkpoint ${migration.getId()}`);\n const execute = () => this.repository.createCheckpoint(migration.getId(), checkpoint);\n await executeWithRetry(execute);\n }\n\n private async getOrCreateRun() {\n const resolvedStatus: Array<MigrationRun[\"status\"]> = [\"done\", \"error\"];\n const unresolvedStatus: Array<MigrationRun[\"status\"]> = [\"init\", \"running\"];\n\n let lastRun = await this.repository.getLastRun();\n\n if (lastRun && unresolvedStatus.includes(lastRun.status)) {\n throw new MigrationInProgress(`Migration is already in progress (ID: ${lastRun.id})!`);\n }\n\n if (!lastRun || resolvedStatus.includes(lastRun.status)) {\n lastRun = {\n id: mdbid(),\n status: \"init\",\n startedOn: getCurrentISOTime(),\n finishedOn: \"\",\n migrations: [],\n context: this.context\n };\n\n await this.repository.saveRun(lastRun);\n }\n\n return lastRun;\n }\n\n private getOrCreateRunItem(run: MigrationRun, migration: DataMigration): MigrationRunItem {\n const existingItem = run.migrations.find(item => item.id === migration.getId());\n if (existingItem) {\n return {\n ...existingItem,\n status: \"running\"\n };\n }\n\n return {\n id: migration.getId(),\n status: \"running\"\n };\n }\n\n private setRunItem(run: MigrationRun, item: MigrationRunItem) {\n const index = run.migrations.findIndex(runItem => runItem.id === item.id);\n if (index < 0) {\n run.migrations.push(item);\n } else {\n run.migrations = [\n ...run.migrations.slice(0, index),\n item,\n ...run.migrations.slice(index + 1)\n ];\n }\n\n run.migrations = run.migrations.sort((a, b) => (a.id > b.id ? 1 : -1));\n }\n\n private async setRunItemAndSave(run: MigrationRun, item: MigrationRunItem) {\n this.setRunItem(run, item);\n await this.repository.saveRun(run);\n }\n\n private printForceExecuteEnvVars() {\n const forceKeys = Object.keys(process.env).filter(key =>\n key.startsWith(\"WEBINY_MIGRATION_FORCE_EXECUTE_\")\n );\n\n if (!forceKeys.length) {\n this.logger.info(\n `No migrations are enforced via WEBINY_MIGRATION_FORCE_EXECUTE environment variable.`\n );\n\n return;\n }\n\n this.logger.info(`FORCED MIGRATIONS DETECTED!`);\n for (const key of forceKeys) {\n this.logger.info(`${key}=${process.env[key]}`);\n }\n }\n\n private printSkipExecuteEnvVars() {\n const skipKeys = Object.keys(process.env).filter(key =>\n key.startsWith(\"WEBINY_MIGRATION_SKIP_\")\n );\n\n if (!skipKeys.length) {\n this.logger.info(\n `No migrations are skipped via WEBINY_MIGRATION_SKIP environment variable.`\n );\n\n return;\n }\n\n this.logger.info(`SKIPPED MIGRATIONS DETECTED!`);\n for (const key of skipKeys) {\n this.logger.info(`${key}=${process.env[key]}`);\n }\n }\n}\n\nmakeInjectable(MigrationRunner, [\n inject(MigrationRepositorySymbol),\n inject(ExecutionTimeLimiterSymbol),\n inject(MigrationSymbol, { multi: true, optional: true }),\n inject(LoggerSymbol, { optional: true })\n]);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MigrationRunnerResult, MigrationRunReporter } from "./";
|
|
2
|
+
import type { CliContext } from "@webiny/cli/types";
|
|
3
|
+
import type { LogReporter } from "./";
|
|
4
|
+
export declare class CliMigrationRunReporter implements MigrationRunReporter {
|
|
5
|
+
private context;
|
|
6
|
+
private logReporter;
|
|
7
|
+
constructor(logReporter: LogReporter, context: CliContext);
|
|
8
|
+
report(result: MigrationRunnerResult): Promise<void>;
|
|
9
|
+
private makeEven;
|
|
10
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.CliMigrationRunReporter = void 0;
|
|
8
|
+
var _centerAlign = _interopRequireDefault(require("center-align"));
|
|
9
|
+
class CliMigrationRunReporter {
|
|
10
|
+
constructor(logReporter, context) {
|
|
11
|
+
this.logReporter = logReporter;
|
|
12
|
+
this.context = context;
|
|
13
|
+
}
|
|
14
|
+
report(result) {
|
|
15
|
+
result.onSuccess(data => {
|
|
16
|
+
const functionName = result.getFunctionName().split(":").pop();
|
|
17
|
+
process.stdout.write("\n");
|
|
18
|
+
this.context.success(`Data migration Lambda %s executed successfully!`, functionName);
|
|
19
|
+
const {
|
|
20
|
+
migrations,
|
|
21
|
+
...run
|
|
22
|
+
} = data;
|
|
23
|
+
if (!migrations.length) {
|
|
24
|
+
this.context.info(`No applicable migrations were found!`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const maxLength = Math.max(...migrations.map(mig => mig.status.length)) + 2;
|
|
28
|
+
this.context.info(`Migration run: %s`, run.id);
|
|
29
|
+
this.context.info(`Status: %s`, run.status);
|
|
30
|
+
this.context.info(`Started on: %s`, run.startedOn);
|
|
31
|
+
if (run.status === "done") {
|
|
32
|
+
this.context.info(`Finished on: %s`, run.finishedOn);
|
|
33
|
+
}
|
|
34
|
+
for (const migration of migrations) {
|
|
35
|
+
this.context.info(...[`[%s] %s: ${migration.description}`, (0, _centerAlign.default)(this.makeEven(migration.status), maxLength), migration.id]);
|
|
36
|
+
}
|
|
37
|
+
this.logReporter.printLogStreamLinks();
|
|
38
|
+
});
|
|
39
|
+
result.onError(error => {
|
|
40
|
+
this.context.error(error.message);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Process the result!
|
|
44
|
+
return result.process();
|
|
45
|
+
}
|
|
46
|
+
makeEven(str) {
|
|
47
|
+
if (str.length % 2 > 0) {
|
|
48
|
+
return str + " ";
|
|
49
|
+
}
|
|
50
|
+
return str;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.CliMigrationRunReporter = CliMigrationRunReporter;
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=CliMigrationRunReporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_centerAlign","_interopRequireDefault","require","CliMigrationRunReporter","constructor","logReporter","context","report","result","onSuccess","data","functionName","getFunctionName","split","pop","process","stdout","write","success","migrations","run","length","info","maxLength","Math","max","map","mig","status","id","startedOn","finishedOn","migration","description","center","makeEven","printLogStreamLinks","onError","error","message","str","exports"],"sources":["CliMigrationRunReporter.ts"],"sourcesContent":["import type { MigrationRunnerResult, MigrationRunReporter } from \"~/cli\";\nimport center from \"center-align\";\nimport type { CliContext } from \"@webiny/cli/types\";\nimport type { LogReporter } from \"~/cli\";\n\nexport class CliMigrationRunReporter implements MigrationRunReporter {\n private context: CliContext;\n private logReporter: LogReporter;\n\n constructor(logReporter: LogReporter, context: CliContext) {\n this.logReporter = logReporter;\n this.context = context;\n }\n\n report(result: MigrationRunnerResult): Promise<void> {\n result.onSuccess(data => {\n const functionName = result.getFunctionName().split(\":\").pop();\n process.stdout.write(\"\\n\");\n this.context.success(`Data migration Lambda %s executed successfully!`, functionName);\n\n const { migrations, ...run } = data;\n if (!migrations.length) {\n this.context.info(`No applicable migrations were found!`);\n return;\n }\n\n const maxLength = Math.max(...migrations.map(mig => mig.status.length)) + 2;\n this.context.info(`Migration run: %s`, run.id);\n this.context.info(`Status: %s`, run.status);\n this.context.info(`Started on: %s`, run.startedOn);\n if (run.status === \"done\") {\n this.context.info(`Finished on: %s`, run.finishedOn);\n }\n for (const migration of migrations) {\n this.context.info(\n ...[\n `[%s] %s: ${migration.description}`,\n center(this.makeEven(migration.status), maxLength),\n migration.id\n ]\n );\n }\n\n this.logReporter.printLogStreamLinks();\n });\n\n result.onError(error => {\n this.context.error(error.message);\n });\n\n // Process the result!\n return result.process();\n }\n\n private makeEven(str: string) {\n if (str.length % 2 > 0) {\n return str + \" \";\n }\n return str;\n }\n}\n"],"mappings":";;;;;;;AACA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAIO,MAAMC,uBAAuB,CAAiC;EAIjEC,WAAWA,CAACC,WAAwB,EAAEC,OAAmB,EAAE;IACvD,IAAI,CAACD,WAAW,GAAGA,WAAW;IAC9B,IAAI,CAACC,OAAO,GAAGA,OAAO;EAC1B;EAEAC,MAAMA,CAACC,MAA6B,EAAiB;IACjDA,MAAM,CAACC,SAAS,CAACC,IAAI,IAAI;MACrB,MAAMC,YAAY,GAAGH,MAAM,CAACI,eAAe,CAAC,CAAC,CAACC,KAAK,CAAC,GAAG,CAAC,CAACC,GAAG,CAAC,CAAC;MAC9DC,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC,IAAI,CAAC;MAC1B,IAAI,CAACX,OAAO,CAACY,OAAO,CAAC,iDAAiD,EAAEP,YAAY,CAAC;MAErF,MAAM;QAAEQ,UAAU;QAAE,GAAGC;MAAI,CAAC,GAAGV,IAAI;MACnC,IAAI,CAACS,UAAU,CAACE,MAAM,EAAE;QACpB,IAAI,CAACf,OAAO,CAACgB,IAAI,CAAC,sCAAsC,CAAC;QACzD;MACJ;MAEA,MAAMC,SAAS,GAAGC,IAAI,CAACC,GAAG,CAAC,GAAGN,UAAU,CAACO,GAAG,CAACC,GAAG,IAAIA,GAAG,CAACC,MAAM,CAACP,MAAM,CAAC,CAAC,GAAG,CAAC;MAC3E,IAAI,CAACf,OAAO,CAACgB,IAAI,CAAC,mBAAmB,EAAEF,GAAG,CAACS,EAAE,CAAC;MAC9C,IAAI,CAACvB,OAAO,CAACgB,IAAI,CAAC,YAAY,EAAEF,GAAG,CAACQ,MAAM,CAAC;MAC3C,IAAI,CAACtB,OAAO,CAACgB,IAAI,CAAC,gBAAgB,EAAEF,GAAG,CAACU,SAAS,CAAC;MAClD,IAAIV,GAAG,CAACQ,MAAM,KAAK,MAAM,EAAE;QACvB,IAAI,CAACtB,OAAO,CAACgB,IAAI,CAAC,iBAAiB,EAAEF,GAAG,CAACW,UAAU,CAAC;MACxD;MACA,KAAK,MAAMC,SAAS,IAAIb,UAAU,EAAE;QAChC,IAAI,CAACb,OAAO,CAACgB,IAAI,CACb,GAAG,CACC,YAAYU,SAAS,CAACC,WAAW,EAAE,EACnC,IAAAC,oBAAM,EAAC,IAAI,CAACC,QAAQ,CAACH,SAAS,CAACJ,MAAM,CAAC,EAAEL,SAAS,CAAC,EAClDS,SAAS,CAACH,EAAE,CAEpB,CAAC;MACL;MAEA,IAAI,CAACxB,WAAW,CAAC+B,mBAAmB,CAAC,CAAC;IAC1C,CAAC,CAAC;IAEF5B,MAAM,CAAC6B,OAAO,CAACC,KAAK,IAAI;MACpB,IAAI,CAAChC,OAAO,CAACgC,KAAK,CAACA,KAAK,CAACC,OAAO,CAAC;IACrC,CAAC,CAAC;;IAEF;IACA,OAAO/B,MAAM,CAACO,OAAO,CAAC,CAAC;EAC3B;EAEQoB,QAAQA,CAACK,GAAW,EAAE;IAC1B,IAAIA,GAAG,CAACnB,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE;MACpB,OAAOmB,GAAG,GAAG,GAAG;IACpB;IACA,OAAOA,GAAG;EACd;AACJ;AAACC,OAAA,CAAAtC,uBAAA,GAAAA,uBAAA","ignoreList":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { MigrationStatusReporter } from "./MigrationStatusReporter";
|
|
2
|
+
import type { MigrationStatus } from "../types";
|
|
3
|
+
import type { LogReporter } from "./LogReporter";
|
|
4
|
+
export declare class InteractiveCliStatusReporter implements MigrationStatusReporter {
|
|
5
|
+
private logReporter;
|
|
6
|
+
private firstCall;
|
|
7
|
+
constructor(logReporter: LogReporter);
|
|
8
|
+
report(migrationStatus: MigrationStatus): Promise<void>;
|
|
9
|
+
private clearLine;
|
|
10
|
+
private getDuration;
|
|
11
|
+
}
|