Skip to content

Commit 6918642

Browse files
author
naman-contentstack
committed
Merge branch 'feat/DX-3646' into feat/DX-3700
2 parents 42828b5 + 6d46d49 commit 6918642

File tree

26 files changed

+1872
-1451
lines changed

26 files changed

+1872
-1451
lines changed

.talismanrc

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
fileignoreconfig:
22
- filename: package-lock.json
3-
checksum: 6ac2ffbe2bcbc1798d714fc55e9bd6f38c40c89ba81889735339b573b758ffae
3+
checksum: fa02e2883b15c973134368ce26c78187e247d3761ef14f603afc0d5ea83102a6
44
- filename: pnpm-lock.yaml
5-
checksum: f53e4e5ab2618734066cc92ebff75d87142f2616cf2558ae9a7170a2a5066d09
5+
checksum: d4174feb2ba68c22cc45987afdaf4d89997df084e7e7eb9edc7e309b5a24aca5
66
- filename: packages/contentstack-import-setup/test/unit/backup-handler.test.ts
77
checksum: 0582d62b88834554cf12951c8690a73ef3ddbb78b82d2804d994cf4148e1ef93
88
- filename: packages/contentstack-import-setup/test/config.json
@@ -213,4 +213,18 @@ fileignoreconfig:
213213
checksum: 83cf034fabee00b42b4243a8c0b8ba280ab7c1e68ffd741c49c31aaee8ca0315
214214
- filename: packages/contentstack-utilities/test/unit/logger.test.ts
215215
checksum: 11778d0252202c18a1ca6a38883d6e12fc324ff86ad0fe058bc2505f9cd66ba3
216+
- filename: packages/contentstack-audit/test/unit/audit-base-command.test.ts
217+
checksum: 17a16b4457c820494442f335d94d0949961e68e8ca72ca0f1fa9d4d0eeb0c17a
218+
- filename: packages/contentstack-import/src/import/modules/taxonomies.ts
219+
checksum: ed7037a220754ecfdf800f6b747059ad309e23e7bafa09f6938021246f67d998
220+
- filename: packages/contentstack-export/test/unit/utils/logger.test.ts
221+
checksum: ce8438d323fd0e42a88ece3dfd826313993c0198dbeffe01d046f835d6aad95f
222+
- filename: packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts
223+
checksum: 57566af0bbd95a28b454e4436b0396dfec2fe05ddd5b448d46e3a8b68db8b9cb
224+
- filename: packages/contentstack-export/test/unit/export/modules/entries.test.ts
225+
checksum: 5950c6f697224e11bec32736e6a967b0ab7ac98e9c8f8bb8eaaf10af60913e40
226+
- filename: packages/contentstack-import-setup/src/commands/cm/stacks/import-setup.ts
227+
checksum: 86b11c2a2dd8c0b14aa558e4e52d6d721cd7707422c26a68e96cc5b55b9fefd8
228+
- filename: packages/contentstack-import-setup/src/utils/login-handler.ts
229+
checksum: 3860c96e31677356963e67049762f944aef7c7b22fabb75a70ff5c64cf1ac274
216230
version: "1.0"

package-lock.json

Lines changed: 749 additions & 669 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/contentstack-audit/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-audit
1919
$ csdx COMMAND
2020
running command...
2121
$ csdx (--version|-v)
22-
@contentstack/cli-audit/1.16.1 darwin-arm64 node-v22.14.0
22+
@contentstack/cli-audit/1.16.1 darwin-arm64 node-v23.11.0
2323
$ csdx --help [COMMAND]
2424
USAGE
2525
$ csdx COMMAND
@@ -282,7 +282,7 @@ DESCRIPTION
282282
Display help for csdx.
283283
```
284284

285-
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.36/src/commands/help.ts)_
285+
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.34/src/commands/help.ts)_
286286

287287
## `csdx plugins`
288288

@@ -305,7 +305,7 @@ EXAMPLES
305305
$ csdx plugins
306306
```
307307

308-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/index.ts)_
308+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/index.ts)_
309309

310310
## `csdx plugins:add PLUGIN`
311311

@@ -379,7 +379,7 @@ EXAMPLES
379379
$ csdx plugins:inspect myplugin
380380
```
381381

382-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/inspect.ts)_
382+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/inspect.ts)_
383383

384384
## `csdx plugins:install PLUGIN`
385385

@@ -428,7 +428,7 @@ EXAMPLES
428428
$ csdx plugins:install someuser/someplugin
429429
```
430430

