@kontent-ai/migration-toolkit 1.0.1 → 1.2.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 (55) hide show
  1. package/README.md +1 -1
  2. package/dist/es2022/core/index.d.ts +1 -0
  3. package/dist/es2022/core/index.js +1 -0
  4. package/dist/es2022/core/index.js.map +1 -1
  5. package/dist/es2022/core/logs/loggers.js +1 -4
  6. package/dist/es2022/core/logs/loggers.js.map +1 -1
  7. package/dist/es2022/core/models/core.models.d.ts +9 -10
  8. package/dist/es2022/core/models/log.models.d.ts +2 -2
  9. package/dist/es2022/core/models/migration.models.d.ts +47 -133
  10. package/dist/es2022/core/models/migration.schema.d.ts +1240 -0
  11. package/dist/es2022/core/models/migration.schema.js +113 -0
  12. package/dist/es2022/core/models/migration.schema.js.map +1 -0
  13. package/dist/es2022/core/utils/confirm.utils.js +3 -3
  14. package/dist/es2022/core/utils/confirm.utils.js.map +1 -1
  15. package/dist/es2022/core/utils/error.utils.js +8 -2
  16. package/dist/es2022/core/utils/error.utils.js.map +1 -1
  17. package/dist/es2022/core/utils/global.utils.d.ts +4 -1
  18. package/dist/es2022/core/utils/global.utils.js +1 -3
  19. package/dist/es2022/core/utils/global.utils.js.map +1 -1
  20. package/dist/es2022/export/context/export-context-fetcher.js +11 -7
  21. package/dist/es2022/export/context/export-context-fetcher.js.map +1 -1
  22. package/dist/es2022/export/export-manager.js +3 -3
  23. package/dist/es2022/export/export-manager.js.map +1 -1
  24. package/dist/es2022/import/import-manager.js.map +1 -1
  25. package/dist/es2022/metadata.js +2 -2
  26. package/dist/es2022/node/cli/actions/export-action.js +2 -2
  27. package/dist/es2022/node/cli/actions/export-action.js.map +1 -1
  28. package/dist/es2022/node/cli/actions/import-action.js +2 -2
  29. package/dist/es2022/node/cli/actions/import-action.js.map +1 -1
  30. package/dist/es2022/toolkit/file.js +3 -3
  31. package/dist/es2022/toolkit/file.js.map +1 -1
  32. package/dist/es2022/translation/transforms/export-transforms.js.map +1 -1
  33. package/dist/es2022/zip/zip-transformer.js +9 -6
  34. package/dist/es2022/zip/zip-transformer.js.map +1 -1
  35. package/dist/es2022/zip/zip.models.d.ts +1 -1
  36. package/lib/core/index.ts +1 -0
  37. package/lib/core/logs/loggers.ts +1 -6
  38. package/lib/core/models/core.models.ts +11 -17
  39. package/lib/core/models/log.models.ts +7 -4
  40. package/lib/core/models/migration.models.ts +78 -158
  41. package/lib/core/models/migration.schema.ts +178 -0
  42. package/lib/core/utils/confirm.utils.ts +4 -4
  43. package/lib/core/utils/error.utils.ts +9 -6
  44. package/lib/core/utils/global.utils.ts +3 -3
  45. package/lib/export/context/export-context-fetcher.ts +23 -55
  46. package/lib/export/export-manager.ts +16 -20
  47. package/lib/import/import-manager.ts +2 -6
  48. package/lib/metadata.ts +2 -2
  49. package/lib/node/cli/actions/export-action.ts +2 -2
  50. package/lib/node/cli/actions/import-action.ts +2 -2
  51. package/lib/toolkit/file.ts +3 -9
  52. package/lib/translation/transforms/export-transforms.ts +1 -4
  53. package/lib/zip/zip-transformer.ts +25 -11
  54. package/lib/zip/zip.models.ts +1 -1
  55. package/package.json +10 -9
