Skip to content

Commit 36f8f8f

Browse files
author
naman-contentstack
committed
chore: resolve PR comments
1 parent 154a34d commit 36f8f8f

5 files changed

Lines changed: 57 additions & 121 deletions

File tree

.talismanrc

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,4 @@
11
fileignoreconfig:
2-
- filename: pnpm-lock.yaml
3-
checksum: 8eb82c59ad8b81af64587af55c6788d09a34d1b651d030d1ef01dce472716f2a
4-
- filename: packages/contentstack-branches/test/unit/helpers/stub-auth.ts
5-
checksum: 8cafd5994d3ec13ba9af74c80b330bfd14721ea4e0359b456598964a6c2913ce
6-
- filename: packages/contentstack-export/src/config/index.ts
7-
checksum: 0219426b1873decef4d74bef5bfd50d1ed8f2567a2136122d869e4e53e4b4b99
8-
- filename: packages/contentstack-clone/README.md
9-
checksum: fad666bf6290c980406ddd18caec2dd89d9c7a22b422010865199659956ab523
10-
- filename: packages/contentstack-migration/README.md
11-
checksum: ceb7631888ee81711a32e2ac07762957bbf0f9c6c7f3f6bbc5d86326bd4352cc
12-
- filename: packages/contentstack-external-migrate/test/commands/migrate/import.test.ts
13-
checksum: 1d955eb34ab7e7e11cfad35cdbcb00692e39568bc690f46089fcbc0ca22a4852
14-
- filename: packages/contentstack-external-migrate/test/adapters/contentful/export.test.ts
15-
checksum: 118cc140edf3b68191d1ef770c4142f9f5aa7af87a5a1832d6b3edee53d61c83
16-
- filename: packages/contentstack-cli-tsgen/test/unit/helper.test.ts
17-
checksum: 146ff2a85a8f5ec463e51821f54c5f08143fa04209541a51017270e83b6ed46d
18-
- filename: packages/contentstack-cli-cm-regex-validate/test/utils/connect-stack.test.ts
19-
checksum: 018980aa2b919967b9ef9ab1bdf635d4867fe21593fba5890afa443f440228ff
20-
- filename: packages/contentstack-bulk-operations/src/messages/index.ts
21-
checksum: ba38daefd561d9acd018b6ebcb65847eceab6d375b28988d7b5624dcea9ccfe0
22-
- filename: packages/contentstack-bulk-operations/src/utils/operation-flag-matrix.ts
23-
checksum: 99a3c3eb422a17f73f4c8f15088004fa4c95df3545bdf510310c1f3a20e4c2c2
24-
- filename: packages/contentstack-bulk-operations/src/base-bulk-command.ts
25-
checksum: cb1147ac666b607a093c4c827d143d0bd2de5b6e9d59973f1b7052451e82a89b
26-
- filename: packages/contentstack-bulk-operations/src/commands/cm/stacks/bulk-assets.ts
27-
checksum: 8bca423db4c3815c651ad922d986a53b6271cce3ea27f5987b66ee594151165e
28-
- filename: packages/contentstack-bulk-operations/test/unit/commands/bulk-assets-init.test.ts
29-
checksum: 590b1cfe42d46d0917ac90f363b1ccd05200b180bd9c58c770ffd1f12eb18327
30-
- filename: packages/contentstack-bulk-operations/test/unit/utils/operation-flag-matrix.test.ts
31-
checksum: 35451ca4c03359b06531a8461091f4a3a45c4dea1f8853081fb53e4ce28c1cc3
32-
- filename: packages/contentstack-bulk-operations/test/unit/base-bulk-command.test.ts
33-
checksum: ca699a9d73757d44ded4d9d27beb4f460f911a7c88a14551a9402a3ac0c69873
34-
- filename: packages/contentstack-external-migrate/src/lib/create-stack.ts
35-
checksum: 68a9510db6f2746ac5006c091d276c1ba619a9e15c76a3edae3967e4f9c2dd4e
36-
- filename: packages/contentstack-external-migrate/test/lib/create-stack.test.ts
37-
checksum: 2dcbc359ee275e59e0536f3c325416eac8c43eb341b04da0d3757f5b5e556d9c
38-
- filename: CHANGELOG.md
39-
checksum: 88c7e1dee308fa4ae25e7815ead0842b1aac7ed669b02859cc8b25cba879595d
40-
- filename: packages/contentstack-bulk-operations/test/unit/services/taxonomy-service.test.ts
41-
checksum: abc5ac707341760cf59d5b8b1c4e13cf2c79955e2735c33e2db3ec6bc48eddb6
42-
- filename: packages/contentstack-import/src/import/modules/assets.ts
43-
checksum: cda61a9c90bb39f27c09951b8a2623851296aefd0d3220d066032287a712d899
44-
- filename: packages/contentstack-asset-management/test/unit/utils/cs-assets-api-adapter.test.ts
45-
checksum: 63c6bff4d51842d8fa3cce88545259d0a2c3cfe71df95d303d993f692cee883b
2+
- filename: packages/contentstack-export/src/utils/export-config-handler.ts
3+
checksum: ab7fd2fb63420e7a66856abace57965c1e9aa1033fc18dc8b194cf1d306f0bab
464
version: '1.0'

