@jungvonmatt/contentful-migrations 6.2.5 → 7.0.0

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/index.d.ts CHANGED
@@ -1,19 +1,19 @@
1
- import type Migration from "contentful-migration";
2
- import type { MigrationContext, MigrationFunction } from "contentful-migration";
3
- import type { LocaleHelpers } from "./lib/helpers/locale";
4
- import type { ValidationHelpers } from "./lib/helpers/validation";
1
+ import type Migration from 'contentful-migration';
2
+ import type { MigrationContext, MigrationFunction } from 'contentful-migration';
3
+ import type { LocaleHelpers } from './lib/helpers/locale';
4
+ import type { ValidationHelpers } from './lib/helpers/validation';
5
5
 
6
6
  export interface MigrationHelpers {
7
- locale: LocaleHelpers,
8
- validation: ValidationHelpers
7
+ locale: LocaleHelpers;
8
+ validation: ValidationHelpers;
9
9
  }
10
10
 
11
11
  export type EnhancedMigrationFunction = (
12
12
  migration: Migration,
13
13
  context?: MigrationContext,
14
- helpers?: MigrationHelpers
14
+ helpers?: MigrationHelpers,
15
15
  ) => void;
16
16
 
17
17
  export function withHelpers(cb: EnhancedMigrationFunction): MigrationFunction;
18
- export { getLocaleHelpers } from "./lib/helpers/locale";
19
- export { getValidationHelpers } from "./lib/helpers/validation";
18
+ export { getLocaleHelpers } from './lib/helpers/locale';
19
+ export { getValidationHelpers } from './lib/helpers/validation';
package/lib/backend.js CHANGED
@@ -1,9 +1,19 @@
1
- const path = require('path');
2
- const fs = require('fs/promises');
3
- const pc = require('picocolors');
4
- const cliProgress = require('cli-progress');
5
- const { getEnvironment, getDefaultLocale, getMigrationItems } = require('./contentful');
6
- const { STORAGE_TAG, STORAGE_CONTENT, STATE_SUCCESS, STATE_FAILURE } = require('./config');
1
+ const path = require("path");
2
+ const fs = require("fs/promises");
3
+ const pc = require("picocolors");
4
+ const cliProgress = require("cli-progress");
5
+ const { glob } = require("tinyglobby");
6
+ const {
7
+ getEnvironment,
8
+ getDefaultLocale,
9
+ getMigrationItems,
10
+ } = require("./contentful");
11
+ const {
12
+ STORAGE_TAG,
13
+ STORAGE_CONTENT,
14
+ STATE_SUCCESS,
15
+ STATE_FAILURE,
16
+ } = require("./config");
7
17
 
