@oliasoft-open-source/node-json-migrator 2.2.0 → 2.3.0-beta-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.
@@ -4,19 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.createMigration = void 0;
7
-
8
7
  var _path = _interopRequireDefault(require("path"));
9
-
10
8
  var _fs = require("fs");
11
-
12
9
  var _chalk = _interopRequireDefault(require("chalk"));
13
-
14
10
  var _validator = require("../plan/validator");
15
-
16
11
  var _plan = require("../plan/plan");
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  const templateMigrationFile = `import produce from 'immer';
21
14
  //other imports not allowed
22
15
 
@@ -24,7 +17,6 @@ export default (dataset) => produce(dataset, (draft) => {
24
17
  // https://immerjs.github.io/immer/produce#example
25
18
  });
26
19
  `;
27
-
28
20
  const templateTestFile = fileName => `import migrate from './${fileName}';
29
21
 
30
22
  describe('describe dataset change', () => {
@@ -39,6 +31,7 @@ describe('describe dataset change', () => {
39
31
  });
40
32
  });
41
33
  `;
34
+
42
35
  /**
43
36
  * Generate a new dataset migration
44
37
  *
@@ -46,22 +39,16 @@ describe('describe dataset change', () => {
46
39
  * @param {String} description description of change-set / migration
47
40
  */
48
41
 