packages/contentstack-export/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@
9090
"csdxConfig": {
9191
"shortCommandName": {
9292
"cm:stacks:export": "EXPRT"
93-
}
93+
},
94+
"planProtectedFeatures": [
95+
"amAssets"
96+
]
9497
},
9598
"repository": {
9699
"type": "git",

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

Lines changed: 12 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
import { PATH_CONSTANTS } from '../../constants';
2626

2727
import config from '../../config';
28-
import { ModuleClassParams } from '../../types';
28+
import { ModuleClassParams, GlobalSummary } from '../../types';
2929
import BaseClass, { CustomPromiseHandler, CustomPromiseHandlerInput } from './base-class';
3030
import { ExportSpaces, type AssetExportCounts } from '@contentstack/cli-asset-management';
3131
import {
@@ -38,23 +38,6 @@ import {
3838
} from '../../utils';
3939
import { handle } from '@oclif/core';
4040

41-
// cli-utilities' CLIProgressManager.globalSummary is runtime-accessible but typed private. These
42-
// shapes describe the slice we mutate; the single accessor (getGlobalSummary) owns the structural
43-
// cast + feature-detect so applyAssetSummaryCounts and markAssetsSkippedInSummary don't each copy it.
44-
type SummaryModuleShape = {
45-
status: string;
46-
successCount: number;
47-
failureCount: number;
48-
failures: Array<{ item: string; error: string }>;
49-
endTime?: number;
50-
};
51-
type GlobalSummaryShape = {
52-
getModules(): Map<string, SummaryModuleShape>;
53-
registerModule(name: string, totalItems?: number): void;
54-
startModule(name: string): void;
55-
completeModule(name: string, success?: boolean): void;
56-
};
57-
5841
export default class ExportAssets extends BaseClass {
5942
private assetsRootPath: string;
6043
public assetConfig = config.modules.assets;
@@ -75,14 +58,10 @@ export default class ExportAssets extends BaseClass {
7558
};
7659
}
7760

78-
/**
79-
* cli-utilities' CLIProgressManager.globalSummary is runtime-accessible but typed private. Reach it
80-
* via a single structural cast + feature-detect here so both callers share one copy of the
81-
* private-shape assumption; returns null (caller degrades) if a future cli-utilities version
82-
* changes the shape.
83-
*/
84-
private getGlobalSummary(): GlobalSummaryShape | null {
85-
const gs = (CLIProgressManager as unknown as { globalSummary?: GlobalSummaryShape | null }).globalSummary;
61+
// globalSummary is runtime-accessible but typed private; feature-detect the shape and return null
62+
// so callers degrade instead of throwing if a future cli-utilities version changes it.
63+
private getGlobalSummary(): GlobalSummary | null {
64+
const gs = (CLIProgressManager as unknown as { globalSummary?: GlobalSummary | null }).globalSummary;
8665
if (
8766
!gs ||
8867
typeof gs.getModules !== 'function' ||
@@ -138,15 +117,9 @@ export default class ExportAssets extends BaseClass {
138117
}
139118
}
140119

141-
/**
142-
* DX-9314 — record the AM 2.0 asset skip in the FINAL export summary without a live progress bar.
143-
* We do NOT call createNestedProgress (it would print an empty "ASSETS:" section); instead we reach
144-
* the global summary directly (same structural cast + feature-detect + degrade pattern as
145-
* applyAssetSummaryCounts) and push a failure entry so the Module Details row shows `✗ ASSETS` and the
146-
* Failure Summary prints the reason verbatim. failureCount stays 0 so the row reads `0/0 items`.
147-
* NOTE: this reuses the failure channel deliberately — a first-class "skipped" summary status is a
148-
* separate cli-utilities ticket.
149-
*/
120+
// Records the skip in the final summary via the failure channel, which is the only per-module
121+
// slot carrying a message. createNestedProgress is intentionally not used: it would render an
122+
// empty "ASSETS:" live section.
150123
private markAssetsSkippedInSummary(reason: string): void {
151124
const gs = this.getGlobalSummary();
152125
if (!gs) {
@@ -170,24 +143,14 @@ export default class ExportAssets extends BaseClass {
170143
}
171144

172145
async start(): Promise<void> {
173-
// AM 2.0 assets cannot be exported with a management token — the CS Assets API only
174-
// accepts a logged-in session (auth token / OAuth). Today the linked-workspaces lookup silently
175-
// returns [] under a management token, so the export falls back to the legacy layout and import
176-
// later reports success with broken entry->asset references. Detect the AM 2.0 org up front via
177-
// the plan-check (which DOES accept a management token) and skip the assets module with a loud
178-
// warning instead of silently emitting the wrong layout.
179-
const amInPlan = this.exportConfig.planStatus?.[FEATURE.ASSET_MANAGEMENT]?.is_part_of_plan;
180-
if (amInPlan && this.exportConfig.management_token) {
146+
const csAssetsInPlan = this.exportConfig.planStatus?.[FEATURE.ASSET_MANAGEMENT]?.is_part_of_plan;
147+
if (csAssetsInPlan && this.exportConfig.management_token) {
181148
const warning =
182-
'Skipping AM 2.0 asset export: management token authentication is not supported by the Assets APIs. ' +
149+
'Skipping Contentstack Assets export: management token authentication is not supported by the Assets APIs. ' +
183150
'Entry-to-asset references will NOT resolve in the exported content. ' +
184-
'Re-run the export with a logged-in session (auth token or OAuth) to export AM 2.0 assets.';
151+
'Re-run the export with a logged-in session (auth token or OAuth) to export Contentstack Assets.';
185152
cliux.print(`\nWARNING!!! ${warning}`, { color: 'yellow' });
186-
// Log at error level so the reason lands in error.log — the final summary's failure section
187-
// points users to the error logs, and a bare warn would leave error.log empty.
188153
log.error(warning, this.exportConfig.context);
189-
// Surface the skip in the FINAL global summary without opening a live progress section
190-
// (createNestedProgress would render an empty "ASSETS:" bar). See markAssetsSkippedInSummary.
191154
this.markAssetsSkippedInSummary(warning);
192155
return;
193156
}

packages/contentstack-export/src/types/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,21 @@ export interface Context {
180180
authenticationMethod?: string;
181181
}
182182

183+
export interface SummaryModule {
184+
status: string;
185+
successCount: number;
186+
failureCount: number;
187+
failures: Array<{ item: string; error: string }>;
188+
endTime?: number;
189+
}
190+
191+
export interface GlobalSummary {
192+
getModules(): Map<string, SummaryModule>;
193+
registerModule(name: string, totalItems?: number): void;
194+
startModule(name: string): void;
195+
completeModule(name: string, success?: boolean): void;
196+
}
197+
183198
export { default as DefaultConfig } from './default-config';
184199
export { default as ExportConfig } from './export-config';
185200
export * from './marketplace-app';

packages/contentstack-export/src/utils/export-config-handler.ts

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
log,
99
isFeatureEnabled,
1010
FeatureCtx,
11-
FEATURE,
1211
} from '@contentstack/cli-utilities';
1312
import defaultConfig from '../config';
1413
import { readFile, isDirectoryNonEmpty } from './file-helper';
@@ -17,10 +16,7 @@ import login from './basic-login';
1716
import { filter, includes } from 'lodash';
1817
import { ExportConfig } from '../types';
1918

20-
const setupConfig = async (
21-
exportCmdFlags: any,
22-
context?: { planCheckRequired?: string[] },
23-
): Promise<ExportConfig> => {
19+
const setupConfig = async (exportCmdFlags: any, context: any): Promise<ExportConfig> => {
2420
// Set progress supported module FIRST, before any log calls
2521
// This ensures the logger respects the showConsoleLogs setting correctly
2622
configHandler.set('log.progressSupportedModule', 'export');
@@ -162,32 +158,33 @@ const setupConfig = async (
162158
}
163159
// Add authentication details to config for context tracking
164160
config.authenticationMethod = authenticationMethod;
161+
log.debug('Export configuration setup completed.', { ...config });
165162

166-
// DX-9314: detect AM 2.0 via the plan-check API. Unlike the CS Assets API (which rejects
167-
// management tokens), the auth-api /feature-status endpoint accepts a management token, so this
168-
// reliably tells us the org is AM 2.0 even under `--alias`. The assets module uses this to skip
169-
// AM 2.0 asset export with a loud warning instead of silently emitting the legacy layout.
170-
// `context.planCheckRequired` is honored if PR #2627's plan-guard prerun hook populated it, but
171-
// we always check ASSET_MANAGEMENT directly so this works even without that hook.
172-
const featuresToCheck: string[] = Array.from(
173-
new Set<string>([FEATURE.ASSET_MANAGEMENT, ...(context?.planCheckRequired ?? [])]),
174-
);
175-
config.planStatus = config.planStatus || {};
176-
const planCtx: FeatureCtx = {
177-
apiKey: config.apiKey,
178-
managementToken: config.management_token,
179-
authToken: config.auth_token,
180-
};
181-
for (const featureUid of featuresToCheck) {
182-
try {
183-
config.planStatus[featureUid] = await isFeatureEnabled(featureUid, planCtx);
184-
log.debug(`[export] Plan status fetched for "${featureUid}".`);
185-
} catch (error) {
186-
log.warn(`[export] Could not fetch plan status for "${featureUid}": ${(error as Error).message}`);
163+
// Deferred plan check — credentials now available after setupExportConfig
164+
const deferredFeatures: string[] = context?.planCheckRequired ?? [];
165+
if (deferredFeatures.length > 0) {
166+
const planCtx: FeatureCtx = {
167+
apiKey: config.apiKey,
168+
managementToken: config.management_token,
169+
authToken: config.auth_token,
170+
};
171+
for (const featureUid of deferredFeatures) {
172+
try {
173+
const status = await isFeatureEnabled(featureUid, planCtx);
174+
if (context) {
175+
context.planStatus[featureUid] = status;
176+
}
177+
178+
log.debug(`[export] Deferred plan status fetched for "${featureUid}".`);
179+
} catch (error) {
180+
log.warn(`[export] Could not fetch deferred plan status for "${featureUid}": ${(error as Error).message}`);
181+
}
187182
}
188183
}
189184

190-
log.debug('Export configuration setup completed.', { ...config });
185+
if (context?.planStatus) {
186+
config.planStatus = context.planStatus;
187+
}
191188

192189
return config;
193190
};

0 commit comments

Comments
 (0)