@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,202 +1,207 @@
1
- import type { WorkflowContracts, WorkflowModels } from '@kontent-ai/management-sdk';
2
- import chalk from 'chalk';
3
- import { findRequired } from '../utils/array.utils.js';
1
+ import type { WorkflowContracts, WorkflowModels } from "@kontent-ai/management-sdk";
2
+ import chalk from "chalk";
3
+ import { MigrationToolkitError } from "../models/error.models.js";
4
+ import { findRequired } from "../utils/array.utils.js";
4
5
 
5
6
  export type WorkflowStep = {
6
- readonly codename: string;
7
- readonly id: string;
8
- readonly transitionsTo: readonly TransitionTo[];
7
+ readonly codename: string;
8
+ readonly id: string;
9
+ readonly transitionsTo: readonly TransitionTo[];
9
10
  };
10
11
 
11
12
  export type ShortestPathResult = {
12
- readonly stepCodename: string;
13
+ readonly stepCodename: string;
13
14
  };
14
15
 
15
16
  type WorkflowMatcher = {
16
- readonly match: (workflow: Readonly<WorkflowModels.Workflow>, index: number) => boolean;
17
- readonly errorMessage: string;
17
+ readonly match: (workflow: Readonly<WorkflowModels.Workflow>, index: number) => boolean;
18
+ readonly errorMessage: string;
18
19
  };
19
20
  type StepMatcher = {
20
- readonly match: (step: WorkflowStep, index: number) => boolean;
21
- readonly errorMessage: string;
21
+ readonly match: (step: WorkflowStep, index: number) => boolean;
22
+ readonly errorMessage: string;
22
23
  };
23
24
 
24
25
  type TransitionTo = {
25
- readonly codename: string;
26
- readonly id: string;
26
+ readonly codename: string;
27
+ readonly id: string;
27
28
  };
28
29
 
