@kontent-ai/migration-toolkit 1.4.0 → 1.5.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 +1 -4
- package/dist/es2022/core/helpers/workflow-helper.d.ts +1 -0
- package/dist/es2022/core/helpers/workflow-helper.js +6 -4
- package/dist/es2022/core/helpers/workflow-helper.js.map +1 -1
- package/dist/es2022/core/logs/loggers.js +13 -22
- package/dist/es2022/core/logs/loggers.js.map +1 -1
- package/dist/es2022/core/models/core.models.d.ts +16 -6
- package/dist/es2022/core/models/migration.schema.d.ts +247 -0
- package/dist/es2022/core/models/migration.schema.js +12 -2
- package/dist/es2022/core/models/migration.schema.js.map +1 -1
- package/dist/es2022/core/utils/array.utils.js.map +1 -1
- package/dist/es2022/core/utils/binary-data.utils.js +2 -6
- package/dist/es2022/core/utils/binary-data.utils.js.map +1 -1
- package/dist/es2022/core/utils/confirm.utils.js +10 -14
- package/dist/es2022/core/utils/confirm.utils.js.map +1 -1
- package/dist/es2022/core/utils/error.utils.js +35 -27
- package/dist/es2022/core/utils/error.utils.js.map +1 -1
- package/dist/es2022/core/utils/http.utils.js +7 -11
- package/dist/es2022/core/utils/http.utils.js.map +1 -1
- package/dist/es2022/core/utils/management-client-utils.d.ts +2 -1
- package/dist/es2022/core/utils/management-client-utils.js +11 -1
- package/dist/es2022/core/utils/management-client-utils.js.map +1 -1
- package/dist/es2022/core/utils/run.utils.js +12 -10
- package/dist/es2022/core/utils/run.utils.js.map +1 -1
- package/dist/es2022/export/context/export-context-fetcher.js +2 -1
- package/dist/es2022/export/context/export-context-fetcher.js.map +1 -1
- package/dist/es2022/export/export-manager.js +8 -0
- package/dist/es2022/export/export-manager.js.map +1 -1
- package/dist/es2022/export/export.models.d.ts +2 -1
- package/dist/es2022/import/comparers/asset-comparer.d.ts +2 -1
- package/dist/es2022/import/comparers/asset-comparer.js +9 -17
- package/dist/es2022/import/comparers/asset-comparer.js.map +1 -1
- package/dist/es2022/import/context/import-context-fetcher.js +120 -40
- package/dist/es2022/import/context/import-context-fetcher.js.map +1 -1
- package/dist/es2022/import/import.models.d.ts +2 -1
- package/dist/es2022/import/importers/assets-importer.js +25 -7
- package/dist/es2022/import/importers/assets-importer.js.map +1 -1
- package/dist/es2022/import/importers/language-variant-importer.js +95 -87
- package/dist/es2022/import/importers/language-variant-importer.js.map +1 -1
- package/dist/es2022/import/importers/workflow-importer.d.ts +41 -4
- package/dist/es2022/import/importers/workflow-importer.js +158 -17
- package/dist/es2022/import/importers/workflow-importer.js.map +1 -1
- package/dist/es2022/metadata.js +2 -2
- package/dist/es2022/node/cli/app.js +8 -12
- package/dist/es2022/node/cli/app.js.map +1 -1
- package/dist/es2022/node/cli/args/args-fetcher.js +9 -10
- package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -1
- package/dist/es2022/toolkit/migrate.d.ts +1 -3
- package/dist/es2022/toolkit/migrate.js.map +1 -1
- package/dist/es2022/translation/extraction/items-extraction.processor.js +17 -17
- package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -1
- package/dist/es2022/zip/zip-packager.js +13 -18
- package/dist/es2022/zip/zip-packager.js.map +1 -1
- package/dist/es2022/zip/zip-transformer.js +3 -1
- package/dist/es2022/zip/zip-transformer.js.map +1 -1
- package/lib/core/helpers/workflow-helper.ts +8 -8
- package/lib/core/logs/loggers.ts +14 -22
- package/lib/core/models/core.models.ts +23 -4
- package/lib/core/models/migration.schema.ts +13 -2
- package/lib/core/utils/array.utils.ts +2 -10
- package/lib/core/utils/binary-data.utils.ts +2 -7
- package/lib/core/utils/confirm.utils.ts +18 -24
- package/lib/core/utils/error.utils.ts +50 -30
- package/lib/core/utils/http.utils.ts +14 -15
- package/lib/core/utils/management-client-utils.ts +188 -176
- package/lib/core/utils/run.utils.ts +27 -18
- package/lib/export/context/export-context-fetcher.ts +2 -1
- package/lib/export/export-manager.ts +14 -3
- package/lib/export/export.models.ts +3 -1
- package/lib/import/comparers/asset-comparer.ts +16 -24
- package/lib/import/context/import-context-fetcher.ts +179 -85
- package/lib/import/import.models.ts +2 -0
- package/lib/import/importers/assets-importer.ts +41 -25
- package/lib/import/importers/language-variant-importer.ts +119 -111
- package/lib/import/importers/workflow-importer.ts +228 -20
- package/lib/metadata.ts +2 -2
- package/lib/node/cli/app.ts +11 -12
- package/lib/node/cli/args/args-fetcher.ts +12 -14
- package/lib/toolkit/migrate.ts +1 -3
- package/lib/translation/extraction/items-extraction.processor.ts +93 -93
- package/lib/zip/zip-packager.ts +26 -28
- package/lib/zip/zip-transformer.ts +3 -1
- package/package.json +13 -12
|
@@ -2,27 +2,30 @@ import { AssetModels, ContentItemModels, LanguageVariantModels } from '@kontent-
|
|
|
2
2
|
import {
|
|
3
3
|
AssetStateInTargetEnvironmentByCodename,
|
|
4
4
|
ItemStateInTargetEnvironmentByCodename,
|
|
5
|
+
LanguageVariantSchedulesStateValues,
|
|
6
|
+
LanguageVariantStateData,
|
|
5
7
|
LanguageVariantStateInTargetEnvironmentByCodename,
|
|
8
|
+
LanguageVariantWorkflowState,
|
|
9
|
+
LanguageVariantWorkflowStateValues,
|
|
10
|
+
LogSpinnerData,
|
|
6
11
|
MigrationItem,
|
|
12
|
+
WorkflowStep,
|
|
7
13
|
findRequired,
|
|
8
14
|
is404Error,
|
|
9
15
|
isNotUndefined,
|
|
10
16
|
managementClientUtils,
|
|
11
17
|
processItemsAsync,
|
|
12
18
|
runMapiRequestAsync,
|
|
13
|
-
workflowHelper
|
|
19
|
+
workflowHelper as workflowHelperInit
|
|
14
20
|
} from '../../core/index.js';
|
|
15
|
-
import {
|
|
16
|
-
GetFlattenedElementByCodenames,
|
|
17
|
-
ImportContext,
|
|
18
|
-
ImportContextConfig,
|
|
19
|
-
ImportContextEnvironmentData
|
|
20
|
-
} from '../import.models.js';
|
|
21
|
+
import { GetFlattenedElementByCodenames, ImportContext, ImportContextConfig, ImportContextEnvironmentData } from '../import.models.js';
|
|
21
22
|
import { ExtractItemByCodename, itemsExtractionProcessor } from '../../translation/index.js';
|
|
22
23
|
import chalk from 'chalk';
|
|
24
|
+
import { match } from 'ts-pattern';
|
|
23
25
|
|
|
24
26
|
interface LanguageVariantWrapper {
|
|
25
|
-
readonly
|
|
27
|
+
readonly draftLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined;
|
|
28
|
+
readonly publishedLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined;
|
|
26
29
|
readonly migrationItem: MigrationItem;
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -37,7 +40,8 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
37
40
|
collections: await mapiUtils.getAllCollectionsAsync(spinnerData),
|
|
38
41
|
languages: await mapiUtils.getAllLanguagesAsync(spinnerData),
|
|
39
42
|
workflows: await mapiUtils.getAllWorkflowsAsync(spinnerData),
|
|
40
|
-
types: await mapiUtils.getFlattenedContentTypesAsync(spinnerData)
|
|
43
|
+
types: await mapiUtils.getFlattenedContentTypesAsync(spinnerData),
|
|
44
|
+
assetFolders: await mapiUtils.getAllAssetFoldersAsync(spinnerData)
|
|
41
45
|
};
|
|
42
46
|
|
|
43
47
|
spinnerData({ type: 'info', message: `Environmental data loaded` });
|
|
@@ -47,13 +51,10 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
47
51
|
};
|
|
48
52
|
|
|
49
53
|
const environmentData = await getEnvironmentDataAsync();
|
|
54
|
+
const workflowHelper = workflowHelperInit(environmentData.workflows);
|
|
50
55
|
|
|
51
56
|
const getElement = () => {
|
|
52
|
-
const getFlattenedElement: GetFlattenedElementByCodenames = (
|
|
53
|
-
contentTypeCodename,
|
|
54
|
-
elementCodename,
|
|
55
|
-
sourceType
|
|
56
|
-
) => {
|
|
57
|
+
const getFlattenedElement: GetFlattenedElementByCodenames = (contentTypeCodename, elementCodename, sourceType) => {
|
|
57
58
|
const contentType = findRequired(
|
|
58
59
|
environmentData.types,
|
|
59
60
|
(type) => type.contentTypeCodename === contentTypeCodename,
|
|
@@ -65,9 +66,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
65
66
|
(element) => element.codename === elementCodename,
|
|
66
67
|
`Element type with codename '${chalk.red(elementCodename)}' was not found in content type '${chalk.red(
|
|
67
68
|
contentTypeCodename
|
|
68
|
-
)}'. Available elements are '${contentType.elements
|
|
69
|
-
.map((element) => chalk.yellow(element.codename))
|
|
70
|
-
.join(', ')}'`
|
|
69
|
+
)}'. Available elements are '${contentType.elements.map((element) => chalk.yellow(element.codename)).join(', ')}'`
|
|
71
70
|
);
|
|
72
71
|
|
|
73
72
|
if (sourceType !== element.type) {
|
|
@@ -84,7 +83,70 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
84
83
|
return getFlattenedElement;
|
|
85
84
|
};
|
|
86
85
|
|
|
87
|
-
const
|
|
86
|
+
const getLatestLanguageVariantAsync = async (
|
|
87
|
+
logSpinner: LogSpinnerData,
|
|
88
|
+
migrationItem: MigrationItem
|
|
89
|
+
): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined> => {
|
|
90
|
+
try {
|
|
91
|
+
const latestLanguageVariant = await runMapiRequestAsync({
|
|
92
|
+
logger: config.logger,
|
|
93
|
+
func: async () =>
|
|
94
|
+
(
|
|
95
|
+
await config.managementClient
|
|
96
|
+
.viewLanguageVariant()
|
|
97
|
+
.byItemCodename(migrationItem.system.codename)
|
|
98
|
+
.byLanguageCodename(migrationItem.system.language.codename)
|
|
99
|
+
.toPromise()
|
|
100
|
+
).data,
|
|
101
|
+
action: 'view',
|
|
102
|
+
type: 'languageVariant',
|
|
103
|
+
logSpinner: logSpinner,
|
|
104
|
+
itemName: `latest -> codename -> ${migrationItem.system.codename} (${migrationItem.system.language.codename})`
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return latestLanguageVariant;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (!is404Error(error)) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const getPublishedLanguageVariantAsync = async (
|
|
118
|
+
logSpinner: LogSpinnerData,
|
|
119
|
+
migrationItem: MigrationItem
|
|
120
|
+
): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined> => {
|
|
121
|
+
try {
|
|
122
|
+
const draftLanguageVariant = await runMapiRequestAsync({
|
|
123
|
+
logger: config.logger,
|
|
124
|
+
func: async () =>
|
|
125
|
+
(
|
|
126
|
+
await config.managementClient
|
|
127
|
+
.viewLanguageVariant()
|
|
128
|
+
.byItemCodename(migrationItem.system.codename)
|
|
129
|
+
.byLanguageCodename(migrationItem.system.language.codename)
|
|
130
|
+
.published()
|
|
131
|
+
.toPromise()
|
|
132
|
+
).data,
|
|
133
|
+
action: 'view',
|
|
134
|
+
type: 'languageVariant',
|
|
135
|
+
logSpinner: logSpinner,
|
|
136
|
+
itemName: `published -> codename -> ${migrationItem.system.codename} (${migrationItem.system.language.codename})`
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return draftLanguageVariant;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (!is404Error(error)) {
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const getLanguageVariantWrappersAsync = async (
|
|
88
150
|
migrationItems: readonly MigrationItem[]
|
|
89
151
|
): Promise<readonly LanguageVariantWrapper[]> => {
|
|
90
152
|
return (
|
|
@@ -100,34 +162,28 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
100
162
|
};
|
|
101
163
|
},
|
|
102
164
|
processAsync: async (item, logSpinner) => {
|
|
103
|
-
|
|
104
|
-
const languageVariant = await runMapiRequestAsync({
|
|
105
|
-
logger: config.logger,
|
|
106
|
-
func: async () =>
|
|
107
|
-
(
|
|
108
|
-
await config.managementClient
|
|
109
|
-
.viewLanguageVariant()
|
|
110
|
-
.byItemCodename(item.system.codename)
|
|
111
|
-
.byLanguageCodename(item.system.language.codename)
|
|
112
|
-
.toPromise()
|
|
113
|
-
).data,
|
|
114
|
-
action: 'view',
|
|
115
|
-
type: 'languageVariant',
|
|
116
|
-
logSpinner: logSpinner,
|
|
117
|
-
itemName: `codename -> ${item.system.codename} (${item.system.language.codename})`
|
|
118
|
-
});
|
|
165
|
+
const latestLanguageVariant = await getLatestLanguageVariantAsync(logSpinner, item);
|
|
119
166
|
|
|
167
|
+
if (!latestLanguageVariant) {
|
|
168
|
+
// there is neither published or draft version as latest version does not exist at all
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (workflowHelper.isPublishedStepById(latestLanguageVariant.workflow.stepIdentifier.id ?? '')) {
|
|
173
|
+
// if latest version is published, it means that there is no draft, but there is published version
|
|
120
174
|
return {
|
|
121
|
-
|
|
122
|
-
|
|
175
|
+
migrationItem: item,
|
|
176
|
+
draftLanguageVariant: undefined,
|
|
177
|
+
publishedLanguageVariant: latestLanguageVariant
|
|
123
178
|
};
|
|
124
|
-
} catch (error) {
|
|
125
|
-
if (!is404Error(error)) {
|
|
126
|
-
throw error;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return undefined;
|
|
130
179
|
}
|
|
180
|
+
|
|
181
|
+
// if latest version is a draft version, check if there is published version as well
|
|
182
|
+
return {
|
|
183
|
+
migrationItem: item,
|
|
184
|
+
draftLanguageVariant: latestLanguageVariant,
|
|
185
|
+
publishedLanguageVariant: await getPublishedLanguageVariantAsync(logSpinner, item)
|
|
186
|
+
};
|
|
131
187
|
}
|
|
132
188
|
})
|
|
133
189
|
).filter(isNotUndefined);
|
|
@@ -152,10 +208,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
152
208
|
try {
|
|
153
209
|
return await runMapiRequestAsync({
|
|
154
210
|
logger: config.logger,
|
|
155
|
-
func: async () =>
|
|
156
|
-
(
|
|
157
|
-
await config.managementClient.viewContentItem().byItemCodename(codename).toPromise()
|
|
158
|
-
).data,
|
|
211
|
+
func: async () => (await config.managementClient.viewContentItem().byItemCodename(codename).toPromise()).data,
|
|
159
212
|
action: 'view',
|
|
160
213
|
type: 'contentItem',
|
|
161
214
|
logSpinner: logSpinner,
|
|
@@ -173,9 +226,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
173
226
|
).filter(isNotUndefined);
|
|
174
227
|
};
|
|
175
228
|
|
|
176
|
-
const getAssetsByCodenamesAsync = async (
|
|
177
|
-
assetCodenames: ReadonlySet<string>
|
|
178
|
-
): Promise<readonly AssetModels.Asset[]> => {
|
|
229
|
+
const getAssetsByCodenamesAsync = async (assetCodenames: ReadonlySet<string>): Promise<readonly AssetModels.Asset[]> => {
|
|
179
230
|
return (
|
|
180
231
|
await processItemsAsync<string, Readonly<AssetModels.Asset> | undefined>({
|
|
181
232
|
action: 'Fetching assets',
|
|
@@ -192,10 +243,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
192
243
|
try {
|
|
193
244
|
return await runMapiRequestAsync({
|
|
194
245
|
logger: config.logger,
|
|
195
|
-
func: async () =>
|
|
196
|
-
(
|
|
197
|
-
await config.managementClient.viewAsset().byAssetCodename(codename).toPromise()
|
|
198
|
-
).data,
|
|
246
|
+
func: async () => (await config.managementClient.viewAsset().byAssetCodename(codename).toPromise()).data,
|
|
199
247
|
action: 'view',
|
|
200
248
|
type: 'asset',
|
|
201
249
|
logSpinner: logSpinner,
|
|
@@ -213,44 +261,98 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
213
261
|
).filter(isNotUndefined);
|
|
214
262
|
};
|
|
215
263
|
|
|
264
|
+
const getVariantState = (languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>): LanguageVariantStateData => {
|
|
265
|
+
const variantWorkflowId = languageVariant.workflow.workflowIdentifier.id;
|
|
266
|
+
const variantStepId = languageVariant.workflow.stepIdentifier.id;
|
|
267
|
+
const { workflow, step } = workflowHelper.getWorkflowAndStep({
|
|
268
|
+
workflowMatcher: {
|
|
269
|
+
errorMessage: `Could not workflow with id '${chalk.red(variantWorkflowId)}' in target project`,
|
|
270
|
+
match: (workflow) => workflow.id == variantWorkflowId
|
|
271
|
+
},
|
|
272
|
+
stepMatcher: {
|
|
273
|
+
errorMessage: `Could not workflow step with id '${chalk.red(variantStepId)}' in workflow '${chalk.yellow(
|
|
274
|
+
variantWorkflowId
|
|
275
|
+
)}'`,
|
|
276
|
+
match: (step) => step.id == variantStepId
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
languageVariant: languageVariant,
|
|
282
|
+
workflow: workflow,
|
|
283
|
+
workflowState: getWorkflowState(step, languageVariant)
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
|
|
216
287
|
const getVariantStatesAsync = async (
|
|
217
288
|
migrationItems: readonly MigrationItem[]
|
|
218
289
|
): Promise<readonly LanguageVariantStateInTargetEnvironmentByCodename[]> => {
|
|
219
|
-
const
|
|
290
|
+
const variantWrappers = await getLanguageVariantWrappersAsync(migrationItems);
|
|
220
291
|
|
|
221
292
|
return migrationItems.map<LanguageVariantStateInTargetEnvironmentByCodename>((migrationItem) => {
|
|
222
|
-
const
|
|
293
|
+
const variantWrapper = variantWrappers.find(
|
|
223
294
|
(m) =>
|
|
224
295
|
m.migrationItem.system.codename === migrationItem.system.codename &&
|
|
225
296
|
m.migrationItem.system.language === migrationItem.system.language
|
|
226
297
|
);
|
|
227
298
|
|
|
228
|
-
const variantWorkflowId = variant?.languageVariant?.workflow?.workflowIdentifier?.id;
|
|
229
|
-
const variantStepId = variant?.languageVariant?.workflow?.stepIdentifier?.id;
|
|
230
|
-
|
|
231
|
-
const workflow = environmentData.workflows.find((workflow) => workflow.id === variantWorkflowId);
|
|
232
|
-
|
|
233
299
|
return {
|
|
234
300
|
itemCodename: migrationItem.system.codename,
|
|
235
301
|
languageCodename: migrationItem.system.language.codename,
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
step: workflow
|
|
239
|
-
? workflowHelper(environmentData.workflows).getWorkflowStep(workflow, {
|
|
240
|
-
errorMessage: `Could not workflow step with id '${chalk.red(
|
|
241
|
-
variantStepId
|
|
242
|
-
)}' in workflow '${chalk.yellow(workflow.codename)}'`,
|
|
243
|
-
match: (step) => step.id == variantStepId
|
|
244
|
-
})
|
|
302
|
+
draftLanguageVariant: variantWrapper?.draftLanguageVariant
|
|
303
|
+
? getVariantState(variantWrapper.draftLanguageVariant)
|
|
245
304
|
: undefined,
|
|
246
|
-
|
|
305
|
+
publishedLanguageVariant: variantWrapper?.publishedLanguageVariant
|
|
306
|
+
? getVariantState(variantWrapper.publishedLanguageVariant)
|
|
307
|
+
: undefined,
|
|
308
|
+
state: variantWrapper ? 'exists' : 'doesNotExists'
|
|
247
309
|
};
|
|
248
310
|
});
|
|
249
311
|
};
|
|
250
312
|
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
313
|
+
const getWorkflowState = (
|
|
314
|
+
step: Readonly<WorkflowStep>,
|
|
315
|
+
variant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined
|
|
316
|
+
): LanguageVariantWorkflowState => {
|
|
317
|
+
if (!variant) {
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const getScheduledState = (): LanguageVariantSchedulesStateValues => {
|
|
322
|
+
return match(variant.schedule)
|
|
323
|
+
.returnType<LanguageVariantSchedulesStateValues>()
|
|
324
|
+
.when(
|
|
325
|
+
(schedule) => schedule.publishTime && schedule.publishDisplayTimezone,
|
|
326
|
+
() => 'scheduledPublish'
|
|
327
|
+
)
|
|
328
|
+
.when(
|
|
329
|
+
(schedule) => schedule.unpublishTime && schedule.unpublishDisplayTimezone,
|
|
330
|
+
() => 'scheduledUnpublish'
|
|
331
|
+
)
|
|
332
|
+
.otherwise(() => 'n/a');
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const getWorkflowState = (): LanguageVariantWorkflowStateValues => {
|
|
336
|
+
return match(step.codename)
|
|
337
|
+
.returnType<LanguageVariantWorkflowStateValues>()
|
|
338
|
+
.when(
|
|
339
|
+
(stepCodename) => workflowHelper.isPublishedStepByCodename(stepCodename),
|
|
340
|
+
() => 'published'
|
|
341
|
+
)
|
|
342
|
+
.when(
|
|
343
|
+
(stepCodename) => workflowHelper.isArchivedStepByCodename(stepCodename),
|
|
344
|
+
() => 'archived'
|
|
345
|
+
)
|
|
346
|
+
.otherwise(() => 'draft');
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
workflowState: getWorkflowState(),
|
|
351
|
+
scheduledState: getScheduledState()
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const getItemStatesAsync = async (itemCodenames: ReadonlySet<string>): Promise<readonly ItemStateInTargetEnvironmentByCodename[]> => {
|
|
254
356
|
const items = await getContentItemsByCodenamesAsync(itemCodenames);
|
|
255
357
|
|
|
256
358
|
return Array.from(itemCodenames).map<ItemStateInTargetEnvironmentByCodename>((codename) => {
|
|
@@ -311,17 +413,13 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
311
413
|
]);
|
|
312
414
|
|
|
313
415
|
// prepare state of objects in target environment
|
|
314
|
-
const itemStates: readonly ItemStateInTargetEnvironmentByCodename[] = await getItemStatesAsync(
|
|
315
|
-
itemCodenamesToCheckInTargetEnv
|
|
316
|
-
);
|
|
416
|
+
const itemStates: readonly ItemStateInTargetEnvironmentByCodename[] = await getItemStatesAsync(itemCodenamesToCheckInTargetEnv);
|
|
317
417
|
|
|
318
418
|
const variantStates: readonly LanguageVariantStateInTargetEnvironmentByCodename[] = await getVariantStatesAsync(
|
|
319
419
|
config.migrationData.items
|
|
320
420
|
);
|
|
321
421
|
|
|
322
|
-
const assetStates: readonly AssetStateInTargetEnvironmentByCodename[] = await getAssetStatesAsync(
|
|
323
|
-
assetCodenamesToCheckInTargetEnv
|
|
324
|
-
);
|
|
422
|
+
const assetStates: readonly AssetStateInTargetEnvironmentByCodename[] = await getAssetStatesAsync(assetCodenamesToCheckInTargetEnv);
|
|
325
423
|
|
|
326
424
|
return {
|
|
327
425
|
environmentData,
|
|
@@ -334,9 +432,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
334
432
|
return findRequired(
|
|
335
433
|
itemStates,
|
|
336
434
|
(state) => state.itemCodename === itemCodename,
|
|
337
|
-
`Invalid state for item '${chalk.red(
|
|
338
|
-
itemCodename
|
|
339
|
-
)}'. It is expected that all item states will be initialized`
|
|
435
|
+
`Invalid state for item '${chalk.red(itemCodename)}'. It is expected that all item states will be initialized`
|
|
340
436
|
);
|
|
341
437
|
},
|
|
342
438
|
getLanguageVariantStateInTargetEnvironment: (itemCodename, languageCodename) => {
|
|
@@ -352,9 +448,7 @@ export async function importContextFetcherAsync(config: ImportContextConfig) {
|
|
|
352
448
|
return findRequired(
|
|
353
449
|
assetStates,
|
|
354
450
|
(state) => state.assetCodename === assetCodename,
|
|
355
|
-
`Invalid state for asset '${chalk.red(
|
|
356
|
-
assetCodename
|
|
357
|
-
)}'. It is expected that all asset states will be initialized`
|
|
451
|
+
`Invalid state for asset '${chalk.red(assetCodename)}'. It is expected that all asset states will be initialized`
|
|
358
452
|
);
|
|
359
453
|
},
|
|
360
454
|
getElement: getElementByCodenames
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
FlattenedContentType
|
|
16
16
|
} from '../core/index.js';
|
|
17
17
|
import {
|
|
18
|
+
AssetFolderModels,
|
|
18
19
|
AssetModels,
|
|
19
20
|
CollectionModels,
|
|
20
21
|
ContentItemModels,
|
|
@@ -34,6 +35,7 @@ export interface ImportContextConfig {
|
|
|
34
35
|
|
|
35
36
|
export interface ImportContextEnvironmentData {
|
|
36
37
|
readonly languages: readonly Readonly<LanguageModels.LanguageModel>[];
|
|
38
|
+
readonly assetFolders: readonly Readonly<AssetFolderModels.AssetFolder>[];
|
|
37
39
|
readonly collections: readonly Readonly<CollectionModels.Collection>[];
|
|
38
40
|
readonly workflows: readonly Readonly<WorkflowModels.Workflow>[];
|
|
39
41
|
readonly types: readonly Readonly<FlattenedContentType>[];
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { AssetModels, ManagementClient } from '@kontent-ai/management-sdk';
|
|
1
|
+
import { AssetModels, LanguageModels, ManagementClient, SharedContracts } from '@kontent-ai/management-sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import mime from 'mime';
|
|
2
4
|
import {
|
|
3
|
-
|
|
5
|
+
geSizeInBytes,
|
|
6
|
+
isNotUndefined,
|
|
4
7
|
Logger,
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
LogSpinnerData,
|
|
9
|
+
MigrationAsset,
|
|
7
10
|
MigrationAssetDescription,
|
|
8
11
|
MigrationReference,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
LogSpinnerData
|
|
12
|
+
processItemsAsync,
|
|
13
|
+
runMapiRequestAsync
|
|
12
14
|
} from '../../core/index.js';
|
|
13
|
-
import mime from 'mime';
|
|
14
|
-
import chalk from 'chalk';
|
|
15
|
-
import { ImportContext, ImportResult } from '../import.models.js';
|
|
16
15
|
import { shouldReplaceBinaryFile, shouldUpdateAsset } from '../comparers/asset-comparer.js';
|
|
16
|
+
import { ImportContext, ImportResult } from '../import.models.js';
|
|
17
17
|
|
|
18
18
|
interface AssetToEdit {
|
|
19
19
|
migrationAsset: MigrationAsset;
|
|
@@ -27,9 +27,11 @@ export function assetsImporter(data: {
|
|
|
27
27
|
readonly importContext: ImportContext;
|
|
28
28
|
}) {
|
|
29
29
|
const getAssetsToUpload = (): readonly MigrationAsset[] => {
|
|
30
|
-
return data.importContext.categorizedImportData.assets
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
return data.importContext.categorizedImportData.assets
|
|
31
|
+
.filter((asset) => {
|
|
32
|
+
return data.importContext.getAssetStateInTargetEnvironment(asset.codename).state === 'doesNotExists';
|
|
33
|
+
})
|
|
34
|
+
.map((asset) => ({ ...asset, descriptions: asset.descriptions?.filter(filterInvalidLanguages) }));
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
const getAssetsToEdit = (): readonly AssetToEdit[] => {
|
|
@@ -45,6 +47,7 @@ export function assetsImporter(data: {
|
|
|
45
47
|
!shouldUpdateAsset({
|
|
46
48
|
collections: data.importContext.environmentData.collections,
|
|
47
49
|
languages: data.importContext.environmentData.languages,
|
|
50
|
+
assetFolders: data.importContext.environmentData.assetFolders,
|
|
48
51
|
migrationAsset: migrationAsset,
|
|
49
52
|
targetAsset: assetState.asset
|
|
50
53
|
})
|
|
@@ -53,7 +56,10 @@ export function assetsImporter(data: {
|
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
return {
|
|
56
|
-
migrationAsset:
|
|
59
|
+
migrationAsset: {
|
|
60
|
+
...migrationAsset,
|
|
61
|
+
descriptions: migrationAsset.descriptions?.filter(filterInvalidLanguages)
|
|
62
|
+
},
|
|
57
63
|
replaceBinaryFile: shouldReplaceBinaryFile({
|
|
58
64
|
migrationAsset: migrationAsset,
|
|
59
65
|
targetAsset: assetState.asset
|
|
@@ -64,9 +70,7 @@ export function assetsImporter(data: {
|
|
|
64
70
|
.filter(isNotUndefined);
|
|
65
71
|
};
|
|
66
72
|
|
|
67
|
-
const editAssets = async (
|
|
68
|
-
assetsToEdit: readonly AssetToEdit[]
|
|
69
|
-
): Promise<readonly Readonly<AssetModels.Asset>[]> => {
|
|
73
|
+
const editAssets = async (assetsToEdit: readonly AssetToEdit[]): Promise<readonly Readonly<AssetModels.Asset>[]> => {
|
|
70
74
|
data.logger.log({
|
|
71
75
|
type: 'upsert',
|
|
72
76
|
message: `Upserting '${chalk.yellow(assetsToEdit.length.toString())}' assets`
|
|
@@ -100,11 +104,10 @@ export function assetsImporter(data: {
|
|
|
100
104
|
.withData(() => {
|
|
101
105
|
return {
|
|
102
106
|
title: assetEditRequest.migrationAsset.title,
|
|
103
|
-
descriptions: mapAssetDescriptions(
|
|
104
|
-
assetEditRequest.migrationAsset.descriptions
|
|
105
|
-
),
|
|
107
|
+
descriptions: mapAssetDescriptions(assetEditRequest.migrationAsset.descriptions),
|
|
106
108
|
collection: mapAssetCollection(assetEditRequest.migrationAsset.collection),
|
|
107
|
-
file_reference: uploadedBinaryFile ?? undefined
|
|
109
|
+
file_reference: uploadedBinaryFile ?? undefined,
|
|
110
|
+
folder: mapAssetFolder(assetEditRequest.migrationAsset.folder)
|
|
108
111
|
};
|
|
109
112
|
})
|
|
110
113
|
.toPromise()
|
|
@@ -119,6 +122,10 @@ export function assetsImporter(data: {
|
|
|
119
122
|
});
|
|
120
123
|
};
|
|
121
124
|
|
|
125
|
+
const filterInvalidLanguages = (description: MigrationAssetDescription): Readonly<LanguageModels.LanguageModel> | undefined => {
|
|
126
|
+
return data.importContext.environmentData.languages.find((lang) => lang.codename === description.language.codename);
|
|
127
|
+
};
|
|
128
|
+
|
|
122
129
|
const mapAssetCollection = (
|
|
123
130
|
migrationCollection: MigrationReference | undefined
|
|
124
131
|
): Readonly<AssetModels.IAssetCollectionReferenceObject> | undefined => {
|
|
@@ -131,6 +138,16 @@ export function assetsImporter(data: {
|
|
|
131
138
|
: undefined;
|
|
132
139
|
};
|
|
133
140
|
|
|
141
|
+
const mapAssetFolder = (
|
|
142
|
+
migrationFolder: MigrationReference | undefined
|
|
143
|
+
): Readonly<SharedContracts.IReferenceObjectContract> | undefined => {
|
|
144
|
+
return migrationFolder
|
|
145
|
+
? {
|
|
146
|
+
codename: migrationFolder.codename
|
|
147
|
+
}
|
|
148
|
+
: undefined;
|
|
149
|
+
};
|
|
150
|
+
|
|
134
151
|
const mapAssetDescriptions = (
|
|
135
152
|
migrationDescription: readonly MigrationAssetDescription[] | undefined
|
|
136
153
|
): Readonly<AssetModels.IAssetFileDescription>[] => {
|
|
@@ -172,9 +189,7 @@ export function assetsImporter(data: {
|
|
|
172
189
|
});
|
|
173
190
|
};
|
|
174
191
|
|
|
175
|
-
const uploadAssetsAsync = async (
|
|
176
|
-
assetsToUpload: readonly MigrationAsset[]
|
|
177
|
-
): Promise<readonly Readonly<AssetModels.Asset>[]> => {
|
|
192
|
+
const uploadAssetsAsync = async (assetsToUpload: readonly MigrationAsset[]): Promise<readonly Readonly<AssetModels.Asset>[]> => {
|
|
178
193
|
data.logger.log({
|
|
179
194
|
type: 'upload',
|
|
180
195
|
message: `Uploading '${chalk.yellow(assetsToUpload.length.toString())}' assets`
|
|
@@ -211,7 +226,8 @@ export function assetsImporter(data: {
|
|
|
211
226
|
title: migrationAsset.title,
|
|
212
227
|
external_id: assetStateInTargetEnv.externalIdToUse,
|
|
213
228
|
collection: mapAssetCollection(migrationAsset.collection),
|
|
214
|
-
descriptions: mapAssetDescriptions(migrationAsset.descriptions)
|
|
229
|
+
descriptions: mapAssetDescriptions(migrationAsset.descriptions),
|
|
230
|
+
folder: mapAssetFolder(migrationAsset.folder)
|
|
215
231
|
};
|
|
216
232
|
return assetRequestData;
|
|
217
233
|
})
|