@oliasoft-open-source/node-json-migrator 2.3.10 → 3.0.0-beta-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/dist/index.cjs +16553 -0
- package/dist/index.d.cts +81 -0
- package/dist/index.d.mts +81 -0
- package/dist/index.mjs +16526 -0
- package/package.json +51 -57
- package/dist/create/create.js +0 -76
- package/dist/database/database.js +0 -102
- package/dist/executed/executed.js +0 -68
- package/dist/git/git.js +0 -130
- package/dist/glob/glob.js +0 -58
- package/dist/hash/hash.js +0 -16
- package/dist/history/history.js +0 -90
- package/dist/index.js +0 -54
- package/dist/migrate/migrate.js +0 -59
- package/dist/pending/pending.js +0 -73
- package/dist/pipe/pipe.js +0 -38
- package/dist/plan/cached-planned-version.js +0 -25
- package/dist/plan/plan.js +0 -274
- package/dist/plan/plan.schema.json +0 -20
- package/dist/plan/planned-version.js +0 -26
- package/dist/plan/validator.js +0 -216
package/dist/plan/validator.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.warnIfFilesHaveBeenRemovedFromPlan = exports.validatePlan = exports.validateFileName = exports.validateFileDescription = exports.throwIfSequenceNotUnique = exports.throwIfSequenceHasIntegerGaps = exports.throwIfSequenceHasChanged = exports.throwIfFilesNotFound = exports.throwIfFilesHaveChanged = exports.throwIfFileNamesNotUnique = exports.throwIfFileNamesInvalid = void 0;
|
|
7
|
-
var _chalk = _interopRequireDefault(require("chalk"));
|
|
8
|
-
var _lodash = require("lodash");
|
|
9
|
-
var _ajv = _interopRequireDefault(require("ajv"));
|
|
10
|
-
var _ajvErrors = _interopRequireDefault(require("ajv-errors"));
|
|
11
|
-
var _planSchema = _interopRequireDefault(require("./plan.schema.json"));
|
|
12
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
-
const isNonEmptyString = input => (0, _lodash.isString)(input) && input.length > 0;
|
|
14
|
-
const ajv = new _ajv.default({
|
|
15
|
-
allErrors: true
|
|
16
|
-
});
|
|
17
|
-
(0, _ajvErrors.default)(ajv);
|
|
18
|
-
|
|
19
|
-
//sequence pattern: https://regex101.com/r/4qHZLm/1
|
|
20
|
-
const planValidator = ajv.compile(_planSchema.default);
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Validates if a plan matches the schema
|
|
24
|
-
*
|
|
25
|
-
* @param {Array<Object>} plan
|
|
26
|
-
* @returns {Boolean} valid
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
const validatePlan = plan => {
|
|
30
|
-
const valid = planValidator(plan);
|
|
31
|
-
const {
|
|
32
|
-
errors
|
|
33
|
-
} = planValidator;
|
|
34
|
-
if (errors?.length) {
|
|
35
|
-
errors.forEach(e => console.error(`${e.message}${e.instancePath ? `at ${e.instancePath}` : ''}`));
|
|
36
|
-
}
|
|
37
|
-
return valid;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Validates if file description format is valid
|
|
42
|
-
*
|
|
43
|
-
* @param {String} description
|
|
44
|
-
* @returns {Boolean} valid
|
|
45
|
-
*/
|
|
46
|
-
exports.validatePlan = validatePlan;
|
|
47
|
-
const validateFileDescription = description => {
|
|
48
|
-
if (!description) {
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
//https://regex101.com/r/IO0dzF/1
|
|
52
|
-
const validFileName = /^([a-z]+|(([a-z]+-)+[a-z]+))$/g;
|
|
53
|
-
return validFileName.test(description);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validates if fileName format is valid
|
|
58
|
-
*
|
|
59
|
-
* @param {String} fileName
|
|
60
|
-
* @returns {Boolean} valid
|
|
61
|
-
*/
|
|
62
|
-
exports.validateFileDescription = validateFileDescription;
|
|
63
|
-
const validateFileName = fileName => {
|
|
64
|
-
//https://regex101.com/r/EX2RlS/1
|
|
65
|
-
const validFileName = /^([a-z]+|(([a-z]+-)+[a-z]+))(.js|.skip.js)$/g;
|
|
66
|
-
return validFileName.test(fileName);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Throws if file names are invalid
|
|
71
|
-
*
|
|
72
|
-
* @param {Array<Object>} migrationEntries
|
|
73
|
-
*/
|
|
74
|
-
exports.validateFileName = validateFileName;
|
|
75
|
-
const throwIfFileNamesInvalid = fileEntries => {
|
|
76
|
-
const invalidFileNames = fileEntries.filter(f => !f.isValidFileName).map(f => f.fileName);
|
|
77
|
-
if (invalidFileNames.length) {
|
|
78
|
-
invalidFileNames.forEach(name => console.error(_chalk.default.red(name)));
|
|
79
|
-
throw new Error('Invalid migration filename format (use kebab-case)');
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Warns if files have been removed
|
|
85
|
-
*
|
|
86
|
-
* @param {Array<Object>} migrationEntries
|
|
87
|
-
* @param {Array<Object>} historicalMigrations
|
|
88
|
-
*/
|
|
89
|
-
exports.throwIfFileNamesInvalid = throwIfFileNamesInvalid;
|
|
90
|
-
const warnIfFilesHaveBeenRemovedFromPlan = (migrationEntries, historicalMigrations) => {
|
|
91
|
-
const fileNames = migrationEntries.map(f => f.fileName);
|
|
92
|
-
const deletedFilesNames = historicalMigrations.filter(e => !fileNames.includes(e.fileName)).map(e => e.fileName);
|
|
93
|
-
if (deletedFilesNames.length) {
|
|
94
|
-
deletedFilesNames.forEach(name => console.warn(_chalk.default.yellow(name)));
|
|
95
|
-
console.warn(_chalk.default.yellow('Previously executed migration files have been deleted from plan.json (rename file to .skip.js and replace with a new file instead)'));
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Throws error if any pre-existing file has changed
|
|
101
|
-
*
|
|
102
|
-
* @param {Array<Object>} migrationEntries
|
|
103
|
-
*/
|
|
104
|
-
exports.warnIfFilesHaveBeenRemovedFromPlan = warnIfFilesHaveBeenRemovedFromPlan;
|
|
105
|
-
const throwIfFilesHaveChanged = migrationEntries => {
|
|
106
|
-
const changedFilesNames = migrationEntries.filter(m => {
|
|
107
|
-
const {
|
|
108
|
-
fileHash,
|
|
109
|
-
fileHashFromPlan,
|
|
110
|
-
fileHashFromHistory,
|
|
111
|
-
skippedFileHashes
|
|
112
|
-
} = m;
|
|
113
|
-
const matchesHistory = !isNonEmptyString(fileHashFromHistory) || [fileHash].concat(skippedFileHashes).includes(fileHashFromHistory);
|
|
114
|
-
const matchesPlan = !isNonEmptyString(fileHashFromPlan) || [fileHash].concat(skippedFileHashes).includes(fileHashFromPlan);
|
|
115
|
-
return !(matchesHistory && matchesPlan);
|
|
116
|
-
}).map(f => f.fileName);
|
|
117
|
-
if (changedFilesNames.length) {
|
|
118
|
-
changedFilesNames.forEach(name => console.error(_chalk.default.red(name)));
|
|
119
|
-
throw new Error('Not allowed to change migration files (for unreleased local work, you can use the `force` option)');
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Throws error if previous sequence numbers have changed
|
|
125
|
-
*
|
|
126
|
-
* @param {Array<Object>} migrationEntries
|
|
127
|
-
*/
|
|
128
|
-
exports.throwIfFilesHaveChanged = throwIfFilesHaveChanged;
|
|
129
|
-
const throwIfSequenceHasChanged = migrationEntries => {
|
|
130
|
-
const changeSequences = migrationEntries.filter(m => {
|
|
131
|
-
const {
|
|
132
|
-
sequence,
|
|
133
|
-
sequenceFromHistory
|
|
134
|
-
} = m;
|
|
135
|
-
const changed = (0, _lodash.isString)(sequenceFromHistory) && sequenceFromHistory !== sequence;
|
|
136
|
-
return changed;
|
|
137
|
-
}).map(f => f.fileName);
|
|
138
|
-
if (changeSequences.length) {
|
|
139
|
-
changeSequences.forEach(name => console.error(_chalk.default.red(name)));
|
|
140
|
-
throw new Error('Not allowed to change migration sequences in plan.json');
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Throws error if sequence numbers are not unique
|
|
146
|
-
*
|
|
147
|
-
* @param {Array<Object>} migrationEntries
|
|
148
|
-
*/
|
|
149
|
-
exports.throwIfSequenceHasChanged = throwIfSequenceHasChanged;
|
|
150
|
-
const throwIfSequenceNotUnique = migrationEntries => {
|
|
151
|
-
const sequenceNumbers = migrationEntries.map(f => f.sequence);
|
|
152
|
-
const repeatedSequenceNumbers = sequenceNumbers.filter(
|
|
153
|
-
//https://stackoverflow.com/a/59517965/942635
|
|
154
|
-
(s => v => s.has(v) || !s.add(v))(new Set()));
|
|
155
|
-
const duplicates = migrationEntries.filter(f => repeatedSequenceNumbers.includes(f.sequence)).map(f => f.fileName);
|
|
156
|
-
if (duplicates.length) {
|
|
157
|
-
duplicates.forEach(fileName => console.error(_chalk.default.red(fileName)));
|
|
158
|
-
throw new Error('Migrations must have unique sequence numbers in plan.json');
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Throws error if sequence numbers are not unique
|
|
164
|
-
*
|
|
165
|
-
* @param {Array<Object>} migrationEntries
|
|
166
|
-
*/
|
|
167
|
-
exports.throwIfSequenceNotUnique = throwIfSequenceNotUnique;
|
|
168
|
-
const throwIfSequenceHasIntegerGaps = migrationEntries => {
|
|
169
|
-
const toInteger = sequence => parseInt(sequence.split('.')[0], 10);
|
|
170
|
-
const unique = arr => Array.from(new Set(arr));
|
|
171
|
-
const sequences = migrationEntries.map(s => s.sequence);
|
|
172
|
-
const sequenceIntegers = sequences.map(s => toInteger(s));
|
|
173
|
-
const uniqueSequenceIntegers = unique(sequenceIntegers);
|
|
174
|
-
const orderedUniqueSequenceIntegers = uniqueSequenceIntegers.sort((a, b) => a - b);
|
|
175
|
-
const max = orderedUniqueSequenceIntegers[orderedUniqueSequenceIntegers.length - 1];
|
|
176
|
-
const expected = Array.from({
|
|
177
|
-
length: max
|
|
178
|
-
}, (v, k) => k + 1);
|
|
179
|
-
const missing = (0, _lodash.xor)(orderedUniqueSequenceIntegers, expected);
|
|
180
|
-
if (missing.length) {
|
|
181
|
-
throw new Error(`Migration sequence numbers in plan.json have unexpected gaps: ${missing.join(', ')}`);
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Throws error if file names are not unique
|
|
187
|
-
*
|
|
188
|
-
* @param {Array<Object>} migrationEntries
|
|
189
|
-
*/
|
|
190
|
-
exports.throwIfSequenceHasIntegerGaps = throwIfSequenceHasIntegerGaps;
|
|
191
|
-
const throwIfFileNamesNotUnique = migrationEntries => {
|
|
192
|
-
const fileNames = migrationEntries.map(f => f.fileName);
|
|
193
|
-
const repeatedFileNames = fileNames.filter(
|
|
194
|
-
//https://stackoverflow.com/a/59517965/942635
|
|
195
|
-
(s => v => s.has(v) || !s.add(v))(new Set()));
|
|
196
|
-
if (repeatedFileNames.length) {
|
|
197
|
-
repeatedFileNames.forEach(fileName => console.error(_chalk.default.red(fileName)));
|
|
198
|
-
throw new Error('Migration file names must be unique');
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Throws error if files listed in plan.json are found
|
|
204
|
-
*
|
|
205
|
-
* @param {Array<Object>} migrationEntries
|
|
206
|
-
* @param {Boolean} importModule
|
|
207
|
-
*/
|
|
208
|
-
exports.throwIfFileNamesNotUnique = throwIfFileNamesNotUnique;
|
|
209
|
-
const throwIfFilesNotFound = (migrationEntries, importModule) => {
|
|
210
|
-
const migrationsWithoutFiles = migrationEntries.filter(m => !m.script || importModule && !m.script && !m.migrator);
|
|
211
|
-
if (migrationsWithoutFiles.length) {
|
|
212
|
-
migrationsWithoutFiles.forEach(migration => console.error(_chalk.default.red(migration.fileName)));
|
|
213
|
-
throw new Error('Migration files from plan.json are missing from filesystem');
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
exports.throwIfFilesNotFound = throwIfFilesNotFound;
|