431-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/install.ts)_
431+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/install.ts)_
432432

433433
## `csdx plugins:link PATH`
434434

@@ -459,7 +459,7 @@ EXAMPLES
459459
$ csdx plugins:link myplugin
460460
```
461461

462-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/link.ts)_
462+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/link.ts)_
463463

464464
## `csdx plugins:remove [PLUGIN]`
465465

@@ -500,7 +500,7 @@ FLAGS
500500
--reinstall Reinstall all plugins after uninstalling.
501501
```
502502

503-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/reset.ts)_
503+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/reset.ts)_
504504

505505
## `csdx plugins:uninstall [PLUGIN]`
506506

@@ -528,7 +528,7 @@ EXAMPLES
528528
$ csdx plugins:uninstall myplugin
529529
```
530530

531-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/uninstall.ts)_
531+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/uninstall.ts)_
532532

533533
## `csdx plugins:unlink [PLUGIN]`
534534

@@ -572,5 +572,5 @@ DESCRIPTION
572572
Update installed plugins.
573573
```
574574

575-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/update.ts)_
575+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.52/src/commands/plugins/update.ts)_
576576
<!-- commandsstop -->

packages/contentstack-audit/src/audit-base-command.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,11 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
271271
missingMultipleFields = missingEntry.missingMultipleFields ?? {};
272272
await this.prepareReport(module, missingEntryRefs);
273273

274-
await this.prepareReport(`Entries_Select_feild`, missingSelectFeild);
274+
await this.prepareReport(`Entries_Select_field`, missingSelectFeild);
275275

276-
await this.prepareReport('Entries_Mandatory_feild', missingMandatoryFields);
276+
await this.prepareReport('Entries_Mandatory_field', missingMandatoryFields);
277277

278-
await this.prepareReport('Entries_Title_feild', missingTitleFields);
278+
await this.prepareReport('Entries_Title_field', missingTitleFields);
279279

280280
await this.prepareReport('Entry_Missing_Locale_and_Env_in_Publish_Details', missingEnvLocalesInEntries);
281281

