@kontent-ai/migration-toolkit 2.9.1 → 3.0.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 (235) hide show
  1. package/README.md +19 -17
  2. package/dist/core/config.js +3 -3
  3. package/dist/core/config.js.map +1 -1
  4. package/dist/core/helpers/workflow-helper.d.ts +1 -1
  5. package/dist/core/helpers/workflow-helper.js +28 -26
  6. package/dist/core/helpers/workflow-helper.js.map +1 -1
  7. package/dist/core/logs/loggers.d.ts +1 -1
  8. package/dist/core/logs/loggers.js +15 -15
  9. package/dist/core/logs/loggers.js.map +1 -1
  10. package/dist/core/models/core.models.d.ts +27 -22
  11. package/dist/core/models/error.models.d.ts +14 -0
  12. package/dist/core/models/error.models.js +25 -0
  13. package/dist/core/models/error.models.js.map +1 -0
  14. package/dist/core/models/log.models.d.ts +2 -2
  15. package/dist/core/models/migration.models.d.ts +14 -14
  16. package/dist/core/models/migration.schema.d.ts +9 -9
  17. package/dist/core/models/migration.schema.js +28 -28
  18. package/dist/core/models/migration.schema.js.map +1 -1
  19. package/dist/core/utils/array.utils.d.ts +1 -1
  20. package/dist/core/utils/array.utils.js +4 -3
  21. package/dist/core/utils/array.utils.js.map +1 -1
  22. package/dist/core/utils/binary-data.utils.d.ts +1 -1
  23. package/dist/core/utils/binary-data.utils.js +6 -6
  24. package/dist/core/utils/binary-data.utils.js.map +1 -1
  25. package/dist/core/utils/confirm.utils.d.ts +1 -1
  26. package/dist/core/utils/confirm.utils.js +21 -20
  27. package/dist/core/utils/confirm.utils.js.map +1 -1
  28. package/dist/core/utils/error.utils.d.ts +1 -1
  29. package/dist/core/utils/error.utils.js +16 -14
  30. package/dist/core/utils/error.utils.js.map +1 -1
  31. package/dist/core/utils/external-id.utils.js +1 -1
  32. package/dist/core/utils/external-id.utils.js.map +1 -1
  33. package/dist/core/utils/global.utils.d.ts +3 -3
  34. package/dist/core/utils/global.utils.js +20 -18
  35. package/dist/core/utils/global.utils.js.map +1 -1
  36. package/dist/core/utils/http.utils.d.ts +2 -2
  37. package/dist/core/utils/http.utils.js +4 -4
  38. package/dist/core/utils/http.utils.js.map +1 -1
  39. package/dist/core/utils/management-client-utils.d.ts +4 -4
  40. package/dist/core/utils/management-client-utils.js +34 -34
  41. package/dist/core/utils/management-client-utils.js.map +1 -1
  42. package/dist/core/utils/processing-utils.d.ts +4 -4
  43. package/dist/core/utils/processing-utils.js +13 -13
  44. package/dist/core/utils/processing-utils.js.map +1 -1
  45. package/dist/core/utils/run.utils.d.ts +2 -2
  46. package/dist/core/utils/run.utils.js +7 -7
  47. package/dist/core/utils/run.utils.js.map +1 -1
  48. package/dist/export/context/export-context-fetcher.d.ts +1 -1
  49. package/dist/export/context/export-context-fetcher.js +92 -62
  50. package/dist/export/context/export-context-fetcher.js.map +1 -1
  51. package/dist/export/export-manager.d.ts +2 -2
  52. package/dist/export/export-manager.js +46 -37
  53. package/dist/export/export-manager.js.map +1 -1
  54. package/dist/export/export.models.d.ts +21 -2
  55. package/dist/export/utils/export.utils.d.ts +1 -1
  56. package/dist/export/utils/export.utils.js +3 -2
  57. package/dist/export/utils/export.utils.js.map +1 -1
  58. package/dist/file/file-manager.d.ts +2 -2
  59. package/dist/file/file-manager.js +7 -7
  60. package/dist/file/file-manager.js.map +1 -1
  61. package/dist/import/comparers/asset-comparer.d.ts +2 -2
  62. package/dist/import/comparers/asset-comparer.js +12 -11
  63. package/dist/import/comparers/asset-comparer.js.map +1 -1
  64. package/dist/import/context/import-context-fetcher.d.ts +1 -1
  65. package/dist/import/context/import-context-fetcher.js +77 -73
  66. package/dist/import/context/import-context-fetcher.js.map +1 -1
  67. package/dist/import/import-manager.d.ts +1 -1
  68. package/dist/import/import-manager.js +59 -56
  69. package/dist/import/import-manager.js.map +1 -1
  70. package/dist/import/import.models.d.ts +6 -2
  71. package/dist/import/importers/assets-importer.d.ts +3 -3
  72. package/dist/import/importers/assets-importer.js +46 -43
  73. package/dist/import/importers/assets-importer.js.map +1 -1
  74. package/dist/import/importers/content-items-importer.d.ts +3 -3
  75. package/dist/import/importers/content-items-importer.js +28 -25
  76. package/dist/import/importers/content-items-importer.js.map +1 -1
  77. package/dist/import/importers/language-variant-importer.d.ts +3 -3
  78. package/dist/import/importers/language-variant-importer.js +45 -45
  79. package/dist/import/importers/language-variant-importer.js.map +1 -1
  80. package/dist/import/importers/workflow-importer.d.ts +3 -2
  81. package/dist/import/importers/workflow-importer.js +58 -54
  82. package/dist/import/importers/workflow-importer.js.map +1 -1
  83. package/dist/import/utils/import.utils.d.ts +1 -1
  84. package/dist/import/utils/import.utils.js +3 -2
  85. package/dist/import/utils/import.utils.js.map +1 -1
  86. package/dist/index.d.ts +11 -7
  87. package/dist/index.js +10 -8
  88. package/dist/index.js.map +1 -1
  89. package/dist/metadata.js +3 -3
  90. package/dist/metadata.js.map +1 -1
  91. package/dist/node/cli/actions/export-action.d.ts +1 -1
  92. package/dist/node/cli/actions/export-action.js +28 -23
  93. package/dist/node/cli/actions/export-action.js.map +1 -1
  94. package/dist/node/cli/actions/import-action.d.ts +1 -1
  95. package/dist/node/cli/actions/import-action.js +15 -12
  96. package/dist/node/cli/actions/import-action.js.map +1 -1
  97. package/dist/node/cli/actions/migrate-action.d.ts +1 -1
  98. package/dist/node/cli/actions/migrate-action.js +25 -22
  99. package/dist/node/cli/actions/migrate-action.js.map +1 -1
  100. package/dist/node/cli/app.js +13 -12
  101. package/dist/node/cli/app.js.map +1 -1
  102. package/dist/node/cli/args/args-fetcher.d.ts +1 -1
  103. package/dist/node/cli/args/args-fetcher.js +14 -13
  104. package/dist/node/cli/args/args-fetcher.js.map +1 -1
  105. package/dist/node/cli/args/args-setter.d.ts +1 -1
  106. package/dist/node/cli/args/args-setter.js +8 -6
  107. package/dist/node/cli/args/args-setter.js.map +1 -1
  108. package/dist/node/cli/cli.models.d.ts +2 -2
  109. package/dist/node/cli/commands.js +68 -56
  110. package/dist/node/cli/commands.js.map +1 -1
  111. package/dist/toolkit/elements-builder.d.ts +1 -1
  112. package/dist/toolkit/elements-builder.js +12 -12
  113. package/dist/toolkit/elements-builder.js.map +1 -1
  114. package/dist/toolkit/export.d.ts +2 -2
  115. package/dist/toolkit/export.js +8 -8
  116. package/dist/toolkit/export.js.map +1 -1
  117. package/dist/toolkit/file.d.ts +2 -1
  118. package/dist/toolkit/file.js +18 -16
  119. package/dist/toolkit/file.js.map +1 -1
  120. package/dist/toolkit/import.d.ts +1 -1
  121. package/dist/toolkit/import.js +12 -12
  122. package/dist/toolkit/import.js.map +1 -1
  123. package/dist/toolkit/migrate.d.ts +13 -4
  124. package/dist/toolkit/migrate.js +15 -13
  125. package/dist/toolkit/migrate.js.map +1 -1
  126. package/dist/translation/extraction/items-extraction.processor.d.ts +5 -4
  127. package/dist/translation/extraction/items-extraction.processor.js +73 -35
  128. package/dist/translation/extraction/items-extraction.processor.js.map +1 -1
  129. package/dist/translation/helpers/export-placeholder.utils.d.ts +11 -0
  130. package/dist/translation/helpers/export-placeholder.utils.js +11 -0
  131. package/dist/translation/helpers/export-placeholder.utils.js.map +1 -0
  132. package/dist/translation/helpers/rich-text.processor.d.ts +6 -6
  133. package/dist/translation/helpers/rich-text.processor.js +38 -38
  134. package/dist/translation/helpers/rich-text.processor.js.map +1 -1
  135. package/dist/translation/transforms/export-transforms.d.ts +2 -2
  136. package/dist/translation/transforms/export-transforms.js +93 -67
  137. package/dist/translation/transforms/export-transforms.js.map +1 -1
  138. package/dist/translation/transforms/import-transforms.d.ts +2 -2
  139. package/dist/translation/transforms/import-transforms.js +38 -40
  140. package/dist/translation/transforms/import-transforms.js.map +1 -1
  141. package/dist/zip/zip-manager.d.ts +4 -3
  142. package/dist/zip/zip-manager.js +9 -9
  143. package/dist/zip/zip-manager.js.map +1 -1
  144. package/dist/zip/zip-packager.d.ts +2 -2
  145. package/dist/zip/zip-packager.js +19 -17
  146. package/dist/zip/zip-packager.js.map +1 -1
  147. package/dist/zip/zip-transformer.d.ts +3 -2
  148. package/dist/zip/zip-transformer.js +16 -15
  149. package/dist/zip/zip-transformer.js.map +1 -1
  150. package/dist/zip/zip.models.d.ts +2 -2
  151. package/lib/core/config.ts +6 -6
  152. package/lib/core/helpers/workflow-helper.ts +190 -185
  153. package/lib/core/logs/loggers.ts +52 -52
  154. package/lib/core/models/core.models.ts +128 -119
  155. package/lib/core/models/error.models.ts +41 -0
  156. package/lib/core/models/log.models.ts +20 -20
  157. package/lib/core/models/migration.models.ts +54 -54
  158. package/lib/core/models/migration.schema.ts +108 -108
  159. package/lib/core/utils/array.utils.ts +43 -42
  160. package/lib/core/utils/binary-data.utils.ts +16 -16
  161. package/lib/core/utils/confirm.utils.ts +106 -105
  162. package/lib/core/utils/error.utils.ts +69 -72
  163. package/lib/core/utils/external-id.utils.ts +4 -4
  164. package/lib/core/utils/global.utils.ts +81 -75
  165. package/lib/core/utils/http.utils.ts +23 -23
  166. package/lib/core/utils/management-client-utils.ts +186 -186
  167. package/lib/core/utils/processing-utils.ts +82 -82
  168. package/lib/core/utils/run.utils.ts +50 -50
  169. package/lib/export/context/export-context-fetcher.ts +472 -447
  170. package/lib/export/export-manager.ts +233 -232
  171. package/lib/export/export.models.ts +71 -56
  172. package/lib/export/utils/export.utils.ts +9 -7
  173. package/lib/file/file-manager.ts +28 -28
  174. package/lib/import/comparers/asset-comparer.ts +107 -106
  175. package/lib/import/context/import-context-fetcher.ts +462 -462
  176. package/lib/import/import-manager.ts +243 -240
  177. package/lib/import/import.models.ts +69 -67
  178. package/lib/import/importers/assets-importer.ts +240 -236
  179. package/lib/import/importers/content-items-importer.ts +126 -122
  180. package/lib/import/importers/language-variant-importer.ts +324 -328
  181. package/lib/import/importers/workflow-importer.ts +372 -367
  182. package/lib/import/utils/import.utils.ts +9 -7
  183. package/lib/index.ts +12 -8
  184. package/lib/metadata.ts +3 -4
  185. package/lib/node/cli/actions/export-action.ts +43 -38
  186. package/lib/node/cli/actions/import-action.ts +32 -29
  187. package/lib/node/cli/actions/migrate-action.ts +49 -46
  188. package/lib/node/cli/app.ts +21 -21
  189. package/lib/node/cli/args/args-fetcher.ts +55 -54
  190. package/lib/node/cli/args/args-setter.ts +34 -32
  191. package/lib/node/cli/cli.models.ts +17 -17
  192. package/lib/node/cli/commands.ts +165 -153
  193. package/lib/toolkit/elements-builder.ts +69 -69
  194. package/lib/toolkit/export.ts +21 -21
  195. package/lib/toolkit/file.ts +59 -53
  196. package/lib/toolkit/import.ts +32 -32
  197. package/lib/toolkit/migrate.ts +60 -49
  198. package/lib/translation/extraction/items-extraction.processor.ts +203 -173
  199. package/lib/translation/helpers/export-placeholder.utils.ts +10 -0
  200. package/lib/translation/helpers/rich-text.processor.ts +311 -311
  201. package/lib/translation/transforms/export-transforms.ts +313 -279
  202. package/lib/translation/transforms/import-transforms.ts +188 -191
  203. package/lib/zip/zip-manager.ts +28 -27
  204. package/lib/zip/zip-packager.ts +75 -73
  205. package/lib/zip/zip-transformer.ts +112 -107
  206. package/lib/zip/zip.models.ts +7 -7
  207. package/package.json +91 -84
  208. package/dist/core/index.d.ts +0 -16
  209. package/dist/core/index.js +0 -17
  210. package/dist/core/index.js.map +0 -1
  211. package/dist/export/index.d.ts +0 -2
  212. package/dist/export/index.js +0 -3
  213. package/dist/export/index.js.map +0 -1
  214. package/dist/file/index.d.ts +0 -1
  215. package/dist/file/index.js +0 -2
  216. package/dist/file/index.js.map +0 -1
  217. package/dist/import/index.d.ts +0 -2
  218. package/dist/import/index.js +0 -3
  219. package/dist/import/index.js.map +0 -1
  220. package/dist/toolkit/index.d.ts +0 -5
  221. package/dist/toolkit/index.js +0 -6
  222. package/dist/toolkit/index.js.map +0 -1
  223. package/dist/translation/index.d.ts +0 -4
  224. package/dist/translation/index.js +0 -5
  225. package/dist/translation/index.js.map +0 -1
  226. package/dist/zip/index.d.ts +0 -4
  227. package/dist/zip/index.js +0 -5
  228. package/dist/zip/index.js.map +0 -1
  229. package/lib/core/index.ts +0 -18
  230. package/lib/export/index.ts +0 -2
  231. package/lib/file/index.ts +0 -1
  232. package/lib/import/index.ts +0 -2
  233. package/lib/toolkit/index.ts +0 -5
  234. package/lib/translation/index.ts +0 -4
  235. package/lib/zip/index.ts +0 -4