8
18
  /**
9
19
  * Create contentful-migrations content-type
@@ -15,79 +25,90 @@ const initializeContentModel = async (config) => {
15
25
  const environmentId = client.sys.id;
16
26
  const { items: contentTypes } = await client.getContentTypes();
17
27
 
18
- const exists = (contentTypes || []).some((contentType) => contentType.sys.id === migrationContentTypeId);
28
+ const exists = (contentTypes || []).some(
29
+ (contentType) => contentType.sys.id === migrationContentTypeId,
30
+ );
19
31
 
20
32
  if (!exists) {
21
33
  console.log(
22
- `\nCreating content-type: ${pc.green(migrationContentTypeId)} in environment ${pc.green(environmentId)}`
34
+ `\nCreating content-type: ${pc.green(migrationContentTypeId)} in environment ${pc.green(environmentId)}`,
35
+ );
36
+ const contentType = await client.createContentTypeWithId(
37
+ migrationContentTypeId,
38
+ {
39
+ name: "Migrations",
40
+ description: "Internal data model holding references to all migrations",
41
+ displayField: "name",
42
+ fields: [
43
+ {
44
+ id: "version",
45
+ name: "Version",
46
+ type: "Symbol",
47
+ localized: false,
48
+ required: true,
49
+ validations: [],
50
+ disabled: false,
51
+ omitted: false,
52
+ },
53
+ {
54
+ id: "name",
55
+ name: "Name",
56
+ type: "Symbol",
57
+ localized: false,
58
+ required: false,
59
+ validations: [],
60
+ disabled: false,
61
+ omitted: false,
62
+ },
63
+ {
64
+ id: "state",
65
+ name: "State",
66
+ type: "Symbol",
67
+ localized: false,
68
+ required: false,
69
+ validations: [
70
+ {
71
+ in: [STATE_SUCCESS, STATE_FAILURE],
72
+ },
73
+ ],
74
+ disabled: false,
75
+ omitted: false,
76
+ },
77
+ {
78
+ id: "message",
79
+ name: "Message",
80
+ type: "Text",
81
+ localized: false,
82
+ required: false,
83
+ validations: [],
84
+ disabled: false,
85
+ omitted: false,
86
+ },
87
+ ],
88
+ },
23
89
  );
24
- const contentType = await client.createContentTypeWithId(migrationContentTypeId, {
25
- name: 'Migrations',
26
- description: 'Internal data model holding references to all migrations',
27
- displayField: 'name',
28
- fields: [
29
- {
30
- id: 'version',
31
- name: 'Version',
32
- type: 'Symbol',
33
- localized: false,
34
- required: true,
35
- validations: [],
36
- disabled: false,
37
- omitted: false,
38
- },
39
- {
40
- id: 'name',
41
- name: 'Name',
42
- type: 'Symbol',
43
- localized: false,
44
- required: false,
45
- validations: [],
46
- disabled: false,
47
- omitted: false,
48
- },
49
- {
50
- id: 'state',
51
- name: 'State',
52
- type: 'Symbol',
53
- localized: false,
54
- required: false,
55
- validations: [
56
- {
57
- in: [STATE_SUCCESS, STATE_FAILURE],
58
- },
59
- ],
60
- disabled: false,
61
- omitted: false,
62
- },
63
- {
64
- id: 'message',
65
- name: 'Message',
66
- type: 'Text',
67
- localized: false,
68
- required: false,
69
- validations: [],
70
- disabled: false,
71
- omitted: false,
72
- },
73
- ],
74
- });
75
90
  await contentType.publish();
76
91
 
77
- const editorInterface = await client.getEditorInterfaceForContentType(migrationContentTypeId);
92
+ const editorInterface = await client.getEditorInterfaceForContentType(
93
+ migrationContentTypeId,
94
+ );
78
95
  if (editorInterface) {
79
- const messageIndex = editorInterface.controls.findIndex((value) => value.fieldId === 'message');
96
+ const messageIndex = editorInterface.controls.findIndex(
97
+ (value) => value.fieldId === "message",
98
+ );
80
99
  editorInterface.controls[messageIndex] = {
81
100
  ...editorInterface.controls[messageIndex],
82
- widgetNamespace: 'builtin',
83
- widgetId: 'multipleLine',
101
+ widgetNamespace: "builtin",
102
+ widgetId: "multipleLine",
84
103
  };
85
104
 
86
- const stateIndex = editorInterface.controls.findIndex((value) => value.fieldId === 'state');
105
+ const stateIndex = editorInterface.controls.findIndex(
106
+ (value) => value.fieldId === "state",
107
+ );
87
108
  editorInterface.controls[stateIndex] = {
88
109
  ...editorInterface.controls[stateIndex],
89
- widgetNamespace: 'builtin',
90
- widgetId: 'radio',
110
+ widgetNamespace: "builtin",
111
+ widgetId: "radio",
91
112
  };
92
113
 
93
114
  await editorInterface.update();
@@ -112,30 +133,34 @@ const addMigrationEntry = async (data, config) => {
112
133
 
113
134
  let entry;
114
135
  try {
115
- entry = await client.getEntry(version);
136
+ entry = await client.getEntry(`${version}`);
116
137
  } catch {}
117
138
 
118
139
  if (!entry) {
119
- entry = await client.createEntryWithId(migrationContentTypeId, version, {
120
- fields: {
121
- version: {
122
- [defaultLocale]: version,
123
- },
124
- name: {
125
- [defaultLocale]: name,
126
- },
127
- state: {
128
- [defaultLocale]: state,
129
- },
130
- message: {
131
- [defaultLocale]: message || '',
140
+ entry = await client.createEntryWithId(
141
+ migrationContentTypeId,
142
+ `${version}`,
143
+ {
144
+ fields: {
145
+ version: {
146
+ [defaultLocale]: `${version}`,
147
+ },
148
+ name: {
149
+ [defaultLocale]: name,
150
+ },
151
+ state: {
152
+ [defaultLocale]: state,
153
+ },
154
+ message: {
155
+ [defaultLocale]: message || "",
156
+ },
132
157
  },
133
158
  },
134
- });
159
+ );
135
160
  } else {
136
161
  entry.fields.name = { [defaultLocale]: name };
137
162
  entry.fields.state = { [defaultLocale]: state };
138
- entry.fields.message = { [defaultLocale]: message || '' };
163
+ entry.fields.message = { [defaultLocale]: message || "" };
139
164
  }
140
165
 
141
166
  try {
@@ -200,8 +225,9 @@ const migrateToContentStorage = async (config) => {
200
225
  const client = await getEnvironment(config);
201
226
  const version = await getMigrationVersionFromTag(config);
202
227
 
203
- const { globby } = await import('globby');
204
- const migrations = await globby([`${directory}/*.js`, `${directory}/*.cjs`]);
228
+ const migrations = await glob([`${directory}/*.js`, `${directory}/*.cjs`], {
229
+ absolute: true,
230
+ });
205
231
  const environmentId = client.sys.id;
206
232
  const filtered = migrations.filter((file) => {
207
233
  const name = path.basename(file);
@@ -210,11 +236,13 @@ const migrateToContentStorage = async (config) => {
210
236
  return version && parseInt(version, 10) >= parseInt(num, 10);
211
237
  });
212
238
 
213
- console.log(`\nFound ${pc.green(filtered.length)} executed migrations in environment ${pc.green(environmentId)}`);
239
+ console.log(
240
+ `\nFound ${pc.green(filtered.length)} executed migrations in environment ${pc.green(environmentId)}`,
241
+ );
214
242
 
215
243
  const bar = new cliProgress.SingleBar(
216
- { format: 'Adding content-entries: {value}/{total} | ETA: {eta}s' },
217
- cliProgress.Presets.legacy
244
+ { format: "Adding content-entries: {value}/{total} | ETA: {eta}s" },
245
+ cliProgress.Presets.legacy,
218
246
  );
219
247
  let progress = 0;
220
248
 
@@ -223,7 +251,10 @@ const migrateToContentStorage = async (config) => {
223
251
  const name = path.basename(file);
224
252
  const [, num] = /^(\d+)-/.exec(name);
225
253
 
226
- await addMigrationEntry({ version: num, name, state: STATE_SUCCESS }, config);
254
+ await addMigrationEntry(
255
+ { version: num, name, state: STATE_SUCCESS },
256
+ config,
257
+ );
227
258
  progress++;
228
259
  bar.update(progress);
229
260
  }
@@ -235,7 +266,7 @@ const migrateToContentStorage = async (config) => {
235
266
  await migrationTag.delete();
236
267
  } catch {}
237
268
  }
238
- console.log('All done 👍🏼');
269
+ console.log("All done 👍🏼");
239
270
  };
240
271
 
241
272
  /**
@@ -248,24 +279,30 @@ const migrateToTagStorage = async (config) => {
248
279
  const oldVersion = await getMigrationVersionFromTag(config);
249
280
  if (migrationContentTypeId) {
250
281
  const client = await getEnvironment(config);
251
- const { items } = await client.getEntries({ content_type: migrationContentTypeId });
282
+ const { items } = await client.getEntries({
283
+ content_type: migrationContentTypeId,
284
+ });
252
285
 
253
286
  const version =
254
287
  items.length &&
255
288
  Math.max(
256
289
  ...items
257
- .filter((item) => item?.fields?.state?.[defaultLocale] === STATE_SUCCESS)
258
- .map((item) => parseInt(item.sys.id, 10))
290
+ .filter(
291
+ (item) => item?.fields?.state?.[defaultLocale] === STATE_SUCCESS,
292
+ )
293
+ .map((item) => parseInt(item.sys.id, 10)),
259
294
  );
260
295
 
261
296
  if (version && (oldVersion || 0) < version) {
262
- console.log(`\nAdding ${pc.green(fieldId)} tag with version ${pc.green(version)}`);
297
+ console.log(
298
+ `\nAdding ${pc.green(fieldId)} tag with version ${pc.green(version)}`,
299
+ );
263
300
  await setMigrationTag(version, config);
264
301
  }
265
302
 
266
303
  const bar = new cliProgress.SingleBar(
267
- { format: 'Removing content-entries: {value}/{total} | ETA: {eta}s' },
268
- cliProgress.Presets.legacy
304
+ { format: "Removing content-entries: {value}/{total} | ETA: {eta}s" },
305
+ cliProgress.Presets.legacy,
269
306
  );
270
307
  let progress = 0;
271
308
 
@@ -288,7 +325,7 @@ const migrateToTagStorage = async (config) => {
288
325
  }
289
326
  }
290
327
 
291
- console.log('All done 👍🏼');
328
+ console.log("All done 👍🏼");
292
329
  };
293
330
 
294
331
  /**
@@ -358,8 +395,11 @@ const getLatestVersion = async (config) => {
358
395
 
359
396
  const getVersionFromFile = (file) => {
360
397
  const name = path.basename(file);
361
- const [, num] = /^(\d+)-/.exec(name);
362
- return parseInt(num, 10);
398
+ const versionMatch = /^\d+/.exec(name);
399
+ if (!versionMatch) {
400
+ return undefined;
401
+ }
402
+ return Number.parseInt(versionMatch[0], 10);
363
403
  };
364
404
 
365
405
  /**
@@ -368,11 +408,12 @@ const getVersionFromFile = (file) => {
368
408
  */
