@kontent-ai/migration-toolkit 1.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/.npmignore +13 -0
- package/LICENSE.md +9 -0
- package/README.md +272 -0
- package/dist/es2022/core/helpers/workflow-helper.d.ts +37 -0
- package/dist/es2022/core/helpers/workflow-helper.js +67 -0
- package/dist/es2022/core/helpers/workflow-helper.js.map +1 -0
- package/dist/es2022/core/index.d.ts +15 -0
- package/dist/es2022/core/index.js +16 -0
- package/dist/es2022/core/index.js.map +1 -0
- package/dist/es2022/core/logs/loggers.d.ts +2 -0
- package/dist/es2022/core/logs/loggers.js +69 -0
- package/dist/es2022/core/logs/loggers.js.map +1 -0
- package/dist/es2022/core/models/core.models.d.ts +91 -0
- package/dist/es2022/core/models/core.models.js +2 -0
- package/dist/es2022/core/models/core.models.js.map +1 -0
- package/dist/es2022/core/models/log.models.d.ts +15 -0
- package/dist/es2022/core/models/log.models.js +2 -0
- package/dist/es2022/core/models/log.models.js.map +1 -0
- package/dist/es2022/core/models/migration.models.d.ts +136 -0
- package/dist/es2022/core/models/migration.models.js +2 -0
- package/dist/es2022/core/models/migration.models.js.map +1 -0
- package/dist/es2022/core/utils/array.utils.d.ts +5 -0
- package/dist/es2022/core/utils/array.utils.js +27 -0
- package/dist/es2022/core/utils/array.utils.js.map +1 -0
- package/dist/es2022/core/utils/binary-data.utils.d.ts +5 -0
- package/dist/es2022/core/utils/binary-data.utils.js +21 -0
- package/dist/es2022/core/utils/binary-data.utils.js.map +1 -0
- package/dist/es2022/core/utils/confirm.utils.d.ts +31 -0
- package/dist/es2022/core/utils/confirm.utils.js +73 -0
- package/dist/es2022/core/utils/confirm.utils.js.map +1 -0
- package/dist/es2022/core/utils/error.utils.d.ts +4 -0
- package/dist/es2022/core/utils/error.utils.js +50 -0
- package/dist/es2022/core/utils/error.utils.js.map +1 -0
- package/dist/es2022/core/utils/external-id.utils.d.ts +5 -0
- package/dist/es2022/core/utils/external-id.utils.js +5 -0
- package/dist/es2022/core/utils/external-id.utils.js.map +1 -0
- package/dist/es2022/core/utils/global.utils.d.ts +14 -0
- package/dist/es2022/core/utils/global.utils.js +45 -0
- package/dist/es2022/core/utils/global.utils.js.map +1 -0
- package/dist/es2022/core/utils/http.utils.d.ts +3 -0
- package/dist/es2022/core/utils/http.utils.js +29 -0
- package/dist/es2022/core/utils/http.utils.js.map +1 -0
- package/dist/es2022/core/utils/management-client-utils.d.ts +19 -0
- package/dist/es2022/core/utils/management-client-utils.js +129 -0
- package/dist/es2022/core/utils/management-client-utils.js.map +1 -0
- package/dist/es2022/core/utils/processing-utils.d.ts +12 -0
- package/dist/es2022/core/utils/processing-utils.js +39 -0
- package/dist/es2022/core/utils/processing-utils.js.map +1 -0
- package/dist/es2022/core/utils/run.utils.d.ts +10 -0
- package/dist/es2022/core/utils/run.utils.js +37 -0
- package/dist/es2022/core/utils/run.utils.js.map +1 -0
- package/dist/es2022/export/context/export-context-fetcher.d.ts +4 -0
- package/dist/es2022/export/context/export-context-fetcher.js +289 -0
- package/dist/es2022/export/context/export-context-fetcher.js.map +1 -0
- package/dist/es2022/export/export-manager.d.ts +5 -0
- package/dist/es2022/export/export-manager.js +167 -0
- package/dist/es2022/export/export-manager.js.map +1 -0
- package/dist/es2022/export/export.models.d.ts +55 -0
- package/dist/es2022/export/export.models.js +2 -0
- package/dist/es2022/export/export.models.js.map +1 -0
- package/dist/es2022/export/index.d.ts +2 -0
- package/dist/es2022/export/index.js +3 -0
- package/dist/es2022/export/index.js.map +1 -0
- package/dist/es2022/export/utils/export.utils.d.ts +2 -0
- package/dist/es2022/export/utils/export.utils.js +5 -0
- package/dist/es2022/export/utils/export.utils.js.map +1 -0
- package/dist/es2022/file/file-manager.d.ts +5 -0
- package/dist/es2022/file/file-manager.js +29 -0
- package/dist/es2022/file/file-manager.js.map +1 -0
- package/dist/es2022/file/index.d.ts +1 -0
- package/dist/es2022/file/index.js +2 -0
- package/dist/es2022/file/index.js.map +1 -0
- package/dist/es2022/import/comparers/asset-comparer.d.ts +12 -0
- package/dist/es2022/import/comparers/asset-comparer.js +65 -0
- package/dist/es2022/import/comparers/asset-comparer.js.map +1 -0
- package/dist/es2022/import/context/import-context-fetcher.d.ts +4 -0
- package/dist/es2022/import/context/import-context-fetcher.js +235 -0
- package/dist/es2022/import/context/import-context-fetcher.js.map +1 -0
- package/dist/es2022/import/import-manager.d.ts +4 -0
- package/dist/es2022/import/import-manager.js +80 -0
- package/dist/es2022/import/import-manager.js.map +1 -0
- package/dist/es2022/import/import.models.d.ts +45 -0
- package/dist/es2022/import/import.models.js +2 -0
- package/dist/es2022/import/import.models.js.map +1 -0
- package/dist/es2022/import/importers/assets-importer.d.ts +10 -0
- package/dist/es2022/import/importers/assets-importer.js +175 -0
- package/dist/es2022/import/importers/assets-importer.js.map +1 -0
- package/dist/es2022/import/importers/content-items-importer.d.ts +10 -0
- package/dist/es2022/import/importers/content-items-importer.js +97 -0
- package/dist/es2022/import/importers/content-items-importer.js.map +1 -0
- package/dist/es2022/import/importers/language-variant-importer.d.ts +11 -0
- package/dist/es2022/import/importers/language-variant-importer.js +215 -0
- package/dist/es2022/import/importers/language-variant-importer.js.map +1 -0
- package/dist/es2022/import/importers/workflow-importer.d.ts +18 -0
- package/dist/es2022/import/importers/workflow-importer.js +122 -0
- package/dist/es2022/import/importers/workflow-importer.js.map +1 -0
- package/dist/es2022/import/index.d.ts +2 -0
- package/dist/es2022/import/index.js +3 -0
- package/dist/es2022/import/index.js.map +1 -0
- package/dist/es2022/import/utils/import.utils.d.ts +2 -0
- package/dist/es2022/import/utils/import.utils.js +5 -0
- package/dist/es2022/import/utils/import.utils.js.map +1 -0
- package/dist/es2022/index.d.ts +8 -0
- package/dist/es2022/index.js +10 -0
- package/dist/es2022/index.js.map +1 -0
- package/dist/es2022/metadata.d.ts +5 -0
- package/dist/es2022/metadata.js +6 -0
- package/dist/es2022/metadata.js.map +1 -0
- package/dist/es2022/node/cli/actions/export-action.d.ts +2 -0
- package/dist/es2022/node/cli/actions/export-action.js +40 -0
- package/dist/es2022/node/cli/actions/export-action.js.map +1 -0
- package/dist/es2022/node/cli/actions/import-action.d.ts +2 -0
- package/dist/es2022/node/cli/actions/import-action.js +29 -0
- package/dist/es2022/node/cli/actions/import-action.js.map +1 -0
- package/dist/es2022/node/cli/actions/migrate-action.d.ts +2 -0
- package/dist/es2022/node/cli/actions/migrate-action.js +47 -0
- package/dist/es2022/node/cli/actions/migrate-action.js.map +1 -0
- package/dist/es2022/node/cli/app.d.ts +2 -0
- package/dist/es2022/node/cli/app.js +27 -0
- package/dist/es2022/node/cli/app.js.map +1 -0
- package/dist/es2022/node/cli/args/args-fetcher.d.ts +2 -0
- package/dist/es2022/node/cli/args/args-fetcher.js +46 -0
- package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -0
- package/dist/es2022/node/cli/args/args-setter.d.ts +2 -0
- package/dist/es2022/node/cli/args/args-setter.js +31 -0
- package/dist/es2022/node/cli/args/args-setter.js.map +1 -0
- package/dist/es2022/node/cli/cli.models.d.ts +24 -0
- package/dist/es2022/node/cli/cli.models.js +2 -0
- package/dist/es2022/node/cli/cli.models.js.map +1 -0
- package/dist/es2022/node/cli/commands.d.ts +1 -0
- package/dist/es2022/node/cli/commands.js +157 -0
- package/dist/es2022/node/cli/commands.js.map +1 -0
- package/dist/es2022/toolkit/elements-builder.d.ts +14 -0
- package/dist/es2022/toolkit/elements-builder.js +69 -0
- package/dist/es2022/toolkit/elements-builder.js.map +1 -0
- package/dist/es2022/toolkit/export.d.ts +3 -0
- package/dist/es2022/toolkit/export.js +21 -0
- package/dist/es2022/toolkit/export.js.map +1 -0
- package/dist/es2022/toolkit/file.d.ts +12 -0
- package/dist/es2022/toolkit/file.js +50 -0
- package/dist/es2022/toolkit/file.js.map +1 -0
- package/dist/es2022/toolkit/import.d.ts +2 -0
- package/dist/es2022/toolkit/import.js +21 -0
- package/dist/es2022/toolkit/import.js.map +1 -0
- package/dist/es2022/toolkit/index.d.ts +5 -0
- package/dist/es2022/toolkit/index.js +6 -0
- package/dist/es2022/toolkit/index.js.map +1 -0
- package/dist/es2022/toolkit/migrate.d.ts +21 -0
- package/dist/es2022/toolkit/migrate.js +39 -0
- package/dist/es2022/toolkit/migrate.js.map +1 -0
- package/dist/es2022/translation/extraction/items-extraction.processor.d.ts +24 -0
- package/dist/es2022/translation/extraction/items-extraction.processor.js +108 -0
- package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -0
- package/dist/es2022/translation/helpers/rich-text.processor.d.ts +22 -0
- package/dist/es2022/translation/helpers/rich-text.processor.js +209 -0
- package/dist/es2022/translation/helpers/rich-text.processor.js.map +1 -0
- package/dist/es2022/translation/index.d.ts +4 -0
- package/dist/es2022/translation/index.js +5 -0
- package/dist/es2022/translation/index.js.map +1 -0
- package/dist/es2022/translation/transforms/export-transforms.d.ts +3 -0
- package/dist/es2022/translation/transforms/export-transforms.js +196 -0
- package/dist/es2022/translation/transforms/export-transforms.js.map +1 -0
- package/dist/es2022/translation/transforms/import-transforms.d.ts +7 -0
- package/dist/es2022/translation/transforms/import-transforms.js +183 -0
- package/dist/es2022/translation/transforms/import-transforms.js.map +1 -0
- package/dist/es2022/zip/index.d.ts +4 -0
- package/dist/es2022/zip/index.js +5 -0
- package/dist/es2022/zip/index.js.map +1 -0
- package/dist/es2022/zip/zip-manager.d.ts +6 -0
- package/dist/es2022/zip/zip-manager.js +27 -0
- package/dist/es2022/zip/zip-manager.js.map +1 -0
- package/dist/es2022/zip/zip-packager.d.ts +3 -0
- package/dist/es2022/zip/zip-packager.js +69 -0
- package/dist/es2022/zip/zip-packager.js.map +1 -0
- package/dist/es2022/zip/zip-transformer.d.ts +6 -0
- package/dist/es2022/zip/zip-transformer.js +82 -0
- package/dist/es2022/zip/zip-transformer.js.map +1 -0
- package/dist/es2022/zip/zip.models.d.ts +13 -0
- package/dist/es2022/zip/zip.models.js +2 -0
- package/dist/es2022/zip/zip.models.js.map +1 -0
- package/lib/core/helpers/workflow-helper.ts +104 -0
- package/lib/core/index.ts +17 -0
- package/lib/core/logs/loggers.ts +80 -0
- package/lib/core/models/core.models.ts +134 -0
- package/lib/core/models/log.models.ts +31 -0
- package/lib/core/models/migration.models.ts +165 -0
- package/lib/core/utils/array.utils.ts +49 -0
- package/lib/core/utils/binary-data.utils.ts +29 -0
- package/lib/core/utils/confirm.utils.ts +139 -0
- package/lib/core/utils/error.utils.ts +65 -0
- package/lib/core/utils/external-id.utils.ts +9 -0
- package/lib/core/utils/global.utils.ts +59 -0
- package/lib/core/utils/http.utils.ts +35 -0
- package/lib/core/utils/management-client-utils.ts +182 -0
- package/lib/core/utils/processing-utils.ts +71 -0
- package/lib/core/utils/run.utils.ts +51 -0
- package/lib/export/context/export-context-fetcher.ts +475 -0
- package/lib/export/export-manager.ts +249 -0
- package/lib/export/export.models.ts +87 -0
- package/lib/export/index.ts +2 -0
- package/lib/export/utils/export.utils.ts +10 -0
- package/lib/file/file-manager.ts +37 -0
- package/lib/file/index.ts +1 -0
- package/lib/import/comparers/asset-comparer.ts +113 -0
- package/lib/import/context/import-context-fetcher.ts +367 -0
- package/lib/import/import-manager.ts +103 -0
- package/lib/import/import.models.ts +84 -0
- package/lib/import/importers/assets-importer.ts +239 -0
- package/lib/import/importers/content-items-importer.ts +142 -0
- package/lib/import/importers/language-variant-importer.ts +342 -0
- package/lib/import/importers/workflow-importer.ts +159 -0
- package/lib/import/index.ts +2 -0
- package/lib/import/utils/import.utils.ts +10 -0
- package/lib/index.ts +9 -0
- package/lib/metadata.ts +6 -0
- package/lib/node/cli/actions/export-action.ts +45 -0
- package/lib/node/cli/actions/import-action.ts +34 -0
- package/lib/node/cli/actions/migrate-action.ts +52 -0
- package/lib/node/cli/app.ts +29 -0
- package/lib/node/cli/args/args-fetcher.ts +61 -0
- package/lib/node/cli/args/args-setter.ts +35 -0
- package/lib/node/cli/cli.models.ts +28 -0
- package/lib/node/cli/commands.ts +161 -0
- package/lib/toolkit/elements-builder.ts +84 -0
- package/lib/toolkit/export.ts +21 -0
- package/lib/toolkit/file.ts +70 -0
- package/lib/toolkit/import.ts +21 -0
- package/lib/toolkit/index.ts +5 -0
- package/lib/toolkit/migrate.ts +71 -0
- package/lib/translation/extraction/items-extraction.processor.ts +181 -0
- package/lib/translation/helpers/rich-text.processor.ts +300 -0
- package/lib/translation/index.ts +4 -0
- package/lib/translation/transforms/export-transforms.ts +253 -0
- package/lib/translation/transforms/import-transforms.ts +215 -0
- package/lib/zip/index.ts +4 -0
- package/lib/zip/zip-manager.ts +33 -0
- package/lib/zip/zip-packager.ts +86 -0
- package/lib/zip/zip-transformer.ts +105 -0
- package/lib/zip/zip.models.ts +12 -0
- package/package.json +88 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WorkflowModels,
|
|
3
|
+
LanguageVariantModels,
|
|
4
|
+
ContentItemModels,
|
|
5
|
+
AssetModels,
|
|
6
|
+
CollectionModels,
|
|
7
|
+
LanguageModels
|
|
8
|
+
} from '@kontent-ai/management-sdk';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import {
|
|
11
|
+
processItemsAsync,
|
|
12
|
+
runMapiRequestAsync,
|
|
13
|
+
is404Error,
|
|
14
|
+
ItemStateInSourceEnvironmentById,
|
|
15
|
+
AssetStateInSourceEnvironmentById,
|
|
16
|
+
FlattenedContentType,
|
|
17
|
+
isNotUndefined,
|
|
18
|
+
managementClientUtils,
|
|
19
|
+
LogSpinnerData,
|
|
20
|
+
findRequired,
|
|
21
|
+
workflowHelper
|
|
22
|
+
} from '../../core/index.js';
|
|
23
|
+
import { itemsExtractionProcessor } from '../../translation/index.js';
|
|
24
|
+
import {
|
|
25
|
+
DefaultExportContextConfig,
|
|
26
|
+
ExportContext,
|
|
27
|
+
ExportContextEnvironmentData,
|
|
28
|
+
SourceExportItem,
|
|
29
|
+
ExportItem,
|
|
30
|
+
GetFlattenedElementByIds,
|
|
31
|
+
ExportItemVersion
|
|
32
|
+
} from '../export.models.js';
|
|
33
|
+
import { throwErrorForItemRequest } from '../utils/export.utils.js';
|
|
34
|
+
|
|
35
|
+
export async function exportContextFetcherAsync(config: DefaultExportContextConfig) {
|
|
36
|
+
const getEnvironmentDataAsync = async (): Promise<ExportContextEnvironmentData> => {
|
|
37
|
+
const mapiUtils = managementClientUtils(config.managementClient, config.logger);
|
|
38
|
+
|
|
39
|
+
return await config.logger.logWithSpinnerAsync(async (spinnerData) => {
|
|
40
|
+
spinnerData({ type: 'info', message: `Loading environment data` });
|
|
41
|
+
|
|
42
|
+
const environmentData: ExportContextEnvironmentData = {
|
|
43
|
+
collections: await mapiUtils.getAllCollectionsAsync(spinnerData),
|
|
44
|
+
contentTypes: await mapiUtils.getFlattenedContentTypesAsync(spinnerData),
|
|
45
|
+
languages: await mapiUtils.getAllLanguagesAsync(spinnerData),
|
|
46
|
+
workflows: await mapiUtils.getAllWorkflowsAsync(spinnerData),
|
|
47
|
+
taxonomies: await mapiUtils.getAllTaxonomiesAsync(spinnerData)
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
spinnerData({ type: 'info', message: `Environmental data loaded` });
|
|
51
|
+
|
|
52
|
+
return environmentData;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const environmentData = await getEnvironmentDataAsync();
|
|
57
|
+
|
|
58
|
+
const getContentItemAsync = async (
|
|
59
|
+
sourceItem: SourceExportItem,
|
|
60
|
+
logSpinner: LogSpinnerData
|
|
61
|
+
): Promise<Readonly<ContentItemModels.ContentItem>> => {
|
|
62
|
+
return await runMapiRequestAsync({
|
|
63
|
+
logger: config.logger,
|
|
64
|
+
logSpinner: logSpinner,
|
|
65
|
+
func: async () =>
|
|
66
|
+
(
|
|
67
|
+
await config.managementClient.viewContentItem().byItemCodename(sourceItem.itemCodename).toPromise()
|
|
68
|
+
).data,
|
|
69
|
+
action: 'view',
|
|
70
|
+
type: 'contentItem',
|
|
71
|
+
itemName: `codename -> ${sourceItem.itemCodename}`
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const getLatestLanguageVariantAsync = async (
|
|
76
|
+
sourceItem: SourceExportItem,
|
|
77
|
+
logSpinner: LogSpinnerData
|
|
78
|
+
): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
|
|
79
|
+
return await runMapiRequestAsync({
|
|
80
|
+
logger: config.logger,
|
|
81
|
+
logSpinner: logSpinner,
|
|
82
|
+
func: async () =>
|
|
83
|
+
(
|
|
84
|
+
await config.managementClient
|
|
85
|
+
.viewLanguageVariant()
|
|
86
|
+
.byItemCodename(sourceItem.itemCodename)
|
|
87
|
+
.byLanguageCodename(sourceItem.languageCodename)
|
|
88
|
+
.toPromise()
|
|
89
|
+
).data,
|
|
90
|
+
action: 'view',
|
|
91
|
+
type: 'languageVariant',
|
|
92
|
+
itemName: `codename -> ${sourceItem.itemCodename} -> latest (${sourceItem.languageCodename})`
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const isLanguageVariantPublished = (
|
|
97
|
+
languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>
|
|
98
|
+
): boolean => {
|
|
99
|
+
return environmentData.workflows.find(
|
|
100
|
+
(workflow) => workflow.publishedStep.id === languageVariant.workflow.stepIdentifier.id
|
|
101
|
+
)
|
|
102
|
+
? true
|
|
103
|
+
: false;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const mapToExportVersionItem = (
|
|
107
|
+
sourceItem: SourceExportItem,
|
|
108
|
+
contentItem: Readonly<ContentItemModels.ContentItem>,
|
|
109
|
+
languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>
|
|
110
|
+
): ExportItemVersion => {
|
|
111
|
+
return {
|
|
112
|
+
languageVariant: languageVariant,
|
|
113
|
+
workflowStepCodename: validateExportItem({
|
|
114
|
+
sourceItem: sourceItem,
|
|
115
|
+
contentItem: contentItem,
|
|
116
|
+
languageVariant: languageVariant
|
|
117
|
+
}).workflowStepCodename
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getExportItemVersionsAsync = async (
|
|
122
|
+
sourceItem: SourceExportItem,
|
|
123
|
+
contentItem: Readonly<ContentItemModels.ContentItem>,
|
|
124
|
+
logSpinner: LogSpinnerData
|
|
125
|
+
): Promise<readonly ExportItemVersion[]> => {
|
|
126
|
+
const latestLanguageVariant = await getLatestLanguageVariantAsync(sourceItem, logSpinner);
|
|
127
|
+
const latestExportVersion = mapToExportVersionItem(sourceItem, contentItem, latestLanguageVariant);
|
|
128
|
+
|
|
129
|
+
if (isLanguageVariantPublished(latestLanguageVariant)) {
|
|
130
|
+
// latest language variant is also published = no need to fetch published version
|
|
131
|
+
return [latestExportVersion];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const publishedLanguageVariant = await getPublishedLanguageVariantAsync(sourceItem, logSpinner);
|
|
135
|
+
|
|
136
|
+
if (!publishedLanguageVariant) {
|
|
137
|
+
return [latestExportVersion];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return [latestExportVersion, mapToExportVersionItem(sourceItem, contentItem, publishedLanguageVariant)];
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const getPublishedLanguageVariantAsync = async (
|
|
144
|
+
sourceItem: SourceExportItem,
|
|
145
|
+
logSpinner: LogSpinnerData
|
|
146
|
+
): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined> => {
|
|
147
|
+
return await runMapiRequestAsync({
|
|
148
|
+
logger: config.logger,
|
|
149
|
+
logSpinner: logSpinner,
|
|
150
|
+
func: async () => {
|
|
151
|
+
try {
|
|
152
|
+
return (
|
|
153
|
+
await config.managementClient
|
|
154
|
+
.viewLanguageVariant()
|
|
155
|
+
.byItemCodename(sourceItem.itemCodename)
|
|
156
|
+
.byLanguageCodename(sourceItem.languageCodename)
|
|
157
|
+
.published()
|
|
158
|
+
.toPromise()
|
|
159
|
+
).data;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
if (is404Error(error)) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
action: 'view',
|
|
168
|
+
type: 'languageVariant',
|
|
169
|
+
itemName: `codename -> ${sourceItem.itemCodename} -> published (${sourceItem.languageCodename})`
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const validateExportItem = (data: {
|
|
174
|
+
readonly sourceItem: SourceExportItem;
|
|
175
|
+
readonly contentItem: Readonly<ContentItemModels.ContentItem>;
|
|
176
|
+
readonly languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>;
|
|
177
|
+
}): {
|
|
178
|
+
collection: Readonly<CollectionModels.Collection>;
|
|
179
|
+
language: Readonly<LanguageModels.LanguageModel>;
|
|
180
|
+
workflow: Readonly<WorkflowModels.Workflow>;
|
|
181
|
+
contentType: Readonly<FlattenedContentType>;
|
|
182
|
+
workflowStepCodename: string;
|
|
183
|
+
} => {
|
|
184
|
+
const collection = findRequired(
|
|
185
|
+
environmentData.collections,
|
|
186
|
+
(collection) => collection.id === data.contentItem.collection.id,
|
|
187
|
+
() => {
|
|
188
|
+
throwErrorForItemRequest(
|
|
189
|
+
data.sourceItem,
|
|
190
|
+
`Invalid collection '${chalk.yellow(data.contentItem.collection.id ?? '')}'`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const contentType = findRequired(
|
|
196
|
+
environmentData.contentTypes,
|
|
197
|
+
(contentType) => contentType.contentTypeId === data.contentItem.type.id,
|
|
198
|
+
() => {
|
|
199
|
+
throwErrorForItemRequest(
|
|
200
|
+
data.sourceItem,
|
|
201
|
+
`Invalid content type '${chalk.red(data.contentItem.type.id)}'`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const language = findRequired(
|
|
207
|
+
environmentData.languages,
|
|
208
|
+
(language) => language.id === data.languageVariant.language.id,
|
|
209
|
+
() => {
|
|
210
|
+
throwErrorForItemRequest(
|
|
211
|
+
data.sourceItem,
|
|
212
|
+
`Invalid language '${chalk.red(data.languageVariant.language.id ?? '')}'`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const workflow = findRequired(
|
|
218
|
+
environmentData.workflows,
|
|
219
|
+
(workflow) => workflow.id === data.languageVariant.workflow.workflowIdentifier.id,
|
|
220
|
+
() => {
|
|
221
|
+
throwErrorForItemRequest(
|
|
222
|
+
data.sourceItem,
|
|
223
|
+
`Invalid workflow '${chalk.red(data.languageVariant.workflow.workflowIdentifier.id ?? '')}'`
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
const workflowStep = workflowHelper(environmentData.workflows).getWorkflowStep(workflow, {
|
|
229
|
+
match: (step) => step.id === data.languageVariant.workflow.stepIdentifier.id,
|
|
230
|
+
errorMessage: `Invalid workflow step '${chalk.red(data.languageVariant.workflow.stepIdentifier.id ?? '')}'`
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
collection,
|
|
235
|
+
language,
|
|
236
|
+
workflow,
|
|
237
|
+
contentType,
|
|
238
|
+
workflowStepCodename: workflowStep.codename
|
|
239
|
+
};
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const prepareExportItemsAsync = async (
|
|
243
|
+
exportItems: readonly SourceExportItem[]
|
|
244
|
+
): Promise<readonly ExportItem[]> => {
|
|
245
|
+
config.logger.log({
|
|
246
|
+
type: 'info',
|
|
247
|
+
message: `Preparing '${chalk.yellow(config.exportItems.length.toString())}' items for export`
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return await processItemsAsync<SourceExportItem, ExportItem>({
|
|
251
|
+
logger: config.logger,
|
|
252
|
+
action: 'Preparing content items & language variants',
|
|
253
|
+
parallelLimit: 1,
|
|
254
|
+
itemInfo: (input) => {
|
|
255
|
+
return {
|
|
256
|
+
title: `${input.itemCodename} (${input.languageCodename})`,
|
|
257
|
+
itemType: 'exportedItem'
|
|
258
|
+
};
|
|
259
|
+
},
|
|
260
|
+
items: exportItems,
|
|
261
|
+
processAsync: async (requestItem, logSpinner) => {
|
|
262
|
+
const contentItem = await getContentItemAsync(requestItem, logSpinner);
|
|
263
|
+
const versions = await getExportItemVersionsAsync(requestItem, contentItem, logSpinner);
|
|
264
|
+
|
|
265
|
+
// get shared attributes from any version
|
|
266
|
+
const anyVersion = versions[0];
|
|
267
|
+
if (!anyVersion) {
|
|
268
|
+
throwErrorForItemRequest(requestItem, `Expected at least 1 version of the content item`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const { collection, contentType, language, workflow } = validateExportItem({
|
|
272
|
+
sourceItem: requestItem,
|
|
273
|
+
contentItem: contentItem,
|
|
274
|
+
languageVariant: anyVersion.languageVariant
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
contentItem,
|
|
279
|
+
versions,
|
|
280
|
+
contentType,
|
|
281
|
+
requestItem,
|
|
282
|
+
workflow,
|
|
283
|
+
collection,
|
|
284
|
+
language
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const getContentItemsByIdsAsync = async (
|
|
291
|
+
itemIds: ReadonlySet<string>
|
|
292
|
+
): Promise<readonly Readonly<ContentItemModels.ContentItem>[]> => {
|
|
293
|
+
return (
|
|
294
|
+
await processItemsAsync<string, Readonly<ContentItemModels.ContentItem> | undefined>({
|
|
295
|
+
logger: config.logger,
|
|
296
|
+
action: 'Fetching content items',
|
|
297
|
+
parallelLimit: 1,
|
|
298
|
+
items: Array.from(itemIds),
|
|
299
|
+
itemInfo: (id) => {
|
|
300
|
+
return {
|
|
301
|
+
itemType: 'contentItem',
|
|
302
|
+
title: id
|
|
303
|
+
};
|
|
304
|
+
},
|
|
305
|
+
processAsync: async (id, logSpinner) => {
|
|
306
|
+
try {
|
|
307
|
+
return await runMapiRequestAsync({
|
|
308
|
+
logSpinner: logSpinner,
|
|
309
|
+
logger: config.logger,
|
|
310
|
+
func: async () =>
|
|
311
|
+
(
|
|
312
|
+
await config.managementClient.viewContentItem().byItemId(id).toPromise()
|
|
313
|
+
).data,
|
|
314
|
+
action: 'view',
|
|
315
|
+
type: 'contentItem',
|
|
316
|
+
itemName: `id -> ${id}`
|
|
317
|
+
});
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (!is404Error(error)) {
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return undefined;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
).filter(isNotUndefined);
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const getAssetsByIdsAsync = async (
|
|
331
|
+
itemIds: ReadonlySet<string>
|
|
332
|
+
): Promise<readonly Readonly<AssetModels.Asset>[]> => {
|
|
333
|
+
return (
|
|
334
|
+
await processItemsAsync<string, Readonly<AssetModels.Asset> | undefined>({
|
|
335
|
+
logger: config.logger,
|
|
336
|
+
action: 'Fetching assets',
|
|
337
|
+
parallelLimit: 1,
|
|
338
|
+
items: Array.from(itemIds),
|
|
339
|
+
itemInfo: (id) => {
|
|
340
|
+
return {
|
|
341
|
+
itemType: 'asset',
|
|
342
|
+
title: id
|
|
343
|
+
};
|
|
344
|
+
},
|
|
345
|
+
processAsync: async (id, logSpinner) => {
|
|
346
|
+
try {
|
|
347
|
+
return await runMapiRequestAsync({
|
|
348
|
+
logger: config.logger,
|
|
349
|
+
logSpinner: logSpinner,
|
|
350
|
+
func: async () =>
|
|
351
|
+
(
|
|
352
|
+
await config.managementClient.viewAsset().byAssetId(id).toPromise()
|
|
353
|
+
).data,
|
|
354
|
+
action: 'view',
|
|
355
|
+
type: 'asset',
|
|
356
|
+
itemName: `id -> ${id}`
|
|
357
|
+
});
|
|
358
|
+
} catch (error) {
|
|
359
|
+
if (!is404Error(error)) {
|
|
360
|
+
throw error;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
})
|
|
367
|
+
).filter(isNotUndefined);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const getItemStatesAsync = async (
|
|
371
|
+
itemIds: ReadonlySet<string>
|
|
372
|
+
): Promise<readonly ItemStateInSourceEnvironmentById[]> => {
|
|
373
|
+
const items = await getContentItemsByIdsAsync(itemIds);
|
|
374
|
+
|
|
375
|
+
return Array.from(itemIds).map<ItemStateInSourceEnvironmentById>((itemId) => {
|
|
376
|
+
const item = items.find((m) => m.id === itemId);
|
|
377
|
+
return {
|
|
378
|
+
id: itemId,
|
|
379
|
+
item: item,
|
|
380
|
+
state: item ? 'exists' : 'doesNotExists'
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const getAssetStatesAsync = async (
|
|
386
|
+
assetIds: ReadonlySet<string>
|
|
387
|
+
): Promise<readonly AssetStateInSourceEnvironmentById[]> => {
|
|
388
|
+
const assets = await getAssetsByIdsAsync(assetIds);
|
|
389
|
+
|
|
390
|
+
return Array.from(assetIds).map<AssetStateInSourceEnvironmentById>((assetId) => {
|
|
391
|
+
const asset = assets.find((m) => m.id === assetId);
|
|
392
|
+
return {
|
|
393
|
+
id: assetId,
|
|
394
|
+
asset: asset,
|
|
395
|
+
state: asset ? 'exists' : 'doesNotExists'
|
|
396
|
+
};
|
|
397
|
+
});
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const getElementByIds = (): GetFlattenedElementByIds => {
|
|
401
|
+
const getFunc: GetFlattenedElementByIds = (contentTypeId: string, elementId: string) => {
|
|
402
|
+
const contentType = findRequired(
|
|
403
|
+
environmentData.contentTypes,
|
|
404
|
+
(contentType) => contentType.contentTypeId === contentTypeId,
|
|
405
|
+
`Could not find content type with id '${chalk.red(contentTypeId)}'`
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
const element = findRequired(
|
|
409
|
+
contentType.elements,
|
|
410
|
+
(element) => element.id === elementId,
|
|
411
|
+
`Could not find element with id '${chalk.red(elementId)}' in content type '${chalk.red(
|
|
412
|
+
contentType.contentTypeCodename
|
|
413
|
+
)}'`
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
return element;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
return getFunc;
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const getExportContextAsync = async (): Promise<ExportContext> => {
|
|
423
|
+
const preparedItems = await prepareExportItemsAsync(config.exportItems);
|
|
424
|
+
|
|
425
|
+
config.logger.log({
|
|
426
|
+
type: 'info',
|
|
427
|
+
message: `Extracting referenced items & assets from content`
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
const referencedData = itemsExtractionProcessor().extractReferencedDataFromExtractItems(
|
|
431
|
+
preparedItems.map((exportItem) => {
|
|
432
|
+
return {
|
|
433
|
+
contentTypeId: exportItem.contentType.contentTypeId,
|
|
434
|
+
elements: exportItem.versions.flatMap((m) => m.languageVariant).flatMap((s) => s.elements)
|
|
435
|
+
};
|
|
436
|
+
}),
|
|
437
|
+
getElementByIds()
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
const itemStates: readonly ItemStateInSourceEnvironmentById[] = await getItemStatesAsync(
|
|
441
|
+
// fetch both referenced items and items that are set to be exported
|
|
442
|
+
new Set<string>([...referencedData.itemIds, ...preparedItems.map((m) => m.contentItem.id)])
|
|
443
|
+
);
|
|
444
|
+
const assetStates: readonly AssetStateInSourceEnvironmentById[] = await getAssetStatesAsync(
|
|
445
|
+
new Set<string>([...referencedData.assetIds])
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
const exportContext: ExportContext = {
|
|
449
|
+
getElement: getElementByIds(),
|
|
450
|
+
exportItems: preparedItems,
|
|
451
|
+
environmentData: environmentData,
|
|
452
|
+
referencedData: referencedData,
|
|
453
|
+
getAssetStateInSourceEnvironment: (id) =>
|
|
454
|
+
findRequired(
|
|
455
|
+
assetStates,
|
|
456
|
+
(m) => m.id === id,
|
|
457
|
+
`Invalid state for asset '${chalk.red(
|
|
458
|
+
id
|
|
459
|
+
)}'. It is expected that all asset states will be initialized`
|
|
460
|
+
),
|
|
461
|
+
getItemStateInSourceEnvironment: (id) =>
|
|
462
|
+
findRequired(
|
|
463
|
+
itemStates,
|
|
464
|
+
(m) => m.id === id,
|
|
465
|
+
`Invalid state for item '${chalk.red(id)}'. It is expected that all item states will be initialized`
|
|
466
|
+
)
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
return exportContext;
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
return {
|
|
473
|
+
getExportContextAsync
|
|
474
|
+
};
|
|
475
|
+
}
|