@@ -1,333 +1,329 @@
1
- import type { LanguageVariantElements, LanguageVariantModels, ManagementClient, WorkflowModels } from '@kontent-ai/management-sdk';
2
- import chalk from 'chalk';
3
- import { match } from 'ts-pattern';
1
+ import type { LanguageVariantElements, LanguageVariantModels, ManagementClient, WorkflowModels } from "@kontent-ai/management-sdk";
2
+ import chalk from "chalk";
3
+ import { match } from "ts-pattern";
4
+ import { workflowHelper } from "../../core/helpers/workflow-helper.js";
4
5
  import type {
5
- LanguageVariantSchedulesStateValues,
6
- LanguageVariantStateInTargetEnvironmentByCodename,
7
- Logger,
8
- LogSpinnerData,
9
- MigrationElement,
10
- MigrationItem,
11
- MigrationItemVersion
12
- } from '../../core/index.js';
13
- import { findRequired, isNotUndefined, processItemsAsync, runMapiRequestAsync, workflowHelper } from '../../core/index.js';
14
- import { importTransforms } from '../../translation/index.js';
15
- import type { ImportContext, ImportedItem, ImportedLanguageVariant } from '../import.models.js';
16
- import { throwErrorForMigrationItem } from '../utils/import.utils.js';
17
- import { workflowImporter as workflowImporterInit } from './workflow-importer.js';
6
+ LanguageVariantSchedulesStateValues,
7
+ LanguageVariantStateInTargetEnvironmentByCodename,
8
+ } from "../../core/models/core.models.js";
9
+ import type { Logger, LogSpinnerData } from "../../core/models/log.models.js";
10
+ import type { MigrationElement, MigrationItem, MigrationItemVersion } from "../../core/models/migration.models.js";
11
+ import { findRequired } from "../../core/utils/array.utils.js";
12
+ import { isNotUndefined } from "../../core/utils/global.utils.js";
13
+ import { processItemsAsync } from "../../core/utils/processing-utils.js";
14
+ import { runMapiRequestAsync } from "../../core/utils/run.utils.js";
15
+ import { importTransforms } from "../../translation/transforms/import-transforms.js";
16
+ import type { ImportContext, ImportedItem, ImportedLanguageVariant } from "../import.models.js";
17
+ import { throwErrorForMigrationItem } from "../utils/import.utils.js";
18
+ import { workflowImporter as workflowImporterInit } from "./workflow-importer.js";
18
19
 
