helm-env-delta 1.15.1 ā 1.15.3
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/README.md +3 -3
- package/dist/consoleFormatter.js +12 -12
- package/dist/index.js +44 -41
- package/dist/pipeline/fileUpdater.js +2 -1
- package/dist/reporters/browserLauncher.js +1 -34
- package/dist/reporters/consoleDiffReporter.js +26 -26
- package/dist/reporters/htmlReporter.js +4 -4
- package/dist/suggestionEngine.js +4 -4
- package/dist/utils/regexSafety.js +3 -1
- package/dist/utils/versionChecker.js +3 -3
- package/package.json +16 -15
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ HelmEnvDelta (`hed`) automates environment synchronization for GitOps workflows
|
|
|
66
66
|
|
|
67
67
|
ā” **High Performance** - Intelligent caching and parallel processing. Formatting rules, compiled regexes, and array normalization are all cached for fast repeated runs.
|
|
68
68
|
|
|
69
|
-
š **Security Hardened** - Regex inputs (stop rules, transforms, pattern files) are validated against ReDoS (catastrophic backtracking). Fixed values are
|
|
69
|
+
š **Security Hardened** - Regex inputs (stop rules, transforms, pattern files) are validated against ReDoS (catastrophic backtracking) ā covers nested quantifiers, optional groups, and alternation patterns. Fixed values and YAML file content are guarded against prototype pollution. HTML report paths are HTML-escaped to prevent XSS from filename transforms.
|
|
70
70
|
|
|
71
71
|
š **Auto Updates** - Notifies when newer versions are available (skips in CI/CD).
|
|
72
72
|
|
|
@@ -428,7 +428,7 @@ requiredVersion: '1.10.0' # Optional: Minimum tool version required to process t
|
|
|
428
428
|
|
|
429
429
|
**Note:** Source and destination paths cannot resolve to the same folder.
|
|
430
430
|
|
|
431
|
-
**`requiredVersion`:** When set, the CLI checks that the installed version of helm-env-delta meets this minimum. If the installed version is older, the CLI exits immediately with a clear upgrade message. This prevents running configs that depend on newer features with an outdated tool version. Supports `"1.2.3"` or `"v1.2.3"` format.
|
|
431
|
+
**`requiredVersion`:** When set, the CLI checks that the installed version of helm-env-delta meets this minimum. If the installed version is older, the CLI exits immediately with a clear upgrade message. This prevents running configs that depend on newer features with an outdated tool version. Supports `"1.2.3"` or `"v1.2.3"` format. Setting `requiredVersion` also suppresses the auto-update notification ā a pinned version requirement signals intentional version targeting.
|
|
432
432
|
|
|
433
433
|
---
|
|
434
434
|
|
|
@@ -680,7 +680,7 @@ stopRules:
|
|
|
680
680
|
|
|
681
681
|
**Override:** Use `--force` to bypass stop rules when needed.
|
|
682
682
|
|
|
683
|
-
**Regex safety:** All `regex` patterns (inline and from files) are validated against catastrophic backtracking (ReDoS).
|
|
683
|
+
**Regex safety:** All `regex` patterns (inline and from files) are validated against catastrophic backtracking (ReDoS). Rejected patterns include: nested quantifiers on groups (e.g., `(a+)+`), optional groups with inner quantifiers (e.g., `(a+)?`), and alternation groups with outer repetition (e.g., `(a|ab)*`).
|
|
684
684
|
|
|
685
685
|
**Visibility:** Stop rule violations appear in console output, JSON reports, and HTML reports (dry-run mode only, as a collapsible table in the header area).
|
|
686
686
|
|
package/dist/consoleFormatter.js
CHANGED
|
@@ -4,18 +4,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.formatProgressMessage = exports.colorizeFileOperation = exports.formatStopRuleViolation = exports.formatBox = void 0;
|
|
7
|
-
const
|
|
7
|
+
const ansi_colors_1 = __importDefault(require("ansi-colors"));
|
|
8
8
|
const formatBox = (title, content, style = 'info', width = 60) => {
|
|
9
9
|
const getColorFunction = (boxStyle) => {
|
|
10
10
|
switch (boxStyle) {
|
|
11
11
|
case 'success':
|
|
12
|
-
return
|
|
12
|
+
return ansi_colors_1.default.green;
|
|
13
13
|
case 'warning':
|
|
14
|
-
return
|
|
14
|
+
return ansi_colors_1.default.yellow;
|
|
15
15
|
case 'error':
|
|
16
|
-
return
|
|
16
|
+
return ansi_colors_1.default.red;
|
|
17
17
|
default:
|
|
18
|
-
return
|
|
18
|
+
return ansi_colors_1.default.cyan;
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
21
|
const colorFunction = getColorFunction(style);
|
|
@@ -44,7 +44,7 @@ const formatStopRuleViolation = (violation, mode) => {
|
|
|
44
44
|
return violationMode === 'error' ? 'error' : 'warning';
|
|
45
45
|
};
|
|
46
46
|
const labelWidth = 10;
|
|
47
|
-
const formatLabel = (label) =>
|
|
47
|
+
const formatLabel = (label) => ansi_colors_1.default.dim(label.padEnd(labelWidth));
|
|
48
48
|
const content = [
|
|
49
49
|
`${formatLabel('File:')} ${violation.file}`,
|
|
50
50
|
`${formatLabel('Path:')} ${violation.path}`,
|
|
@@ -61,13 +61,13 @@ const colorizeFileOperation = (operation, filePath, isDryRun, alreadyDeleted = f
|
|
|
61
61
|
const getOperationDisplay = (op) => {
|
|
62
62
|
switch (op) {
|
|
63
63
|
case 'add':
|
|
64
|
-
return { symbol: '+', verb: 'add', colorFn:
|
|
64
|
+
return { symbol: '+', verb: 'add', colorFn: ansi_colors_1.default.green };
|
|
65
65
|
case 'update':
|
|
66
|
-
return { symbol: '~', verb: 'update', colorFn:
|
|
66
|
+
return { symbol: '~', verb: 'update', colorFn: ansi_colors_1.default.yellow };
|
|
67
67
|
case 'delete':
|
|
68
|
-
return { symbol: '-', verb: 'delete', colorFn:
|
|
68
|
+
return { symbol: '-', verb: 'delete', colorFn: ansi_colors_1.default.red };
|
|
69
69
|
case 'format':
|
|
70
|
-
return { symbol: 'ā', verb: 'format', colorFn:
|
|
70
|
+
return { symbol: 'ā', verb: 'format', colorFn: ansi_colors_1.default.cyan };
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
const { symbol, verb, colorFn } = getOperationDisplay(operation);
|
|
@@ -91,9 +91,9 @@ const formatProgressMessage = (message, style) => {
|
|
|
91
91
|
const getColorFunction = (progressStyle) => {
|
|
92
92
|
switch (progressStyle) {
|
|
93
93
|
case 'success':
|
|
94
|
-
return
|
|
94
|
+
return ansi_colors_1.default.green;
|
|
95
95
|
default:
|
|
96
|
-
return
|
|
96
|
+
return ansi_colors_1.default.cyan;
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
99
|
const icon = getIcon(style);
|
package/dist/index.js
CHANGED
|
@@ -40,7 +40,7 @@ const node_fs_1 = require("node:fs");
|
|
|
40
40
|
const promises_1 = require("node:fs/promises");
|
|
41
41
|
const node_os_1 = require("node:os");
|
|
42
42
|
const node_path_1 = __importDefault(require("node:path"));
|
|
43
|
-
const
|
|
43
|
+
const ansi_colors_1 = __importDefault(require("ansi-colors"));
|
|
44
44
|
const YAML = __importStar(require("yaml"));
|
|
45
45
|
const package_json_1 = __importDefault(require("../package.json"));
|
|
46
46
|
const commandLine_1 = require("./commandLine");
|
|
@@ -60,7 +60,7 @@ const versionChecker_1 = require("./utils/versionChecker");
|
|
|
60
60
|
const main = async () => {
|
|
61
61
|
const command = (0, commandLine_1.parseCommandLine)();
|
|
62
62
|
if (command.noColor)
|
|
63
|
-
|
|
63
|
+
ansi_colors_1.default.enabled = false;
|
|
64
64
|
const verbosityLevel = command.verbose ? 'verbose' : command.quiet ? 'quiet' : 'normal';
|
|
65
65
|
const logger = new logger_1.Logger({ level: verbosityLevel, isDiffJson: command.diffJson });
|
|
66
66
|
logger.log(`Now you run ${package_json_1.default.name} v${package_json_1.default.version}...`);
|
|
@@ -68,18 +68,20 @@ const main = async () => {
|
|
|
68
68
|
const firstRunMarker = node_path_1.default.join(configDirectory, 'first-run');
|
|
69
69
|
const isFirstRun = !(0, node_fs_1.existsSync)(firstRunMarker);
|
|
70
70
|
if (isFirstRun && !command.quiet) {
|
|
71
|
-
console.log(
|
|
72
|
-
console.log(
|
|
73
|
-
console.log(
|
|
74
|
-
console.log(
|
|
75
|
-
console.log(
|
|
76
|
-
console.log(
|
|
71
|
+
console.log(ansi_colors_1.default.cyan('\nš First time using helm-env-delta?\n'));
|
|
72
|
+
console.log(ansi_colors_1.default.dim(' Tips:'));
|
|
73
|
+
console.log(ansi_colors_1.default.dim(' ⢠Always use --dry-run first to preview changes'));
|
|
74
|
+
console.log(ansi_colors_1.default.dim(' ⢠Use --diff-html to review diffs in your browser'));
|
|
75
|
+
console.log(ansi_colors_1.default.dim(' ⢠See examples: https://github.com/balazscsaba2006/helm-env-delta/tree/main/example'));
|
|
76
|
+
console.log(ansi_colors_1.default.dim(' ⢠Run with --help to see all options\n'));
|
|
77
77
|
(0, node_fs_1.mkdirSync)(configDirectory, { recursive: true });
|
|
78
78
|
(0, node_fs_1.writeFileSync)(firstRunMarker, new Date().toISOString());
|
|
79
79
|
}
|
|
80
80
|
const config = (0, config_1.loadConfigFile)(command.config, command.quiet, logger, { formatOnly: command.formatOnly });
|
|
81
|
+
if (config.requiredVersion)
|
|
82
|
+
configHasRequiredVersion = true;
|
|
81
83
|
if (command.showConfig) {
|
|
82
|
-
console.log(
|
|
84
|
+
console.log(ansi_colors_1.default.cyan('\nāļø Resolved Configuration:\n'));
|
|
83
85
|
console.log(YAML.stringify(config, { indent: 2 }));
|
|
84
86
|
return;
|
|
85
87
|
}
|
|
@@ -93,9 +95,9 @@ const main = async () => {
|
|
|
93
95
|
const warningResult = (0, config_1.validateConfigWarnings)(validationConfig);
|
|
94
96
|
let hasAnyWarnings = warningResult.hasWarnings;
|
|
95
97
|
if (warningResult.hasWarnings) {
|
|
96
|
-
console.warn(
|
|
98
|
+
console.warn(ansi_colors_1.default.yellow('\nā ļø Configuration Warnings (non-fatal):\n'));
|
|
97
99
|
for (const warning of warningResult.warnings)
|
|
98
|
-
console.warn(
|
|
100
|
+
console.warn(ansi_colors_1.default.yellow(` ⢠${warning}`));
|
|
99
101
|
}
|
|
100
102
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Loading files for validation...', 'loading'));
|
|
101
103
|
const sourceResult = await (0, pipeline_1.loadFiles)({
|
|
@@ -133,12 +135,12 @@ const main = async () => {
|
|
|
133
135
|
const usageResult = (0, pipeline_1.validatePatternUsage)(validationConfig, sourceFiles, destinationFiles);
|
|
134
136
|
hasAnyWarnings = hasAnyWarnings || usageResult.hasWarnings;
|
|
135
137
|
if (usageResult.hasWarnings) {
|
|
136
|
-
console.warn(
|
|
138
|
+
console.warn(ansi_colors_1.default.yellow('\nā ļø Pattern Usage Warnings (non-fatal):\n'));
|
|
137
139
|
for (const warning of usageResult.warnings) {
|
|
138
|
-
const contextString = warning.context ?
|
|
139
|
-
console.warn(
|
|
140
|
+
const contextString = warning.context ? ansi_colors_1.default.dim(` (${warning.context})`) : '';
|
|
141
|
+
console.warn(ansi_colors_1.default.yellow(` ⢠${warning.message}${contextString}`));
|
|
140
142
|
if (warning.hint)
|
|
141
|
-
console.warn(
|
|
143
|
+
console.warn(ansi_colors_1.default.dim(` Hint: ${warning.hint}`));
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
if (hasAnyWarnings)
|
|
@@ -159,7 +161,7 @@ const main = async () => {
|
|
|
159
161
|
}
|
|
160
162
|
if (command.formatOnly) {
|
|
161
163
|
if (!config.outputFormat) {
|
|
162
|
-
logger.log(
|
|
164
|
+
logger.log(ansi_colors_1.default.yellow('\nā ļø No outputFormat configured. Nothing to format.'));
|
|
163
165
|
return;
|
|
164
166
|
}
|
|
165
167
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Loading destination files...', 'loading'));
|
|
@@ -174,10 +176,10 @@ const main = async () => {
|
|
|
174
176
|
logger.progress(`Loaded ${destinationFiles.size} destination file(s)`, 'success');
|
|
175
177
|
if (command.listFiles) {
|
|
176
178
|
const filesList = [...destinationFiles.keys()].toSorted();
|
|
177
|
-
console.log(
|
|
178
|
-
console.log(
|
|
179
|
+
console.log(ansi_colors_1.default.cyan('\nš Files to be formatted:\n'));
|
|
180
|
+
console.log(ansi_colors_1.default.yellow(`Destination files: ${filesList.length}`));
|
|
179
181
|
for (const file of filesList)
|
|
180
|
-
console.log(` ${
|
|
182
|
+
console.log(` ${ansi_colors_1.default.dim(file)}`);
|
|
181
183
|
return;
|
|
182
184
|
}
|
|
183
185
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Formatting files...', 'info'));
|
|
@@ -263,13 +265,13 @@ const main = async () => {
|
|
|
263
265
|
if (command.listFiles) {
|
|
264
266
|
const sourceFilesList = [...sourceFiles.keys()].toSorted();
|
|
265
267
|
const destinationFilesList = [...destinationFiles.keys()].toSorted();
|
|
266
|
-
console.log(
|
|
267
|
-
console.log(
|
|
268
|
+
console.log(ansi_colors_1.default.cyan('\nš Files to be synced:\n'));
|
|
269
|
+
console.log(ansi_colors_1.default.green(`Source files: ${sourceFilesList.length}`));
|
|
268
270
|
for (const file of sourceFilesList)
|
|
269
|
-
console.log(` ${
|
|
270
|
-
console.log(
|
|
271
|
+
console.log(` ${ansi_colors_1.default.dim(file)}`);
|
|
272
|
+
console.log(ansi_colors_1.default.yellow(`\nDestination files: ${destinationFilesList.length}`));
|
|
271
273
|
for (const file of destinationFilesList)
|
|
272
|
-
console.log(` ${
|
|
274
|
+
console.log(` ${ansi_colors_1.default.dim(file)}`);
|
|
273
275
|
return;
|
|
274
276
|
}
|
|
275
277
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Computing differences...', 'info'));
|
|
@@ -290,13 +292,13 @@ const main = async () => {
|
|
|
290
292
|
try {
|
|
291
293
|
const suggestions = (0, suggestionEngine_1.analyzeDifferencesForSuggestions)(diffResult, syncConfig, command.suggestThreshold);
|
|
292
294
|
const yaml = (0, suggestionEngine_1.formatSuggestionsAsYaml)(suggestions);
|
|
293
|
-
console.log(
|
|
295
|
+
console.log(ansi_colors_1.default.cyan('\nš” Suggested Configuration:\n'));
|
|
294
296
|
console.log(yaml);
|
|
295
297
|
if (suggestions.metadata.changedFiles === 0)
|
|
296
|
-
console.log(
|
|
298
|
+
console.log(ansi_colors_1.default.yellow('\nā¹ļø No changes detected. Files are already in sync.'));
|
|
297
299
|
else {
|
|
298
|
-
console.log(
|
|
299
|
-
console.log(
|
|
300
|
+
console.log(ansi_colors_1.default.dim('\n---'));
|
|
301
|
+
console.log(ansi_colors_1.default.dim('š” Tip: Copy relevant sections to your config.yaml and test with --dry-run'));
|
|
300
302
|
}
|
|
301
303
|
return;
|
|
302
304
|
}
|
|
@@ -324,29 +326,29 @@ const main = async () => {
|
|
|
324
326
|
process.exit(1);
|
|
325
327
|
}
|
|
326
328
|
if (!command.dryRun && !command.quiet) {
|
|
327
|
-
console.log(
|
|
328
|
-
console.log(
|
|
329
|
-
console.log(` ${
|
|
330
|
-
console.log(` ${
|
|
331
|
-
console.log(` ${
|
|
332
|
-
console.log(` ${
|
|
333
|
-
console.log(
|
|
329
|
+
console.log(ansi_colors_1.default.cyan('\nš Sync Summary:'));
|
|
330
|
+
console.log(ansi_colors_1.default.dim('ā'.repeat(60)));
|
|
331
|
+
console.log(` ${ansi_colors_1.default.green('Added:')} ${diffResult.addedFiles.length} files`);
|
|
332
|
+
console.log(` ${ansi_colors_1.default.yellow('Changed:')} ${diffResult.changedFiles.length} files`);
|
|
333
|
+
console.log(` ${ansi_colors_1.default.red('Deleted:')} ${diffResult.deletedFiles.length} files (${syncConfig.prune ? 'prune enabled' : 'prune disabled'})`);
|
|
334
|
+
console.log(` ${ansi_colors_1.default.blue('Unchanged:')} ${diffResult.unchangedFiles.length} files`);
|
|
335
|
+
console.log(ansi_colors_1.default.dim('ā'.repeat(60)));
|
|
334
336
|
if (diffResult.deletedFiles.length > 0 && syncConfig.prune) {
|
|
335
|
-
console.warn(
|
|
337
|
+
console.warn(ansi_colors_1.default.red('ā ļø Warning: Prune is enabled. The following files will be permanently deleted:'));
|
|
336
338
|
for (const f of diffResult.deletedFiles)
|
|
337
|
-
console.warn(
|
|
339
|
+
console.warn(ansi_colors_1.default.red(` - ${f}`));
|
|
338
340
|
}
|
|
339
341
|
if (syncConfig.confirmationDelay > 0) {
|
|
340
342
|
const totalSeconds = Math.ceil(syncConfig.confirmationDelay / 1000);
|
|
341
|
-
console.log(
|
|
343
|
+
console.log(ansi_colors_1.default.dim('\nPress Ctrl+C to cancel.\n'));
|
|
342
344
|
for (let remaining = totalSeconds; remaining > 0; remaining--) {
|
|
343
|
-
process.stdout.write(
|
|
345
|
+
process.stdout.write(ansi_colors_1.default.dim(` Proceeding in ${remaining}s...\r`));
|
|
344
346
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
345
347
|
}
|
|
346
348
|
process.stdout.write(' '.repeat(40) + '\r');
|
|
347
349
|
}
|
|
348
350
|
else
|
|
349
|
-
console.log(
|
|
351
|
+
console.log(ansi_colors_1.default.dim('\nPress Ctrl+C to cancel, or use --dry-run to preview changes first.\n'));
|
|
350
352
|
}
|
|
351
353
|
const formattedFiles = await (0, pipeline_1.updateFiles)(diffResult, sourceFiles, destinationFiles, syncConfig, command.dryRun, command.skipFormat, logger);
|
|
352
354
|
if (command.diffHtml && !command.quiet)
|
|
@@ -354,6 +356,7 @@ const main = async () => {
|
|
|
354
356
|
if (command.diffJson)
|
|
355
357
|
(0, reporters_1.generateJsonReport)(diffResult, formattedFiles, validationResult, syncConfig, command.dryRun, package_json_1.default.version);
|
|
356
358
|
};
|
|
359
|
+
let configHasRequiredVersion = false;
|
|
357
360
|
(async () => {
|
|
358
361
|
try {
|
|
359
362
|
await main();
|
|
@@ -393,7 +396,7 @@ const main = async () => {
|
|
|
393
396
|
}
|
|
394
397
|
finally {
|
|
395
398
|
const command = (0, commandLine_1.parseCommandLine)();
|
|
396
|
-
if (!command.quiet)
|
|
399
|
+
if (!command.quiet && !configHasRequiredVersion)
|
|
397
400
|
void (0, versionChecker_1.checkForUpdates)(package_json_1.default.version);
|
|
398
401
|
}
|
|
399
402
|
})();
|
|
@@ -115,8 +115,9 @@ const deepMerge = (fullTarget, filteredSource, filteredTarget, currentPath = [],
|
|
|
115
115
|
const fullTargetObject = fullTarget;
|
|
116
116
|
const filteredTargetObject = filteredTarget || {};
|
|
117
117
|
const result = { ...sourceObject };
|
|
118
|
+
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
118
119
|
for (const [key, value] of Object.entries(fullTargetObject))
|
|
119
|
-
if (!(key in filteredTargetObject) && !(key in sourceObject))
|
|
120
|
+
if (!DANGEROUS_KEYS.has(key) && !(key in filteredTargetObject) && !(key in sourceObject))
|
|
120
121
|
result[key] = value;
|
|
121
122
|
for (const [key, value] of Object.entries(sourceObject))
|
|
122
123
|
if (key in fullTargetObject)
|
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -46,7 +13,7 @@ exports.BrowserLauncherError = BrowserLauncherError;
|
|
|
46
13
|
exports.isBrowserLauncherError = (0, errors_1.createErrorTypeGuard)(BrowserLauncherError);
|
|
47
14
|
const openInBrowser = async (filePath) => {
|
|
48
15
|
try {
|
|
49
|
-
const openModule = await
|
|
16
|
+
const openModule = await import('open');
|
|
50
17
|
const open = openModule.default;
|
|
51
18
|
const absolutePath = node_path_1.default.resolve(filePath);
|
|
52
19
|
await open(absolutePath);
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.showConsoleDiff = void 0;
|
|
7
|
-
const
|
|
7
|
+
const ansi_colors_1 = __importDefault(require("ansi-colors"));
|
|
8
8
|
const pipeline_1 = require("../pipeline");
|
|
9
9
|
const diffGenerator_1 = require("../utils/diffGenerator");
|
|
10
10
|
const fileType_1 = require("../utils/fileType");
|
|
@@ -14,36 +14,36 @@ const colorizeUnifiedDiff = (diff) => {
|
|
|
14
14
|
.split('\n')
|
|
15
15
|
.map((line) => {
|
|
16
16
|
if (line.startsWith('+') && !line.startsWith('+++'))
|
|
17
|
-
return
|
|
17
|
+
return ansi_colors_1.default.green(line);
|
|
18
18
|
if (line.startsWith('-') && !line.startsWith('---'))
|
|
19
|
-
return
|
|
19
|
+
return ansi_colors_1.default.red(line);
|
|
20
20
|
if (line.startsWith('@@'))
|
|
21
|
-
return
|
|
22
|
-
return
|
|
21
|
+
return ansi_colors_1.default.cyan(line);
|
|
22
|
+
return ansi_colors_1.default.gray(line);
|
|
23
23
|
})
|
|
24
24
|
.join('\n');
|
|
25
25
|
};
|
|
26
26
|
const formatAddedFiles = (files) => {
|
|
27
27
|
if (files.length === 0)
|
|
28
28
|
return '';
|
|
29
|
-
const header =
|
|
30
|
-
const fileList = files.map((file) =>
|
|
29
|
+
const header = ansi_colors_1.default.green.bold(`\nAdded Files (${files.length}):`);
|
|
30
|
+
const fileList = files.map((file) => ansi_colors_1.default.green(` + ${file.path}`)).join('\n');
|
|
31
31
|
return `${header}\n${fileList}\n`;
|
|
32
32
|
};
|
|
33
33
|
const formatDeletedFiles = (files) => {
|
|
34
34
|
if (files.length === 0)
|
|
35
35
|
return '';
|
|
36
|
-
const header =
|
|
37
|
-
const fileList = files.map((file) =>
|
|
36
|
+
const header = ansi_colors_1.default.red.bold(`\nDeleted Files (${files.length}):`);
|
|
37
|
+
const fileList = files.map((file) => ansi_colors_1.default.red(` - ${file}`)).join('\n');
|
|
38
38
|
return `${header}\n${fileList}\n`;
|
|
39
39
|
};
|
|
40
40
|
const formatChangedFile = (file, config) => {
|
|
41
41
|
const isYaml = (0, fileType_1.isYamlFile)(file.path);
|
|
42
|
-
const separator =
|
|
42
|
+
const separator = ansi_colors_1.default.yellow('ā'.repeat(60));
|
|
43
43
|
const skipPaths = (0, pipeline_1.getSkipPathsForFile)(file.path, config.skipPath);
|
|
44
44
|
const skipPathInfo = skipPaths.length > 0
|
|
45
|
-
?
|
|
46
|
-
:
|
|
45
|
+
? ansi_colors_1.default.dim(`SkipPath patterns applied: ${skipPaths.join(', ')}`)
|
|
46
|
+
: ansi_colors_1.default.dim('No skipPath patterns applied');
|
|
47
47
|
const destinationContent = isYaml
|
|
48
48
|
? (0, serialization_1.serializeForDiff)(file.processedDestContent, true)
|
|
49
49
|
: String(file.processedDestContent);
|
|
@@ -54,7 +54,7 @@ const formatChangedFile = (file, config) => {
|
|
|
54
54
|
const colorizedDiff = colorizeUnifiedDiff(unifiedDiff);
|
|
55
55
|
return `
|
|
56
56
|
${separator}
|
|
57
|
-
${
|
|
57
|
+
${ansi_colors_1.default.yellow.bold(`File: ${file.path}`)}
|
|
58
58
|
${skipPathInfo}
|
|
59
59
|
|
|
60
60
|
${colorizedDiff}
|
|
@@ -63,39 +63,39 @@ ${colorizedDiff}
|
|
|
63
63
|
const formatChangedFiles = (files, config) => {
|
|
64
64
|
if (files.length === 0)
|
|
65
65
|
return '';
|
|
66
|
-
const header =
|
|
66
|
+
const header = ansi_colors_1.default.yellow.bold(`\nChanged Files (${files.length}):`);
|
|
67
67
|
const fileContent = files.map((file) => formatChangedFile(file, config)).join('\n');
|
|
68
68
|
return `${header}\n${fileContent}`;
|
|
69
69
|
};
|
|
70
70
|
const formatSummaryBox = (diffResult, pruneEnabled) => {
|
|
71
71
|
const width = 60;
|
|
72
|
-
const topBorder =
|
|
73
|
-
const bottomBorder =
|
|
74
|
-
const addedLine =
|
|
75
|
-
const changedLine =
|
|
72
|
+
const topBorder = ansi_colors_1.default.cyan(`āā Diff Summary ${'ā'.repeat(width - 14)}ā®`);
|
|
73
|
+
const bottomBorder = ansi_colors_1.default.cyan(`ā°${'ā'.repeat(width + 1)}āÆ`);
|
|
74
|
+
const addedLine = ansi_colors_1.default.cyan(`ā ${ansi_colors_1.default.green('ā Added:')} ${diffResult.addedFiles.length.toString().padEnd(width - 15)} ā`);
|
|
75
|
+
const changedLine = ansi_colors_1.default.cyan(`ā ${ansi_colors_1.default.yellow('ā Changed:')} ${diffResult.changedFiles.length.toString().padEnd(width - 15)} ā`);
|
|
76
76
|
const deletedText = pruneEnabled
|
|
77
77
|
? `${diffResult.deletedFiles.length} (prune enabled)`
|
|
78
78
|
: `${diffResult.deletedFiles.length} (prune disabled)`;
|
|
79
|
-
const deletedLine =
|
|
80
|
-
const unchangedLine =
|
|
79
|
+
const deletedLine = ansi_colors_1.default.cyan(`ā ${ansi_colors_1.default.red('ā Deleted:')} ${deletedText.padEnd(width - 15)} ā`);
|
|
80
|
+
const unchangedLine = ansi_colors_1.default.cyan(`ā ${ansi_colors_1.default.gray('ā Unchanged:')} ${diffResult.unchangedFiles.length.toString().padEnd(width - 15)} ā`);
|
|
81
81
|
return `${topBorder}\n${addedLine}\n${changedLine}\n${deletedLine}\n${unchangedLine}\n${bottomBorder}\n`;
|
|
82
82
|
};
|
|
83
83
|
const showConsoleDiff = (diffResult, config) => {
|
|
84
84
|
console.log('');
|
|
85
85
|
console.log(formatSummaryBox(diffResult, config.prune));
|
|
86
|
-
console.log(
|
|
87
|
-
console.log(
|
|
86
|
+
console.log(ansi_colors_1.default.bold('\nInclude patterns:'), config.include.join(', '));
|
|
87
|
+
console.log(ansi_colors_1.default.bold('Exclude patterns:'), config.exclude.length > 0 ? config.exclude.join(', ') : ansi_colors_1.default.dim('(none)'));
|
|
88
88
|
if (diffResult.addedFiles.length === 0 &&
|
|
89
89
|
diffResult.changedFiles.length === 0 &&
|
|
90
90
|
diffResult.deletedFiles.length === 0) {
|
|
91
91
|
const totalCompared = diffResult.unchangedFiles.length;
|
|
92
92
|
const hasSkipPath = config.skipPath && Object.keys(config.skipPath).length > 0;
|
|
93
|
-
const skipNote = hasSkipPath ?
|
|
93
|
+
const skipNote = hasSkipPath ? ansi_colors_1.default.dim(' (some paths may be excluded via skipPath)') : '';
|
|
94
94
|
if (totalCompared === 0)
|
|
95
|
-
console.log(
|
|
95
|
+
console.log(ansi_colors_1.default.yellow.bold('\nā No files matched the include/exclude patterns\n'));
|
|
96
96
|
else
|
|
97
|
-
console.log(
|
|
98
|
-
|
|
97
|
+
console.log(ansi_colors_1.default.green.bold(`\nā No differences found`) +
|
|
98
|
+
ansi_colors_1.default.dim(` ā ${totalCompared} file(s) compared, all identical`) +
|
|
99
99
|
skipNote +
|
|
100
100
|
'\n');
|
|
101
101
|
return;
|
|
@@ -51,13 +51,13 @@ const countDiffLines = (unifiedDiff) => {
|
|
|
51
51
|
};
|
|
52
52
|
const generateFileSummary = (file) => {
|
|
53
53
|
if (!file.originalPath)
|
|
54
|
-
return file.path;
|
|
55
|
-
return `<span class="filename-transform">${file.originalPath} ā ${file.path}</span>`;
|
|
54
|
+
return (0, treeRenderer_1.escapeHtml)(file.path);
|
|
55
|
+
return `<span class="filename-transform">${(0, treeRenderer_1.escapeHtml)(file.originalPath)} ā ${(0, treeRenderer_1.escapeHtml)(file.path)}</span>`;
|
|
56
56
|
};
|
|
57
57
|
const generateAddedFileSummary = (file) => {
|
|
58
58
|
if (!file.originalPath)
|
|
59
|
-
return file.path;
|
|
60
|
-
return `<span class="filename-transform">${file.originalPath} ā ${file.path}</span>`;
|
|
59
|
+
return (0, treeRenderer_1.escapeHtml)(file.path);
|
|
60
|
+
return `<span class="filename-transform">${(0, treeRenderer_1.escapeHtml)(file.originalPath)} ā ${(0, treeRenderer_1.escapeHtml)(file.path)}</span>`;
|
|
61
61
|
};
|
|
62
62
|
const JUMP_TO_SIDEBAR_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M2 2h3v12H2V2zm0-1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H2zm5 4h7v1H7V5zm0 3h7v1H7V8zm0 3h5v1H7v-1z"/></svg>`;
|
|
63
63
|
const generateAddedFileSection = (file, fileId, open) => {
|
package/dist/suggestionEngine.js
CHANGED
|
@@ -548,9 +548,9 @@ const calculateLevenshteinDistance = (string1, string2) => {
|
|
|
548
548
|
matrix[0][col] = col;
|
|
549
549
|
for (let row = 1; row <= string2.length; row++)
|
|
550
550
|
for (let col = 1; col <= string1.length; col++)
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
551
|
+
matrix[row][col] =
|
|
552
|
+
string2.charAt(row - 1) === string1.charAt(col - 1)
|
|
553
|
+
? matrix[row - 1][col - 1]
|
|
554
|
+
: Math.min(matrix[row - 1][col - 1] + 1, matrix[row][col - 1] + 1, matrix[row - 1][col] + 1);
|
|
555
555
|
return matrix[string2.length][string1.length];
|
|
556
556
|
};
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isSafeRegex = void 0;
|
|
4
4
|
const isSafeRegex = (pattern) => {
|
|
5
|
-
if (/\([^()]*[*+][^()]*\)[
|
|
5
|
+
if (/\([^()]*[*+][^()]*\)[*+?{]/.test(pattern))
|
|
6
|
+
return false;
|
|
7
|
+
if (/\([^()]*\|[^()]*\)[*+{]/.test(pattern))
|
|
6
8
|
return false;
|
|
7
9
|
return true;
|
|
8
10
|
};
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.checkForUpdates = exports.isNewerVersion = exports.parseVersion = exports.isVersionCheckerError = exports.VersionCheckerError = void 0;
|
|
7
7
|
const node_https_1 = __importDefault(require("node:https"));
|
|
8
|
-
const
|
|
8
|
+
const ansi_colors_1 = __importDefault(require("ansi-colors"));
|
|
9
9
|
const package_json_1 = __importDefault(require("../../package.json"));
|
|
10
10
|
const errors_1 = require("./errors");
|
|
11
11
|
const VersionCheckerErrorClass = (0, errors_1.createErrorClass)('Version Checker Error', {
|
|
@@ -102,8 +102,8 @@ const fetchLatestVersion = (packageName, timeout) => {
|
|
|
102
102
|
});
|
|
103
103
|
};
|
|
104
104
|
const displayUpdateNotification = (currentVersion, latestVersion) => {
|
|
105
|
-
console.log('\n' +
|
|
106
|
-
console.log(
|
|
105
|
+
console.log('\n' + ansi_colors_1.default.yellow(`ā Update available! v${currentVersion} ā v${latestVersion}`));
|
|
106
|
+
console.log(ansi_colors_1.default.yellow('Run: npm install -g helm-env-delta@latest'));
|
|
107
107
|
};
|
|
108
108
|
const checkForUpdates = async (currentVersion) => {
|
|
109
109
|
if (isCiEnvironment())
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helm-env-delta",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.3",
|
|
4
4
|
"description": "HelmEnvDelta ā environment-aware YAML delta and sync for GitOps",
|
|
5
5
|
"author": "BCsabaEngine",
|
|
6
6
|
"license": "ISC",
|
|
@@ -65,29 +65,30 @@
|
|
|
65
65
|
],
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@eslint/js": "^10.0.1",
|
|
68
|
-
"@types/
|
|
69
|
-
"@types/
|
|
70
|
-
"@
|
|
71
|
-
"@
|
|
72
|
-
"
|
|
68
|
+
"@types/ansi-colors": "^3.2.0",
|
|
69
|
+
"@types/node": "^25.5.2",
|
|
70
|
+
"@types/picomatch": "^4.0.3",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^8.58.0",
|
|
72
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
73
|
+
"eslint": "^10.2.0",
|
|
73
74
|
"eslint-config-prettier": "^10.1.8",
|
|
74
|
-
"eslint-plugin-simple-import-sort": "^
|
|
75
|
-
"eslint-plugin-unicorn": "^
|
|
75
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
76
|
+
"eslint-plugin-unicorn": "^64.0.0",
|
|
76
77
|
"prettier": "^3.8.1",
|
|
77
78
|
"tsx": "^4.21.0",
|
|
78
|
-
"typescript": "^
|
|
79
|
-
"vitest": "^4.1.
|
|
79
|
+
"typescript": "^6.0.2",
|
|
80
|
+
"vitest": "^4.1.2"
|
|
80
81
|
},
|
|
81
82
|
"dependencies": {
|
|
82
|
-
"
|
|
83
|
+
"ansi-colors": "^4.1.3",
|
|
83
84
|
"commander": "^14.0.3",
|
|
84
|
-
"diff": "^8.0.
|
|
85
|
+
"diff": "^8.0.4",
|
|
85
86
|
"diff2html": "3.4.56",
|
|
86
87
|
"open": "^11.0.0",
|
|
87
|
-
"picomatch": "^4.0.
|
|
88
|
-
"simple-git": "^3.
|
|
88
|
+
"picomatch": "^4.0.4",
|
|
89
|
+
"simple-git": "^3.35.2",
|
|
89
90
|
"tinyglobby": "^0.2.15",
|
|
90
|
-
"yaml": "^2.8.
|
|
91
|
+
"yaml": "^2.8.3",
|
|
91
92
|
"zod": "^4.3.6"
|
|
92
93
|
}
|
|
93
94
|
}
|