@13w/miri 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -0,0 +1,53 @@
1
+ #### Migration manager
2
+ ### Migrations folder structure
3
+
4
+ * migrations/
5
+ * init/
6
+ * 01-create-collections.js
7
+ ```javascript
8
+ db.createCollection('users');
9
+ db.createCollection('goods');
10
+ ```
11
+ * 02-create-default-users.js
12
+ ```javascript
13
+ db.users.insertOne({firstName: 'foo', lastName: 'zoo'});
14
+ db.users.insertOne({firstName: 'baz', lastName: 'poo'});
15
+ ```
16
+ * 03-create-default-goods.js
17
+ ```javascript
18
+ db.goods.insertOne({name: 'lemon'});
19
+ db.goods.insertOne({name: 'orange'});
20
+ ```
21
+ * indexes/
22
+ * users.json
23
+ ```json
24
+ [
25
+ {name: 1}
26
+ ]
27
+ ```
28
+ * goods.json
29
+ ```json
30
+ [
31
+ [{name: 1}, { unique: true }]
32
+ ]
33
+ ```
34
+ * version-1/
35
+ * 01-02-2023-add-full-name.js
36
+ ```javascript
37
+ export const test = () => db.users.countDocuments({ fullName: { $exists: false } });
38
+ export const up = () => db.users.updateMany({ fullName: { $exists: false } }, [{ $set: { fullName: { $concat: ['$firstName', ' ', '$lastName'] } } }])
39
+ export const down = () => db.users.updateMany({}, {$unset: { fullName: 1 }})
40
+ ```
41
+ * 04-05-2023-add-user-age.js
42
+ ```javascript
43
+ export const test = () => db.users.countDocuments({ age: { $exists: false } });
44
+ export const up => () => db.users.updateMany({ age: { $exists: false } }, {$set: { age: 135 }})
45
+ export const down = () => db.users.updateMany({}, {$unset: { age: 1 }})
46
+ ```
47
+ * version-2/
48
+ * 05-08-2023-add-price-to-goods.js
49
+ ```javascript
50
+ export const test = () => db.goods.countDocuments({ price: { $exists: false } });
51
+ export const up => () => db.goods.updateMany({ price: { $exists: false } }, { $set: {price: 12.24} })
52
+ export const down = () => db.goods.updateMany({}, {$unset: { price: 1 }})
53
+ ```
package/dist/cli.js CHANGED
@@ -16,9 +16,9 @@ const getMiri = async () => {
16
16
  localMigrations: opts.migrations,
17
17
  });
18
18
  };
