Skip to content

Commit 193944e

Browse files
cs-rajclaude
andcommitted
feat(global-fields): switch to per-file export/import format
Replaces the bulk-array globalfields.json export with individual {uid}.json files per global field, consistent with how content types are handled. Export writes each global field to global_fields/{uid}.json instead of collecting all into a single array file. Import and content-types modules now use readGlobalFieldSchemas to scan the directory and read all per-file schemas. The audit base command is updated to use the same function when loading global field schemas for cross-reference validation. The globalfields.json fileName config values are retained for type compatibility but are no longer read or written at runtime. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4ceb421 commit 193944e

8 files changed

Lines changed: 17 additions & 33 deletions

File tree

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import {
1414
CLIProgressManager,
1515
clearProgressModuleSetting,
1616
readContentTypeSchemas,
17+
readGlobalFieldSchemas,
1718
generateUid
1819
} from '@contentstack/cli-utilities';
19-
import { createWriteStream, existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'fs';
20+
import { createWriteStream, existsSync, mkdirSync, writeFileSync, rmSync } from 'fs';
2021
import config from './config';
2122
import { print } from './util/log';
2223
import { auditMsg } from './messages';
@@ -491,13 +492,9 @@ export abstract class AuditBaseCommand extends BaseCommand<typeof AuditBaseComma
491492
*/
492493
getCtAndGfSchema() {
493494
const ctDirPath = join(this.sharedConfig.basePath, this.sharedConfig.moduleConfig['content-types'].dirName);
494-
const gfPath = join(
495-
this.sharedConfig.basePath,
496-
this.sharedConfig.moduleConfig['global-fields'].dirName,
497-
this.sharedConfig.moduleConfig['global-fields'].fileName,
498-
);
495+
const gfDirPath = join(this.sharedConfig.basePath, this.sharedConfig.moduleConfig['global-fields'].dirName);
499496

500-
const gfSchema = existsSync(gfPath) ? (JSON.parse(readFileSync(gfPath, 'utf8')) as ContentTypeStruct[]) : [];
497+
const gfSchema = (readGlobalFieldSchemas(gfDirPath) || []) as ContentTypeStruct[];
501498
const ctSchema = (readContentTypeSchemas(ctDirPath) || []) as ContentTypeStruct[];
502499

503500
return { ctSchema, gfSchema };

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const config = {
2424
'global-fields': {
2525
name: 'global field',
2626
dirName: 'global_fields',
27-
fileName: 'globalfields.json',
27+
fileName: 'globalfields.json', // Not used - reads from individual files via readGlobalFieldSchemas
2828
},
2929
entries: {
3030
name: 'entries',

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ const config: DefaultConfig = {
9898
},
9999
'global-fields': {
100100
dirName: 'global_fields',
101-
fileName: 'globalfields.json',
101+
fileName: 'globalfields.json', // Not used - writes individual {uid}.json files
102102
validKeys: ['title', 'uid', 'schema', 'options', 'singleton', 'description'],
103103
},
104104
assets: {

packages/contentstack-export/src/export/modules/global-fields.ts

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,12 @@ export default class GlobalFieldsExport extends BaseClass {
1717
};
1818
private globalFieldsConfig: {
1919
dirName?: string;
20-
fileName?: string;
2120
validKeys?: string[];
2221
fetchConcurrency?: number;
2322
writeConcurrency?: number;
2423
limit?: number;
2524
};
2625
private globalFieldsDirPath: string;
27-
private globalFields: Record<string, unknown>[];
2826

2927
constructor({ exportConfig, stackAPIClient }: ModuleClassParams) {
3028
super({ exportConfig, stackAPIClient });
@@ -41,7 +39,6 @@ export default class GlobalFieldsExport extends BaseClass {
4139
sanitizePath(getExportBasePath(exportConfig)),
4240
sanitizePath(this.globalFieldsConfig.dirName),
4341
);
44-
this.globalFields = [];
4542
this.applyQueryFilters(this.qs, 'global-fields');
4643
this.exportConfig.context.module = MODULE_CONTEXTS.GLOBAL_FIELDS;
4744
this.currentModuleName = MODULE_NAMES[MODULE_CONTEXTS.GLOBAL_FIELDS];
@@ -66,20 +63,13 @@ export default class GlobalFieldsExport extends BaseClass {
6663

6764
if (totalCount === 0) {
6865
log.info(messageHandler.parse('GLOBAL_FIELDS_NOT_FOUND'), this.exportConfig.context);
69-
const globalFieldsFilePath = path.join(this.globalFieldsDirPath, this.globalFieldsConfig.fileName);
70-
log.debug(`Writing global fields to: ${globalFieldsFilePath}`, this.exportConfig.context);
71-
fsUtil.writeFile(globalFieldsFilePath, this.globalFields);
7266
this.completeProgress(true);
7367
return;
7468
}
7569

7670
progress.updateStatus('Fetching global fields...');
7771
await this.getGlobalFields();
7872

79-
const globalFieldsFilePath = path.join(this.globalFieldsDirPath, this.globalFieldsConfig.fileName);
80-
log.debug(`Writing global fields to: ${globalFieldsFilePath}`, this.exportConfig.context);
81-
fsUtil.writeFile(globalFieldsFilePath, this.globalFields);
82-
8373

8474

8575
this.completeProgressWithMessage();
@@ -133,14 +123,15 @@ export default class GlobalFieldsExport extends BaseClass {
133123
delete globalField[key];
134124
}
135125
}
136-
this.globalFields.push(globalField);
126+
const filePath = path.join(this.globalFieldsDirPath, `${globalField.uid}.json`);
127+
fsUtil.writeFile(filePath, globalField);
137128

138129
// Track progress for each global field
139130
this.progressManager?.tick(true, `global-field: ${globalField.uid}`);
140131
});
141132

142133
log.debug(
143-
`Sanitization complete. Total global fields processed: ${this.globalFields.length}`,
134+
`Sanitization complete. Total global fields processed: ${globalFields.length}`,
144135
this.exportConfig.context,
145136
);
146137
}

packages/contentstack-import-setup/src/config/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const config: DefaultConfig = {
8787
},
8888
'global-fields': {
8989
dirName: 'global_fields',
90-
fileName: 'globalfields.json',
90+
fileName: 'globalfields.json', // Not used - reads individual {uid}.json files
9191
dependencies: ['extensions', 'marketplace-apps'],
9292
},
9393
'marketplace-apps': {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ const config: DefaultConfig = {
177177
},
178178
'global-fields': {
179179
dirName: 'global_fields',
180-
fileName: 'globalfields.json',
180+
fileName: 'globalfields.json', // Not used - reads individual {uid}.json files
181181
validKeys: ['title', 'uid', 'schema', 'options', 'singleton', 'description'],
182182
limit: 100,
183183
},

packages/contentstack-import/src/import/modules/content-types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77
import * as path from 'path';
88
import { find, cloneDeep, map } from 'lodash';
9-
import { sanitizePath, log, handleAndLogError, readContentTypeSchemas } from '@contentstack/cli-utilities';
9+
import { sanitizePath, log, handleAndLogError, readContentTypeSchemas, readGlobalFieldSchemas } from '@contentstack/cli-utilities';
1010
import { PATH_CONSTANTS } from '../../constants';
1111
import { ImportConfig, ModuleClassParams } from '../../types';
1212
import BaseClass, { ApiOptions } from './base-class';
@@ -50,7 +50,6 @@ export default class ContentTypesImport extends BaseClass {
5050
};
5151
private gFsConfig: {
5252
dirName: string;
53-
fileName: string;
5453
validKeys: string[];
5554
limit: number;
5655
writeConcurrency?: number;
@@ -105,6 +104,7 @@ export default class ContentTypesImport extends BaseClass {
105104
['__master.json', 'true'],
106105
['__priority.json', 'true'],
107106
[PATH_CONSTANTS.FILES.SCHEMA, 'true'],
107+
['globalfields.json', 'true'],
108108
['.DS_Store', 'true'],
109109
]);
110110

@@ -499,7 +499,7 @@ export default class ContentTypesImport extends BaseClass {
499499
'CONTENT TYPES: Analyzing import data...',
500500
async () => {
501501
const cts = readContentTypeSchemas(this.cTsFolderPath);
502-
const gfs = fsUtil.readFile(path.resolve(this.gFsFolderPath, this.gFsConfig.fileName));
502+
const gfs = readGlobalFieldSchemas(this.gFsFolderPath);
503503
const pendingGfs = fsUtil.readFile(this.gFsPendingPath);
504504
const pendingExt = fsUtil.readFile(this.extPendingPath);
505505
return [cts, gfs, pendingGfs, pendingExt];

packages/contentstack-import/src/import/modules/global-fields.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import * as path from 'path';
99
import { isEmpty, cloneDeep } from 'lodash';
10-
import { sanitizePath, log, handleAndLogError, GlobalFieldData, GlobalField } from '@contentstack/cli-utilities';
10+
import { sanitizePath, log, handleAndLogError, GlobalFieldData, GlobalField, readGlobalFieldSchemas } from '@contentstack/cli-utilities';
1111
import { PATH_CONSTANTS } from '../../constants';
1212
import { fsUtil,
1313
fileHelper,
@@ -41,7 +41,6 @@ export default class ImportGlobalFields extends BaseClass {
4141
private existingGFs: Record<string, any>[];
4242
private gFsConfig: {
4343
dirName: string;
44-
fileName: string;
4544
validKeys: string[];
4645
limit: number;
4746
writeConcurrency?: number;
@@ -430,12 +429,9 @@ export default class ImportGlobalFields extends BaseClass {
430429
}
431430

432431
log.debug(`Found global fields folder: ${this.gFsFolderPath}`, this.importConfig.context);
433-
this.gFs = fsUtil.readFile(path.join(this.gFsFolderPath, this.gFsConfig.fileName)) as Record<string, unknown>[];
432+
this.gFs = readGlobalFieldSchemas(this.gFsFolderPath) as Record<string, unknown>[];
434433
if (!this.gFs || isEmpty(this.gFs)) {
435-
log.info(
436-
`No global fields found in file - '${path.join(this.gFsFolderPath, this.gFsConfig.fileName)}'`,
437-
this.importConfig.context,
438-
);
434+
log.info(`No global fields found in directory - '${this.gFsFolderPath}'`, this.importConfig.context);
439435
return [0];
440436
}
441437

0 commit comments

Comments
 (0)