29
30
  export function workflowHelper(workflows: readonly Readonly<WorkflowModels.Workflow>[]) {
30
- const mapContractToWorkflowSteps = (
31
- workflow: Readonly<WorkflowModels.Workflow>,
32
- stepsContract: readonly Readonly<WorkflowContracts.IWorkflowStepNewContract>[]
33
- ): readonly WorkflowStep[] => {
34
- const allStepsContracts = [...workflow.steps, workflow.archivedStep, workflow.publishedStep, workflow.scheduledStep];
35
-
36
- return stepsContract.map<WorkflowStep>((m) => {
37
- return {
38
- codename: m.codename,
39
- id: m.id,
40
- transitionsTo: m.transitions_to.map((transitionTo) => {
41
- const transitionStep = allStepsContracts.find((step) => step.id === transitionTo.step.id);
42
-
43
- if (!transitionStep) {
44
- throw Error(`Could not find transition step with id '${transitionTo.step.id}' in workflow '${workflow.codename}'`);
45
- }
46
-
47
- return {
48
- codename: transitionStep.codename,
49
- id: transitionStep.id
50
- };
51
- })
52
- };
53
- });
54
- };
55
-
56
- const getWorkflowStep = (workflow: Readonly<WorkflowModels.Workflow>, stepMatcher: StepMatcher): WorkflowStep => {
57
- const workflowSteps: readonly WorkflowStep[] = [
58
- ...mapContractToWorkflowSteps(workflow, workflow.steps),
59
- {
60
- codename: workflow.archivedStep.codename,
61
- id: workflow.archivedStep.id,
62
- transitionsTo: []
63
- },
64
- {
65
- codename: workflow.publishedStep.codename,
66
- id: workflow.publishedStep.id,
67
- transitionsTo: []
68
- },
69
- {
70
- codename: workflow.scheduledStep.codename,
71
- id: workflow.scheduledStep.id,
72
- transitionsTo: []
73
- }
74
- ];
75
-
76
- return findRequired(workflowSteps, stepMatcher.match, stepMatcher.errorMessage);
77
- };
78
-
79
- const getWorkflow = (workflowMatcher: WorkflowMatcher): Readonly<WorkflowModels.Workflow> => {
80
- return findRequired(workflows, workflowMatcher.match, workflowMatcher.errorMessage);
81
- };
82
-
83
- const getWorkflowByCodename = (workflowCodename: string): Readonly<WorkflowModels.Workflow> => {
84
- return getWorkflow({
85
- errorMessage: [
86
- `Workflow with codename '${chalk.red(workflowCodename)}' does not exist in target project`,
87
- `Available workflows are (${workflows.length}): ${workflows.map((m) => chalk.cyan(m.codename)).join(', ')}`
88
- ].join(', '),
89
- match: (workflow) => workflow.codename.toLowerCase() === workflowCodename.toLowerCase()
90
- });
91
- };
92
-
93
- const getWorkflowStepByCodename = (workflow: Readonly<WorkflowModels.Workflow>, stepCodename: string): WorkflowStep => {
94
- return getWorkflowStep(workflow, {
95
- errorMessage: [
96
- `Workflow step with codename '${chalk.red(stepCodename)}' does not exist in target project`,
97
- `Steps in workflow '${chalk.yellow(workflow.codename)}' are (${workflow.steps.length}): ${workflow.steps
98
- .map((m) => chalk.cyan(m.codename))
99
- .join(', ')}`
100
- ].join(', '),
101
- match: (step) => step.codename.toLowerCase() === stepCodename.toLowerCase()
102
- });
103
- };
104
-
105
- const getWorkflowStepById = (workflow: Readonly<WorkflowModels.Workflow>, stepId: string): WorkflowStep => {
106
- return getWorkflowStep(workflow, {
107
- errorMessage: [
108
- `Workflow step with codename '${chalk.red(stepId)}' does not exist in target project`,
109
- `Steps in workflow '${chalk.yellow(workflow.codename)}' are (${workflow.steps.length}): ${workflow.steps
110
- .map((m) => chalk.cyan(m.id))
111
- .join(', ')}`
112
- ].join(', '),
113
- match: (step) => step.id.toLowerCase() === stepId.toLowerCase()
114
- });
115
- };
116
-
117
- const getWorkflowAndStep = (data: {
118
- readonly workflowMatcher: WorkflowMatcher;
119
- readonly stepMatcher: StepMatcher;
120
- }): { step: WorkflowStep; workflow: Readonly<WorkflowModels.Workflow> } => {
121
- const workflow = getWorkflow(data.workflowMatcher);
122
- return {
123
- workflow,
124
- step: getWorkflowStep(workflow, data.stepMatcher)
125
- };
126
- };
127
-
128
- const getWorkflowAndStepByCodenames = (data: {
129
- readonly workflowCodename: string;
130
- readonly stepCodename: string;
131
- }): { step: WorkflowStep; workflow: Readonly<WorkflowModels.Workflow> } => {
132
- const workflow = getWorkflowByCodename(data.workflowCodename);
133
- return {
134
- workflow,
135
- step: getWorkflowStepByCodename(workflow, data.stepCodename)
136
- };
137
- };
138
-
139
- const findShortestPathBetweenSteps = (
140
- workflow: WorkflowModels.Workflow,
141
- startStep: WorkflowStep,
142
- endStep: WorkflowStep
143
- ): ReadonlyArray<ShortestPathResult> => {
144
- type Node = Readonly<{ parent: null | Node; step: WorkflowStep }>;
145
- let deque: Array<Node> = [{ parent: null, step: startStep }];
146
-
147
- const getResult = (node: Node): ReadonlyArray<ShortestPathResult> =>
148
- node.parent === null ? [] : [...getResult(node.parent), { stepCodename: node.step.codename }];
149
-
150
- while (deque.length !== 0) {
151
- const node = deque.shift() as Node;
152
-
153
- if (node.step.codename === endStep.codename) {
154
- return getResult(node);
155
- }
156
-
157
- const newNodes = node.step.transitionsTo
158
- .filter((s) => deque.find((n) => n.step.codename === s.codename) === undefined)
159
- .map((t) => ({
160
- parent: node,
161
- step: getWorkflowStepByCodename(workflow, t.codename)
162
- }));
163
-
164
- deque = deque.concat(newNodes);
165
- }
166
-
167
- throw new Error(
168
- `Could not find the path from step (codename: ${startStep.codename}) to step (codename: ${endStep.codename}) in workflow (codename: ${workflow.codename})`
169
- );
170
- };
171
-
172
- const isPublishedStepByCodename = (stepCodename: string): boolean => {
173
- return workflows.find((workflow) => workflow.publishedStep.codename === stepCodename) ? true : false;
174
- };
175
-
176
- const isArchivedStepByCodename = (stepCodename: string): boolean => {
177
- return workflows.find((workflow) => workflow.archivedStep.codename === stepCodename) ? true : false;
178
- };
179
-
180
- const isScheduledStepByCodename = (stepCodename: string): boolean => {
181
- return workflows.find((workflow) => workflow.scheduledStep.codename === stepCodename) ? true : false;
182
- };
183
-
184
- const isPublishedStepById = (stepId: string): boolean => {
185
- return workflows.find((workflow) => workflow.publishedStep.id === stepId) ? true : false;
186
- };
187
-
188
- return {
189
- getWorkflowByCodename,
190
- getWorkflowStepByCodename,
191
- getWorkflowAndStepByCodenames,
192
- getWorkflowStepById,
193
- getWorkflowStep,
194
- getWorkflowAndStep,
195
- getWorkflow,
196
- isPublishedStepByCodename,
197
- isArchivedStepByCodename,
198
- isScheduledStepByCodename,
199
- isPublishedStepById,
200
- findShortestPathBetweenSteps
201
- };
31
+ const mapContractToWorkflowSteps = (
32
+ workflow: Readonly<WorkflowModels.Workflow>,
33
+ stepsContract: readonly Readonly<WorkflowContracts.IWorkflowStepNewContract>[],
34
+ ): readonly WorkflowStep[] => {
35
+ const allStepsContracts = [...workflow.steps, workflow.archivedStep, workflow.publishedStep, workflow.scheduledStep];
36
+
37
+ return stepsContract.map<WorkflowStep>((m) => {
38
+ return {
39
+ codename: m.codename,
40
+ id: m.id,
41
+ transitionsTo: m.transitions_to.map((transitionTo) => {
42
+ const transitionStep = allStepsContracts.find((step) => step.id === transitionTo.step.id);
43
+
44
+ if (!transitionStep) {
45
+ throw new MigrationToolkitError(
46
+ "missingWorkflowStep",
47
+ `Could not find transition step with id '${transitionTo.step.id}' in workflow '${workflow.codename}'`,
48
+ );
49
+ }
50
+
51
+ return {
52
+ codename: transitionStep.codename,
53
+ id: transitionStep.id,
54
+ };
55
+ }),
56
+ };
57
+ });
58
+ };
59
+
60
+ const getWorkflowStep = (workflow: Readonly<WorkflowModels.Workflow>, stepMatcher: StepMatcher): WorkflowStep => {
61
+ const workflowSteps: readonly WorkflowStep[] = [
62
+ ...mapContractToWorkflowSteps(workflow, workflow.steps),
63
+ {
64
+ codename: workflow.archivedStep.codename,
65
+ id: workflow.archivedStep.id,
66
+ transitionsTo: [],
67
+ },
68
+ {
69
+ codename: workflow.publishedStep.codename,
70
+ id: workflow.publishedStep.id,
71
+ transitionsTo: [],
72
+ },
73
+ {
74
+ codename: workflow.scheduledStep.codename,
75
+ id: workflow.scheduledStep.id,
76
+ transitionsTo: [],
77
+ },
78
+ ];
79
+
80
+ return findRequired(workflowSteps, stepMatcher.match, stepMatcher.errorMessage);
81
+ };
82
+
83
+ const getWorkflow = (workflowMatcher: WorkflowMatcher): Readonly<WorkflowModels.Workflow> => {
84
+ return findRequired(workflows, workflowMatcher.match, workflowMatcher.errorMessage);
85
+ };
86
+
87
+ const getWorkflowByCodename = (workflowCodename: string): Readonly<WorkflowModels.Workflow> => {
88
+ return getWorkflow({
89
+ errorMessage: [
90
+ `Workflow with codename '${chalk.red(workflowCodename)}' does not exist in target project`,
91
+ `Available workflows are (${workflows.length}): ${workflows.map((m) => chalk.cyan(m.codename)).join(", ")}`,
92
+ ].join(", "),
93
+ match: (workflow) => workflow.codename.toLowerCase() === workflowCodename.toLowerCase(),
94
+ });
95
+ };
96
+
97
+ const getWorkflowStepByCodename = (workflow: Readonly<WorkflowModels.Workflow>, stepCodename: string): WorkflowStep => {
98
+ return getWorkflowStep(workflow, {
99
+ errorMessage: [
100
+ `Workflow step with codename '${chalk.red(stepCodename)}' does not exist in target project`,
101
+ `Steps in workflow '${chalk.yellow(workflow.codename)}' are (${workflow.steps.length}): ${workflow.steps
102
+ .map((m) => chalk.cyan(m.codename))
103
+ .join(", ")}`,
104
+ ].join(", "),
105
+ match: (step) => step.codename.toLowerCase() === stepCodename.toLowerCase(),
106
+ });
107
+ };
108
+
109
+ const getWorkflowStepById = (workflow: Readonly<WorkflowModels.Workflow>, stepId: string): WorkflowStep => {
110
+ return getWorkflowStep(workflow, {
111
+ errorMessage: [
112
+ `Workflow step with codename '${chalk.red(stepId)}' does not exist in target project`,
113
+ `Steps in workflow '${chalk.yellow(workflow.codename)}' are (${workflow.steps.length}): ${workflow.steps
114
+ .map((m) => chalk.cyan(m.id))
115
+ .join(", ")}`,
116
+ ].join(", "),
117
+ match: (step) => step.id.toLowerCase() === stepId.toLowerCase(),
118
+ });
119
+ };
120
+
121
+ const getWorkflowAndStep = (data: {
122
+ readonly workflowMatcher: WorkflowMatcher;
123
+ readonly stepMatcher: StepMatcher;
124
+ }): { step: WorkflowStep; workflow: Readonly<WorkflowModels.Workflow> } => {
125
+ const workflow = getWorkflow(data.workflowMatcher);
126
+ return {
127
+ workflow,
128
+ step: getWorkflowStep(workflow, data.stepMatcher),
129
+ };
130
+ };
131
+
132
+ const getWorkflowAndStepByCodenames = (data: {
133
+ readonly workflowCodename: string;
134
+ readonly stepCodename: string;
135
+ }): { step: WorkflowStep; workflow: Readonly<WorkflowModels.Workflow> } => {
136
+ const workflow = getWorkflowByCodename(data.workflowCodename);
137
+ return {
138
+ workflow,
139
+ step: getWorkflowStepByCodename(workflow, data.stepCodename),
140
+ };
141
+ };
142
+
143
+ const findShortestPathBetweenSteps = (
144
+ workflow: WorkflowModels.Workflow,
145
+ startStep: WorkflowStep,
146
+ endStep: WorkflowStep,
147
+ ): ReadonlyArray<ShortestPathResult> => {
148
+ type Node = Readonly<{ parent: null | Node; step: WorkflowStep }>;
149
+ let deque: Array<Node> = [{ parent: null, step: startStep }];
150
+
151
+ const getResult = (node: Node): ReadonlyArray<ShortestPathResult> =>
152
+ node.parent === null ? [] : [...getResult(node.parent), { stepCodename: node.step.codename }];
153
+
154
+ while (deque.length !== 0) {
155
+ const node = deque.shift() as Node;
156
+
157
+ if (node.step.codename === endStep.codename) {
158
+ return getResult(node);
159
+ }
160
+
161
+ const newNodes = node.step.transitionsTo
162
+ // eslint-disable-next-line @typescript-eslint/no-loop-func
163
+ .filter((s) => deque.find((n) => n.step.codename === s.codename) === undefined)
164
+ .map((t) => ({
165
+ parent: node,
166
+ step: getWorkflowStepByCodename(workflow, t.codename),
167
+ }));
168
+
169
+ deque = deque.concat(newNodes);
170
+ }
171
+
172
+ throw new Error(
173
+ `Could not find the path from step (codename: ${startStep.codename}) to step (codename: ${endStep.codename}) in workflow (codename: ${workflow.codename})`,
174
+ );
175
+ };
176
+
177
+ const isPublishedStepByCodename = (stepCodename: string): boolean => {
178
+ return workflows.some((workflow) => workflow.publishedStep.codename === stepCodename);
179
+ };
180
+
181
+ const isArchivedStepByCodename = (stepCodename: string): boolean => {
182
+ return workflows.some((workflow) => workflow.archivedStep.codename === stepCodename);
183
+ };
184
+
185
+ const isScheduledStepByCodename = (stepCodename: string): boolean => {
186
+ return workflows.some((workflow) => workflow.scheduledStep.codename === stepCodename);
187
+ };
188
+
189
+ const isPublishedStepById = (stepId: string): boolean => {
190
+ return workflows.some((workflow) => workflow.publishedStep.id === stepId);
191
+ };
192
+
193
+ return {
194
+ getWorkflowByCodename,
195
+ getWorkflowStepByCodename,
196
+ getWorkflowAndStepByCodenames,
197
+ getWorkflowStepById,
198
+ getWorkflowStep,
199
+ getWorkflowAndStep,
200
+ getWorkflow,
201
+ isPublishedStepByCodename,
202
+ isArchivedStepByCodename,
203
+ isScheduledStepByCodename,
204
+ isPublishedStepById,
205
+ findShortestPathBetweenSteps,
206
+ };
202
207
  }
