@kontent-ai/migration-toolkit 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -67
- package/dist/es2022/core/helpers/workflow-helper.d.ts +1 -0
- package/dist/es2022/core/helpers/workflow-helper.js +6 -4
- package/dist/es2022/core/helpers/workflow-helper.js.map +1 -1
- package/dist/es2022/core/logs/loggers.js +13 -22
- package/dist/es2022/core/logs/loggers.js.map +1 -1
- package/dist/es2022/core/models/core.models.d.ts +16 -6
- package/dist/es2022/core/models/migration.models.d.ts +9 -9
- package/dist/es2022/core/models/migration.schema.d.ts +247 -0
- package/dist/es2022/core/models/migration.schema.js +12 -2
- package/dist/es2022/core/models/migration.schema.js.map +1 -1
- package/dist/es2022/core/utils/array.utils.js.map +1 -1
- package/dist/es2022/core/utils/binary-data.utils.js +2 -6
- package/dist/es2022/core/utils/binary-data.utils.js.map +1 -1
- package/dist/es2022/core/utils/confirm.utils.js +10 -14
- package/dist/es2022/core/utils/confirm.utils.js.map +1 -1
- package/dist/es2022/core/utils/error.utils.js +35 -27
- package/dist/es2022/core/utils/error.utils.js.map +1 -1
- package/dist/es2022/core/utils/http.utils.js +7 -11
- package/dist/es2022/core/utils/http.utils.js.map +1 -1
- package/dist/es2022/core/utils/management-client-utils.d.ts +2 -1
- package/dist/es2022/core/utils/management-client-utils.js +12 -2
- package/dist/es2022/core/utils/management-client-utils.js.map +1 -1
- package/dist/es2022/core/utils/run.utils.js +12 -10
- package/dist/es2022/core/utils/run.utils.js.map +1 -1
- package/dist/es2022/export/context/export-context-fetcher.js +2 -1
- package/dist/es2022/export/context/export-context-fetcher.js.map +1 -1
- package/dist/es2022/export/export-manager.js +8 -0
- package/dist/es2022/export/export-manager.js.map +1 -1
- package/dist/es2022/export/export.models.d.ts +2 -1
- package/dist/es2022/import/comparers/asset-comparer.d.ts +2 -1
- package/dist/es2022/import/comparers/asset-comparer.js +9 -17
- package/dist/es2022/import/comparers/asset-comparer.js.map +1 -1
- package/dist/es2022/import/context/import-context-fetcher.js +120 -40
- package/dist/es2022/import/context/import-context-fetcher.js.map +1 -1
- package/dist/es2022/import/import.models.d.ts +2 -1
- package/dist/es2022/import/importers/assets-importer.js +12 -2
- package/dist/es2022/import/importers/assets-importer.js.map +1 -1
- package/dist/es2022/import/importers/language-variant-importer.js +95 -83
- package/dist/es2022/import/importers/language-variant-importer.js.map +1 -1
- package/dist/es2022/import/importers/workflow-importer.d.ts +41 -4
- package/dist/es2022/import/importers/workflow-importer.js +158 -17
- package/dist/es2022/import/importers/workflow-importer.js.map +1 -1
- package/dist/es2022/metadata.js +2 -2
- package/dist/es2022/node/cli/app.js +8 -12
- package/dist/es2022/node/cli/app.js.map +1 -1
- package/dist/es2022/node/cli/args/args-fetcher.js +9 -10
- package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -1
- package/dist/es2022/toolkit/migrate.d.ts +1 -3
- package/dist/es2022/toolkit/migrate.js.map +1 -1
- package/dist/es2022/translation/extraction/items-extraction.processor.js +17 -17
- package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -1
- package/dist/es2022/translation/transforms/export-transforms.js +1 -1
- package/dist/es2022/translation/transforms/export-transforms.js.map +1 -1
- package/dist/es2022/zip/zip-packager.js +13 -18
- package/dist/es2022/zip/zip-packager.js.map +1 -1
- package/dist/es2022/zip/zip-transformer.js +3 -1
- package/dist/es2022/zip/zip-transformer.js.map +1 -1
- package/lib/core/helpers/workflow-helper.ts +8 -8
- package/lib/core/logs/loggers.ts +14 -22
- package/lib/core/models/core.models.ts +23 -4
- package/lib/core/models/migration.models.ts +13 -12
- package/lib/core/models/migration.schema.ts +189 -178
- package/lib/core/utils/array.utils.ts +2 -10
- package/lib/core/utils/binary-data.utils.ts +2 -7
- package/lib/core/utils/confirm.utils.ts +18 -24
- package/lib/core/utils/error.utils.ts +50 -30
- package/lib/core/utils/http.utils.ts +14 -15
- package/lib/core/utils/management-client-utils.ts +188 -182
- package/lib/core/utils/run.utils.ts +27 -18
- package/lib/export/context/export-context-fetcher.ts +2 -1
- package/lib/export/export-manager.ts +14 -3
- package/lib/export/export.models.ts +3 -1
- package/lib/import/comparers/asset-comparer.ts +16 -24
- package/lib/import/context/import-context-fetcher.ts +179 -85
- package/lib/import/import.models.ts +2 -0
- package/lib/import/importers/assets-importer.ts +19 -12
- package/lib/import/importers/language-variant-importer.ts +125 -129
- package/lib/import/importers/workflow-importer.ts +228 -20
- package/lib/metadata.ts +2 -2
- package/lib/node/cli/app.ts +11 -12
- package/lib/node/cli/args/args-fetcher.ts +12 -14
- package/lib/toolkit/migrate.ts +1 -3
- package/lib/translation/extraction/items-extraction.processor.ts +93 -93
- package/lib/translation/transforms/export-transforms.ts +1 -1
- package/lib/zip/zip-packager.ts +26 -28
- package/lib/zip/zip-transformer.ts +3 -1
- package/package.json +14 -13
|
@@ -1,182 +1,188 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
readonly
|
|
24
|
-
readonly
|
|
25
|
-
readonly
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
1
|
+
import {
|
|
2
|
+
AssetFolderModels,
|
|
3
|
+
CollectionModels,
|
|
4
|
+
ContentTypeModels,
|
|
5
|
+
ContentTypeSnippetModels,
|
|
6
|
+
EnvironmentModels,
|
|
7
|
+
LanguageModels,
|
|
8
|
+
ManagementClient,
|
|
9
|
+
TaxonomyModels,
|
|
10
|
+
WorkflowModels,
|
|
11
|
+
createManagementClient
|
|
12
|
+
} from '@kontent-ai/management-sdk';
|
|
13
|
+
import { IRetryStrategyOptions } from '@kontent-ai/core-sdk';
|
|
14
|
+
import { runMapiRequestAsync } from './run.utils.js';
|
|
15
|
+
import { LogSpinnerData, Logger } from '../models/log.models.js';
|
|
16
|
+
import { FlattenedContentType, FlattenedContentTypeElement } from '../models/core.models.js';
|
|
17
|
+
import { isNotUndefined } from './global.utils.js';
|
|
18
|
+
import chalk from 'chalk';
|
|
19
|
+
import { defaultHttpService, defaultRetryStrategy } from './http.utils.js';
|
|
20
|
+
import { findRequired } from './array.utils.js';
|
|
21
|
+
|
|
22
|
+
export interface ManagementClientConfig {
|
|
23
|
+
readonly environmentId: string;
|
|
24
|
+
readonly apiKey: string;
|
|
25
|
+
readonly retryStrategy?: Readonly<IRetryStrategyOptions>;
|
|
26
|
+
readonly baseUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getMigrationManagementClient(config: ManagementClientConfig): ManagementClient {
|
|
30
|
+
return createManagementClient({
|
|
31
|
+
environmentId: config.environmentId,
|
|
32
|
+
retryStrategy: config.retryStrategy ?? defaultRetryStrategy,
|
|
33
|
+
httpService: defaultHttpService,
|
|
34
|
+
apiKey: config.apiKey
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function managementClientUtils(client: Readonly<ManagementClient>, logger: Logger) {
|
|
39
|
+
const getEnvironmentAsync = async (): Promise<EnvironmentModels.EnvironmentInformationModel> => {
|
|
40
|
+
return (await client.environmentInformation().toPromise()).data.project;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const getAllLanguagesAsync = async (logSpinner: LogSpinnerData): Promise<readonly LanguageModels.LanguageModel[]> => {
|
|
44
|
+
return await runMapiRequestAsync({
|
|
45
|
+
logSpinner: logSpinner,
|
|
46
|
+
logger: logger,
|
|
47
|
+
func: async () => (await client.listLanguages().toAllPromise()).data.items,
|
|
48
|
+
action: 'list',
|
|
49
|
+
type: 'language'
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const getAllCollectionsAsync = async (logSpinner: LogSpinnerData): Promise<readonly CollectionModels.Collection[]> => {
|
|
54
|
+
return await runMapiRequestAsync({
|
|
55
|
+
logger: logger,
|
|
56
|
+
logSpinner: logSpinner,
|
|
57
|
+
func: async () => (await client.listCollections().toPromise()).data.collections,
|
|
58
|
+
action: 'list',
|
|
59
|
+
type: 'collection'
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const getAllWorkflowsAsync = async (logSpinner: LogSpinnerData): Promise<readonly WorkflowModels.Workflow[]> => {
|
|
64
|
+
return await runMapiRequestAsync({
|
|
65
|
+
logger: logger,
|
|
66
|
+
logSpinner: logSpinner,
|
|
67
|
+
func: async () => (await client.listWorkflows().toPromise()).data,
|
|
68
|
+
action: 'list',
|
|
69
|
+
type: 'workflow'
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const getAllTaxonomiesAsync = async (logSpinner: LogSpinnerData): Promise<readonly TaxonomyModels.Taxonomy[]> => {
|
|
74
|
+
return await runMapiRequestAsync({
|
|
75
|
+
logger: logger,
|
|
76
|
+
logSpinner: logSpinner,
|
|
77
|
+
func: async () => (await client.listTaxonomies().toAllPromise()).data.items,
|
|
78
|
+
action: 'list',
|
|
79
|
+
type: 'taxonomy'
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const getAllAssetFoldersAsync = async (logSpinner: LogSpinnerData): Promise<readonly AssetFolderModels.AssetFolder[]> => {
|
|
84
|
+
return await runMapiRequestAsync({
|
|
85
|
+
logger: logger,
|
|
86
|
+
logSpinner: logSpinner,
|
|
87
|
+
func: async () => (await client.listAssetFolders().toPromise()).data.items,
|
|
88
|
+
action: 'list',
|
|
89
|
+
type: 'assetFolder'
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const getContentTypeElements = (
|
|
94
|
+
contentType: ContentTypeModels.ContentType,
|
|
95
|
+
contentTypeSnippets: readonly ContentTypeSnippetModels.ContentTypeSnippet[]
|
|
96
|
+
): readonly FlattenedContentTypeElement[] => {
|
|
97
|
+
return contentType.elements
|
|
98
|
+
.flatMap((element) => {
|
|
99
|
+
if (!element.codename || !element.id) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (element.type === 'guidelines') {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (element.type === 'snippet') {
|
|
108
|
+
const snippetElement = element;
|
|
109
|
+
|
|
110
|
+
// replace snippet element with actual elements
|
|
111
|
+
const contentTypeSnippet = findRequired(
|
|
112
|
+
contentTypeSnippets,
|
|
113
|
+
(snippet) => snippet.id === snippetElement.snippet.id,
|
|
114
|
+
`Could not find content type snippet for element. This snippet is referenced in type '${chalk.red(
|
|
115
|
+
contentType.codename
|
|
116
|
+
)}'`
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
return contentTypeSnippet.elements.map((snippetElement) => {
|
|
120
|
+
if (snippetElement.type === 'guidelines' || snippetElement.type === 'snippet') {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
if (!snippetElement.codename || !snippetElement.id) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const flattenedElement: FlattenedContentTypeElement = {
|
|
128
|
+
codename: snippetElement.codename,
|
|
129
|
+
type: snippetElement.type,
|
|
130
|
+
id: snippetElement.id,
|
|
131
|
+
element: snippetElement
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return flattenedElement;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const flattenedElement: FlattenedContentTypeElement = {
|
|
138
|
+
codename: element.codename,
|
|
139
|
+
id: element.id,
|
|
140
|
+
type: element.type,
|
|
141
|
+
element: element
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return flattenedElement;
|
|
145
|
+
})
|
|
146
|
+
.filter(isNotUndefined);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const getFlattenedContentTypesAsync = async (logSpinner: LogSpinnerData): Promise<readonly FlattenedContentType[]> => {
|
|
150
|
+
const contentTypes = await runMapiRequestAsync({
|
|
151
|
+
logger: logger,
|
|
152
|
+
logSpinner: logSpinner,
|
|
153
|
+
func: async () => (await client.listContentTypes().toAllPromise()).data.items,
|
|
154
|
+
action: 'list',
|
|
155
|
+
type: 'contentType'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const contentTypeSnippets = await runMapiRequestAsync({
|
|
159
|
+
logger: logger,
|
|
160
|
+
logSpinner: logSpinner,
|
|
161
|
+
func: async () => (await client.listContentTypeSnippets().toAllPromise()).data.items,
|
|
162
|
+
action: 'list',
|
|
163
|
+
type: 'contentTypeSnippet'
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return [
|
|
167
|
+
...contentTypes.map((contentType) => {
|
|
168
|
+
const importType: FlattenedContentType = {
|
|
169
|
+
contentTypeCodename: contentType.codename,
|
|
170
|
+
contentTypeId: contentType.id,
|
|
171
|
+
elements: getContentTypeElements(contentType, contentTypeSnippets)
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return importType;
|
|
175
|
+
})
|
|
176
|
+
];
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
getAllCollectionsAsync,
|
|
181
|
+
getAllLanguagesAsync,
|
|
182
|
+
getAllWorkflowsAsync,
|
|
183
|
+
getAllTaxonomiesAsync,
|
|
184
|
+
getFlattenedContentTypesAsync,
|
|
185
|
+
getEnvironmentAsync,
|
|
186
|
+
getAllAssetFoldersAsync
|
|
187
|
+
};
|
|
188
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { MapiAction, MapiType } from '../models/core.models.js';
|
|
3
3
|
import { LogMessage, LogSpinnerData, Logger } from '../models/log.models.js';
|
|
4
|
+
import { match } from 'ts-pattern';
|
|
4
5
|
|
|
5
6
|
export async function runMapiRequestAsync<TResult>(data: {
|
|
6
7
|
readonly logger: Logger;
|
|
@@ -10,24 +11,32 @@ export async function runMapiRequestAsync<TResult>(data: {
|
|
|
10
11
|
readonly func: () => Promise<TResult>;
|
|
11
12
|
readonly itemName?: string;
|
|
12
13
|
}): Promise<TResult> {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
const logData: LogMessage = match(data)
|
|
15
|
+
.returnType<LogMessage>()
|
|
16
|
+
.when(
|
|
17
|
+
(data) => data.action === 'list',
|
|
18
|
+
(data) => {
|
|
19
|
+
return {
|
|
20
|
+
message: `Fetching objects of type '${chalk.yellow(data.type)}'`,
|
|
21
|
+
type: data.action
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
.when(
|
|
26
|
+
(data) => data.itemName,
|
|
27
|
+
(data) => {
|
|
28
|
+
return {
|
|
29
|
+
message: `${data.type} -> ${data.itemName}`,
|
|
30
|
+
type: data.action
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
.otherwise(() => {
|
|
35
|
+
return {
|
|
36
|
+
message: `${data.type}`,
|
|
37
|
+
type: data.action
|
|
38
|
+
};
|
|
39
|
+
});
|
|
31
40
|
|
|
32
41
|
logSpinnerOrDefault({
|
|
33
42
|
logSpinner: data.logSpinner,
|
|
@@ -44,7 +44,8 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
|
|
|
44
44
|
contentTypes: await mapiUtils.getFlattenedContentTypesAsync(spinnerData),
|
|
45
45
|
languages: await mapiUtils.getAllLanguagesAsync(spinnerData),
|
|
46
46
|
workflows: await mapiUtils.getAllWorkflowsAsync(spinnerData),
|
|
47
|
-
taxonomies: await mapiUtils.getAllTaxonomiesAsync(spinnerData)
|
|
47
|
+
taxonomies: await mapiUtils.getAllTaxonomiesAsync(spinnerData),
|
|
48
|
+
assetFolders: await mapiUtils.getAllAssetFoldersAsync(spinnerData)
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
spinnerData({ type: 'info', message: `Environmental data loaded` });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ExportContext, ExportConfig, ExportItem } from './export.models.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { AssetModels, CollectionModels, ElementModels } from '@kontent-ai/management-sdk';
|
|
3
|
+
import { AssetFolderModels, AssetModels, CollectionModels, ElementModels } from '@kontent-ai/management-sdk';
|
|
4
4
|
import {
|
|
5
5
|
MigrationAsset,
|
|
6
6
|
MigrationItem,
|
|
@@ -19,7 +19,8 @@ import {
|
|
|
19
19
|
findRequired,
|
|
20
20
|
Writeable,
|
|
21
21
|
MigrationItemsSchema,
|
|
22
|
-
MigrationAssetsSchema
|
|
22
|
+
MigrationAssetsSchema,
|
|
23
|
+
MigrationItemVersion
|
|
23
24
|
} from '../core/index.js';
|
|
24
25
|
import { exportTransforms } from '../translation/index.js';
|
|
25
26
|
import { exportContextFetcherAsync } from './context/export-context-fetcher.js';
|
|
@@ -45,8 +46,14 @@ export function exportManager(config: ExportConfig) {
|
|
|
45
46
|
}
|
|
46
47
|
},
|
|
47
48
|
versions: exportItem.versions.map((version) => {
|
|
48
|
-
return {
|
|
49
|
+
return <MigrationItemVersion>{
|
|
49
50
|
elements: getMigrationElements(context, exportItem.contentType, version.languageVariant.elements),
|
|
51
|
+
schedule: {
|
|
52
|
+
publish_time: version.languageVariant.schedule.publishTime ?? undefined,
|
|
53
|
+
publish_display_timezone: version.languageVariant.schedule.publishDisplayTimezone ?? undefined,
|
|
54
|
+
unpublish_display_timezone: version.languageVariant.schedule.unpublishDisplayTimezone ?? undefined,
|
|
55
|
+
unpublish_time: version.languageVariant.schedule.unpublishTime ?? undefined
|
|
56
|
+
},
|
|
50
57
|
workflow_step: {
|
|
51
58
|
codename: version.workflowStepCodename
|
|
52
59
|
}
|
|
@@ -182,6 +189,9 @@ export function exportManager(config: ExportConfig) {
|
|
|
182
189
|
const assetCollection: Readonly<CollectionModels.Collection> | undefined = context.environmentData.collections.find(
|
|
183
190
|
(m) => m.id === asset.collection?.reference?.id
|
|
184
191
|
);
|
|
192
|
+
const assetFolder: Readonly<AssetFolderModels.AssetFolder> | undefined = context.environmentData.assetFolders.find(
|
|
193
|
+
(m) => m.id === asset.folder?.id
|
|
194
|
+
);
|
|
185
195
|
|
|
186
196
|
logSpinner({
|
|
187
197
|
type: 'download',
|
|
@@ -196,6 +206,7 @@ export function exportManager(config: ExportConfig) {
|
|
|
196
206
|
codename: asset.codename,
|
|
197
207
|
binaryData: binaryData.data,
|
|
198
208
|
collection: assetCollection ? { codename: assetCollection.codename } : undefined,
|
|
209
|
+
folder: assetFolder ? { codename: assetFolder.codename } : undefined,
|
|
199
210
|
descriptions: asset.descriptions.map((description) => {
|
|
200
211
|
const language = findRequired(
|
|
201
212
|
context.environmentData.languages,
|
|
@@ -18,13 +18,15 @@ import {
|
|
|
18
18
|
LanguageModels,
|
|
19
19
|
TaxonomyModels,
|
|
20
20
|
ManagementClient,
|
|
21
|
-
SharedModels
|
|
21
|
+
SharedModels,
|
|
22
|
+
AssetFolderModels
|
|
22
23
|
} from '@kontent-ai/management-sdk';
|
|
23
24
|
|
|
24
25
|
export interface ExportContextEnvironmentData {
|
|
25
26
|
readonly languages: readonly Readonly<LanguageModels.LanguageModel>[];
|
|
26
27
|
readonly contentTypes: readonly Readonly<FlattenedContentType>[];
|
|
27
28
|
readonly collections: readonly Readonly<CollectionModels.Collection>[];
|
|
29
|
+
readonly assetFolders: readonly Readonly<AssetFolderModels.AssetFolder>[];
|
|
28
30
|
readonly workflows: readonly Readonly<WorkflowModels.Workflow>[];
|
|
29
31
|
readonly taxonomies: readonly Readonly<TaxonomyModels.Taxonomy>[];
|
|
30
32
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AssetModels, CollectionModels, LanguageModels } from '@kontent-ai/management-sdk';
|
|
1
|
+
import { AssetFolderModels, AssetModels, CollectionModels, LanguageModels } from '@kontent-ai/management-sdk';
|
|
2
2
|
import { MigrationAsset, MigrationAssetDescription, findRequired, geSizeInBytes } from '../../core/index.js';
|
|
3
3
|
import deepEqual from 'deep-equal';
|
|
4
4
|
|
|
@@ -7,35 +7,22 @@ export function shouldUpdateAsset(data: {
|
|
|
7
7
|
readonly targetAsset: Readonly<AssetModels.Asset>;
|
|
8
8
|
readonly collections: readonly Readonly<CollectionModels.Collection>[];
|
|
9
9
|
readonly languages: readonly Readonly<LanguageModels.LanguageModel>[];
|
|
10
|
+
readonly assetFolders: readonly Readonly<AssetFolderModels.AssetFolder>[];
|
|
10
11
|
}): boolean {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!isTitleIdentical(data)) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (!isBinaryFileIdentical(data)) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return false;
|
|
12
|
+
return (
|
|
13
|
+
!isInSameCollection(data) ||
|
|
14
|
+
!areDescriptionsIdentical(data) ||
|
|
15
|
+
!isTitleIdentical(data) ||
|
|
16
|
+
!isFolderIdentical(data) ||
|
|
17
|
+
!isBinaryFileIdentical(data)
|
|
18
|
+
);
|
|
28
19
|
}
|
|
29
20
|
|
|
30
21
|
export function shouldReplaceBinaryFile(data: {
|
|
31
22
|
readonly migrationAsset: MigrationAsset;
|
|
32
23
|
readonly targetAsset: Readonly<AssetModels.Asset>;
|
|
33
24
|
}): boolean {
|
|
34
|
-
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return false;
|
|
25
|
+
return !isBinaryFileIdentical(data);
|
|
39
26
|
}
|
|
40
27
|
|
|
41
28
|
function isBinaryFileIdentical(data: {
|
|
@@ -51,10 +38,15 @@ function isBinaryFileIdentical(data: {
|
|
|
51
38
|
return sourceFileSize === targetFileSize && sourceFilename === targetFilename;
|
|
52
39
|
}
|
|
53
40
|
|
|
54
|
-
function
|
|
41
|
+
function isFolderIdentical(data: {
|
|
55
42
|
readonly migrationAsset: MigrationAsset;
|
|
56
43
|
readonly targetAsset: Readonly<AssetModels.Asset>;
|
|
44
|
+
readonly assetFolders: readonly Readonly<AssetFolderModels.AssetFolder>[];
|
|
57
45
|
}): boolean {
|
|
46
|
+
return data.assetFolders.find((m) => m.id === data.targetAsset.folder?.id)?.codename === data.migrationAsset.folder?.codename;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isTitleIdentical(data: { readonly migrationAsset: MigrationAsset; readonly targetAsset: Readonly<AssetModels.Asset> }): boolean {
|
|
58
50
|
const sourceTitle = data.migrationAsset.title?.length ? data.migrationAsset.title : undefined;
|
|
59
51
|
const targetTitle = data.targetAsset.title?.length ? data.targetAsset.title : undefined;
|
|
60
52
|
|