contentful-migration 4.8.1 → 4.9.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.
Files changed (91) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/README.md +237 -140
  3. package/built/lib/action/content-type-annotate.js +27 -0
  4. package/built/lib/action/content-type-annotate.js.map +1 -0
  5. package/built/lib/action/editor-layout/editor-layout-change-field-group-control.js +23 -0
  6. package/built/lib/action/editor-layout/editor-layout-change-field-group-control.js.map +1 -0
  7. package/built/lib/action/editor-layout/editor-layout-create-field-group.js +26 -0
  8. package/built/lib/action/editor-layout/editor-layout-create-field-group.js.map +1 -0
  9. package/built/lib/action/editor-layout/editor-layout-create.js +18 -0
  10. package/built/lib/action/editor-layout/editor-layout-create.js.map +1 -0
  11. package/built/lib/action/editor-layout/editor-layout-delete-field-group.js +23 -0
  12. package/built/lib/action/editor-layout/editor-layout-delete-field-group.js.map +1 -0
  13. package/built/lib/action/editor-layout/editor-layout-delete.js +21 -0
  14. package/built/lib/action/editor-layout/editor-layout-delete.js.map +1 -0
  15. package/built/lib/action/editor-layout/editor-layout-move-field.js +24 -0
  16. package/built/lib/action/editor-layout/editor-layout-move-field.js.map +1 -0
  17. package/built/lib/action/editor-layout/editor-layout-update-field-group.js +41 -0
  18. package/built/lib/action/editor-layout/editor-layout-update-field-group.js.map +1 -0
  19. package/built/lib/action/field-annotate.js +28 -0
  20. package/built/lib/action/field-annotate.js.map +1 -0
  21. package/built/lib/action/field-rename.js +4 -0
  22. package/built/lib/action/field-rename.js.map +1 -1
  23. package/built/lib/entities/content-type.js +239 -11
  24. package/built/lib/entities/content-type.js.map +1 -1
  25. package/built/lib/fetcher.js +2 -1
  26. package/built/lib/fetcher.js.map +1 -1
  27. package/built/lib/intent/base-intent.js +47 -0
  28. package/built/lib/intent/base-intent.js.map +1 -1
  29. package/built/lib/intent/composed-intent.js +51 -1
  30. package/built/lib/intent/composed-intent.js.map +1 -1
  31. package/built/lib/intent/content-type-annotate.js +57 -0
  32. package/built/lib/intent/content-type-annotate.js.map +1 -0
  33. package/built/lib/intent/editor-layout/editor-layout-change-field-group-control.js +57 -0
  34. package/built/lib/intent/editor-layout/editor-layout-change-field-group-control.js.map +1 -0
  35. package/built/lib/intent/editor-layout/editor-layout-change-field-group-id.js +59 -0
  36. package/built/lib/intent/editor-layout/editor-layout-change-field-group-id.js.map +1 -0
  37. package/built/lib/intent/editor-layout/editor-layout-create-field-group.js +54 -0
  38. package/built/lib/intent/editor-layout/editor-layout-create-field-group.js.map +1 -0
  39. package/built/lib/intent/editor-layout/editor-layout-create.js +49 -0
  40. package/built/lib/intent/editor-layout/editor-layout-create.js.map +1 -0
  41. package/built/lib/intent/editor-layout/editor-layout-delete-field-group.js +53 -0
  42. package/built/lib/intent/editor-layout/editor-layout-delete-field-group.js.map +1 -0
  43. package/built/lib/intent/editor-layout/editor-layout-delete.js +45 -0
  44. package/built/lib/intent/editor-layout/editor-layout-delete.js.map +1 -0
  45. package/built/lib/intent/editor-layout/editor-layout-invalid-method.js +38 -0
  46. package/built/lib/intent/editor-layout/editor-layout-invalid-method.js.map +1 -0
  47. package/built/lib/intent/editor-layout/editor-layout-move-field.js +81 -0
  48. package/built/lib/intent/editor-layout/editor-layout-move-field.js.map +1 -0
  49. package/built/lib/intent/editor-layout/editor-layout-update-field-group.js +57 -0
  50. package/built/lib/intent/editor-layout/editor-layout-update-field-group.js.map +1 -0
  51. package/built/lib/intent/field-annotate.js +57 -0
  52. package/built/lib/intent/field-annotate.js.map +1 -0
  53. package/built/lib/intent/index.js +23 -1
  54. package/built/lib/intent/index.js.map +1 -1
  55. package/built/lib/intent-list/index.js +4 -0
  56. package/built/lib/intent-list/index.js.map +1 -1
  57. package/built/lib/interfaces/annotation.js +86 -0
  58. package/built/lib/interfaces/annotation.js.map +1 -0
  59. package/built/lib/migration-chunks/validation/editor-layout.js +305 -0
  60. package/built/lib/migration-chunks/validation/editor-layout.js.map +1 -0
  61. package/built/lib/migration-chunks/validation/errors.js +91 -0
  62. package/built/lib/migration-chunks/validation/errors.js.map +1 -1
  63. package/built/lib/migration-chunks/validation/field.js +24 -23
  64. package/built/lib/migration-chunks/validation/field.js.map +1 -1
  65. package/built/lib/migration-chunks/validation/index.js +16 -3
  66. package/built/lib/migration-chunks/validation/index.js.map +1 -1
  67. package/built/lib/migration-parser.js +1 -1
  68. package/built/lib/migration-parser.js.map +1 -1
  69. package/built/lib/migration-steps/action-creators.js +164 -0
  70. package/built/lib/migration-steps/action-creators.js.map +1 -1
  71. package/built/lib/migration-steps/index.js +111 -3
  72. package/built/lib/migration-steps/index.js.map +1 -1
  73. package/built/lib/offline-api/index.js +13 -4
  74. package/built/lib/offline-api/index.js.map +1 -1
  75. package/built/lib/offline-api/validator/annotations.js +76 -0
  76. package/built/lib/offline-api/validator/annotations.js.map +1 -0
  77. package/built/lib/offline-api/validator/editor-interface.js +16 -0
  78. package/built/lib/offline-api/validator/editor-interface.js.map +1 -0
  79. package/built/lib/offline-api/validator/errors.js +21 -0
  80. package/built/lib/offline-api/validator/errors.js.map +1 -1
  81. package/built/lib/offline-api/validator/field-groups-count.js +34 -0
  82. package/built/lib/offline-api/validator/field-groups-count.js.map +1 -0
  83. package/built/lib/offline-api/validator/schema/editor-layout-schema.js +46 -0
  84. package/built/lib/offline-api/validator/schema/editor-layout-schema.js.map +1 -0
  85. package/built/lib/offline-api/validator/schema/schema-validation.js +42 -1
  86. package/built/lib/offline-api/validator/schema/schema-validation.js.map +1 -1
  87. package/built/lib/utils/editor-layout.js +60 -0
  88. package/built/lib/utils/editor-layout.js.map +1 -0
  89. package/docs/validation.md +104 -0
  90. package/index.d.ts +87 -0
  91. package/package.json +2 -2
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  ![header](./.github/header.png)
2
+
2
3
  <p align="center">