@@ -62,10 +62,9 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
62
62
  return await runMapiRequestAsync({
63
63
  logger: config.logger,
64
64
  logSpinner: logSpinner,
65
- func: async () =>
66
- (
67
- await config.managementClient.viewContentItem().byItemCodename(sourceItem.itemCodename).toPromise()
68
- ).data,
65
+ func: async () => {
66
+ return (await config.managementClient.viewContentItem().byItemCodename(sourceItem.itemCodename).toPromise()).data;
67
+ },
69
68
  action: 'view',
70
69
  type: 'contentItem',
71
70
  itemName: `codename -> ${sourceItem.itemCodename}`
@@ -79,26 +78,24 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
79
78
  return await runMapiRequestAsync({
80
79
  logger: config.logger,
81
80
  logSpinner: logSpinner,
82
- func: async () =>
83
- (
81
+ func: async () => {
82
+ return (
84
83
  await config.managementClient
85
84
  .viewLanguageVariant()
86
85
  .byItemCodename(sourceItem.itemCodename)
87
86
  .byLanguageCodename(sourceItem.languageCodename)
88
87
  .toPromise()
89
- ).data,
88
+ ).data;
89
+ },
90
+
90
91
  action: 'view',
91
92
  type: 'languageVariant',
92
93
  itemName: `codename -> ${sourceItem.itemCodename} -> latest (${sourceItem.languageCodename})`
93
94
  });
94
95
  };
95
96
 
96
- const isLanguageVariantPublished = (
97
- languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>
98
- ): boolean => {
99
- return environmentData.workflows.find(
100
- (workflow) => workflow.publishedStep.id === languageVariant.workflow.stepIdentifier.id
101
- )
97
+ const isLanguageVariantPublished = (languageVariant: Readonly<LanguageVariantModels.ContentItemLanguageVariant>): boolean => {
98
+ return environmentData.workflows.find((workflow) => workflow.publishedStep.id === languageVariant.workflow.stepIdentifier.id)
102
99
  ? true
103
100
  : false;
104
101
  };
@@ -185,10 +182,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
185
182
  environmentData.collections,
186
183
  (collection) => collection.id === data.contentItem.collection.id,
187
184
  () => {
188
- throwErrorForItemRequest(
189
- data.sourceItem,
190
- `Invalid collection '${chalk.yellow(data.contentItem.collection.id ?? '')}'`
191
- );
185
+ throwErrorForItemRequest(data.sourceItem, `Invalid collection '${chalk.yellow(data.contentItem.collection.id ?? '')}'`);
192
186
  }
193
187
  );
194
188
 
@@ -196,10 +190,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
196
190
  environmentData.contentTypes,
197
191
  (contentType) => contentType.contentTypeId === data.contentItem.type.id,
198
192
  () => {
199
- throwErrorForItemRequest(
200
- data.sourceItem,
201
- `Invalid content type '${chalk.red(data.contentItem.type.id)}'`
202
- );
193
+ throwErrorForItemRequest(data.sourceItem, `Invalid content type '${chalk.red(data.contentItem.type.id)}'`);
203
194
  }
204
195
  );
205
196
 
@@ -207,10 +198,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
207
198
  environmentData.languages,
208
199
  (language) => language.id === data.languageVariant.language.id,
209
200
  () => {
210
- throwErrorForItemRequest(
211
- data.sourceItem,
212
- `Invalid language '${chalk.red(data.languageVariant.language.id ?? '')}'`
213
- );
201
+ throwErrorForItemRequest(data.sourceItem, `Invalid language '${chalk.red(data.languageVariant.language.id ?? '')}'`);
214
202
  }
215
203
  );
216
204
 
@@ -239,9 +227,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
239
227
  };
240
228
  };
241
229
 
