contentful-export 8.1.3 → 8.2.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 +64 -1
- package/dist/index.js +10 -3
- package/dist/parseOptions.js +1 -0
- package/dist/tasks/get-space-data.js +129 -0
- package/dist/tasks/init-client.js +8 -1
- package/dist/usageParams.js +4 -0
- package/package.json +1 -1
- package/types.d.ts +2 -1
package/README.md
CHANGED
|
@@ -216,6 +216,14 @@ Skip exporting webhooks
|
|
|
216
216
|
|
|
217
217
|
Untag assets and entries
|
|
218
218
|
|
|
219
|
+
#### `includeExperienceOrchestration` [boolean] [default: true]
|
|
220
|
+
|
|
221
|
+
Export Experience Orchestration (ExO) entities: Design Tokens, Components, Experience Templates, Data Assemblies, Experience Fragments, and Experiences.
|
|
222
|
+
|
|
223
|
+
Requires the Organization to have the `exo_m1` entitlement. If the Organization is not entitled, the export will not throw — each ExO array will be empty and a warning will be logged.
|
|
224
|
+
|
|
225
|
+
See [docs/exo-export.md](./docs/exo-export.md) for full details.
|
|
226
|
+
|
|
219
227
|
#### `contentOnly` [boolean] [default: false]
|
|
220
228
|
|
|
221
229
|
Only export entries and assets
|
|
@@ -268,6 +276,12 @@ Full path to the error log file
|
|
|
268
276
|
|
|
269
277
|
Display progress in new lines instead of displaying a busy spinner and the status in the same line. Useful for CI.
|
|
270
278
|
|
|
279
|
+
### Experience Orchestration
|
|
280
|
+
|
|
281
|
+
#### `includeExperienceOrchestration` [boolean] [default: true]
|
|
282
|
+
|
|
283
|
+
Flag controlling whether Experience Orchestration (ExO) entities — Design Tokens, Components, Experience Templates, Data Assemblies, Experience Fragments, and Experiences — are exported when present in the source space. Requires the `exoM1` entitlement on the source space's organization. Set to `false` to opt out. See the "Experience Orchestration (ExO) entities" section below for what happens when the space isn't entitled.
|
|
284
|
+
|
|
271
285
|
## :rescue_worker_helmet: Troubleshooting
|
|
272
286
|
|
|
273
287
|
### Proxy
|
|
@@ -324,12 +338,61 @@ This is an overview of the exported data:
|
|
|
324
338
|
"tags": [],
|
|
325
339
|
"webhooks": [],
|
|
326
340
|
"roles": [],
|
|
327
|
-
"editorInterfaces": []
|
|
341
|
+
"editorInterfaces": [],
|
|
342
|
+
"designTokens": [],
|
|
343
|
+
"components": [],
|
|
344
|
+
"experienceTemplates": [],
|
|
345
|
+
"dataAssemblies": [],
|
|
346
|
+
"experienceFragments": [],
|
|
347
|
+
"experiences": []
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
When `includeExperienceOrchestration: true` is set, six additional arrays are included:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"designTokens": [],
|
|
356
|
+
"components": [],
|
|
357
|
+
"experienceTemplates": [],
|
|
358
|
+
"dataAssemblies": [],
|
|
359
|
+
"experienceFragments": [],
|
|
360
|
+
"experiences": []
|
|
328
361
|
}
|
|
329
362
|
```
|
|
330
363
|
|
|
331
364
|
_Note:_ Tags feature is not available for all users. If you do not have access to this feature, the tags array will always be empty.
|
|
332
365
|
|
|
366
|
+
_Note:_ `designTokens`, `components`, `experienceTemplates`, `dataAssemblies`, `experienceFragments`, and `experiences` are Experience Orchestration (ExO) entities — present by default; absent only if you explicitly set `includeExperienceOrchestration: false` — see the "Experience Orchestration (ExO) entities" section below.
|
|
367
|
+
|
|
368
|
+
## :test_tube: Experience Orchestration (ExO) entities
|
|
369
|
+
|
|
370
|
+
Experience Orchestration (ExO) is Contentful's system for composing and rendering structured page experiences. It sits above the traditional entry/content-type layer and provides six dedicated entity types — Design Tokens, Components, Experience Templates, Data Assemblies, Experience Fragments, and Experiences — that together describe how content is fetched, assembled, and laid out.
|
|
371
|
+
|
|
372
|
+
> **Experimental:** ExO entities (`designTokens`, `components`, `experienceTemplates`, `dataAssemblies`, `experienceFragments`, `experiences`) are `@internal` and considered experimental. Their shape and export behavior are subject to change without notice.
|
|
373
|
+
|
|
374
|
+
ExO export is on by default (`includeExperienceOrchestration: true`) — for the CLI and the module API alike. Pass `includeExperienceOrchestration: false` (`--include-experience-orchestration=false` on the CLI) to opt out.
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
import contentfulExport from 'contentful-export'
|
|
378
|
+
|
|
379
|
+
const options = {
|
|
380
|
+
spaceId: '<space_id>',
|
|
381
|
+
managementToken: '<content_management_api_key>',
|
|
382
|
+
includeExperienceOrchestration: false // opt out; omit to export ExO entities when present (the default)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
await contentfulExport(options)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
If the source space has no ExO entities, or lacks the `exoM1` entitlement, each ExO entity type logs a `Skipping <Entity> export` warning and exports as an empty array — it does not fail the export. Pass `includeExperienceOrchestration: false` if you want to avoid it.
|
|
389
|
+
|
|
390
|
+
Requires the `exoM1` entitlement on the source space's organization. [contentful-cli](https://github.com/contentful/contentful-cli)'s `space export` command doesn't expose this option at all yet, so ExO export isn't reachable through that separate CLI regardless of default.
|
|
391
|
+
|
|
392
|
+
### Round-tripping into `contentful-import`
|
|
393
|
+
|
|
394
|
+
The ExO entities exported here are designed to be fed directly into [`contentful-import`](https://github.com/contentful/contentful-import), which preserves source IDs, applies dependency ordering (a topological sort for Components and Experience Fragments, since either can reference others of the same type), and upgrades entities from older, pre-rename export files automatically. See `contentful-import`'s README "Experience Orchestration (ExO) entities" section for the import-side details.
|
|
395
|
+
|
|
333
396
|
## :warning: Limitations
|
|
334
397
|
|
|
335
398
|
- This tool currently does **not** support the export of space memberships.
|
package/dist/index.js
CHANGED
|
@@ -18,8 +18,9 @@ var _formatDistance = require("date-fns/formatDistance");
|
|
|
18
18
|
var _contentfulBatchLibs = require("contentful-batch-libs");
|
|
19
19
|
var _downloadAssets = _interopRequireDefault(require("./tasks/download-assets"));
|
|
20
20
|
var _getSpaceData = _interopRequireDefault(require("./tasks/get-space-data"));
|
|
21
|
-
var _initClient =
|
|
21
|
+
var _initClient = _interopRequireWildcard(require("./tasks/init-client"));
|
|
22
22
|
var _parseOptions = _interopRequireDefault(require("./parseOptions"));
|
|
23
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
23
24
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
25
|
const accessP = _bluebird.default.promisify(_fs.access);
|
|
25
26
|
const tableOptions = {
|
|
@@ -53,6 +54,7 @@ function runContentfulExport(params) {
|
|
|
53
54
|
try {
|
|
54
55
|
// CMA client
|
|
55
56
|
ctx.client = (0, _initClient.default)(options);
|
|
57
|
+
ctx.plainClient = (0, _initClient.initPlainClient)(options);
|
|
56
58
|
if (options.deliveryToken && !options.includeDrafts) {
|
|
57
59
|
// CDA client for fetching only public entries
|
|
58
60
|
ctx.cdaClient = (0, _initClient.default)(options, true);
|
|
@@ -67,6 +69,7 @@ function runContentfulExport(params) {
|
|
|
67
69
|
task: ctx => {
|
|
68
70
|
return (0, _getSpaceData.default)({
|
|
69
71
|
client: ctx.client,
|
|
72
|
+
plainClient: ctx.plainClient,
|
|
70
73
|
cdaClient: ctx.cdaClient,
|
|
71
74
|
spaceId: options.spaceId,
|
|
72
75
|
environmentId: options.environmentId,
|
|
@@ -81,6 +84,7 @@ function runContentfulExport(params) {
|
|
|
81
84
|
skipRoles: options.skipRoles,
|
|
82
85
|
skipTags: options.skipTags,
|
|
83
86
|
stripTags: options.stripTags,
|
|
87
|
+
includeExperienceOrchestration: options.includeExperienceOrchestration,
|
|
84
88
|
listrOptions,
|
|
85
89
|
queryEntries: options.queryEntries,
|
|
86
90
|
queryAssets: options.queryAssets
|
|
@@ -114,8 +118,11 @@ function runContentfulExport(params) {
|
|
|
114
118
|
return _bfj.default.write(options.logFilePath, ctx.data, {
|
|
115
119
|
circular: 'ignore',
|
|
116
120
|
space: 2,
|
|
117
|
-
bufferLength
|
|
118
|
-
|
|
121
|
+
// Do not set `yieldRate` -- values above `bufferLength`
|
|
122
|
+
// make bfj 9's serialization quadratic and it never
|
|
123
|
+
// finishes. See DX-1343.
|
|
124
|
+
bufferLength: 65536,
|
|
125
|
+
highWaterMark: 1024 * 1024
|
|
119
126
|
});
|
|
120
127
|
}
|
|
121
128
|
}]);
|
package/dist/parseOptions.js
CHANGED
|
@@ -18,6 +18,7 @@ let pageLimit = MAX_ALLOWED_LIMIT;
|
|
|
18
18
|
*/
|
|
19
19
|
function getFullSourceSpace({
|
|
20
20
|
client,
|
|
21
|
+
plainClient,
|
|
21
22
|
cdaClient,
|
|
22
23
|
spaceId,
|
|
23
24
|
environmentId = 'master',
|
|
@@ -32,6 +33,7 @@ function getFullSourceSpace({
|
|
|
32
33
|
includeDrafts,
|
|
33
34
|
includeArchived,
|
|
34
35
|
maxAllowedLimit,
|
|
36
|
+
includeExperienceOrchestration,
|
|
35
37
|
listrOptions,
|
|
36
38
|
queryEntries,
|
|
37
39
|
queryAssets
|
|
@@ -149,6 +151,102 @@ function getFullSourceSpace({
|
|
|
149
151
|
});
|
|
150
152
|
}),
|
|
151
153
|
skip: () => skipRoles || environmentId !== 'master' && 'Roles can only be exported from master environment'
|
|
154
|
+
}, {
|
|
155
|
+
title: 'Fetching Design Tokens data',
|
|
156
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
157
|
+
try {
|
|
158
|
+
ctx.data.designTokens = await cursorPagedGet({
|
|
159
|
+
client: plainClient,
|
|
160
|
+
spaceId,
|
|
161
|
+
environmentId,
|
|
162
|
+
method: 'designToken.getMany'
|
|
163
|
+
});
|
|
164
|
+
} catch (err) {
|
|
165
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Design Tokens export: ${err.message}`);
|
|
166
|
+
ctx.data.designTokens = [];
|
|
167
|
+
}
|
|
168
|
+
}),
|
|
169
|
+
skip: () => !includeExperienceOrchestration
|
|
170
|
+
}, {
|
|
171
|
+
title: 'Fetching Components data',
|
|
172
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
173
|
+
try {
|
|
174
|
+
ctx.data.components = await cursorPagedGet({
|
|
175
|
+
client: plainClient,
|
|
176
|
+
spaceId,
|
|
177
|
+
environmentId,
|
|
178
|
+
method: 'component.getMany'
|
|
179
|
+
});
|
|
180
|
+
} catch (err) {
|
|
181
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Components export: ${err.message}`);
|
|
182
|
+
ctx.data.components = [];
|
|
183
|
+
}
|
|
184
|
+
}),
|
|
185
|
+
skip: () => !includeExperienceOrchestration
|
|
186
|
+
}, {
|
|
187
|
+
title: 'Fetching Experience Templates data',
|
|
188
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
189
|
+
try {
|
|
190
|
+
ctx.data.experienceTemplates = await cursorPagedGet({
|
|
191
|
+
client: plainClient,
|
|
192
|
+
spaceId,
|
|
193
|
+
environmentId,
|
|
194
|
+
method: 'experienceTemplate.getMany'
|
|
195
|
+
});
|
|
196
|
+
} catch (err) {
|
|
197
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Experience Templates export: ${err.message}`);
|
|
198
|
+
ctx.data.experienceTemplates = [];
|
|
199
|
+
}
|
|
200
|
+
}),
|
|
201
|
+
skip: () => !includeExperienceOrchestration
|
|
202
|
+
}, {
|
|
203
|
+
title: 'Fetching Data Assemblies data',
|
|
204
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
205
|
+
try {
|
|
206
|
+
ctx.data.dataAssemblies = await cursorPagedGet({
|
|
207
|
+
client: plainClient,
|
|
208
|
+
spaceId,
|
|
209
|
+
environmentId,
|
|
210
|
+
method: 'dataAssembly.getMany'
|
|
211
|
+
});
|
|
212
|
+
} catch (err) {
|
|
213
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Data Assemblies export: ${err.message}`);
|
|
214
|
+
ctx.data.dataAssemblies = [];
|
|
215
|
+
}
|
|
216
|
+
}),
|
|
217
|
+
skip: () => !includeExperienceOrchestration
|
|
218
|
+
}, {
|
|
219
|
+
title: 'Fetching Experience Fragments data',
|
|
220
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
221
|
+
try {
|
|
222
|
+
ctx.data.experienceFragments = await cursorPagedGet({
|
|
223
|
+
client: plainClient,
|
|
224
|
+
spaceId,
|
|
225
|
+
environmentId,
|
|
226
|
+
method: 'experienceFragment.getMany'
|
|
227
|
+
});
|
|
228
|
+
} catch (err) {
|
|
229
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Experience Fragments export: ${err.message}`);
|
|
230
|
+
ctx.data.experienceFragments = [];
|
|
231
|
+
}
|
|
232
|
+
}),
|
|
233
|
+
skip: () => !includeExperienceOrchestration
|
|
234
|
+
}, {
|
|
235
|
+
title: 'Fetching Experiences data',
|
|
236
|
+
task: (0, _contentfulBatchLibs.wrapTask)(async ctx => {
|
|
237
|
+
try {
|
|
238
|
+
ctx.data.experiences = await cursorPagedGet({
|
|
239
|
+
client: plainClient,
|
|
240
|
+
spaceId,
|
|
241
|
+
environmentId,
|
|
242
|
+
method: 'experience.getMany'
|
|
243
|
+
});
|
|
244
|
+
} catch (err) {
|
|
245
|
+
_contentfulBatchLibs.logEmitter.emit('warning', `Skipping Experiences export: ${err.message}`);
|
|
246
|
+
ctx.data.experiences = [];
|
|
247
|
+
}
|
|
248
|
+
}),
|
|
249
|
+
skip: () => !includeExperienceOrchestration
|
|
152
250
|
}], listrOptions);
|
|
153
251
|
}
|
|
154
252
|
function getEditorInterfaces(contentTypes) {
|
|
@@ -167,6 +265,37 @@ function getEditorInterfaces(contentTypes) {
|
|
|
167
265
|
});
|
|
168
266
|
}
|
|
169
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Gets all ExO entities using cursor-based pagination (pageNext/pagePrev tokens).
|
|
270
|
+
* ExO list endpoints do not support skip-based pagination or the order param.
|
|
271
|
+
*/
|
|
272
|
+
async function cursorPagedGet({
|
|
273
|
+
client,
|
|
274
|
+
spaceId,
|
|
275
|
+
environmentId,
|
|
276
|
+
method
|
|
277
|
+
}) {
|
|
278
|
+
const [entity, operation] = method.split('.');
|
|
279
|
+
const allItems = [];
|
|
280
|
+
let pageNext = null;
|
|
281
|
+
do {
|
|
282
|
+
var _response$pages$next, _response$pages;
|
|
283
|
+
const query = {
|
|
284
|
+
spaceId,
|
|
285
|
+
environmentId,
|
|
286
|
+
limit: pageLimit
|
|
287
|
+
};
|
|
288
|
+
if (pageNext) {
|
|
289
|
+
query.pageNext = pageNext;
|
|
290
|
+
}
|
|
291
|
+
const response = await client[entity][operation](query);
|
|
292
|
+
allItems.push(...response.items);
|
|
293
|
+
_contentfulBatchLibs.logEmitter.emit('info', `Fetched ${allItems.length} ${entity} items`);
|
|
294
|
+
pageNext = (_response$pages$next = (_response$pages = response.pages) === null || _response$pages === void 0 ? void 0 : _response$pages.next) !== null && _response$pages$next !== void 0 ? _response$pages$next : null;
|
|
295
|
+
} while (pageNext);
|
|
296
|
+
return allItems;
|
|
297
|
+
}
|
|
298
|
+
|
|
170
299
|
/**
|
|
171
300
|
* Gets all the existing entities based on pagination parameters.
|
|
172
301
|
* The first call will have no aggregated response. Subsequent calls will
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = initClient;
|
|
7
|
+
exports.initPlainClient = initPlainClient;
|
|
7
8
|
var _contentful = require("contentful");
|
|
8
9
|
var _contentfulBatchLibs = require("contentful-batch-libs");
|
|
9
10
|
var _contentfulManagement = require("contentful-management");
|
|
@@ -34,4 +35,10 @@ function initClient(opts, useCda = false) {
|
|
|
34
35
|
type: 'legacy'
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
function initPlainClient(opts) {
|
|
39
|
+
return (0, _contentfulManagement.createClient)({
|
|
40
|
+
accessToken: opts.managementToken,
|
|
41
|
+
host: opts.host,
|
|
42
|
+
logHandler
|
|
43
|
+
});
|
|
44
|
+
}
|
package/dist/usageParams.js
CHANGED
|
@@ -107,6 +107,10 @@ var _default = exports.default = _yargs.default.version(_package.default.version
|
|
|
107
107
|
describe: 'Display progress in new lines instead of displaying a busy spinner and the status in the same line. Useful for CI.',
|
|
108
108
|
type: 'boolean',
|
|
109
109
|
default: false
|
|
110
|
+
}).option('include-experience-orchestration', {
|
|
111
|
+
describe: 'Include Experience Orchestration entities (Components, Experience Templates, Data Assemblies, Experience Fragments, Experiences, Design Tokens). Requires exo_m1 entitlement on the source space.',
|
|
112
|
+
type: 'boolean',
|
|
113
|
+
default: true
|
|
110
114
|
}).option('header', {
|
|
111
115
|
alias: 'H',
|
|
112
116
|
type: 'string',
|
package/package.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -29,9 +29,10 @@ export interface Options {
|
|
|
29
29
|
skipWebhooks?: boolean;
|
|
30
30
|
skipTags?: boolean;
|
|
31
31
|
useVerboseRenderer?: boolean;
|
|
32
|
+
includeExperienceOrchestration?: boolean;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
type ContentfulExportField = 'contentTypes' | 'entries' | 'assets' | 'locales' | 'tags' | 'webhooks' | 'roles' | 'editorInterfaces';
|
|
35
|
+
type ContentfulExportField = 'contentTypes' | 'entries' | 'assets' | 'locales' | 'tags' | 'webhooks' | 'roles' | 'editorInterfaces' | 'designTokens' | 'components' | 'experienceTemplates' | 'dataAssemblies' | 'experienceFragments' | 'experiences';
|
|
35
36
|
|
|
36
37
|
declare const runContentfulExport: (params: Options) => Promise<Record<ContentfulExportField, unknown[]>>
|
|
37
38
|
export default runContentfulExport
|