369
409
  const getNewMigrations = async (config) => {
370
410
  const { directory, storage, migrationContentTypeId } = config || {};
371
- const { globby } = await import('globby');
372
- const migrations = (await globby([`${directory}/*.js`, `${directory}/*.cjs`])).sort((a, b) => {
411
+ const migrations = (
412
+ await glob([`${directory}/*.js`, `${directory}/*.cjs`], { absolute: true })
413
+ ).sort((a, b) => {
373
414
  const numA = getVersionFromFile(a);
374
415
  const numB = getVersionFromFile(b);
375
- return numA - numB;
416
+ return (numA || 0) - (numB || 0);
376
417
  });
377
418
 
378
419
  if (storage === STORAGE_CONTENT) {
@@ -380,25 +421,31 @@ const getNewMigrations = async (config) => {
380
421
  const versions = await getMigrationVersions(config);
381
422
  const result = migrations.filter((file) => {
382
423
  const num = getVersionFromFile(file);
383
- return !(versions || []).includes(num);
424
+ return !!num && !(versions || []).includes(num);
384
425
  });
385
426
 
386
427
  return result;
387
- } catch (error) {
428
+ } catch {
388
429
  // check if we have a migration scheduled which adds the initial content-type
389
- const regexp = new RegExp(`createContentType\\(['"]${migrationContentTypeId}['"]\\)`, 'mg');
430
+ const regexp = new RegExp(
431
+ `createContentType\\(['"]${migrationContentTypeId}['"]\\)`,
432
+ "mg",
433
+ );
390
434
  const initial = (
391
435
  await Promise.all(
392
436
  migrations.map(async (file) => {
393
- return fs.readFile(file, 'utf8');
394
- })
437
+ return fs.readFile(file, "utf8");
438
+ }),
395
439
  )
396
440
  ).some((content) => regexp.test(content));
397
441
 
398
442
  if (initial) {
399
443
  return migrations;
400
444
  }
401
- console.error(pc.red('\nError:'), `Missing migration content type. Run ${pc.cyan('npx migrations init')}`);
445
+ console.error(
446
+ pc.red("\nError:"),
447
+ `Missing migration content type. Run ${pc.cyan("npx migrations init")}`,
448
+ );
402
449
  process.exit(1);
403
450
  }
404
451
  }
@@ -420,3 +467,4 @@ module.exports.getMigrationVersionFromTag = getMigrationVersionFromTag;
420
467
  module.exports.getLatestVersion = getLatestVersion;
421
468
  module.exports.storeMigration = storeMigration;
422
469
  module.exports.getNewMigrations = getNewMigrations;
470
+ module.exports.getVersionFromFile = getVersionFromFile;
package/lib/content.js CHANGED
@@ -61,8 +61,8 @@ const transferContent = async (config) => {
61
61
  if (sourceVersion !== destVersion) {
62
62
  throw new Error(
63
63
  `Different migration states detected. ${pc.bold(sourceEnvironmentId)} (${sourceVersion}) !== ${pc.bold(
64
- destEnvironmentId
65
- )} (${destVersion})`
64
+ destEnvironmentId,
65
+ )} (${destVersion})`,
66
66
  );
67
67
  }
68
68
 
@@ -72,7 +72,7 @@ const transferContent = async (config) => {
72
72
  entries: sourceEntries,
73
73
  assets: sourceAssetsBase,
74
74
  filteredEntries,
75
- contentTypes: sourceContentTypes,
75
+ contentTypes: _sourceContentTypes,
76
76
  } = await getContent({
77
77
  ...config,
78
78
  environmentId: sourceEnvironmentId,
@@ -147,8 +147,8 @@ const transferContent = async (config) => {
147
147
 
148
148
  console.log(
149
149
  `${br}Transfering ${pc.cyan(`${entries.length} Entries`)} and ${pc.cyan(`${assets.length} Assets`)} from ${pc.cyan(
150
- sourceEnvironmentId
151
- )} to ${pc.cyan(destEnvironmentId)}`
150
+ sourceEnvironmentId,
151
+ )} to ${pc.cyan(destEnvironmentId)}`,
152
152
  );
153
153
 
154
154
  proceed = await confirm(config);