19
- const status = async (remote = false) => {
19
+ const status = async (remote = false, group) => {
20
20
  const miri = await getMiri();
21
- const patches = await miri.stat(remote);
21
+ const patches = await miri.stat(remote, group);
22
22
  await miri[Symbol.asyncDispose]();
23
23
  if (!patches.length) {
24
24
  return;
@@ -47,7 +47,8 @@ const status = async (remote = false) => {
47
47
  program.command('status')
48
48
  .description('Displays list of applied migrations')
49
49
  .action(() => status(true));
50
- const initProgram = program.command('init');
50
+ const initProgram = program.command('init')
51
+ .description('Manage initial scripts');
51
52
  initProgram.command('apply')
52
53
  .action(async () => {
53
54
  const miri = await getMiri();
@@ -55,16 +56,15 @@ initProgram.command('apply')
55
56
  await miri[Symbol.asyncDispose]();
56
57
  });
57
58
  initProgram.command('status')
58
- .action(() => {
59
- console.log('There should be init status....');
60
- });
59
+ .action(() => status(false, 'init'));
61
60
  const indexesProgram = program.command('indexes')
62
- .command('status')
61
+ .description('Manage indexes');
62
+ const indexStatusProgram = indexesProgram.command('status')
63
63
  .argument('[collection]', 'MongoDB Collection name')
64
64
  .option('-q --quiet', 'Show only changes', false)
65
65
  .action(async () => {
66
- const collection = indexesProgram.args[0];
67
- const { quiet } = indexesProgram.opts();
66
+ const collection = indexStatusProgram.args[0];
67
+ const { quiet } = indexStatusProgram.opts();
68
68
  const miri = await getMiri();
69
69
  const structure = await miri.indexesDiff(collection);
70
70
  await miri[Symbol.asyncDispose]();
@@ -93,13 +93,13 @@ const indexesProgram = program.command('indexes')
93
93
  console.groupEnd();
94
94
  }
95
95
  });
96
- indexesProgram.command('sync')
97
- .option('<collection>', 'MongoDB Collection name', '')
96
+ const indexSyncProgram = indexesProgram.command('sync');
97
+ indexSyncProgram.option('<collection>', 'MongoDB Collection name', '')
98
98
  .action(async () => {
99
99
  const miri = await getMiri();
100
100
  let group = '';
101
- console.group('Starting synchronisation...', indexesProgram.opts());
102
- for await (const { collection, status, name, error } of miri.indexesSync()) {
101
+ console.group('Starting synchronisation...');
102
+ for await (const { collection, status, name, error } of miri.indexesSync(...indexSyncProgram.args)) {
103
103
  if (group !== collection) {
104
104
  if (group) {
105
105
  console.log('Done');
@@ -120,17 +120,19 @@ indexesProgram.command('sync')
120
120
  console.groupEnd();
121
121
  await miri[Symbol.asyncDispose]();
122
122
  });
123
- program.command('diff')
123
+ const patchProgram = program.command('patch')
124
+ .description('Applies patch to database');
125
+ const patchDiffProgram = patchProgram.command('diff')
124
126
  .description('Displays difference between local and applied migrations')
125
127
  .action(() => status());
126
- const programSync = program.command('sync')
128
+ const patchSyncProgram = patchProgram.command('sync')
129
+ .description('Applies migrations')
127
130
  .option('--remote', 'Remote only')
128
131
  .option('--degraded', 'Re-apply patches on degraded migrations')
129
132
  .option('--all', 'Re-apply all patches')
130
- .description('Applies migrations')
131
133
  .action(async () => {
132
134
  const miri = await getMiri();
133
- await miri.sync(programSync.opts());
135
+ await miri.sync(patchSyncProgram.opts());
134
136
  await miri[Symbol.asyncDispose]();
135
137
  });
136
138
  program.parse();
package/dist/miri.js CHANGED
@@ -22,9 +22,9 @@ export var IndexStatus;
22
22
  })(IndexStatus || (IndexStatus = {}));
23
23
  const sortPatches = (a, b) => {
24
24
  if (a.group === b.group) {
25
- return a.name < b.name ? -1 : 1;
25
+ return a.name.localeCompare(b.name);
26
26
  }
27
- return a.group < b.group ? 1 : -1;
27
+ return a.group.localeCompare(b.group);
28
28
  };
29
29
  export default class Migrator {
30
30
  client;
@@ -42,9 +42,9 @@ export default class Migrator {
42
42
  async [Symbol.asyncDispose]() {
43
43
  await this.#client.close();
44
44
  }
45
- async diff() {
46
- const localPatches = await this.getLocalPatches();
47
- const remotePatches = await this.getRemotePatches();
45
+ async diff(group) {
46
+ const localPatches = await this.getLocalPatches(false, group);
47
+ const remotePatches = await this.getRemotePatches(group);
48
48
  for (const localPatch of localPatches) {
49
49
  const remotePatch = remotePatches.find(({ group, name }) => localPatch.group === group && localPatch.name === name);
50
50
  if (remotePatch) {
@@ -93,29 +93,29 @@ export default class Migrator {
93
93
  const filename = `${patch.group}/${patch.name}`;
94
94
  console.group(`Patch ${patch.group} / ${patch.name}...`);
95
95
  if (patch.status === PatchStatus.Removed) {
96
- console.group('Reverting changes');
97
- const result = await this.applyPatchContent(patch.remoteContent?.down, filename);
98
- console.log(result === -1 ? 'Revert script not found' : 'done');
96
+ console.group(colors.cyan('reverting changes'));
97
+ const result = await this.applyPatchContent((patch.remoteContent ?? patch.content)?.down, filename);
98
+ console.log(result === -1 ? colors.white('revert script not found') : colors.green('done'));
99
99
  console.groupEnd();
100
100
  await this.#collection.deleteOne({ _id: patch._id });
101
101
  console.groupEnd();
102
102
  continue;
103
103
  }
104
104
  if (patch.status === PatchStatus.Changed) {
105
- console.group('Reverting changes');
106
- const result = await this.applyPatchContent(patch.remoteContent?.down, filename);
107
- console.log(result === -1 ? 'Revert script not found' : 'done');
105
+ console.group(colors.cyan('reverting changes'));
106
+ const result = await this.applyPatchContent((patch.remoteContent ?? patch.content)?.down, filename);
107
+ console.log(result === -1 ? colors.white('revert script not found') : colors.green('done'));
108
108
  console.groupEnd();
109
109
  patch.status = PatchStatus.New;
110
110
  }
111
111
  if (all || degraded || patch.status === PatchStatus.New) {
112
- console.group(colors.white('Testing migration'));
112
+ console.group(colors.white('resting migration'));
113
113
  const test = await this.applyPatchContent(patch.content.test, filename);
114
114
  console.log(colors.white(`degradation level: ${test}`));
115
115
  if (all || test !== 0) {
116
- console.group(colors.cyan('Applying migration...'));
116
+ console.group(colors.cyan('applying migration...'));
117
117
  await this.applyPatchContent(patch.content.up, filename);
118
- console.log(colors.green('Done'));
118
+ console.log(colors.green('done'));
119
119
  console.groupEnd();
120
120
  }
121
121
  else {
@@ -166,7 +166,8 @@ export default class Migrator {
166
166
  patchObject.raw = patchContent.toString('base64');
167
167
  continue;
168
168
  }
169
- const patchExports = await evaluateJs(patchContent.toString());
169
+ const patchExports = await evaluateJs(patchContent.toString())
170
+ .catch(() => ({}));
170
171
  for (const key of ['test', 'up', 'down']) {
171
172
  const func = patchExports[key];
172
173
  if (typeof func !== 'function') {
@@ -302,8 +303,8 @@ export default class Migrator {
302
303
  }
303
304
  console.groupEnd();
304
305
  }
305
- async stat(remote = false) {
306
- const patches = await (remote ? this.getRemotePatches() : this.diff());
306
+ async stat(remote = false, group) {
307
+ const patches = await (remote ? this.getRemotePatches(group) : this.diff(group));
307
308
  for (const patch of patches) {
308
309
  patch.status = patch.status ?? PatchStatus.Ok;
309
310
  const degradation = await this.applyPatchContent(patch.content.test, `${patch.group}/${patch.name}`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@13w/miri",
3
3
  "description": "MongoDB patch manager",
4
- "version": "1.1.7",
4
+ "version": "1.1.9",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "v20"