@contentstack/cli-utilities 1.14.4 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Contentstack
3
+ Copyright (c) 2026 Contentstack
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -114,7 +114,7 @@ class AuthHandler {
114
114
  await this.openOAuthURL();
115
115
  }
116
116
  catch (error) {
117
- this.logger.error('OAuth login failed', error.message);
117
+ this.logger.error('OAuth login failed!', error.message);
118
118
  throw error;
119
119
  }
120
120
  }
@@ -123,20 +123,20 @@ class AuthHandler {
123
123
  const server = http_1.default.createServer(async (req, res) => {
124
124
  const queryObject = url_1.default.parse(req.url, true).query;
125
125
  if (!queryObject.code) {
126
- cli_ux_1.default.error('Error occoured while login with OAuth, please login with command - csdx auth:login --oauth');
126
+ cli_ux_1.default.error('Error occurred while logging in with OAuth!');
127
127
  return sendErrorResponse(res);
128
128
  }
129
129
  cli_ux_1.default.print('Auth code successfully fetched.');
130
130
  try {
131
131
  await this.getAccessToken(queryObject.code);
132
132
  await this.setOAuthBaseURL();
133
- cli_ux_1.default.print('Access token fetched using auth code successfully.');
133
+ cli_ux_1.default.print('Access token successfully fetched using auth code.');
134
134
  cli_ux_1.default.print(`You can review the access permissions on the page - ${this.OAuthBaseURL}/#!/marketplace/authorized-apps`);
135
135
  sendSuccessResponse(res);
136
136
  stopServer();
137
137
  }
138
138
  catch (error) {
139
- cli_ux_1.default.error('Error occoured while login with OAuth, please login with command - csdx auth:login --oauth');
139
+ cli_ux_1.default.error('Error occurred while logging in with OAuth!');
140
140
  cli_ux_1.default.error(error);
141
141
  sendErrorResponse(res);
142
142
  stopServer();
@@ -301,8 +301,8 @@ class AuthHandler {
301
301
  }
302
302
  }
303
303
  else {
304
- cli_ux_1.default.error('Invalid/Empty access token.');
305
- throw new Error('Invalid/Empty access token');
304
+ cli_ux_1.default.error('Invalid or empty access token.');
305
+ throw new Error('Invalid or empty access token.');
306
306
  }
307
307
  }
308
308
  async oauthLogout() {
@@ -346,7 +346,7 @@ class AuthHandler {
346
346
  const oauthValidUpto = new Date();
347
347
  oauthValidUpto.setTime(oauthDate.getTime() + 59 * 60 * 1000);
348
348
  if (force) {
349
- cli_ux_1.default.print('Force refreshing the token');
349
+ cli_ux_1.default.print('Forcing token refresh...');
350
350
  return this.refreshToken();
351
351
  }
352
352
  else {
@@ -373,7 +373,7 @@ class AuthHandler {
373
373
  }
374
374
  }
375
375
  else {
376
- cli_ux_1.default.print('No OAuth set');
376
+ cli_ux_1.default.print('No OAuth configuration set.');
377
377
  this.unsetConfigData();
378
378
  }
379
379
  }
@@ -47,7 +47,7 @@ class Config {
47
47
  }
48
48
  }
49
49
  catch (error) {
50
- console.log('No data to be imported from Old config file');
50
+ console.log('No data to import from old configuration file.');
51
51
  }
52
52
  this.set(OLD_CONFIG_BACKUP_FLAG, true);
53
53
  }
@@ -22,17 +22,17 @@ function default_1(deprecatedFlags = [], suggestions = [], customMessage) {
22
22
  }
23
23
  });
