@contentstack/cli-utilities 2.0.0-beta → 2.0.0-beta.10
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/lib/auth-handler.d.ts +5 -2
- package/lib/auth-handler.js +29 -29
- package/lib/chalk.d.ts +15 -0
- package/lib/chalk.js +66 -0
- package/lib/cli-ux.js +23 -10
- package/lib/config-handler.js +4 -4
- package/lib/constants/logging.d.ts +1 -1
- package/lib/constants/logging.js +3 -3
- package/lib/content-type-utils.d.ts +7 -0
- package/lib/content-type-utils.js +44 -0
- package/lib/contentstack-management-sdk.js +14 -4
- package/lib/contentstack-marketplace-sdk.d.ts +2 -2
- package/lib/contentstack-marketplace-sdk.js +1 -1
- package/lib/fs-utility/core.d.ts +0 -1
- package/lib/fs-utility/core.js +2 -6
- package/lib/fs-utility/helper.js +2 -3
- package/lib/helpers.d.ts +3 -1
- package/lib/helpers.js +14 -4
- package/lib/http-client/client.d.ts +2 -2
- package/lib/http-client/client.js +22 -2
- package/lib/http-client/http-response.d.ts +1 -1
- package/lib/http-client/http-response.js +1 -0
- package/lib/index.d.ts +4 -1
- package/lib/index.js +5 -1
- package/lib/inquirer-table-prompt.d.ts +49 -28
- package/lib/inquirer-table-prompt.js +144 -136
- package/lib/interfaces/index.d.ts +3 -1
- package/lib/logger/cli-error-handler.js +1 -1
- package/lib/logger/log.js +4 -4
- package/lib/logger/session-path.d.ts +5 -0
- package/lib/logger/session-path.js +18 -3
- package/lib/message-handler.d.ts +0 -3
- package/lib/message-handler.js +6 -10
- package/lib/progress-summary/cli-progress-manager.d.ts +3 -1
- package/lib/progress-summary/cli-progress-manager.js +46 -36
- package/lib/progress-summary/summary-manager.js +30 -30
- package/lib/proxy-helper.d.ts +42 -1
- package/lib/proxy-helper.js +183 -32
- package/package.json +28 -27
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
-
const chalk_1 =
|
|
4
|
+
const chalk_1 = require("../chalk");
|
|
5
5
|
const ora_1 = tslib_1.__importDefault(require("ora"));
|
|
6
6
|
const cli_progress_1 = tslib_1.__importDefault(require("cli-progress"));
|
|
7
7
|
const summary_manager_1 = tslib_1.__importDefault(require("./summary-manager"));
|
|
@@ -46,14 +46,16 @@ class CLIProgressManager {
|
|
|
46
46
|
return;
|
|
47
47
|
const safeBranchName = branchName || 'main';
|
|
48
48
|
const branchInfo = headerTitle || `${safeBranchName === null || safeBranchName === void 0 ? void 0 : safeBranchName.toUpperCase()} CONTENT`;
|
|
49
|
-
console.log('\n' + chalk_1.
|
|
49
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold('='.repeat(80)));
|
|
50
50
|
if (branchInfo) {
|
|
51
|
-
console.log(chalk_1.
|
|
51
|
+
console.log((0, chalk_1.getChalk)().bold.white(` ${branchInfo}`));
|
|
52
52
|
}
|
|
53
|
-
console.log(chalk_1.
|
|
53
|
+
console.log((0, chalk_1.getChalk)().bold('='.repeat(80)) + '\n');
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Print the final summary for all modules using strategies
|
|
56
|
+
* Print the final summary for all modules using strategies.
|
|
57
|
+
* When showConsoleLogs is enabled, skip the Progress Manager summary block
|
|
58
|
+
* so output is pure timestamped log lines (per documentation).
|
|
57
59
|
*/
|
|
58
60
|
static printGlobalSummary() {
|
|
59
61
|
if (!CLIProgressManager.globalSummary) {
|
|
@@ -238,20 +240,20 @@ class CLIProgressManager {
|
|
|
238
240
|
this.multiBar = new cli_progress_1.default.MultiBar({
|
|
239
241
|
clearOnComplete: false,
|
|
240
242
|
hideCursor: true,
|
|
241
|
-
format: ' {label} |' + chalk_1.
|
|
243
|
+
format: ' {label} |' + (0, chalk_1.getChalk)().cyan('{bar}') + '| {percentage}% | {value}/{total} | {status}',
|
|
242
244
|
barCompleteChar: '\u2588',
|
|
243
245
|
barIncompleteChar: '\u2591',
|
|
244
246
|
}, cli_progress_1.default.Presets.shades_classic);
|
|
245
247
|
if (!this.showConsoleLogs) {
|
|
246
|
-
console.log(chalk_1.
|
|
248
|
+
console.log((0, chalk_1.getChalk)().bold.cyan(`\n${this.moduleName}:`));
|
|
247
249
|
}
|
|
248
250
|
}
|
|
249
251
|
else if (this.total > 0) {
|
|
250
252
|
if (!this.showConsoleLogs) {
|
|
251
|
-
console.log(chalk_1.
|
|
253
|
+
console.log((0, chalk_1.getChalk)().bold.cyan(`\n${this.moduleName}:`));
|
|
252
254
|
}
|
|
253
255
|
this.progressBar = new cli_progress_1.default.SingleBar({
|
|
254
|
-
format: ' {label} |' + chalk_1.
|
|
256
|
+
format: ' {label} |' + (0, chalk_1.getChalk)().cyan('{bar}') + '| {percentage}% | {value}/{total} | {status}',
|
|
255
257
|
barCompleteChar: '\u2588',
|
|
256
258
|
barIncompleteChar: '\u2591',
|
|
257
259
|
hideCursor: true,
|
|
@@ -259,13 +261,13 @@ class CLIProgressManager {
|
|
|
259
261
|
const formattedName = this.formatModuleName(this.moduleName);
|
|
260
262
|
const displayName = formattedName.length > 20 ? formattedName.substring(0, 17) + '...' : formattedName;
|
|
261
263
|
this.progressBar.start(this.total, 0, {
|
|
262
|
-
label: chalk_1.
|
|
263
|
-
status: chalk_1.
|
|
264
|
+
label: (0, chalk_1.getChalk)().gray(` └─ ${displayName}`.padEnd(25)),
|
|
265
|
+
status: (0, chalk_1.getChalk)().gray('Starting...'),
|
|
264
266
|
percentage: ' 0',
|
|
265
267
|
});
|
|
266
268
|
}
|
|
267
269
|
else {
|
|
268
|
-
this.spinner = (0, ora_1.default)(`${chalk_1.
|
|
270
|
+
this.spinner = (0, ora_1.default)(`${(0, chalk_1.getChalk)().bold(this.moduleName)}: Processing...`).start();
|
|
269
271
|
}
|
|
270
272
|
}
|
|
271
273
|
/**
|
|
@@ -287,8 +289,8 @@ class CLIProgressManager {
|
|
|
287
289
|
const displayName = this.formatProcessName(processName);
|
|
288
290
|
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
|
|
289
291
|
process.progressBar = this.multiBar.create(total, 0, {
|
|
290
|
-
label: chalk_1.
|
|
291
|
-
status: chalk_1.
|
|
292
|
+
label: (0, chalk_1.getChalk)().gray(indentedLabel),
|
|
293
|
+
status: (0, chalk_1.getChalk)().gray('Pending'),
|
|
292
294
|
percentage: ' 0',
|
|
293
295
|
});
|
|
294
296
|
}
|
|
@@ -324,8 +326,8 @@ class CLIProgressManager {
|
|
|
324
326
|
const displayName = this.formatProcessName(processName);
|
|
325
327
|
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
|
|
326
328
|
process.progressBar.update(0, {
|
|
327
|
-
label: chalk_1.
|
|
328
|
-
status: chalk_1.
|
|
329
|
+
label: (0, chalk_1.getChalk)().yellow(indentedLabel),
|
|
330
|
+
status: (0, chalk_1.getChalk)().yellow('Processing'),
|
|
329
331
|
percentage: ' 0',
|
|
330
332
|
});
|
|
331
333
|
}
|
|
@@ -354,12 +356,12 @@ class CLIProgressManager {
|
|
|
354
356
|
const percentage = Math.round((totalProcessed / process.total) * 100);
|
|
355
357
|
const formattedPercentage = this.formatPercentage(percentage);
|
|
356
358
|
const statusText = success
|
|
357
|
-
? chalk_1.
|
|
358
|
-
: chalk_1.
|
|
359
|
+
? (0, chalk_1.getChalk)().green(`✓ Complete (${process.successCount}/${process.current})`)
|
|
360
|
+
: (0, chalk_1.getChalk)().red(`✗ Failed (${process.successCount}/${process.current})`);
|
|
359
361
|
const displayName = this.formatProcessName(processName);
|
|
360
362
|
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
|
|
361
363
|
process.progressBar.update(process.total, {
|
|
362
|
-
label: success ? chalk_1.
|
|
364
|
+
label: success ? (0, chalk_1.getChalk)().green(indentedLabel) : (0, chalk_1.getChalk)().red(indentedLabel),
|
|
363
365
|
status: statusText,
|
|
364
366
|
percentage: formattedPercentage,
|
|
365
367
|
});
|
|
@@ -380,8 +382,8 @@ class CLIProgressManager {
|
|
|
380
382
|
const displayName = this.formatProcessName(processName);
|
|
381
383
|
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
|
|
382
384
|
process.progressBar.update(process.current, {
|
|
383
|
-
label: chalk_1.
|
|
384
|
-
status: chalk_1.
|
|
385
|
+
label: (0, chalk_1.getChalk)().yellow(indentedLabel),
|
|
386
|
+
status: (0, chalk_1.getChalk)().yellow(message),
|
|
385
387
|
percentage: formattedPercentage,
|
|
386
388
|
});
|
|
387
389
|
}
|
|
@@ -392,13 +394,13 @@ class CLIProgressManager {
|
|
|
392
394
|
const formattedName = this.formatModuleName(this.moduleName);
|
|
393
395
|
const displayName = formattedName.length > 20 ? formattedName.substring(0, 17) + '...' : formattedName;
|
|
394
396
|
this.progressBar.update(this.progressBar.getProgress() * this.total, {
|
|
395
|
-
label: chalk_1.
|
|
396
|
-
status: chalk_1.
|
|
397
|
+
label: (0, chalk_1.getChalk)().yellow(` └─ ${displayName}`.padEnd(25)),
|
|
398
|
+
status: (0, chalk_1.getChalk)().yellow(message),
|
|
397
399
|
percentage: formattedPercentage,
|
|
398
400
|
});
|
|
399
401
|
}
|
|
400
402
|
else if (this.spinner) {
|
|
401
|
-
this.spinner.text = `${chalk_1.
|
|
403
|
+
this.spinner.text = `${(0, chalk_1.getChalk)().bold(this.moduleName)}: ${message}`;
|
|
402
404
|
}
|
|
403
405
|
}
|
|
404
406
|
return this;
|
|
@@ -442,8 +444,8 @@ class CLIProgressManager {
|
|
|
442
444
|
const displayName = this.formatProcessName(targetProcess);
|
|
443
445
|
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
|
|
444
446
|
process.progressBar.increment(1, {
|
|
445
|
-
label: chalk_1.
|
|
446
|
-
status: chalk_1.
|
|
447
|
+
label: (0, chalk_1.getChalk)().cyan(indentedLabel),
|
|
448
|
+
status: (0, chalk_1.getChalk)().cyan(statusText),
|
|
447
449
|
percentage: formattedPercentage,
|
|
448
450
|
});
|
|
449
451
|
}
|
|
@@ -459,10 +461,14 @@ class CLIProgressManager {
|
|
|
459
461
|
// Show completion status when finished, otherwise show running count
|
|
460
462
|
const statusText = totalProcessed >= this.total
|
|
461
463
|
? this.failureCount === 0
|
|
462
|
-
? chalk_1.
|
|
463
|
-
: chalk_1.
|
|
464
|
-
: chalk_1.
|
|
465
|
-
const labelColor = totalProcessed >= this.total
|
|
464
|
+
? (0, chalk_1.getChalk)().green(`✓ Complete (${this.successCount}/${totalProcessed})`)
|
|
465
|
+
: (0, chalk_1.getChalk)().yellow(`✓ Complete (${this.successCount}/${totalProcessed})`)
|
|
466
|
+
: (0, chalk_1.getChalk)().cyan(`${this.successCount}✓ ${this.failureCount}✗`);
|
|
467
|
+
const labelColor = totalProcessed >= this.total
|
|
468
|
+
? this.failureCount === 0
|
|
469
|
+
? (0, chalk_1.getChalk)().green
|
|
470
|
+
: (0, chalk_1.getChalk)().yellow
|
|
471
|
+
: (0, chalk_1.getChalk)().cyan;
|
|
466
472
|
const formattedName = this.formatModuleName(this.moduleName);
|
|
467
473
|
const displayName = formattedName.length > 20 ? formattedName.substring(0, 17) + '...' : formattedName;
|
|
468
474
|
this.progressBar.increment(1, {
|
|
@@ -473,7 +479,7 @@ class CLIProgressManager {
|
|
|
473
479
|
}
|
|
474
480
|
else if (this.spinner) {
|
|
475
481
|
const total = this.successCount + this.failureCount;
|
|
476
|
-
this.spinner.text = `${chalk_1.
|
|
482
|
+
this.spinner.text = `${(0, chalk_1.getChalk)().bold(this.moduleName)}: ${total} items (${this.successCount}✓ ${this.failureCount}✗)`;
|
|
477
483
|
}
|
|
478
484
|
}
|
|
479
485
|
}
|
|
@@ -512,15 +518,19 @@ class CLIProgressManager {
|
|
|
512
518
|
}
|
|
513
519
|
}
|
|
514
520
|
printSummary() {
|
|
521
|
+
// In console logs mode, use only timestamped log lines (no Progress Manager blocks)
|
|
522
|
+
if (this.showConsoleLogs) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
515
525
|
if (!this.enableNestedProgress) {
|
|
516
526
|
// Simple summary for single progress
|
|
517
|
-
this.log('\n' + chalk_1.
|
|
518
|
-
this.log(`✓ Success: ${chalk_1.
|
|
519
|
-
this.log(`✗ Failures: ${chalk_1.
|
|
527
|
+
this.log('\n' + (0, chalk_1.getChalk)().bold(`${this.moduleName} Summary:`));
|
|
528
|
+
this.log(`✓ Success: ${(0, chalk_1.getChalk)().green(this.successCount)}`);
|
|
529
|
+
this.log(`✗ Failures: ${(0, chalk_1.getChalk)().red(this.failureCount)}`);
|
|
520
530
|
return;
|
|
521
531
|
}
|
|
522
532
|
// Detailed summary for nested progress
|
|
523
|
-
this.log('\n' + chalk_1.
|
|
533
|
+
this.log('\n' + (0, chalk_1.getChalk)().bold(`${this.moduleName} Detailed Summary:`));
|
|
524
534
|
for (const [processName, process] of this.processes) {
|
|
525
535
|
const status = process.status === 'completed'
|
|
526
536
|
? '✓'
|
|
@@ -540,5 +550,5 @@ class CLIProgressManager {
|
|
|
540
550
|
return this.failureCount;
|
|
541
551
|
}
|
|
542
552
|
}
|
|
543
|
-
exports.default = CLIProgressManager;
|
|
544
553
|
CLIProgressManager.globalSummary = null;
|
|
554
|
+
exports.default = CLIProgressManager;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const
|
|
4
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
3
|
+
const chalk_1 = require("../chalk");
|
|
5
4
|
class SummaryManager {
|
|
6
5
|
constructor({ operationName, context }) {
|
|
7
6
|
this.modules = new Map();
|
|
@@ -83,16 +82,16 @@ class SummaryManager {
|
|
|
83
82
|
const totalItems = Array.from(this.modules.values()).reduce((sum, m) => sum + m.successCount + m.failureCount, 0);
|
|
84
83
|
const totalSuccess = Array.from(this.modules.values()).reduce((sum, m) => sum + m.successCount, 0);
|
|
85
84
|
const totalFailures = Array.from(this.modules.values()).reduce((sum, m) => sum + m.failureCount, 0);
|
|
86
|
-
console.log('\n' + chalk_1.
|
|
87
|
-
console.log(chalk_1.
|
|
88
|
-
console.log('\n' + chalk_1.
|
|
89
|
-
console.log(` Total ${this.operationName} Time: ${chalk_1.
|
|
90
|
-
console.log(` Modules Processed: ${chalk_1.
|
|
91
|
-
console.log(` Items Processed: ${chalk_1.
|
|
92
|
-
console.log(` Success Rate: ${chalk_1.
|
|
85
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold('='.repeat(80)));
|
|
86
|
+
console.log((0, chalk_1.getChalk)().bold(`${this.operationName} SUMMARY`));
|
|
87
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold('Overall Statistics:'));
|
|
88
|
+
console.log(` Total ${this.operationName} Time: ${(0, chalk_1.getChalk)().cyan(this.formatDuration(totalDuration))}`);
|
|
89
|
+
console.log(` Modules Processed: ${(0, chalk_1.getChalk)().cyan(completedModules)}/${(0, chalk_1.getChalk)().cyan(totalModules)}`);
|
|
90
|
+
console.log(` Items Processed: ${(0, chalk_1.getChalk)().green(totalSuccess)} success, ${(0, chalk_1.getChalk)().red(totalFailures)} failed of ${(0, chalk_1.getChalk)().cyan(totalItems)} total`);
|
|
91
|
+
console.log(` Success Rate: ${(0, chalk_1.getChalk)().cyan(this.calculateSuccessRate(totalSuccess, totalItems))}%`);
|
|
93
92
|
// Module Details
|
|
94
|
-
console.log('\n' + chalk_1.
|
|
95
|
-
console.log(chalk_1.
|
|
93
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold('Module Details:'));
|
|
94
|
+
console.log((0, chalk_1.getChalk)().gray('-'.repeat(80)));
|
|
96
95
|
Array.from(this.modules.values()).forEach((module) => {
|
|
97
96
|
const status = this.getStatusIcon(module.status);
|
|
98
97
|
const totalCount = module.successCount + module.failureCount;
|
|
@@ -104,18 +103,18 @@ class SummaryManager {
|
|
|
104
103
|
`${duration.padStart(8)}`);
|
|
105
104
|
});
|
|
106
105
|
// Final Status
|
|
107
|
-
console.log('\n' + chalk_1.
|
|
106
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold('Final Status:'));
|
|
108
107
|
if (!this.hasFailures() && failedModules === 0) {
|
|
109
|
-
console.log(chalk_1.
|
|
108
|
+
console.log((0, chalk_1.getChalk)().bold.green(`✅ ${this.operationName} completed successfully!`));
|
|
110
109
|
}
|
|
111
110
|
else if (this.hasFailures() || failedModules > 0) {
|
|
112
|
-
console.log(chalk_1.
|
|
111
|
+
console.log((0, chalk_1.getChalk)().bold.yellow(`⚠️ ${this.operationName} completed with failures, see the logs for more details.`));
|
|
113
112
|
}
|
|
114
113
|
else {
|
|
115
|
-
console.log(chalk_1.
|
|
114
|
+
console.log((0, chalk_1.getChalk)().bold.red(`❌ ${this.operationName} failed`));
|
|
116
115
|
}
|
|
117
|
-
console.log(chalk_1.
|
|
118
|
-
console.log(chalk_1.
|
|
116
|
+
console.log((0, chalk_1.getChalk)().bold('='.repeat(80)));
|
|
117
|
+
console.log((0, chalk_1.getChalk)().bold('='.repeat(80)));
|
|
119
118
|
// Simple failure summary with log reference
|
|
120
119
|
this.printFailureSummaryWithLogReference();
|
|
121
120
|
}
|
|
@@ -129,36 +128,37 @@ class SummaryManager {
|
|
|
129
128
|
const modulesWithFailures = Array.from(this.modules.values()).filter((m) => m.failures.length > 0);
|
|
130
129
|
if (modulesWithFailures.length === 0)
|
|
131
130
|
return;
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- kept for future session log path / totals UX
|
|
132
132
|
const totalFailures = modulesWithFailures.reduce((sum, m) => sum + m.failures.length, 0);
|
|
133
|
-
console.log('\n' + chalk_1.
|
|
134
|
-
console.log(chalk_1.
|
|
133
|
+
console.log('\n' + (0, chalk_1.getChalk)().bold.red('Failure Summary:'));
|
|
134
|
+
console.log((0, chalk_1.getChalk)().red('-'.repeat(50)));
|
|
135
135
|
modulesWithFailures.forEach((module) => {
|
|
136
|
-
console.log(`${chalk_1.
|
|
136
|
+
console.log(`${(0, chalk_1.getChalk)().bold.red('✗')} ${(0, chalk_1.getChalk)().bold(module.name)}: ${(0, chalk_1.getChalk)().red(module.failures.length)} failures`);
|
|
137
137
|
// Show just first 2-3 failures briefly
|
|
138
138
|
const preview = module.failures.slice(0, 2);
|
|
139
139
|
preview.forEach((failure) => {
|
|
140
|
-
console.log(` • ${chalk_1.
|
|
140
|
+
console.log(` • ${(0, chalk_1.getChalk)().gray(failure.item)}`);
|
|
141
141
|
});
|
|
142
142
|
if (module.failures.length > 2) {
|
|
143
|
-
console.log(` ${chalk_1.
|
|
143
|
+
console.log(` ${(0, chalk_1.getChalk)().gray(`... and ${module.failures.length - 2} more`)}`);
|
|
144
144
|
}
|
|
145
145
|
});
|
|
146
|
-
console.log(chalk_1.
|
|
147
|
-
//console.log(
|
|
148
|
-
console.log(chalk_1.
|
|
146
|
+
console.log((0, chalk_1.getChalk)().blue('\n📋 For detailed error information, check the log files:'));
|
|
147
|
+
//console.log(getChalk().blue(` ${getSessionLogPath()}`));
|
|
148
|
+
console.log((0, chalk_1.getChalk)().gray(' Recent errors are logged with full context and stack traces.'));
|
|
149
149
|
}
|
|
150
150
|
getStatusIcon(status) {
|
|
151
151
|
switch (status) {
|
|
152
152
|
case 'completed':
|
|
153
|
-
return chalk_1.
|
|
153
|
+
return (0, chalk_1.getChalk)().green('✓');
|
|
154
154
|
case 'failed':
|
|
155
|
-
return chalk_1.
|
|
155
|
+
return (0, chalk_1.getChalk)().red('✗');
|
|
156
156
|
case 'running':
|
|
157
|
-
return chalk_1.
|
|
157
|
+
return (0, chalk_1.getChalk)().yellow('●');
|
|
158
158
|
case 'pending':
|
|
159
|
-
return chalk_1.
|
|
159
|
+
return (0, chalk_1.getChalk)().gray('○');
|
|
160
160
|
default:
|
|
161
|
-
return chalk_1.
|
|
161
|
+
return (0, chalk_1.getChalk)().gray('?');
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
formatDuration(ms) {
|
package/lib/proxy-helper.d.ts
CHANGED
|
@@ -8,10 +8,51 @@ export interface ProxyConfig {
|
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Parse NO_PROXY / no_proxy env (both uppercase and lowercase).
|
|
12
|
+
* NO_PROXY has priority over HTTP_PROXY/HTTPS_PROXY: hosts in this list never use the proxy.
|
|
13
|
+
* Values are hostnames only, comma-separated; leading dot matches subdomains (e.g. .contentstack.io).
|
|
14
|
+
* The bypass list is fully dynamic: only env values are used (no hardcoded default).
|
|
15
|
+
* @returns List of trimmed entries, or empty array when NO_PROXY/no_proxy is unset
|
|
16
|
+
*/
|
|
17
|
+
export declare function getNoProxyList(): string[];
|
|
18
|
+
/**
|
|
19
|
+
* Check if the given host should bypass the proxy based on NO_PROXY / no_proxy.
|
|
20
|
+
* Supports: exact host, leading-dot subdomain match (e.g. .contentstack.io), and wildcard *.
|
|
21
|
+
* @param host - Request hostname (with or without port; will be normalized)
|
|
22
|
+
* @returns true if proxy should not be used for this host
|
|
23
|
+
*/
|
|
24
|
+
export declare function shouldBypassProxy(host: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Get proxy configuration. Priority order (per spec):
|
|
27
|
+
* 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
|
|
28
|
+
* 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
29
|
+
* For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
|
|
12
30
|
* @returns ProxyConfig object or undefined if no proxy is configured
|
|
13
31
|
*/
|
|
14
32
|
export declare function getProxyConfig(): ProxyConfig | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Get proxy config only when the request host is not in NO_PROXY.
|
|
35
|
+
* NO_PROXY has priority over both HTTP_PROXY/HTTPS_PROXY and over proxy set via
|
|
36
|
+
* `csdx config:set:proxy` — if the host matches NO_PROXY, no proxy is used.
|
|
37
|
+
* Use this for all outbound requests so Contentstack and localhost bypass the proxy when set.
|
|
38
|
+
* @param host - Request hostname (e.g. api.contentstack.io or full URL like https://api.contentstack.io)
|
|
39
|
+
* @returns ProxyConfig or undefined if proxy is disabled or host should bypass (NO_PROXY)
|
|
40
|
+
*/
|
|
41
|
+
export declare function getProxyConfigForHost(host: string): ProxyConfig | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
|
|
44
|
+
* default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
|
|
45
|
+
* `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveRequestHost(config: {
|
|
48
|
+
host?: string;
|
|
49
|
+
}): string;
|
|
50
|
+
/**
|
|
51
|
+
* Temporarily clear proxy-related env vars so SDK/axios cannot use them.
|
|
52
|
+
* Call the returned function to restore. Use when creating a client for a host in NO_PROXY.
|
|
53
|
+
* @returns Restore function (call to put env back)
|
|
54
|
+
*/
|
|
55
|
+
export declare function clearProxyEnv(): () => void;
|
|
15
56
|
/**
|
|
16
57
|
* Check if proxy is configured (from any source)
|
|
17
58
|
* @returns true if proxy is configured, false otherwise
|
package/lib/proxy-helper.js
CHANGED
|
@@ -1,41 +1,100 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getNoProxyList = getNoProxyList;
|
|
4
|
+
exports.shouldBypassProxy = shouldBypassProxy;
|
|
5
|
+
exports.getProxyConfig = getProxyConfig;
|
|
6
|
+
exports.getProxyConfigForHost = getProxyConfigForHost;
|
|
7
|
+
exports.resolveRequestHost = resolveRequestHost;
|
|
8
|
+
exports.clearProxyEnv = clearProxyEnv;
|
|
9
|
+
exports.hasProxy = hasProxy;
|
|
10
|
+
exports.getProxyUrl = getProxyUrl;
|
|
4
11
|
const tslib_1 = require("tslib");
|
|
5
12
|
const config_handler_1 = tslib_1.__importDefault(require("./config-handler"));
|
|
6
13
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
14
|
+
* Parse NO_PROXY / no_proxy env (both uppercase and lowercase).
|
|
15
|
+
* NO_PROXY has priority over HTTP_PROXY/HTTPS_PROXY: hosts in this list never use the proxy.
|
|
16
|
+
* Values are hostnames only, comma-separated; leading dot matches subdomains (e.g. .contentstack.io).
|
|
17
|
+
* The bypass list is fully dynamic: only env values are used (no hardcoded default).
|
|
18
|
+
* @returns List of trimmed entries, or empty array when NO_PROXY/no_proxy is unset
|
|
9
19
|
*/
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
20
|
+
function getNoProxyList() {
|
|
21
|
+
const raw = process.env.NO_PROXY || process.env.no_proxy || '';
|
|
22
|
+
return raw
|
|
23
|
+
.split(',')
|
|
24
|
+
.map((s) => s.trim())
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Normalize host for NO_PROXY matching: strip protocol/URL, port, lowercase, handle IPv6 brackets.
|
|
29
|
+
* Accepts hostname, host:port, or full URL (e.g. https://api.contentstack.io).
|
|
30
|
+
*/
|
|
31
|
+
function normalizeHost(host) {
|
|
32
|
+
if (!host || typeof host !== 'string')
|
|
33
|
+
return '';
|
|
34
|
+
let h = host.trim().toLowerCase();
|
|
35
|
+
// If it looks like a URL, extract hostname so NO_PROXY matching works (e.g. region.cma is full URL)
|
|
36
|
+
if (h.includes('://')) {
|
|
14
37
|
try {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
|
|
18
|
-
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
|
|
19
|
-
const protocol = url.protocol.replace(':', '');
|
|
20
|
-
const proxyConfig = {
|
|
21
|
-
protocol: protocol,
|
|
22
|
-
host: url.hostname,
|
|
23
|
-
port: port,
|
|
24
|
-
};
|
|
25
|
-
if (url.username || url.password) {
|
|
26
|
-
proxyConfig.auth = {
|
|
27
|
-
username: url.username,
|
|
28
|
-
password: url.password,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return proxyConfig;
|
|
32
|
-
}
|
|
38
|
+
const u = new URL(h);
|
|
39
|
+
h = u.hostname;
|
|
33
40
|
}
|
|
34
41
|
catch (_a) {
|
|
35
|
-
//
|
|
42
|
+
// fall through to port stripping below
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const portIdx = h.lastIndexOf(':');
|
|
46
|
+
if (h.startsWith('[')) {
|
|
47
|
+
const close = h.indexOf(']');
|
|
48
|
+
if (close !== -1 && h.length > close + 1 && h[close + 1] === ':') {
|
|
49
|
+
h = h.slice(1, close);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (portIdx !== -1) {
|
|
53
|
+
const after = h.slice(portIdx + 1);
|
|
54
|
+
if (/^\d+$/.test(after)) {
|
|
55
|
+
h = h.slice(0, portIdx);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return h;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if the given host should bypass the proxy based on NO_PROXY / no_proxy.
|
|
62
|
+
* Supports: exact host, leading-dot subdomain match (e.g. .contentstack.io), and wildcard *.
|
|
63
|
+
* @param host - Request hostname (with or without port; will be normalized)
|
|
64
|
+
* @returns true if proxy should not be used for this host
|
|
65
|
+
*/
|
|
66
|
+
function shouldBypassProxy(host) {
|
|
67
|
+
const normalized = normalizeHost(host);
|
|
68
|
+
if (!normalized)
|
|
69
|
+
return false;
|
|
70
|
+
const list = getNoProxyList();
|
|
71
|
+
for (const entry of list) {
|
|
72
|
+
const e = entry.trim().toLowerCase();
|
|
73
|
+
if (!e)
|
|
74
|
+
continue;
|
|
75
|
+
if (e === '*')
|
|
76
|
+
return true;
|
|
77
|
+
if (e.startsWith('.')) {
|
|
78
|
+
const domain = e.slice(1);
|
|
79
|
+
if (normalized === domain || normalized.endsWith(e))
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (normalized === e)
|
|
84
|
+
return true;
|
|
36
85
|
}
|
|
37
86
|
}
|
|
38
|
-
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get proxy configuration. Priority order (per spec):
|
|
91
|
+
* 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
|
|
92
|
+
* 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
93
|
+
* For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
|
|
94
|
+
* @returns ProxyConfig object or undefined if no proxy is configured
|
|
95
|
+
*/
|
|
96
|
+
function getProxyConfig() {
|
|
97
|
+
// Priority 1: Global config (csdx config:set:proxy)
|
|
39
98
|
const globalProxyConfig = config_handler_1.default.get('proxy');
|
|
40
99
|
if (globalProxyConfig) {
|
|
41
100
|
if (typeof globalProxyConfig === 'object') {
|
|
@@ -65,14 +124,108 @@ function getProxyConfig() {
|
|
|
65
124
|
return proxyConfig;
|
|
66
125
|
}
|
|
67
126
|
}
|
|
68
|
-
catch (
|
|
69
|
-
// Invalid URL,
|
|
127
|
+
catch (_a) {
|
|
128
|
+
// Invalid URL, continue to check environment
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Priority 2: Environment variables (HTTPS_PROXY or HTTP_PROXY)
|
|
133
|
+
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
|
|
134
|
+
if (proxyUrl) {
|
|
135
|
+
try {
|
|
136
|
+
const url = new URL(proxyUrl);
|
|
137
|
+
const defaultPort = url.protocol === 'https:' ? 443 : 80;
|
|
138
|
+
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
|
|
139
|
+
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
|
|
140
|
+
const protocol = url.protocol.replace(':', '');
|
|
141
|
+
const proxyConfig = {
|
|
142
|
+
protocol: protocol,
|
|
143
|
+
host: url.hostname,
|
|
144
|
+
port: port,
|
|
145
|
+
};
|
|
146
|
+
if (url.username || url.password) {
|
|
147
|
+
proxyConfig.auth = {
|
|
148
|
+
username: url.username,
|
|
149
|
+
password: url.password,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return proxyConfig;
|
|
70
153
|
}
|
|
71
154
|
}
|
|
155
|
+
catch (_b) {
|
|
156
|
+
// Invalid URL, return undefined
|
|
157
|
+
}
|
|
72
158
|
}
|
|
73
159
|
return undefined;
|
|
74
160
|
}
|
|
75
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Get proxy config only when the request host is not in NO_PROXY.
|
|
163
|
+
* NO_PROXY has priority over both HTTP_PROXY/HTTPS_PROXY and over proxy set via
|
|
164
|
+
* `csdx config:set:proxy` — if the host matches NO_PROXY, no proxy is used.
|
|
165
|
+
* Use this for all outbound requests so Contentstack and localhost bypass the proxy when set.
|
|
166
|
+
* @param host - Request hostname (e.g. api.contentstack.io or full URL like https://api.contentstack.io)
|
|
167
|
+
* @returns ProxyConfig or undefined if proxy is disabled or host should bypass (NO_PROXY)
|
|
168
|
+
*/
|
|
169
|
+
function getProxyConfigForHost(host) {
|
|
170
|
+
if (shouldBypassProxy(host))
|
|
171
|
+
return undefined;
|
|
172
|
+
return getProxyConfig();
|
|
173
|
+
}
|
|
174
|
+
function regionCmaHostname() {
|
|
175
|
+
var _a;
|
|
176
|
+
const cma = (_a = config_handler_1.default.get('region')) === null || _a === void 0 ? void 0 : _a.cma;
|
|
177
|
+
if (!cma || typeof cma !== 'string') {
|
|
178
|
+
return '';
|
|
179
|
+
}
|
|
180
|
+
if (cma.startsWith('http')) {
|
|
181
|
+
try {
|
|
182
|
+
const u = new URL(cma);
|
|
183
|
+
return u.hostname || cma;
|
|
184
|
+
}
|
|
185
|
+
catch (_b) {
|
|
186
|
+
return cma;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return cma;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
|
|
193
|
+
* default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
|
|
194
|
+
* `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
|
|
195
|
+
*/
|
|
196
|
+
function resolveRequestHost(config) {
|
|
197
|
+
var _a;
|
|
198
|
+
const fromRegion = regionCmaHostname();
|
|
199
|
+
if (fromRegion) {
|
|
200
|
+
return normalizeHost(fromRegion) || fromRegion;
|
|
201
|
+
}
|
|
202
|
+
const raw = ((_a = config.host) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
203
|
+
if (!raw) {
|
|
204
|
+
return '';
|
|
205
|
+
}
|
|
206
|
+
return normalizeHost(raw) || raw;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Temporarily clear proxy-related env vars so SDK/axios cannot use them.
|
|
210
|
+
* Call the returned function to restore. Use when creating a client for a host in NO_PROXY.
|
|
211
|
+
* @returns Restore function (call to put env back)
|
|
212
|
+
*/
|
|
213
|
+
function clearProxyEnv() {
|
|
214
|
+
const saved = {};
|
|
215
|
+
const keys = ['HTTP_PROXY', 'HTTPS_PROXY', 'http_proxy', 'https_proxy', 'ALL_PROXY', 'all_proxy'];
|
|
216
|
+
for (const k of keys) {
|
|
217
|
+
if (k in process.env) {
|
|
218
|
+
saved[k] = process.env[k];
|
|
219
|
+
delete process.env[k];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return () => {
|
|
223
|
+
for (const k of keys) {
|
|
224
|
+
if (saved[k] !== undefined)
|
|
225
|
+
process.env[k] = saved[k];
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
76
229
|
/**
|
|
77
230
|
* Check if proxy is configured (from any source)
|
|
78
231
|
* @returns true if proxy is configured, false otherwise
|
|
@@ -80,7 +233,6 @@ exports.getProxyConfig = getProxyConfig;
|
|
|
80
233
|
function hasProxy() {
|
|
81
234
|
return !!getProxyConfig() || !!process.env.HTTPS_PROXY || !!process.env.HTTP_PROXY || !!config_handler_1.default.get('proxy');
|
|
82
235
|
}
|
|
83
|
-
exports.hasProxy = hasProxy;
|
|
84
236
|
/**
|
|
85
237
|
* Get proxy URL string for display purposes
|
|
86
238
|
* @returns Proxy URL string or 'proxy server' if not available
|
|
@@ -100,4 +252,3 @@ function getProxyUrl() {
|
|
|
100
252
|
}
|
|
101
253
|
return 'proxy server';
|
|
102
254
|
}
|
|
103
|
-
exports.getProxyUrl = getProxyUrl;
|