49
-
50
42
  const createMigration = async (directory, description) => {
51
43
  if (!(0, _validator.validateFileDescription)(description)) {
52
44
  throw new Error('Invalid migration description');
53
45
  }
54
-
55
46
  try {
56
47
  const directoryFullPath = _path.default.resolve(directory, description);
57
-
58
48
  const fileName = `${description}.js`;
59
49
  const testFileName = `${description}.test.js`;
60
-
61
50
  const filePath = _path.default.resolve(directoryFullPath, fileName);
62
-
63
51
  const testFilePath = _path.default.resolve(directoryFullPath, testFileName);
64
-
65
52
  await _fs.promises.mkdir(directoryFullPath, {
66
53
  recursive: true
67
54
  });
@@ -86,5 +73,4 @@ const createMigration = async (directory, description) => {
86
73
  throw new Error('Unable to create migration file');
87
74
  }
88
75
  };
89
-
90
76
  exports.createMigration = createMigration;
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.replaceMigrationsRecords = exports.migrationTablesExist = exports.insertVersions = exports.insertMigrationsRecords = exports.getVersions = exports.getPlanFromVersion = exports.getMigrationRecords = exports.createMigrationsTables = void 0;
7
-
8
7
  const migrationTablesExist = (db, entity) => {
9
8
  const query = `
10
9
  SELECT EXISTS (
@@ -15,9 +14,7 @@ const migrationTablesExist = (db, entity) => {
15
14
  `;
16
15
  return db.any(query);
17
16
  };
18
-
19
17
  exports.migrationTablesExist = migrationTablesExist;
20
-
21
18
  const createMigrationsTables = (db, entity) => {
22
19
  const query = `
23
20
  CREATE TABLE IF NOT EXISTS ${entity}_migrations (
@@ -36,9 +33,7 @@ const createMigrationsTables = (db, entity) => {
36
33
  `;
37
34
  return db.any(query);
38
35
  };
39
-
40
36
  exports.createMigrationsTables = createMigrationsTables;
41
-
42
37
  const getMigrationRecords = (db, entity) => {
43
38
  const query = `
44
39
  SELECT file_hash, file_name, sequence FROM ${entity}_migrations
@@ -50,9 +45,7 @@ const getMigrationRecords = (db, entity) => {
50
45
  sequence: r.sequence
51
46
  })));
52
47
  };
53
-
54
48
  exports.getMigrationRecords = getMigrationRecords;
55
-
56
49
  const insertMigrationsRecords = (db, pgpHelpers, entity, migrations) => {
57
50
  if (migrations.length) {
58
51
  const toInsert = migrations.map(m => ({
@@ -60,7 +53,6 @@ const insertMigrationsRecords = (db, pgpHelpers, entity, migrations) => {
60
53
  file_hash: m.fileHash,
61
54
  sequence: m.sequence
62
55
  })).filter(m => m.file_hash !== null); //can't insert null file hash
63
-
64
56
  const cs = new pgpHelpers.ColumnSet(['file_name', 'file_hash', 'sequence'], {
65
57
  table: `${entity}_migrations`
66
58
  });
@@ -69,9 +61,7 @@ const insertMigrationsRecords = (db, pgpHelpers, entity, migrations) => {
69
61
  return db.none(query);
70
62
  }
71
63
  };
72
-
73
64
  exports.insertMigrationsRecords = insertMigrationsRecords;
74
-
75
65
  const replaceMigrationsRecords = async (db, pgpHelpers, entity, migrations) => {
76
66
  /*
77
67
  OW-9043: Table is used for change detection/tracking. DELETE ALL not
@@ -82,9 +72,7 @@ const replaceMigrationsRecords = async (db, pgpHelpers, entity, migrations) => {
82
72
  await db.none(truncate);
83
73
  await insertMigrationsRecords(db, pgpHelpers, entity, migrations);
84
74
  };
85
-
86
75
  exports.replaceMigrationsRecords = replaceMigrationsRecords;
87
-
88
76
  const insertVersions = (db, pgpHelpers, entity, records) => {
89
77
  const cs = new pgpHelpers.ColumnSet(['version', 'plan'], {
90
78
  table: `${entity}_versions`
@@ -93,19 +81,15 @@ const insertVersions = (db, pgpHelpers, entity, records) => {
93
81
  const query = pgpHelpers.insert(records, cs) + onConflict;
94
82
  return db.none(query);
95
83
  };
96
-
97
84
  exports.insertVersions = insertVersions;
98
-
99
85
  const getPlanFromVersion = (db, entity, version) => {
100
86
  const query = `
101
87
  SELECT plan FROM ${entity}_versions
102
88
  WHERE version=$1;
103
89
  `;
104
- return db.oneOrNone(query, [version], r => (r === null || r === void 0 ? void 0 : r.plan) || null);
90
+ return db.oneOrNone(query, [version], r => r?.plan || null);
105
91
  };
106
-
107
92
  exports.getPlanFromVersion = getPlanFromVersion;
108
-
109
93
  const getVersions = async (db, entity) => {
110
94
  const query = `
111
95
  SELECT
@@ -115,5 +99,4 @@ const getVersions = async (db, entity) => {
115
99
  `;
116
100
  return db.any(query);
117
101
  };
118
-
119
102
  exports.getVersions = getVersions;
@@ -4,17 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getExecutedMigrationsFromVersion = void 0;
7
-
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _database = require("../database/database");
11
-
12
9
  var _validator = require("../plan/validator");
13
-
14
10
  var _git = require("../git/git");
15
-
16
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
-
18
12
  /**
19
13
  * Get the executed migrations for a given payload version
20
14
  *
@@ -27,43 +21,37 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
27
21
  * @param {Array<Object>} plannedMigrations planned migration entries
28
22
  * returns Promise<Array<Object>> executed migration entries
29
23
  */
24
+
30
25
  const getExecutedMigrationsFromVersion = async (database, pgpHelpers, entity, directory, currentVersion, plannedVersion, plannedMigrations) => {
31
26
  if (!currentVersion) {
32
27
  //when there is no current version, payload has never been migrated
33
28
  //so executed entries is empty
34
29
  return [];
35
30
  }
36
-
37
31
  if (currentVersion === plannedVersion) {
38
32
  //when planned version matches current version, there is nothing to migrate
39
33
  return plannedMigrations;
40
34
  } else {
41
35
  //otherwise we look up the historical plan file for that version from the DB
42
36
  let planFromVersion = await (0, _database.getPlanFromVersion)(database, entity, currentVersion);
43
-
44
37
  if (planFromVersion === null) {
45
- var _historicalPlans$find;
46
-
47
38
  //if not in database, try to get it from the git history
48
39
  console.warn(_chalk.default.yellow(`Version not found in ${entity}_version table, trying git history instead`));
49
40
  const planFilePath = `${directory}/plan.json`;
50
41
  const {
51
42
  historicalPlans
52
- } = await (0, _git.getHistoricalPlansFromGit)(planFilePath); //cache the response in the entity versions table
53
-
43
+ } = await (0, _git.getHistoricalPlansFromGit)(planFilePath);
44
+ //cache the response in the entity versions table
54
45
  await (0, _database.insertVersions)(database, pgpHelpers, entity, historicalPlans);
55
- planFromVersion = ((_historicalPlans$find = historicalPlans.find(p => p.version === currentVersion)) === null || _historicalPlans$find === void 0 ? void 0 : _historicalPlans$find.plan) || null;
46
+ planFromVersion = historicalPlans.find(p => p.version === currentVersion)?.plan || null;
56
47
  }
57
-
58
48
  if (planFromVersion !== null) {
59
49
  let migrationsFromHistory = null;
60
-
61
50
  try {
62
51
  migrationsFromHistory = JSON.parse(planFromVersion);
63
52
  } catch {
64
53
  throw new Error(`Invalid record in ${entity}_version table (cannot parse JSON)`);
65
54
  }
66
-
67
55
  if (!(0, _validator.validatePlan)(migrationsFromHistory)) {
68
56
  throw new Error(`Invalid plan in ${entity}_version table (does not match schema)`);
69
57
  } else {
@@ -74,5 +62,4 @@ const getExecutedMigrationsFromVersion = async (database, pgpHelpers, entity, di
74
62
  }
75
63
  }
76
64
  };
77
-
78
65
  exports.getExecutedMigrationsFromVersion = getExecutedMigrationsFromVersion;
package/dist/git/git.js CHANGED
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getPlanRevisionsFromGit = exports.getPlanFromGit = exports.getHistoricalPlansFromGit = exports.exec = void 0;
7
-
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _child_process = require("child_process");
11
-
12
9
  var _hash = require("../hash/hash");
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
11
  const exec = command => new Promise((resolve, reject) => {
17
12
  const args = ['-c', command];
18
13
  const thread = (0, _child_process.spawn)('bash', args, {
@@ -31,16 +26,13 @@ const exec = command => new Promise((resolve, reject) => {
31
26
  reject(stdErr.join(''));
32
27
  return;
33
28
  }
34
-
35
29
  resolve(stdOut.join(''));
36
30
  });
37
31
  });
38
-
39
32
  exports.exec = exec;
40
-
41
33
  const getPlanRevisionsFromGit = async planFilePath => {
42
34
  const stdOut = await exec(`git rev-list --pretty='format:%H|%ad' HEAD ${planFilePath}`);
43
- const lines = stdOut.split(/\r\n|\r|\n/).filter(r => r === null || r === void 0 ? void 0 : r.includes('|'));
35
+ const lines = stdOut.split(/\r\n|\r|\n/).filter(r => r?.includes('|'));
44
36
  return lines.map(line => {
45
37
  const [version, timeStamp] = line.split('|');
46
38
  const utcTimeStamp = new Date(timeStamp).toISOString();
@@ -50,15 +42,11 @@ const getPlanRevisionsFromGit = async planFilePath => {
50
42
  };
51
43
  });
52
44
  };
53
-
54
45
  exports.getPlanRevisionsFromGit = getPlanRevisionsFromGit;
55
-
56
46
  const getPlanFromGit = async (planFilePath, revision) => {
57
47
  return exec(`git show ${revision}:${planFilePath}`);
58
48
  };
59
-
60
49
  exports.getPlanFromGit = getPlanFromGit;
61
-
62
50
  const getHistoricalPlansFromGit = async planFilePath => {
63
51
  try {
64
52
  const revisions = await getPlanRevisionsFromGit(planFilePath);
@@ -79,5 +67,4 @@ const getHistoricalPlansFromGit = async planFilePath => {
79
67
  throw new Error('Unable to fetch plan.json history from git');
80
68
  }
81
69
  };
82
-
83
70
  exports.getHistoricalPlansFromGit = getHistoricalPlansFromGit;
package/dist/glob/glob.js CHANGED
@@ -4,16 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.sortFilePathsByFilename = exports.getUniqueSkippedFileNames = exports.getSkippedFilePaths = exports.getMigrationFilePaths = void 0;
7
-
8
7
  var _path = _interopRequireDefault(require("path"));
9
-
10
8
  var _globPromise = _interopRequireDefault(require("glob-promise"));
11
-
12
9
  var _lodash = require("lodash");
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
11
  const matchSkip = /(.skip|.skip\d+).js$/g;
12
+
17
13
  /**
18
14
  * Sorts migration file paths
19
15
  *
@@ -24,48 +20,39 @@ const matchSkip = /(.skip|.skip\d+).js$/g;
24
20
  const sortFilePathsByFilename = filePaths => (0, _lodash.sortBy)(filePaths, file => {
25
21
  return _path.default.parse(file).base;
26
22
  });
23
+
27
24
  /**
28
25
  * Gets paths to entity migrations in a directory
29
26
  *
30
27
  * @param {String} pathToMigrations
31
28
  * @returns {Promise<Array<String>>} matching migration filePaths
32
29
  */
33
-
34
-
35
30
  exports.sortFilePathsByFilename = sortFilePathsByFilename;
36
-
37
31
  const getMigrationFilePaths = async pathToMigrations => {
38
32
  const filePath = pattern => `${pathToMigrations}${pattern}`;
39
-
40
33
  const filePaths = await (0, _globPromise.default)(filePath('/**/*.js'), {
41
34
  ignore: [filePath('/**/*.skip?([0-9]*).js'), filePath('/**/index.js'), filePath('/**/plan.json'), filePath('/**/*.bundle.js'), filePath('/**/*.test.js'), filePath('/**/*.spec.js'), filePath('/**/__tests__/*'), filePath('/**/__test__/*')]
42
35
  });
43
36
  return sortFilePathsByFilename(filePaths);
44
37
  };
38
+
45
39
  /**
46
40
  * Gets paths to skipped migrations in a directory
47
41
  *
48
42
  * @param {String} pathToMigrations
49
43
  * @returns {Promise<Array<String>>} skipped migration filePaths
50
44
  */
51
-
52
-
53
45
  exports.getMigrationFilePaths = getMigrationFilePaths;
54
-
55
46
  const getSkippedFilePaths = async pathToMigrations => {
56
47
  const filePath = pattern => `${pathToMigrations}${pattern}`;
57
-
58
48
  const filePaths = await (0, _globPromise.default)(filePath('/**/*.skip?([0-9]*).js'), {
59
49
  ignore: [filePath('/**/index.js'), filePath('/**/plan.json'), filePath('/**/*.bundle.js'), filePath('/**/*.test.js'), filePath('/**/*.spec.js'), filePath('/**/__tests__/*'), filePath('/**/__test__/*')]
60
50
  });
61
51
  return sortFilePathsByFilename(filePaths);
62
52
  };
63
-
64
53
  exports.getSkippedFilePaths = getSkippedFilePaths;
65
-
66
54
  const getUniqueSkippedFileNames = skippedPaths => {
67
55
  const fileNames = skippedPaths.map(p => _path.default.parse(p).base.replace(matchSkip, '.js'));
68
56
  return Array.from(new Set(fileNames));
69
57
  };
70
-
71
58
  exports.getUniqueSkippedFileNames = getUniqueSkippedFileNames;
package/dist/hash/hash.js CHANGED
@@ -4,19 +4,15 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.hash = void 0;
7
-
8
7
  var crypto = _interopRequireWildcard(require("crypto"));
9
-
10
8
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
11
-
12
9
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
-
14
10
  /**
15
11
  * Generate SHA256 hash from a string
16
12
  *
17
13
  * @param {String} string
18
14
  * @returns {String} SHA256 hash
19
15
  */
20
- const hash = string => crypto.createHash('sha256').update(string).digest('hex');
21
16
 
17
+ const hash = string => crypto.createHash('sha256').update(string).digest('hex');
22
18
  exports.hash = hash;
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.printVersionHistory = void 0;
7
-
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _git = require("../git/git");
11
-
12
9
  var _database = require("../database/database");
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
11
  /**
17
12
  * Parse plan.json
18
13
  *
@@ -29,6 +24,7 @@ const parsePlan = plan => {
29
24
  }
30
25
  })();
31
26
  };
27
+
32
28
  /**
33
29
  * @typedef {Object} Configuration
34
30
  * @property {string} directory (path to migrations directory)
@@ -42,8 +38,6 @@ const parsePlan = plan => {
42
38
  * @param {Object} args
43
39
  * @param {Configuration} args.config
44
40
  */
45
-
46
-
47
41
  const printVersionHistory = async ({
48
42
  config
49
43
  }) => {
@@ -52,35 +46,34 @@ const printVersionHistory = async ({
52
46
  entity,
53
47
  directory
54
48
  } = config;
55
-
56
49
  try {
57
- const planFilePath = `${directory}/plan.json`; //read version history from database cache
50
+ const planFilePath = `${directory}/plan.json`;
58
51
 
52
+ //read version history from database cache
59
53
  const versionHistoryFromDatabase = await (0, _database.getVersions)(database, entity);
60
54
  const fullDatabaseVersionHistory = versionHistoryFromDatabase.map(d => {
61
- const plan = parsePlan(d === null || d === void 0 ? void 0 : d.plan);
62
- const finalMigration = plan !== null && plan !== void 0 && plan.length ? plan[plan.length - 1] : null;
55
+ const plan = parsePlan(d?.plan);
56
+ const finalMigration = plan?.length ? plan[plan.length - 1] : null;
63
57
  return {
64
- planVersion: d === null || d === void 0 ? void 0 : d.version,
65
- lastFileName: (finalMigration === null || finalMigration === void 0 ? void 0 : finalMigration.fileName) || null,
66
- lastSequence: (finalMigration === null || finalMigration === void 0 ? void 0 : finalMigration.sequence) || null
58
+ planVersion: d?.version,
59
+ lastFileName: finalMigration?.fileName || null,
60
+ lastSequence: finalMigration?.sequence || null
67
61
  };
68
- }); //read full version history from git logs (back to beginning of time)
62
+ });
69
63
 
64
+ //read full version history from git logs (back to beginning of time)
70
65
  const {
71
66
  historicalPlans: fullHistoricalPlans
72
67
  } = await (0, _git.getHistoricalPlansFromGit)(planFilePath);
73
68
  const fullGitVersionHistory = fullHistoricalPlans.map(p => {
74
- var _p$revision, _p$revision2;
75
-
76
- const plan = parsePlan(p === null || p === void 0 ? void 0 : p.plan);
77
- const finalMigration = plan !== null && plan !== void 0 && plan.length ? plan[plan.length - 1] : null;
69
+ const plan = parsePlan(p?.plan);
70
+ const finalMigration = plan?.length ? plan[plan.length - 1] : null;
78
71
  return {
79
- gitCommitHash: p === null || p === void 0 ? void 0 : (_p$revision = p.revision) === null || _p$revision === void 0 ? void 0 : _p$revision.version,
80
- planVersion: p === null || p === void 0 ? void 0 : p.version,
81
- timeStamp: p === null || p === void 0 ? void 0 : (_p$revision2 = p.revision) === null || _p$revision2 === void 0 ? void 0 : _p$revision2.timeStamp,
82
- lastFileName: (finalMigration === null || finalMigration === void 0 ? void 0 : finalMigration.fileName) || null,
83
- lastSequence: (finalMigration === null || finalMigration === void 0 ? void 0 : finalMigration.sequence) || null
72
+ gitCommitHash: p?.revision?.version,
73
+ planVersion: p?.version,
74
+ timeStamp: p?.revision?.timeStamp,
75
+ lastFileName: finalMigration?.fileName || null,
76
+ lastSequence: finalMigration?.sequence || null
84
77
  };
85
78
  });
86
79
  const output = {
@@ -93,5 +86,4 @@ const printVersionHistory = async ({
93
86
  throw new Error('Unable to print debug history');
94
87
  }
95
88
  };
96
-
97
89
  exports.printVersionHistory = printVersionHistory;
package/dist/index.js CHANGED
@@ -45,17 +45,10 @@ Object.defineProperty(exports, "printVersionHistory", {
45
45
  return _history.printVersionHistory;
46
46
  }
47
47
  });
48
-
49
48
  var _create = require("./create/create");
50
-
51
49
  var _plan = require("./plan/plan");
52
-
53
50
  var _plannedVersion = require("./plan/planned-version");
54
-
55
51
  var _migrate = require("./migrate/migrate");
56
-
57
52
  var _pipe = require("./pipe/pipe");
58
-
59
53
  var _database = require("./database/database");
60
-
61
54
  var _history = require("./history/history");
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.migrate = void 0;
7
-
8
7
  var _pipe = require("../pipe/pipe");
9
-
10
8
  var _pending = require("../pending/pending");
11
-
12
9
  /**
13
10
  * @typedef {Array|Object} Payload
14
11
  */
@@ -43,6 +40,7 @@ var _pending = require("../pending/pending");
43
40
  * @param {Configuration} args.config
44
41
  * @returns Promise<{nextPayload: Payload, nextVersion: string}>
45
42
  */
43
+
46
44
  const migrate = async ({
47
45
  payload,
48
46
  config
@@ -59,5 +57,4 @@ const migrate = async ({
59
57
  nextVersion
60
58
  };
61
59
  };
62
-
63
60
  exports.migrate = migrate;
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getPendingMigrators = exports.getPendingMigrations = void 0;
7
-
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _plan = require("../plan/plan");
11
-
12
9
  var _executed = require("../executed/executed");
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
11
  const getPendingMigrations = ({
17
12
  plannedMigrations,
18
13
  executedMigrations,
@@ -20,21 +15,17 @@ const getPendingMigrations = ({
20
15
  }) => {
21
16
  const executedMigrationFileNames = executedMigrations.map(e => e.fileName);
22
17
  const pendingMigrations = plannedMigrations.filter(m => !executedMigrationFileNames.includes(m.fileName));
23
-
24
18
  if (printPendingFileNames) {
25
19
  pendingMigrations.forEach(m => {
26
20
  console.log(_chalk.default.gray(` ${m.fileName}`));
27
21
  });
28
22
  }
29
-
30
23
  return pendingMigrations.map(m => ({
31
24
  fileName: m.fileName,
32
25
  migrator: m.migrator
33
26
  }));
34
27
  };
35
-
36
28
  exports.getPendingMigrations = getPendingMigrations;
37
-
38
29
  const getPendingMigrators = async ({
39
30
  config
40
31
  }) => {
@@ -64,5 +55,4 @@ const getPendingMigrators = async ({
64
55
  nextVersion
65
56
  };
66
57
  };
67
-
68
58
  exports.getPendingMigrators = getPendingMigrators;
package/dist/pipe/pipe.js CHANGED
@@ -4,11 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.pipe = void 0;
7
-
8
7
  const errorMessage = (fileName, message, stack) => `Unhandled exception in file ${fileName}: ${message}
9
8
 
10
9
  ${stack}
11
10
  `;
11
+
12
12
  /**
13
13
  * Executes the pending migrators on a payload, returns modified payload
14
14
  *
@@ -25,17 +25,14 @@ const errorMessage = (fileName, message, stack) => `Unhandled exception in file
25
25
  * @returns {Object} migratedPayload
26
26
  */
27
27
 
28
-
29
28
  const pipe = (migrations, payload) => migrations.reduce((v, m) => {
30
- if (typeof (m === null || m === void 0 ? void 0 : m.migrator) !== 'function') {
29
+ if (typeof m?.migrator !== 'function') {
31
30
  throw new TypeError('Expected a function');
32
31
  }
33
-
34
32
  try {
35
33
  return m.migrator(v);
36
34
  } catch (error) {
37
- throw new Error(errorMessage(m === null || m === void 0 ? void 0 : m.fileName, error.message, error.stack));
35
+ throw new Error(errorMessage(m?.fileName, error.message, error.stack));
38
36
  }
39
37
  }, payload);
40
-
41
38
  exports.pipe = pipe;
@@ -5,13 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.setCachedPlannedVersion = exports.getCachedPlannedVersion = void 0;
7
7
  let cachedPlannedVersion = null;
8
-
9
8
  const getCachedPlannedVersion = () => cachedPlannedVersion;
10
-
11
9
  exports.getCachedPlannedVersion = getCachedPlannedVersion;
12
-
13
10
  const setCachedPlannedVersion = version => {
14
11
  cachedPlannedVersion = version;
15
12
  };
16
-
17
13
  exports.setCachedPlannedVersion = setCachedPlannedVersion;
package/dist/plan/plan.js CHANGED
@@ -4,30 +4,21 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.writePlan = exports.sortPlanEntries = exports.readPlan = exports.parsePlan = exports.getPlannedMigrations = exports.getNextSequenceString = exports.generatePlanEntries = void 0;
7
-
8
7
  var _path = _interopRequireDefault(require("path"));
9
-
10
8
  var _fs = require("fs");
11
-
12
9
  var _moduleFromString = require("module-from-string");
13
-
14
10
  var _hash = require("../hash/hash");
15
-
16
11
  var _glob = require("../glob/glob");
17
-
18
12
  var _validator = require("./validator");
19
-
20
13
  var _database = require("../database/database");
21
-
22
14
  var _cachedPlannedVersion = require("./cached-planned-version");
23
-
24
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
-
26
16
  //https://stackoverflow.com/a/31102605/942635
27
17
  const sortEntry = entry => Object.keys(entry).sort().reduce((obj, key) => {
28
18
  obj[key] = entry[key];
29
19
  return obj;
30
20
  }, {});
21
+
31
22
  /**
32
23
  * Sorts the plan entries by sequence string
33
24
  *
@@ -35,44 +26,36 @@ const sortEntry = entry => Object.keys(entry).sort().reduce((obj, key) => {
35
26
  * returns Array<Object>
36
27
  */
37
28
 
38
-
39
29
  const maxSequence = 1000000;
40
-
41
- const sortPlanEntries = plannedMigrations => plannedMigrations //dotted sequence sort https://stackoverflow.com/a/40201629/942635
30
+ const sortPlanEntries = plannedMigrations => plannedMigrations
31
+ //dotted sequence sort https://stackoverflow.com/a/40201629/942635
42
32
  .sort((a, b) => a.sequence.replace(/\d+/g, n => +n + maxSequence).localeCompare(b.sequence.replace(/\d+/g, n => +n + maxSequence))).map(p => sortEntry(p));
33
+
43
34
  /**
44
35
  * Get next automatic sequence string
45
36
  *
46
37
  * @param {String} sortedPlannedMigrations
47
38
  * returns String next sequence
48
39
  */
49
-
50
-
51
40
  exports.sortPlanEntries = sortPlanEntries;
52
-
53
41
  const getNextSequenceString = sortedPlannedMigrations => {
54
42
  const lastMigration = sortedPlannedMigrations[sortedPlannedMigrations.length - 1];
55
-
56
43
  if (!lastMigration) {
57
44
  return '1';
58
45
  }
59
-
60
46
  const currentLastSequenceNumber = lastMigration.sequence;
61
47
  return `${parseInt(`${currentLastSequenceNumber}`, 10) + 1}`;
62
48
  };
49
+
63
50
  /**
64
51
  * Read the plan.json file
65
52
  *
66
53
  * @param {String} directory path to migrations directory
67
54
  * returns Promise<String> plan.json string
68
55
  */
69
-
70
-
71
56
  exports.getNextSequenceString = getNextSequenceString;
72
-
73
57
  const readPlan = async directory => {
74
58
  let plan;
75
-
76
59
  try {
77
60
  plan = await _fs.promises.readFile(`${directory}/plan.json`, {
78
61
  encoding: 'utf8'
@@ -82,31 +65,27 @@ const readPlan = async directory => {
82
65
  return '[]';
83
66
  }
84
67
  };
68
+
85
69
  /**
86
70
  * Parse the plan.json string into a sorted object
87
71
  *
88
72
  * @param {String} plan plan.json string
89
73
  * returns Array<Object> migration entries from plan.json
90
74
  */
91
-
92
-
93
75
  exports.readPlan = readPlan;
94
-
95
76
  const parsePlan = plan => {
96
77
  let plannedMigrations;
97
-
98
78
  try {
99
79
  plannedMigrations = JSON.parse(plan);
100
80
  } catch {
101
81
  throw new Error('Invalid JSON for migrator plan.js (unable to parse file)');
102
82
  }
103
-
104
83
  if (!(0, _validator.validatePlan)(plannedMigrations)) {
105
84
  throw new Error('Invalid JSON for migrator plan.js (does not match schema)');
106
85
  }
107
-
108
86
  return sortPlanEntries(plannedMigrations);
109
87
  };
88
+
110
89
  /**
111
90
  * Write the plan.json file
112
91
  *
@@ -114,34 +93,27 @@ const parsePlan = plan => {
114
93
  * @param {String} content string to be written to file
115
94
  * returns Promise<>
116
95
  */
117
-
118
-
119
96
  exports.parsePlan = parsePlan;
120
-
121
97
  const writePlan = async (directory, content) => {
122
98
  //todo this is not being written in the correct order
123
99
  await _fs.promises.writeFile(_path.default.resolve(`${directory}/plan.json`), content, {
124
100
  encoding: 'utf8'
125
101
  });
126
102
  };
103
+
127
104
  /**
128
105
  * Generate plan entries
129
106
  *
130
107
  * @param {Array<Object>} sortedMigrationEntries
131
108
  * returns Array<Object>
132
109
  */
133
-
134
-
135
110
  exports.writePlan = writePlan;
136
-
137
111
  const generatePlanEntries = sortedMigrationEntries => sortedMigrationEntries.map(m => ({
138
112
  fileHash: m.fileHash,
139
113
  fileName: m.fileName,
140
114
  sequence: m.sequence
141
115
  }));
142
-
143
116
  exports.generatePlanEntries = generatePlanEntries;
144
-
145
117
  const getPlannedMigrations = async ({
146
118
  config
147
119
  }) => {
@@ -154,7 +126,6 @@ const getPlannedMigrations = async ({
154
126
  dry,
155
127
  importModule = true
156
128
  } = config;
157
-
158
129
  if (database && !dry) {
159
130
  /*
160
131
  OW-9043 and OW-9238: The tool tries to self-create its own meta tables
@@ -164,12 +135,10 @@ const getPlannedMigrations = async ({
164
135
  because it throws errors.
165
136
  */
166
137
  const tablesExist = await (0, _database.migrationTablesExist)(database, entity);
167
-
168
138
  if (!tablesExist) {
169
139
  await (0, _database.createMigrationsTables)(database, entity);
170
140
  }
171
141
  }
172
-
173
142
  const rawPlan = await readPlan(directory);
174
143
  const parsedPlan = parsePlan(rawPlan);
175
144
  const plannedMigrations = parsedPlan.map(m => ({
@@ -180,8 +149,6 @@ const getPlannedMigrations = async ({
180
149
  const filePaths = await (0, _glob.getMigrationFilePaths)(directory);
181
150
  const skippedFilePaths = await (0, _glob.getSkippedFilePaths)(directory);
182
151
  const plannedMigrationsWithFileEntries = await Promise.all(plannedMigrations.map(async m => {
183
- var _await$importFromStri;
184
-
185
152
  const {
186
153
  fileName
187
154
  } = m;
@@ -190,17 +157,15 @@ const getPlannedMigrations = async ({
190
157
  const script = filePath ? await _fs.promises.readFile(filePath, {
191
158
  encoding: 'utf8'
192
159
  }) : null;
193
- const migrator = script && importModule ? (_await$importFromStri = await (0, _moduleFromString.importFromString)(script)) === null || _await$importFromStri === void 0 ? void 0 : _await$importFromStri.default : null;
194
- const fileHash = script ? (0, _hash.hash)(script) : null; //skipped files
160
+ const migrator = script && importModule ? (await (0, _moduleFromString.importFromString)(script))?.default : null;
161
+ const fileHash = script ? (0, _hash.hash)(script) : null;
195
162
 
163
+ //skipped files
196
164
  const skipMatch = '(.skip|.skip\\d+).js$';
197
-
198
165
  const nameMatch = _path.default.parse(m.fileName).name;
199
-
200
166
  const regex = new RegExp(`${nameMatch}${skipMatch}`, 'g');
201
167
  const matchingSkippedFilePaths = skippedFilePaths.filter(f => {
202
168
  const name = _path.default.parse(f).base;
203
-
204
169
  return name.match(regex);
205
170
  });
206
171
  const skippedFileHashes = await Promise.all(matchingSkippedFilePaths.map(async skippedFilePath => {
@@ -209,7 +174,8 @@ const getPlannedMigrations = async ({
209
174
  });
210
175
  return skippedScript ? (0, _hash.hash)(skippedScript) : null;
211
176
  }));
212
- return { ...m,
177
+ return {
178
+ ...m,
213
179
  filePath,
214
180
  isValidFileName,
215
181
  script,
@@ -221,32 +187,29 @@ const getPlannedMigrations = async ({
221
187
  const historicalMigrations = database ? await (0, _database.getMigrationRecords)(database, entity) : [];
222
188
  const plannedMigrationsWithHistory = plannedMigrationsWithFileEntries.map(m => {
223
189
  const historicalMigration = historicalMigrations.find(h => h.fileName === m.fileName);
224
- return { ...m,
225
- fileHashFromHistory: (historicalMigration === null || historicalMigration === void 0 ? void 0 : historicalMigration.fileHash) || null,
226
- sequenceFromHistory: (historicalMigration === null || historicalMigration === void 0 ? void 0 : historicalMigration.sequence) || null
190
+ return {
191
+ ...m,
192
+ fileHashFromHistory: historicalMigration?.fileHash || null,
193
+ sequenceFromHistory: historicalMigration?.sequence || null
227
194
  };
228
195
  });
229
196
  (0, _validator.throwIfFilesNotFound)(plannedMigrationsWithHistory, importModule);
230
197
  (0, _validator.throwIfFileNamesInvalid)(plannedMigrationsWithHistory);
231
198
  (0, _validator.throwIfFileNamesNotUnique)(plannedMigrationsWithHistory);
232
199
  (0, _validator.throwIfSequenceNotUnique)(plannedMigrationsWithHistory);
233
-
234
200
  if (!force) {
235
201
  (0, _validator.warnIfFilesHaveBeenRemovedFromPlan)(plannedMigrationsWithHistory, historicalMigrations);
236
202
  (0, _validator.throwIfFilesHaveChanged)(plannedMigrationsWithHistory);
237
203
  (0, _validator.throwIfSequenceHasChanged)(plannedMigrationsWithHistory);
238
204
  }
239
-
240
205
  (0, _validator.throwIfSequenceHasIntegerGaps)(plannedMigrationsWithHistory);
241
206
  const validatedPlannedMigrations = generatePlanEntries(plannedMigrationsWithHistory);
242
207
  const validatedPlan = JSON.stringify(validatedPlannedMigrations, null, 2);
243
208
  const nextVersion = (0, _hash.hash)(validatedPlan);
244
209
  const planHasChanged = validatedPlan !== rawPlan;
245
-
246
210
  if (!dry && planHasChanged) {
247
211
  await writePlan(directory, validatedPlan);
248
212
  }
249
-
250
213
  if (database && !dry) {
251
214
  await (0, _database.replaceMigrationsRecords)(database, pgpHelpers, entity, validatedPlannedMigrations);
252
215
  const versionRecord = [{
@@ -255,12 +218,10 @@ const getPlannedMigrations = async ({
255
218
  }];
256
219
  await (0, _database.insertVersions)(database, pgpHelpers, entity, versionRecord);
257
220
  }
258
-
259
221
  (0, _cachedPlannedVersion.setCachedPlannedVersion)(nextVersion);
260
222
  return {
261
223
  plannedMigrations: plannedMigrationsWithHistory,
262
224
  nextVersion
263
225
  };
264
226
  };
265
-
266
227
  exports.getPlannedMigrations = getPlannedMigrations;
@@ -4,15 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getPlannedVersion = void 0;
7
-
8
7
  var _fs = require("fs");
9
-
10
8
  var _hash = require("../hash/hash");
11
-
12
9
  var _plan = require("./plan");
13
-
14
10
  var _cachedPlannedVersion = require("./cached-planned-version");
15
-
16
11
  const getPlannedVersion = async ({
17
12
  config
18
13
  }) => {
@@ -25,10 +20,10 @@ const getPlannedVersion = async ({
25
20
  const plannedVersion = (0, _hash.hash)(currentPlan);
26
21
  const cachedPlannedVersion = (0, _cachedPlannedVersion.getCachedPlannedVersion)();
27
22
  return cachedPlannedVersion === plannedVersion ? cachedPlannedVersion : (await (0, _plan.getPlannedMigrations)({
28
- config: { ...config,
23
+ config: {
24
+ ...config,
29
25
  importModule: false
30
26
  }
31
27
  })).nextVersion;
32
28
  };
33
-
34
29
  exports.getPlannedVersion = getPlannedVersion;
@@ -4,27 +4,21 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
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
-
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _lodash = require("lodash");
11
-
12
9
  var _ajv = _interopRequireDefault(require("ajv"));
13
-
14
10
  var _ajvErrors = _interopRequireDefault(require("ajv-errors"));
15
-
16
11
  var _planSchema = _interopRequireDefault(require("./plan.schema.json"));
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  const isNonEmptyString = input => (0, _lodash.isString)(input) && input.length > 0;
21
-
22
14
  const ajv = new _ajv.default({
23
15
  allErrors: true
24
16
  });
25
- (0, _ajvErrors.default)(ajv); //sequence pattern: https://regex101.com/r/4qHZLm/1
17
+ (0, _ajvErrors.default)(ajv);
26
18
 
19
+ //sequence pattern: https://regex101.com/r/4qHZLm/1
27
20
  const planValidator = ajv.compile(_planSchema.default);
21
+
28
22
  /**
29
23
  * Validates if a plan matches the schema
30
24
  *
@@ -37,92 +31,77 @@ const validatePlan = plan => {
37
31
  const {
38
32
  errors
39
33
  } = planValidator;
40
-
41
- if (errors !== null && errors !== void 0 && errors.length) {
34
+ if (errors?.length) {
42
35
  errors.forEach(e => console.error(`${e.message}${e.instancePath ? `at ${e.instancePath}` : ''}`));
43
36
  }
44
-
45
37
  return valid;
46
38
  };
39
+
47
40
  /**
48
41
  * Validates if file description format is valid
49
42
  *
50
43
  * @param {String} description
51
44
  * @returns {Boolean} valid
52
45
  */
53
-
54
-
55
46
  exports.validatePlan = validatePlan;
56
-
57
47
  const validateFileDescription = description => {
58
48
  if (!description) {
59
49
  return false;
60
- } //https://regex101.com/r/IO0dzF/1
61
-
62
-
50
+ }
51
+ //https://regex101.com/r/IO0dzF/1
63
52
  const validFileName = /^([a-z]+|(([a-z]+-)+[a-z]+))$/g;
64
53
  return validFileName.test(description);
65
54
  };
55
+
66
56
  /**
67
57
  * Validates if fileName format is valid
68
58
  *
69
59
  * @param {String} fileName
70
60
  * @returns {Boolean} valid
71
61
  */
72
-
73
-
74
62
  exports.validateFileDescription = validateFileDescription;
75
-
76
63
  const validateFileName = fileName => {
77
64
  //https://regex101.com/r/EX2RlS/1
78
65
  const validFileName = /^([a-z]+|(([a-z]+-)+[a-z]+))(.js|.skip.js)$/g;
79
66
  return validFileName.test(fileName);
80
67
  };
68
+
81
69
  /**
82
70
  * Throws if file names are invalid
83
71
  *
84
72
  * @param {Array<Object>} migrationEntries
85
73
  */
86
-
87
-
88
74
  exports.validateFileName = validateFileName;
89
-
90
75
  const throwIfFileNamesInvalid = fileEntries => {
91
76
  const invalidFileNames = fileEntries.filter(f => !f.isValidFileName).map(f => f.fileName);
92
-
93
77
  if (invalidFileNames.length) {
94
78
  invalidFileNames.forEach(name => console.error(_chalk.default.red(name)));
95
79
  throw new Error('Invalid migration filename format (use kebab-case)');
96
80
  }
97
81
  };
82
+
98
83
  /**
99
84
  * Warns if files have been removed
100
85
  *
101
86
  * @param {Array<Object>} migrationEntries
102
87
  * @param {Array<Object>} historicalMigrations
103
88
  */
104
-
105
-
106
89
  exports.throwIfFileNamesInvalid = throwIfFileNamesInvalid;
107
-
108
90
  const warnIfFilesHaveBeenRemovedFromPlan = (migrationEntries, historicalMigrations) => {
109
91
  const fileNames = migrationEntries.map(f => f.fileName);
110
92
  const deletedFilesNames = historicalMigrations.filter(e => !fileNames.includes(e.fileName)).map(e => e.fileName);
111
-
112
93
  if (deletedFilesNames.length) {
113
94
  deletedFilesNames.forEach(name => console.warn(_chalk.default.yellow(name)));
114
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)'));
115
96
  }
116
97
  };
98
+
117
99
  /**
118
100
  * Throws error if any pre-existing file has changed
119
101
  *
120
102
  * @param {Array<Object>} migrationEntries
121
103
  */
122
-
123
-
124
104
  exports.warnIfFilesHaveBeenRemovedFromPlan = warnIfFilesHaveBeenRemovedFromPlan;
125
-
126
105
  const throwIfFilesHaveChanged = migrationEntries => {
127
106
  const changedFilesNames = migrationEntries.filter(m => {
128
107
  const {
@@ -135,21 +114,18 @@ const throwIfFilesHaveChanged = migrationEntries => {
135
114
  const matchesPlan = !isNonEmptyString(fileHashFromPlan) || [fileHash].concat(skippedFileHashes).includes(fileHashFromPlan);
136
115
  return !(matchesHistory && matchesPlan);
137
116
  }).map(f => f.fileName);
138
-
139
117
  if (changedFilesNames.length) {
140
118
  changedFilesNames.forEach(name => console.error(_chalk.default.red(name)));
141
119
  throw new Error('Not allowed to change migration files (for unreleased local work, you can use the `force` option)');
142
120
  }
143
121
  };
122
+
144
123
  /**
145
124
  * Throws error if previous sequence numbers have changed
146
125
  *
147
126
  * @param {Array<Object>} migrationEntries
148
127
  */
149
-
150
-
151
128
  exports.throwIfFilesHaveChanged = throwIfFilesHaveChanged;
152
-
153
129
  const throwIfSequenceHasChanged = migrationEntries => {
154
130
  const changeSequences = migrationEntries.filter(m => {
155
131
  const {
@@ -159,46 +135,39 @@ const throwIfSequenceHasChanged = migrationEntries => {
159
135
  const changed = (0, _lodash.isString)(sequenceFromHistory) && sequenceFromHistory !== sequence;
160
136
  return changed;
161
137
  }).map(f => f.fileName);
162
-
163
138
  if (changeSequences.length) {
164
139
  changeSequences.forEach(name => console.error(_chalk.default.red(name)));
165
140
  throw new Error('Not allowed to change migration sequences in plan.json');
166
141
  }
167
142
  };
143
+
168
144
  /**
169
145
  * Throws error if sequence numbers are not unique
170
146
  *
171
147
  * @param {Array<Object>} migrationEntries
172
148
  */
173
-
174
-
175
149
  exports.throwIfSequenceHasChanged = throwIfSequenceHasChanged;
176
-
177
150
  const throwIfSequenceNotUnique = migrationEntries => {
178
151
  const sequenceNumbers = migrationEntries.map(f => f.sequence);
179
- const repeatedSequenceNumbers = sequenceNumbers.filter( //https://stackoverflow.com/a/59517965/942635
152
+ const repeatedSequenceNumbers = sequenceNumbers.filter(
153
+ //https://stackoverflow.com/a/59517965/942635
180
154
  (s => v => s.has(v) || !s.add(v))(new Set()));
181
155
  const duplicates = migrationEntries.filter(f => repeatedSequenceNumbers.includes(f.sequence)).map(f => f.fileName);
182
-
183
156
  if (duplicates.length) {
184
157
  duplicates.forEach(fileName => console.error(_chalk.default.red(fileName)));
185
158
  throw new Error('Migrations must have unique sequence numbers in plan.json');
186
159
  }
187
160
  };
161
+
188
162
  /**
189
163
  * Throws error if sequence numbers are not unique
190
164
  *
191
165
  * @param {Array<Object>} migrationEntries
192
166
  */
193
-
194
-
195
167
  exports.throwIfSequenceNotUnique = throwIfSequenceNotUnique;
196
-
197
168
  const throwIfSequenceHasIntegerGaps = migrationEntries => {
198
169
  const toInteger = sequence => parseInt(sequence.split('.')[0], 10);
199
-
200
170
  const unique = arr => Array.from(new Set(arr));
201
-
202
171
  const sequences = migrationEntries.map(s => s.sequence);
203
172
  const sequenceIntegers = sequences.map(s => toInteger(s));
204
173
  const uniqueSequenceIntegers = unique(sequenceIntegers);
@@ -208,47 +177,40 @@ const throwIfSequenceHasIntegerGaps = migrationEntries => {
208
177
  length: max
209
178
  }, (v, k) => k + 1);
210
179
  const missing = (0, _lodash.xor)(orderedUniqueSequenceIntegers, expected);
211
-
212
180
  if (missing.length) {
213
181
  throw new Error(`Migration sequence numbers in plan.json have unexpected gaps: ${missing.join(', ')}`);
214
182
  }
215
183
  };
184
+
216
185
  /**
217
186
  * Throws error if file names are not unique
218
187
  *
219
188
  * @param {Array<Object>} migrationEntries
220
189
  */
221
-
222
-
223
190
  exports.throwIfSequenceHasIntegerGaps = throwIfSequenceHasIntegerGaps;
224
-
225
191
  const throwIfFileNamesNotUnique = migrationEntries => {
226
192
  const fileNames = migrationEntries.map(f => f.fileName);
227
- const repeatedFileNames = fileNames.filter( //https://stackoverflow.com/a/59517965/942635
193
+ const repeatedFileNames = fileNames.filter(
194
+ //https://stackoverflow.com/a/59517965/942635
228
195
  (s => v => s.has(v) || !s.add(v))(new Set()));
229
-
230
196
  if (repeatedFileNames.length) {
231
197
  repeatedFileNames.forEach(fileName => console.error(_chalk.default.red(fileName)));
232
198
  throw new Error('Migration file names must be unique');
233
199
  }
234
200
  };
201
+
235
202
  /**
236
203
  * Throws error if files listed in plan.json are found
237
204
  *
238
205
  * @param {Array<Object>} migrationEntries
239
206
  * @param {Boolean} importModule
240
207
  */
241
-
242
-
243
208
  exports.throwIfFileNamesNotUnique = throwIfFileNamesNotUnique;
244
-
245
209
  const throwIfFilesNotFound = (migrationEntries, importModule) => {
246
210
  const migrationsWithoutFiles = migrationEntries.filter(m => !m.script || importModule && !m.script && !m.migrator);
247
-
248
211
  if (migrationsWithoutFiles.length) {
249
212
  migrationsWithoutFiles.forEach(migration => console.error(_chalk.default.red(migration.fileName)));
250
213
  throw new Error('Migration files from plan.json are missing from filesystem');
251
214
  }
252
215
  };
253
-
254
216
  exports.throwIfFilesNotFound = throwIfFilesNotFound;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@oliasoft-open-source/node-json-migrator",
3
- "version": "2.2.0",
3
+ "version": "2.3.0-beta-2",
4
4
  "description": "A library for JSON migrations",
5
5
  "scripts": {
6
6
  "build": "npx babel src --ignore 'src/**/*.test.js' --out-dir dist --copy-files --no-copy-ignored",
7
- "test": "npm run prettier:check && npm run lint:check && npm run test:unit:coverage",
7
+ "test": "yarn run prettier:check && yarn run lint:check && yarn run test:unit:coverage",
8
8
  "test:unit": "jest --silent=true",
9
9
  "test:unit:coverage": "jest --silent=true --collectCoverage=true",
10
10
  "test:unit:verbose": "jest --silent=false --verbose",
package/release-notes.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Node JSON Migrator Release Notes
2
2
 
3
+ ## 2.3.0
4
+
5
+ - switch from npm to yarn (to match other repos)
6
+ - Add optional CI pipeline that automates publishing of beta releases ([OW-10003](https://oliasoft.atlassian.net/browse/OW-10003))
7
+
3
8
  ## 2.2.0
4
9
 
5
10
  - first publish of release notes
6
-
File without changes