24
24
  if (isCommandHasDeprecationFlag) {
25
- let depreactionMessage = '';
25
+ let deprecationMessage = '';
26
26
  if (customMessage) {
27
- depreactionMessage = customMessage;
27
+ deprecationMessage = customMessage;
28
28
  }
29
29
  else {
30
- depreactionMessage = `WARNING!!! You're using the old (soon to be deprecated) Contentstack CLI flags (${deprecatedFlags.join(', ')}).`;
30
+ deprecationMessage = `WARNING!!! You're using the old (soon to be deprecated) Contentstack CLI flags (${deprecatedFlags.join(', ')}).`;
31
31
  if (suggestions.length > 0) {
32
- depreactionMessage += ` We recommend you to use the updated flags (${suggestions.join(', ')}).`;
32
+ deprecationMessage += ` We recommend you to use the updated flags (${suggestions.join(', ')}).`;
33
33
  }
34
34
  }
35
- cli_ux_1.default.print(depreactionMessage, { color: 'yellow' });
35
+ cli_ux_1.default.print(deprecationMessage, { color: 'yellow' });
36
36
  }
37
37
  return input;
38
38
  };
package/lib/helpers.d.ts CHANGED
@@ -27,3 +27,28 @@ export declare const formatError: (error: any) => string;
27
27
  * from.
28
28
  */
29
29
  export declare const redactObject: (obj: any) => any;
30
+ /**
31
+ * Get authentication method from config
32
+ * @returns Authentication method string ('OAuth', 'Basic Auth', or empty string)
33
+ */
34
+ export declare function getAuthenticationMethod(): string;
35
+ /**
36
+ * Creates a standardized context object for logging
37
+ * This context contains all session-level metadata that should be in session.json
38
+ * The apiKey is stored in configHandler so it's available for session.json generation
39
+ *
40
+ * @param commandId - The command ID (e.g., 'cm:stacks:export')
41
+ * @param apiKey - The API key for the stack (will be stored in configHandler for session.json)
42
+ * @param authenticationMethod - Optional authentication method
43
+ * @returns Context object with all session-level metadata
44
+ */
45
+ export declare function createLogContext(commandId: string, apiKey: string, authenticationMethod?: string): {
46
+ command: string;
47
+ module: string;
48
+ userId: string;
49
+ email: string;
50
+ sessionId: string;
51
+ apiKey: string;
52
+ orgId: string;
53
+ authenticationMethod: string;
54
+ };
package/lib/helpers.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.redactObject = exports.formatError = exports.validateRegex = exports.validateFileName = exports.validateUids = exports.sanitizePath = exports.escapeRegExp = exports.validatePath = exports.createDeveloperHubUrl = exports.isManagementTokenValid = exports.getBranchFromAlias = exports.doesBranchExist = exports.isAuthenticated = void 0;
3
+ exports.createLogContext = exports.getAuthenticationMethod = exports.redactObject = exports.formatError = exports.validateRegex = exports.validateFileName = exports.validateUids = exports.sanitizePath = exports.escapeRegExp = exports.validatePath = exports.createDeveloperHubUrl = exports.isManagementTokenValid = exports.getBranchFromAlias = exports.doesBranchExist = exports.isAuthenticated = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const recheck_1 = require("recheck");
6
6
  const traverse_1 = tslib_1.__importDefault(require("traverse"));
@@ -238,3 +238,48 @@ const sensitiveKeys = [
238
238
  /management[-._]?token/i,
239
239
  /delivery[-._]?token/i,
240
240
  ];
241
+ /**
242
+ * Get authentication method from config
243
+ * @returns Authentication method string ('OAuth', 'Basic Auth', or empty string)
244
+ */
245
+ function getAuthenticationMethod() {
246
+ const authType = _1.configHandler.get('authorisationType');
247
+ if (authType === 'OAUTH') {
248
+ return 'OAuth';
249
+ }
250
+ else if (authType === 'BASIC') {
251
+ return 'Basic Auth';
252
+ }
253
+ // Management token detection is command-specific and not stored globally
254
+ // Return empty string if unknown
255
+ return '';
256
+ }
257
+ exports.getAuthenticationMethod = getAuthenticationMethod;
258
+ /**
259
+ * Creates a standardized context object for logging
260
+ * This context contains all session-level metadata that should be in session.json
261
+ * The apiKey is stored in configHandler so it's available for session.json generation
262
+ *
263
+ * @param commandId - The command ID (e.g., 'cm:stacks:export')
264
+ * @param apiKey - The API key for the stack (will be stored in configHandler for session.json)
265
+ * @param authenticationMethod - Optional authentication method
266
+ * @returns Context object with all session-level metadata
267
+ */
268
+ function createLogContext(commandId, apiKey, authenticationMethod) {
269
+ // Store apiKey in configHandler so it's available for session.json
270
+ if (apiKey) {
271
+ _1.configHandler.set('apiKey', apiKey);
272
+ }
273
+ const authMethod = authenticationMethod || getAuthenticationMethod();
274
+ return {
275
+ command: commandId,
276
+ module: '',
277
+ userId: _1.configHandler.get('clientId') || '',
278
+ email: _1.configHandler.get('email') || '',
279
+ sessionId: _1.configHandler.get('sessionId') || '',
280
+ apiKey: apiKey || '',
281
+ orgId: _1.configHandler.get('oauthOrgUid') || '',
282
+ authenticationMethod: authMethod,
283
+ };
284
+ }
285
+ exports.createLogContext = createLogContext;
package/lib/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export * from './fs-utility';
13
13
  export { default as NodeCrypto } from './encrypter';
