Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/contentstack-auth/.mocharc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"require": [
"test/helpers/init.js",
"ts-node/register",
"source-map-support/register"
"source-map-support/register",
"test/helpers/mocha-root-hooks.js"
],
"watch-extensions": [
"ts"
Expand Down
11 changes: 11 additions & 0 deletions packages/contentstack-auth/test/helpers/mocha-root-hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @contentstack/cli-utilities uses lazy-loaded Chalk 5; preload before tests that hit cliux.
*/
const { loadChalk } = require('@contentstack/cli-utilities');

exports.mochaHooks = {
beforeAll() {
this.timeout(30_000);
return loadChalk();
},
};
3 changes: 2 additions & 1 deletion packages/contentstack-config/.mocharc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"require": [
"ts-node/register",
"source-map-support/register"
"source-map-support/register",
"test/helpers/mocha-root-hooks.js"
],
"watch-extensions": [
"ts"
Expand Down
11 changes: 11 additions & 0 deletions packages/contentstack-config/test/helpers/mocha-root-hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @contentstack/cli-utilities uses lazy-loaded Chalk 5; preload before tests that hit cliux.success etc.
*/
const { loadChalk } = require('@contentstack/cli-utilities');

exports.mochaHooks = {
beforeAll() {
this.timeout(30_000);
return loadChalk();
},
};
3 changes: 2 additions & 1 deletion packages/contentstack-utilities/.mocharc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"require": [
"test/helpers/init.js",
"ts-node/register",
"source-map-support/register"
"source-map-support/register",
"test/helpers/mocha-root-hooks.js"
],
"watch-extensions": [
"ts"
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-utilities/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@contentstack/marketplace-sdk": "^1.5.0",
"@oclif/core": "^4.3.0",
"axios": "^1.13.5",
"chalk": "^4.1.2",
"chalk": "^5.6.2",
"cli-cursor": "^3.1.0",
"cli-progress": "^3.12.0",
"cli-table": "^0.3.11",
Expand Down
27 changes: 27 additions & 0 deletions packages/contentstack-utilities/src/chalk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Chalk 5 is ESM-only. We load it via dynamic import and cache for use in CommonJS.
*/
let chalkInstance: typeof import('chalk').default | null = null;

export type ChalkInstance = typeof import('chalk').default;

/**
* Load chalk (ESM) and cache it. Call this once during CLI init before any chalk usage.
*/
export async function loadChalk(): Promise<ChalkInstance> {
if (!chalkInstance) {
const chalkModule = await import('chalk');
chalkInstance = chalkModule.default;
}
return chalkInstance;
}

/**
* Get the cached chalk instance. Must call loadChalk() first (e.g. in init hook).
*/
export function getChalk(): ChalkInstance {
if (!chalkInstance) {
throw new Error('Chalk not loaded. Ensure loadChalk() is called during init (e.g. in utils-init hook).');
}
return chalkInstance;
}
13 changes: 7 additions & 6 deletions packages/contentstack-utilities/src/cli-ux.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chalk, { Chalk } from 'chalk';
import { getChalk, ChalkInstance } from './chalk';
import inquirer from 'inquirer';
import { ux as cliux, Args, Flags, Command } from '@oclif/core';
import { Ora, default as ora } from 'ora';
Expand Down Expand Up @@ -29,10 +29,11 @@ class CLIInterface {

print(message: string, opts?: PrintOptions): void {
if (opts) {
let chalkFn: Chalk = chalk;
const chalk = getChalk();
let chalkFn: ChalkInstance = chalk;

if (opts.color) chalkFn = chalkFn[opts.color] as Chalk;
if (opts.bold) chalkFn = chalkFn.bold as Chalk;
if (opts.color) chalkFn = chalkFn[opts.color] as ChalkInstance;
if (opts.bold) chalkFn = chalkFn.bold as ChalkInstance;

cliux.stdout(chalkFn(messageHandler.parse(message)));
return;
Expand All @@ -42,11 +43,11 @@ class CLIInterface {
}

success(message: string): void {
cliux.stdout(chalk.green(messageHandler.parse(message)));
cliux.stdout(getChalk().green(messageHandler.parse(message)));
}

error(message: string, ...params: any): void {
cliux.stdout(chalk.red(messageHandler.parse(message) + (params && params.length > 0 ? ': ' : '')), ...params);
cliux.stdout(getChalk().red(messageHandler.parse(message) + (params && params.length > 0 ? ': ' : '')), ...params);
}

loader(message: string = ''): void {
Expand Down
8 changes: 4 additions & 4 deletions packages/contentstack-utilities/src/config-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Conf from 'conf';
import has from 'lodash/has';
import { v4 as uuid } from 'uuid';
import { existsSync, unlinkSync, readFileSync } from 'fs';
import chalk from 'chalk';
import { getChalk } from './chalk';
import { cliux } from '.';

const ENC_KEY = process.env.ENC_KEY || 'encryptionKey';
Expand Down Expand Up @@ -85,7 +85,7 @@ class Config {

safeDeleteConfigIfInvalid(configFilePath: string) {
if (existsSync(configFilePath) && !this.isConfigFileValid(configFilePath)) {
console.warn(chalk.yellow(`Warning: Detected corrupted config at ${configFilePath}. Removing...`));
console.warn(getChalk().yellow(`Warning: Detected corrupted config at ${configFilePath}. Removing...`));
unlinkSync(configFilePath);
}
}
Expand Down Expand Up @@ -152,7 +152,7 @@ class Config {
const oldConfigData = this.getConfigDataAndUnlinkConfigFile(config);
this.getEncryptedConfig(oldConfigData, true);
} catch (_error) {
cliux.print(chalk.red('Error: Config file is corrupted'));
cliux.print(getChalk().red('Error: Config file is corrupted'));
cliux.print(_error);
process.exit(1);
}
Expand Down Expand Up @@ -203,7 +203,7 @@ class Config {
this.getDecryptedConfig(_configData); // NOTE reinitialize the config with old data and new decrypted file
} catch (__error) {
// console.trace(error.message)
cliux.print(chalk.red('Error: Config file is corrupted'));
cliux.print(getChalk().red('Error: Config file is corrupted'));
cliux.print(_error);
process.exit(1);
}
Expand Down
18 changes: 11 additions & 7 deletions packages/contentstack-utilities/src/content-type-utils.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { existsSync, readdirSync, readFileSync } from 'node:fs';
import { resolve as pResolve } from 'node:path';
import { FsUtility } from './fs-utility';

/**
* Reads all content type schema files from a directory
* @param dirPath - Path to content types directory
* @param ignoredFiles - Files to ignore (defaults to schema.json, .DS_Store, __master.json, __priority.json)
* @returns Array of content type schemas
* @returns Array of content type schemas (empty if the path is missing or has no eligible files)
*/
export function readContentTypeSchemas(
dirPath: string,
ignoredFiles: string[] = ['schema.json', '.DS_Store', '__master.json', '__priority.json', 'field_rules_uid.json'],
): Record<string, unknown>[] | null {
const fsUtil = new FsUtility();
const files = fsUtil.readdir(dirPath);
): Record<string, unknown>[] {
if (!existsSync(dirPath)) {
return [];
}

const files = readdirSync(dirPath);

if (!files || files.length === 0) {
return null;
return [];
}

const contentTypes: Record<string, unknown>[] = [];
Expand All @@ -33,7 +36,8 @@ export function readContentTypeSchemas(

try {
const filePath = pResolve(dirPath, file);
const contentType = fsUtil.readFile(filePath);
const raw = readFileSync(filePath, 'utf8');
const contentType = JSON.parse(raw) as Record<string, unknown>;
if (contentType) {
contentTypes.push(contentType as Record<string, unknown>);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/contentstack-utilities/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export {
export { FlagInput, ArgInput, FlagDefinition } from '@oclif/core/lib/interfaces/parser';

export { default as TablePrompt } from './inquirer-table-prompt';
export { loadChalk, getChalk } from './chalk';
export type { ChalkInstance } from './chalk';

export { Logger };
export { default as authenticationHandler } from './authentication-handler';
Expand Down
16 changes: 8 additions & 8 deletions packages/contentstack-utilities/src/inquirer-table-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import * as readline from 'readline';
import chalk from 'chalk';
import { getChalk } from './chalk';
import figures from 'figures';
import cliCursor from 'cli-cursor';
import Table from 'cli-table';
Expand Down Expand Up @@ -182,13 +182,13 @@ class TablePrompt {
if (!this.spaceKeyPressed) {
msg +=
' (Press ' +
chalk.cyan.bold('<space>') +
getChalk().cyan.bold('<space>') +
' to select, ' +
chalk.cyan.bold('<Up/Down>') +
getChalk().cyan.bold('<Up/Down>') +
' rows, ' +
chalk.cyan.bold('<Left/Right>') +
getChalk().cyan.bold('<Left/Right>') +
' columns, ' +
chalk.cyan.bold('<Enter>') +
getChalk().cyan.bold('<Enter>') +
' to confirm)';
}
return msg;
Expand All @@ -197,8 +197,8 @@ class TablePrompt {
private render(): void {
const [firstIndex, lastIndex] = this.paginate();
const table = new Table({
head: [chalk.reset.dim(`${firstIndex + 1}-${lastIndex + 1} of ${this.rows.length}`)].concat(
this.columns.map((c) => chalk.reset.bold(pluckName(c))),
head: [getChalk().reset.dim(`${firstIndex + 1}-${lastIndex + 1} of ${this.rows.length}`)].concat(
this.columns.map((c) => getChalk().reset.bold(pluckName(c))),
),
});

Expand All @@ -214,7 +214,7 @@ class TablePrompt {
columnValues.push(`${isSelected ? '[' : ' '} ${cellValue} ${isSelected ? ']' : ' '}`);
}
const chalkModifier =
this.status !== 'answered' && this.pointer === rowIndex ? chalk.reset.bold.cyan : chalk.reset;
this.status !== 'answered' && this.pointer === rowIndex ? getChalk().reset.bold.cyan : getChalk().reset;
table.push({ [chalkModifier(pluckName(row))]: columnValues });
}

Expand Down
Loading
Loading