@contentstack/cli-utilities 1.13.2 → 1.14.1

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.
@@ -26,16 +26,17 @@ class AuthenticationHandler {
26
26
  index_1.cliux.print('Session timed out, please login to proceed', {
27
27
  color: 'yellow',
28
28
  });
29
- process.exit(1);
29
+ throw new Error('Session timed out, please login to proceed');
30
30
  }
31
31
  break;
32
32
  }
33
33
  }
34
34
  catch (error) {
35
- index_1.cliux.print(`Error occurred while fetching auth details: ${error.message}`, {
35
+ const formattedError = (0, index_1.formatError)(error);
36
+ index_1.cliux.print(`Error occurred while fetching auth details: ${formattedError}`, {
36
37
  color: 'red',
37
38
  });
38
- process.exit(1);
39
+ throw error;
39
40
  }
40
41
  }
41
42
  get isOauthEnabled() {
@@ -48,6 +49,7 @@ class AuthenticationHandler {
48
49
  return this.token;
49
50
  }
50
51
  async refreshAccessToken(error, maxRetryCount = 1) {
52
+ var _a, _b;
51
53
  // Add configurable delay only for CI/CD pipelines
52
54
  const delayMs = process.env.DELAY_MS;
53
55
  if (delayMs) {
@@ -71,7 +73,8 @@ class AuthenticationHandler {
71
73
  if (refreshed) {
72
74
  return this.refreshAccessToken(error, maxRetryCount); // Retry after refreshing the token
73
75
  }
74
- console.log('API(401) case error:-', error.response);
76
+ const errorDetails = (0, index_1.formatError)(error);
77
+ index_1.cliux.print(`Authentication failed: ${errorDetails}`, { color: 'red' });
75
78
  // For Basic Auth, exit immediately without retrying
76
79
  return;
77
80
  }
@@ -79,10 +82,12 @@ class AuthenticationHandler {
79
82
  case 429:
80
83
  case 408:
81
84
  if (maxRetryCount >= 3) {
82
- index_1.cliux.print('Max retry count reached, please login to proceed', {
83
- color: 'yellow',
84
- });
85
- process.exit(1);
85
+ const errorDetails = (0, index_1.formatError)(error);
86
+ const statusText = ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) === 429 ? 'Rate Limited' : 'Request Timeout';
87
+ index_1.cliux.print(`Max retry attempts exceeded (${maxRetryCount}/3)`, { color: 'red' });
88
+ index_1.cliux.print(`Status: ${(_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.status} - ${statusText}`, { color: 'yellow' });
89
+ index_1.cliux.print(`Error: ${errorDetails}`, { color: 'white' });
90
+ return;
86
91
  }
87
92
  maxRetryCount++; // Increment for the next retry attempt
88
93
  // These cases require a wait, adding a delay before retrying
@@ -99,7 +104,9 @@ class AuthenticationHandler {
99
104
  index_1.cliux.print('Session timed out, please login to proceed', {
100
105
  color: 'yellow',
101
106
  });
102
- process.exit();
107
+ index_1.cliux.print('\nTo fix this:', { color: 'cyan' });
108
+ index_1.cliux.print('• Run: "csdx auth:login"', { color: 'white' });
109
+ resolve(false);
103
110
  }
104
111
  else if (this.authType === 'OAUTH') {
105
112
  index_1.authHandler.host = hostName;
@@ -111,7 +118,9 @@ class AuthenticationHandler {
111
118
  resolve(true);
112
119
  })
113
120
  .catch((error) => {
114
- console.log(error);
121
+ const errorDetails = (0, index_1.formatError)(error);
122
+ index_1.cliux.print('OAuth Token Refresh Failed', { color: 'red' });
123
+ index_1.cliux.print(`Error: ${errorDetails}`, { color: 'white' });
115
124
  resolve(false);
116
125
  });
117
126
  }
@@ -119,7 +128,7 @@ class AuthenticationHandler {
119
128
  index_1.cliux.print('You do not have the permissions to perform this action, please login to proceed', {
120
129
  color: 'yellow',
121
130
  });
122
- process.exit();
131
+ resolve(false);
123
132
  }
124
133
  });
125
134
  }
package/lib/helpers.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import { ContentstackClient } from '.';
1
2
  export declare const isAuthenticated: () => boolean;
2
3
  export declare const doesBranchExist: (stack: any, branchName: any) => Promise<any>;