3
4
  <a href="https://www.contentful.com/slack/">
4
5
  <img src="https://img.shields.io/badge/-Join%20Community%20Slack-2AB27B.svg?logo=slack&maxAge=31557600" alt="Join Contentful Community Slack">
@@ -25,7 +26,6 @@
25
26
  </a>
26
27
  </p>
27
28
 
28
-
29
29
  <p align="center">
30
30
  <a href="https://www.npmjs.com/package/contentful-migration">
31
31
  <img src="https://img.shields.io/npm/v/contentful-migration.svg" alt="NPM">
@@ -67,7 +67,7 @@
67
67
  - [`deriveLinkedEntries(config)` Example](#derivelinkedentriesconfig-example)
68
68
  - [`transformEntriesToType(config)`](#transformentriestotypeconfig)
69
69
  - [`transformEntriesToType` Example](#transformentriestotype-example)
70
- - [`createTag(id[, opts])`](#createtagid-opts)
70
+ - [`createTag(id[, opts, visibility])`](#createtagid-opts-visibility)
71
71
  - [`editTag(id[, opts])`](#edittagid-opts)
72
72
  - [`deleteTag(id)`](#deletetagid)
73
73
  - [`setTagsForEntries(config)`](#settagsforentriesconfig)
@@ -92,11 +92,24 @@
92
92
  - [`configureEntryEditor (widgetNamespace, widgetId[, settings])` : void](#configureentryeditor-widgetnamespace-widgetid-settings--void)
93
93
  - [`configureEntryEditors (EntryEditor[])` : void](#configureentryeditors-entryeditor--void)
94
94
  - [`resetEntryEditorToDefault ()` : void](#resetentryeditortodefault---void)
95
+ - [`createEditorLayout ()` : EditorLayout](#createeditorlayout---editorlayout)
96
+ - [`editEditorLayout ()` : EditorLayout](#editeditorlayout---editorlayout)
97
+ - [`deleteEditorLayout ()` : void](#deleteeditorlayout---void)
95
98
  - [Field](#field)
99
+ - [Editor Layout](#editor-layout)
100
+ - [`moveField(id)` : MovableEditorLayoutItem](#movefieldid--movableeditorlayoutitem)
101
+ - [`createFieldGroup(id[, opts])` : EditorLayoutFieldGroup](#createfieldgroupid-opts--editorlayoutfieldgroup)
102
+ - [`deleteFieldGroup (id)` : void](#deletefieldgroup-id--void)
103
+ - [`changeFieldGroupId (currentId, newId)`](#changefieldgroupid-currentid-newid)
104
+ - [`editFieldGroup (id[, opts])` : EditorLayoutFieldGroup](#editfieldgroup-id-opts--editorlayoutfieldgroup)
105
+ - [Editor Layout Field Group](#editor-layout-field-group)
106
+ - [`createFieldGroup (id[, opts])` : EditorLayoutFieldGroup](#createfieldgroup-id-opts--editorlayoutfieldgroup)
107
+ - [`changeFieldGroupControl (id, widgetNamespace, widgetId[, settings])` : void](#changefieldgroupcontrol-id-widgetnamespace-widgetid-settings--void)
96
108
  - [Validation errors](#validation-errors)
97
109
  - [Example migrations](#example-migrations)
98
110
  - [Writing Migrations in Typescript](#writing-migrations-in-typescript)
99
111
  - [Troubleshooting](#troubleshooting)
112
+ - [Updating Integration tests fixtures](#updating-integration-tests-fixtures)
100
113
  - [Reach out to us](#reach-out-to-us)
101
114
  - [You have questions about how to use this library?](#you-have-questions-about-how-to-use-this-library)
102
115
  - [You found a bug or want to propose a feature?](#you-found-a-bug-or-want-to-propose-a-feature)
@@ -150,6 +163,7 @@ npm install contentful-migration
150
163
  > We moved the CLI version of this tool into our [Contentful CLI](https://github.com/contentful/contentful-cli). This allows our users to use and install only one single CLI tool to get the full Contentful experience.
151
164
  >
152
165
  > Please have a look at the [Contentful CLI migration command documentation](https://github.com/contentful/contentful-cli/tree/master/docs/space/migration) to learn more about how to use this as command line tool.
166
+
153
167
  ### Usage as a library
154
168
 
155
169
  ```javascript
@@ -168,10 +182,10 @@ In your migration description file, export a function that accepts the `migratio
168
182
 
169
183
  ```javascript
170
184
  module.exports = function (migration, context) {
171
- const dog = migration.createContentType('dog');
172
- const name = dog.createField('name');
173
- name.type('Symbol').required(true);
174
- };
185
+ const dog = migration.createContentType('dog')
186
+ const name = dog.createField('name')
187
+ name.type('Symbol').required(true)
188
+ }
175
189
  ```
176
190
 
177
191
  You can also pass the function directly. For example:
@@ -179,10 +193,10 @@ You can also pass the function directly. For example:
179
193
  ```javascript
180
194
  const { runMigration } = require('contentful-migration')
181
195
 
182
- function migrationFunction (migration, context) {
183
- const dog = migration.createContentType('dog');
184
- const name = dog.createField('name');
185
- name.type('Symbol').required(true);
196
+ function migrationFunction(migration, context) {
197
+ const dog = migration.createContentType('dog')
198
+ const name = dog.createField('name')
199
+ name.type('Symbol').required(true)
186
200
  }
187
201
 
188
202
  const options = {
@@ -192,39 +206,40 @@ const options = {
192
206
  }
193
207
 
194
208
  runMigration(options)
195
- .then(() => console.log('Migration Done!'))
196
- .catch((e) => console.error(e))
209
+ .then(() => console.log('Migration Done!'))
210
+ .catch((e) => console.error(e))
197
211
  ```
198
212
 
199
213
  ## Documentation & References
200
214
 
201
215
  ### Configuration
202
216
 
203
- | Name | Default | Type | Description | Required |
204
- |-------------------|------------|---------|-------------------------------------------------------------|----------|
205
- | filePath | | string | The path to the migration file | if `migrationFunction` is not supplied |
206
- | migrationFunction | | function| Specify the migration function directly. See the [expected signature](https://github.com/contentful/contentful-migration/blob/4b9dcae0e7616da9153d0fa481871978595049e7/index.d.ts#L506). | if `filePath` is not supplied |
207
- | spaceId | | string | ID of the space to run the migration script on | true |
208
- | environmentId | `'master'` | string | ID of the environment within the space to run the | false |
209
- | accessToken | | string | The access token to use | true |
210
- | yes | false | boolean | Skips any confirmation before applying the migration,script | false |
211
- | retryLimit | 5 | number | Number of retries before failure (every subsequent retry will increase the timeout to the previous retry by about 1.5 seconds) | false |
212
- | requestBatchSize | 100 | number | Limit for every single request | false |
213
- | headers | | object | Additional headers to attach to the requests | false |
217
+ | Name | Default | Type | Description | Required |
218
+ | ----------------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- |
219
+ | filePath | | string | The path to the migration file | if `migrationFunction` is not supplied |
220
+ | migrationFunction | | function | Specify the migration function directly. See the [expected signature](https://github.com/contentful/contentful-migration/blob/4b9dcae0e7616da9153d0fa481871978595049e7/index.d.ts#L506). | if `filePath` is not supplied |
221
+ | spaceId | | string | ID of the space to run the migration script on | true |
222
+ | environmentId | `'master'` | string | ID of the environment within the space to run the | false |
223
+ | accessToken | | string | The access token to use | true |
224
+ | yes | false | boolean | Skips any confirmation before applying the migration,script | false |
225
+ | retryLimit | 5 | number | Number of retries before failure (every subsequent retry will increase the timeout to the previous retry by about 1.5 seconds) | false |
226
+ | requestBatchSize | 100 | number | Limit for every single request | false |
227
+ | headers | | object | Additional headers to attach to the requests | false |
214
228
 
215
229
  ### Chaining vs Object notation
216
230
 
217
231
  All methods described below can be used in two flavors:
218
232
 
219
- 1. The chained approach:
233
+ 1. The chained approach:
220
234
 
221
235
  ```javascript
222
- const author = migration.createContentType('author')
236
+ const author = migration
237
+ .createContentType('author')
223
238
  .name('Author')
224
239
  .description('Author of blog posts or pages')
225
240
  ```
226
241
 
227
- 1. The object approach:
242
+ 1. The object approach:
228
243
 
229
244
  ```javascript
230
245
  const author = migration.createContentType('author', {
@@ -247,7 +262,7 @@ Creates a content type with provided `id` and returns a reference to the newly c
247
262
 
248
263
  **`opts : Object`** – Content type definition, with the following options:
249
264
 
250
- - **`name : string`** – Name of the content type.
265
+ - **`name : string`** – Name of the content type.
251
266
  - **`description : string`** – Description of the content type.
252
267
  - **`displayField : string`** – ID of the field to use as the display field for the content type. This is referred to as the "Entry title" in the web application.
253
268
 
@@ -271,27 +286,26 @@ The transform function is expected to return an object with the desired target f
271
286
  - **`from : array`** _(required)_ – Array of the source field IDs
272
287
  - **`to : array`** _(required)_ – Array of the target field IDs
273
288
  - **`transformEntryForLocale : function (fields, locale): object`** _(required)_ – Transformation function to be applied.
274
- - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
275
- - `locale` one of the locales in the space being transformed
276
- The return value must be an object with the same keys as specified in `to`. Their values will be written to the respective entry fields for the current locale (i.e. `{nameField: 'myNewValue'}`). If it returns `undefined`, this the values for this locale on the entry will be left untouched.
289
+ - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
290
+ - `locale` one of the locales in the space being transformed
291
+ The return value must be an object with the same keys as specified in `to`. Their values will be written to the respective entry fields for the current locale (i.e. `{nameField: 'myNewValue'}`). If it returns `undefined`, this the values for this locale on the entry will be left untouched.
277
292
  - **`shouldPublish : bool | 'preserve'`** _(optional)_ – Flag that specifies publishing of target entries, `preserve` will keep current states of the source entries (default `'preserve'`)
278
293
 
279
-
280
294
  ##### `transformEntries` Example
281
295
 
282
296
  ```javascript
283
297
  migration.transformEntries({
284
- contentType: 'newsArticle',
285
- from: ['author', 'authorCity'],
286
- to: ['byline'],
287
- transformEntryForLocale: function (fromFields, currentLocale) {
288
- if (currentLocale === 'de-DE') {
289
- return;
290
- }
291
- const newByline = `${fromFields.author[currentLocale]} ${fromFields.authorCity[currentLocale]}`;
292
- return { byline: newByline };
298
+ contentType: 'newsArticle',
299
+ from: ['author', 'authorCity'],
300
+ to: ['byline'],
301
+ transformEntryForLocale: function (fromFields, currentLocale) {
302
+ if (currentLocale === 'de-DE') {
303
+ return
293
304
  }
294
- });
305
+ const newByline = `${fromFields.author[currentLocale]} ${fromFields.authorCity[currentLocale]}`
306
+ return { byline: newByline }
307
+ }
308
+ })
295
309
  ```
296
310
 
297
311
  For the complete version, please refer to [this example](./examples/12-transform-content.js).
@@ -315,9 +329,11 @@ The derive function is expected to return an object with the desired target fiel
315
329
  - **`derivedFields : array`** _(required)_ – Array of the field IDs on the target content type
316
330
 
317
331
  - **`identityKey: function (fields): string`** _(required)_ - Called once per source entry. Returns the ID used for the derived entry, which is also used for de-duplication so that multiple source entries can link to the same derived entry.
332
+
318
333
  - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
319
334
 
320
335
  - **`deriveEntryForLocale : function (fields, locale): object`** _(required)_ – Function that generates the field values for the derived entry.
336
+
321
337
  - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
322
338
  - `locale` one of the locales in the space being transformed
323
339
 
@@ -325,31 +341,30 @@ The derive function is expected to return an object with the desired target fiel
325
341
 
326
342
  - **`shouldPublish : bool|'preserve'`** _(optional)_ – If true, both the source and the derived entries will be published. If false, both will remain in draft state. If preserve, will keep current states of the source entries (default `true`)
327
343
 
328
-
329
344
  ##### `deriveLinkedEntries(config)` Example
330
345
 
331
346
  ```javascript
332
347
  migration.deriveLinkedEntries({
333
- contentType: 'dog',
334
- derivedContentType: 'owner',
335
- from: ['owner'],
336
- toReferenceField: 'ownerRef',
337
- derivedFields: ['firstName', 'lastName'],
338
- identityKey: async (fromFields) => {
339
- return fromFields.owner['en-US'].toLowerCase().replace(' ', '-');
340
- },
341
- shouldPublish: true,
342
- deriveEntryForLocale: async (inputFields, locale) => {
343
- if (locale !== 'en-US') {
344
- return;
345
- }
346
- const [firstName, lastName] = inputFields.owner[locale].split(' ');
347
- return {
348
- firstName,
349
- lastName
350
- };
348
+ contentType: 'dog',
349
+ derivedContentType: 'owner',
350
+ from: ['owner'],
351
+ toReferenceField: 'ownerRef',
352
+ derivedFields: ['firstName', 'lastName'],
353
+ identityKey: async (fromFields) => {
354
+ return fromFields.owner['en-US'].toLowerCase().replace(' ', '-')
355
+ },
356
+ shouldPublish: true,
357
+ deriveEntryForLocale: async (inputFields, locale) => {
358
+ if (locale !== 'en-US') {
359
+ return
360
+ }
361
+ const [firstName, lastName] = inputFields.owner[locale].split(' ')
362
+ return {
363
+ firstName,
364
+ lastName
351
365
  }
352
- });
366
+ }
367
+ })
353
368
  ```
354
369
 
355
370
  For the complete version of this migration, please refer to [this example](./examples/15-derive-entry-n-to-1.js).
@@ -368,33 +383,34 @@ For the given (source) content type, transforms all its entries according to the
368
383
  - **`updateReferences : bool`** _(optional)_ – Flag that specifies if linking entries should be updated with target entries (default `false`). Note that this flag does not support Rich Text Fields references.
369
384
  - **`removeOldEntries : bool`** _(optional)_ – Flag that specifies if source entries should be deleted (default `false`)
370
385
  - **`transformEntryForLocale : function (fields, locale): object`** _(required)_ – Transformation function to be applied.
371
- - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
372
- - `locale` one of the locales in the space being transformed
386
+
387
+ - `fields` is an object containing each of the `from` fields. Each field will contain their current localized values (i.e. `fields == {myField: {'en-US': 'my field value'}}`)
388
+ - `locale` one of the locales in the space being transformed
373
389
 
374
390
  The return value must be an object with the same keys as specified in the `targetContentType`. Their values will be written to the respective entry fields for the current locale (i.e. `{nameField: 'myNewValue'}`). If it returns `undefined`, this the values for this locale on the entry will be left untouched.
375
391
 
376
392
  ##### `transformEntriesToType` Example
377
393
 
378
394
  ```javascript
379
- const MurmurHash3 = require('imurmurhash');
395
+ const MurmurHash3 = require('imurmurhash')
380
396
 
381
397
  migration.transformEntriesToType({
382
- sourceContentType: 'dog',
383
- targetContentType: 'copycat',
384
- from: ['woofs'],
385
- shouldPublish: false,
386
- updateReferences: false,
387
- removeOldEntries: false,
388
- identityKey: function (fields) {
389
- const value = fields.woofs['en-US'].toString();
390
- return MurmurHash3(value).result().toString();
391
- },
392
- transformEntryForLocale: function (fromFields, currentLocale) {
393
- return {
394
- woofs: `copy - ${fromFields.woofs[currentLocale]}`
395
- };
398
+ sourceContentType: 'dog',
399
+ targetContentType: 'copycat',
400
+ from: ['woofs'],
401
+ shouldPublish: false,
402
+ updateReferences: false,
403
+ removeOldEntries: false,
404
+ identityKey: function (fields) {
405
+ const value = fields.woofs['en-US'].toString()
406
+ return MurmurHash3(value).result().toString()
407
+ },
408
+ transformEntryForLocale: function (fromFields, currentLocale) {
409
+ return {
410
+ woofs: `copy - ${fromFields.woofs[currentLocale]}`
396
411
  }
397
- });
412
+ }
413
+ })
398
414
  ```
399
415
 
400
416
  For the complete version of this migration, please refer to [this example](./examples/22-transform-entries-to-type.js).
@@ -407,7 +423,7 @@ Creates a tag with provided `id` and returns a reference to the newly created ta
407
423
 
408
424
  - **`opts : Object`** – Tag definition, with the following options:
409
425
 
410
- - **`name : string`** – Name of the tag.
426
+ - **`name : string`** – Name of the tag.
411
427
 
412
428
  - **`visibility : 'private' | 'public'`** Tag visibility - defaults to `private`.
413
429
 
@@ -428,22 +444,19 @@ For the given content type, updates the tags that are attached to its entries ac
428
444
 
429
445
  - **`contentType : string`** _(required)_ – Content type ID
430
446
  - **`from : array`** _(required)_ – Array of the source field IDs
431
- - **`setTagsForEntry : function (entryFields, entryTags, apiTags): array`** _(required)_ – Transformation function to be applied.
432
- - `entryFields` is an object containing each of the `from` fields.
433
- - `entryTags` is an array containing link objects of all tags
434
- already attached to the entry.
435
- - `apiTags` is an array containing link objects of all tags
436
- available in the environment.
447
+ - **`setTagsForEntry : function (entryFields, entryTags, apiTags): array`** _(required)_ – Transformation function to be applied. - `entryFields` is an object containing each of the `from` fields. - `entryTags` is an array containing link objects of all tags
448
+ already attached to the entry. - `apiTags` is an array containing link objects of all tags
449
+ available in the environment.
437
450
 
438
451
  ##### `setTagsForEntries` Example
439
452
 
440
- ``` javascript
453
+ ```javascript
441
454
  migration.createTag('department-sf').name('Department: San Francisco')
442
455
  migration.createTag('department-ldn').name('Department: London')
443
456
 
444
457
  const departmentMapping = {
445
458
  'san-francisco': 'department-sf',
446
- 'london': 'department-ldn'
459
+ london: 'department-ldn'
447
460
  }
448
461
 
449
462
  migration.setTagsForEntries({
@@ -453,11 +466,7 @@ migration.setTagsForEntries({
453
466
  const departmentField = entryFields.department['en-US']
454
467
  const newTag = apiTags.find((tag) => tag.sys.id === departmentMapping[departmentField])
455
468
 
456
- return [
457
- ...entryTags,
458
- newTag,
459
- ]
460
-
469
+ return [...entryTags, newTag]
461
470
  }
462
471
  })
463
472
  ```
@@ -471,10 +480,10 @@ module.exports = async function (migration, { makeRequest, spaceId, accessToken
471
480
  const contentType = await makeRequest({
472
481
  method: 'GET',
473
482
  url: `/content_types?sys.id[in]=foo`
474
- });
483
+ })
475
484
 
476
485
  const anyOtherTool = new AnyOtherTool({ spaceId, accessToken })
477
- };
486
+ }
478
487
  ```
479
488
 
480
489
  #### `makeRequest(config)`
@@ -482,8 +491,9 @@ module.exports = async function (migration, { makeRequest, spaceId, accessToken
482
491
  The function used by the migration object to talk to the Contentful Management API. This can be useful if you want to use API features that may not be supported by the `migration` object.
483
492
 
484
493
  `config : Object` - Configuration for the request based on [the Contentful management SDK](https://contentful.github.io/contentful-management.js/contentful-management/7.3.0/globals.html#http)
485
- - `method` : `string` – HTTP method
486
- - `url` : `string` - HTTP endpoint
494
+
495
+ - `method` : `string` HTTP method
496
+ - `url` : `string` - HTTP endpoint
487
497
 
488
498
  ```javascript
489
499
  module.exports = async function (migration, { makeRequest }) {
@@ -491,7 +501,7 @@ module.exports = async function (migration, { makeRequest }) {
491
501
  method: 'GET',
492
502
  url: `/content_types?sys.id[in]=foo`
493
503
  })
494
- };
504
+ }
495
505
  ```
496
506
 
497
507
  #### `spaceId` : `string`
@@ -502,7 +512,6 @@ The space ID that was set for the current migration.
502
512
 
503
513
  The access token that was set for the current migration.
504
514
 
505
-
506
515
  ### Content type
507
516
 
508
517
  For a comprehensive guide to content modelling, please refer to [this guide](https://www.contentful.com/developers/docs/concepts/data-model/).
@@ -511,7 +520,7 @@ For a comprehensive guide to content modelling, please refer to [this guide](htt
511
520
 
512
521
  Creates a field with provided `id`.
513
522
 
514
- **`id : string`** – The ID of the field.
523
+ **`id : string`** – The ID of the field.
515
524
 
516
525
  **`opts : Object`** – Field definition, with the following options:
517
526
 
@@ -548,19 +557,18 @@ Creates a field with provided `id`.
548
557
  Example:
549
558
 
550
559
  ```javascript
551
- validations: [
552
- { in: [ 'Web', 'iOS', 'Android' ] }
553
- ]
560
+ validations: [{ in: ['Web', 'iOS', 'Android'] }]
554
561
  ```
555
562
 
556
563
  _See [The CMA documentation](https://www.contentful.com/developers/docs/references/content-management-api/#/reference/content-types/content-type) for the list of available validations._
564
+
557
565
  - **`localized : boolean`** – Sets the field as localized.
558
566
  - **`disabled : boolean`** – Sets the field as disabled, hence not editable by authors.
559
567
  - **`omitted : boolean`** – Sets the field as omitted, hence not sent in response.
560
568
  - **`deleted : boolean`** – Sets the field as deleted. Requires to have been `omitted` first.
561
569
  _You may prefer using the `deleteField` method._
562
- - **`defaultValue : Object`** – Sets the default value for the field.
563
- Example:
570
+ - **`defaultValue : Object`** – Sets the default value for the field.
571
+ Example:
564
572
 
565
573
  ```javascript
566
574
  defaultValue: {
@@ -606,35 +614,26 @@ Move the field (position of the field in the web editor)
606
614
  - **`.afterField(fieldId)`**
607
615
 
608
616
  Example:
617
+
609
618
  ```javascript
610
619
  module.exports = function (migration) {
611
- const food = migration.editContentType('food');
620
+ const food = migration.editContentType('food')
612
621
 
613
- food.createField('calories')
614
- .type('Number')
615
- .name('How many calories does it have?');
622
+ food.createField('calories').type('Number').name('How many calories does it have?')
616
623
 
617
- food.createField('sugar')
618
- .type('Number')
619
- .name('Amount of sugar');
624
+ food.createField('sugar').type('Number').name('Amount of sugar')
620
625
 
621
- food.createField('vegan')
622
- .type('Boolean')
623
- .name('Vegan friendly');
626
+ food.createField('vegan').type('Boolean').name('Vegan friendly')
624
627
 
625
- food.createField('producer')
626
- .type('Symbol')
627
- .name('Food producer');
628
+ food.createField('producer').type('Symbol').name('Food producer')
628
629
 
629
- food.createField('gmo')
630
- .type('Boolean')
631
- .name('Genetically modified food');
630
+ food.createField('gmo').type('Boolean').name('Genetically modified food')
632
631
 
633
- food.moveField('calories').toTheTop();
634
- food.moveField('sugar').toTheBottom();
635
- food.moveField('producer').beforeField('vegan');
636
- food.moveField('gmo').afterField('vegan');
637
- };
632
+ food.moveField('calories').toTheTop()
633
+ food.moveField('sugar').toTheBottom()
634
+ food.moveField('producer').beforeField('vegan')
635
+ food.moveField('gmo').afterField('vegan')
636
+ }
638
637
  ```
639
638
 
640
639
  #### `changeFieldControl (fieldId, widgetNamespace, widgetId[, settings])` : void
@@ -644,6 +643,7 @@ Changes control interface of given field's ID.
644
643
  **`fieldId : string`** – The ID of the field.
645
644
 
646
645
  **`widgetNamespace : string`** – The namespace of the widget, one of the following values:
646
+
647
647
  - `builtin` (Standard widget)
648
648
  - `app` (Custom App)
649
649
  - `extension` (Custom UI extension)
@@ -678,6 +678,7 @@ Changes control interface of given field's ID.
678
678
  Adds a builtin or custom widget to the sidebar of the content type.
679
679
 
680
680
  **`widgetNamespace: string`** – The namespace of the widget, one of the following values:
681
+
681
682
  - `sidebar-builtin` (Standard widget, default)
682
683
  - `extension` (Custom UI extension)
683
684
 
@@ -692,6 +693,7 @@ Adds a builtin or custom widget to the sidebar of the content type.
692
693
  Updates the configuration of a widget in the sidebar of the content type.
693
694
 
694
695
  **`widgetNamespace: string`** – The namespace of the widget, one of the following values:
696
+
695
697
  - `sidebar-builtin` (Standard widget, default)
696
698
  - `extension` (Custom UI extension)
697
699
 
@@ -704,6 +706,7 @@ Updates the configuration of a widget in the sidebar of the content type.
704
706
  Removes a widget from the sidebar of the content type.
705
707
 
706
708
  **`widgetNamespace: string`** – The namespace of the widget, one of the following values:
709
+
707
710
  - `sidebar-builtin` (Standard widget, default)
708
711
  - `extension` (Custom UI extension)
709
712
 
@@ -735,10 +738,106 @@ Each `EntryEditor` has the following properties:
735
738
 
736
739
  Resets the entry editor of the content type to default.
737
740
 
741
+ #### `createEditorLayout ()` : [EditorLayout](#editor-layout)
742
+
743
+ Creates an empty editor layout for this content type.
744
+
745
+ #### `editEditorLayout ()` : [EditorLayout](#editor-layout)
746
+
747
+ Edits the editor layout for this content type.
748
+
749
+ #### `deleteEditorLayout ()` : void
750
+
751
+ Deletes the editor layout for this content type.
752
+
753
+ #### `setAnnotations(AnnotationId[])`
754
+
755
+ Configure the annotations assigned to this content type. See [annotations documentation](https://www.contentful.com/developers/docs/references/content-management-api/#annotations) for more details on valid `AnnotationId`.
756
+
757
+ #### `clearAnnotations()`
758
+
759
+ Remove all assigned annotations from this content type
760
+
738
761
  ### Field
739
762
 
740
763
  The field object has the same methods as the properties listed in the [`ContentType.createField`](#createfieldid--string-opts--object--field) method.
741
764
 
765
+ In addition the following methods allow to manage field annotations.
766
+
767
+ #### `setAnnotations(AnnotationId[])`
768
+
769
+ Configure the annotations assigned to this field. See [annotations documentation](https://www.contentful.com/developers/docs/references/content-management-api/#annotations) for more details on valid `AnnotationId`.
770
+
771
+ #### `clearAnnotations()`
772
+
773
+ Remove all assigned annotations from this field.
774
+
775
+ ### Editor Layout
776
+
777
+ #### `moveField(id)` : MovableEditorLayoutItem
778
+
779
+ Moves the field with the provided `id`.
780
+
781
+ `moveField(id)` returns a movable editor layout item type which must be called with a direction function:
782
+
783
+ - **`.toTheTopOfFieldGroup(groupId)`**
784
+ - - if no `groupId` is provided, the field will be moved within its group
785
+ - **`.toTheBottomOfFieldGroup(groupId)`**
786
+ - - if no `groupId` is provided, the field will be moved within its group
787
+ - **`.beforeFieldGroup(groupId)`**
788
+ - **`.afterFieldGroup(groupId)`**
789
+ - **`.beforeField(fieldId)`**
790
+ - **`.afterField(fieldId)`**
791
+
792
+ #### `createFieldGroup(id[, opts])` : [EditorLayoutFieldGroup](#editor-layout-field-group)
793
+
794
+ Creates a tab with the provided `id`.
795
+
796
+ **`id : string`** – The ID of the group.
797
+
798
+ **`opts : Object`** – Group settings, with the following options:
799
+
800
+ - **`name : string`** _(required)_ – Group name.
801
+
802
+ #### `deleteFieldGroup (id)` : void
803
+
804
+ Deletes the group with the provided `id` from the editor layout,
805
+ moving its contents to the parent if the group to delete is a field set or to the default tab if it’s a tab.
806
+
807
+ #### `changeFieldGroupId (currentId, newId)`
808
+
809
+ Changes the group’s ID.
810
+
811
+ **`currentId : string`** – The current ID of the group.
812
+
813
+ **`newId : string`** – The new ID for the group.
814
+
815
+ #### `editFieldGroup (id[, opts])` : [EditorLayoutFieldGroup](#editor-layout-field-group)
816
+
817
+ ### Editor Layout Field Group
818
+
819
+ #### `createFieldGroup (id[, opts])` : [EditorLayoutFieldGroup](#editor-layout-field-group)
820
+
821
+ Creates a field set with the provided `id`.
822
+
823
+ **`id : string`** – The ID of the group.
824
+
825
+ **`opts : Object`** – Group settings, with the following options:
826
+
827
+ - **`name : string`** _(required)_ – Group name.
828
+
829
+ #### `changeFieldGroupControl (id, widgetNamespace, widgetId[, settings])` : void
830
+
831
+ Sets the group control for a field group.
832
+
833
+ **`widgetNamespace : string`** – The namespace for the group control. Currently allowed: `builtin`.
834
+ **`widgetId : string`** - The widget ID for the group control. Allowed values: `fieldset`, `topLevelTab`.
835
+ **`settings : Object`** – Field set settings, with the following properties:
836
+
837
+ - **`helpText : string`** – Help text for the field set. Displayed when editing.
838
+ - **`collapsible : boolean`** – Whether the field set can be collapsed when editing.
839
+ - **`collapsedByDefault : string`** – Whether the field set is collapsed when opening the editor.
840
+
742
841
  ## Validation errors
743
842
 
744
843
  You can learn more from the [possible validation errors here](./docs/validation.md).
@@ -758,22 +857,21 @@ const options = {
758
857
  }
759
858
 
760
859
  const migrations = async () => {
761
- await runMigration({...options, ...{filePath: '01-angry-dog.js'}})
762
- await runMigration({...options, ...{filePath: '02-friendly-dog.js'}})
763
- await runMigration({...options, ...{filePath: '03-long-example.js'}})
764
- await runMigration({...options, ...{filePath: '04-steps-errors.js'}})
765
- await runMigration({...options, ...{filePath: '05-plan-errors.js'}})
766
- await runMigration({...options, ...{filePath: '06-delete-field.js'}})
767
- await runMigration({...options, ...{filePath: '07-display-field.js'}})
860
+ await runMigration({ ...options, ...{ filePath: '01-angry-dog.js' } })
861
+ await runMigration({ ...options, ...{ filePath: '02-friendly-dog.js' } })
862
+ await runMigration({ ...options, ...{ filePath: '03-long-example.js' } })
863
+ await runMigration({ ...options, ...{ filePath: '04-steps-errors.js' } })
864
+ await runMigration({ ...options, ...{ filePath: '05-plan-errors.js' } })
865
+ await runMigration({ ...options, ...{ filePath: '06-delete-field.js' } })
866
+ await runMigration({ ...options, ...{ filePath: '07-display-field.js' } })
768
867
  }
769
868
 
770
869
  migrations()
771
-
772
870
  ```
773
871
 
774
872
  ## Writing Migrations in Typescript
775
873
 
776
- You can use Typescript to write your migration files using `ts-node`! First `npm install --save ts-node typescript`,
874
+ You can use Typescript to write your migration files using `ts-node`! First `npm install --save ts-node typescript`,
777
875
  then run your migration with ts-node:
778
876
 
779
877
  ```bash
@@ -781,6 +879,7 @@ node_modules/.bin/ts-node node_modules/.bin/contentful-migration -s $CONTENTFUL_
781
879
  ```
782
880
 
783
881
  An example Typescript migration:
882
+
784
883
  ```typescript
785
884
  import { MigrationFunction } from 'contentful-migration'
786
885
 
@@ -791,9 +890,7 @@ export = function (migration, { makeRequest, spaceId, accessToken }) {
791
890
  })
792
891
 
793
892
  const name = dog.createField('name')
794
- name.name('Name')
795
- .type('Symbol')
796
- .required(true)
893
+ name.name('Name').type('Symbol').required(true)
797
894
  } as MigrationFunction
798
895
  ```
799
896
 
@@ -803,7 +900,7 @@ Here's how it looks inside VS Code:
803
900
 
804
901
  ## Troubleshooting
805
902
 
806
- * Unable to connect to Contentful through your Proxy? Try to set the `rawProxy` option to `true`.
903
+ - Unable to connect to Contentful through your Proxy? Try to set the `rawProxy` option to `true`.
807
904
 
808
905
  ```javascript
809
906
  runMigration({
@@ -814,8 +911,8 @@ runMigration({
814
911
  ```
815
912
 
816
913
  ## Updating Integration tests fixtures
817
- * To add new/update integration tests, you need to set environment variable `NOCK_RECORD=1` which should automatically update fixtures
818
914
 
915
+ - To add new/update integration tests, you need to set environment variable `NOCK_RECORD=1` which should automatically update fixtures
819
916
 
820
917
  ## Reach out to us
821
918