14
14
  export { Args as args, Flags as flags, Command } from './cli-ux';
15
15
  export * from './helpers';
16
+ export { createLogContext } from './helpers';
16
17
  export * from './interfaces';
17
18
  export * from './date-time';
18
19
  export * from './add-locale';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.log = exports.authenticationHandler = exports.Logger = exports.TablePrompt = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.marketplaceSDKInitiator = exports.MarketplaceSDKInitiator = exports.marketplaceSDKClient = exports.CLITable = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
3
+ exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.log = exports.authenticationHandler = exports.Logger = exports.TablePrompt = exports.execute = exports.ux = exports.flush = exports.settings = exports.toConfiguredId = exports.toStandardizedId = exports.run = exports.Plugin = exports.Parser = exports.Interfaces = exports.HelpBase = exports.Help = exports.loadHelpClass = exports.Flags = exports.Errors = exports.Config = exports.CommandHelp = exports.Args = exports.marketplaceSDKInitiator = exports.MarketplaceSDKInitiator = exports.marketplaceSDKClient = exports.CLITable = exports.createLogContext = exports.Command = exports.flags = exports.args = exports.NodeCrypto = exports.printFlagDeprecation = exports.managementSDKInitiator = exports.managementSDKClient = exports.configHandler = exports.authHandler = exports.messageHandler = exports.CLIError = exports.cliux = exports.LoggerService = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const logger_1 = tslib_1.__importDefault(require("./logger"));
6
6
  exports.Logger = logger_1.default;