242
- const prepareExportItemsAsync = async (
243
- exportItems: readonly SourceExportItem[]
244
- ): Promise<readonly ExportItem[]> => {
230
+ const prepareExportItemsAsync = async (exportItems: readonly SourceExportItem[]): Promise<readonly ExportItem[]> => {
245
231
  config.logger.log({
246
232
  type: 'info',
247
233
  message: `Preparing '${chalk.yellow(config.exportItems.length.toString())}' items for export`
@@ -254,7 +240,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
254
240
  itemInfo: (input) => {
255
241
  return {
256
242
  title: `${input.itemCodename} (${input.languageCodename})`,
257
- itemType: 'exportedItem'
243
+ itemType: 'exportItem'
258
244
  };
259
245
  },
260
246
  items: exportItems,
@@ -287,9 +273,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
287
273
  });
288
274
  };
289
275
 
290
- const getContentItemsByIdsAsync = async (
291
- itemIds: ReadonlySet<string>
292
- ): Promise<readonly Readonly<ContentItemModels.ContentItem>[]> => {
276
+ const getContentItemsByIdsAsync = async (itemIds: ReadonlySet<string>): Promise<readonly Readonly<ContentItemModels.ContentItem>[]> => {
293
277
  return (
294
278
  await processItemsAsync<string, Readonly<ContentItemModels.ContentItem> | undefined>({
295
279
  logger: config.logger,
@@ -307,10 +291,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
307
291
  return await runMapiRequestAsync({
308
292
  logSpinner: logSpinner,
309
293
  logger: config.logger,
310
- func: async () =>
311
- (
312
- await config.managementClient.viewContentItem().byItemId(id).toPromise()
313
- ).data,
294
+ func: async () => (await config.managementClient.viewContentItem().byItemId(id).toPromise()).data,
314
295
  action: 'view',
315
296
  type: 'contentItem',
316
297
  itemName: `id -> ${id}`
@@ -327,9 +308,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
327
308
  ).filter(isNotUndefined);
328
309
  };
329
310
 
330
- const getAssetsByIdsAsync = async (
331
- itemIds: ReadonlySet<string>
332
- ): Promise<readonly Readonly<AssetModels.Asset>[]> => {
311
+ const getAssetsByIdsAsync = async (itemIds: ReadonlySet<string>): Promise<readonly Readonly<AssetModels.Asset>[]> => {
333
312
  return (
334
313
  await processItemsAsync<string, Readonly<AssetModels.Asset> | undefined>({
335
314
  logger: config.logger,
@@ -347,10 +326,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
347
326
  return await runMapiRequestAsync({
348
327
  logger: config.logger,
349
328
  logSpinner: logSpinner,
350
- func: async () =>
351
- (
352
- await config.managementClient.viewAsset().byAssetId(id).toPromise()
353
- ).data,
329
+ func: async () => (await config.managementClient.viewAsset().byAssetId(id).toPromise()).data,
354
330
  action: 'view',
355
331
  type: 'asset',
356
332
  itemName: `id -> ${id}`
@@ -367,9 +343,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
367
343
  ).filter(isNotUndefined);
368
344
  };
369
345
 
370
- const getItemStatesAsync = async (
371
- itemIds: ReadonlySet<string>
372
- ): Promise<readonly ItemStateInSourceEnvironmentById[]> => {
346
+ const getItemStatesAsync = async (itemIds: ReadonlySet<string>): Promise<readonly ItemStateInSourceEnvironmentById[]> => {
373
347
  const items = await getContentItemsByIdsAsync(itemIds);
374
348
 
375
349
  return Array.from(itemIds).map<ItemStateInSourceEnvironmentById>((itemId) => {
@@ -382,9 +356,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
382
356
  });
383
357
  };
384
358
 
385
- const getAssetStatesAsync = async (
386
- assetIds: ReadonlySet<string>
387
- ): Promise<readonly AssetStateInSourceEnvironmentById[]> => {
359
+ const getAssetStatesAsync = async (assetIds: ReadonlySet<string>): Promise<readonly AssetStateInSourceEnvironmentById[]> => {
388
360
  const assets = await getAssetsByIdsAsync(assetIds);
389
361
 
390
362
  return Array.from(assetIds).map<AssetStateInSourceEnvironmentById>((assetId) => {
@@ -408,9 +380,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
408
380
  const element = findRequired(
409
381
  contentType.elements,
410
382
  (element) => element.id === elementId,
411
- `Could not find element with id '${chalk.red(elementId)}' in content type '${chalk.red(
412
- contentType.contentTypeCodename
413
- )}'`
383
+ `Could not find element with id '${chalk.red(elementId)}' in content type '${chalk.red(contentType.contentTypeCodename)}'`
414
384
  );
415
385
 
416
386
  return element;
@@ -454,9 +424,7 @@ export async function exportContextFetcherAsync(config: DefaultExportContextConf
454
424
  findRequired(
455
425
  assetStates,
456
426
  (m) => m.id === id,
457
- `Invalid state for asset '${chalk.red(
458
- id
459
- )}'. It is expected that all asset states will be initialized`
427
+ `Invalid state for asset '${chalk.red(id)}'. It is expected that all asset states will be initialized`
460
428
  ),
461
429
  getItemStateInSourceEnvironment: (id) =>
462
430
  findRequired(
@@ -16,7 +16,10 @@ import {
16
16
  isNotUndefined,
17
17
  MigrationElementValue,
18
18
  getMigrationManagementClient,
19
- findRequired
19
+ findRequired,
20
+ Writeable,
21
+ MigrationItemsSchema,
22
+ MigrationAssetsSchema
20
23
  } from '../core/index.js';
21
24
  import { exportTransforms } from '../translation/index.js';
22
25
  import { exportContextFetcherAsync } from './context/export-context-fetcher.js';
@@ -61,11 +64,7 @@ export function exportManager(config: ExportConfig) {
61
64
  const componentType = context.environmentData.contentTypes.find((m) => m.contentTypeId === component.type.id);
62
65
 
63
66
  if (!componentType) {
64
- throw Error(
65
- `Could not find content type with id '${chalk.red(component.type.id)}' for component '${chalk.red(
66
- component.id
67
- )}'`
68
- );
67
+ throw Error(`Could not find content type with id '${chalk.red(component.type.id)}' for component '${chalk.red(component.id)}'`);
69
68
  }
70
69
 
71
70
  const migrationItem: MigrationComponent = {
@@ -96,7 +95,7 @@ export function exportManager(config: ExportConfig) {
96
95
  }
97
96
  return 0;
98
97
  })
99
- .reduce<MigrationElements>((model, typeElement) => {
98
+ .reduce<Writeable<MigrationElements>>((model, typeElement) => {
100
99
  const itemElement = findRequired(
101
100
  elements,
102
101
  (m) => m.element.id === typeElement.id,
@@ -128,9 +127,7 @@ export function exportManager(config: ExportConfig) {
128
127
  context: data.context,
129
128
  typeElement: data.typeElement,
130
129
  exportElement: {
131
- components: data.exportElement.components.map((component) =>
132
- mapToMigrationComponent(data.context, component)
133
- ),
130
+ components: data.exportElement.components.map((component) => mapToMigrationComponent(data.context, component)),
134
131
  value: data.exportElement.value,
135
132
  urlSlugMode: data.exportElement.mode
136
133
  }
@@ -155,9 +152,7 @@ export function exportManager(config: ExportConfig) {
155
152
 
156
153
  const exportAssetsAsync = async (context: ExportContext): Promise<readonly Readonly<MigrationAsset>[]> => {
157
154
  const assets = Array.from(context.referencedData.assetIds)
158
- .map<Readonly<AssetModels.Asset> | undefined>(
159
- (assetId) => context.getAssetStateInSourceEnvironment(assetId).asset
160
- )
155
+ .map<Readonly<AssetModels.Asset> | undefined>((assetId) => context.getAssetStateInSourceEnvironment(assetId).asset)
161
156
  .filter(isNotUndefined);
162
157
 
163
158
  return await getMigrationAssetsWithBinaryDataAsync(assets, context);
@@ -184,8 +179,9 @@ export function exportManager(config: ExportConfig) {
184
179
  },
185
180
  items: assets,
186
181
  processAsync: async (asset, logSpinner) => {
187
- const assetCollection: Readonly<CollectionModels.Collection> | undefined =
188
- context.environmentData.collections.find((m) => m.id === asset.collection?.reference?.id);
182
+ const assetCollection: Readonly<CollectionModels.Collection> | undefined = context.environmentData.collections.find(
183
+ (m) => m.id === asset.collection?.reference?.id
184
+ );
189
185
 
190
186
  logSpinner({
191
187
  type: 'download',
@@ -204,9 +200,9 @@ export function exportManager(config: ExportConfig) {
204
200
  const language = findRequired(
205
201
  context.environmentData.languages,
206
202
  (language) => language.id === description.language.id,
207
- `Could not find language with id '${chalk.red(
208
- description.language.id
209
- )}' requested by asset '${chalk.red(asset.codename)}'`
203
+ `Could not find language with id '${chalk.red(description.language.id)}' requested by asset '${chalk.red(
204
+ asset.codename
205
+ )}'`
210
206
  );
211
207
 
212
208
  return {
@@ -234,8 +230,8 @@ export function exportManager(config: ExportConfig) {
234
230
  ).getExportContextAsync();
235
231
 
236
232
  const migrationData: MigrationData = {
237
- items: getMigrationItems(exportContext),
238
- assets: await exportAssetsAsync(exportContext)
233
+ items: MigrationItemsSchema.parse(getMigrationItems(exportContext)),
234
+ assets: MigrationAssetsSchema.parse(await exportAssetsAsync(exportContext))
239
235
  };
240
236
 
241
237
  logger.log({
@@ -11,9 +11,7 @@ export function importManager(config: ImportConfig) {
11
11
  const logger: Logger = config.logger ?? getDefaultLogger();
12
12
  const targetEnvironmentClient: ManagementClient = getMigrationManagementClient(config);
13
13
 
14
- const importAssetsAsync = async (
15
- importContext: ImportContext
16
- ): Promise<Pick<ImportResult, 'editedAssets' | 'uploadedAssets'>> => {
14
+ const importAssetsAsync = async (importContext: ImportContext): Promise<Pick<ImportResult, 'editedAssets' | 'uploadedAssets'>> => {
17
15
  if (!importContext.categorizedImportData.assets.length) {
18
16
  logger.log({
19
17
  type: 'info',
@@ -31,9 +29,7 @@ export function importManager(config: ImportConfig) {
31
29
  logger: logger
32
30
  }).importAsync();
33
31
  };
34
- const importContentItemsAsync = async (
35
- importContext: ImportContext
36
- ): Promise<readonly Readonly<ContentItemModels.ContentItem>[]> => {
32
+ const importContentItemsAsync = async (importContext: ImportContext): Promise<readonly Readonly<ContentItemModels.ContentItem>[]> => {
37
33
  if (!importContext.categorizedImportData.contentItems.length) {
38
34
  logger.log({
39
35
  type: 'info',
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: 'Wed, 10 Jul 2024 11:27:45 GMT',
5
- version: '1.0.1'
4
+ timestamp: 'Thu, 18 Jul 2024 09:58:42 GMT',
5
+ version: '1.2.0'
6
6
  };
@@ -1,4 +1,4 @@
1
- import { confirmExportAsync, getDefaultZipFilename, getDefaultLogger } from '../../../core/index.js';
1
+ import { confirmExportAsync, defaultZipFilename, getDefaultLogger } from '../../../core/index.js';
2
2
  import { exportAsync, storeAsync } from '../../../toolkit/index.js';
3
3
  import { CliArgumentsFetcher } from '../cli.models.js';
4
4
 
@@ -10,7 +10,7 @@ export async function exportActionAsync(cliFetcher: CliArgumentsFetcher): Promis
10
10
  const items = cliFetcher.getRequiredArgumentValue('items').split(',');
11
11
  const baseUrl = cliFetcher.getOptionalArgumentValue('baseUrl');
12
12
  const force = cliFetcher.getBooleanArgumentValue('force', false);
13
- const filename = cliFetcher.getOptionalArgumentValue('filename') ?? getDefaultZipFilename();
13
+ const filename = cliFetcher.getOptionalArgumentValue('filename') ?? defaultZipFilename;
14
14
 
15
15
  await confirmExportAsync({
16
16
  force: force,
@@ -1,4 +1,4 @@
1
- import { confirmImportAsync, getDefaultZipFilename, getDefaultLogger } from '../../../core/index.js';
1
+ import { confirmImportAsync, defaultZipFilename, getDefaultLogger } from '../../../core/index.js';
2
2
  import { extractAsync, importAsync } from '../../../toolkit/index.js';
3
3
  import { CliArgumentsFetcher } from '../cli.models.js';
4
4
 
@@ -8,7 +8,7 @@ export async function importActionAsync(argsFetcher: CliArgumentsFetcher): Promi
8
8
  const apiKey = argsFetcher.getRequiredArgumentValue('targetApiKey');
9
9
  const baseUrl = argsFetcher.getOptionalArgumentValue('baseUrl');
10
10
  const force = argsFetcher.getBooleanArgumentValue('force', false);
11
- const filename = argsFetcher.getOptionalArgumentValue('filename') ?? getDefaultZipFilename();
11
+ const filename = argsFetcher.getOptionalArgumentValue('filename') ?? defaultZipFilename;
12
12
 
13
13
  await confirmImportAsync({
14
14
  force: force,
@@ -1,11 +1,5 @@
1
1
  import { fileManager } from '../file/index.js';
2
- import {
3
- Logger,
4
- executeWithTrackingAsync,
5
- getDefaultZipFilename,
6
- getDefaultLogger,
7
- MigrationData
8
- } from '../core/index.js';
2
+ import { Logger, executeWithTrackingAsync, defaultZipFilename, getDefaultLogger, MigrationData } from '../core/index.js';
9
3
  import { zipManager } from '../zip/index.js';
10
4
  import { libMetadata } from '../metadata.js';
11
5
 
@@ -22,7 +16,7 @@ export interface ExtractConfig {
22
16
 
23
17
  export async function storeAsync(config: StoreConfig): Promise<void> {
24
18
  const logger = config.logger ?? getDefaultLogger();
25
- const filename: string = getDefaultZipFilename();
19
+ const filename = config.filename ?? defaultZipFilename;
26
20
 
27
21
  await executeWithTrackingAsync<void>({
28
22
  event: {
@@ -49,7 +43,7 @@ export async function storeAsync(config: StoreConfig): Promise<void> {
49
43
 
50
44
  export async function extractAsync(config: ExtractConfig): Promise<MigrationData> {
51
45
  const logger = config.logger ?? getDefaultLogger();
52
- const filename: string = getDefaultZipFilename();
46
+ const filename = config.filename ?? defaultZipFilename;
53
47
 
54
48
  return await executeWithTrackingAsync({
55
49
  event: {
@@ -175,10 +175,7 @@ export const exportTransforms: Readonly<Record<MigrationElementType, ExportTrans
175
175
  }
176
176
  };
177
177
 
178
- function findTaxonomy(
179
- termId: string,
180
- taxonomy: Readonly<TaxonomyModels.Taxonomy>
181
- ): Readonly<TaxonomyModels.Taxonomy> | undefined {
178
+ function findTaxonomy(termId: string, taxonomy: Readonly<TaxonomyModels.Taxonomy>): Readonly<TaxonomyModels.Taxonomy> | undefined {
182
179
  if (taxonomy.id === termId) {
183
180
  return taxonomy;
184
181
  }
@@ -1,10 +1,19 @@
1
- import { FileBinaryData, ZipPackager } from './zip.models.js';
2
- import { Logger, MigrationAsset, MigrationData, MigrationItem, getDefaultLogger, mapAsync } from '../core/index.js';
3
1
  import chalk from 'chalk';
4
-
5
- type ZipAssetRecord = Omit<MigrationAsset, 'binaryData'> & {
6
- _zipFilename: string;
7
- };
2
+ import { z } from 'zod';
3
+ import { FileBinaryData, ZipPackager } from './zip.models.js';
4
+ import {
5
+ Logger,
6
+ MigrationAsset,
7
+ MigrationData,
8
+ MigrationItem,
9
+ MigrationItemsSchema,
10
+ ZipMigrationAssetSchema,
11
+ ZipMigrationAssetsSchema,
12
+ getDefaultLogger,
13
+ mapAsync
14
+ } from '../core/index.js';
15
+
16
+ type ZipAssetRecord = z.infer<typeof ZipMigrationAssetSchema>;
8
17
 
9
18
  export function zipTransformer(zip: ZipPackager, logger?: Logger) {
10
19
  const loggerToUse: Logger = logger ?? getDefaultLogger();
@@ -51,18 +60,23 @@ export function zipTransformer(zip: ZipPackager, logger?: Logger) {
51
60
  };
52
61
 
53
62
  const parseItems = async () => {
54
- const fileContent = await zip.getFileContentAsync(filename);
55
- return fileContent ? (JSON.parse(fileContent) as MigrationItem[]) : [];
63
+ const content = await zip.getFileContentAsync(filename);
64
+
65
+ if (!content) {
66
+ return [];
67
+ }
68
+
69
+ return MigrationItemsSchema.parse(JSON.parse(content));
56
70
  };
57
71
 
58
72
  const parseAssets = async () => {
59
- const text = await zip.getFileContentAsync(assetsFilename);
73
+ const content = await zip.getFileContentAsync(assetsFilename);
60
74
 
61
- if (!text) {
75
+ if (!content) {
62
76
  return [];
63
77
  }
64
78
 
65
- const assetRecords = JSON.parse(text) as ZipAssetRecord[];
79
+ const assetRecords = ZipMigrationAssetsSchema.parse(JSON.parse(content));
66
80
 
67
81
  return await mapAsync(assetRecords, async (assetRecord) => {
68
82
  const binaryFile = await zip.getBinaryDataAsync(`${assetRecord._zipFilename}`);
@@ -4,7 +4,7 @@ export type FileBinaryData = Buffer | Blob;
4
4
  export type ZipCompressionLevel = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
5
5
 
6
6
  export type ZipPackager = {
7
- addFile(filePath: string, data: string | Blob | Buffer): void;
7
+ addFile(filePath: string, data: string | FileBinaryData): void;
8
8
  addFolder(name: string): ZipPackager;
9
9
  generateZipAsync(config: { logger?: Logger; compressionLevel?: ZipCompressionLevel }): Promise<FileBinaryData>;
10
10
  getBinaryDataAsync(filePath: string): Promise<FileBinaryData | undefined>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontent-ai/migration-toolkit",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "This program can be used to import content related data into Kontent.ai from various formats. Additionally, it can also be used to export Kontent.ai data using Delivery API.",
5
5
  "preferGlobal": true,
6
6
  "private": false,
@@ -59,29 +59,30 @@
59
59
  "chalk": "5.3.0",
60
60
  "dotenv": "16.4.5",
61
61
  "jszip": "3.10.1",
62
- "mime": "4.0.3",
62
+ "mime": "4.0.4",
63
63
  "ora": "8.0.1",
64
64
  "prompts": "2.4.2",
65
65
  "yargs": "17.7.2",
66
- "p-limit": "5.0.0",
67
- "deep-equal": "2.2.3"
66
+ "p-limit": "6.1.0",
67
+ "deep-equal": "2.2.3",
68
+ "zod": "3.23.8"
68
69
  },
69
70
  "devDependencies": {
70
- "@eslint/js": "9.6.0",
71
+ "@eslint/js": "9.7.0",
71
72
  "@types/deep-equal": "1.0.4",
72
73
  "@types/browser-or-node": "1.3.2",
73
74
  "@types/bytes": "3.1.4",
74
75
  "@types/eslint__js": "8.42.3",
75
- "@types/node": "20.14.9",
76
+ "@types/node": "20.14.11",
76
77
  "@types/prompts": "2.4.9",
77
78
  "@types/yargs": "17.0.32",
78
- "@typescript-eslint/eslint-plugin": "7.15.0",
79
- "@typescript-eslint/parser": "7.15.0",
79
+ "@typescript-eslint/eslint-plugin": "7.16.1",
80
+ "@typescript-eslint/parser": "7.16.1",
80
81
  "eslint": "8.57.0",
81
82
  "standard-version": "9.5.0",
82
83
  "tslib": "2.6.3",
83
84
  "tsx": "4.16.2",
84
85
  "typescript": "5.5.3",
85
- "typescript-eslint": "7.15.0"
86
+ "typescript-eslint": "7.16.1"
86
87
  }
87
88
  }