@@ -1,72 +1,72 @@
1
- import type { ChalkInstance } from 'chalk';
2
- import chalk from 'chalk';
3
- import { match, P } from 'ts-pattern';
4
- import type { Logger, LogSpinnerMessage } from '../models/log.models.js';
5
- import { getCurrentEnvironment } from '../utils/global.utils.js';
1
+ import type { ChalkInstance } from "chalk";
2
+ import chalk from "chalk";
3
+ import { match, P } from "ts-pattern";
4
+ import type { Logger, LogSpinnerMessage } from "../models/log.models.js";
5
+ import { getCurrentEnvironment } from "../utils/global.utils.js";
6
6
 
7
7
  const originalWarn = console.warn;
8
8
 
9
9
  export function getDefaultLogger(): Logger {
10
- return match(getCurrentEnvironment())
11
- .with('node', () => defaultNodeLogger)
12
- .with('browser', () => defaultBrowserLogger)
13
- .exhaustive();
10
+ return match(getCurrentEnvironment())
11
+ .with("node", () => defaultNodeLogger)
12
+ .with("browser", () => defaultBrowserLogger)
13
+ .exhaustive();
14
14
  }
15
15
 
16
16
  const defaultNodeLogger: Logger = {
17
- log: (data) => console.log(getLogDataMessage(data)),
18
- logWithSpinnerAsync: async (func) => {
19
- const ora = await import('ora');
17
+ log: (data) => console.log(getLogDataMessage(data)),
18
+ logWithSpinnerAsync: async (func) => {
19
+ const ora = await import("ora");
20
20
 
21
- return await ora.oraPromise(async (spinner) => {
22
- // patch global console to prevent disrupting ora instance
23
- // this often happens when JS SDK logs console.warn for
24
- // retried requests. Patching this ensures the flow is uninterrupted
25
- global.console.warn = (m) => {
26
- if (m) {
27
- spinner.text = (m as unknown)?.toString() ?? 'Invalid warn value';
28
- }
29
- };
21
+ return await ora.oraPromise(async (spinner) => {
22
+ // patch global console to prevent disrupting ora instance
23
+ // this often happens when JS SDK logs console.warn for
24
+ // retried requests. Patching this ensures the flow is uninterrupted
25
+ global.console.warn = (m) => {
26
+ if (m) {
27
+ spinner.text = (m as unknown)?.toString() ?? "Invalid warn value";
28
+ }
29
+ };
30
30
 
31
- const result = await func((data) => {
32
- // remember last used prefix. This is useful as we don't have to pass prefix to every single function
33
- // calling the spinner
34
- if (data.prefix) {
35
- spinner.prefixText = data.prefix ?? '';
36
- }
37
- spinner.text = getLogDataMessage(data);
38
- });
31
+ const result = await func((data) => {
32
+ // remember last used prefix. This is useful as we don't have to pass prefix to every single function
33
+ // calling the spinner
34
+ if (data.prefix) {
35
+ spinner.prefixText = data.prefix ?? "";
36
+ }
37
+ spinner.text = getLogDataMessage(data);
38
+ });
39
39
 
40
- // restore original warn
41
- global.console.warn = originalWarn;
40
+ // restore original warn
41
+ global.console.warn = originalWarn;
42
42
 
43
- return result;
44
- }, {});
45
- }
43
+ return result;
44
+ }, {});
45
+ },
46
46
  };
