@jungvonmatt/contentful-migrations 4.0.1 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,7 +29,6 @@ This initializes migrations and stores the config values in the `package.json` o
29
29
  | accessToken | `undefined` | Contentful Management Token. Just run `npx contentful login` and you're done. |
30
30
  | spaceId | `undefined` | Contentful Space id. Will fallback to `process.env.CONTENTFUL_SPACE_ID` if not set. |
31
31
  | environmentId | `undefined` | Contentful Environment id. Will fallback to `process.env.CONTENTFUL_ENVIRONMENT_ID` if not set.<br/>If neither `environmentId` nor `CONTENTFUL_ENVIRONMENT_ID` is available we search for environment whose id matches the current git branch |
32
- | fallbackEnvironmentId | `'master'` | Contentful Space environment. Acts as default if there is no environment named after the current git branch or the passed env doesn't exist |
33
32
  | storage | `undefined` | We need to keep a hint to the executed migrations inside Contentful. You can choose between **content* and **tag**. <br/><br/>**Content** will add a new content type to your Contentful environment and stores the state of every migration as content entry (recommended approach) <br/>**tag** Will only store the latest version inside a tag. You need to preserve the right order yourself. When you add a new migration with an older version number it will not be executed. |
34
33
  | fieldId | `'migration'` | Id of the tag where the migration version is stored (only used with storage `tag`) |
35
34
  | migrationContentTypeId | `'contentful-migrations'` | Id of the migration content-type (only used with storage `content`) |
@@ -48,6 +47,9 @@ npx migrations environment <environment-id> --create
48
47
 
49
48
  # Remove an environment
50
49
  npx migrations environment <environment-id> --remove