4
+ export declare const getBranchFromAlias: (stack: ReturnType<ContentstackClient['stack']>, branchAlias: string) => Promise<string>;
3
5
  export declare const isManagementTokenValid: (stackAPIKey: any, managementToken: any) => Promise<{
4
6
  valid: boolean;
5
7
  message?: undefined;
@@ -17,7 +19,7 @@ export declare const sanitizePath: (str: string) => string;
17
19
  export declare const validateUids: (uid: any) => boolean;
18
20
  export declare const validateFileName: (fileName: any) => boolean;
19
21
  export declare const validateRegex: (str: unknown) => import("recheck").Diagnostics;
20
- export declare const formatError: (error: any) => any;
22
+ export declare const formatError: (error: any) => string;
21
23
  /**
22
24
  * The function redactObject takes an object as input and replaces any sensitive keys with the string
23
25
  * '[REDACTED]'.
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.doesBranchExist = exports.isAuthenticated = void 0;
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;
4
4
  const tslib_1 = require("tslib");
5
5
  const recheck_1 = require("recheck");
6
6
  const traverse_1 = tslib_1.__importDefault(require("traverse"));
@@ -17,6 +17,22 @@ const doesBranchExist = async (stack, branchName) => {
17
17
  });
18
18
  };
19
19
  exports.doesBranchExist = doesBranchExist;
20
+ const getBranchFromAlias = async (stack, branchAlias) => {
21
+ if (!stack || !branchAlias || typeof branchAlias !== 'string') {
22
+ throw new Error('Invalid input. Both stack and branch alias are required.');
23
+ }
24
+ try {
25
+ const response = await stack.branchAlias(branchAlias).fetch();
26
+ if (!(response === null || response === void 0 ? void 0 : response.uid)) {
27
+ throw new Error(`Invalid Branch Alias. No Branch found for the branch alias: ${branchAlias}`);
28
+ }
29
+ return response.uid;
30
+ }
31
+ catch (error) {
32
+ throw error;
33
+ }
34
+ };
35
+ exports.getBranchFromAlias = getBranchFromAlias;
20
36
  const isManagementTokenValid = async (stackAPIKey, managementToken) => {
21
37
  var _a;
22
38
  const httpClient = new _1.HttpClient({ headers: { api_key: stackAPIKey, authorization: managementToken } });
@@ -86,7 +102,7 @@ const validateRegex = (str) => {
86
102
  };
87
103
  exports.validateRegex = validateRegex;
88
104
  const formatError = function (error) {
89
- var _a, _b, _c, _d, _e;
105
+ var _a, _b, _c, _d, _e, _f;
90
106
  let parsedError;
91
107
  // Parse the error
92
108
  try {
@@ -103,6 +119,26 @@ const formatError = function (error) {
103
119
  catch (e) {
104
120
  parsedError = error;
105
121
  }
122
+ // Helper function to append error details
123
+ const appendErrorDetails = (message, errorObj) => {
124
+ if (errorObj.errors && typeof errorObj.errors === 'object' && Object.keys(errorObj.errors).length > 0) {
125
+ const entityNames = {
126
+ authorization: 'Authentication',
127
+ api_key: 'Stack API key',
128
+ uid: 'Content Type',
129
+ access_token: 'Delivery Token',
130
+ };
131
+ const errorList = Object.entries(errorObj.errors)
132
+ .map(([field, errors]) => {
133
+ const errorArray = Array.isArray(errors) ? errors : [errors];
134
+ const fieldName = entityNames[field] || field;
135
+ return ` • ${fieldName}: ${errorArray.join(', ')}`;
136
+ })
137
+ .join('\n');
138
+ return `${message}\n\nError Details:\n${errorList}\n`;
139
+ }
140
+ return message;
141
+ };
106
142
  if (parsedError && typeof parsedError === 'object' && Object.keys(parsedError).length === 0) {
107
143
  if (!parsedError.message &&
108
144
  !parsedError.code &&
@@ -113,21 +149,21 @@ const formatError = function (error) {
113
149
  }
114
150
  }
115
151
  if ((_b = (_a = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errorMessage) {
116
- return parsedError.response.data.errorMessage;
152
+ return appendErrorDetails(parsedError.response.data.errorMessage, ((_c = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _c === void 0 ? void 0 : _c.data) || parsedError);
117
153
  }
118
154
  if (parsedError === null || parsedError === void 0 ? void 0 : parsedError.errorMessage) {
119
- return parsedError.errorMessage;
155
+ return appendErrorDetails(parsedError.errorMessage, parsedError);
120
156
  }
121
- const status = (parsedError === null || parsedError === void 0 ? void 0 : parsedError.status) || ((_c = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _c === void 0 ? void 0 : _c.status);
122
- const errorCode = (parsedError === null || parsedError === void 0 ? void 0 : parsedError.errorCode) || ((_e = (_d = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.errorCode);
157
+ const status = (parsedError === null || parsedError === void 0 ? void 0 : parsedError.status) || ((_d = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _d === void 0 ? void 0 : _d.status);
158
+ const errorCode = (parsedError === null || parsedError === void 0 ? void 0 : parsedError.errorCode) || ((_f = (_e = parsedError === null || parsedError === void 0 ? void 0 : parsedError.response) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.errorCode);
123
159
  if (status === 422 && errorCode === 104) {
124
- return 'Invalid email or password. Please check your credentials and try again.';
160
+ return appendErrorDetails('Invalid email or password. Please check your credentials and try again.', parsedError);
125
161
  }
126
162
  if (status === 401) {
127
- return 'Authentication failed. Please check your credentials.';
163
+ return appendErrorDetails('Authentication failed. Please check your credentials.', parsedError);
128
164
  }
129
165
  if (status === 403) {
130
- return 'Access denied. Please check your permissions.';
166
+ return appendErrorDetails('Access denied. Please check your permissions.', parsedError);
131
167
  }
132
168
  // Check for specific SSL error
133
169
  if ((parsedError === null || parsedError === void 0 ? void 0 : parsedError.code) === 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY') {
@@ -156,25 +192,8 @@ const formatError = function (error) {
156
192
  catch (e) {
157
193
  // message is not in JSON format, no need to parse
158
194
  }
159
- // Append detailed error information if available
160
- if (parsedError.errors && typeof parsedError.errors === 'object' && Object.keys(parsedError.errors).length > 0) {
161
- const entityNames = {
162
- authorization: 'Authentication',
163
- api_key: 'Stack API key',
164
- uid: 'Content Type',
165
- // deepcode ignore HardcodedNonCryptoSecret: The hardcoded value 'access_token' is used as a key in an error message mapping object and does not represent a sensitive secret or cryptographic key.
166
- access_token: 'Delivery Token',
167
- };
168
- const errorList = Object.entries(parsedError.errors)
169
- .map(([field, errors]) => {
170
- const errorArray = Array.isArray(errors) ? errors : [errors];
171
- const fieldName = entityNames[field] || field;
172
- return ` • ${fieldName}: ${errorArray.join(', ')}`;
173
- })
174
- .join('\n');
175
- message += `\n\nAPI Errors:\n${errorList}`;
176
- }
177
- return message;
195
+ // Always append error details at the end
196
+ return appendErrorDetails(message, parsedError);
178
197
  };
179
198
  exports.formatError = formatError;
180
199
  /**
@@ -82,21 +82,15 @@ class CLIErrorHandler {
82
82
  * Extracts a clear, concise error message from various error types.
83
83
  */
84
84
  extractClearMessage(error) {
85
- var _a, _b, _c, _d;
86
- if ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errorMessage) {
87
- return error.response.data.errorMessage;
88
- }
89
- if (error === null || error === void 0 ? void 0 : error.errorMessage) {
90
- return error.errorMessage;
91
- }
85
+ var _a, _b;
92
86
  // Use existing formatError function for other cases
93
87
  try {
94
88
  const formattedMessage = (0, helpers_1.formatError)(error);
95
89
  return formattedMessage || 'An error occurred. Please try again.';
96
90
  }
97
- catch (_e) {
91
+ catch (_c) {
98
92
  // Fallback to basic error message extraction if formatError fails
99
- if (typeof ((_d = (_c = error === null || error === void 0 ? void 0 : error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.errorMessage) === 'string') {
93
+ if (typeof ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errorMessage) === 'string') {
100
94
  return error.response.data.errorMessage;
101
95
  }
102
96
  if (typeof (error === null || error === void 0 ? void 0 : error.errorMessage) === 'string') {
package/lib/logger/log.js CHANGED
@@ -10,9 +10,15 @@ const cli_error_handler_1 = require("./cli-error-handler");
10
10
  const __1 = require("..");
11
11
  let loggerInstance = null;
12
12
  function createLoggerInstance() {
13
+ var _a;
14
+ const logConfig = __1.configHandler.get('log');
15
+ const logLevel = (logConfig === null || logConfig === void 0 ? void 0 : logConfig.level) || 'info';
16
+ const showConsoleLogs = (_a = logConfig === null || logConfig === void 0 ? void 0 : logConfig['show-console-logs']) !== null && _a !== void 0 ? _a : false;
13
17
  const config = {
14
18
  basePath: getLogPath(),
15
- logLevel: __1.configHandler.get('log.level') || 'info',
19
+ logLevel: logLevel,
20
+ consoleLoggingEnabled: showConsoleLogs,
21
+ consoleLogLevel: logLevel,
16
22
  };
17
23
  return new logger_1.default(config);
18
24
  }
@@ -95,6 +95,10 @@ class Logger {
95
95
  }
96
96
  }
97
97
  shouldLog(level, target) {
98
+ // If console logging is disabled, don't log to console
99
+ if (target === 'console' && this.config.consoleLoggingEnabled === false) {
100
+ return false;
101
+ }
98
102
  const configLevel = target === 'console' ? this.config.consoleLogLevel : this.config.logLevel;
99
103
  const minLevel = configLevel ? logging_1.logLevels[configLevel] : 2;
100
104
  return logging_1.logLevels[level] <= minLevel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentstack/cli-utilities",
3
- "version": "1.13.2",
3
+ "version": "1.14.1",
4
4
  "description": "Utilities for contentstack projects",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",