47
47
 
48
48
  const defaultBrowserLogger: Logger = {
49
- log: (data) => console.log(getLogDataMessage(data)),
50
- logWithSpinnerAsync: async (func) => {
51
- return await func((data) => {
52
- const prefix = data.prefix ? `${data.prefix}: ` : '';
53
- console.log(`${prefix}${getLogDataMessage(data)}`);
54
- });
55
- }
49
+ log: (data) => console.log(getLogDataMessage(data)),
50
+ logWithSpinnerAsync: async (func) => {
51
+ return await func((data) => {
52
+ const prefix = data.prefix ? `${data.prefix}: ` : "";
53
+ console.log(`${prefix}${getLogDataMessage(data)}`);
54
+ });
55
+ },
56
56
  };
57
57
 
58
58
  function getLogDataMessage(data: LogSpinnerMessage): string {
59
- if (!data.type) {
60
- return data.message;
61
- }
59
+ if (!data.type) {
60
+ return data.message;
61
+ }
62
62
 
63
- const color = match(data.type)
64
- .returnType<ChalkInstance>()
65
- .with('info', () => chalk.cyan)
66
- .with(P.union('error', 'errorData', 'warning', 'cancel'), () => chalk.red)
67
- .with('completed', () => chalk.green)
68
- .with('skip', () => chalk.gray)
69
- .otherwise(() => chalk.yellow);
63
+ const color = match(data.type)
64
+ .returnType<ChalkInstance>()
65
+ .with("info", () => chalk.cyan)
66
+ .with(P.union("error", "errorData", "warning", "cancel"), () => chalk.red)
67
+ .with("completed", () => chalk.green)
68
+ .with("skip", () => chalk.gray)
69
+ .otherwise(() => chalk.yellow);
70
70
 
71
- return `${color(data.type)}: ${data.message}`;
71
+ return `${color(data.type)}: ${data.message}`;
72
72
  }