50
+
51
+ # Reset an environment
52
+ npx migrations environment <environment-id> --reset
51
53
  ```
52
54
 
53
55
  ## Generating blank migrations
package/index.js CHANGED
@@ -13,9 +13,9 @@ const { createMigration, runMigrations, fetchMigration, executeMigration } = req
13
13
  const { versionDelete, versionAdd } = require('./lib/version');
14
14
  const { transferContent } = require('./lib/content');
15
15
  const { createOfflineDocs } = require('./lib/doc');
16
+ const { createEnvironment, removeEnvironment, resetEnvironment } = require('./lib/environment');
16
17
  const { getConfig, askAll, askMissing, STORAGE_CONTENT, STORAGE_TAG } = require('./lib/config');
17
18
  const pkg = require('./package.json');
18
- const { createEnvironment, removeEnvironment } = require('./lib/environment');
19
19
 
20
20
  require('dotenv').config();
21
21
 
@@ -30,6 +30,7 @@ const parseArgs = (cmd) => {
30
30
  destEnvironmentId: cmd.destEnvironmentId || parent.destEnvironmentId,
31
31
  verbose: cmd.verbose || parent.verbose,
32
32
  template: cmd.template || parent.template,
33
+ yes: cmd.yes || parent.yes,
33
34
  extension: cmd.extension || parent.extension,
34
35
  bail: cmd.bail || parent.bail,
35
36
  };
@@ -47,7 +48,10 @@ const errorHandler = (error, log) => {
47
48
  };
48
49
 
49
50
  const actionRunner = (fn, log = true) => {
50
- return (...args) => fn(...args).catch((error) => errorHandler(error, log));
51
+ return (...args) => {
52
+ const verbose = args.some((arg) => arg.verbose);
53
+ return fn(...args).catch((error) => errorHandler(error, verbose || log));
54
+ };
51
55
  };
52
56
 
53
57
  const program = new Command();
@@ -60,7 +64,7 @@ program
60
64
  actionRunner(async (cmd) => {
61
65
  const config = await getConfig(parseArgs(cmd || {}));
62
66
  const verified = await askAll(config);
63
- const { managementToken, accessToken, environmentId, ...rest } = verified;
67
+ const { managementToken, accessToken, environmentId, spaceId, ...rest } = verified;
64
68
 
65
69
  if (verified.storage === STORAGE_CONTENT) {
66
70
  await initializeContentModel({ ...config, ...verified });
@@ -70,6 +74,10 @@ program
70
74
  await migrateToTagStorage({ ...config, ...verified });
71
75
  }
72
76
 
77
+ if (!process.env.CONTENTFUL_SPACE_ID) {
78
+ rest.spaceId = spaceId;
79
+ }
80
+
73
81
  // try to store in package.json
74
82
  const localPkg = await pkgUp();
75
83
  if (localPkg) {
@@ -121,6 +129,7 @@ program
121
129
  .option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
122
130
  .option('-p, --path <path/to/migrations>', 'Change the path where the migrations are stored')
123
131
  .option('-v, --verbose', 'Verbosity')
132
+ .option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
124
133
  .option('--bail', 'Abort execution after first failed migration (default: true)', true)
125
134
  .option('--no-bail', 'Ignore failed migrations')
126
135
  .description('Execute all unexecuted migrations available.')
@@ -139,13 +148,15 @@ program
139
148
  }
140
149
 
141
150
  await runMigrations(verified);
142
- }, true)
151
+ }, false)
143
152
  );
144
153
 
145
154
  program
146
155
  .command('execute <file>')
147
156
  .option('-s, --space-id <space-id>', 'Contentful space id')
148
157
  .option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
158
+ .option('-v, --verbose', 'Verbosity')
159
+ .option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
149
160
  .description('Execute a single migration.')
150
161
  .action(
151
162
  actionRunner(async (file, options) => {
@@ -169,6 +180,7 @@ program
169
180
  .command('version <file>')
170
181
  .option('-s, --space-id <space-id>', 'Contentful space id')
171
182
  .option('-e, --environment-id <environment-id>', 'Change the Contentful environment')
183
+ .option('-v, --verbose', 'Verbosity')
172
184
  .option('--add', 'Mark migration as migrated')
173
185
  .option('--remove', 'Delete migration entry in Contentful')
174
186
  .description('Manually mark a migration as migrated or not. (Only available with the Content-model storage)')
@@ -202,15 +214,17 @@ program
202
214
  program
203
215
  .command('environment <environment-id>')
204
216
  .option('-s, --space-id <space-id>', 'Contentful space id')
217
+ .option('-v, --verbose', 'Verbosity')
205
218
  .option('--create', 'Create new contentful environment')
206
219
  .option('--remove', 'Delete contentful environment')
207
220
  .option('--reset', 'Reset contentful environment')
221
+ .option('--source-environment-id <environment-id>', 'Set the source environment to clone new environment from')
208
222
  .description('Add or remove a contentful environment for migrations')
209
223
  .action(
210
224
  actionRunner(async (environmentId, options) => {
211
- const { remove, create } = options;
212
- const config = await getConfig(parseArgs(options || {}));
213
- const verified = await askMissing(config);
225
+ const { remove, create, reset } = options;
226
+ const config = await getConfig(parseArgs({ ...(options || {}), environmentId }));
227
+ const verified = await askMissing(config, ['accessToken', 'spaceId', 'environmentId']);
214
228
 
215
229
  if (create) {
216
230
  return createEnvironment(environmentId, verified);
@@ -238,7 +252,7 @@ program
238
252
  .action(
239
253
  actionRunner(async (cmd) => {
240
254
  const config = await getConfig(parseArgs(cmd || {}));
241
- const verified = await askMissing(config);
255
+ const verified = await askMissing(config, ['accessToken', 'spaceId', 'environmentId']);
242
256
  await createOfflineDocs(verified);
243
257
  }, true)
244
258
  );
@@ -249,14 +263,15 @@ program
249
263
  .requiredOption('--dest-environment-id <environment-id>', 'Set the Contentful destination environment (to)')
250
264
  .option('-s, --space-id <space-id>', 'Contentful space id')
251
265
  .option('-c, --content-type <content-type>', 'Specify content-type')
266
+ .option('-v, --verbose', 'Verbosity')
267
+ .option('-y, --yes', 'Assume "yes" as answer to all prompts and run non-interactively.')
252
268
  .option('--diff', 'Manually choose skip/overwrite for every conflict')
253
269
  .option('--force', 'No manual diffing. Overwrites all conflicting entries/assets')
254
- .option('-v, --verbose', 'Verbosity')
255
270
  .description('Transfer content from source environment to destination environment')
256
271
  .action(
257
272
  actionRunner(async (cmd) => {
258
273
  const config = await getConfig(parseArgs(cmd || {}));
259
- const verified = await askMissing(config);
274
+ const verified = await askMissing({ ...config, environmentId: 'not-used' });
260
275
 
261
276
  // run migrations on destination environment
262
277
  await transferContent({
package/lib/backend.js CHANGED
@@ -360,14 +360,19 @@ const getNewMigrations = async (config) => {
360
360
  const migrations = await globby(`${directory}/*.js`);
361
361
 
362
362
  if (storage === STORAGE_CONTENT) {
363
- const versions = await getMigrationVersions(config);
363
+ try {
364
+ const versions = await getMigrationVersions(config);
364
365
 
365
- return migrations.filter((file) => {
366
- const name = path.basename(file);
367
- const [, num] = /^(\d+)-/.exec(name);
366
+ return migrations.filter((file) => {
367
+ const name = path.basename(file);
368
+ const [, num] = /^(\d+)-/.exec(name);
368
369
 
369
- return !(versions || []).includes(parseInt(num, 10));
370
- });
370
+ return !(versions || []).includes(parseInt(num, 10));
371
+ });
372
+ } catch (error) {
373
+ console.error(chalk.red('\nError:'), `Missing migration content type. Run ${chalk.cyan('npx migrations init')}`);
374
+ process.exit(1);
375
+ }
371
376
  }
372
377
 
373
378
  const version = await getMigrationVersionFromTag(config);
package/lib/config.js CHANGED
@@ -2,7 +2,6 @@ const path = require('path');
2
2
  const inquirer = require('inquirer');
3
3
  const mergeOptions = require('merge-options').bind({ ignoreUndefined: true });
4
4
  const { cosmiconfig } = require('cosmiconfig');
5
- const branch = require('git-branch');
6
5
 
7
6
  const { getSpaces, getEnvironments } = require('./contentful');
8
7
 
@@ -20,7 +19,6 @@ const getConfig = async (args) => {
20
19
  const defaultOptions = {
21
20
  fieldId: 'migration',
22
21
  migrationContentTypeId: 'contentful-migrations',
23
- fallbackEnvironmentId: 'master',
24
22
  host: 'api.contentful.com',
25
23
  directory: path.resolve(process.cwd(), 'migrations'),
26
24
  };
@@ -31,10 +29,6 @@ const getConfig = async (args) => {
31
29
  accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN,
32
30
  };
33
31
 
34
- try {
35
- defaultOptions.branch = await branch();
36
- } catch (error) {}
37
-
38
32
  let contentfulCliOptions = {};
39
33
  try {
40
34
  // get configuration from contentful rc file (created by the contentful cli command)
@@ -92,7 +86,7 @@ const getPromts = (data) => {
92
86
  name: 'spaceId',
93
87
  message: 'Space ID',
94
88
  choices: async (answers) => {
95
- const spaces = await getSpaces(answers);
89
+ const spaces = await getSpaces({ ...(data || {}), ...answers });
96
90
  return spaces.map((space) => ({
97
91
  name: `${space.name} (${space.sys.id})`,
98
92
  value: space.sys.id,
@@ -104,14 +98,14 @@ const getPromts = (data) => {
104
98
  },
105
99
  {
106
100
  type: 'list',
107
- name: 'fallbackEnvironmentId',
108
- message: 'Fallback environment',
101
+ name: 'environmentId',
102
+ message: 'Environment ID',
109
103
  choices: async (answers) => {
110
- const environments = await getEnvironments(answers);
104
+ const environments = await getEnvironments({ ...(data || {}), ...answers });
111
105
  return environments.map((environment) => environment.sys.id);
112
106
  },
113
107
  default: function () {
114
- return data.fallbackEnvironmentId;
108
+ return data.environmentId;
115
109
  },
116
110
  },
117
111
  {
@@ -174,8 +168,13 @@ const askAll = async (data = {}) => {
174
168
  return answers;
175
169
  };
176
170
 
177
- const askMissing = async (data = {}) => {
178
- const missingPromts = getPromts(data).filter(({ name }) => !data[name]);
171
+ const askMissing = async (data = {}, requiredFields = undefined) => {
172
+ const allQuestions = getPromts(data);
173
+ if (!requiredFields) {
174
+ requiredFields = allQuestions.map(({ name }) => name);
175
+ }
176
+
177
+ const missingPromts = getPromts(data).filter(({ name }) => !data[name] && requiredFields.includes(name));
179
178
 
180
179
  // Check if storage changed to content and run initialization
181
180
  const missingStorage = missingPromts.some((prompt) => prompt.name === 'storage');
@@ -185,9 +184,26 @@ const askMissing = async (data = {}) => {
185
184
  return { ...data, ...answers, missingStorageModel: missingStorage && storage === STORAGE_CONTENT };
186
185
  };
187
186
 
187
+ const confirm = async (config = {}) => {
188
+ if (config.yes) {
189
+ return true;
190
+ }
191
+ const { proceed } = await inquirer.prompt([
192
+ {
193
+ type: 'confirm',
194
+ name: 'check',
195
+ message: 'Do you wish to proceed?',
196
+ default: true,
197
+ },
198
+ ]);
199
+
200
+ return proceed;
201
+ };
202
+
188
203
  module.exports.getConfig = getConfig;
189
204
  module.exports.askAll = askAll;
190
205
  module.exports.askMissing = askMissing;
206
+ module.exports.confirm = confirm;
191
207
  module.exports.STORAGE_TAG = STORAGE_TAG;
192
208
  module.exports.STORAGE_CONTENT = STORAGE_CONTENT;
193
209
  module.exports.STATE_SUCCESS = STATE_SUCCESS;
package/lib/content.js CHANGED
@@ -5,6 +5,7 @@ const { getContent, getContentId, getLinkedAssets, getLinkedEntries } = require(
5
5
  const { diff } = require('./diff');
6
6
  const { buildTree } = require('./tree');
7
7
  const { getLatestVersion } = require('./backend');
8
+ const { confirm } = require('./config');
8
9
 
9
10
  const resolveConflicts = async (sourceEntries, destEntries, options) => {
10
11
  const { contentTypes, diffConflicts, forceOverwrite } = options;
@@ -150,16 +151,8 @@ const transferContent = async (config) => {
150
151
  )} from ${chalk.cyan(sourceEnvironmentId)} to ${chalk.cyan(destEnvironmentId)}`
151
152
  );
152
153
 
153
- const { proceed } = await inquirer.prompt([
154
- {
155
- type: 'confirm',
156
- message: 'Do you wish to proceed?',
157
- default: true,
158
- name: 'proceed',
159
- },
160
- ]);
161
-
162
- if (proceed !== true) {
154
+ proceed = await confirm(config);
155
+ if (!proceed) {
163
156
  return;
164
157
  }
165
158
 
package/lib/contentful.js CHANGED
@@ -156,18 +156,22 @@ const getEnvironment = async (options) => {
156
156
  if (environmentCache.has(cacheKey)) {
157
157
  return environmentCache.get(cacheKey);
158
158
  }
159
- const { environmentId, branch, fallbackEnvironmentId } = options || {};
159
+ const { environmentId, spaceId } = options || {};
160
160
  const space = await getSpace(options);
161
161
 
162
162
  const { items: environments } = await space.getEnvironments();
163
163
 
164
164
  const environmentIds = (environments || []).map((env) => env.sys.id);
165
165
 
166
- const targetEnvironmentId = environmentId || branch;
166
+ const targetEnvironmentId = environmentId;
167
167
  if (targetEnvironmentId && environmentIds.includes(targetEnvironmentId)) {
168
168
  environmentCache.set(cacheKey, space.getEnvironment(targetEnvironmentId));
169
+ } else if (targetEnvironmentId) {
170
+ throw new Error(`Environment "${targetEnvironmentId}" is not available in space "${spaceId}"`);
169
171
  } else {
170
- environmentCache.set(cacheKey, space.getEnvironment(fallbackEnvironmentId || DEFAULT_ENVIRONMENT_ID));
172
+ throw new Error(
173
+ 'Missing environment id. Use -e <environment-id> or set environment variable CONTENTFUL_ENVIRONMENT_ID'
174
+ );
171
175
  }
172
176
 
173
177
  return environmentCache.get(cacheKey);
package/lib/doc.js CHANGED
@@ -1,11 +1,11 @@
1
1
  const path = require('path');
2
- const table = require('markdown-table');
3
2
  const chalk = require('chalk');
4
3
  const fs = require('fs-extra');
5
4
  const Mustache = require('mustache');
6
5
  const { getEditorInterfaces, getContentTypes, getContentTypeId, getContentId } = require('./contentful');
7
6
 
8
- const getFieldTable = (fields, editorInterfaces) => {
7
+ const getFieldTable = async (fields, editorInterfaces) => {
8
+ const { markdownTable: table } = await import('markdown-table');
9
9
  const { controls = [] } = editorInterfaces;
10
10
  return table([
11
11
  ['Id', 'Name', 'Type', 'Required', 'Localized', 'HelpText', 'Remarks'],
@@ -27,7 +27,8 @@ const getFieldTable = (fields, editorInterfaces) => {
27
27
  ]);
28
28
  };
29
29
 
30
- const createDoc = (contentType, editorInterfaces) => {
30
+ const createDoc = async (contentType, editorInterfaces) => {
31
+ const { markdownTable: table } = await import('markdown-table');
31
32
  const { name, displayField, description, sys, fields } = contentType || {};
32
33
  const { id } = sys || {};
33
34
 
@@ -50,7 +51,7 @@ ${description}
50
51
 
51
52
  ## Fields
52
53
 
53
- ${getFieldTable(fields, editorInterfaces)}
54
+ ${await getFieldTable(fields, editorInterfaces)}
54
55
  `;
55
56
  };
56
57
 
@@ -98,7 +99,7 @@ const createOfflineDocs = async (config) => {
98
99
  const data = prepareData(contentType, interfaces);
99
100
  content = await customRender(data);
100
101
  } else {
101
- content = createDoc(contentType, interfaces);
102
+ content = await createDoc(contentType, interfaces);
102
103
  }
103
104
 
104
105
  const filename = `${getContentId(contentType)}.${extension}`;
@@ -20,11 +20,11 @@ const getActiveApiKey = async (config) => {
20
20
  * @param {Object} config The config object including all required data
21
21
  */