packages/contentstack-audit/src/config/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,17 @@ const config = {
116116
"Passed",
117117
],
118118
ReportTitleForEntries: {
119-
Entries_Select_feild: 'Entries_Select_feild',
120-
Entries_Mandatory_feild: 'Entries_Mandatory_feild',
121-
Entries_Title_feild: 'Entries_Title_feild',
119+
Entries_Select_field: 'Entries_Select_field',
120+
Entries_Mandatory_field: 'Entries_Mandatory_field',
121+
Entries_Title_field: 'Entries_Title_field',
122122
Entry_Missing_Locale_and_Env: 'Entry_Missing_Locale_and_Env',
123123
Entry_Missing_Locale_and_Env_in_Publish_Details: 'Entry_Missing_Locale_and_Env_in_Publish_Details',
124124
Entry_Multiple_Fields:"Entry_Multiple_Fields"
125125
},
126126
feild_level_modules: [
127-
'Entries_Title_feild',
128-
'Entries_Mandatory_feild',
129-
'Entries_Select_feild',
127+
'Entries_Title_field',
128+
'Entries_Mandatory_field',
129+
'Entries_Select_field',
130130
'Entry_Missing_Locale_and_Env_in_Publish_Details',
131131
'field-rules',
132132
'Entry_Multiple_Fields',

packages/contentstack-audit/test/unit/audit-base-command.test.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,4 +370,146 @@ describe('AuditBaseCommand class', () => {
370370
});
371371
});
372372
});
373+
374+
describe('prepareReport method - Report file names', () => {
375+
fancy
376+
.stdout({ print: process.env.PRINT === 'true' || false })
377+
.stub(winston.transports, 'File', () => fsTransport)
378+
.stub(winston, 'createLogger', createMockWinstonLogger)
379+
.stub(fs, 'createWriteStream', () => new PassThrough())
380+
.stub(fs, 'mkdirSync', () => {})
381+
.stub(fs, 'existsSync', () => true)
382+
.it('should generate report file with correct spelling: Entries_Select_field (not feild)', async () => {
383+
const writeFileSyncSpy = sinon.spy(fs, 'writeFileSync');
384+
class CMD extends AuditBaseCommand {
385+
async run() {
386+
await this.init();
387+
this.sharedConfig.reportPath = resolve(__dirname, 'mock', 'contents');
388+
389+
await this.prepareReport('Entries_Select_field', {
390+
entry1: {
391+
name: 'Test Entry',
392+
display_name: 'Select Field',
393+
missingRefs: ['ref1'],
394+
},
395+
});
396+
397+
const jsonCall = writeFileSyncSpy.getCalls().find(call =>
398+
typeof call.args[0] === 'string' && call.args[0].includes('.json')
399+
);
400+
return jsonCall ? (jsonCall.args[0] as string) : undefined;
401+
}
402+
}
403+
404+
const result = await CMD.run([]);
405+
writeFileSyncSpy.restore();
406+
expect(result).to.include('Entries_Select_field.json');
407+
expect(result).to.not.include('Entries_Select_feild');
408+
});
409+
410+
fancy
411+
.stdout({ print: process.env.PRINT === 'true' || false })
412+
.stub(winston.transports, 'File', () => fsTransport)
413+
.stub(winston, 'createLogger', createMockWinstonLogger)
414+
.stub(fs, 'createWriteStream', () => new PassThrough())
415+
.stub(fs, 'mkdirSync', () => {})
416+
.stub(fs, 'existsSync', () => true)
417+
.it('should generate report file with correct spelling: Entries_Mandatory_field (not feild)', async () => {
418+
const writeFileSyncSpy = sinon.spy(fs, 'writeFileSync');
419+
class CMD extends AuditBaseCommand {
420+
async run() {
421+
await this.init();
422+
this.sharedConfig.reportPath = resolve(__dirname, 'mock', 'contents');
423+
424+
await this.prepareReport('Entries_Mandatory_field', {
425+
entry1: {
426+
name: 'Test Entry',
427+
display_name: 'Mandatory Field',
428+
missingRefs: ['ref1'],
429+
},
430+
});
431+
432+
const jsonCall = writeFileSyncSpy.getCalls().find(call =>
433+
typeof call.args[0] === 'string' && call.args[0].includes('.json')
434+
);
435+
return jsonCall ? (jsonCall.args[0] as string) : undefined;
436+
}
437+
}
438+
439+
const result = await CMD.run([]);
440+
writeFileSyncSpy.restore();
441+
expect(result).to.include('Entries_Mandatory_field.json');
442+
expect(result).to.not.include('Entries_Mandatory_feild');
443+
});
444+
445+
fancy
446+
.stdout({ print: process.env.PRINT === 'true' || false })
447+
.stub(winston.transports, 'File', () => fsTransport)
448+
.stub(winston, 'createLogger', createMockWinstonLogger)
449+
.stub(fs, 'createWriteStream', () => new PassThrough())
450+
.stub(fs, 'mkdirSync', () => {})
451+
.stub(fs, 'existsSync', () => true)
452+
.it('should generate report file with correct spelling: Entries_Title_field (not feild)', async () => {
453+
const writeFileSyncSpy = sinon.spy(fs, 'writeFileSync');
454+
class CMD extends AuditBaseCommand {
455+
async run() {
456+
await this.init();
457+
this.sharedConfig.reportPath = resolve(__dirname, 'mock', 'contents');
458+
459+
await this.prepareReport('Entries_Title_field', {
460+
entry1: {
461+
name: 'Test Entry',
462+
display_name: 'Title Field',
463+
missingRefs: ['ref1'],
464+
},
465+
});
466+
467+
const jsonCall = writeFileSyncSpy.getCalls().find(call =>
468+
typeof call.args[0] === 'string' && call.args[0].includes('.json')
469+
);
470+
return jsonCall ? (jsonCall.args[0] as string) : undefined;
471+
}
472+
}
473+
474+
const result = await CMD.run([]);
475+
writeFileSyncSpy.restore();
476+
expect(result).to.include('Entries_Title_field.json');
477+
expect(result).to.not.include('Entries_Title_feild');
478+
});
479+
});
480+
481+
describe('Config - ReportTitleForEntries keys', () => {
482+
it('should have correct spelling in ReportTitleForEntries config', () => {
483+
const config = require('../../src/config').default;
484+
485+
// Verify correct spelling (field, not feild)
486+
expect(config.ReportTitleForEntries).to.have.property('Entries_Select_field');
487+
expect(config.ReportTitleForEntries).to.have.property('Entries_Mandatory_field');
488+
expect(config.ReportTitleForEntries).to.have.property('Entries_Title_field');
489+
490+
// Verify old typo is not present
491+
expect(config.ReportTitleForEntries).to.not.have.property('Entries_Select_feild');
492+
expect(config.ReportTitleForEntries).to.not.have.property('Entries_Mandatory_feild');
493+
expect(config.ReportTitleForEntries).to.not.have.property('Entries_Title_feild');
494+
495+
// Verify values match keys
496+
expect(config.ReportTitleForEntries.Entries_Select_field).to.equal('Entries_Select_field');
497+
expect(config.ReportTitleForEntries.Entries_Mandatory_field).to.equal('Entries_Mandatory_field');
498+
expect(config.ReportTitleForEntries.Entries_Title_field).to.equal('Entries_Title_field');
499+
});
500+
501+
it('should have correct spelling in feild_level_modules array', () => {
502+
const config = require('../../src/config').default;
503+
504+
// Verify correct spelling in the array
505+
expect(config.feild_level_modules).to.include('Entries_Select_field');
506+
expect(config.feild_level_modules).to.include('Entries_Mandatory_field');
507+
expect(config.feild_level_modules).to.include('Entries_Title_field');
508+
509+
// Verify old typo is not present
510+
expect(config.feild_level_modules).to.not.include('Entries_Select_feild');
511+
expect(config.feild_level_modules).to.not.include('Entries_Mandatory_feild');
512+
expect(config.feild_level_modules).to.not.include('Entries_Title_feild');
513+
});
514+
});
373515
});

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ export default class ExportTaxonomies extends BaseClass {
7373
await this.fetchTaxonomies(masterLocale, true);
7474

7575
if (!this.isLocaleBasedExportSupported) {
76-
log.debug('Localization disabled, falling back to legacy export method', this.exportConfig.context);
76+
this.taxonomies = {};
77+
this.taxonomiesByLocale = {};
78+
79+
// Fetch taxonomies without locale parameter
80+
await this.fetchTaxonomies();
7781
await this.exportTaxonomies();
7882
await this.writeTaxonomiesMetadata();
7983
} else {
@@ -174,15 +178,26 @@ export default class ExportTaxonomies extends BaseClass {
174178
log.debug(`Completed fetching all taxonomies ${localeInfo}`, this.exportConfig.context);
175179
break;
176180
}
177-
} catch (error) {
181+
} catch (error: any) {
178182
log.debug(`Error fetching taxonomies ${localeInfo}`, this.exportConfig.context);
179-
handleAndLogError(error, {
180-
...this.exportConfig.context,
181-
...(localeCode && { locale: localeCode }),
182-
});
183-
if (checkLocaleSupport) {
183+
184+
if (checkLocaleSupport && this.isLocalePlanLimitationError(error)) {
185+
log.debug(
186+
'Taxonomy localization is not included in your plan. Falling back to non-localized export.',
187+
this.exportConfig.context,
188+
);
184189
this.isLocaleBasedExportSupported = false;
190+
} else if (checkLocaleSupport) {
191+
log.debug('Locale-based taxonomy export not supported, will use legacy method', this.exportConfig.context);
192+
this.isLocaleBasedExportSupported = false;
193+
} else {
194+
// Log actual errors during normal fetch (not locale check)
195+
handleAndLogError(error, {
196+
...this.exportConfig.context,
197+
...(localeCode && { locale: localeCode }),
198+
});
185199
}
200+
186201
// Break to avoid infinite retry loop on errors
187202
break;
188203
}
@@ -312,4 +327,15 @@ export default class ExportTaxonomies extends BaseClass {
312327

313328
return localesToExport;
314329
}
330+
331+
private isLocalePlanLimitationError(error: any): boolean {
332+
return (
333+
error?.status === 403 &&
334+
error?.errors?.taxonomies?.some(
335+
(msg: string) =>
336+
msg.toLowerCase().includes('taxonomy localization') &&
337+
msg.toLowerCase().includes('not included in your plan'),
338+
)
339+
);
340+
}
315341
}

0 commit comments

Comments
 (0)