Skip to content

Commit d965844

Browse files
Merge pull request #2568 from contentstack/fix/dx-7341-fix-chalk-load-error
refactor: enhance chalk loading mechanism with global caching
2 parents 061bcf1 + 52b33b9 commit d965844

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

packages/contentstack-utilities/src/chalk.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,30 @@
11
/**
22
* Chalk 5 is ESM-only. We load it via dynamic import and cache for use in CommonJS.
3+
*
4+
* More than one physical copy of this package can load in one process (e.g. pnpm).
5+
* Cache on globalThis via Symbol.for so loadChalk() from any copy warms getChalk() for all.
36
*/
4-
let chalkInstance: typeof import('chalk').default | null = null;
5-
67
export type ChalkInstance = typeof import('chalk').default;
78

9+
const chalkGlobal = Symbol.for('@contentstack/cli-utilities/chalk');
10+
11+
function readCached(): ChalkInstance | undefined {
12+
return (globalThis as unknown as Record<symbol, ChalkInstance | undefined>)[chalkGlobal];
13+
}
14+
15+
function writeCached(chalkInstance: ChalkInstance): void {
16+
(globalThis as unknown as Record<symbol, ChalkInstance>)[chalkGlobal] = chalkInstance;
17+
}
18+
819
/**
920
* Load chalk (ESM) and cache it. Call this once during CLI init before any chalk usage.
1021
*/
1122
export async function loadChalk(): Promise<ChalkInstance> {
23+
let chalkInstance = readCached();
1224
if (!chalkInstance) {
1325
const chalkModule = await import('chalk');
1426
chalkInstance = chalkModule.default;
27+
writeCached(chalkInstance);
1528
}
1629
return chalkInstance;
1730
}
@@ -20,6 +33,7 @@ export async function loadChalk(): Promise<ChalkInstance> {
2033
* Get the cached chalk instance. Must call loadChalk() first (e.g. in init hook).
2134
*/
2235
export function getChalk(): ChalkInstance {
36+
const chalkInstance = readCached();
2337
if (!chalkInstance) {
2438
throw new Error('Chalk not loaded. Ensure loadChalk() is called during init (e.g. in utils-init hook).');
2539
}

packages/contentstack/bin/run.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
11
#!/usr/bin/env node
2+
3+
const path = require('path');
4+
const fs = require('fs');
5+
const Module = require('module');
6+
7+
// In this monorepo, pnpm can place a second physical copy of @contentstack/cli-utilities
8+
// (older chalk cache) while plugins resolve the main package's symlinked copy. Force all
9+
// requires to the same package root so loadChalk/getChalk share one implementation.
10+
const utilitiesPkgJson = path.resolve(__dirname, '..', 'node_modules', '@contentstack', 'cli-utilities', 'package.json');
11+
if (fs.existsSync(utilitiesPkgJson)) {
12+
const resolveFromUtilities = Module.createRequire(utilitiesPkgJson);
13+
const origResolveFilename = Module._resolveFilename.bind(Module);
14+
Module._resolveFilename = (request, parent, isMain, options) => {
15+
if (request === '@contentstack/cli-utilities' || request.startsWith('@contentstack/cli-utilities/')) {
16+
try {
17+
const relative =
18+
request === '@contentstack/cli-utilities' ? '.' : `.${request.slice('@contentstack/cli-utilities'.length)}`;
19+
return resolveFromUtilities.resolve(relative);
20+
} catch {
21+
/* fall through */
22+
}
23+
}
24+
return origResolveFilename(request, parent, isMain, options);
25+
};
26+
}
27+
228
// eslint-disable-next-line unicorn/prefer-top-level-await
329
(async () => {
430
try {

0 commit comments

Comments
 (0)