22
22
  const createEnvironment = async (environmentId, config) => {
23
- const { sourceEnvironment = 'master' } = config;
24
- console.log(`\nCreating new environment ${chalk.green(environmentId)} from ${chalk.green(sourceEnvironment)}`);
23
+ const { sourceEnvironmentId = 'master' } = config;
24
+ console.log(`\nCreating new environment ${chalk.green(environmentId)} from ${chalk.green(sourceEnvironmentId)}`);
25
25
 
26
26
  const space = await getSpace(config);
27
- const environment = await space.createEnvironmentWithId(environmentId, { name: environmentId }, sourceEnvironment);
27
+ const environment = await space.createEnvironmentWithId(environmentId, { name: environmentId }, sourceEnvironmentId);
28
28
 
29
29
  const apiKey = await getActiveApiKey(config);
30
30
 
@@ -52,9 +52,8 @@ const createEnvironment = async (environmentId, config) => {
52
52
  * @param {Object} config The config object including all required data
53
53
  */
54
54
  const removeEnvironment = async (environmentId, config) => {
55
- const { fallbackEnvironment } = config;
56
- if ([fallbackEnvironment, 'master'].includes(environmentId)) {
57
- throw new Error('Removing the fallback environment or the master environment is not supported');
55
+ if (['master'].includes(environmentId)) {
56
+ throw new Error('Removing the master environment is not supported');
58
57
  }
59
58
  console.log(`\nRemoving environment ${chalk.green(environmentId)}`);
60
59
  const space = await getSpace(config);
@@ -79,7 +78,7 @@ const removeEnvironment = async (environmentId, config) => {
79
78
  */
80
79
  const resetEnvironment = async (environmentId, config) => {
81
80
  if (['master'].includes(environmentId)) {
82
- throw new Error('Removing the fallback environment or the master environment is not supported');
81
+ throw new Error('Removing the master environment is not supported');
83
82
  }
84
83
  console.log(`\nRemoving environment ${chalk.green(environmentId)}`);
85
84
  const space = await getSpace(config);
@@ -88,8 +87,6 @@ const resetEnvironment = async (environmentId, config) => {
88
87
  await environment.delete();
89
88
  } catch {}
90
89
  await createEnvironment(environmentId, config);
91
-
92
- console.log(chalk.green('\nDone'), '🚀');
93
90
  };
94
91
 
95
92
  module.exports.createEnvironment = createEnvironment;
package/lib/migration.js CHANGED
@@ -9,7 +9,7 @@ const {
9
9
  const chalk = require('chalk');
10
10
  const { getEnvironment } = require('./contentful');
11
11
 
12
- const { STATE_SUCCESS, STATE_FAILURE } = require('./config');
12
+ const { confirm, STATE_SUCCESS, STATE_FAILURE } = require('./config');
13
13
 
14
14
  const { storeMigration, getNewMigrations } = require('./backend');
15
15
 
@@ -69,7 +69,6 @@ const executeMigration = async (file, config) => {
69
69
  const { accessToken, spaceId } = config || {};
70
70
  const client = await getEnvironment(config);
71
71
  const environmentId = client.sys.id;
72
-
73
72
  const name = path.basename(file);
74
73
  const [, version] = /^(\d+)-/.exec(name);
75
74
 
@@ -81,7 +80,11 @@ const executeMigration = async (file, config) => {
81
80
  yes: true,
82
81
  };
83
82
 
84
- console.log(`\nRun migration ${chalk.green(version)} ...`);
83
+ console.log(`\nRun migration ${chalk.green(version)} in environment ${chalk.green(environmentId)}`);
84
+ const proceed = await confirm(config);
85
+ if (!proceed) {
86
+ return;
87
+ }
85
88
  try {
86
89
  await runMigration(options);
87
90
  await storeMigration({ version, name, state: STATE_SUCCESS }, config);
@@ -104,17 +107,25 @@ const runMigrations = async (config) => {
104
107
 
105
108
  const client = await getEnvironment(config);
106
109
  const environmentId = client.sys.id;
107
- console.log('TEST 1');
108
- const migrations = await getNewMigrations(config);
109
- console.log('TEST 2', migrations);
110
+ let migrations = [];
111
+ try {
112
+ migrations = await getNewMigrations(config);
113
+ } catch (error) {
114
+ console.log(error.message);
115
+ throw error;
116
+ }
110
117
  console.log(
111
118
  `Found ${chalk.green(migrations.length)} unexecuted migrations in environment ${chalk.green(environmentId)}`
112
119
  );
113
120
 
114
- let migrationVersion = 0;
121
+ const proceed = migrations.length === 0 || (await confirm(config));
122
+ if (!proceed) {
123
+ return;
124
+ }
125
+
115
126
  for await (const file of migrations) {
116
127
  try {
117
- migrationVersion = await executeMigration(file, config);
128
+ await executeMigration(file, { ...config, yes: true });
118
129
  } catch (error) {
119
130
  if (bail) {
120
131
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungvonmatt/contentful-migrations",
3
- "version": "4.0.1",
3
+ "version": "5.0.1",
4
4
  "description": "Helper to handle migrations in contentful",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -30,40 +30,39 @@
30
30
  "content-type"
31
31
  ],
32
32
  "dependencies": {
33
- "@contentful/rich-text-plain-text-renderer": "^14.1.2",
34
- "array.prototype.flatmap": "^1.2.4",
33
+ "@contentful/rich-text-plain-text-renderer": "^15.5.1",
34
+ "array.prototype.flatmap": "^1.2.5",
35
35
  "ascii-tree": "^0.3.0",
36
36
  "chalk": "^4.1.2",
37
37
  "cli-progress": "^3.9.1",
38
- "commander": "^7.2.0",
38
+ "commander": "^8.3.0",
39
39
  "common-tags": "^1.8.0",
40
40
  "contentful-cli": "^1.8.23",
41
41
  "contentful-import": "^8.2.22",
42
42
  "contentful-management": "^7.32.0",
43
43
  "contentful-migration": "^4.3.0",
44
- "cosmiconfig": "^7.0.0",
44
+ "cosmiconfig": "^7.0.1",
45
45
  "deep-diff": "^1.0.2",
46
46
  "diff": "^5.0.0",
47
47
  "dotenv": "^10.0.0",
48
48
  "fs-extra": "^10.0.0",
49
- "git-branch": "^2.0.1",
50
49
  "globby": "^11.0.3",
51
- "inquirer": "^8.1.2",
52
- "markdown-table": "^2.0.0",
50
+ "inquirer": "^8.2.0",
51
+ "markdown-table": "^3.0.1",
53
52
  "merge-options": "^3.0.4",
54
53
  "mustache": "^4.2.0",
55
- "node-fetch": "^2.6.1",
54
+ "node-fetch": "^3.0.0",
56
55
  "node-object-hash": "^2.3.10",
57
56
  "pkg-up": "^3.1.0"
58
57
  },
59
58
  "devDependencies": {
60
59
  "babel-eslint": "^10.1.0",
61
- "eslint": "^7.32.0",
60
+ "eslint": "^8.1.0",
62
61
  "eslint-config-prettier": "^8.3.0",
63
- "eslint-plugin-prettier": "^3.4.0",
64
- "husky": "^6.0.0",
65
- "lint-staged": "^11.1.2",
66
- "prettier": "^2.3.2"
62
+ "eslint-plugin-prettier": "^4.0.0",
63
+ "husky": "^7.0.4",
64
+ "lint-staged": "^11.2.6",
65
+ "prettier": "^2.4.1"
67
66
  },
68
67
  "publishConfig": {
69
68
  "access": "public"
@@ -107,5 +106,11 @@
107
106
  "hooks": {
108
107
  "pre-commit": "lint-staged"
109
108
  }
109
+ },
110
+ "migrations": {
111
+ "spaceId": "89na9aswdzfj",
112
+ "storage": "content",
113
+ "migrationContentTypeId": "contentful-migrations",
114
+ "directory": "migrations"
110
115
  }
111
116
  }