@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.
Files changed (88) hide show
  1. package/README.md +79 -67
  2. package/dist/es2022/core/helpers/workflow-helper.d.ts +1 -0
  3. package/dist/es2022/core/helpers/workflow-helper.js +6 -4
  4. package/dist/es2022/core/helpers/workflow-helper.js.map +1 -1
  5. package/dist/es2022/core/logs/loggers.js +13 -22
  6. package/dist/es2022/core/logs/loggers.js.map +1 -1
  7. package/dist/es2022/core/models/core.models.d.ts +16 -6
  8. package/dist/es2022/core/models/migration.models.d.ts +9 -9
  9. package/dist/es2022/core/models/migration.schema.d.ts +247 -0
  10. package/dist/es2022/core/models/migration.schema.js +12 -2
  11. package/dist/es2022/core/models/migration.schema.js.map +1 -1
  12. package/dist/es2022/core/utils/array.utils.js.map +1 -1
  13. package/dist/es2022/core/utils/binary-data.utils.js +2 -6
  14. package/dist/es2022/core/utils/binary-data.utils.js.map +1 -1
  15. package/dist/es2022/core/utils/confirm.utils.js +10 -14
  16. package/dist/es2022/core/utils/confirm.utils.js.map +1 -1
  17. package/dist/es2022/core/utils/error.utils.js +35 -27
  18. package/dist/es2022/core/utils/error.utils.js.map +1 -1
  19. package/dist/es2022/core/utils/http.utils.js +7 -11
  20. package/dist/es2022/core/utils/http.utils.js.map +1 -1
  21. package/dist/es2022/core/utils/management-client-utils.d.ts +2 -1
  22. package/dist/es2022/core/utils/management-client-utils.js +12 -2
  23. package/dist/es2022/core/utils/management-client-utils.js.map +1 -1
  24. package/dist/es2022/core/utils/run.utils.js +12 -10
  25. package/dist/es2022/core/utils/run.utils.js.map +1 -1
  26. package/dist/es2022/export/context/export-context-fetcher.js +2 -1
  27. package/dist/es2022/export/context/export-context-fetcher.js.map +1 -1
  28. package/dist/es2022/export/export-manager.js +8 -0
  29. package/dist/es2022/export/export-manager.js.map +1 -1
  30. package/dist/es2022/export/export.models.d.ts +2 -1
  31. package/dist/es2022/import/comparers/asset-comparer.d.ts +2 -1
  32. package/dist/es2022/import/comparers/asset-comparer.js +9 -17
  33. package/dist/es2022/import/comparers/asset-comparer.js.map +1 -1
  34. package/dist/es2022/import/context/import-context-fetcher.js +120 -40
  35. package/dist/es2022/import/context/import-context-fetcher.js.map +1 -1
  36. package/dist/es2022/import/import.models.d.ts +2 -1
  37. package/dist/es2022/import/importers/assets-importer.js +12 -2
  38. package/dist/es2022/import/importers/assets-importer.js.map +1 -1
  39. package/dist/es2022/import/importers/language-variant-importer.js +95 -83
  40. package/dist/es2022/import/importers/language-variant-importer.js.map +1 -1
  41. package/dist/es2022/import/importers/workflow-importer.d.ts +41 -4
  42. package/dist/es2022/import/importers/workflow-importer.js +158 -17
  43. package/dist/es2022/import/importers/workflow-importer.js.map +1 -1
  44. package/dist/es2022/metadata.js +2 -2
  45. package/dist/es2022/node/cli/app.js +8 -12
  46. package/dist/es2022/node/cli/app.js.map +1 -1
  47. package/dist/es2022/node/cli/args/args-fetcher.js +9 -10
  48. package/dist/es2022/node/cli/args/args-fetcher.js.map +1 -1
  49. package/dist/es2022/toolkit/migrate.d.ts +1 -3
  50. package/dist/es2022/toolkit/migrate.js.map +1 -1
  51. package/dist/es2022/translation/extraction/items-extraction.processor.js +17 -17
  52. package/dist/es2022/translation/extraction/items-extraction.processor.js.map +1 -1
  53. package/dist/es2022/translation/transforms/export-transforms.js +1 -1
  54. package/dist/es2022/translation/transforms/export-transforms.js.map +1 -1
  55. package/dist/es2022/zip/zip-packager.js +13 -18
  56. package/dist/es2022/zip/zip-packager.js.map +1 -1
  57. package/dist/es2022/zip/zip-transformer.js +3 -1
  58. package/dist/es2022/zip/zip-transformer.js.map +1 -1
  59. package/lib/core/helpers/workflow-helper.ts +8 -8
  60. package/lib/core/logs/loggers.ts +14 -22
  61. package/lib/core/models/core.models.ts +23 -4
  62. package/lib/core/models/migration.models.ts +13 -12
  63. package/lib/core/models/migration.schema.ts +189 -178
  64. package/lib/core/utils/array.utils.ts +2 -10
  65. package/lib/core/utils/binary-data.utils.ts +2 -7
  66. package/lib/core/utils/confirm.utils.ts +18 -24
  67. package/lib/core/utils/error.utils.ts +50 -30
  68. package/lib/core/utils/http.utils.ts +14 -15
  69. package/lib/core/utils/management-client-utils.ts +188 -182
  70. package/lib/core/utils/run.utils.ts +27 -18
  71. package/lib/export/context/export-context-fetcher.ts +2 -1
  72. package/lib/export/export-manager.ts +14 -3
  73. package/lib/export/export.models.ts +3 -1
  74. package/lib/import/comparers/asset-comparer.ts +16 -24
  75. package/lib/import/context/import-context-fetcher.ts +179 -85
  76. package/lib/import/import.models.ts +2 -0
  77. package/lib/import/importers/assets-importer.ts +19 -12
  78. package/lib/import/importers/language-variant-importer.ts +125 -129
  79. package/lib/import/importers/workflow-importer.ts +228 -20
  80. package/lib/metadata.ts +2 -2
  81. package/lib/node/cli/app.ts +11 -12
  82. package/lib/node/cli/args/args-fetcher.ts +12 -14
  83. package/lib/toolkit/migrate.ts +1 -3
  84. package/lib/translation/extraction/items-extraction.processor.ts +93 -93
  85. package/lib/translation/transforms/export-transforms.ts +1 -1
  86. package/lib/zip/zip-packager.ts +26 -28
  87. package/lib/zip/zip-transformer.ts +3 -1
  88. package/package.json +14 -13
