@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,35 @@
|
|
|
1
|
+
import { HttpService, IRetryStrategyOptions } from '@kontent-ai/core-sdk';
|
|
2
|
+
import { OriginalManagementError } from '../models/core.models.js';
|
|
3
|
+
|
|
4
|
+
const rateExceededErrorCode: number = 10000;
|
|
5
|
+
const notFoundErrorCode: number = 10000;
|
|
6
|
+
|
|
7
|
+
export const defaultHttpService: Readonly<HttpService> = new HttpService({
|
|
8
|
+
logErrorsToConsole: false
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const defaultRetryStrategy: Readonly<IRetryStrategyOptions> = {
|
|
12
|
+
addJitter: true,
|
|
13
|
+
canRetryError: (err) => {
|
|
14
|
+
const originalError = err as OriginalManagementError | undefined;
|
|
15
|
+
const errorCode: number = originalError?.response?.data?.error_code ?? -1;
|
|
16
|
+
|
|
17
|
+
if (errorCode === rateExceededErrorCode) {
|
|
18
|
+
// retry rate exceeded error
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (errorCode === notFoundErrorCode) {
|
|
23
|
+
// do not retry errors indicating resource does not exist
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (errorCode >= 0) {
|
|
28
|
+
// otherwise if error code is set, do not retry the request
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
},
|
|
33
|
+
maxAttempts: 3,
|
|
34
|
+
deltaBackoffMs: 1000
|
|
35
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CollectionModels,
|
|
3
|
+
ContentTypeModels,
|
|
4
|
+
ContentTypeSnippetModels,
|
|
5
|
+
EnvironmentModels,
|
|
6
|
+
LanguageModels,
|
|
7
|
+
ManagementClient,
|
|
8
|
+
TaxonomyModels,
|
|
9
|
+
WorkflowModels,
|
|
10
|
+
createManagementClient
|
|
11
|
+
} from '@kontent-ai/management-sdk';
|
|
12
|
+
import { IRetryStrategyOptions } from '@kontent-ai/core-sdk';
|
|
13
|
+
import { runMapiRequestAsync } from './run.utils.js';
|
|
14
|
+
import { LogSpinnerData, Logger } from '../models/log.models.js';
|
|
15
|
+
import { FlattenedContentType, FlattenedContentTypeElement } from '../models/core.models.js';
|
|
16
|
+
import { isNotUndefined } from './global.utils.js';
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
import { defaultHttpService, defaultRetryStrategy } from './http.utils.js';
|
|
19
|
+
import { findRequired } from './array.utils.js';
|
|
20
|
+
|
|
21
|
+
export interface ManagementClientConfig {
|
|
22
|
+
readonly environmentId: string;
|
|
23
|
+
readonly apiKey: string;
|
|
24
|
+
readonly retryStrategy?: Readonly<IRetryStrategyOptions>;
|
|
25
|
+
readonly baseUrl?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getMigrationManagementClient(config: ManagementClientConfig): ManagementClient {
|
|
29
|
+
return createManagementClient({
|
|
30
|
+
environmentId: config.environmentId,
|
|
31
|
+
retryStrategy: config.retryStrategy ?? defaultRetryStrategy,
|
|
32
|
+
httpService: defaultHttpService,
|
|
33
|
+
apiKey: config.apiKey
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function managementClientUtils(client: Readonly<ManagementClient>, logger: Logger) {
|
|
38
|
+
const getEnvironmentAsync = async (): Promise<EnvironmentModels.EnvironmentInformationModel> => {
|
|
39
|
+
return (await client.environmentInformation().toPromise()).data.project;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const getAllLanguagesAsync = async (
|
|
43
|
+
logSpinner: LogSpinnerData
|
|
44
|
+
): Promise<readonly LanguageModels.LanguageModel[]> => {
|
|
45
|
+
return await runMapiRequestAsync({
|
|
46
|
+
logSpinner: logSpinner,
|
|
47
|
+
logger: logger,
|
|
48
|
+
func: async () => (await client.listLanguages().toAllPromise()).data.items,
|
|
49
|
+
action: 'list',
|
|
50
|
+
type: 'language'
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const getAllCollectionsAsync = async (
|
|
55
|
+
logSpinner: LogSpinnerData
|
|
56
|
+
): Promise<readonly CollectionModels.Collection[]> => {
|
|
57
|
+
return await runMapiRequestAsync({
|
|
58
|
+
logger: logger,
|
|
59
|
+
logSpinner: logSpinner,
|
|
60
|
+
func: async () => (await client.listCollections().toPromise()).data.collections,
|
|
61
|
+
action: 'list',
|
|
62
|
+
type: 'collection'
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getAllWorkflowsAsync = async (logSpinner: LogSpinnerData): Promise<readonly WorkflowModels.Workflow[]> => {
|
|
67
|
+
return await runMapiRequestAsync({
|
|
68
|
+
logger: logger,
|
|
69
|
+
logSpinner: logSpinner,
|
|
70
|
+
func: async () => (await client.listWorkflows().toPromise()).data,
|
|
71
|
+
action: 'list',
|
|
72
|
+
type: 'workflow'
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const getAllTaxonomiesAsync = async (logSpinner: LogSpinnerData): Promise<readonly TaxonomyModels.Taxonomy[]> => {
|
|
77
|
+
return await runMapiRequestAsync({
|
|
78
|
+
logger: logger,
|
|
79
|
+
logSpinner: logSpinner,
|
|
80
|
+
func: async () => (await client.listTaxonomies().toAllPromise()).data.items,
|
|
81
|
+
action: 'list',
|
|
82
|
+
type: 'taxonomy'
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const getContentTypeElements = (
|
|
87
|
+
contentType: ContentTypeModels.ContentType,
|
|
88
|
+
contentTypeSnippets: readonly ContentTypeSnippetModels.ContentTypeSnippet[]
|
|
89
|
+
): readonly FlattenedContentTypeElement[] => {
|
|
90
|
+
return contentType.elements
|
|
91
|
+
.flatMap((element) => {
|
|
92
|
+
if (!element.codename || !element.id) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (element.type === 'guidelines') {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (element.type === 'snippet') {
|
|
101
|
+
const snippetElement = element;
|
|
102
|
+
|
|
103
|
+
// replace snippet element with actual elements
|
|
104
|
+
const contentTypeSnippet = findRequired(
|
|
105
|
+
contentTypeSnippets,
|
|
106
|
+
(snippet) => snippet.id === snippetElement.snippet.id,
|
|
107
|
+
`Could not find content type snippet for element. This snippet is referenced in type '${chalk.red(
|
|
108
|
+
contentType.codename
|
|
109
|
+
)}'`
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
return contentTypeSnippet.elements.map((snippetElement) => {
|
|
113
|
+
if (snippetElement.type === 'guidelines' || snippetElement.type === 'snippet') {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
if (!snippetElement.codename || !snippetElement.id) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const flattenedElement: FlattenedContentTypeElement = {
|
|
121
|
+
codename: snippetElement.codename,
|
|
122
|
+
type: snippetElement.type,
|
|
123
|
+
id: snippetElement.id,
|
|
124
|
+
element: element
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return flattenedElement;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
const flattenedElement: FlattenedContentTypeElement = {
|
|
131
|
+
codename: element.codename,
|
|
132
|
+
id: element.id,
|
|
133
|
+
type: element.type,
|
|
134
|
+
element: element
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return flattenedElement;
|
|
138
|
+
})
|
|
139
|
+
.filter(isNotUndefined);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const getFlattenedContentTypesAsync = async (
|
|
143
|
+
logSpinner: LogSpinnerData
|
|
144
|
+
): Promise<readonly FlattenedContentType[]> => {
|
|
145
|
+
const contentTypes = await runMapiRequestAsync({
|
|
146
|
+
logger: logger,
|
|
147
|
+
logSpinner: logSpinner,
|
|
148
|
+
func: async () => (await client.listContentTypes().toAllPromise()).data.items,
|
|
149
|
+
action: 'list',
|
|
150
|
+
type: 'contentType'
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const contentTypeSnippets = await runMapiRequestAsync({
|
|
154
|
+
logger: logger,
|
|
155
|
+
logSpinner: logSpinner,
|
|
156
|
+
func: async () => (await client.listContentTypeSnippets().toAllPromise()).data.items,
|
|
157
|
+
action: 'list',
|
|
158
|
+
type: 'contentTypeSnippet'
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return [
|
|
162
|
+
...contentTypes.map((contentType) => {
|
|
163
|
+
const importType: FlattenedContentType = {
|
|
164
|
+
contentTypeCodename: contentType.codename,
|
|
165
|
+
contentTypeId: contentType.id,
|
|
166
|
+
elements: getContentTypeElements(contentType, contentTypeSnippets)
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
return importType;
|
|
170
|
+
})
|
|
171
|
+
];
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
getAllCollectionsAsync,
|
|
176
|
+
getAllLanguagesAsync,
|
|
177
|
+
getAllWorkflowsAsync,
|
|
178
|
+
getAllTaxonomiesAsync,
|
|
179
|
+
getFlattenedContentTypesAsync,
|
|
180
|
+
getEnvironmentAsync
|
|
181
|
+
};
|
|
182
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import pLimit from 'p-limit';
|
|
3
|
+
import { ItemInfo } from '../models/core.models.js';
|
|
4
|
+
import { LogSpinnerData, Logger } from '../models/log.models.js';
|
|
5
|
+
|
|
6
|
+
type ProcessSetAction =
|
|
7
|
+
| 'Fetching assets'
|
|
8
|
+
| 'Downloading assets'
|
|
9
|
+
| 'Fetching content items'
|
|
10
|
+
| 'Preparing content items & language variants'
|
|
11
|
+
| 'Importing content items'
|
|
12
|
+
| 'Importing language variants'
|
|
13
|
+
| 'Fetching language variants'
|
|
14
|
+
| 'Upserting assets'
|
|
15
|
+
| 'Uploading assets';
|
|
16
|
+
|
|
17
|
+
export async function processItemsAsync<InputItem, OutputItem>(data: {
|
|
18
|
+
readonly action: ProcessSetAction;
|
|
19
|
+
readonly logger: Logger;
|
|
20
|
+
readonly items: Readonly<InputItem[]>;
|
|
21
|
+
readonly parallelLimit: number;
|
|
22
|
+
readonly processAsync: (item: Readonly<InputItem>, logSpinner: LogSpinnerData) => Promise<Readonly<OutputItem>>;
|
|
23
|
+
readonly itemInfo: (item: Readonly<InputItem>) => ItemInfo;
|
|
24
|
+
}): Promise<readonly OutputItem[]> {
|
|
25
|
+
if (!data.items.length) {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const firstItemInfo = data.itemInfo(data.items[0]);
|
|
30
|
+
|
|
31
|
+
return await data.logger.logWithSpinnerAsync(async (logSpinner) => {
|
|
32
|
+
const limit = pLimit(data.parallelLimit);
|
|
33
|
+
let processedItemsCount: number = 1;
|
|
34
|
+
|
|
35
|
+
const requests: Promise<OutputItem>[] = data.items.map((item) =>
|
|
36
|
+
limit(() => {
|
|
37
|
+
return data.processAsync(item, logSpinner).then((output) => {
|
|
38
|
+
const itemInfo = data.itemInfo(item);
|
|
39
|
+
const prefix = getPercentagePrefix(processedItemsCount, data.items.length);
|
|
40
|
+
|
|
41
|
+
logSpinner({
|
|
42
|
+
prefix: prefix,
|
|
43
|
+
message: itemInfo.title,
|
|
44
|
+
type: itemInfo.itemType
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
processedItemsCount++;
|
|
48
|
+
return output;
|
|
49
|
+
});
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
// log processing of first item as progress is set after each item finishes
|
|
54
|
+
logSpinner({
|
|
55
|
+
prefix: getPercentagePrefix(0, data.items.length),
|
|
56
|
+
message: firstItemInfo.title,
|
|
57
|
+
type: firstItemInfo.itemType
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Only '<parallelLimit>' promises at a time
|
|
61
|
+
const outputItems = await Promise.all(requests);
|
|
62
|
+
|
|
63
|
+
logSpinner({ type: 'info', message: `Completed '${chalk.yellow(data.action)}' (${outputItems.length})` });
|
|
64
|
+
|
|
65
|
+
return outputItems;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getPercentagePrefix(processedItems: number, totalCount: number): string {
|
|
70
|
+
return chalk.gray(`${Math.round((processedItems / totalCount) * 100)}%`);
|
|
71
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { MapiAction, MapiType } from '../models/core.models.js';
|
|
3
|
+
import { LogMessage, LogSpinnerData, Logger } from '../models/log.models.js';
|
|
4
|
+
|
|
5
|
+
export async function runMapiRequestAsync<TResult>(data: {
|
|
6
|
+
readonly logger: Logger;
|
|
7
|
+
readonly logSpinner?: LogSpinnerData;
|
|
8
|
+
readonly action: MapiAction;
|
|
9
|
+
readonly type: MapiType;
|
|
10
|
+
readonly func: () => Promise<TResult>;
|
|
11
|
+
readonly itemName?: string;
|
|
12
|
+
}): Promise<TResult> {
|
|
13
|
+
let logData: LogMessage | undefined;
|
|
14
|
+
|
|
15
|
+
if (data.action === 'list') {
|
|
16
|
+
logData = {
|
|
17
|
+
message: `Fetching objects of type '${chalk.yellow(data.type)}'`,
|
|
18
|
+
type: data.action
|
|
19
|
+
};
|
|
20
|
+
} else if (data.itemName) {
|
|
21
|
+
logData = {
|
|
22
|
+
message: `${data.type} -> ${data.itemName}`,
|
|
23
|
+
type: data.action
|
|
24
|
+
};
|
|
25
|
+
} else {
|
|
26
|
+
logData = {
|
|
27
|
+
message: `${data.type}`,
|
|
28
|
+
type: data.action
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
logSpinnerOrDefault({
|
|
33
|
+
logSpinner: data.logSpinner,
|
|
34
|
+
logger: data.logger,
|
|
35
|
+
logData: logData
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
return await data.func();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function logSpinnerOrDefault(data: {
|
|
42
|
+
readonly logSpinner: LogSpinnerData | undefined;
|
|
43
|
+
readonly logData: LogMessage;
|
|
44
|
+
readonly logger: Logger;
|
|
45
|
+
}): void {
|
|
46
|
+
if (data.logSpinner) {
|
|
47
|
+
data.logSpinner(data.logData);
|
|
48
|
+
} else {
|
|
49
|
+
data.logger.log(data.logData);
|
|
50
|
+
}
|
|
51
|
+
}
|