@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.
Files changed (240) hide show
  1. package/.npmignore +13 -0
  2. package/LICENSE.md +9 -0
  3. package/README.md +272 -0
  4. package/dist/es2022/core/helpers/workflow-helper.d.ts +37 -0
  5. package/dist/es2022/core/helpers/workflow-helper.js +67 -0
  6. package/dist/es2022/core/helpers/workflow-helper.js.map +1 -0
  7. package/dist/es2022/core/index.d.ts +15 -0
  8. package/dist/es2022/core/index.js +16 -0
  9. package/dist/es2022/core/index.js.map +1 -0
  10. package/dist/es2022/core/logs/loggers.d.ts +2 -0
  11. package/dist/es2022/core/logs/loggers.js +69 -0
  12. package/dist/es2022/core/logs/loggers.js.map +1 -0
  13. package/dist/es2022/core/models/core.models.d.ts +91 -0
  14. package/dist/es2022/core/models/core.models.js +2 -0
  15. package/dist/es2022/core/models/core.models.js.map +1 -0
  16. package/dist/es2022/core/models/log.models.d.ts +15 -0
  17. package/dist/es2022/core/models/log.models.js +2 -0
  18. package/dist/es2022/core/models/log.models.js.map +1 -0
  19. package/dist/es2022/core/models/migration.models.d.ts +136 -0
  20. package/dist/es2022/core/models/migration.models.js +2 -0
  21. package/dist/es2022/core/models/migration.models.js.map +1 -0
  22. package/dist/es2022/core/utils/array.utils.d.ts +5 -0
  23. package/dist/es2022/core/utils/array.utils.js +27 -0
  24. package/dist/es2022/core/utils/array.utils.js.map +1 -0
  25. package/dist/es2022/core/utils/binary-data.utils.d.ts +5 -0
  26. package/dist/es2022/core/utils/binary-data.utils.js +21 -0
  27. package/dist/es2022/core/utils/binary-data.utils.js.map +1 -0
  28. package/dist/es2022/core/utils/confirm.utils.d.ts +31 -0
  29. package/dist/es2022/core/utils/confirm.utils.js +73 -0
  30. package/dist/es2022/core/utils/confirm.utils.js.map +1 -0
  31. package/dist/es2022/core/utils/error.utils.d.ts +4 -0
  32. package/dist/es2022/core/utils/error.utils.js +50 -0
  33. package/dist/es2022/core/utils/error.utils.js.map +1 -0
  34. package/dist/es2022/core/utils/external-id.utils.d.ts +5 -0
  35. package/dist/es2022/core/utils/external-id.utils.js +5 -0
  36. package/dist/es2022/core/utils/external-id.utils.js.map +1 -0
  37. package/dist/es2022/core/utils/global.utils.d.ts +14 -0
  38. package/dist/es2022/core/utils/global.utils.js +45 -0
  39. package/dist/es2022/core/utils/global.utils.js.map +1 -0
  40. package/dist/es2022/core/utils/http.utils.d.ts +3 -0
  41. package/dist/es2022/core/utils/http.utils.js +29 -0
  42. package/dist/es2022/core/utils/http.utils.js.map +1 -0
  43. package/dist/es2022/core/utils/management-client-utils.d.ts +19 -0
  44. package/dist/es2022/core/utils/management-client-utils.js +129 -0
  45. package/dist/es2022/core/utils/management-client-utils.js.map +1 -0
  46. package/dist/es2022/core/utils/processing-utils.d.ts +12 -0
  47. package/dist/es2022/core/utils/processing-utils.js +39 -0
  48. package/dist/es2022/core/utils/processing-utils.js.map +1 -0
  49. package/dist/es2022/core/utils/run.utils.d.ts +10 -0
  50. package/dist/es2022/core/utils/run.utils.js +37 -0
  51. package/dist/es2022/core/utils/run.utils.js.map +1 -0
  52. package/dist/es2022/export/context/export-context-fetcher.d.ts +4 -0
  53. package/dist/es2022/export/context/export-context-fetcher.js +289 -0
  54. package/dist/es2022/export/context/export-context-fetcher.js.map +1 -0
  55. package/dist/es2022/export/export-manager.d.ts +5 -0
  56. package/dist/es2022/export/export-manager.js +167 -0
  57. package/dist/es2022/export/export-manager.js.map +1 -0
  58. package/dist/es2022/export/export.models.d.ts +55 -0
  59. package/dist/es2022/export/export.models.js +2 -0
  60. package/dist/es2022/export/export.models.js.map +1 -0
  61. package/dist/es2022/export/index.d.ts +2 -0
  62. package/dist/es2022/export/index.js +3 -0
  63. package/dist/es2022/export/index.js.map +1 -0
  64. package/dist/es2022/export/utils/export.utils.d.ts +2 -0
  65. package/dist/es2022/export/utils/export.utils.js +5 -0
  66. package/dist/es2022/export/utils/export.utils.js.map +1 -0
  67. package/dist/es2022/file/file-manager.d.ts +5 -0
  68. package/dist/es2022/file/file-manager.js +29 -0
  69. package/dist/es2022/file/file-manager.js.map +1 -0
  70. package/dist/es2022/file/index.d.ts +1 -0
  71. package/dist/es2022/file/index.js +2 -0
  72. package/dist/es2022/file/index.js.map +1 -0
  73. package/dist/es2022/import/comparers/asset-comparer.d.ts +12 -0
  74. package/dist/es2022/import/comparers/asset-comparer.js +65 -0
  75. package/dist/es2022/import/comparers/asset-comparer.js.map +1 -0
  76. package/dist/es2022/import/context/import-context-fetcher.d.ts +4 -0
  77. package/dist/es2022/import/context/import-context-fetcher.js +235 -0
  78. package/dist/es2022/import/context/import-context-fetcher.js.map +1 -0
  79. package/dist/es2022/import/import-manager.d.ts +4 -0
  80. package/dist/es2022/import/import-manager.js +80 -0
  81. package/dist/es2022/import/import-manager.js.map +1 -0
  82. package/dist/es2022/import/import.models.d.ts +45 -0
  83. package/dist/es2022/import/import.models.js +2 -0
  84. package/dist/es2022/import/import.models.js.map +1 -0
  85. package/dist/es2022/import/importers/assets-importer.d.ts +10 -0
  86. package/dist/es2022/import/importers/assets-importer.js +175 -0
  87. package/dist/es2022/import/importers/assets-importer.js.map +1 -0
  88. package/dist/es2022/import/importers/content-items-importer.d.ts +10 -0
  89. package/dist/es2022/import/importers/content-items-importer.js +97 -0
  90. package/dist/es2022/import/importers/content-items-importer.js.map +1 -0
  91. package/dist/es2022/import/importers/language-variant-importer.d.ts +11 -0
  92. package/dist/es2022/import/importers/language-variant-importer.js +215 -0
  93. package/dist/es2022/import/importers/language-variant-importer.js.map +1 -0
  94. package/dist/es2022/import/importers/workflow-importer.d.ts +18 -0
  95. package/dist/es2022/import/importers/workflow-importer.js +122 -0
  96. package/dist/es2022/import/importers/workflow-importer.js.map +1 -0
  97. package/dist/es2022/import/index.d.ts +2 -0
  98. package/dist/es2022/import/index.js +3 -0
  99. package/dist/es2022/import/index.js.map +1 -0
  100. package/dist/es2022/import/utils/import.utils.d.ts +2 -0
  101. package/dist/es2022/import/utils/import.utils.js +5 -0
  102. package/dist/es2022/import/utils/import.utils.js.map +1 -0
  103. package/dist/es2022/index.d.ts +8 -0
  104. package/dist/es2022/index.js +10 -0
  105. package/dist/es2022/index.js.map +1 -0
  106. package/dist/es2022/metadata.d.ts +5 -0
  107. package/dist/es2022/metadata.js +6 -0
  108. package/dist/es2022/metadata.js.map +1 -0
  109. package/dist/es2022/node/cli/actions/export-action.d.ts +2 -0
  110. package/dist/es2022/node/cli/actions/export-action.js +40 -0
  111. package/dist/es2022/node/cli/actions/export-action.js.map +1 -0
  112. package/dist/es2022/node/cli/actions/import-action.d.ts +2 -0
  113. package/dist/es2022/node/cli/actions/import-action.js +29 -0
  114. package/dist/es2022/node/cli/actions/import-action.js.map +1 -0
  115. package/dist/es2022/node/cli/actions/migrate-action.d.ts +2 -0
  116. package/dist/es2022/node/cli/actions/migrate-action.js +47 -0
  117. package/dist/es2022/node/cli/actions/migrate-action.js.map +1 -0
  118. package/dist/es2022/node/cli/app.d.ts +2 -0
  119. package/dist/es2022/node/cli/app.js +27 -0
  120. package/dist/es2022/node/cli/app.js.map +1 -0
  121. package/dist/es2022/node/cli/args/args-fetcher.d.ts +2 -0
  122. package/dist/es2022/node/cli/args/args-fetcher.js +46 -0
  123. package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -0
  124. package/dist/es2022/node/cli/args/args-setter.d.ts +2 -0
  125. package/dist/es2022/node/cli/args/args-setter.js +31 -0
  126. package/dist/es2022/node/cli/args/args-setter.js.map +1 -0
  127. package/dist/es2022/node/cli/cli.models.d.ts +24 -0
  128. package/dist/es2022/node/cli/cli.models.js +2 -0
  129. package/dist/es2022/node/cli/cli.models.js.map +1 -0
  130. package/dist/es2022/node/cli/commands.d.ts +1 -0
  131. package/dist/es2022/node/cli/commands.js +157 -0
  132. package/dist/es2022/node/cli/commands.js.map +1 -0
  133. package/dist/es2022/toolkit/elements-builder.d.ts +14 -0
  134. package/dist/es2022/toolkit/elements-builder.js +69 -0
  135. package/dist/es2022/toolkit/elements-builder.js.map +1 -0
  136. package/dist/es2022/toolkit/export.d.ts +3 -0
  137. package/dist/es2022/toolkit/export.js +21 -0
  138. package/dist/es2022/toolkit/export.js.map +1 -0
  139. package/dist/es2022/toolkit/file.d.ts +12 -0
  140. package/dist/es2022/toolkit/file.js +50 -0
  141. package/dist/es2022/toolkit/file.js.map +1 -0
  142. package/dist/es2022/toolkit/import.d.ts +2 -0
  143. package/dist/es2022/toolkit/import.js +21 -0
  144. package/dist/es2022/toolkit/import.js.map +1 -0
  145. package/dist/es2022/toolkit/index.d.ts +5 -0
  146. package/dist/es2022/toolkit/index.js +6 -0
  147. package/dist/es2022/toolkit/index.js.map +1 -0
  148. package/dist/es2022/toolkit/migrate.d.ts +21 -0
  149. package/dist/es2022/toolkit/migrate.js +39 -0
  150. package/dist/es2022/toolkit/migrate.js.map +1 -0
  151. package/dist/es2022/translation/extraction/items-extraction.processor.d.ts +24 -0
  152. package/dist/es2022/translation/extraction/items-extraction.processor.js +108 -0
  153. package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -0
  154. package/dist/es2022/translation/helpers/rich-text.processor.d.ts +22 -0
  155. package/dist/es2022/translation/helpers/rich-text.processor.js +209 -0
  156. package/dist/es2022/translation/helpers/rich-text.processor.js.map +1 -0
  157. package/dist/es2022/translation/index.d.ts +4 -0
  158. package/dist/es2022/translation/index.js +5 -0
  159. package/dist/es2022/translation/index.js.map +1 -0
  160. package/dist/es2022/translation/transforms/export-transforms.d.ts +3 -0
  161. package/dist/es2022/translation/transforms/export-transforms.js +196 -0
  162. package/dist/es2022/translation/transforms/export-transforms.js.map +1 -0
  163. package/dist/es2022/translation/transforms/import-transforms.d.ts +7 -0
  164. package/dist/es2022/translation/transforms/import-transforms.js +183 -0
  165. package/dist/es2022/translation/transforms/import-transforms.js.map +1 -0
  166. package/dist/es2022/zip/index.d.ts +4 -0
  167. package/dist/es2022/zip/index.js +5 -0
  168. package/dist/es2022/zip/index.js.map +1 -0
  169. package/dist/es2022/zip/zip-manager.d.ts +6 -0
  170. package/dist/es2022/zip/zip-manager.js +27 -0
  171. package/dist/es2022/zip/zip-manager.js.map +1 -0
  172. package/dist/es2022/zip/zip-packager.d.ts +3 -0
  173. package/dist/es2022/zip/zip-packager.js +69 -0
  174. package/dist/es2022/zip/zip-packager.js.map +1 -0
  175. package/dist/es2022/zip/zip-transformer.d.ts +6 -0
  176. package/dist/es2022/zip/zip-transformer.js +82 -0
  177. package/dist/es2022/zip/zip-transformer.js.map +1 -0
  178. package/dist/es2022/zip/zip.models.d.ts +13 -0
  179. package/dist/es2022/zip/zip.models.js +2 -0
  180. package/dist/es2022/zip/zip.models.js.map +1 -0
  181. package/lib/core/helpers/workflow-helper.ts +104 -0
  182. package/lib/core/index.ts +17 -0
  183. package/lib/core/logs/loggers.ts +80 -0
  184. package/lib/core/models/core.models.ts +134 -0
  185. package/lib/core/models/log.models.ts +31 -0
  186. package/lib/core/models/migration.models.ts +165 -0
  187. package/lib/core/utils/array.utils.ts +49 -0
  188. package/lib/core/utils/binary-data.utils.ts +29 -0
  189. package/lib/core/utils/confirm.utils.ts +139 -0
  190. package/lib/core/utils/error.utils.ts +65 -0
  191. package/lib/core/utils/external-id.utils.ts +9 -0
  192. package/lib/core/utils/global.utils.ts +59 -0
  193. package/lib/core/utils/http.utils.ts +35 -0
  194. package/lib/core/utils/management-client-utils.ts +182 -0
  195. package/lib/core/utils/processing-utils.ts +71 -0
  196. package/lib/core/utils/run.utils.ts +51 -0
  197. package/lib/export/context/export-context-fetcher.ts +475 -0
  198. package/lib/export/export-manager.ts +249 -0
  199. package/lib/export/export.models.ts +87 -0
  200. package/lib/export/index.ts +2 -0
  201. package/lib/export/utils/export.utils.ts +10 -0
  202. package/lib/file/file-manager.ts +37 -0
  203. package/lib/file/index.ts +1 -0
  204. package/lib/import/comparers/asset-comparer.ts +113 -0
  205. package/lib/import/context/import-context-fetcher.ts +367 -0
  206. package/lib/import/import-manager.ts +103 -0
  207. package/lib/import/import.models.ts +84 -0
  208. package/lib/import/importers/assets-importer.ts +239 -0
  209. package/lib/import/importers/content-items-importer.ts +142 -0
  210. package/lib/import/importers/language-variant-importer.ts +342 -0
  211. package/lib/import/importers/workflow-importer.ts +159 -0
  212. package/lib/import/index.ts +2 -0
  213. package/lib/import/utils/import.utils.ts +10 -0
  214. package/lib/index.ts +9 -0
  215. package/lib/metadata.ts +6 -0
  216. package/lib/node/cli/actions/export-action.ts +45 -0
  217. package/lib/node/cli/actions/import-action.ts +34 -0
  218. package/lib/node/cli/actions/migrate-action.ts +52 -0
  219. package/lib/node/cli/app.ts +29 -0
  220. package/lib/node/cli/args/args-fetcher.ts +61 -0
  221. package/lib/node/cli/args/args-setter.ts +35 -0
  222. package/lib/node/cli/cli.models.ts +28 -0
  223. package/lib/node/cli/commands.ts +161 -0
  224. package/lib/toolkit/elements-builder.ts +84 -0
  225. package/lib/toolkit/export.ts +21 -0
  226. package/lib/toolkit/file.ts +70 -0
  227. package/lib/toolkit/import.ts +21 -0
  228. package/lib/toolkit/index.ts +5 -0
  229. package/lib/toolkit/migrate.ts +71 -0
  230. package/lib/translation/extraction/items-extraction.processor.ts +181 -0
  231. package/lib/translation/helpers/rich-text.processor.ts +300 -0
  232. package/lib/translation/index.ts +4 -0
  233. package/lib/translation/transforms/export-transforms.ts +253 -0
  234. package/lib/translation/transforms/import-transforms.ts +215 -0
  235. package/lib/zip/index.ts +4 -0
  236. package/lib/zip/zip-manager.ts +33 -0
  237. package/lib/zip/zip-packager.ts +86 -0
  238. package/lib/zip/zip-transformer.ts +105 -0
  239. package/lib/zip/zip.models.ts +12 -0
  240. 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
+ }