@@ -1,10 +1,5 @@
1
- import {
2
- ContentItemModels,
3
- ElementContracts,
4
- LanguageVariantModels,
5
- ManagementClient,
6
- WorkflowModels
7
- } from '@kontent-ai/management-sdk';
1
+ import { match } from 'ts-pattern';
2
+ import { ContentItemModels, ElementContracts, LanguageVariantModels, ManagementClient, WorkflowModels } from '@kontent-ai/management-sdk';
8
3
  import {
9
4
  Logger,
10
5
  processItemsAsync,
@@ -14,12 +9,15 @@ import {
14
9
  MigrationElement,
15
10
  MigrationItemVersion,
16
11
  workflowHelper,
17
- findRequired
12
+ findRequired,
13
+ isNotUndefined,
14
+ LanguageVariantSchedulesStateValues,
15
+ LanguageVariantStateInTargetEnvironmentByCodename
18
16
  } from '../../core/index.js';
19
17
  import chalk from 'chalk';
20
18
  import { ImportContext } from '../import.models.js';
21
19
  import { importTransforms } from '../../translation/index.js';
22
- import { workflowImporter } from './workflow-importer.js';
20
+ import { workflowImporter as workflowImporterInit } from './workflow-importer.js';
23
21
  import { throwErrorForMigrationItem } from '../utils/import.utils.js';
24
22
 
25
23
  export function languageVariantImporter(config: {
@@ -28,6 +26,12 @@ export function languageVariantImporter(config: {
28
26
  readonly importContext: ImportContext;
29
27
  readonly client: Readonly<ManagementClient>;
30
28
  }) {
29
+ const workflowImporter = workflowImporterInit({
30
+ logger: config.logger,
31
+ managementClient: config.client,
32
+ workflows: config.importContext.environmentData.workflows
33
+ });
34
+
31
35
  const upsertLanguageVariantAsync = async (data: {
32
36
  readonly workflow: Readonly<WorkflowModels.Workflow>;
33
37
  readonly logSpinner: LogSpinnerData;
@@ -45,11 +49,9 @@ export function languageVariantImporter(config: {
45
49
  .byLanguageCodename(data.migrationItem.system.language.codename)
46
50
  .withData(() => {
47
51
  return {
48
- elements: Object.entries(data.migrationItemVersion.elements).map(
49
- ([codename, migrationElement]) => {
50
- return getElementContract(data.migrationItem, migrationElement, codename);
51
- }
52
- ),
52
+ elements: Object.entries(data.migrationItemVersion.elements).map(([codename, migrationElement]) => {
53
+ return getElementContract(data.migrationItem, migrationElement, codename);
54
+ }),
53
55
  workflow: {
54
56
  workflow_identifier: {
55
57
  codename: data.workflow.codename
@@ -94,7 +96,7 @@ export function languageVariantImporter(config: {
94
96
  if (draftVersions.length > 1) {
95
97
  throwErrorForMigrationItem(
96
98
  migrationItem,
97
- `There can be only 1 draft version. There are '${publishedVersions.length}' draft versions for the item.`
99
+ `There can be only 1 draft version. There are '${draftVersions.length}' draft versions for the item.`
98
100
  );
99
101
  }
100
102
 
@@ -109,26 +111,21 @@ export function languageVariantImporter(config: {
109
111
  readonly migrationItem: MigrationItem;
110
112
  readonly migrationItemVersion: MigrationItemVersion;
111
113
  readonly preparedContentItem: Readonly<ContentItemModels.ContentItem>;
112
- readonly workflowStepCodenameInTargetEnvironment: string | undefined;
114
+ readonly createNewVersion?: boolean;
113
115
  }): Promise<Readonly<LanguageVariantModels.ContentItemLanguageVariant>> => {
114
116
  // validate workflow
115
- const { step, workflow } = workflowHelper(
116
- config.importContext.environmentData.workflows
117
- ).getWorkflowAndStepByCodenames({
117
+ const { step, workflow } = workflowHelper(config.importContext.environmentData.workflows).getWorkflowAndStepByCodenames({
118
118
  workflowCodename: data.migrationItem.system.workflow.codename,
119
119
  stepCodename: data.migrationItemVersion.workflow_step.codename
120
120
  });
121
121
 
122
- // prepare target variant for upsert if it exists in target env
123
- if (data.workflowStepCodenameInTargetEnvironment) {
124
- await prepareLanguageVariantForImportAsync({
122
+ // create new version if necessary. This is needed when both draft & published version are imported
123
+ if (data.createNewVersion) {
124
+ await workflowImporter.createNewVersionOfLanguageVariantAsync({
125
125
  logSpinner: data.logSpinner,
126
- workflowStepCodenameInTargetEnvironment: data.workflowStepCodenameInTargetEnvironment,
127
- migrationItem: data.migrationItem,
128
- workflow
126
+ migrationItem: data.migrationItem
129
127
  });
130
128
  }
131
-
132
129
  // upsert language variant
133
130
  const languageVariant = await upsertLanguageVariantAsync({
134
131
  logSpinner: data.logSpinner,
@@ -139,15 +136,19 @@ export function languageVariantImporter(config: {
139
136
  });
140
137
 
141
138
  // set workflow accordingly (publish, move to workflow step, archive ...)
142
- await workflowImporter({
143
- logger: config.logger,
144
- managementClient: config.client,
145
- workflows: config.importContext.environmentData.workflows
146
- }).setWorkflowOfLanguageVariantAsync({
139
+ await workflowImporter.setWorkflowOfLanguageVariantAsync({
147
140
  logSpinner: data.logSpinner,
148
141
  migrationItem: data.migrationItem,
149
142
  workflowCodename: workflow.codename,
150
- stepCodename: step.codename
143
+ stepCodename: step.codename,
144
+ migrationItemVersion: data.migrationItemVersion
145
+ });
146
+
147
+ // set scheduling
148
+ await workflowImporter.setScheduledStateOfLanguageVariantAsync({
149
+ logSpinner: data.logSpinner,
150
+ migrationItem: data.migrationItem,
151
+ migrationItemVersion: data.migrationItemVersion
151
152
  });
152
153
 
153
154
  return languageVariant;
@@ -160,126 +161,124 @@ export function languageVariantImporter(config: {
160
161
  ): Promise<readonly LanguageVariantModels.ContentItemLanguageVariant[]> => {
161
162
  const { draftVersion, publishedVersion } = categorizeVersions(migrationItem);
162
163
 
163
- let publishedLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined;
164
- let draftLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined;
165
- let lastWorkflowStepCodenameInTargetEnvironment: string | undefined;
166
-
167
- const workflow = workflowHelper(config.importContext.environmentData.workflows).getWorkflowByCodename(
168
- migrationItem.system.workflow.codename
169
- );
170
-
171
164
  // get initial state of language variant from target env
172
- const languageVariantState = config.importContext.getLanguageVariantStateInTargetEnvironment(
165
+ const targetVariantState = config.importContext.getLanguageVariantStateInTargetEnvironment(
173
166
  migrationItem.system.codename,
174
167
  migrationItem.system.language.codename
175
168
  );
176
169
 
177
- if (languageVariantState.step) {
178
- // keep track of last worfklow step
179
- lastWorkflowStepCodenameInTargetEnvironment = languageVariantState.step.codename;
180
- }
170
+ // prepare language variant for import (unpublish, create new version, un-schedule ...)
171
+ await prepareTargetEnvironmentVariantForImportAsync({
172
+ logSpinner,
173
+ migrationItem,
174
+ targetVariantState
175
+ });
181
176
 
182
177
  // first import published version if it exists
183
- if (publishedVersion) {
184
- publishedLanguageVariant = await importVersionAsync({
185
- logSpinner: logSpinner,
186
- migrationItem: migrationItem,
187
- preparedContentItem: preparedContentItem,
188
- migrationItemVersion: publishedVersion,
189
- workflowStepCodenameInTargetEnvironment: lastWorkflowStepCodenameInTargetEnvironment
178
+ const publishedLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = publishedVersion
179
+ ? await importVersionAsync({
180
+ logSpinner: logSpinner,
181
+ migrationItem: migrationItem,
182
+ preparedContentItem: preparedContentItem,
183
+ migrationItemVersion: publishedVersion
184
+ })
185
+ : undefined;
186
+
187
+ // if target env contains published version & imported version not, unpublish it from the target env
188
+ if (targetVariantState.publishedLanguageVariant && !publishedVersion) {
189
+ await workflowImporter.unpublishLanguageVariantAsync({
190
+ logSpinner,
191
+ migrationItem
190
192
  });
191
-
192
- // set last published workflow step to publish as language variant has just been published in target environment
193
- lastWorkflowStepCodenameInTargetEnvironment = workflow.publishedStep.codename;
194
- }
195
-
196
- if (draftVersion) {
197
- draftLanguageVariant = await importVersionAsync({
198
- logSpinner: logSpinner,
199
- migrationItem: migrationItem,
200
- preparedContentItem: preparedContentItem,
201
- migrationItemVersion: draftVersion,
202
- workflowStepCodenameInTargetEnvironment: lastWorkflowStepCodenameInTargetEnvironment
193
+ await workflowImporter.moveToDraftStepAsync({
194
+ logSpinner,
195
+ migrationItem
203
196
  });
204
197
  }
205
-
206
- return [
207
- ...(publishedLanguageVariant ? [publishedLanguageVariant] : []),
208
- ...(draftLanguageVariant ? [draftLanguageVariant] : [])
209
- ];
210
- };
211
-
212
- const createNewVersionOfLanguageVariantAsync = async (
213
- logSpinner: LogSpinnerData,
214
- migrationItem: MigrationItem
215
- ): Promise<void> => {
216
- await runMapiRequestAsync({
217
- logger: config.logger,
218
- func: async () => {
219
- await config.client
220
- .createNewVersionOfLanguageVariant()
221
- .byItemCodename(migrationItem.system.codename)
222
- .byLanguageCodename(migrationItem.system.language.codename)
223
- .toPromise();
224
- },
225
- action: 'createNewVersion',
226
- type: 'languageVariant',
227
- logSpinner: logSpinner,
228
- itemName: `${migrationItem.system.codename} (${migrationItem.system.language.codename})`
229
- });
198
+ const draftLanguageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant> | undefined = draftVersion
199
+ ? await importVersionAsync({
200
+ logSpinner: logSpinner,
201
+ migrationItem: migrationItem,
202
+ preparedContentItem: preparedContentItem,
203
+ migrationItemVersion: draftVersion,
204
+ createNewVersion: publishedLanguageVariant ? true : false
205
+ })
206
+ : undefined;
207
+
208
+ return [publishedLanguageVariant, draftLanguageVariant].filter(isNotUndefined);
230
209
  };
231
210
 
232
- const moveToDraftStepAsync = async (
233
- logSpinner: LogSpinnerData,
234
- migrationItem: MigrationItem,
235
- workflow: Readonly<WorkflowModels.Workflow>
236
- ): Promise<void> => {
237
- const firstWorkflowStep = workflow.steps?.[0];
211
+ const cancelScheduledStateAsync = async (data: {
212
+ readonly logSpinner: LogSpinnerData;
213
+ readonly migrationItem: MigrationItem;
214
+ readonly scheduledState: LanguageVariantSchedulesStateValues;
215
+ }): Promise<void> => {
216
+ const changeWorkflowData = {
217
+ logSpinner: data.logSpinner,
218
+ migrationItem: data.migrationItem
219
+ };
238
220
 
239
- if (firstWorkflowStep) {
240
- await runMapiRequestAsync({
241
- logger: config.logger,
242
- func: async () => {
243
- await config.client
244
- .changeWorkflowStepOfLanguageVariant()
245
- .byItemCodename(migrationItem.system.codename)
246
- .byLanguageCodename(migrationItem.system.language.codename)
247
- .byWorkflowStepCodename(firstWorkflowStep.codename)
248
- .toPromise();
249
- },
250
- action: 'changeWorkflowStep',
251
- type: 'languageVariant',
252
- logSpinner: logSpinner,
253
- itemName: `${migrationItem.system.codename} (${migrationItem.system.language.codename}) -> ${firstWorkflowStep.codename}`
254
- });
255
- }
221
+ await match(data.scheduledState)
222
+ .with('scheduledPublish', async () => {
223
+ // cancel scheduled publish if language variant is scheduled to be published
224
+ await workflowImporter.cancelScheduledPublishAsync(changeWorkflowData);
225
+ })
226
+ .with('scheduledUnpublish', async () => {
227
+ // cancel scheduled unpublish if language variant is scheduled to be unpublished
228
+ await workflowImporter.cancelScheduledUnpublishAsync(changeWorkflowData);
229
+ })
230
+ .otherwise(() => {});
256
231
  };
257
232
 
258
- const prepareLanguageVariantForImportAsync = async (data: {
233
+ const prepareTargetEnvironmentVariantForImportAsync = async (data: {
259
234
  readonly logSpinner: LogSpinnerData;
260
235
  readonly migrationItem: MigrationItem;
261
- readonly workflowStepCodenameInTargetEnvironment: string;
262
- readonly workflow: Readonly<WorkflowModels.Workflow>;
236
+ readonly targetVariantState: LanguageVariantStateInTargetEnvironmentByCodename;
263
237
  }): Promise<void> => {
264
- // create new version if language variant is published
265
- if (isPublishedWorkflowStep(data.workflowStepCodenameInTargetEnvironment, data.workflow)) {
266
- await createNewVersionOfLanguageVariantAsync(data.logSpinner, data.migrationItem);
238
+ if (!data.targetVariantState) {
239
+ // no need to prepare language variant as it doesn't exist in target environment
240
+ return;
267
241
  }
268
242
 
269
- // move to draft step if language variant is archived
270
- if (isArchivedWorkflowStep(data.workflowStepCodenameInTargetEnvironment, data.workflow)) {
271
- await moveToDraftStepAsync(data.logSpinner, data.migrationItem, data.workflow);
243
+ // when language variant exists in target env, we need to prepare it for import by unscheduling, moving to draft etc...
244
+ // we use draft language variant if it exists, otherwise we use published language variant
245
+ const languageVariantToPrepare = data.targetVariantState.draftLanguageVariant ?? data.targetVariantState.publishedLanguageVariant;
246
+
247
+ if (!languageVariantToPrepare) {
248
+ return;
272
249
  }
250
+
251
+ // there is likely a bug which causes /published endpoint to return invalid scheduled state
252
+ // use conditions below to determine scheduled state to use - this will be fixed in future
253
+ if (languageVariantToPrepare.workflowState?.scheduledState) {
254
+ await cancelScheduledStateAsync({
255
+ logSpinner: data.logSpinner,
256
+ migrationItem: data.migrationItem,
257
+ scheduledState: languageVariantToPrepare.workflowState.scheduledState
258
+ });
259
+ }
260
+
261
+ const changeWorkflowData = {
262
+ logSpinner: data.logSpinner,
263
+ migrationItem: data.migrationItem
264
+ };
265
+
266
+ await match(languageVariantToPrepare.workflowState?.workflowState)
267
+ .with('published', async () => {
268
+ // create new version if language variant is published
269
+ await workflowImporter.createNewVersionOfLanguageVariantAsync(changeWorkflowData);
270
+ })
271
+ .with('archived', async () => {
272
+ // move to draft step if language variant is archived
273
+ await workflowImporter.moveToDraftStepAsync(changeWorkflowData);
274
+ })
275
+ .otherwise(() => {});
273
276
  };
274
277
 
275
278
  const isPublishedWorkflowStep = (stepCodename: string, workflow: Readonly<WorkflowModels.Workflow>): boolean => {
276
279
  return workflow.publishedStep.codename === stepCodename;
277
280
  };
278
281
 
279
- const isArchivedWorkflowStep = (stepCodename: string, workflow: Readonly<WorkflowModels.Workflow>): boolean => {
280
- return workflow.archivedStep.codename === stepCodename;
281
- };
282
-
283
282
  const getElementContract = (
284
283
  migrationItem: MigrationItem,
285
284
  element: MigrationElement,
@@ -306,10 +305,7 @@ export function languageVariantImporter(config: {
306
305
  });
307
306
 
308
307
  return (
309
- await processItemsAsync<
310
- MigrationItem,
311
- readonly Readonly<LanguageVariantModels.ContentItemLanguageVariant>[]
312
- >({
308
+ await processItemsAsync<MigrationItem, readonly Readonly<LanguageVariantModels.ContentItemLanguageVariant>[]>({
313
309
  action: 'Importing language variants',
314
310
  logger: config.logger,
315
311
  parallelLimit: 1,
@@ -1,11 +1,21 @@
1
1
  import { ManagementClient, SharedModels, WorkflowModels } from '@kontent-ai/management-sdk';
2
- import { Logger, runMapiRequestAsync, LogSpinnerData, MigrationItem, workflowHelper } from '../../core/index.js';
2
+ import {
3
+ Logger,
4
+ runMapiRequestAsync,
5
+ LogSpinnerData,
6
+ MigrationItem,
7
+ workflowHelper as workflowHelperInit,
8
+ MigrationItemVersion
9
+ } from '../../core/index.js';
10
+ import { match } from 'ts-pattern';
3
11
 
4
12
  export function workflowImporter(config: {
5
- logger: Logger;
6
- managementClient: Readonly<ManagementClient>;
7
- workflows: readonly Readonly<WorkflowModels.Workflow>[];
13
+ readonly logger: Logger;
14
+ readonly managementClient: Readonly<ManagementClient>;
15
+ readonly workflows: readonly Readonly<WorkflowModels.Workflow>[];
8
16
  }) {
17
+ const workflowHelper = workflowHelperInit(config.workflows);
18
+
9
19
  const publishLanguageVariantAsync = async (data: {
10
20
  readonly logSpinner: LogSpinnerData;
11
21
  readonly migrationItem: MigrationItem;
@@ -64,12 +74,70 @@ export function workflowImporter(config: {
64
74
  }
65
75
  };
66
76
 
77
+ const schedulePublishLanguageVariantAsync = async (data: {
78
+ readonly logSpinner: LogSpinnerData;
79
+ readonly migrationItem: MigrationItem;
80
+ readonly schedule: {
81
+ readonly publish_time: string;
82
+ readonly publish_display_timezone: string;
83
+ };
84
+ }): Promise<void> => {
85
+ await runMapiRequestAsync({
86
+ logger: config.logger,
87
+ func: async () =>
88
+ (
89
+ await config.managementClient
90
+ .publishLanguageVariant()
91
+ .byItemCodename(data.migrationItem.system.codename)
92
+ .byLanguageCodename(data.migrationItem.system.language.codename)
93
+ .withData({
94
+ scheduled_to: data.schedule.publish_time,
95
+ display_timezone: data.schedule.publish_display_timezone
96
+ })
97
+ .toPromise()
98
+ ).data,
99
+ action: 'schedulePublish',
100
+ type: 'languageVariant',
101
+ logSpinner: data.logSpinner,
102
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename})`
103
+ });
104
+ };
105
+
106
+ const scheduleUnpublishLanguageVariantAsync = async (data: {
107
+ readonly logSpinner: LogSpinnerData;
108
+ readonly migrationItem: MigrationItem;
109
+ readonly schedule: {
110
+ readonly unpublish_time: string;
111
+ readonly unpublish_display_timezone: string;
112
+ };
113
+ }): Promise<void> => {
114
+ await runMapiRequestAsync({
115
+ logger: config.logger,
116
+ func: async () =>
117
+ (
118
+ await config.managementClient
119
+ .unpublishLanguageVariant()
120
+ .byItemCodename(data.migrationItem.system.codename)
121
+ .byLanguageCodename(data.migrationItem.system.language.codename)
122
+ .withData({
123
+ scheduled_to: data.schedule.unpublish_time,
124
+ display_timezone: data.schedule.unpublish_display_timezone
125
+ })
126
+ .toPromise()
127
+ ).data,
128
+ action: 'scheduleUnpublish',
129
+ type: 'languageVariant',
130
+ logSpinner: data.logSpinner,
131
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename})`
132
+ });
133
+ };
134
+
67
135
  const archiveLanguageVariantAsync = async (data: {
68
136
  readonly logSpinner: LogSpinnerData;
69
137
  readonly workflowCodename: string;
70
138
  readonly migrationItem: MigrationItem;
71
139
  }): Promise<void> => {
72
- const workflow = workflowHelper(config.workflows).getWorkflowByCodename(data.workflowCodename);
140
+ const workflow = workflowHelper.getWorkflowByCodename(data.workflowCodename);
73
141
  await runMapiRequestAsync({
74
142
  logger: config.logger,
75
143
  func: async () =>
@@ -101,7 +169,7 @@ export function workflowImporter(config: {
101
169
  readonly stepCodename: string;
102
170
  readonly migrationItem: MigrationItem;
103
171
  }): Promise<void> => {
104
- const { workflow, step } = workflowHelper(config.workflows).getWorkflowAndStepByCodenames({
172
+ const { workflow, step } = workflowHelper.getWorkflowAndStepByCodenames({
105
173
  workflowCodename: data.workflowCodename,
106
174
  stepCodename: data.stepCodename
107
175
  });
@@ -131,29 +199,169 @@ export function workflowImporter(config: {
131
199
  });
132
200
  };
133
201
 
202
+ const createNewVersionOfLanguageVariantAsync = async (data: {
203
+ readonly logSpinner: LogSpinnerData;
204
+ readonly migrationItem: MigrationItem;
205
+ }): Promise<void> => {
206
+ await runMapiRequestAsync({
207
+ logger: config.logger,
208
+ func: async () => {
209
+ await config.managementClient
210
+ .createNewVersionOfLanguageVariant()
211
+ .byItemCodename(data.migrationItem.system.codename)
212
+ .byLanguageCodename(data.migrationItem.system.language.codename)
213
+ .toPromise();
214
+ },
215
+ action: 'createNewVersion',
216
+ type: 'languageVariant',
217
+ logSpinner: data.logSpinner,
218
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename})`
219
+ });
220
+ };
221
+
222
+ const cancelScheduledPublishAsync = async (data: {
223
+ readonly logSpinner: LogSpinnerData;
224
+ readonly migrationItem: MigrationItem;
225
+ }): Promise<void> => {
226
+ await runMapiRequestAsync({
227
+ logger: config.logger,
228
+ func: async () => {
229
+ await config.managementClient
230
+ .cancelSheduledPublishingOfLanguageVariant()
231
+ .byItemCodename(data.migrationItem.system.codename)
232
+ .byLanguageCodename(data.migrationItem.system.language.codename)
233
+ .toPromise();
234
+ },
235
+ action: 'cancelScheduledPublish',
236
+ type: 'languageVariant',
237
+ logSpinner: data.logSpinner,
238
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename}) -> Cancel scheduled publish`
239
+ });
240
+ };
241
+
242
+ const cancelScheduledUnpublishAsync = async (data: {
243
+ readonly logSpinner: LogSpinnerData;
244
+ readonly migrationItem: MigrationItem;
245
+ }): Promise<void> => {
246
+ await runMapiRequestAsync({
247
+ logger: config.logger,
248
+ func: async () => {
249
+ await config.managementClient
250
+ .cancelSheduledUnpublishingOfLanguageVariant()
251
+ .byItemCodename(data.migrationItem.system.codename)
252
+ .byLanguageCodename(data.migrationItem.system.language.codename)
253
+ .toPromise();
254
+ },
255
+ action: 'cancelScheduledUnpublish',
256
+ type: 'languageVariant',
257
+ logSpinner: data.logSpinner,
258
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename}) -> Cancel scheduled unpublish`
259
+ });
260
+ };
261
+
262
+ const moveToDraftStepAsync = async (data: {
263
+ readonly logSpinner: LogSpinnerData;
264
+ readonly migrationItem: MigrationItem;
265
+ }): Promise<void> => {
266
+ const workflow = workflowHelper.getWorkflowByCodename(data.migrationItem.system.workflow.codename);
267
+ const firstWorkflowStep = workflow.steps?.[0];
268
+
269
+ if (firstWorkflowStep) {
270
+ await runMapiRequestAsync({
271
+ logger: config.logger,
272
+ func: async () => {
273
+ await config.managementClient
274
+ .changeWorkflowOfLanguageVariant()
275
+ .byItemCodename(data.migrationItem.system.codename)
276
+ .byLanguageCodename(data.migrationItem.system.language.codename)
277
+ .withData({
278
+ workflow_identifier: {
279
+ codename: workflow.codename
280
+ },
281
+ step_identifier: {
282
+ codename: firstWorkflowStep.codename
283
+ }
284
+ })
285
+ .toPromise();
286
+ },
287
+ action: 'changeWorkflowStep',
288
+ type: 'languageVariant',
289
+ logSpinner: data.logSpinner,
290
+ itemName: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename}) -> ${firstWorkflowStep.codename}`
291
+ });
292
+ }
293
+ };
294
+
295
+ const setScheduledStateOfLanguageVariantAsync = async (data: {
296
+ readonly logSpinner: LogSpinnerData;
297
+ readonly migrationItem: MigrationItem;
298
+ readonly migrationItemVersion: MigrationItemVersion;
299
+ }): Promise<void> => {
300
+ if (!data.migrationItemVersion.schedule) {
301
+ return;
302
+ }
303
+
304
+ // set scheduling
305
+ if (data.migrationItemVersion.schedule.unpublish_time && data.migrationItemVersion.schedule.unpublish_display_timezone) {
306
+ await scheduleUnpublishLanguageVariantAsync({
307
+ logSpinner: data.logSpinner,
308
+ migrationItem: data.migrationItem,
309
+ schedule: {
310
+ unpublish_time: data.migrationItemVersion.schedule.unpublish_time,
311
+ unpublish_display_timezone: data.migrationItemVersion.schedule.unpublish_display_timezone
312
+ }
313
+ });
314
+ }
315
+
316
+ if (data.migrationItemVersion.schedule.publish_time && data.migrationItemVersion.schedule.publish_display_timezone) {
317
+ await schedulePublishLanguageVariantAsync({
318
+ logSpinner: data.logSpinner,
319
+ migrationItem: data.migrationItem,
320
+ schedule: {
321
+ publish_time: data.migrationItemVersion.schedule.publish_time,
322
+ publish_display_timezone: data.migrationItemVersion.schedule.publish_display_timezone
323
+ }
324
+ });
325
+ }
326
+ };
327
+
134
328
  const setWorkflowOfLanguageVariantAsync = async (data: {
135
329
  readonly logSpinner: LogSpinnerData;
136
330
  readonly workflowCodename: string;
137
331
  readonly stepCodename: string;
138
332
  readonly migrationItem: MigrationItem;
333
+ readonly migrationItemVersion: MigrationItemVersion;
139
334
  }): Promise<void> => {
140
- if (workflowHelper(config.workflows).isPublishedStepByCodename(data.stepCodename)) {
141
- await publishLanguageVariantAsync(data);
142
- } else if (workflowHelper(config.workflows).isScheduledStepByCodename(data.stepCodename)) {
143
- data.logSpinner({
144
- type: 'skip',
145
- message: `${data.migrationItem.system.codename} (${data.migrationItem.system.language.codename}) -> Skipping scheduled workflow step assignment`
146
- });
147
- } else if (workflowHelper(config.workflows).isArchivedStepByCodename(data.stepCodename)) {
148
- await unpublishLanguageVariantAsync(data);
149
- await archiveLanguageVariantAsync(data);
150
- } else {
151
- await changeWorkflowOfLanguageVariantAsync(data);
152
- }
335
+ return await match(data.stepCodename)
336
+ .returnType<Promise<void>>()
337
+ .when(
338
+ (stepCodename) => workflowHelper.isPublishedStepByCodename(stepCodename),
339
+ async () => await publishLanguageVariantAsync(data)
340
+ )
341
+ .when(
342
+ (stepCodename) => workflowHelper.isArchivedStepByCodename(stepCodename),
343
+ async () => await archiveLanguageVariantAsync(data)
344
+ )
345
+ .when(
346
+ (stepCodename) => workflowHelper.isScheduledStepByCodename(stepCodename),
347
+ async () => {
348
+ // do nothing for scheduled step
349
+ return await Promise.resolve();
350
+ }
351
+ )
352
+ .otherwise(async () => await changeWorkflowOfLanguageVariantAsync(data));
153
353
  };
154
354
 
155
355
  return {
356
+ setScheduledStateOfLanguageVariantAsync,
156
357
  setWorkflowOfLanguageVariantAsync,
157
- publishLanguageVariantAsync
358
+ publishLanguageVariantAsync,
359
+ unpublishLanguageVariantAsync,
360
+ archiveLanguageVariantAsync,
361
+ changeWorkflowOfLanguageVariantAsync,
362
+ moveToDraftStepAsync,
363
+ createNewVersionOfLanguageVariantAsync,
364
+ cancelScheduledPublishAsync,
365
+ cancelScheduledUnpublishAsync
158
366
  };
159
367
  }
package/lib/metadata.ts CHANGED
@@ -1,6 +1,6 @@
1
1
 
2
2
  export const libMetadata = {
3
3
  name: '@kontent-ai/migration-toolkit',
4
- timestamp: 'Thu, 18 Jul 2024 10:19:20 GMT',
5
- version: '1.3.0'
4
+ timestamp: 'Thu, 15 Aug 2024 09:56:05 GMT',
5
+ version: '1.5.0'
6
6
  };