@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,134 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AssetModels,
|
|
3
|
+
ContentItemModels,
|
|
4
|
+
ContentTypeElements,
|
|
5
|
+
LanguageVariantModels,
|
|
6
|
+
WorkflowModels
|
|
7
|
+
} from '@kontent-ai/management-sdk';
|
|
8
|
+
import { MigrationElementType } from './migration.models.js';
|
|
9
|
+
import { WorkflowStep } from '../helpers/workflow-helper.js';
|
|
10
|
+
|
|
11
|
+
export type TargetItemState = 'exists' | 'doesNotExists';
|
|
12
|
+
export type CliAction = 'export' | 'import' | 'migrate';
|
|
13
|
+
export type GeneralItemType = 'exportedItem' | 'migrationItem';
|
|
14
|
+
export type GeneralActionType = 'readFs' | 'skip' | 'writeFs' | 'download';
|
|
15
|
+
export type EnvContext = 'browser' | 'node';
|
|
16
|
+
|
|
17
|
+
export type MapiAction =
|
|
18
|
+
| 'list'
|
|
19
|
+
| 'view'
|
|
20
|
+
| 'archive'
|
|
21
|
+
| 'unpublish'
|
|
22
|
+
| 'changeWorkflowStep'
|
|
23
|
+
| 'publish'
|
|
24
|
+
| 'upload'
|
|
25
|
+
| 'create'
|
|
26
|
+
| 'upsert'
|
|
27
|
+
| 'createNewVersion';
|
|
28
|
+
|
|
29
|
+
export type MapiType =
|
|
30
|
+
| 'contentType'
|
|
31
|
+
| 'asset'
|
|
32
|
+
| 'contentTypeSnippet'
|
|
33
|
+
| 'contentItem'
|
|
34
|
+
| 'languageVariant'
|
|
35
|
+
| 'language'
|
|
36
|
+
| 'collection'
|
|
37
|
+
| 'taxonomy'
|
|
38
|
+
| 'binaryFile'
|
|
39
|
+
| 'workflow';
|
|
40
|
+
|
|
41
|
+
export interface ItemInfo {
|
|
42
|
+
readonly title: string;
|
|
43
|
+
readonly itemType: GeneralItemType | MapiType;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ErrorData {
|
|
47
|
+
readonly message: string;
|
|
48
|
+
readonly requestData?: string;
|
|
49
|
+
readonly requestUrl?: string;
|
|
50
|
+
readonly isUnknownError: boolean;
|
|
51
|
+
readonly error: unknown;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ReferencedDataInMigrationItems {
|
|
55
|
+
readonly itemCodenames: ReadonlySet<string>;
|
|
56
|
+
readonly assetCodenames: ReadonlySet<string>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ReferencedDataInLanguageVariants {
|
|
60
|
+
readonly itemIds: ReadonlySet<string>;
|
|
61
|
+
readonly assetIds: ReadonlySet<string>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ItemStateInSourceEnvironmentById {
|
|
65
|
+
readonly state: TargetItemState;
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly item: Readonly<ContentItemModels.ContentItem> | undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface AssetStateInSourceEnvironmentById {
|
|
71
|
+
readonly state: TargetItemState;
|
|
72
|
+
readonly id: string;
|
|
73
|
+
readonly asset: Readonly<AssetModels.Asset> | undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ItemStateInTargetEnvironmentByCodename {
|
|
77
|
+
readonly state: TargetItemState;
|
|
78
|
+
readonly itemCodename: string;
|
|
79
|
+
readonly item: Readonly<ContentItemModels.ContentItem> | undefined;
|
|
80
|
+
readonly externalIdToUse: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface LanguageVariantStateInTargetEnvironmentByCodename {
|
|
84
|
+
readonly state: TargetItemState;
|
|
85
|
+
readonly itemCodename: string;
|
|
86
|
+
readonly languageCodename: string;
|
|
87
|
+
readonly languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined;
|
|
88
|
+
readonly workflow: Readonly<WorkflowModels.Workflow> | undefined;
|
|
89
|
+
readonly step: Readonly<WorkflowStep> | undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface AssetStateInTargetEnvironmentByCodename {
|
|
93
|
+
readonly state: TargetItemState;
|
|
94
|
+
readonly assetCodename: string;
|
|
95
|
+
readonly asset: Readonly<AssetModels.Asset> | undefined;
|
|
96
|
+
readonly externalIdToUse: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface PackageMetadata {
|
|
100
|
+
readonly created: Date;
|
|
101
|
+
readonly environmentId: string;
|
|
102
|
+
readonly dataOverview: PackageDataOverview;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface PackageDataOverview {
|
|
106
|
+
readonly contentItemsCount: number;
|
|
107
|
+
readonly assetsCount: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface FlattenedContentTypeElement {
|
|
111
|
+
readonly codename: string;
|
|
112
|
+
readonly id: string;
|
|
113
|
+
readonly type: MigrationElementType;
|
|
114
|
+
readonly element: Readonly<ContentTypeElements.ContentTypeElementModel>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface FlattenedContentType {
|
|
118
|
+
readonly contentTypeCodename: string;
|
|
119
|
+
readonly contentTypeId: string;
|
|
120
|
+
readonly elements: readonly FlattenedContentTypeElement[];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface OriginalManagementError {
|
|
124
|
+
response?: {
|
|
125
|
+
status?: number;
|
|
126
|
+
config?: {
|
|
127
|
+
url?: string;
|
|
128
|
+
data?: string;
|
|
129
|
+
};
|
|
130
|
+
data?: {
|
|
131
|
+
error_code?: number;
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { GeneralActionType, GeneralItemType, MapiAction, MapiType } from '../index.js';
|
|
2
|
+
|
|
3
|
+
export type DebugType =
|
|
4
|
+
| 'error'
|
|
5
|
+
| 'completed'
|
|
6
|
+
| 'warning'
|
|
7
|
+
| 'info'
|
|
8
|
+
| 'errorData'
|
|
9
|
+
| 'cancel'
|
|
10
|
+
| 'process'
|
|
11
|
+
| MapiType
|
|
12
|
+
| GeneralActionType
|
|
13
|
+
| MapiAction
|
|
14
|
+
| GeneralItemType;
|
|
15
|
+
|
|
16
|
+
export interface LogMessage {
|
|
17
|
+
readonly type: DebugType;
|
|
18
|
+
readonly message: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface LogSpinnerMessage extends LogMessage {
|
|
22
|
+
readonly prefix?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type LogData = (data: LogMessage) => void;
|
|
26
|
+
export type LogSpinnerData = (data: LogSpinnerMessage) => void;
|
|
27
|
+
|
|
28
|
+
export interface Logger {
|
|
29
|
+
readonly logWithSpinnerAsync: <T>(func: (logData: LogSpinnerData) => Promise<T>) => Promise<T>;
|
|
30
|
+
readonly log: LogData;
|
|
31
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
export type MigrationElementType =
|
|
2
|
+
| 'text'
|
|
3
|
+
| 'rich_text'
|
|
4
|
+
| 'number'
|
|
5
|
+
| 'multiple_choice'
|
|
6
|
+
| 'date_time'
|
|
7
|
+
| 'asset'
|
|
8
|
+
| 'modular_content'
|
|
9
|
+
| 'taxonomy'
|
|
10
|
+
| 'url_slug'
|
|
11
|
+
| 'custom'
|
|
12
|
+
| 'subpages';
|
|
13
|
+
|
|
14
|
+
export type MigrationUrlSlugMode = 'autogenerated' | 'custom';
|
|
15
|
+
|
|
16
|
+
export interface MigrationRichTextElementValue {
|
|
17
|
+
value: string;
|
|
18
|
+
components: readonly MigrationComponent[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface MigrationUrlSlugElementValue {
|
|
22
|
+
value: string | undefined;
|
|
23
|
+
mode: MigrationUrlSlugMode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface MigrationComponent {
|
|
27
|
+
system: {
|
|
28
|
+
id: string;
|
|
29
|
+
type: MigrationReference;
|
|
30
|
+
};
|
|
31
|
+
elements: MigrationElements;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type MigrationElementValue =
|
|
35
|
+
| string
|
|
36
|
+
| undefined
|
|
37
|
+
| MigrationReference[]
|
|
38
|
+
| number
|
|
39
|
+
| MigrationRichTextElementValue
|
|
40
|
+
| MigrationUrlSlugElementValue;
|
|
41
|
+
|
|
42
|
+
export interface MigrationElement<
|
|
43
|
+
TElementType extends MigrationElementType = MigrationElementType,
|
|
44
|
+
TValue extends MigrationElementValue = MigrationElementValue
|
|
45
|
+
> {
|
|
46
|
+
/**
|
|
47
|
+
* Value of the element
|
|
48
|
+
*/
|
|
49
|
+
readonly value: TValue;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Type of the element
|
|
53
|
+
*/
|
|
54
|
+
readonly type: TElementType;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export namespace MigrationElementModels {
|
|
58
|
+
export interface TextElement extends MigrationElement<'text', string | undefined> {}
|
|
59
|
+
export interface NumberElement extends MigrationElement<'number', number | undefined> {}
|
|
60
|
+
export interface RichTextElement extends MigrationElement<'rich_text', MigrationRichTextElementValue | undefined> {}
|
|
61
|
+
export interface MultipleChoiceElement
|
|
62
|
+
extends MigrationElement<'multiple_choice', MigrationReference[] | undefined> {}
|
|
63
|
+
export interface DateTimeElement extends MigrationElement<'date_time', string | undefined> {}
|
|
64
|
+
export interface AssetElement extends MigrationElement<'asset', MigrationReference[] | undefined> {}
|
|
65
|
+
export interface LinkedItemsElement extends MigrationElement<'modular_content', MigrationReference[] | undefined> {}
|
|
66
|
+
export interface TaxonomyElement extends MigrationElement<'taxonomy', MigrationReference[] | undefined> {}
|
|
67
|
+
export interface UrlSlugElement extends MigrationElement<'url_slug', MigrationUrlSlugElementValue | undefined> {}
|
|
68
|
+
export interface CustomElement extends MigrationElement<'custom', string | undefined> {}
|
|
69
|
+
export interface SubpagesElement extends MigrationElement<'subpages', MigrationReference[] | undefined> {}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface MigrationElements {
|
|
73
|
+
[elementCodename: string]: MigrationElement;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface MigrationItemVersion<TElements extends MigrationElements = MigrationElements> {
|
|
77
|
+
readonly elements: TElements;
|
|
78
|
+
readonly workflow_step: MigrationReference;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface MigrationItem<TElements extends MigrationElements = MigrationElements> {
|
|
82
|
+
readonly system: {
|
|
83
|
+
/**
|
|
84
|
+
* Codename of the content item
|
|
85
|
+
*/
|
|
86
|
+
readonly codename: string;
|
|
87
|
+
/**
|
|
88
|
+
* Name of the content item
|
|
89
|
+
*/
|
|
90
|
+
readonly name: string;
|
|
91
|
+
/**
|
|
92
|
+
* Language of the language variant
|
|
93
|
+
*/
|
|
94
|
+
readonly language: MigrationReference;
|
|
95
|
+
/**
|
|
96
|
+
* Content type of the item
|
|
97
|
+
*/
|
|
98
|
+
readonly type: MigrationReference;
|
|
99
|
+
/**
|
|
100
|
+
* Collection of the item
|
|
101
|
+
*/
|
|
102
|
+
readonly collection: MigrationReference;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Workflow of the item
|
|
106
|
+
*/
|
|
107
|
+
readonly workflow: MigrationReference;
|
|
108
|
+
};
|
|
109
|
+
readonly versions: MigrationItemVersion<TElements>[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface MigrationReference {
|
|
113
|
+
/**
|
|
114
|
+
* Codename of the referenced object
|
|
115
|
+
*/
|
|
116
|
+
readonly codename: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface MigrationAssetDescription {
|
|
120
|
+
readonly language: MigrationReference;
|
|
121
|
+
readonly description?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface MigrationAsset {
|
|
125
|
+
/**
|
|
126
|
+
* Codename of the asset
|
|
127
|
+
*/
|
|
128
|
+
readonly codename: string;
|
|
129
|
+
/**
|
|
130
|
+
* Binary data of the asset
|
|
131
|
+
*/
|
|
132
|
+
readonly binaryData: Buffer | Blob;
|
|
133
|
+
/**
|
|
134
|
+
* Filename of the asset, will be used as a filename in Kontent.ai after importing the asset
|
|
135
|
+
*/
|
|
136
|
+
readonly filename: string;
|
|
137
|
+
/**
|
|
138
|
+
* Title of the asset
|
|
139
|
+
*/
|
|
140
|
+
readonly title: string;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Optional
|
|
144
|
+
* Collection of the asset
|
|
145
|
+
*/
|
|
146
|
+
readonly collection?: MigrationReference;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Optional.
|
|
150
|
+
* Descriptions of the assets
|
|
151
|
+
*/
|
|
152
|
+
readonly descriptions?: readonly MigrationAssetDescription[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface MigrationData {
|
|
156
|
+
/**
|
|
157
|
+
* Array of migration items to process (export / import)
|
|
158
|
+
*/
|
|
159
|
+
readonly items: readonly MigrationItem[];
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Array of migration assets to process
|
|
163
|
+
*/
|
|
164
|
+
readonly assets: readonly MigrationAsset[];
|
|
165
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { MigrationElementValue, MigrationReference } from '../models/migration.models.js';
|
|
2
|
+
|
|
3
|
+
export function parseAsMigrationReferencesArray(value: MigrationElementValue): readonly MigrationReference[] {
|
|
4
|
+
if (!value) {
|
|
5
|
+
return [];
|
|
6
|
+
}
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
throw Error(`Value is not an array`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function findRequired<T>(
|
|
14
|
+
array: readonly T[],
|
|
15
|
+
predicate: (item: T, index: number) => boolean,
|
|
16
|
+
errorMessage: string
|
|
17
|
+
): T;
|
|
18
|
+
export function findRequired<T>(
|
|
19
|
+
array: readonly T[],
|
|
20
|
+
predicate: (item: T, index: number) => boolean,
|
|
21
|
+
errorMessage: () => never
|
|
22
|
+
): T;
|
|
23
|
+
export function findRequired<T>(
|
|
24
|
+
array: readonly T[],
|
|
25
|
+
predicate: (item: T, index: number) => boolean,
|
|
26
|
+
errorMessage: string | (() => never)
|
|
27
|
+
): T {
|
|
28
|
+
const item = array.find(predicate);
|
|
29
|
+
|
|
30
|
+
if (item) {
|
|
31
|
+
return item;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (typeof errorMessage === 'string' || errorMessage instanceof String) {
|
|
35
|
+
throw Error(errorMessage.toString());
|
|
36
|
+
}
|
|
37
|
+
return errorMessage();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function mapAsync<Input, Result>(
|
|
41
|
+
array: readonly Input[],
|
|
42
|
+
callbackAsync: (item: Readonly<Input>, index: number, array: readonly Input[]) => Promise<Readonly<Result>>
|
|
43
|
+
): Promise<Readonly<Result[]>> {
|
|
44
|
+
const results: Result[] = [];
|
|
45
|
+
for (let i = 0; i < array.length; i++) {
|
|
46
|
+
results.push(await callbackAsync(array[i], i, array));
|
|
47
|
+
}
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defaultHttpService, defaultRetryStrategy } from './http.utils.js';
|
|
2
|
+
|
|
3
|
+
export async function getBinaryDataFromUrlAsync(url: string): Promise<{ data: Buffer | Blob; contentLength: number }> {
|
|
4
|
+
// temp fix for Kontent.ai Repository not validating url
|
|
5
|
+
url = url.replace('#', '%23');
|
|
6
|
+
|
|
7
|
+
const response = await defaultHttpService.getAsync<Buffer | Blob>(
|
|
8
|
+
{
|
|
9
|
+
url
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
responseType: 'arraybuffer',
|
|
13
|
+
retryStrategy: defaultRetryStrategy
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const contentLengthHeader = response.headers.find((m) => m.header.toLowerCase() === 'content-length');
|
|
18
|
+
const contentLength = contentLengthHeader ? +contentLengthHeader.value : 0;
|
|
19
|
+
|
|
20
|
+
return { data: response.data, contentLength: contentLength };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function geSizeInBytes(data: Blob | Buffer): number {
|
|
24
|
+
if (data instanceof Blob) {
|
|
25
|
+
return data.size;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return data.byteLength;
|
|
29
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { Logger } from '../models/log.models.js';
|
|
3
|
+
import { getMigrationManagementClient, managementClientUtils } from './management-client-utils.js';
|
|
4
|
+
|
|
5
|
+
export async function confirmExportAsync(data: {
|
|
6
|
+
readonly force: boolean;
|
|
7
|
+
readonly environmentId: string;
|
|
8
|
+
readonly apiKey: string;
|
|
9
|
+
readonly logger: Logger;
|
|
10
|
+
readonly dataToExport: {
|
|
11
|
+
readonly itemsCount: number;
|
|
12
|
+
};
|
|
13
|
+
}): Promise<void> {
|
|
14
|
+
const environment = await managementClientUtils(
|
|
15
|
+
getMigrationManagementClient({
|
|
16
|
+
environmentId: data.environmentId,
|
|
17
|
+
apiKey: data.apiKey
|
|
18
|
+
}),
|
|
19
|
+
data.logger
|
|
20
|
+
).getEnvironmentAsync();
|
|
21
|
+
|
|
22
|
+
const text: string = `Are you sure to export '${chalk.cyan(
|
|
23
|
+
data.dataToExport.itemsCount
|
|
24
|
+
)}' content ${getItemsPluralText(data.dataToExport.itemsCount)} from ${chalk.yellow(
|
|
25
|
+
environment.name
|
|
26
|
+
)} (${chalk.yellow(environment.environment)}?`;
|
|
27
|
+
|
|
28
|
+
await confirmAsync({
|
|
29
|
+
force: data.force,
|
|
30
|
+
logger: data.logger,
|
|
31
|
+
action: 'Export',
|
|
32
|
+
message: text
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function confirmMigrateAsync(data: {
|
|
37
|
+
readonly force: boolean;
|
|
38
|
+
readonly sourceEnvironment: {
|
|
39
|
+
readonly environmentId: string;
|
|
40
|
+
readonly apiKey: string;
|
|
41
|
+
};
|
|
42
|
+
readonly targetEnvironment: {
|
|
43
|
+
readonly environmentId: string;
|
|
44
|
+
readonly apiKey: string;
|
|
45
|
+
};
|
|
46
|
+
readonly logger: Logger;
|
|
47
|
+
readonly dataToMigrate: {
|
|
48
|
+
readonly itemsCount: number;
|
|
49
|
+
};
|
|
50
|
+
}): Promise<void> {
|
|
51
|
+
const sourceEnvironment = await managementClientUtils(
|
|
52
|
+
getMigrationManagementClient({
|
|
53
|
+
environmentId: data.sourceEnvironment.environmentId,
|
|
54
|
+
apiKey: data.sourceEnvironment.apiKey
|
|
55
|
+
}),
|
|
56
|
+
data.logger
|
|
57
|
+
).getEnvironmentAsync();
|
|
58
|
+
const targetEnvironment = await managementClientUtils(
|
|
59
|
+
getMigrationManagementClient({
|
|
60
|
+
environmentId: data.targetEnvironment.environmentId,
|
|
61
|
+
apiKey: data.targetEnvironment.apiKey
|
|
62
|
+
}),
|
|
63
|
+
data.logger
|
|
64
|
+
).getEnvironmentAsync();
|
|
65
|
+
|
|
66
|
+
const text: string = `Are you sure to migrate '${chalk.cyan(data.dataToMigrate.itemsCount)}' ${getItemsPluralText(
|
|
67
|
+
data.dataToMigrate.itemsCount
|
|
68
|
+
)} from ${chalk.yellow(sourceEnvironment.name)} (${chalk.yellow(
|
|
69
|
+
sourceEnvironment.environment
|
|
70
|
+
)}) to environment ${chalk.yellow(targetEnvironment.name)} (${chalk.yellow(targetEnvironment.environment)}) ?`;
|
|
71
|
+
|
|
72
|
+
await confirmAsync({
|
|
73
|
+
force: data.force,
|
|
74
|
+
logger: data.logger,
|
|
75
|
+
action: 'Migrate',
|
|
76
|
+
message: text
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function confirmImportAsync(data: {
|
|
81
|
+
readonly force: boolean;
|
|
82
|
+
readonly environmentId: string;
|
|
83
|
+
readonly apiKey: string;
|
|
84
|
+
readonly logger: Logger;
|
|
85
|
+
}): Promise<void> {
|
|
86
|
+
const environment = await managementClientUtils(
|
|
87
|
+
getMigrationManagementClient({
|
|
88
|
+
environmentId: data.environmentId,
|
|
89
|
+
apiKey: data.apiKey
|
|
90
|
+
}),
|
|
91
|
+
data.logger
|
|
92
|
+
).getEnvironmentAsync();
|
|
93
|
+
|
|
94
|
+
const text: string = `Are you sure to import data into ${chalk.yellow(environment.name)} (${chalk.yellow(
|
|
95
|
+
environment.environment
|
|
96
|
+
)})?`;
|
|
97
|
+
|
|
98
|
+
await confirmAsync({
|
|
99
|
+
force: data.force,
|
|
100
|
+
logger: data.logger,
|
|
101
|
+
action: 'Import',
|
|
102
|
+
message: text
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function confirmAsync(data: {
|
|
107
|
+
readonly action: string;
|
|
108
|
+
readonly message: string;
|
|
109
|
+
readonly force: boolean;
|
|
110
|
+
readonly logger: Logger;
|
|
111
|
+
}): Promise<void> {
|
|
112
|
+
// Prompts is imported dynamically because it's a node.js only module and would not work if user
|
|
113
|
+
// tried using this library in a browser
|
|
114
|
+
const prompts = await import('prompts');
|
|
115
|
+
|
|
116
|
+
if (data.force) {
|
|
117
|
+
data.logger.log({
|
|
118
|
+
type: 'info',
|
|
119
|
+
message: `Skipping confirmation prompt due to the use of 'force' param`
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
const confirmed = await prompts.default({
|
|
123
|
+
type: 'confirm',
|
|
124
|
+
name: 'confirm',
|
|
125
|
+
message: `${chalk.cyan(data.action)}: ${data.message}`
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
if (!confirmed.confirm) {
|
|
129
|
+
throw Error(`Confirmation refused.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getItemsPluralText(count: number): string {
|
|
135
|
+
if (count === 1) {
|
|
136
|
+
return 'item';
|
|
137
|
+
}
|
|
138
|
+
return 'items';
|
|
139
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { SharedModels } from '@kontent-ai/management-sdk';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ErrorData, OriginalManagementError } from '../models/core.models.js';
|
|
4
|
+
|
|
5
|
+
export function extractErrorData(error: unknown): ErrorData {
|
|
6
|
+
let isUnknownError: boolean = true;
|
|
7
|
+
let message: string = `Unknown error`;
|
|
8
|
+
let requestUrl: string | undefined = undefined;
|
|
9
|
+
let requestData: string | undefined = undefined;
|
|
10
|
+
|
|
11
|
+
if (error instanceof SharedModels.ContentManagementBaseKontentError) {
|
|
12
|
+
isUnknownError = false;
|
|
13
|
+
message = `${error.message}`;
|
|
14
|
+
|
|
15
|
+
const originalError: OriginalManagementError | undefined = error.originalError as
|
|
16
|
+
| OriginalManagementError
|
|
17
|
+
| undefined;
|
|
18
|
+
|
|
19
|
+
requestUrl = originalError?.response?.config?.url;
|
|
20
|
+
requestData = originalError?.response?.config?.data;
|
|
21
|
+
message += error.validationErrors.map((m) => m.message).join(', ');
|
|
22
|
+
} else if (error instanceof Error) {
|
|
23
|
+
message = error.message;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const errorData: ErrorData = {
|
|
27
|
+
message: message,
|
|
28
|
+
requestData: requestData,
|
|
29
|
+
requestUrl: requestUrl,
|
|
30
|
+
error: error,
|
|
31
|
+
isUnknownError: isUnknownError
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return errorData;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function is404Error(error: unknown): boolean {
|
|
38
|
+
if (error instanceof SharedModels.ContentManagementBaseKontentError) {
|
|
39
|
+
const originalError = error.originalError as OriginalManagementError | undefined;
|
|
40
|
+
|
|
41
|
+
if (originalError?.response?.status === 404) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function handleError(error: unknown): void {
|
|
50
|
+
const errorData = extractErrorData(error);
|
|
51
|
+
|
|
52
|
+
if (errorData.isUnknownError) {
|
|
53
|
+
console.error(error);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (errorData.requestData) {
|
|
57
|
+
console.log(`${chalk.red('Request data')}: ${errorData.requestData}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (errorData.requestUrl) {
|
|
61
|
+
console.log(`${chalk.red('Request url')}: ${errorData.requestUrl}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.error(`${chalk.red('Error:')} ${errorData.message}`);
|
|
65
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ExternalIdGenerator {
|
|
2
|
+
readonly assetExternalId: (codename: string) => string;
|
|
3
|
+
readonly contentItemExternalId: (codename: string) => string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const defaultExternalIdGenerator: ExternalIdGenerator = {
|
|
7
|
+
assetExternalId: (codename) => `asset_${codename}`,
|
|
8
|
+
contentItemExternalId: (codename) => `item_${codename}`
|
|
9
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { format } from 'bytes';
|
|
2
|
+
import { ITrackingEventData, getTrackingService } from '@kontent-ai-consulting/tools-analytics';
|
|
3
|
+
import { isBrowser, isNode, isWebWorker } from 'browser-or-node';
|
|
4
|
+
import { EnvContext } from '../models/core.models.js';
|
|
5
|
+
|
|
6
|
+
export const isNotUndefined = <T>(item: T | undefined): item is T => item !== undefined;
|
|
7
|
+
|
|
8
|
+
export function formatBytes(bytes: number): string {
|
|
9
|
+
return format(bytes);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function sleepAsync(ms: number): Promise<void> {
|
|
13
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function exitProgram(data: { readonly message: string }): never {
|
|
17
|
+
throw Error(data.message);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getCurrentEnvironment(): EnvContext {
|
|
21
|
+
if (isNode) {
|
|
22
|
+
return 'node';
|
|
23
|
+
}
|
|
24
|
+
if (isBrowser || isWebWorker) {
|
|
25
|
+
return 'browser';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
throw Error(`Invalid current environment. This library can be used in node.js or in browsers.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getDefaultZipFilename(): string {
|
|
32
|
+
return `data.zip`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function executeWithTrackingAsync<TResult>(data: {
|
|
36
|
+
func: () => Promise<TResult extends void ? void : Readonly<TResult>>;
|
|
37
|
+
event: Readonly<ITrackingEventData>;
|
|
38
|
+
}): Promise<TResult extends void ? void : Readonly<TResult>> {
|
|
39
|
+
const trackingService = getTrackingService();
|
|
40
|
+
const event = await trackingService.trackEventAsync(data.event);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const result = await data.func();
|
|
44
|
+
|
|
45
|
+
await trackingService.setEventResultAsync({
|
|
46
|
+
eventId: event.eventId,
|
|
47
|
+
result: 'success'
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
await trackingService.setEventResultAsync({
|
|
53
|
+
eventId: event.eventId,
|
|
54
|
+
result: 'fail'
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|