Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
fileignoreconfig:
- filename: package-lock.json
checksum: d3b93fad9630655f037e36b78fea3354f1a038988562254afdad0f6e54ece12d
checksum: 34aa1a9da3b0c085598486f025fcf7972d9a70f16ea605283c98af9e692a01a4
- filename: pnpm-lock.yaml
checksum: aa6177859aaa87caf2892e8034657fd485c3abe7c13a833fd28449a1d33fa950
checksum: 558462842f0da2675d9c08a7e87a8f1e8266901d549e6387b15b3c1370f0f5c2
- filename: packages/contentstack-import-setup/test/unit/backup-handler.test.ts
checksum: 0582d62b88834554cf12951c8690a73ef3ddbb78b82d2804d994cf4148e1ef93
- filename: packages/contentstack-import-setup/test/config.json
Expand Down Expand Up @@ -211,4 +211,6 @@ fileignoreconfig:
checksum: 49dd8e754a0d3635585a74e943ab097593f061089a7cddc22683ec6caddbb3c5
- filename: packages/contentstack-export/test/unit/export/modules/personalize.test.ts
checksum: 83cf034fabee00b42b4243a8c0b8ba280ab7c1e68ffd741c49c31aaee8ca0315
- filename: packages/contentstack-utilities/test/unit/logger.test.ts
checksum: 11778d0252202c18a1ca6a38883d6e12fc324ff86ad0fe058bc2505f9cd66ba3
version: "1.0"
2,116 changes: 1,056 additions & 1,060 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/contentstack-audit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
],
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"@oclif/plugin-plugins": "^5.4.38",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"otplib": "^12.0.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-bootstrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"dependencies": {
"@contentstack/cli-cm-seed": "~1.13.0",
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"inquirer": "8.2.7",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-branches/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@contentstack/cli-command": "~1.6.1",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"chalk": "^4.1.2",
"just-diff": "^6.0.2",
"lodash": "^4.17.21"
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-bulk-publish/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-config": "~1.15.0",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"chalk": "^4.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-clone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"@contentstack/cli-cm-export": "~1.21.0",
"@contentstack/cli-cm-import": "~1.29.0",
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"chalk": "^4.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-command/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"test:unit": "mocha --timeout 10000 --forbid-only \"test/unit/**/*.test.ts\""
},
"dependencies": {
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"contentstack": "^3.25.3",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28"
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"lodash": "^4.17.21"
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-export-to-csv/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.32",
"fast-csv": "^4.3.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-export/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-variants": "~1.3.4",
"@oclif/core": "^4.3.3",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"async": "^3.2.6",
"big-json": "^3.2.0",
"bluebird": "^3.7.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-import-setup/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"big-json": "^3.2.0",
"chalk": "^4.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-import/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dependencies": {
"@contentstack/cli-audit": "~1.16.0",
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@contentstack/management": "~1.22.0",
"@contentstack/cli-variants": "~1.3.4",
"@oclif/core": "^4.3.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-migrate-rte/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@contentstack/json-rte-serializer": "~2.1.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-migration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@oclif/core": "^4.3.0",
"@oclif/plugin-help": "^6.2.28",
"async": "^3.2.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-seed/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dependencies": {
"@contentstack/cli-cm-import": "~1.29.0",
"@contentstack/cli-command": "~1.6.1",
"@contentstack/cli-utilities": "~1.14.4",
"@contentstack/cli-utilities": "~1.15.0",
"@contentstack/management": "~1.22.0",
"inquirer": "8.2.7",
"mkdirp": "^1.0.4",
Expand Down
4 changes: 2 additions & 2 deletions packages/contentstack-utilities/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/cli-utilities",
"version": "1.14.4",
"version": "1.15.0",
"description": "Utilities for contentstack projects",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down Expand Up @@ -46,7 +46,7 @@
"inquirer": "8.2.7",
"inquirer-search-checkbox": "^1.0.0",
"inquirer-search-list": "^1.2.6",
"js-yaml": "^4.1.0",
"js-yaml": "^4.1.1",
"klona": "^2.0.6",
"lodash": "^4.17.21",
"mkdirp": "^1.0.4",
Expand Down
3 changes: 3 additions & 0 deletions packages/contentstack-utilities/src/logger/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { default as Logger } from './logger';
import { CLIErrorHandler } from './cli-error-handler';
import { ErrorContext } from '../interfaces';
import { configHandler } from '..';
import { getSessionLogPath } from './session-path';

let loggerInstance: Logger | null = null;

Expand Down Expand Up @@ -105,4 +106,6 @@ function getLogPath(): string {
return path.join(os.homedir(), 'contentstack', 'logs');
}

// Re-export getSessionLogPath for external use
export { getSessionLogPath } from './session-path';
export { v2Logger, cliErrorHandler, handleAndLogError, getLogPath };
5 changes: 4 additions & 1 deletion packages/contentstack-utilities/src/logger/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { normalize } from 'path';
import * as winston from 'winston';
import { levelColors, logLevels } from '../constants/logging';
import { LoggerConfig, LogLevel, LogType } from '../interfaces/index';
import { getSessionLogPath } from './session-path';

export default class Logger {
private loggers: Record<string, winston.Logger>;
Expand Down Expand Up @@ -36,7 +37,9 @@ export default class Logger {
}

getLoggerInstance(level: 'error' | 'info' | 'warn' | 'debug' | 'hidden' = 'info'): winston.Logger {
const filePath = normalize(process.env.CS_CLI_LOG_PATH || this.config.basePath).replace(/^(\.\.(\/|\\|$))+/, '');
// Use session-based path for date-organized logging
const sessionPath = getSessionLogPath();
const filePath = normalize(sessionPath).replace(/^(\.\.(\/|\\|$))+/, '');
return this.createLogger(level === 'hidden' ? 'error' : level, filePath);
}

Expand Down
91 changes: 91 additions & 0 deletions packages/contentstack-utilities/src/logger/session-path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as shortUUID from 'short-uuid';
import { configHandler } from '..';

/**
* Get the log path for centralized logging
* Priority:
* 1. CS_CLI_LOG_PATH environment variable (user override)
* 2. User config (log.path from CLI config)
* 3. Current working directory + logs (where user ran the command)
* 4. Home directory (~/contentstack/logs) (fallback)
*/
function getLogPath(): string {
// 1. Environment variable override
if (process.env.CS_CLI_LOG_PATH) {
return process.env.CS_CLI_LOG_PATH;
}

// 2. User configured path
const configuredPath = configHandler.get('log.path');
if (configuredPath) {
return configuredPath;
}

// 3. Use current working directory (where user ran the command)
try {
const cwdPath = path.join(process.cwd(), 'logs');
if (!fs.existsSync(cwdPath)) {
fs.mkdirSync(cwdPath, { recursive: true });
}
fs.accessSync(cwdPath, fs.constants.W_OK);
return cwdPath;
} catch (error) {
// If current directory is not writable, fall back to home directory
}

// 4. Fallback to home directory
return path.join(os.homedir(), 'contentstack', 'logs');
}

/**
* Get the session-based log path for date-organized logging
* Structure: {basePath}/{YYYY-MM-DD}/{command}-{YYYYMMDD-HHMMSS}-{sessionId}/
*
* @returns The session-specific log directory path
*/
export function getSessionLogPath(): string {
// Get base log path
const basePath = getLogPath();

// Get current date in YYYY-MM-DD format
const now = new Date();
const dateStr = now.toISOString().split('T')[0]; // YYYY-MM-DD

// Get command ID (fallback to 'unknown' if not set)
let commandId = configHandler.get('currentCommandId') || 'unknown';
// Sanitize command ID - remove colons and replace with hyphens for folder name
commandId = commandId.replace(/:/g, '-');

// Get sessionId (fallback to short UUID if not set)
let sessionId = configHandler.get('sessionId');
if (!sessionId) {
sessionId = shortUUID.generate();
configHandler.set('sessionId', sessionId);
}

// Get timestamp in YYYYMMDD-HHMMSS format
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const timestamp = `${year}${month}${day}-${hours}${minutes}${seconds}`;

// Create session folder name: command-YYYYMMDD-HHMMSS-sessionId
const sessionFolderName = `${commandId}-${timestamp}-${sessionId}`;

// Build full session path
const sessionPath = path.join(basePath, dateStr, sessionFolderName);

// Ensure directory exists
if (!fs.existsSync(sessionPath)) {
fs.mkdirSync(sessionPath, { recursive: true });
}

return sessionPath;
}

29 changes: 17 additions & 12 deletions packages/contentstack-utilities/test/unit/cliErrorHandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { expect } from 'chai';
import { fancy } from 'fancy-test';
import CLIErrorHandler from '../../src/logger/cliErrorHandler';
import CLIErrorHandler from '../../src/logger/cli-error-handler';
import { ERROR_TYPES } from '../../src/constants/errorTypes';

describe('CLIErrorHandler', () => {
let errorHandler: CLIErrorHandler;

beforeEach(() => {
errorHandler = new CLIErrorHandler(true); // debug mode enabled
errorHandler = new CLIErrorHandler();
});

fancy.it('should normalize string error to Error object', () => {
Expand Down Expand Up @@ -36,7 +36,7 @@ describe('CLIErrorHandler', () => {
expect(hidden).to.equal(true);
});

fancy.it('should extract debug payload correctly', () => {
fancy.it('should extract error payload correctly', () => {
const error = new Error('API error');
(error as any).request = {
method: 'GET',
Expand All @@ -49,11 +49,14 @@ describe('CLIErrorHandler', () => {
statusText: 'Internal Server Error',
data: { error: 'fail' },
};
(error as any).status = 500; // Also set status on error directly

const debugPayload = errorHandler['extractDebugPayload'](error);
expect(debugPayload.request.method).to.equal('GET');
expect(debugPayload.response.status).to.equal(500);
expect(debugPayload.command).to.be.undefined;
const errorPayload = errorHandler['extractErrorPayload'](error);
expect(errorPayload.request.method).to.equal('GET');
expect(errorPayload.response.status).to.equal(500);
expect(errorPayload.status).to.equal(500);
expect(errorPayload.name).to.equal('Error');
expect(errorPayload.message).to.equal('API error');
});

fancy.it('should return full classified error with context', () => {
Expand All @@ -66,7 +69,8 @@ describe('CLIErrorHandler', () => {

expect(classified.type).to.equal(ERROR_TYPES.SERVER_ERROR);
expect(classified.message).to.equal('Test error');
expect(classified.context).to.contain('testOp');
expect(classified.meta?.operation).to.equal('testOp');
expect(classified.meta?.component).to.equal('testComponent');
expect(classified.meta?.email).to.be.undefined;
expect(classified.hidden).to.be.false;
});
Expand All @@ -80,17 +84,18 @@ describe('CLIErrorHandler', () => {
fancy.it('extractMeta should return full meta', () => {
const meta = errorHandler['extractMeta']({
email: 'a@b.com',
apiKey: '123',
sessionId: 's1',
userId: 'u1',
orgId: 'o1',
});
}, 'API_ERROR');
// extractMeta only extracts specific fields: operation, component, userId, sessionId, orgId, email
// apiKey is not extracted by extractMeta
expect(meta).to.deep.equal({
email: 'a@b.com',
apiKey: '123',
sessionId: 's1',
userId: 'u1',
orgId: 'o1',
errorType: 'API_ERROR',
});
});

Expand All @@ -103,6 +108,6 @@ describe('CLIErrorHandler', () => {

const result = errorHandler.classifyError(invalidError);
expect(result.type).to.equal(ERROR_TYPES.NORMALIZATION);
expect(result.message).to.include('Failed to normalize');
expect(result.message).to.equal('Failed to process error');
});
});
Loading
Loading