From 59250ba58cc13ca0a897a9b8c73b5aebef16e234 Mon Sep 17 00:00:00 2001 From: harshitha-cstk Date: Tue, 12 May 2026 14:55:23 +0530 Subject: [PATCH 1/2] refactor: enhance chalk loading mechanism with global caching --- packages/contentstack-utilities/src/chalk.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/contentstack-utilities/src/chalk.ts b/packages/contentstack-utilities/src/chalk.ts index 593b9b8ddb..7c2cae623e 100644 --- a/packages/contentstack-utilities/src/chalk.ts +++ b/packages/contentstack-utilities/src/chalk.ts @@ -1,17 +1,30 @@ /** * Chalk 5 is ESM-only. We load it via dynamic import and cache for use in CommonJS. + * + * More than one physical copy of this package can load in one process (e.g. pnpm). + * Cache on globalThis via Symbol.for so loadChalk() from any copy warms getChalk() for all. */ -let chalkInstance: typeof import('chalk').default | null = null; - export type ChalkInstance = typeof import('chalk').default; +const chalkGlobal = Symbol.for('@contentstack/cli-utilities/chalk'); + +function readCached(): ChalkInstance | undefined { + return (globalThis as unknown as Record)[chalkGlobal]; +} + +function writeCached(chalkInstance: ChalkInstance): void { + (globalThis as unknown as Record)[chalkGlobal] = chalkInstance; +} + /** * Load chalk (ESM) and cache it. Call this once during CLI init before any chalk usage. */ export async function loadChalk(): Promise { + let chalkInstance = readCached(); if (!chalkInstance) { const chalkModule = await import('chalk'); chalkInstance = chalkModule.default; + writeCached(chalkInstance); } return chalkInstance; } @@ -20,6 +33,7 @@ export async function loadChalk(): Promise { * Get the cached chalk instance. Must call loadChalk() first (e.g. in init hook). */ export function getChalk(): ChalkInstance { + const chalkInstance = readCached(); if (!chalkInstance) { throw new Error('Chalk not loaded. Ensure loadChalk() is called during init (e.g. in utils-init hook).'); } From aa23403f51b2796cf57408f7c93a2c9e0abe3ab0 Mon Sep 17 00:00:00 2001 From: harshitha-cstk Date: Thu, 14 May 2026 12:10:39 +0530 Subject: [PATCH 2/2] fix: unify loading of @contentstack/cli-utilities to prevent multiple instances in monorepo --- packages/contentstack/bin/run.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/contentstack/bin/run.js b/packages/contentstack/bin/run.js index e028614701..2c27580f6f 100755 --- a/packages/contentstack/bin/run.js +++ b/packages/contentstack/bin/run.js @@ -1,4 +1,30 @@ #!/usr/bin/env node + +const path = require('path'); +const fs = require('fs'); +const Module = require('module'); + +// In this monorepo, pnpm can place a second physical copy of @contentstack/cli-utilities +// (older chalk cache) while plugins resolve the main package's symlinked copy. Force all +// requires to the same package root so loadChalk/getChalk share one implementation. +const utilitiesPkgJson = path.resolve(__dirname, '..', 'node_modules', '@contentstack', 'cli-utilities', 'package.json'); +if (fs.existsSync(utilitiesPkgJson)) { + const resolveFromUtilities = Module.createRequire(utilitiesPkgJson); + const origResolveFilename = Module._resolveFilename.bind(Module); + Module._resolveFilename = (request, parent, isMain, options) => { + if (request === '@contentstack/cli-utilities' || request.startsWith('@contentstack/cli-utilities/')) { + try { + const relative = + request === '@contentstack/cli-utilities' ? '.' : `.${request.slice('@contentstack/cli-utilities'.length)}`; + return resolveFromUtilities.resolve(relative); + } catch { + /* fall through */ + } + } + return origResolveFilename(request, parent, isMain, options); + }; +} + // eslint-disable-next-line unicorn/prefer-top-level-await (async () => { try {