Skip to content

Commit 4f99b26

Browse files
author
naman-contentstack
committed
chore: optimise the code
1 parent 2ef8e3a commit 4f99b26

File tree

7 files changed

+114
-140
lines changed

7 files changed

+114
-140
lines changed

.talismanrc

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
fileignoreconfig:
2-
- filename: packages/contentstack-asset-management/src/export/base.ts
3-
checksum: 01cb2158fea9cbe05449c04efb42d8d416d24868d411bd7300d8fa99c9a4ab01
4-
- filename: packages/contentstack-asset-management/test/unit/export/base.test.ts
5-
checksum: 164fc2e5a4337a2739903499b66eecc66a85bb9b50aa2e71079bdd046a195a94
6-
- filename: packages/contentstack-asset-management/src/import/fields.ts
7-
checksum: 1cd52254ddbfd186d8ade2c73fc799dd1caa0f10bdd3c6b151621c27207ee173
8-
- filename: packages/contentstack-import/src/utils/asset-management-import-options.ts
9-
checksum: 96b61b683109be2cc2dbab5231e1ded19282fbf176cd8492c75cc4861f2efea0
10-
- filename: packages/contentstack-asset-management/src/import/asset-types.ts
11-
checksum: fa2aeea704fd259628f9c86eacd3cf9f6f12543b06b387bd65db7df6b6f5fc49
2+
- filename: packages/contentstack-asset-management/src/import/spaces.ts
3+
checksum: e972d66f6a889f72d72ba48112a12f9447de39285cfb568d3b99a4969cf9f5f9
124
version: '1.0'

packages/contentstack-asset-management/src/import/spaces.ts

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { resolve as pResolve, join } from 'node:path';
1+
import { join, resolve as pResolve } from 'node:path';
22
import { mkdirSync, readdirSync, statSync } from 'node:fs';
33
import { writeFile } from 'node:fs/promises';
44
import { log, CLIProgressManager, configHandler } from '@contentstack/cli-utilities';
55

