@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/README.md +22 -11
- package/cli.js +314 -171
- package/index.d.ts +9 -9
- package/lib/backend.js +155 -107
- package/lib/content.js +5 -5
- package/lib/contentful.js +90 -43
- package/lib/diff.js +46 -32
- package/lib/helpers/locale.d.ts +3 -3
- package/lib/helpers/validation.d.ts +94 -15
- package/lib/helpers/validation.js +4 -4
- package/lib/migration.js +68 -51
- package/package.json +54 -117
- package/lib/helpers/validation.test.js +0 -381
- package/lib/helpers/validation.utils.test.js +0 -45
package/lib/contentful.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
|
-
const contentful = require(
|
|
2
|
-
const
|
|
3
|
-
const hasher = require('node-object-hash');
|
|
1
|
+
const contentful = require("contentful-management");
|
|
2
|
+
const { hasher } = require("node-object-hash");
|
|
4
3
|
const objectHash = hasher();
|
|
5
4
|
|
|
6
5
|
let client;
|
|
7
6
|
let environmentCache = new Map();
|
|
8
7
|
let spaceCache = new Map();
|
|
9
8
|
|
|
10
|
-
const TYPE_SYMBOL =
|
|
11
|
-
const TYPE_TEXT =
|
|
12
|
-
const TYPE_RICHTEXT =
|
|
13
|
-
const TYPE_NUMBER =
|
|
14
|
-
const TYPE_DATE =
|
|
15
|
-
const TYPE_LOCATION =
|
|
16
|
-
const TYPE_ARRAY =
|
|
17
|
-
const TYPE_BOOLEAN =
|
|
18
|
-
const TYPE_LINK =
|
|
19
|
-
const LINK_TYPE_ASSET =
|
|
20
|
-
const LINK_TYPE_ENTRY =
|
|
9
|
+
const TYPE_SYMBOL = "Symbol";
|
|
10
|
+
const TYPE_TEXT = "Text";
|
|
11
|
+
const TYPE_RICHTEXT = "RichText";
|
|
12
|
+
const TYPE_NUMBER = "Integer";
|
|
13
|
+
const TYPE_DATE = "Date";
|
|
14
|
+
const TYPE_LOCATION = "Location";
|
|
15
|
+
const TYPE_ARRAY = "Array";
|
|
16
|
+
const TYPE_BOOLEAN = "Boolean";
|
|
17
|
+
const TYPE_LINK = "Link";
|
|
18
|
+
const LINK_TYPE_ASSET = "Asset";
|
|
19
|
+
const LINK_TYPE_ENTRY = "Entry";
|
|
21
20
|
|
|
22
21
|
const MAX_ALLOWED_LIMIT = 1000;
|
|
23
22
|
|
|
@@ -47,13 +46,13 @@ const getContentId = (node) => {
|
|
|
47
46
|
|
|
48
47
|
const getContentName = (node, displayField) => {
|
|
49
48
|
const { fields, sys } = node;
|
|
50
|
-
const { id: fallback =
|
|
49
|
+
const { id: fallback = "unknown" } = sys || {};
|
|
51
50
|
const { [displayField]: field, name, title, id } = fields || {};
|
|
52
51
|
|
|
53
52
|
for (const tmp of [field, name, title, id].filter((v) => v)) {
|
|
54
53
|
const [result] = Object.values(tmp);
|
|
55
54
|
|
|
56
|
-
if (result && typeof result ===
|
|
55
|
+
if (result && typeof result === "string") {
|
|
57
56
|
return result;
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -81,10 +80,13 @@ const getClient = async (options) => {
|
|
|
81
80
|
return client;
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
throw new Error(
|
|
83
|
+
throw new Error("You need to login first. Run npx contentful login");
|
|
85
84
|
};
|
|
86
85
|
|
|
87
|
-
const getSpaces = async (
|
|
86
|
+
const getSpaces = async (
|
|
87
|
+
options,
|
|
88
|
+
{ skip = 0, aggregatedResponse = null } = {},
|
|
89
|
+
) => {
|
|
88
90
|
const client = await getClient(options);
|
|
89
91
|
const query = {
|
|
90
92
|
skip: skip,
|
|
@@ -132,7 +134,10 @@ const getEnvironments = async (options) => {
|
|
|
132
134
|
return environments;
|
|
133
135
|
};
|
|
134
136
|
|
|
135
|
-
const getApiKeys = async (
|
|
137
|
+
const getApiKeys = async (
|
|
138
|
+
options,
|
|
139
|
+
{ skip = 0, aggregatedResponse = null } = {},
|
|
140
|
+
) => {
|
|
136
141
|
const space = await getSpace(options);
|
|
137
142
|
const query = {
|
|
138
143
|
skip: skip,
|
|
@@ -177,10 +182,12 @@ const getEnvironment = async (options) => {
|
|
|
177
182
|
if (targetEnvironmentId && environmentIds.includes(targetEnvironmentId)) {
|
|
178
183
|
environmentCache.set(cacheKey, space.getEnvironment(targetEnvironmentId));
|
|
179
184
|
} else if (targetEnvironmentId) {
|
|
180
|
-
throw new Error(
|
|
185
|
+
throw new Error(
|
|
186
|
+
`Environment "${targetEnvironmentId}" is not available in space "${spaceId}"`,
|
|
187
|
+
);
|
|
181
188
|
} else {
|
|
182
189
|
throw new Error(
|
|
183
|
-
|
|
190
|
+
"Missing environment id. Use -e <environment-id> or set environment variable CONTENTFUL_ENVIRONMENT_ID",
|
|
184
191
|
);
|
|
185
192
|
}
|
|
186
193
|
|
|
@@ -198,7 +205,7 @@ const getDefaultLocale = async (config) => {
|
|
|
198
205
|
|
|
199
206
|
const defaultLocale = locales.find((locale) => locale.default);
|
|
200
207
|
const { code } = defaultLocale || {};
|
|
201
|
-
return code ||
|
|
208
|
+
return code || "de";
|
|
202
209
|
};
|
|
203
210
|
|
|
204
211
|
/**
|
|
@@ -210,12 +217,15 @@ const getDefaultLocale = async (config) => {
|
|
|
210
217
|
* - getEntries
|
|
211
218
|
* - getAssets
|
|
212
219
|
*/
|
|
213
|
-
const pagedGet = async (
|
|
220
|
+
const pagedGet = async (
|
|
221
|
+
environment,
|
|
222
|
+
{ method, skip = 0, aggregatedResponse = null, query = null },
|
|
223
|
+
) => {
|
|
214
224
|
const fullQuery = {
|
|
215
225
|
skip: skip,
|
|
216
226
|
limit: MAX_ALLOWED_LIMIT,
|
|
217
|
-
order:
|
|
218
|
-
...
|
|
227
|
+
order: "sys.createdAt,sys.id",
|
|
228
|
+
...query,
|
|
219
229
|
};
|
|
220
230
|
|
|
221
231
|
const response = await environment[method](fullQuery);
|
|
@@ -227,17 +237,28 @@ const pagedGet = async (environment, { method, skip = 0, aggregatedResponse = nu
|
|
|
227
237
|
}
|
|
228
238
|
|
|
229
239
|
if (skip + fullQuery.limit <= response.total) {
|
|
230
|
-
return pagedGet(environment, {
|
|
240
|
+
return pagedGet(environment, {
|
|
241
|
+
method,
|
|
242
|
+
skip: skip + fullQuery.limit,
|
|
243
|
+
aggregatedResponse,
|
|
244
|
+
query,
|
|
245
|
+
});
|
|
231
246
|
}
|
|
232
247
|
return aggregatedResponse;
|
|
233
248
|
};
|
|
234
249
|
|
|
235
|
-
const
|
|
236
|
-
return includeDrafts
|
|
250
|
+
const _filterDrafts = (items, includeDrafts) => {
|
|
251
|
+
return includeDrafts
|
|
252
|
+
? items
|
|
253
|
+
: items.filter(
|
|
254
|
+
(item) => !!item.sys.publishedVersion || !!item.sys.archivedVersion,
|
|
255
|
+
);
|
|
237
256
|
};
|
|
238
257
|
|
|
239
|
-
const
|
|
240
|
-
return includeArchived
|
|
258
|
+
const _filterArchived = (items, includeArchived) => {
|
|
259
|
+
return includeArchived
|
|
260
|
+
? items
|
|
261
|
+
: items.filter((item) => !item.sys.archivedVersion);
|
|
241
262
|
};
|
|
242
263
|
|
|
243
264
|
const getLinkedId = (node, destType) => {
|
|
@@ -251,7 +272,7 @@ const getLinkedId = (node, destType) => {
|
|
|
251
272
|
const getLinkedIds = (entry, destType) => {
|
|
252
273
|
const { fields } = entry || {};
|
|
253
274
|
const ids = Object.values(fields).reduce((result, locales) => {
|
|
254
|
-
const ids =
|
|
275
|
+
const ids = Object.values(locales).flatMap((value) => {
|
|
255
276
|
if (Array.isArray(value)) {
|
|
256
277
|
return value.map((node) => getLinkedId(node, destType));
|
|
257
278
|
}
|
|
@@ -271,15 +292,26 @@ const getLinkedEntries = (entries, allEntries, options) => {
|
|
|
271
292
|
return [];
|
|
272
293
|
}
|
|
273
294
|
const entryIds = (entries || []).map((entry) => getContentId(entry));
|
|
274
|
-
const linkedIds = (entries || []).reduce(
|
|
295
|
+
const linkedIds = (entries || []).reduce(
|
|
296
|
+
(result, entry) => [...result, ...getLinkedIds(entry, LINK_TYPE_ENTRY)],
|
|
297
|
+
[],
|
|
298
|
+
);
|
|
275
299
|
const newIds = linkedIds.filter(
|
|
276
|
-
(id) =>
|
|
300
|
+
(id) =>
|
|
301
|
+
!collectedIds.includes(id) &&
|
|
302
|
+
!entryIds.includes(id) &&
|
|
303
|
+
includeIds.includes(id),
|
|
304
|
+
);
|
|
305
|
+
const newEntries = allEntries.filter((entry) =>
|
|
306
|
+
newIds.includes(getContentId(entry)),
|
|
277
307
|
);
|
|
278
|
-
const newEntries = allEntries.filter((entry) => newIds.includes(getContentId(entry)));
|
|
279
308
|
|
|
280
309
|
return [
|
|
281
310
|
...newEntries,
|
|
282
|
-
...getLinkedEntries(newEntries, allEntries, {
|
|
311
|
+
...getLinkedEntries(newEntries, allEntries, {
|
|
312
|
+
...options,
|
|
313
|
+
collectedIds: [...collectedIds, ...entryIds],
|
|
314
|
+
}),
|
|
283
315
|
];
|
|
284
316
|
};
|
|
285
317
|
|
|
@@ -287,7 +319,10 @@ const getLinkedAssets = (entries, assets) => {
|
|
|
287
319
|
if ((entries || []).length === 0) {
|
|
288
320
|
return [];
|
|
289
321
|
}
|
|
290
|
-
const linkedIds = (entries || []).reduce(
|
|
322
|
+
const linkedIds = (entries || []).reduce(
|
|
323
|
+
(result, entry) => [...result, ...getLinkedIds(entry, LINK_TYPE_ASSET)],
|
|
324
|
+
[],
|
|
325
|
+
);
|
|
291
326
|
|
|
292
327
|
return assets.filter((asset) => linkedIds.includes(getContentId(asset)));
|
|
293
328
|
};
|
|
@@ -305,12 +340,20 @@ const getContent = async (options) => {
|
|
|
305
340
|
const { contentType } = options;
|
|
306
341
|
const environment = await getEnvironment(options);
|
|
307
342
|
|
|
308
|
-
const { items: contentTypes } = await pagedGet(environment, {
|
|
309
|
-
|
|
310
|
-
|
|
343
|
+
const { items: contentTypes } = await pagedGet(environment, {
|
|
344
|
+
method: "getContentTypes",
|
|
345
|
+
});
|
|
346
|
+
const { items: entries } = await pagedGet(environment, {
|
|
347
|
+
method: "getEntries",
|
|
348
|
+
});
|
|
349
|
+
const { items: assets } = await pagedGet(environment, {
|
|
350
|
+
method: "getAssets",
|
|
351
|
+
});
|
|
311
352
|
|
|
312
353
|
if (contentType) {
|
|
313
|
-
const baseEntries = entries.filter(
|
|
354
|
+
const baseEntries = entries.filter(
|
|
355
|
+
(entry) => getContentTypeId(entry) === contentType,
|
|
356
|
+
);
|
|
314
357
|
|
|
315
358
|
return {
|
|
316
359
|
entries,
|
|
@@ -328,7 +371,7 @@ const getMigrationItems = async (options) => {
|
|
|
328
371
|
const { migrationContentTypeId } = options;
|
|
329
372
|
const environment = await getEnvironment(options);
|
|
330
373
|
const { items } = await pagedGet(environment, {
|
|
331
|
-
method:
|
|
374
|
+
method: "getEntries",
|
|
332
375
|
query: { content_type: migrationContentTypeId },
|
|
333
376
|
});
|
|
334
377
|
|
|
@@ -339,7 +382,9 @@ const getContentTypes = async (options) => {
|
|
|
339
382
|
const { contentType } = options;
|
|
340
383
|
const environment = await getEnvironment(options);
|
|
341
384
|
|
|
342
|
-
const { items: contentTypes } = await pagedGet(environment, {
|
|
385
|
+
const { items: contentTypes } = await pagedGet(environment, {
|
|
386
|
+
method: "getContentTypes",
|
|
387
|
+
});
|
|
343
388
|
|
|
344
389
|
if (contentType) {
|
|
345
390
|
return contentTypes.filter((entry) => getContentId(entry) === contentType);
|
|
@@ -351,7 +396,9 @@ const getContentTypes = async (options) => {
|
|
|
351
396
|
const getEditorInterfaces = async (options) => {
|
|
352
397
|
const environment = await getEnvironment(options);
|
|
353
398
|
|
|
354
|
-
const { items: editorInterfaces } = await pagedGet(environment, {
|
|
399
|
+
const { items: editorInterfaces } = await pagedGet(environment, {
|
|
400
|
+
method: "getEditorInterfaces",
|
|
401
|
+
});
|
|
355
402
|
|
|
356
403
|
return editorInterfaces;
|
|
357
404
|
};
|
package/lib/diff.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
const Diff = require(
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const Diff = require("diff");
|
|
2
|
+
const {
|
|
3
|
+
documentToPlainTextString,
|
|
4
|
+
} = require("@contentful/rich-text-plain-text-renderer");
|
|
5
|
+
const pc = require("picocolors");
|
|
6
|
+
const microdiff = require("microdiff").default;
|
|
5
7
|
const {
|
|
6
8
|
getContentId,
|
|
7
9
|
getContentTypeId,
|
|
@@ -16,13 +18,19 @@ const {
|
|
|
16
18
|
TYPE_ARRAY,
|
|
17
19
|
TYPE_BOOLEAN,
|
|
18
20
|
TYPE_LINK,
|
|
19
|
-
} = require(
|
|
21
|
+
} = require("./contentful");
|
|
20
22
|
|
|
21
23
|
const getNodeDate = (node) => {
|
|
22
24
|
const { sys } = node || {};
|
|
23
25
|
const { updatedAt } = sys || {};
|
|
24
26
|
const date = new Date(updatedAt);
|
|
25
|
-
const options = {
|
|
27
|
+
const options = {
|
|
28
|
+
hour: "2-digit",
|
|
29
|
+
minute: "2-digit",
|
|
30
|
+
year: "numeric",
|
|
31
|
+
month: "2-digit",
|
|
32
|
+
day: "numeric",
|
|
33
|
+
};
|
|
26
34
|
const { locale } = Intl.DateTimeFormat().resolvedOptions();
|
|
27
35
|
|
|
28
36
|
return date.toLocaleDateString(locale, options);
|
|
@@ -51,7 +59,7 @@ const diffString = (source, dest) => {
|
|
|
51
59
|
return unchangedColor(part.value);
|
|
52
60
|
});
|
|
53
61
|
|
|
54
|
-
return parts.join(
|
|
62
|
+
return parts.join("");
|
|
55
63
|
};
|
|
56
64
|
|
|
57
65
|
const getField = (fieldId, contentType) => {
|
|
@@ -69,7 +77,7 @@ const getFieldValue = (fieldId, node) => {
|
|
|
69
77
|
|
|
70
78
|
const normalizeArray = (array) =>
|
|
71
79
|
(array || []).map((val) => {
|
|
72
|
-
if (typeof val ===
|
|
80
|
+
if (typeof val === "string") {
|
|
73
81
|
return val;
|
|
74
82
|
}
|
|
75
83
|
|
|
@@ -80,13 +88,15 @@ const normalizeArray = (array) =>
|
|
|
80
88
|
|
|
81
89
|
const diff = (source, dest, contentTypes) => {
|
|
82
90
|
const id = getContentId(dest);
|
|
83
|
-
const contentType = (contentTypes || []).find(
|
|
91
|
+
const contentType = (contentTypes || []).find(
|
|
92
|
+
(ct) => getContentId(ct) === getContentTypeId(dest),
|
|
93
|
+
);
|
|
84
94
|
const { fields: contentTypeFields } = contentType || {};
|
|
85
95
|
const { fields: sourceFields } = source || {};
|
|
86
96
|
const { fields: destFields } = dest || {};
|
|
87
|
-
const diffResult =
|
|
97
|
+
const diffResult = microdiff(destFields || {}, sourceFields || {});
|
|
88
98
|
|
|
89
|
-
if (
|
|
99
|
+
if (diffResult.length === 0) {
|
|
90
100
|
return;
|
|
91
101
|
}
|
|
92
102
|
|
|
@@ -100,23 +110,27 @@ const diff = (source, dest, contentTypes) => {
|
|
|
100
110
|
const [fieldId] = path || [];
|
|
101
111
|
return fieldId;
|
|
102
112
|
})
|
|
103
|
-
.filter((v) => v)
|
|
113
|
+
.filter((v) => v),
|
|
104
114
|
),
|
|
105
115
|
];
|
|
106
116
|
|
|
107
117
|
// console.log(contentType);
|
|
108
118
|
const fieldData = changedFields.map((fieldId) => {
|
|
109
|
-
const { name = fieldId } =
|
|
119
|
+
const { name = fieldId } =
|
|
120
|
+
(contentTypeFields || []).find(({ id }) => id === fieldId) || {};
|
|
110
121
|
const field = getField(fieldId, contentType);
|
|
111
122
|
const { type, linkType } = field || {};
|
|
112
123
|
const sourceValue = getFieldValue(fieldId, source);
|
|
113
124
|
const destValue = getFieldValue(fieldId, dest);
|
|
114
125
|
if (type === TYPE_SYMBOL) {
|
|
115
|
-
return `${pc.bold(name)}: ${pc.reset(diffString(`${destValue ||
|
|
126
|
+
return `${pc.bold(name)}: ${pc.reset(diffString(`${destValue || ""}`, `${sourceValue || ""}`))}`;
|
|
116
127
|
}
|
|
117
128
|
if (type === TYPE_RICHTEXT) {
|
|
118
129
|
return `${pc.bold(name)}: ${pc.reset(
|
|
119
|
-
diffString(
|
|
130
|
+
diffString(
|
|
131
|
+
documentToPlainTextString(destValue || {}),
|
|
132
|
+
documentToPlainTextString(sourceValue || {}),
|
|
133
|
+
),
|
|
120
134
|
)}`;
|
|
121
135
|
}
|
|
122
136
|
if (type === TYPE_NUMBER) {
|
|
@@ -124,26 +138,26 @@ const diff = (source, dest, contentTypes) => {
|
|
|
124
138
|
return `${pc.bold(name)}: ${oldValueColor(`${destValue}`)} ${newValueColor(`${sourceValue}`)}`;
|
|
125
139
|
}
|
|
126
140
|
if (type === TYPE_TEXT) {
|
|
127
|
-
return `${pc.bold(name)}: ${pc.reset(diffString(`${destValue ||
|
|
141
|
+
return `${pc.bold(name)}: ${pc.reset(diffString(`${destValue || ""}`, `${sourceValue || ""}`))}`;
|
|
128
142
|
}
|
|
129
143
|
if (type === TYPE_DATE) {
|
|
130
|
-
return `${pc.bold(name)}: ${oldValueColor(`${destValue ||
|
|
144
|
+
return `${pc.bold(name)}: ${oldValueColor(`${destValue || ""}`)} ${newValueColor(`${sourceValue || ""}`)}`;
|
|
131
145
|
}
|
|
132
146
|
if (type === TYPE_LOCATION) {
|
|
133
|
-
return `${pc.bold(name)}: ${oldValueColor(`${JSON.stringify(destValue ||
|
|
134
|
-
`${JSON.stringify(sourceValue ||
|
|
147
|
+
return `${pc.bold(name)}: ${oldValueColor(`${JSON.stringify(destValue || "")}`)} ${newValueColor(
|
|
148
|
+
`${JSON.stringify(sourceValue || "")}`,
|
|
135
149
|
)}`;
|
|
136
150
|
}
|
|
137
151
|
if (type === TYPE_BOOLEAN) {
|
|
138
152
|
return `${pc.bold(name)}: ${oldValueColor(`${JSON.stringify(destValue)}`)} ${newValueColor(
|
|
139
|
-
`${JSON.stringify(sourceValue)}
|
|
153
|
+
`${JSON.stringify(sourceValue)}`,
|
|
140
154
|
)}`;
|
|
141
155
|
}
|
|
142
156
|
if (type === TYPE_LINK) {
|
|
143
157
|
const sourceValueId = getContentId(sourceValue || {});
|
|
144
158
|
const destValueId = getContentId(destValue || {});
|
|
145
|
-
return `${pc.bold(name)} (${linkType}): ${oldValueColor(destValueId ||
|
|
146
|
-
sourceValueId ||
|
|
159
|
+
return `${pc.bold(name)} (${linkType}): ${oldValueColor(destValueId || "deleted")} ${newValueColor(
|
|
160
|
+
sourceValueId || "empty",
|
|
147
161
|
)}`;
|
|
148
162
|
}
|
|
149
163
|
|
|
@@ -158,24 +172,24 @@ const diff = (source, dest, contentTypes) => {
|
|
|
158
172
|
const destArray = normalizeArray(destValue);
|
|
159
173
|
|
|
160
174
|
const array = Array(Math.max(sourceArray.length, destArray.length))
|
|
161
|
-
.fill(
|
|
175
|
+
.fill("")
|
|
162
176
|
.map((_, index) => {
|
|
163
177
|
if (sourceArray[index] === destArray[index]) {
|
|
164
178
|
return unchangedColor(sourceArray[index]);
|
|
165
179
|
}
|
|
166
180
|
|
|
167
181
|
if (sourceArray[index] && destArray[index]) {
|
|
168
|
-
return `${oldValueColor(destArray[index] ||
|
|
182
|
+
return `${oldValueColor(destArray[index] || "")} ${newValueColor(sourceArray[index])}`;
|
|
169
183
|
}
|
|
170
184
|
|
|
171
185
|
if (destArray[index]) {
|
|
172
186
|
return `${newValueColor(sourceArray[index])}`;
|
|
173
187
|
}
|
|
174
188
|
|
|
175
|
-
return `${oldValueColor(destArray[index] ||
|
|
189
|
+
return `${oldValueColor(destArray[index] || "")}`;
|
|
176
190
|
});
|
|
177
191
|
|
|
178
|
-
return `${pc.bold(name)}: [\n ${array.join(
|
|
192
|
+
return `${pc.bold(name)}: [\n ${array.join("\n ")}\n ]`;
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
return name;
|
|
@@ -185,20 +199,20 @@ const diff = (source, dest, contentTypes) => {
|
|
|
185
199
|
const sourceEnv = getEnvironmentId(source);
|
|
186
200
|
|
|
187
201
|
return {
|
|
188
|
-
type:
|
|
189
|
-
message: `${pc.reset(
|
|
202
|
+
type: "list",
|
|
203
|
+
message: `${pc.reset("Conflict on")} ${pc.cyan(name)}\n ${pc.reset(`${fieldData.join("\n ")}`)}\n`,
|
|
190
204
|
|
|
191
205
|
name: id,
|
|
192
206
|
choices: [
|
|
193
207
|
{
|
|
194
|
-
name: `Use ${oldValueColor(destEnv)} - updated on ${getNodeDate(dest)} ${pc.bold(
|
|
208
|
+
name: `Use ${oldValueColor(destEnv)} - updated on ${getNodeDate(dest)} ${pc.bold("(skip)")}`,
|
|
195
209
|
value: false,
|
|
196
|
-
short:
|
|
210
|
+
short: "skip",
|
|
197
211
|
},
|
|
198
212
|
{
|
|
199
|
-
name: `Use ${newValueColor(sourceEnv)} - updated on ${getNodeDate(source)} ${pc.bold(
|
|
213
|
+
name: `Use ${newValueColor(sourceEnv)} - updated on ${getNodeDate(source)} ${pc.bold("(overwrite)")}`,
|
|
200
214
|
value: true,
|
|
201
|
-
short:
|
|
215
|
+
short: "overwrite",
|
|
202
216
|
},
|
|
203
217
|
],
|
|
204
218
|
};
|
package/lib/helpers/locale.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Locale } from
|
|
2
|
-
import type Migration from
|
|
3
|
-
import type { MigrationContext } from
|
|
1
|
+
import type { Locale } from 'contentful-management/dist/typings/export-types';
|
|
2
|
+
import type Migration from 'contentful-migration';
|
|
3
|
+
import type { MigrationContext } from 'contentful-migration';
|
|
4
4
|
|
|
5
5
|
export interface LocaleHelpers {
|
|
6
6
|
getLocales(): Promise<Locale[]>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type Migration from
|
|
2
|
-
import type { MigrationContext } from
|
|
1
|
+
import type Migration from 'contentful-migration';
|
|
2
|
+
import type { MigrationContext } from 'contentful-migration';
|
|
3
3
|
|
|
4
4
|
export type ValueMappingFunction<T extends string = string> = (values: T[]) => T[];
|
|
5
5
|
|
|
@@ -11,31 +11,110 @@ export interface AddValuesOptions {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// define some known mark and node values here to support code completion, but allow any string as well
|
|
14
|
-
export type RichTextMarks =
|
|
15
|
-
|
|
14
|
+
export type RichTextMarks =
|
|
15
|
+
| 'bold'
|
|
16
|
+
| 'italic'
|
|
17
|
+
| 'underline'
|
|
18
|
+
| 'code'
|
|
19
|
+
| 'superscript'
|
|
20
|
+
| 'subscript'
|
|
21
|
+
| 'strikethrough'
|
|
22
|
+
| (string & {});
|
|
23
|
+
export type RichTextNodeType =
|
|
24
|
+
| 'document'
|
|
25
|
+
| 'paragraph'
|
|
26
|
+
| 'heading-1'
|
|
27
|
+
| 'heading-2'
|
|
28
|
+
| 'heading-3'
|
|
29
|
+
| 'heading-4'
|
|
30
|
+
| 'heading-5'
|
|
31
|
+
| 'heading-6'
|
|
32
|
+
| 'ordered-list'
|
|
33
|
+
| 'unordered-list'
|
|
34
|
+
| 'list-item'
|
|
35
|
+
| 'hr'
|
|
36
|
+
| 'blockquote'
|
|
37
|
+
| 'embedded-entry-block'
|
|
38
|
+
| 'embedded-asset-block'
|
|
39
|
+
| 'embedded-resource-block'
|
|
40
|
+
| 'table'
|
|
41
|
+
| 'table-row'
|
|
42
|
+
| 'table-cell'
|
|
43
|
+
| 'table-header-cell'
|
|
44
|
+
| 'asset-hyperlink'
|
|
45
|
+
| 'embedded-entry-inline'
|
|
46
|
+
| 'embedded-resource-inline'
|
|
47
|
+
| 'entry-hyperlink'
|
|
48
|
+
| 'hyperlink'
|
|
49
|
+
| 'resource-hyperlink'
|
|
50
|
+
| (string & {});
|
|
16
51
|
|
|
17
|
-
export type RichTextLinkedNodeType = 'entry-hyperlink' | 'embedded-entry-block' | 'embedded-entry-inline'
|
|
52
|
+
export type RichTextLinkedNodeType = 'entry-hyperlink' | 'embedded-entry-block' | 'embedded-entry-inline';
|
|
18
53
|
|
|
19
54
|
export interface RichTextValidationHelpers {
|
|
20
55
|
addEnabledMarksValues(contentTypeId: string, fieldId: string, values: RichTextMarks | RichTextMarks[]): Promise<void>;
|
|
21
|
-
removeEnabledMarksValues(
|
|
22
|
-
|
|
56
|
+
removeEnabledMarksValues(
|
|
57
|
+
contentTypeId: string,
|
|
58
|
+
fieldId: string,
|
|
59
|
+
values: RichTextMarks | RichTextMarks[],
|
|
60
|
+
): Promise<void>;
|
|
61
|
+
modifyEnabledMarksValues(
|
|
62
|
+
contentTypeId: string,
|
|
63
|
+
fieldId: string,
|
|
64
|
+
valueMappingFunction: ValueMappingFunction<RichTextMarks>,
|
|
65
|
+
): Promise<void>;
|
|
23
66
|
|
|
24
|
-
addEnabledNodeTypeValues(
|
|
25
|
-
|
|
26
|
-
|
|
67
|
+
addEnabledNodeTypeValues(
|
|
68
|
+
contentTypeId: string,
|
|
69
|
+
fieldId: string,
|
|
70
|
+
values: RichTextNodeType | RichTextNodeType[],
|
|
71
|
+
): Promise<void>;
|
|
72
|
+
removeEnabledNodeTypeValues(
|
|
73
|
+
contentTypeId: string,
|
|
74
|
+
fieldId: string,
|
|
75
|
+
values: RichTextNodeType | RichTextNodeType[],
|
|
76
|
+
): Promise<void>;
|
|
77
|
+
modifyEnabledNodeTypeValues(
|
|
78
|
+
contentTypeId: string,
|
|
79
|
+
fieldId: string,
|
|
80
|
+
valueMappingFunction: ValueMappingFunction<RichTextNodeType>,
|
|
81
|
+
): Promise<void>;
|
|
27
82
|
|
|
28
|
-
addNodeContentTypeValues(
|
|
29
|
-
|
|
30
|
-
|
|
83
|
+
addNodeContentTypeValues(
|
|
84
|
+
contentTypeId: string,
|
|
85
|
+
fieldId: string,
|
|
86
|
+
nodeType: RichTextLinkedNodeType,
|
|
87
|
+
values: string | string[],
|
|
88
|
+
): Promise<void>;
|
|
89
|
+
removeNodeContentTypeValues(
|
|
90
|
+
contentTypeId: string,
|
|
91
|
+
fieldId: string,
|
|
92
|
+
nodeType: RichTextLinkedNodeType,
|
|
93
|
+
values: string | string[],
|
|
94
|
+
): Promise<void>;
|
|
95
|
+
modifyNodeContentTypeValues(
|
|
96
|
+
contentTypeId: string,
|
|
97
|
+
fieldId: string,
|
|
98
|
+
nodeType: RichTextLinkedNodeType,
|
|
99
|
+
valueMappingFunction: ValueMappingFunction,
|
|
100
|
+
): Promise<void>;
|
|
31
101
|
}
|
|
32
102
|
|
|
33
103
|
export interface ValidationHelpers {
|
|
34
104
|
addLinkContentTypeValues(contentTypeId: string, fieldId: string, values: string | string[]): Promise<void>;
|
|
35
105
|
removeLinkContentTypeValues(contentTypeId: string, fieldId: string, values: string | string[]): Promise<void>;
|
|
36
|
-
modifyLinkContentTypeValues(
|
|
106
|
+
modifyLinkContentTypeValues(
|
|
107
|
+
contentTypeId: string,
|
|
108
|
+
fieldId: string,
|
|
109
|
+
valueMappingFunction: ValueMappingFunction,
|
|
110
|
+
): Promise<void>;
|
|
37
111
|
|
|
38
|
-
addInValues(
|
|
112
|
+
addInValues(
|
|
113
|
+
contentTypeId: string,
|
|
114
|
+
fieldId: string,
|
|
115
|
+
values: string | string[],
|
|
116
|
+
options?: AddValuesOptions,
|
|
117
|
+
): Promise<void>;
|
|
39
118
|
removeInValues(contentTypeId: string, fieldId: string, values: string | string[]): Promise<void>;
|
|
40
119
|
modifyInValues(contentTypeId: string, fieldId: string, valueMappingFunction: ValueMappingFunction): Promise<void>;
|
|
41
120
|
|
|
@@ -172,7 +172,7 @@ const getValidationHelpers = (migration, context) => {
|
|
|
172
172
|
removeValidationValues,
|
|
173
173
|
contentTypeId,
|
|
174
174
|
fieldId,
|
|
175
|
-
values
|
|
175
|
+
values,
|
|
176
176
|
);
|
|
177
177
|
},
|
|
178
178
|
async modifyEnabledNodeTypeValues(contentTypeId, fieldId, valueMappingFunction) {
|
|
@@ -186,7 +186,7 @@ const getValidationHelpers = (migration, context) => {
|
|
|
186
186
|
addValidationValues,
|
|
187
187
|
contentTypeId,
|
|
188
188
|
fieldId,
|
|
189
|
-
values
|
|
189
|
+
values,
|
|
190
190
|
);
|
|
191
191
|
},
|
|
192
192
|
async removeNodeContentTypeValues(contentTypeId, fieldId, nodeType, values) {
|
|
@@ -195,7 +195,7 @@ const getValidationHelpers = (migration, context) => {
|
|
|
195
195
|
removeValidationValues,
|
|
196
196
|
contentTypeId,
|
|
197
197
|
fieldId,
|
|
198
|
-
values
|
|
198
|
+
values,
|
|
199
199
|
);
|
|
200
200
|
},
|
|
201
201
|
async modifyNodeContentTypeValues(contentTypeId, fieldId, nodeType, valueMappingFunction) {
|
|
@@ -205,7 +205,7 @@ const getValidationHelpers = (migration, context) => {
|
|
|
205
205
|
uniqueMappingFunction,
|
|
206
206
|
contentTypeId,
|
|
207
207
|
fieldId,
|
|
208
|
-
[]
|
|
208
|
+
[],
|
|
209
209
|
);
|
|
210
210
|
},
|
|
211
211
|
},
|