19
20
  export function languageVariantImporter(config: {
20
- readonly logger: Logger;
21
- readonly preparedContentItems: readonly ImportedItem[];
22
- readonly importContext: ImportContext;
23
- readonly client: Readonly<ManagementClient>;
21
+ readonly logger: Logger;
22
+ readonly preparedContentItems: readonly ImportedItem[];
23
+ readonly importContext: ImportContext;
24
+ readonly client: Readonly<ManagementClient>;
24
25
  }) {
25
- const workflowImporter = workflowImporterInit({
26
- logger: config.logger,
27
- managementClient: config.client,
28
- workflows: config.importContext.environmentData.workflows
29
- });
30
-
31
- const upsertLanguageVariantAsync = async (data: {
32
- readonly workflow: Readonly<WorkflowModels.Workflow>;
33
- readonly logSpinner: LogSpinnerData;
34
- readonly migrationItem: MigrationItem;
35
- readonly migrationItemVersion: MigrationItemVersion;
36
- readonly preparedContentItem: ImportedItem;
37
- }): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
38
- return await runMapiRequestAsync({
39
- logger: config.logger,
40
- func: async () => {
41
- return (
42
- await config.client
43
- .upsertLanguageVariant()
44
- .byItemCodename(data.preparedContentItem.inputItem.system.codename)
45
- .byLanguageCodename(data.migrationItem.system.language.codename)
46
- .withData(() => {
47
- return {
48
- elements: Object.entries(data.migrationItemVersion.elements).map(([codename, migrationElement]) => {
49
- return getElementContract(data.migrationItem, migrationElement, codename);
50
- }),
51
- workflow: {
52
- workflow_identifier: {
53
- codename: data.workflow.codename
54
- },
55
- step_identifier: {
56
- codename: data.workflow.steps[0].codename // use always first step
57
- }
58
- }
59
- };
60
- })
61
- .toPromise()
62
- ).data;
63
- },
64
- action: 'upsert',
65
- type: 'languageVariant',
66
- logSpinner: data.logSpinner,
67
- itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename})`
68
- });
69
- };
70
-
71
- const categorizeVersions = (
72
- migrationItem: MigrationItem
73
- ): { publishedVersion: MigrationItemVersion | undefined; draftVersion: MigrationItemVersion | undefined } => {
74
- const workflow = workflowHelper(config.importContext.environmentData.workflows).getWorkflowByCodename(
75
- migrationItem.system.workflow.codename
76
- );
77
-
78
- const publishedVersions = migrationItem.versions.filter((version) =>
79
- isPublishedWorkflowStep(version.workflow_step.codename, workflow)
80
- );
81
- const draftVersions = migrationItem.versions.filter(
82
- (version) => !isPublishedWorkflowStep(version.workflow_step.codename, workflow)
83
- );
84
-
85
- if (publishedVersions.length > 1) {
86
- throwErrorForMigrationItem(
87
- migrationItem,
88
- `There can be only 1 published version. There are '${publishedVersions.length}' published versions for the item.`
89
- );
90
- }
91
-
92
- if (draftVersions.length > 1) {
93
- throwErrorForMigrationItem(
94
- migrationItem,
95
- `There can be only 1 draft version. There are '${draftVersions.length}' draft versions for the item.`
96
- );
97
- }
98
-
99
- return {
100
- draftVersion: draftVersions?.[0],
101
- publishedVersion: publishedVersions?.[0]
102
- };
103
- };
104
-
105
- const importVersionAsync = async (data: {
106
- readonly logSpinner: LogSpinnerData;
107
- readonly migrationItem: MigrationItem;
108
- readonly migrationItemVersion: MigrationItemVersion;
109
- readonly preparedContentItem: ImportedItem;
110
- readonly createNewVersion?: boolean;
111
- }): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
112
- // validate workflow
113
- const { step, workflow } = workflowHelper(config.importContext.environmentData.workflows).getWorkflowAndStepByCodenames({
114
- workflowCodename: data.migrationItem.system.workflow.codename,
115
- stepCodename: data.migrationItemVersion.workflow_step.codename
116
- });
117
-
118
- // create new version if necessary. This is needed when both draft & published version are imported
119
- if (data.createNewVersion) {
120
- await workflowImporter.createNewVersionOfLanguageVariantAsync({
121
- logSpinner: data.logSpinner,
122
- migrationItem: data.migrationItem
123
- });
124
- }
125
- // upsert language variant
126
- const languageVariant = await upsertLanguageVariantAsync({
127
- logSpinner: data.logSpinner,
128
- migrationItem: data.migrationItem,
129
- preparedContentItem: data.preparedContentItem,
130
- migrationItemVersion: data.migrationItemVersion,
131
- workflow
132
- });
133
-
134
- // set workflow accordingly (publish, move to workflow step, archive ...)
135
- await workflowImporter.setWorkflowOfLanguageVariantAsync({
136
- logSpinner: data.logSpinner,
137
- migrationItem: data.migrationItem,
138
- workflowCodename: workflow.codename,
139
- stepCodename: step.codename,
140
- migrationItemVersion: data.migrationItemVersion,
141
- languageVariant: languageVariant
142
- });
143
-
144
- // set scheduling
145
- await workflowImporter.setScheduledStateOfLanguageVariantAsync({
146
- logSpinner: data.logSpinner,
147
- migrationItem: data.migrationItem,
148
- migrationItemVersion: data.migrationItemVersion
149
- });
150
-
151
- return languageVariant;
152
- };
153
-
154
- const importLanguageVariantAsync = async (
155
- logSpinner: LogSpinnerData,
156
- migrationItem: MigrationItem,
157
- preparedContentItem: ImportedItem
158
- ): Promise<readonly LanguageVariantModels.ContentItemLanguageVariant[]> => {
159
- const { draftVersion, publishedVersion } = categorizeVersions(migrationItem);
160
-
161
- // get initial state of language variant from target env
162
- const targetVariantState = config.importContext.getLanguageVariantStateInTargetEnvironment(
163
- migrationItem.system.codename,
164
- migrationItem.system.language.codename
165
- );
166
-
167
- // prepare language variant for import (unpublish, create new version, un-schedule ...)
168
- await prepareTargetEnvironmentVariantForImportAsync({
169
- logSpinner,
170
- migrationItem,
171
- targetVariantState
172
- });
173
-
174
- // first import published version if it exists
175
- const publishedLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = publishedVersion
176
- ? await importVersionAsync({
177
- logSpinner: logSpinner,
178
- migrationItem: migrationItem,
179
- preparedContentItem: preparedContentItem,
180
- migrationItemVersion: publishedVersion
181
- })
182
- : undefined;
183
-
184
- // if target env contains published version & imported version not, unpublish it from the target env
185
- if (targetVariantState.publishedLanguageVariant && !publishedVersion) {
186
- await workflowImporter.unpublishLanguageVariantAsync({
187
- logSpinner,
188
- migrationItem
189
- });
190
- await workflowImporter.moveToDraftStepAsync({
191
- logSpinner,
192
- migrationItem
193
- });
194
- }
195
- const draftLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = draftVersion
196
- ? await importVersionAsync({
197
- logSpinner: logSpinner,
198
- migrationItem: migrationItem,
199
- preparedContentItem: preparedContentItem,
200
- migrationItemVersion: draftVersion,
201
- createNewVersion: publishedLanguageVariant ? true : false
202
- })
203
- : undefined;
204
-
205
- return [publishedLanguageVariant, draftLanguageVariant].filter(isNotUndefined);
206
- };
207
-
208
- const cancelScheduledStateAsync = async (data: {
209
- readonly logSpinner: LogSpinnerData;
210
- readonly migrationItem: MigrationItem;
211
- readonly scheduledState: LanguageVariantSchedulesStateValues;
212
- }): Promise<void> => {
213
- const changeWorkflowData = {
214
- logSpinner: data.logSpinner,
215
- migrationItem: data.migrationItem
216
- };
217
-
218
- await match(data.scheduledState)
219
- .with('scheduledPublish', async () => {
220
- // cancel scheduled publish if language variant is scheduled to be published
221
- await workflowImporter.cancelScheduledPublishAsync(changeWorkflowData);
222
- })
223
- .with('scheduledUnpublish', async () => {
224
- // cancel scheduled unpublish if language variant is scheduled to be unpublished
225
- await workflowImporter.cancelScheduledUnpublishAsync(changeWorkflowData);
226
- })
227
- .otherwise(() => { });
228
- };
229
-
230
- const prepareTargetEnvironmentVariantForImportAsync = async (data: {
231
- readonly logSpinner: LogSpinnerData;
232
- readonly migrationItem: MigrationItem;
233
- readonly targetVariantState: LanguageVariantStateInTargetEnvironmentByCodename;
234
- }): Promise<void> => {
235
- if (!data.targetVariantState) {
236
- // no need to prepare language variant as it doesn't exist in target environment
237
- return;
238
- }
239
-
240
- // when language variant exists in target env, we need to prepare it for import by unscheduling, moving to draft etc...
241
- // we use draft language variant if it exists, otherwise we use published language variant
242
- const languageVariantToPrepare = data.targetVariantState.draftLanguageVariant ?? data.targetVariantState.publishedLanguageVariant;
243
-
244
- if (!languageVariantToPrepare) {
245
- return;
246
- }
247
-
248
- // there is likely a bug which causes /published endpoint to return invalid scheduled state
249
- // use conditions below to determine scheduled state to use - this will be fixed in future
250
- if (languageVariantToPrepare.workflowState?.scheduledState) {
251
- await cancelScheduledStateAsync({
252
- logSpinner: data.logSpinner,
253
- migrationItem: data.migrationItem,
254
- scheduledState: languageVariantToPrepare.workflowState.scheduledState
255
- });
256
- }
257
-
258
- const changeWorkflowData = {
259
- logSpinner: data.logSpinner,
260
- migrationItem: data.migrationItem
261
- };
262
-
263
- await match(languageVariantToPrepare.workflowState?.workflowState)
264
- .with('published', async () => {
265
- // create new version if language variant is published
266
- await workflowImporter.createNewVersionOfLanguageVariantAsync(changeWorkflowData);
267
- })
268
- .with('archived', async () => {
269
- // move to draft step if language variant is archived
270
- await workflowImporter.moveToDraftStepAsync(changeWorkflowData);
271
- })
272
- .otherwise(() => { });
273
- };
274
-
275
- const isPublishedWorkflowStep = (stepCodename: string, workflow: Readonly<WorkflowModels.Workflow>): boolean => {
276
- return workflow.publishedStep.codename === stepCodename;
277
- };
278
-
279
- const getElementContract = (
280
- migrationItem: MigrationItem,
281
- element: MigrationElement,
282
- elementCodename: string
283
- ): Readonly<LanguageVariantElements.ILanguageVariantElementBase> => {
284
- const importTransformResult = importTransforms[
285
- config.importContext.getElement(migrationItem.system.type.codename, elementCodename, element.type).type
286
- ]({
287
- elementCodename: elementCodename,
288
- importContext: config.importContext,
289
- migrationItems: config.importContext.categorizedImportData.contentItems,
290
- elementData: element
291
- });
292
-
293
- return importTransformResult;
294
- };
295
-
296
- const importAsync = async (): Promise<readonly ImportedLanguageVariant[]> => {
297
- config.logger.log({
298
- type: 'info',
299
- message: `Importing '${chalk.yellow(
300
- config.importContext.categorizedImportData.contentItems.length.toString()
301
- )}' language variants`
302
- });
303
-
304
- return await processItemsAsync<MigrationItem, readonly Readonly<LanguageVariantModels.ContentItemLanguageVariant>[]>({
305
- action: 'Importing language variants',
306
- logger: config.logger,
307
- parallelLimit: 1,
308
- items: config.importContext.categorizedImportData.contentItems,
309
- itemInfo: (input) => {
310
- return {
311
- itemType: 'languageVariant',
312
- title: input.system.name,
313
- partA: input.system.language.codename
314
- };
315
- },
316
- processAsync: async (migrationItem, logSpinner) => {
317
- const contentItem = findRequired(
318
- config.preparedContentItems,
319
- (item) => item.inputItem.system.codename === migrationItem.system.codename,
320
- `Missing content item with codename '${chalk.red(
321
- migrationItem.system.codename
322
- )}'. Content item should have been prepepared.`
323
- );
324
-
325
- return await importLanguageVariantAsync(logSpinner, migrationItem, contentItem);
326
- }
327
- });
328
- };
329
-
330
- return {
331
- importAsync
332
- };
26
+ const workflowImporter = workflowImporterInit({
27
+ logger: config.logger,
28
+ managementClient: config.client,
29
+ workflows: config.importContext.environmentData.workflows,
30
+ });
31
+
32
+ const upsertLanguageVariantAsync = async (data: {
33
+ readonly workflow: Readonly<WorkflowModels.Workflow>;
34
+ readonly logSpinner: LogSpinnerData;
35
+ readonly migrationItem: MigrationItem;
36
+ readonly migrationItemVersion: MigrationItemVersion;
37
+ readonly preparedContentItem: ImportedItem;
38
+ }): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
39
+ return await runMapiRequestAsync({
40
+ logger: config.logger,
41
+ func: async () => {
42
+ return (
43
+ await config.client
44
+ .upsertLanguageVariant()
45
+ .byItemCodename(data.preparedContentItem.inputItem.system.codename)
46
+ .byLanguageCodename(data.migrationItem.system.language.codename)
47
+ .withData(() => {
48
+ return {
49
+ elements: Object.entries(data.migrationItemVersion.elements).map(([codename, migrationElement]) => {
50
+ return getElementContract(data.migrationItem, migrationElement, codename);
51
+ }),
52
+ workflow: {
53
+ workflow_identifier: {
54
+ codename: data.workflow.codename,
55
+ },
56
+ step_identifier: {
57
+ codename: data.workflow.steps[0].codename, // use always first step
58
+ },
59
+ },
60
+ };
61
+ })
62
+ .toPromise()
63
+ ).data;
64
+ },
65
+ action: "upsert",
66
+ type: "languageVariant",
67
+ logSpinner: data.logSpinner,
68
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename})`,
69
+ });
70
+ };
71
+
72
+ const categorizeVersions = (
73
+ migrationItem: MigrationItem,
74
+ ): { publishedVersion: MigrationItemVersion | undefined; draftVersion: MigrationItemVersion | undefined } => {
75
+ const workflow = workflowHelper(config.importContext.environmentData.workflows).getWorkflowByCodename(
76
+ migrationItem.system.workflow.codename,
77
+ );
78
+
79
+ const publishedVersions = migrationItem.versions.filter((version) =>
80
+ isPublishedWorkflowStep(version.workflow_step.codename, workflow),
81
+ );
82
+ const draftVersions = migrationItem.versions.filter(
83
+ (version) => !isPublishedWorkflowStep(version.workflow_step.codename, workflow),
84
+ );
85
+
86
+ if (publishedVersions.length > 1) {
87
+ throwErrorForMigrationItem(
88
+ migrationItem,
89
+ `There can be only 1 published version. There are '${publishedVersions.length}' published versions for the item.`,
90
+ );
91
+ }
92
+
93
+ if (draftVersions.length > 1) {
94
+ throwErrorForMigrationItem(
95
+ migrationItem,
96
+ `There can be only 1 draft version. There are '${draftVersions.length}' draft versions for the item.`,
97
+ );
98
+ }
99
+
100
+ return {
101
+ draftVersion: draftVersions[0],
102
+ publishedVersion: publishedVersions[0],
103
+ };
104
+ };
105
+
106
+ const importVersionAsync = async (data: {
107
+ readonly logSpinner: LogSpinnerData;
108
+ readonly migrationItem: MigrationItem;
109
+ readonly migrationItemVersion: MigrationItemVersion;
110
+ readonly preparedContentItem: ImportedItem;
111
+ readonly createNewVersion?: boolean;
112
+ }): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
113
+ // validate workflow
114
+ const { step, workflow } = workflowHelper(config.importContext.environmentData.workflows).getWorkflowAndStepByCodenames({
115
+ workflowCodename: data.migrationItem.system.workflow.codename,
116
+ stepCodename: data.migrationItemVersion.workflow_step.codename,
117
+ });
118
+
119
+ // create new version if necessary. This is needed when both draft & published version are imported
120
+ if (data.createNewVersion) {
121
+ await workflowImporter.createNewVersionOfLanguageVariantAsync({
122
+ logSpinner: data.logSpinner,
123
+ migrationItem: data.migrationItem,
124
+ });
125
+ }
126
+ // upsert language variant
127
+ const languageVariant = await upsertLanguageVariantAsync({
128
+ logSpinner: data.logSpinner,
129
+ migrationItem: data.migrationItem,
130
+ preparedContentItem: data.preparedContentItem,
131
+ migrationItemVersion: data.migrationItemVersion,
132
+ workflow,
133
+ });
134
+
135
+ // set workflow accordingly (publish, move to workflow step, archive ...)
136
+ await workflowImporter.setWorkflowOfLanguageVariantAsync({
137
+ logSpinner: data.logSpinner,
138
+ migrationItem: data.migrationItem,
139
+ workflowCodename: workflow.codename,
140
+ stepCodename: step.codename,
141
+ migrationItemVersion: data.migrationItemVersion,
142
+ languageVariant: languageVariant,
143
+ });
144
+
145
+ // set scheduling
146
+ await workflowImporter.setScheduledStateOfLanguageVariantAsync({
147
+ logSpinner: data.logSpinner,
148
+ migrationItem: data.migrationItem,
149
+ migrationItemVersion: data.migrationItemVersion,
150
+ });
151
+
152
+ return languageVariant;
153
+ };
154
+
155
+ const importLanguageVariantAsync = async (
156
+ logSpinner: LogSpinnerData,
157
+ migrationItem: MigrationItem,
158
+ preparedContentItem: ImportedItem,
159
+ ): Promise<readonly LanguageVariantModels.ContentItemLanguageVariant[]> => {
160
+ const { draftVersion, publishedVersion } = categorizeVersions(migrationItem);
161
+
162
+ // get initial state of language variant from target env
163
+ const targetVariantState = config.importContext.getLanguageVariantStateInTargetEnvironment(
164
+ migrationItem.system.codename,
165
+ migrationItem.system.language.codename,
166
+ );
167
+
168
+ // prepare language variant for import (unpublish, create new version, un-schedule ...)
169
+ await prepareTargetEnvironmentVariantForImportAsync({
170
+ logSpinner,
171
+ migrationItem,
172
+ targetVariantState,
173
+ });
174
+
175
+ // first import published version if it exists
176
+ const publishedLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = publishedVersion
177
+ ? await importVersionAsync({
178
+ logSpinner: logSpinner,
179
+ migrationItem: migrationItem,
180
+ preparedContentItem: preparedContentItem,
181
+ migrationItemVersion: publishedVersion,
182
+ })
183
+ : undefined;
184
+
185
+ // if target env contains published version & imported version not, unpublish it from the target env
186
+ if (targetVariantState.publishedLanguageVariant && !publishedVersion) {
187
+ await workflowImporter.unpublishLanguageVariantAsync({
188
+ logSpinner,
189
+ migrationItem,
190
+ });
191
+ await workflowImporter.moveToDraftStepAsync({
192
+ logSpinner,
193
+ migrationItem,
194
+ });
195
+ }
196
+ const draftLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = draftVersion
197
+ ? await importVersionAsync({
198
+ logSpinner: logSpinner,
199
+ migrationItem: migrationItem,
200
+ preparedContentItem: preparedContentItem,
201
+ migrationItemVersion: draftVersion,
202
+ createNewVersion: !!publishedLanguageVariant,
203
+ })
204
+ : undefined;
205
+
206
+ return [publishedLanguageVariant, draftLanguageVariant].filter(isNotUndefined);
207
+ };
208
+
209
+ const cancelScheduledStateAsync = async (data: {
210
+ readonly logSpinner: LogSpinnerData;
211
+ readonly migrationItem: MigrationItem;
212
+ readonly scheduledState: LanguageVariantSchedulesStateValues;
213
+ }): Promise<void> => {
214
+ const changeWorkflowData = {
215
+ logSpinner: data.logSpinner,
216
+ migrationItem: data.migrationItem,
217
+ };
218
+
219
+ await match(data.scheduledState)
220
+ .with("scheduledPublish", async () => {
221
+ // cancel scheduled publish if language variant is scheduled to be published
222
+ await workflowImporter.cancelScheduledPublishAsync(changeWorkflowData);
223
+ })
224
+ .with("scheduledUnpublish", async () => {
225
+ // cancel scheduled unpublish if language variant is scheduled to be unpublished
226
+ await workflowImporter.cancelScheduledUnpublishAsync(changeWorkflowData);
227
+ })
228
+ .otherwise(() => {});
229
+ };
230
+
231
+ const prepareTargetEnvironmentVariantForImportAsync = async (data: {
232
+ readonly logSpinner: LogSpinnerData;
233
+ readonly migrationItem: MigrationItem;
234
+ readonly targetVariantState: LanguageVariantStateInTargetEnvironmentByCodename;
235
+ }): Promise<void> => {
236
+ // when language variant exists in target env, we need to prepare it for import by unscheduling, moving to draft etc...
237
+ // we use draft language variant if it exists, otherwise we use published language variant
238
+ const languageVariantToPrepare = data.targetVariantState.draftLanguageVariant ?? data.targetVariantState.publishedLanguageVariant;
239
+
240
+ if (!languageVariantToPrepare) {
241
+ return;
242
+ }
243
+
244
+ // there is likely a bug which causes /published endpoint to return invalid scheduled state
245
+ // use conditions below to determine scheduled state to use - this will be fixed in future
246
+ if (languageVariantToPrepare.workflowState?.scheduledState) {
247
+ await cancelScheduledStateAsync({
248
+ logSpinner: data.logSpinner,
249
+ migrationItem: data.migrationItem,
250
+ scheduledState: languageVariantToPrepare.workflowState.scheduledState,
251
+ });
252
+ }
253
+
254
+ const changeWorkflowData = {
255
+ logSpinner: data.logSpinner,
256
+ migrationItem: data.migrationItem,
257
+ };
258
+
259
+ await match(languageVariantToPrepare.workflowState?.workflowState)
260
+ .with("published", async () => {
261
+ // create new version if language variant is published
262
+ await workflowImporter.createNewVersionOfLanguageVariantAsync(changeWorkflowData);
263
+ })
264
+ .with("archived", async () => {
265
+ // move to draft step if language variant is archived
266
+ await workflowImporter.moveToDraftStepAsync(changeWorkflowData);
267
+ })
268
+ .otherwise(() => {});
269
+ };
270
+
271
+ const isPublishedWorkflowStep = (stepCodename: string, workflow: Readonly<WorkflowModels.Workflow>): boolean => {
272
+ return workflow.publishedStep.codename === stepCodename;
273
+ };
274
+
275
+ const getElementContract = (
276
+ migrationItem: MigrationItem,
277
+ element: MigrationElement,
278
+ elementCodename: string,
279
+ ): Readonly<LanguageVariantElements.ILanguageVariantElementBase> => {
280
+ const importTransformResult = importTransforms[
281
+ config.importContext.getElement(migrationItem.system.type.codename, elementCodename, element.type).type
282
+ ]({
283
+ elementCodename: elementCodename,
284
+ importContext: config.importContext,
285
+ migrationItems: config.importContext.categorizedImportData.contentItems,
286
+ elementData: element,
287
+ });
288
+
289
+ return importTransformResult;
290
+ };
291
+
292
+ const importAsync = async (): Promise<readonly ImportedLanguageVariant[]> => {
293
+ config.logger.log({
294
+ type: "info",
295
+ message: `Importing '${chalk.yellow(
296
+ config.importContext.categorizedImportData.contentItems.length.toString(),
297
+ )}' language variants`,
298
+ });
299
+
300
+ return await processItemsAsync<MigrationItem, readonly Readonly<LanguageVariantModels.ContentItemLanguageVariant>[]>({
301
+ action: "Importing language variants",
302
+ logger: config.logger,
303
+ parallelLimit: 1,
304
+ items: config.importContext.categorizedImportData.contentItems,
305
+ itemInfo: (input) => {
306
+ return {
307
+ itemType: "languageVariant",
308
+ title: input.system.name,
309
+ partA: input.system.language.codename,
310
+ };
311
+ },
312
+ processAsync: async (migrationItem, logSpinner) => {
313
+ const contentItem = findRequired(
314
+ config.preparedContentItems,
315
+ (item) => item.inputItem.system.codename === migrationItem.system.codename,
316
+ `Missing content item with codename '${chalk.red(
317
+ migrationItem.system.codename,
318
+ )}'. Content item should have been prepepared.`,
319
+ );
320
+
321
+ return await importLanguageVariantAsync(logSpinner, migrationItem, contentItem);
322
+ },
323
+ });
324
+ };
325
+
326
+ return {
327
+ importAsync,
328
+ };
333
329
  }