helm-env-delta 1.7.1 → 1.7.2
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 +9 -2
- package/dist/commandLine.d.ts +1 -0
- package/dist/commandLine.js +6 -0
- package/dist/fileLoader.d.ts +1 -0
- package/dist/fileLoader.js +10 -6
- package/dist/index.js +47 -2
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -642,7 +642,8 @@ hed --config <file> [options] # Short alias
|
|
|
642
642
|
| `--diff-json` | Output JSON to stdout (pipe to jq) |
|
|
643
643
|
| `--list-files` | List source/destination files without processing |
|
|
644
644
|
| `--show-config` | Display resolved config after inheritance |
|
|
645
|
-
| `--
|
|
645
|
+
| `--format-only` | Format destination files without syncing |
|
|
646
|
+
| `--skip-format` | Skip YAML formatting during sync |
|
|
646
647
|
| `--no-color` | Disable colored output (CI/accessibility) |
|
|
647
648
|
| `--verbose` | Show detailed debug info |
|
|
648
649
|
| `--quiet` | Suppress output except errors |
|
|
@@ -679,6 +680,12 @@ hed --config config.yaml
|
|
|
679
680
|
|
|
680
681
|
# Force override stop rules
|
|
681
682
|
hed --config config.yaml --force
|
|
683
|
+
|
|
684
|
+
# Format destination files only (no sync)
|
|
685
|
+
hed --config config.yaml --format-only
|
|
686
|
+
|
|
687
|
+
# Preview format changes
|
|
688
|
+
hed --config config.yaml --format-only --dry-run
|
|
682
689
|
```
|
|
683
690
|
|
|
684
691
|
---
|
|
@@ -749,7 +756,7 @@ git push origin main
|
|
|
749
756
|
|
|
750
757
|
✅ **Flexibility** - Per-file patterns. Config inheritance. Regex transforms.
|
|
751
758
|
|
|
752
|
-
✅ **Reliability** -
|
|
759
|
+
✅ **Reliability** - 920 tests, 84% coverage. Battle-tested.
|
|
753
760
|
|
|
754
761
|
---
|
|
755
762
|
|
package/dist/commandLine.d.ts
CHANGED
package/dist/commandLine.js
CHANGED
|
@@ -19,6 +19,7 @@ const parseCommandLine = (argv) => {
|
|
|
19
19
|
.option('--diff-html', 'Generate and open HTML diff report in browser', false)
|
|
20
20
|
.option('--diff-json', 'Output diff as JSON to stdout', false)
|
|
21
21
|
.option('--skip-format', 'Skip YAML formatting (outputFormat section)', false)
|
|
22
|
+
.option('--format-only', 'Format YAML files in destination without syncing', false)
|
|
22
23
|
.option('--validate', 'Validate configuration file and exit', false)
|
|
23
24
|
.option('--list-files', 'List files that would be synced without processing diffs', false)
|
|
24
25
|
.option('--show-config', 'Display resolved configuration after inheritance and exit', false)
|
|
@@ -53,6 +54,10 @@ Documentation: https://github.com/balazscsaba2006/helm-env-delta
|
|
|
53
54
|
console.error('Error: --verbose and --quiet flags are mutually exclusive');
|
|
54
55
|
process.exit(1);
|
|
55
56
|
}
|
|
57
|
+
if (options['formatOnly'] && options['skipFormat']) {
|
|
58
|
+
console.error('Error: --format-only and --skip-format flags are mutually exclusive');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
56
61
|
const threshold = Number.parseFloat(options['suggestThreshold']);
|
|
57
62
|
if (Number.isNaN(threshold) || threshold < 0 || threshold > 1) {
|
|
58
63
|
console.error('Error: --suggest-threshold must be a number between 0 and 1');
|
|
@@ -66,6 +71,7 @@ Documentation: https://github.com/balazscsaba2006/helm-env-delta
|
|
|
66
71
|
diffHtml: options['diffHtml'],
|
|
67
72
|
diffJson: options['diffJson'],
|
|
68
73
|
skipFormat: options['skipFormat'],
|
|
74
|
+
formatOnly: options['formatOnly'],
|
|
69
75
|
validate: options['validate'],
|
|
70
76
|
listFiles: options['listFiles'],
|
|
71
77
|
showConfig: options['showConfig'],
|
package/dist/fileLoader.d.ts
CHANGED
package/dist/fileLoader.js
CHANGED
|
@@ -67,10 +67,12 @@ const validateAndResolveBaseDirectory = async (baseDirectory) => {
|
|
|
67
67
|
throw accessError;
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
|
-
const findMatchingFiles = async (baseDirectory, includePatterns, excludePatterns, transforms) => {
|
|
70
|
+
const findMatchingFiles = async (baseDirectory, includePatterns, excludePatterns, transforms, skipExclude) => {
|
|
71
71
|
try {
|
|
72
72
|
if (!transforms) {
|
|
73
|
-
const allPatterns =
|
|
73
|
+
const allPatterns = skipExclude
|
|
74
|
+
? [...includePatterns]
|
|
75
|
+
: [...includePatterns, ...excludePatterns.map((pattern) => `!${pattern}`)];
|
|
74
76
|
const matchedFiles = await (0, tinyglobby_1.glob)(allPatterns, {
|
|
75
77
|
cwd: baseDirectory,
|
|
76
78
|
absolute: true,
|
|
@@ -94,9 +96,11 @@ const findMatchingFiles = async (baseDirectory, includePatterns, excludePatterns
|
|
|
94
96
|
const included = includePatterns.some((pattern) => patternMatcher_1.globalMatcher.match(transformedPath, pattern));
|
|
95
97
|
if (!included)
|
|
96
98
|
continue;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
if (!skipExclude) {
|
|
100
|
+
const excluded = excludePatterns.some((pattern) => patternMatcher_1.globalMatcher.match(transformedPath, pattern));
|
|
101
|
+
if (excluded)
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
100
104
|
filtered.push(absolutePath);
|
|
101
105
|
}
|
|
102
106
|
return filtered;
|
|
@@ -153,7 +157,7 @@ const loadFiles = async (options, logger) => {
|
|
|
153
157
|
const absoluteBaseDirectory = await validateAndResolveBaseDirectory(options.baseDirectory);
|
|
154
158
|
const includePatterns = options.include ?? ['**/*'];
|
|
155
159
|
const excludePatterns = options.exclude ?? [];
|
|
156
|
-
const files = await findMatchingFiles(absoluteBaseDirectory, includePatterns, excludePatterns, options.transforms);
|
|
160
|
+
const files = await findMatchingFiles(absoluteBaseDirectory, includePatterns, excludePatterns, options.transforms, options.skipExclude);
|
|
157
161
|
if (logger?.shouldShow('debug')) {
|
|
158
162
|
logger.debug('Glob matching:');
|
|
159
163
|
logger.debug(` Directory: ${absoluteBaseDirectory}`);
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const node_fs_1 = require("node:fs");
|
|
40
|
+
const promises_1 = require("node:fs/promises");
|
|
40
41
|
const node_os_1 = require("node:os");
|
|
41
42
|
const node_path_1 = __importDefault(require("node:path"));
|
|
42
43
|
const chalk_1 = __importDefault(require("chalk"));
|
|
@@ -60,7 +61,9 @@ const stopRulesValidator_1 = require("./stopRulesValidator");
|
|
|
60
61
|
const suggestionEngine_1 = require("./suggestionEngine");
|
|
61
62
|
const collisionDetector_1 = require("./utils/collisionDetector");
|
|
62
63
|
const filenameTransformer_1 = require("./utils/filenameTransformer");
|
|
64
|
+
const fileType_1 = require("./utils/fileType");
|
|
63
65
|
const versionChecker_1 = require("./utils/versionChecker");
|
|
66
|
+
const yamlFormatter_1 = require("./yamlFormatter");
|
|
64
67
|
const ZodError_1 = require("./ZodError");
|
|
65
68
|
const main = async () => {
|
|
66
69
|
const command = (0, commandLine_1.parseCommandLine)();
|
|
@@ -102,13 +105,15 @@ const main = async () => {
|
|
|
102
105
|
baseDirectory: config.source,
|
|
103
106
|
include: config.include,
|
|
104
107
|
exclude: config.exclude,
|
|
105
|
-
transforms: config.transforms
|
|
108
|
+
transforms: config.transforms,
|
|
109
|
+
skipExclude: true
|
|
106
110
|
}, logger);
|
|
107
111
|
const sourceFiles = sourceResult.fileMap;
|
|
108
112
|
const destinationResult = await (0, fileLoader_1.loadFiles)({
|
|
109
113
|
baseDirectory: config.destination,
|
|
110
114
|
include: config.include,
|
|
111
|
-
exclude: config.exclude
|
|
115
|
+
exclude: config.exclude,
|
|
116
|
+
skipExclude: true
|
|
112
117
|
}, logger);
|
|
113
118
|
const destinationFiles = destinationResult.fileMap;
|
|
114
119
|
logger.progress(`Loaded ${sourceFiles.size} source, ${destinationFiles.size} destination file(s)`, 'success');
|
|
@@ -171,6 +176,46 @@ const main = async () => {
|
|
|
171
176
|
console.log(` ${chalk_1.default.dim(file)}`);
|
|
172
177
|
return;
|
|
173
178
|
}
|
|
179
|
+
if (command.formatOnly) {
|
|
180
|
+
if (!config.outputFormat) {
|
|
181
|
+
logger.log(chalk_1.default.yellow('\n⚠️ No outputFormat configured. Nothing to format.'));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Formatting files...', 'info'));
|
|
185
|
+
let formattedCount = 0;
|
|
186
|
+
const errors = [];
|
|
187
|
+
for (const [relativePath, content] of destinationFiles) {
|
|
188
|
+
if (!(0, fileType_1.isYamlFile)(relativePath))
|
|
189
|
+
continue;
|
|
190
|
+
try {
|
|
191
|
+
const formatted = (0, yamlFormatter_1.formatYaml)(content, relativePath, config.outputFormat);
|
|
192
|
+
if (formatted !== content) {
|
|
193
|
+
const absolutePath = node_path_1.default.join(config.destination, relativePath);
|
|
194
|
+
if (command.dryRun)
|
|
195
|
+
logger.fileOp('format', relativePath, true);
|
|
196
|
+
else {
|
|
197
|
+
await (0, promises_1.writeFile)(absolutePath, formatted, 'utf8');
|
|
198
|
+
logger.fileOp('format', relativePath, false);
|
|
199
|
+
}
|
|
200
|
+
formattedCount++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
errors.push({ path: relativePath, error: error });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (command.dryRun)
|
|
208
|
+
logger.log(`\n[DRY RUN] Would format ${formattedCount} file(s)`);
|
|
209
|
+
else
|
|
210
|
+
logger.log(`\n✓ Formatted ${formattedCount} file(s)`);
|
|
211
|
+
if (errors.length > 0) {
|
|
212
|
+
logger.error(`\n❌ Encountered ${errors.length} error(s):`, 'critical');
|
|
213
|
+
for (const { path: errorPath, error } of errors)
|
|
214
|
+
logger.error(` ${errorPath}: ${error.message}`, 'critical');
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
174
219
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Computing differences...', 'info'));
|
|
175
220
|
const diffResult = (0, fileDiff_1.computeFileDiff)(sourceFiles, destinationFiles, config, logger, originalPaths);
|
|
176
221
|
if (logger.shouldShow('debug'))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "helm-env-delta",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "HelmEnvDelta – environment-aware YAML delta and sync for GitOps",
|
|
5
5
|
"author": "BCsabaEngine",
|
|
6
6
|
"license": "ISC",
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/hogan.js": "^3.0.5",
|
|
65
|
-
"@types/node": "^25.0.
|
|
65
|
+
"@types/node": "^25.0.10",
|
|
66
66
|
"@types/picomatch": "^4.0.2",
|
|
67
|
-
"@typescript-eslint/eslint-plugin": "^8.53.
|
|
68
|
-
"@typescript-eslint/parser": "^8.53.
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
68
|
+
"@typescript-eslint/parser": "^8.53.1",
|
|
69
69
|
"@vitest/coverage-v8": "^4.0.17",
|
|
70
70
|
"eslint": "^9.39.2",
|
|
71
71
|
"eslint-config-prettier": "^10.1.8",
|
|
72
72
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
73
73
|
"eslint-plugin-unicorn": "^62.0.0",
|
|
74
|
-
"prettier": "^3.8.
|
|
74
|
+
"prettier": "^3.8.1",
|
|
75
75
|
"tsx": "^4.21.0",
|
|
76
76
|
"typescript": "^5.9.3",
|
|
77
77
|
"vitest": "^4.0.17"
|