@@ -34,6 +34,8 @@ Object.defineProperty(exports, "args", { enumerable: true, get: function () { re
34
34
  Object.defineProperty(exports, "flags", { enumerable: true, get: function () { return cli_ux_2.Flags; } });
35
35
  Object.defineProperty(exports, "Command", { enumerable: true, get: function () { return cli_ux_2.Command; } });
36
36
  tslib_1.__exportStar(require("./helpers"), exports);
37
+ var helpers_1 = require("./helpers");
38
+ Object.defineProperty(exports, "createLogContext", { enumerable: true, get: function () { return helpers_1.createLogContext; } });
37
39
  tslib_1.__exportStar(require("./interfaces"), exports);
38
40
  tslib_1.__exportStar(require("./date-time"), exports);
39
41
  tslib_1.__exportStar(require("./add-locale"), exports);
@@ -29,4 +29,5 @@ declare function handleAndLogError(error: unknown, context?: ErrorContext, error
29
29
  * 4. Home directory (~/contentstack/logs) (fallback)
30
30
  */
31
31
  declare function getLogPath(): string;
32
+ export { getSessionLogPath } from './session-path';
32
33
  export { v2Logger, cliErrorHandler, handleAndLogError, getLogPath };
package/lib/logger/log.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.v2Logger = void 0;
3
+ exports.getLogPath = exports.handleAndLogError = exports.cliErrorHandler = exports.v2Logger = exports.getSessionLogPath = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const fs = tslib_1.__importStar(require("fs"));
6
6
  const os = tslib_1.__importStar(require("os"));
@@ -103,3 +103,6 @@ function getLogPath() {
103
103
  return path.join(os.homedir(), 'contentstack', 'logs');
104
104
  }
105
105
  exports.getLogPath = getLogPath;
106
+ // Re-export getSessionLogPath for external use
107
+ var session_path_1 = require("./session-path");
108
+ Object.defineProperty(exports, "getSessionLogPath", { enumerable: true, get: function () { return session_path_1.getSessionLogPath; } });
@@ -6,6 +6,7 @@ const full_1 = require("klona/full");
6
6
  const path_1 = require("path");
7
7
  const winston = tslib_1.__importStar(require("winston"));
8
8
  const logging_1 = require("../constants/logging");
9
+ const session_path_1 = require("./session-path");
9
10
  class Logger {
10
11
  constructor(config) {
11
12
  this.consoleSensitiveKeys = [
@@ -31,7 +32,9 @@ class Logger {
31
32
  };
32
33
  }
33
34
  getLoggerInstance(level = 'info') {
34
- const filePath = (0, path_1.normalize)(process.env.CS_CLI_LOG_PATH || this.config.basePath).replace(/^(\.\.(\/|\\|$))+/, '');
35
+ // Use session-based path for date-organized logging
36
+ const sessionPath = (0, session_path_1.getSessionLogPath)();
37
+ const filePath = (0, path_1.normalize)(sessionPath).replace(/^(\.\.(\/|\\|$))+/, '');
35
38
  return this.createLogger(level === 'hidden' ? 'error' : level, filePath);
36
39
  }
37
40
  get loggerOptions() {
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Get the session-based log path for date-organized logging
3
+ * Structure: {basePath}/{YYYY-MM-DD}/{command}-{YYYYMMDD-HHMMSS}-{sessionId}/
4
+ *
5
+ * @returns The session-specific log directory path
6
+ */
7
+ export declare function getSessionLogPath(): string;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSessionLogPath = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ const os = tslib_1.__importStar(require("os"));
7
+ const path = tslib_1.__importStar(require("path"));
8
+ const __1 = require("..");
9
+ const log_1 = require("./log");
10
+ /**
11
+ * Extract module name from command ID
12
+ * Example: "cm:stacks:audit" -> "audit"
13
+ */
14
+ function extractModule(commandId) {
15
+ if (!commandId || commandId === 'unknown') {
16
+ return '';
17
+ }
18
+ // Split by colon and get the last part
19
+ const parts = commandId.split(':');
20
+ return parts[parts.length - 1] || '';
21
+ }
22
+ /**
23
+ * Generate session metadata object for session.json
24
+ * Uses createLogContext() to get base context, then adds session-specific metadata
25
+ */
26
+ function generateSessionMetadata(commandId, sessionId, startTimestamp) {
27
+ const originalCommandId = __1.configHandler.get('currentCommandId') || commandId;
28
+ const module = extractModule(originalCommandId);
29
+ const apiKey = __1.configHandler.get('apiKey') || '';
30
+ const baseContext = (0, __1.createLogContext)(originalCommandId, apiKey);
31
+ return Object.assign(Object.assign({}, baseContext), { module: module, sessionId: sessionId, startTimestamp: startTimestamp.toISOString(), MachineEnvironment: {
32
+ nodeVersion: process.version,
33
+ os: os.platform(),
34
+ hostname: os.hostname(),
35
+ CLI_VERSION: __1.configHandler.get('CLI_VERSION') || '',
36
+ } });
37
+ }
38
+ /**
39
+ * Create session.json metadata file in the session directory
40
+ */
41
+ function createSessionMetadataFile(sessionPath, metadata) {
42
+ const metadataPath = path.join(sessionPath, 'session.json');
43
+ try {
44
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf8');
45
+ }
46
+ catch (error) {
47
+ // Silently fail if metadata file cannot be created
48
+ // Logging here would cause circular dependency
49
+ // The session folder and logs will still be created
50
+ }
51
+ }
52
+ /**
53
+ * Get the session-based log path for date-organized logging
54
+ * Structure: {basePath}/{YYYY-MM-DD}/{command}-{YYYYMMDD-HHMMSS}-{sessionId}/
55
+ *
56
+ * @returns The session-specific log directory path
57
+ */
58
+ function getSessionLogPath() {
59
+ // Get base log path
60
+ const basePath = (0, log_1.getLogPath)();
61
+ // Get current date in YYYY-MM-DD format
62
+ const now = new Date();
63
+ const dateStr = now.toISOString().split('T')[0]; // YYYY-MM-DD
64
+ // Get command ID (fallback to 'unknown' if not set)
65
+ let commandId = __1.configHandler.get('currentCommandId') || 'unknown';
66
+ // Sanitize command ID - remove colons and replace with hyphens for folder name
67
+ commandId = commandId === null || commandId === void 0 ? void 0 : commandId.replace(/:/g, '-');
68
+ // Use helper methods to format date and time
69
+ const dateStrFormatted = (0, __1.formatDate)(now); // YYYYMMDD
70
+ const timeStrFormatted = (0, __1.formatTime)(now); // HHMMSS
71
+ const timestamp = `${dateStrFormatted}-${timeStrFormatted}`; // YYYYMMDD-HHMMSS
72
+ let sessionId = __1.configHandler.get('sessionId');
73
+ if (!sessionId) {
74
+ // Format: first 8 chars of command + timestamp (YYYYMMDDHHMMSS)
75
+ const timestampForId = `${dateStrFormatted}${timeStrFormatted}`; // YYYYMMDDHHMMSS
76
+ const commandHash = commandId.substring(0, 8).padEnd(8, '0'); // Use first 8 chars of command
77
+ sessionId = `${commandHash}-${timestampForId}`;
78
+ }
79
+ // Create session folder name: command-YYYYMMDD-HHMMSS-sessionId
80
+ const sessionFolderName = `${commandId}-${timestamp}-${sessionId}`;
81
+ // Build full session path
82
+ const sessionPath = path.join(basePath, dateStr, sessionFolderName);
83
+ // Ensure directory exists
84
+ const isNewSession = !fs.existsSync(sessionPath);
85
+ if (isNewSession) {
86
+ fs.mkdirSync(sessionPath, { recursive: true });
87
+ }
88
+ // Create session.json metadata file for new sessions
89
+ // This ensures metadata is created before any logs are written
90
+ if (isNewSession) {
91
+ const metadata = generateSessionMetadata(__1.configHandler.get('currentCommandId') || commandId, sessionId, now);
92
+ createSessionMetadataFile(sessionPath, metadata);
93
+ }
94
+ return sessionPath;
95
+ }
96
+ exports.getSessionLogPath = getSessionLogPath;
package/lib/logger.js CHANGED
@@ -26,7 +26,7 @@ class LoggerService {
26
26
  stringifiedParam = JSON.stringify(info.obj);
27
27
  }
28
28
  catch (error) {
29
- console.log('warning: failed to log the result');
29
+ console.log('Warning: Failed to log the result');
30
30
  }
31
31
  // parse message
32
32
  info.message = index_1.messageHandler.parse(info.message);
@@ -23,7 +23,7 @@ class Messages {
23
23
  this.messages = {};
24
24
  }
25
25
  else {
26
- throw new cli_error_1.default(error.message);
26
+ throw new cli_error_1.default(`Error: ${error.message}`);
27
27
  }
28
28
  }
29
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-utilities",
3
- "version": "1.14.4",
3
+ "version": "1.16.0",
4
4
  "description": "Utilities for contentstack projects",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -43,10 +43,10 @@
43
43
  "conf": "^10.2.0",
44
44
  "dotenv": "^16.5.0",
45
45
  "figures": "^3.2.0",
46
- "inquirer": "8.2.6",
46
+ "inquirer": "8.2.7",
47
47
  "inquirer-search-checkbox": "^1.0.0",
48
48
  "inquirer-search-list": "^1.2.6",
49
- "js-yaml": "^4.1.0",
49
+ "js-yaml": "^4.1.1",
50
50
  "klona": "^2.0.6",
51
51
  "lodash": "^4.17.21",
52
52
  "mkdirp": "^1.0.4",