66
import type {
77
AssetManagementAPIConfig,
8-
AssetManagementImportOptions,
98
ImportContext,
109
ImportResult,
10+
ImportSpacesOptions,
1111
SpaceMapping,
1212
} from '../types/asset-management-api';
1313
import { AM_MAIN_PROCESS_NAME } from '../constants/index';
@@ -22,11 +22,11 @@ import ImportWorkspace from './workspaces';
2222
* Returns combined uidMap, urlMap, and spaceMappings for the bridge module.
2323
*/
2424
export class ImportSpaces {
25-
private readonly options: AssetManagementImportOptions;
25+
private readonly options: ImportSpacesOptions;
2626
private parentProgressManager: CLIProgressManager | null = null;
2727
private progressManager: CLIProgressManager | null = null;
2828

29-
constructor(options: AssetManagementImportOptions) {
29+
constructor(options: ImportSpacesOptions) {
3030
this.options = options;
3131
}
3232

@@ -35,63 +35,37 @@ export class ImportSpaces {
3535
}
3636

3737
async start(): Promise<ImportResult> {
38-
const {
39-
contentDir,
40-
assetManagementUrl,
41-
org_uid,
42-
apiKey,
43-
host,
44-
sourceApiKey,
45-
context,
46-
apiConcurrency,
47-
uploadAssetsConcurrency,
48-
importFoldersConcurrency,
49-
spacesDirName,
50-
fieldsDir,
51-
assetTypesDir,
52-
fieldsFileName,
53-
assetTypesFileName,
54-
foldersFileName,
55-
assetsFileName,
56-
fieldsImportInvalidKeys,
57-
assetTypesImportInvalidKeys,
58-
mapperRootDir,
59-
mapperAssetsModuleDir,
60-
mapperUidFileName,
61-
mapperUrlFileName,
62-
mapperSpaceUidFileName,
63-
} = this.options;
64-
65-
const spacesRootPath = pResolve(contentDir, spacesDirName ?? 'spaces');
66-
38+
const configOptions = this.options;
39+
const spacesRootPath = pResolve(configOptions.contentDir, 'spaces');
40+
const org_uid = configOptions.org_uid;
41+
const context = configOptions.context;
6742
const importContext: ImportContext = {
6843
spacesRootPath,
69-
sourceApiKey,
70-
apiKey,
71-
host,
44+
sourceApiKey: configOptions.sourceApiKey,
45+
apiKey: configOptions.apiKey,
46+
host: configOptions.host,
7247
org_uid,
7348
context,
74-
apiConcurrency,
75-
uploadAssetsConcurrency,
76-
importFoldersConcurrency,
77-
spacesDirName,
78-
fieldsDir,
79-
assetTypesDir,
80-
fieldsFileName,
81-
assetTypesFileName,
82-
foldersFileName,
83-
assetsFileName,
84-
fieldsImportInvalidKeys,
85-
assetTypesImportInvalidKeys,
86-
mapperRootDir,
87-
mapperAssetsModuleDir,
88-
mapperUidFileName,
89-
mapperUrlFileName,
90-
mapperSpaceUidFileName,
49+
apiConcurrency: configOptions.apiConcurrency,
50+
uploadAssetsConcurrency: configOptions.uploadAssetsConcurrency,
51+
importFoldersConcurrency: configOptions.importFoldersConcurrency,
52+
spacesDirName: configOptions.spacesDirName,
53+
fieldsDir: configOptions.fieldsDir,
54+
assetTypesDir: configOptions.assetTypesDir,
55+
fieldsFileName: configOptions.fieldsFileName,
56+
assetTypesFileName: configOptions.assetTypesFileName,
57+
foldersFileName: configOptions.foldersFileName,
58+
assetsFileName: configOptions.assetsFileName,
59+
fieldsImportInvalidKeys: configOptions.fieldsImportInvalidKeys,
60+
assetTypesImportInvalidKeys: configOptions.assetTypesImportInvalidKeys,
61+
mapperRootDir: configOptions.mapperRootDir,
62+
mapperAssetsModuleDir: configOptions.mapperAssetsModuleDir,
63+
mapperUidFileName: configOptions.mapperUidFileName,
64+
mapperUrlFileName: configOptions.mapperUrlFileName,
65+
mapperSpaceUidFileName: configOptions.mapperSpaceUidFileName,
9166
};
92-
9367
const apiConfig: AssetManagementAPIConfig = {
94-
baseURL: assetManagementUrl,
68+
baseURL: configOptions.assetManagementUrl,
9569
headers: { organization_uid: org_uid },
9670
context,
9771
};
@@ -186,13 +160,13 @@ export class ImportSpaces {
186160
}
187161

188162
if (this.options.backupDir) {
189-
const mapperRoot = this.options.mapperRootDir ?? 'mapper';
190-
const mapperAssetsMod = this.options.mapperAssetsModuleDir ?? 'assets';
163+
const mapperRoot = importContext.mapperRootDir ?? 'mapper';
164+
const mapperAssetsMod = importContext.mapperAssetsModuleDir ?? 'assets';
191165
const mapperDir = join(this.options.backupDir, mapperRoot, mapperAssetsMod);
192166
mkdirSync(mapperDir, { recursive: true });
193-
const uidFile = this.options.mapperUidFileName ?? 'uid-mapping.json';
194-
const urlFile = this.options.mapperUrlFileName ?? 'url-mapping.json';
195-
const spaceUidFile = this.options.mapperSpaceUidFileName ?? 'space-uid-mapping.json';
167+
const uidFile = importContext.mapperUidFileName ?? 'uid-mapping.json';
168+
const urlFile = importContext.mapperUrlFileName ?? 'url-mapping.json';
169+
const spaceUidFile = importContext.mapperSpaceUidFileName ?? 'space-uid-mapping.json';
196170
await writeFile(join(mapperDir, uidFile), JSON.stringify(allUidMap), 'utf8');
197171
await writeFile(join(mapperDir, urlFile), JSON.stringify(allUrlMap), 'utf8');
198172
await writeFile(join(mapperDir, spaceUidFile), JSON.stringify(allSpaceUidMap), 'utf8');

packages/contentstack-asset-management/src/types/asset-management-api.ts

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export type ImportContext = {
177177
context?: Record<string, unknown>;
178178
/**
179179
* Max parallel AM API calls for import (fields, asset types, and default for folders/uploads).
180-
* Set from `AssetManagementImportOptions.apiConcurrency`.
180+
* Set from `ImportSpacesOptions.apiConcurrency` (or host wiring).
181181
*/
182182
apiConcurrency?: number;
183183
/** Overrides parallel limit for asset uploads when set (import `modules['asset-management'].uploadAssetsConcurrency`). */
@@ -203,28 +203,21 @@ export type ImportContext = {
203203
};
204204

205205
/**
206-
* Options accepted by the top-level `ImportSpaces` class.
206+
* Single options object for `ImportSpaces` (matches the export-side pattern: one flat shape from the host,
207+
* then AM splits API vs context internally like `ExportSpaces`).
207208
*/
208-
export type AssetManagementImportOptions = {
209+
export type ImportSpacesOptions = {
209210
/** Absolute path to the root content / backup directory. */
210211
contentDir: string;
211212
/** AM 2.0 base URL (e.g. "https://am.contentstack.io"). */
212213
assetManagementUrl: string;
213-
/** Target organisation UID. */
214214
org_uid: string;
215-
/** Target stack API key. */
216215
apiKey: string;
217-
/** Target CMA host. */
218216
host: string;
219-
/** Source stack API key — used for old CMA proxy URL reconstruction. */
220217
sourceApiKey?: string;
221-
/** Optional logging context. */
222218
context?: Record<string, unknown>;
223-
/**
224-
* When set, mapper files are written under `{backupDir}/mapper/assets/` after import.
225-
*/
219+
/** When set, mapper JSON is written after import under `{backupDir}/mapper/...`. */
226220
backupDir?: string;
227-
/** Parallel AM API limit; defaults to package constant when omitted. */
228221
apiConcurrency?: number;
229222
uploadAssetsConcurrency?: number;
230223
importFoldersConcurrency?: number;
@@ -257,7 +250,7 @@ export type SpaceMapping = {
257250

258251
/**
259252
* The value returned by `ImportSpaces.start()`.
260-
* When `backupDir` is set on options, the AM package also writes these maps under
253+
* When `ImportSpacesOptions.backupDir` is set, the AM package also writes these maps under
261254
* `mapper/assets/` for `entries.ts` to resolve asset references.
262255
*/
263256
export type ImportResult = {

packages/contentstack-import/src/commands/cm/stacks/import.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ export default class ImportCommand extends Command {
124124
importConfig = await setupImportConfig(flags);
125125
// Prepare the context object
126126
createLogContext(
127-
this.context?.info?.command || 'cm:stacks:export',
127+
this.context?.info?.command || 'cm:stacks:import',
128128
importConfig.apiKey,
129-
importConfig.authenticationMethod
129+
importConfig.authenticationMethod,
130130
);
131131
const context = this.createImportContext(importConfig.apiKey, importConfig.authenticationMethod);
132132
importConfig.context = { ...context };

packages/contentstack-import/src/import/modules/assets.ts

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import includes from 'lodash/includes';
1010
import { v4 as uuid } from 'uuid';
1111
import { resolve as pResolve, join } from 'node:path';
1212
import { FsUtility, log, handleAndLogError } from '@contentstack/cli-utilities';
13-
import { ImportSpaces } from '@contentstack/cli-asset-management';
13+
import { ImportSpaces, type SpaceMapping } from '@contentstack/cli-asset-management';
1414
import { PATH_CONSTANTS } from '../../constants';
1515

1616
import config from '../../config';
1717
import { ModuleClassParams } from '../../types';
1818
import {
19-
buildAssetManagementImportOptions,
19+
buildImportSpacesOptions,
2020
formatDate,
2121
fsUtil,
2222
PROCESS_NAMES,
@@ -69,8 +69,7 @@ export default class ImportAssets extends BaseClass {
6969

7070
// AM 2.0: assetManagementEnabled is set in the config handler when spaces/ + am_v2 are detected.
7171
if (this.importConfig.assetManagementEnabled) {
72-
const assetManagementUrl = this.importConfig.assetManagementUrl;
73-
if (!assetManagementUrl) {
72+
if (!this.importConfig.assetManagementUrl) {
7473
log.info(
7574
'AM 2.0 export detected but assetManagementUrl is not configured in the region settings. Skipping AM 2.0 asset import.',
7675
this.importConfig.context,
@@ -79,54 +78,22 @@ export default class ImportAssets extends BaseClass {
7978
}
8079

8180
const progress = this.createNestedProgress(this.currentModuleName);
81+
let spaceMappings: SpaceMapping[] = [];
82+
8283
try {
83-
const importer = new ImportSpaces(buildAssetManagementImportOptions(this.importConfig, assetManagementUrl));
84+
const importer = new ImportSpaces(
85+
buildImportSpacesOptions(this.importConfig, this.importConfig.assetManagementUrl),
86+
);
8487
importer.setParentProgressManager(progress);
85-
86-
const { spaceMappings } = await importer.start();
87-
88-
// Link imported AM spaces to the target stack via CMA branch settings.
89-
if (spaceMappings.length > 0) {
90-
try {
91-
const branchUid = this.importConfig.branchName ?? 'main';
92-
93-
const branchData = (await this.stack.branch(branchUid).fetch({ include_settings: true })) as Record<
94-
string,
95-
any
96-
>;
97-
const currentLinked = (branchData?.settings?.am_v2?.linked_workspaces ?? []) as Array<{
98-
uid: string;
99-
space_uid: string;
100-
is_default: boolean;
101-
operation?: string;
102-
}>;
103-
104-
const newWorkspaces = spaceMappings.map(({ newSpaceUid, workspaceUid }) => ({
105-
uid: workspaceUid,
106-
space_uid: newSpaceUid,
107-
is_default: false,
108-
operation: 'LINK',
109-
}));
110-
111-
const combinedWorkspaces = [...currentLinked, ...newWorkspaces];
112-
113-
await this.stack.branch(branchUid).updateSettings({
114-
branch: { settings: { am_v2: { linked_workspaces: combinedWorkspaces } } },
115-
});
116-
log.success(
117-
`Linked ${newWorkspaces.length} space(s) to branch "${branchUid}"`,
118-
this.importConfig.context,
119-
);
120-
} catch (linkErr) {
121-
handleAndLogError(linkErr, { ...this.importConfig.context });
122-
}
123-
}
124-
125-
this.completeProgressWithMessage();
88+
({ spaceMappings } = await importer.start());
12689
} catch (error) {
12790
this.completeProgress(false, (error as Error)?.message ?? 'AM 2.0 asset import failed');
12891
throw error;
12992
}
93+
94+
await this.linkImportedAmSpacesToBranch(spaceMappings);
95+
96+
this.completeProgressWithMessage();
13097
return;
13198
}
13299
// Legacy flow continues below
@@ -191,6 +158,53 @@ export default class ImportAssets extends BaseClass {
191158
}
192159
}
193160

161+
/**
162+
* Merges imported AM spaces into the target stack branch's `am_v2.linked_workspaces`.
163+
* Errors are logged and swallowed so a successful import still completes; import failures are handled separately.
164+
*/
165+
private async linkImportedAmSpacesToBranch(spaceMappings: SpaceMapping[]): Promise<void> {
166+
if (spaceMappings.length === 0) {
167+
return;
168+
}
169+
170+
try {
171+
const branchUid = this.importConfig.branchName ?? 'main';
172+
173+
const branchData = (await this.stack.branch(branchUid).fetch({ include_settings: true })) as Record<
174+
string,
175+
any
176+
>;
177+
const currentLinked = (branchData?.settings?.am_v2?.linked_workspaces ?? []) as Array<{
178+
uid: string;
179+
space_uid: string;
180+
is_default: boolean;
181+
operation?: string;
182+
}>;
183+
184+
const newWorkspaces = spaceMappings.map(({ newSpaceUid, workspaceUid }) => ({
185+
uid: workspaceUid,
186+
space_uid: newSpaceUid,
187+
is_default: false,
188+
operation: 'LINK' as const,
189+
}));
190+
191+
const combinedWorkspaces = [...currentLinked, ...newWorkspaces];
192+
193+
await this.stack.branch(branchUid).updateSettings({
194+
branch: { settings: { am_v2: { linked_workspaces: combinedWorkspaces } } },
195+
});
196+
log.success(
197+
`Linked ${newWorkspaces.length} space(s) to branch "${branchUid}"`,
198+
this.importConfig.context,
199+
);
200+
} catch (linkErr) {
201+
handleAndLogError(linkErr, {
202+
...this.importConfig.context,
203+
phase: 'AM 2.0 branch linking (linked_workspaces)',
204+
});
205+
}
206+
}
207+
194208
/**
195209
* @method importFolders
196210
* @returns {Promise<any>} Promise<any>

packages/contentstack-import/src/utils/asset-management-import-options.ts renamed to packages/contentstack-import/src/utils/build-import-spaces-options.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import type { AssetManagementImportOptions } from '@contentstack/cli-asset-management';
1+
import type { ImportSpacesOptions } from '@contentstack/cli-asset-management';
22

33
import { PATH_CONSTANTS } from '../constants';
44
import type ImportConfig from '../types/import-config';
55

66
/**
7-
* Maps stack import config and resolved AM base URL into options for `ImportSpaces`.
8-
* Centralizes defaults (`PATH_CONSTANTS`) and field renames so `ImportAssets` stays thin.
7+
* Maps stack `ImportConfig` and AM base URL into a single `ImportSpacesOptions` for the AM package
8+
* (variants-style: one flat object; `ImportSpaces` splits API vs context internally).
99
*/
10-
export function buildAssetManagementImportOptions(
10+
export function buildImportSpacesOptions(
1111
importConfig: ImportConfig,
1212
assetManagementUrl: string,
13-
): AssetManagementImportOptions {
13+
): ImportSpacesOptions {
1414
const am = importConfig.modules['asset-management'];
15+
const org_uid = importConfig.org_uid ?? '';
1516

1617
return {
1718
contentDir: importConfig.contentDir,
1819
assetManagementUrl,
19-
org_uid: importConfig.org_uid ?? '',
20+
org_uid,
2021
apiKey: importConfig.apiKey,
2122
host: importConfig.region?.cma ?? importConfig.host ?? '',
2223
sourceApiKey: importConfig.source_stack,

0 commit comments

Comments
 (0)