helm-env-delta 1.15.2 → 2.0.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/README.md +279 -95
- package/config.schema.json +496 -0
- package/dist/commandLine.d.ts +9 -11
- package/dist/commandLine.js +288 -101
- package/dist/config/ZodError.d.ts +2 -2
- package/dist/config/configFile.d.ts +1 -1
- package/dist/config/configFile.js +87 -41
- package/dist/config/configLoader.d.ts +2 -1
- package/dist/config/configMerger.d.ts +2 -1
- package/dist/consoleFormatter.d.ts +1 -1
- package/dist/consoleFormatter.js +12 -12
- package/dist/exitCodes.d.ts +5 -0
- package/dist/exitCodes.js +8 -0
- package/dist/index.js +82 -77
- package/dist/logger.d.ts +3 -3
- package/dist/pipeline/fileDiff.d.ts +6 -5
- package/dist/pipeline/fileLoader.d.ts +2 -1
- package/dist/pipeline/fileLoader.js +2 -2
- package/dist/pipeline/fileUpdater.d.ts +4 -4
- package/dist/pipeline/fileUpdater.js +1 -1
- package/dist/pipeline/stopRulesValidator.d.ts +2 -1
- package/dist/pipeline/stopRulesValidator.js +2 -4
- package/dist/pipeline/yamlFormatter.d.ts +1 -1
- package/dist/pipeline/yamlFormatter.js +9 -9
- package/dist/reporters/browserLauncher.js +1 -34
- package/dist/reporters/consoleDiffReporter.d.ts +2 -2
- package/dist/reporters/consoleDiffReporter.js +26 -26
- package/dist/reporters/htmlReporter.d.ts +4 -3
- package/dist/reporters/htmlReporter.js +20 -10
- package/dist/reporters/htmlTemplate.d.ts +1 -1
- package/dist/reporters/jsonReporter.d.ts +2 -2
- package/dist/reporters/treeRenderer.d.ts +1 -1
- package/dist/suggestionEngine.d.ts +2 -2
- package/dist/suggestionEngine.js +2 -2
- package/dist/utils/arrayMerger.d.ts +1 -1
- package/dist/utils/patternMatcher.d.ts +1 -1
- package/dist/utils/versionChecker.js +3 -3
- package/package.json +19 -17
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StopRuleViolation } from './pipeline/stopRulesValidator';
|
|
1
|
+
import { type StopRuleViolation } from './pipeline/stopRulesValidator';
|
|
2
2
|
export type BoxStyle = 'success' | 'warning' | 'error' | 'info';
|
|
3
3
|
export type ProgressStyle = 'loading' | 'success' | 'info';
|
|
4
4
|
export type ViolationMode = 'error' | 'warning' | 'force';
|
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);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EXIT_VALIDATION_WARNINGS = exports.EXIT_CONFIG_ERROR = exports.EXIT_STOP_RULE_VIOLATION = exports.EXIT_CHANGES_SYNCED = exports.EXIT_NO_CHANGES = void 0;
|
|
4
|
+
exports.EXIT_NO_CHANGES = 0;
|
|
5
|
+
exports.EXIT_CHANGES_SYNCED = 1;
|
|
6
|
+
exports.EXIT_STOP_RULE_VIOLATION = 2;
|
|
7
|
+
exports.EXIT_CONFIG_ERROR = 3;
|
|
8
|
+
exports.EXIT_VALIDATION_WARNINGS = 4;
|
package/dist/index.js
CHANGED
|
@@ -40,12 +40,13 @@ 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");
|
|
47
47
|
const config_1 = require("./config");
|
|
48
48
|
const consoleFormatter_1 = require("./consoleFormatter");
|
|
49
|
+
const exitCodes_1 = require("./exitCodes");
|
|
49
50
|
const logger_1 = require("./logger");
|
|
50
51
|
const pipeline_1 = require("./pipeline");
|
|
51
52
|
const reporters_1 = require("./reporters");
|
|
@@ -60,44 +61,46 @@ const versionChecker_1 = require("./utils/versionChecker");
|
|
|
60
61
|
const main = async () => {
|
|
61
62
|
const command = (0, commandLine_1.parseCommandLine)();
|
|
62
63
|
if (command.noColor)
|
|
63
|
-
|
|
64
|
+
ansi_colors_1.default.enabled = false;
|
|
64
65
|
const verbosityLevel = command.verbose ? 'verbose' : command.quiet ? 'quiet' : 'normal';
|
|
65
|
-
const logger = new logger_1.Logger({ level: verbosityLevel, isDiffJson: command.
|
|
66
|
+
const logger = new logger_1.Logger({ level: verbosityLevel, isDiffJson: command.json });
|
|
66
67
|
logger.log(`Now you run ${package_json_1.default.name} v${package_json_1.default.version}...`);
|
|
67
68
|
const configDirectory = node_path_1.default.join((0, node_os_1.homedir)(), '.helm-env-delta');
|
|
68
69
|
const firstRunMarker = node_path_1.default.join(configDirectory, 'first-run');
|
|
69
70
|
const isFirstRun = !(0, node_fs_1.existsSync)(firstRunMarker);
|
|
70
71
|
if (isFirstRun && !command.quiet) {
|
|
71
|
-
console.log(
|
|
72
|
-
console.log(
|
|
73
|
-
console.log(
|
|
74
|
-
console.log(
|
|
75
|
-
console.log(
|
|
76
|
-
console.log(
|
|
72
|
+
console.log(ansi_colors_1.default.cyan('\n👋 First time using helm-env-delta?\n'));
|
|
73
|
+
console.log(ansi_colors_1.default.dim(' Tips:'));
|
|
74
|
+
console.log(ansi_colors_1.default.dim(' • Always use --dry-run first to preview changes'));
|
|
75
|
+
console.log(ansi_colors_1.default.dim(' • Use the diff command to review changes before syncing'));
|
|
76
|
+
console.log(ansi_colors_1.default.dim(' • See examples: https://github.com/balazscsaba2006/helm-env-delta/tree/main/example'));
|
|
77
|
+
console.log(ansi_colors_1.default.dim(' • Run with --help to see all options\n'));
|
|
77
78
|
(0, node_fs_1.mkdirSync)(configDirectory, { recursive: true });
|
|
78
79
|
(0, node_fs_1.writeFileSync)(firstRunMarker, new Date().toISOString());
|
|
79
80
|
}
|
|
80
|
-
const config = (0, config_1.loadConfigFile)(command.config, command.quiet, logger, {
|
|
81
|
+
const config = (0, config_1.loadConfigFile)(command.config, command.quiet, logger, {
|
|
82
|
+
formatOnly: command.commandName === 'format'
|
|
83
|
+
});
|
|
81
84
|
if (config.requiredVersion)
|
|
82
85
|
configHasRequiredVersion = true;
|
|
83
|
-
if (command.
|
|
84
|
-
console.log(
|
|
86
|
+
if (command.commandName === 'show-config') {
|
|
87
|
+
console.log(ansi_colors_1.default.cyan('\n⚙️ Resolved Configuration:\n'));
|
|
85
88
|
console.log(YAML.stringify(config, { indent: 2 }));
|
|
86
89
|
return;
|
|
87
90
|
}
|
|
88
|
-
if (command.validate) {
|
|
91
|
+
if (command.commandName === 'validate') {
|
|
89
92
|
if (!config.source) {
|
|
90
|
-
logger.error('\nSource folder is required for
|
|
91
|
-
process.exit(
|
|
93
|
+
logger.error('\nSource folder is required for the validate command.', 'critical');
|
|
94
|
+
process.exit(exitCodes_1.EXIT_CONFIG_ERROR);
|
|
92
95
|
}
|
|
93
96
|
const validationConfig = config;
|
|
94
97
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Validating configuration...', 'info'));
|
|
95
98
|
const warningResult = (0, config_1.validateConfigWarnings)(validationConfig);
|
|
96
99
|
let hasAnyWarnings = warningResult.hasWarnings;
|
|
97
100
|
if (warningResult.hasWarnings) {
|
|
98
|
-
console.warn(
|
|
101
|
+
console.warn(ansi_colors_1.default.yellow('\n⚠️ Configuration Warnings (non-fatal):\n'));
|
|
99
102
|
for (const warning of warningResult.warnings)
|
|
100
|
-
console.warn(
|
|
103
|
+
console.warn(ansi_colors_1.default.yellow(` • ${warning}`));
|
|
101
104
|
}
|
|
102
105
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Loading files for validation...', 'loading'));
|
|
103
106
|
const sourceResult = await (0, pipeline_1.loadFiles)({
|
|
@@ -135,16 +138,21 @@ const main = async () => {
|
|
|
135
138
|
const usageResult = (0, pipeline_1.validatePatternUsage)(validationConfig, sourceFiles, destinationFiles);
|
|
136
139
|
hasAnyWarnings = hasAnyWarnings || usageResult.hasWarnings;
|
|
137
140
|
if (usageResult.hasWarnings) {
|
|
138
|
-
console.warn(
|
|
141
|
+
console.warn(ansi_colors_1.default.yellow('\n⚠️ Pattern Usage Warnings (non-fatal):\n'));
|
|
139
142
|
for (const warning of usageResult.warnings) {
|
|
140
|
-
const contextString = warning.context ?
|
|
141
|
-
console.warn(
|
|
143
|
+
const contextString = warning.context ? ansi_colors_1.default.dim(` (${warning.context})`) : '';
|
|
144
|
+
console.warn(ansi_colors_1.default.yellow(` • ${warning.message}${contextString}`));
|
|
142
145
|
if (warning.hint)
|
|
143
|
-
console.warn(
|
|
146
|
+
console.warn(ansi_colors_1.default.dim(` Hint: ${warning.hint}`));
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
if (hasAnyWarnings)
|
|
147
|
-
|
|
150
|
+
if (command.strict) {
|
|
151
|
+
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Configuration has warnings — strict mode: failing', 'info'));
|
|
152
|
+
process.exitCode = exitCodes_1.EXIT_VALIDATION_WARNINGS;
|
|
153
|
+
}
|
|
154
|
+
else
|
|
155
|
+
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Configuration has warnings but is usable', 'info'));
|
|
148
156
|
else
|
|
149
157
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Configuration is valid', 'success'));
|
|
150
158
|
return;
|
|
@@ -159,11 +167,7 @@ const main = async () => {
|
|
|
159
167
|
logger.debug(` Transforms: ${Object.keys(config.transforms || {}).length} pattern(s)`);
|
|
160
168
|
logger.debug(` Prune enabled: ${config.prune}`);
|
|
161
169
|
}
|
|
162
|
-
if (command.
|
|
163
|
-
if (!config.outputFormat) {
|
|
164
|
-
logger.log(chalk_1.default.yellow('\n⚠️ No outputFormat configured. Nothing to format.'));
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
170
|
+
if (command.commandName === 'format') {
|
|
167
171
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Loading destination files...', 'loading'));
|
|
168
172
|
const destinationResult = await (0, pipeline_1.loadFiles)({
|
|
169
173
|
baseDirectory: config.destination,
|
|
@@ -174,14 +178,6 @@ const main = async () => {
|
|
|
174
178
|
if (command.filter)
|
|
175
179
|
destinationFiles = (0, fileFilter_1.filterFileMap)(destinationFiles, command.filter);
|
|
176
180
|
logger.progress(`Loaded ${destinationFiles.size} destination file(s)`, 'success');
|
|
177
|
-
if (command.listFiles) {
|
|
178
|
-
const filesList = [...destinationFiles.keys()].toSorted();
|
|
179
|
-
console.log(chalk_1.default.cyan('\n📋 Files to be formatted:\n'));
|
|
180
|
-
console.log(chalk_1.default.yellow(`Destination files: ${filesList.length}`));
|
|
181
|
-
for (const file of filesList)
|
|
182
|
-
console.log(` ${chalk_1.default.dim(file)}`);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
181
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Formatting files...', 'info'));
|
|
186
182
|
let formattedCount = 0;
|
|
187
183
|
const errors = [];
|
|
@@ -215,13 +211,15 @@ const main = async () => {
|
|
|
215
211
|
logger.error(`\n❌ Encountered ${errors.length} error(s):`, 'critical');
|
|
216
212
|
for (const { path: errorPath, error } of errors)
|
|
217
213
|
logger.error(` ${errorPath}: ${error.message}`, 'critical');
|
|
218
|
-
process.exit(
|
|
214
|
+
process.exit(exitCodes_1.EXIT_CHANGES_SYNCED);
|
|
219
215
|
}
|
|
216
|
+
if (formattedCount > 0)
|
|
217
|
+
process.exitCode = exitCodes_1.EXIT_CHANGES_SYNCED;
|
|
220
218
|
return;
|
|
221
219
|
}
|
|
222
220
|
if (!config.source) {
|
|
223
|
-
logger.error('\nSource folder is required for
|
|
224
|
-
process.exit(
|
|
221
|
+
logger.error('\nSource folder is required for this command.', 'critical');
|
|
222
|
+
process.exit(exitCodes_1.EXIT_CONFIG_ERROR);
|
|
225
223
|
}
|
|
226
224
|
const syncConfig = config;
|
|
227
225
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Loading files...', 'loading'));
|
|
@@ -262,16 +260,16 @@ const main = async () => {
|
|
|
262
260
|
destinationFiles = filtered.destinationFiles;
|
|
263
261
|
logger.progress(`--my filter (${command.myDays} days, author: "${author}") matched ${sourceFiles.size} source, ${destinationFiles.size} destination file(s)`, 'info');
|
|
264
262
|
}
|
|
265
|
-
if (command.
|
|
263
|
+
if (command.commandName === 'list-files') {
|
|
266
264
|
const sourceFilesList = [...sourceFiles.keys()].toSorted();
|
|
267
265
|
const destinationFilesList = [...destinationFiles.keys()].toSorted();
|
|
268
|
-
console.log(
|
|
269
|
-
console.log(
|
|
266
|
+
console.log(ansi_colors_1.default.cyan('\n📋 Files to be synced:\n'));
|
|
267
|
+
console.log(ansi_colors_1.default.green(`Source files: ${sourceFilesList.length}`));
|
|
270
268
|
for (const file of sourceFilesList)
|
|
271
|
-
console.log(` ${
|
|
272
|
-
console.log(
|
|
269
|
+
console.log(` ${ansi_colors_1.default.dim(file)}`);
|
|
270
|
+
console.log(ansi_colors_1.default.yellow(`\nDestination files: ${destinationFilesList.length}`));
|
|
273
271
|
for (const file of destinationFilesList)
|
|
274
|
-
console.log(` ${
|
|
272
|
+
console.log(` ${ansi_colors_1.default.dim(file)}`);
|
|
275
273
|
return;
|
|
276
274
|
}
|
|
277
275
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Computing differences...', 'info'));
|
|
@@ -279,33 +277,38 @@ const main = async () => {
|
|
|
279
277
|
const diffResult = (0, fileFilter_1.filterDiffResultByMode)(rawDiffResult, command.mode);
|
|
280
278
|
if (logger.shouldShow('debug'))
|
|
281
279
|
logger.debug('Diff pipeline: parse → transforms → skipPath → normalize → compare');
|
|
282
|
-
if (command.
|
|
283
|
-
(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
280
|
+
if (command.commandName === 'diff') {
|
|
281
|
+
if (!command.quiet && !command.html && !command.json)
|
|
282
|
+
(0, reporters_1.showConsoleDiff)(diffResult, syncConfig);
|
|
283
|
+
if ((command.html || command.reportOutput) && !command.quiet)
|
|
284
|
+
await (0, reporters_1.generateHtmlReport)(diffResult, [], syncConfig, true, logger, undefined, command.reportOutput);
|
|
285
|
+
if (command.json)
|
|
286
|
+
(0, reporters_1.generateJsonReport)(diffResult, [], { violations: [], isValid: true }, syncConfig, true, package_json_1.default.version);
|
|
287
|
+
return;
|
|
289
288
|
}
|
|
290
|
-
|
|
289
|
+
logger.log(` New files: ${diffResult.addedFiles.length}`);
|
|
290
|
+
logger.log(` Deleted files: ${diffResult.deletedFiles.length}`);
|
|
291
|
+
logger.log(` Changed files: ${diffResult.changedFiles.length}`);
|
|
292
|
+
logger.log(` Unchanged files: ${diffResult.unchangedFiles.length}`);
|
|
293
|
+
if (command.commandName === 'suggest') {
|
|
291
294
|
logger.log('\n' + (0, consoleFormatter_1.formatProgressMessage)('Analyzing differences for suggestions...', 'info'));
|
|
292
295
|
try {
|
|
293
296
|
const suggestions = (0, suggestionEngine_1.analyzeDifferencesForSuggestions)(diffResult, syncConfig, command.suggestThreshold);
|
|
294
297
|
const yaml = (0, suggestionEngine_1.formatSuggestionsAsYaml)(suggestions);
|
|
295
|
-
console.log(
|
|
298
|
+
console.log(ansi_colors_1.default.cyan('\n💡 Suggested Configuration:\n'));
|
|
296
299
|
console.log(yaml);
|
|
297
300
|
if (suggestions.metadata.changedFiles === 0)
|
|
298
|
-
console.log(
|
|
301
|
+
console.log(ansi_colors_1.default.yellow('\nℹ️ No changes detected. Files are already in sync.'));
|
|
299
302
|
else {
|
|
300
|
-
console.log(
|
|
301
|
-
console.log(
|
|
303
|
+
console.log(ansi_colors_1.default.dim('\n---'));
|
|
304
|
+
console.log(ansi_colors_1.default.dim('💡 Tip: Copy relevant sections to your config.yaml and test with run --dry-run'));
|
|
302
305
|
}
|
|
303
306
|
return;
|
|
304
307
|
}
|
|
305
308
|
catch (error) {
|
|
306
309
|
if ((0, suggestionEngine_1.isSuggestionEngineError)(error)) {
|
|
307
310
|
logger.error('\nFailed to generate suggestions: ' + error.message, 'critical');
|
|
308
|
-
process.exit(
|
|
311
|
+
process.exit(exitCodes_1.EXIT_CHANGES_SYNCED);
|
|
309
312
|
}
|
|
310
313
|
throw error;
|
|
311
314
|
}
|
|
@@ -323,41 +326,40 @@ const main = async () => {
|
|
|
323
326
|
for (const violation of validationResult.violations)
|
|
324
327
|
logger.stopRule(violation, 'error');
|
|
325
328
|
logger.error('\nUse --force to override stop rules or --dry-run to preview changes.', 'critical');
|
|
326
|
-
process.exit(
|
|
329
|
+
process.exit(exitCodes_1.EXIT_STOP_RULE_VIOLATION);
|
|
327
330
|
}
|
|
328
331
|
if (!command.dryRun && !command.quiet) {
|
|
329
|
-
console.log(
|
|
330
|
-
console.log(
|
|
331
|
-
console.log(` ${
|
|
332
|
-
console.log(` ${
|
|
333
|
-
console.log(` ${
|
|
334
|
-
console.log(` ${
|
|
335
|
-
console.log(
|
|
332
|
+
console.log(ansi_colors_1.default.cyan('\n📊 Sync Summary:'));
|
|
333
|
+
console.log(ansi_colors_1.default.dim('─'.repeat(60)));
|
|
334
|
+
console.log(` ${ansi_colors_1.default.green('Added:')} ${diffResult.addedFiles.length} files`);
|
|
335
|
+
console.log(` ${ansi_colors_1.default.yellow('Changed:')} ${diffResult.changedFiles.length} files`);
|
|
336
|
+
console.log(` ${ansi_colors_1.default.red('Deleted:')} ${diffResult.deletedFiles.length} files (${syncConfig.prune ? 'prune enabled' : 'prune disabled'})`);
|
|
337
|
+
console.log(` ${ansi_colors_1.default.blue('Unchanged:')} ${diffResult.unchangedFiles.length} files`);
|
|
338
|
+
console.log(ansi_colors_1.default.dim('─'.repeat(60)));
|
|
336
339
|
if (diffResult.deletedFiles.length > 0 && syncConfig.prune) {
|
|
337
|
-
console.warn(
|
|
340
|
+
console.warn(ansi_colors_1.default.red('⚠️ Warning: Prune is enabled. The following files will be permanently deleted:'));
|
|
338
341
|
for (const f of diffResult.deletedFiles)
|
|
339
|
-
console.warn(
|
|
342
|
+
console.warn(ansi_colors_1.default.red(` - ${f}`));
|
|
340
343
|
}
|
|
341
344
|
if (syncConfig.confirmationDelay > 0) {
|
|
342
345
|
const totalSeconds = Math.ceil(syncConfig.confirmationDelay / 1000);
|
|
343
|
-
console.log(
|
|
346
|
+
console.log(ansi_colors_1.default.dim('\nPress Ctrl+C to cancel.\n'));
|
|
344
347
|
for (let remaining = totalSeconds; remaining > 0; remaining--) {
|
|
345
|
-
process.stdout.write(
|
|
348
|
+
process.stdout.write(ansi_colors_1.default.dim(` Proceeding in ${remaining}s...\r`));
|
|
346
349
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
347
350
|
}
|
|
348
351
|
process.stdout.write(' '.repeat(40) + '\r');
|
|
349
352
|
}
|
|
350
353
|
else
|
|
351
|
-
console.log(
|
|
354
|
+
console.log(ansi_colors_1.default.dim('\nPress Ctrl+C to cancel, or use --dry-run to preview changes first.\n'));
|
|
352
355
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
(0, reporters_1.generateJsonReport)(diffResult, formattedFiles, validationResult, syncConfig, command.dryRun, package_json_1.default.version);
|
|
356
|
+
await (0, pipeline_1.updateFiles)(diffResult, sourceFiles, destinationFiles, syncConfig, command.dryRun, command.skipFormat, logger);
|
|
357
|
+
const hasChanges = diffResult.addedFiles.length > 0 || diffResult.deletedFiles.length > 0 || diffResult.changedFiles.length > 0;
|
|
358
|
+
if (hasChanges)
|
|
359
|
+
process.exitCode = exitCodes_1.EXIT_CHANGES_SYNCED;
|
|
358
360
|
};
|
|
359
361
|
let configHasRequiredVersion = false;
|
|
360
|
-
(async () => {
|
|
362
|
+
void (async () => {
|
|
361
363
|
try {
|
|
362
364
|
await main();
|
|
363
365
|
}
|
|
@@ -392,7 +394,10 @@ let configHasRequiredVersion = false;
|
|
|
392
394
|
console.error('Unexpected error:', error.message);
|
|
393
395
|
else
|
|
394
396
|
console.error('Unexpected error:', error);
|
|
395
|
-
|
|
397
|
+
if ((0, config_1.isConfigMergerError)(error) || (0, config_1.isConfigLoaderError)(error) || (0, config_1.isZodValidationError)(error))
|
|
398
|
+
process.exit(exitCodes_1.EXIT_CONFIG_ERROR);
|
|
399
|
+
else
|
|
400
|
+
process.exit(exitCodes_1.EXIT_CHANGES_SYNCED);
|
|
396
401
|
}
|
|
397
402
|
finally {
|
|
398
403
|
const command = (0, commandLine_1.parseCommandLine)();
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FileOperation, ProgressStyle, ViolationMode } from './consoleFormatter';
|
|
2
|
-
import { StopRuleViolation } from './pipeline/stopRulesValidator';
|
|
1
|
+
import { type FileOperation, type ProgressStyle, type ViolationMode } from './consoleFormatter';
|
|
2
|
+
import { type StopRuleViolation } from './pipeline/stopRulesValidator';
|
|
3
3
|
export type VerbosityLevel = 'quiet' | 'normal' | 'verbose';
|
|
4
4
|
export type OutputCategory = 'critical' | 'normal' | 'debug' | 'special';
|
|
5
5
|
export type LoggerOptions = {
|
|
@@ -7,7 +7,7 @@ export type LoggerOptions = {
|
|
|
7
7
|
isDiffJson: boolean;
|
|
8
8
|
};
|
|
9
9
|
export declare class Logger {
|
|
10
|
-
private level;
|
|
10
|
+
private readonly level;
|
|
11
11
|
constructor(options: LoggerOptions);
|
|
12
12
|
shouldShow(category: OutputCategory): boolean;
|
|
13
13
|
log(message: string, category?: OutputCategory): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Config, FixedValueConfig, FixedValueRule, TransformConfig } from '../config';
|
|
2
|
-
import {
|
|
1
|
+
import { type Config, type FixedValueConfig, type FixedValueRule, type TransformConfig } from '../config';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
3
|
+
import { type FileMap } from './fileLoader';
|
|
3
4
|
export interface FileDiffResult {
|
|
4
5
|
addedFiles: AddedFile[];
|
|
5
6
|
deletedFiles: string[];
|
|
@@ -15,8 +16,8 @@ export interface ChangedFile {
|
|
|
15
16
|
processedDestContent: unknown;
|
|
16
17
|
rawParsedSource: unknown;
|
|
17
18
|
rawParsedDest: unknown;
|
|
18
|
-
skipPaths
|
|
19
|
-
fixedValueRules
|
|
19
|
+
skipPaths?: string[];
|
|
20
|
+
fixedValueRules?: FixedValueRule[];
|
|
20
21
|
normalizedSource?: unknown;
|
|
21
22
|
normalizedDest?: unknown;
|
|
22
23
|
parsedSource?: unknown;
|
|
@@ -55,5 +56,5 @@ export declare class FileDiffError extends FileDiffErrorClass {
|
|
|
55
56
|
}
|
|
56
57
|
export declare const isFileDiffError: (error: unknown) => error is FileDiffError;
|
|
57
58
|
export declare const getSkipPathsForFile: (filePath: string, skipPath?: Record<string, string[]>) => string[];
|
|
58
|
-
export declare const computeFileDiff: (sourceFiles: FileMap, destinationFiles: FileMap, config: Config, logger?:
|
|
59
|
+
export declare const computeFileDiff: (sourceFiles: FileMap, destinationFiles: FileMap, config: Config, logger?: Logger, originalPaths?: Map<string, string>) => FileDiffResult;
|
|
59
60
|
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TransformConfig } from '../config';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
2
3
|
export interface FileLoaderOptions {
|
|
3
4
|
baseDirectory: string;
|
|
4
5
|
include: string[];
|
|
@@ -29,5 +30,5 @@ declare const FileLoaderErrorClass: {
|
|
|
29
30
|
export declare class FileLoaderError extends FileLoaderErrorClass {
|
|
30
31
|
}
|
|
31
32
|
export declare const isFileLoaderError: (error: unknown) => error is FileLoaderError;
|
|
32
|
-
export declare const loadFiles: (options: FileLoaderOptions, logger?:
|
|
33
|
+
export declare const loadFiles: (options: FileLoaderOptions, logger?: Logger) => Promise<FileLoaderResult>;
|
|
33
34
|
export {};
|
|
@@ -155,8 +155,8 @@ const readFilesIntoMap = async (baseDirectory, absoluteFilePaths) => {
|
|
|
155
155
|
};
|
|
156
156
|
const loadFiles = async (options, logger) => {
|
|
157
157
|
const absoluteBaseDirectory = await validateAndResolveBaseDirectory(options.baseDirectory);
|
|
158
|
-
const includePatterns = options.include
|
|
159
|
-
const excludePatterns = options.exclude
|
|
158
|
+
const includePatterns = options.include;
|
|
159
|
+
const excludePatterns = options.exclude;
|
|
160
160
|
const files = await findMatchingFiles(absoluteBaseDirectory, includePatterns, excludePatterns, options.transforms, options.skipExclude);
|
|
161
161
|
if (logger?.shouldShow('debug')) {
|
|
162
162
|
logger.debug('Glob matching:');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Config } from '../config';
|
|
2
|
-
import { Logger } from '../logger';
|
|
3
|
-
import { ChangedFile, FileDiffResult } from './fileDiff';
|
|
4
|
-
import { FileMap } from './fileLoader';
|
|
1
|
+
import { type Config } from '../config';
|
|
2
|
+
import { type Logger } from '../logger';
|
|
3
|
+
import { type ChangedFile, type FileDiffResult } from './fileDiff';
|
|
4
|
+
import { type FileMap } from './fileLoader';
|
|
5
5
|
export interface FileUpdateError {
|
|
6
6
|
operation: 'add' | 'update' | 'delete';
|
|
7
7
|
path: string;
|
|
@@ -113,7 +113,7 @@ const deepMerge = (fullTarget, filteredSource, filteredTarget, currentPath = [],
|
|
|
113
113
|
if (typeof filteredSource === 'object' && typeof fullTarget === 'object') {
|
|
114
114
|
const sourceObject = filteredSource;
|
|
115
115
|
const fullTargetObject = fullTarget;
|
|
116
|
-
const filteredTargetObject = filteredTarget
|
|
116
|
+
const filteredTargetObject = (typeof filteredTarget === 'object' && filteredTarget ? filteredTarget : {});
|
|
117
117
|
const result = { ...sourceObject };
|
|
118
118
|
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
119
119
|
for (const [key, value] of Object.entries(fullTargetObject))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { StopRule } from '../config';
|
|
2
|
+
import type { Logger } from '../logger';
|
|
2
3
|
import type { FileDiffResult } from './fileDiff';
|
|
3
4
|
declare const StopRulesValidatorErrorClass: {
|
|
4
5
|
new (message: string, options?: import("../utils").ErrorOptions): {
|
|
@@ -37,5 +38,5 @@ export interface ValidationContext {
|
|
|
37
38
|
filePath: string;
|
|
38
39
|
configDirectory?: string;
|
|
39
40
|
}
|
|
40
|
-
export declare const validateStopRules: (diffResult: FileDiffResult, stopRulesConfig?: Record<string, StopRule[]>, configDirectory?: string, logger?:
|
|
41
|
+
export declare const validateStopRules: (diffResult: FileDiffResult, stopRulesConfig?: Record<string, StopRule[]>, configDirectory?: string, logger?: Logger) => ValidationResult;
|
|
41
42
|
export {};
|
|
@@ -89,16 +89,14 @@ const validateRule = (context) => {
|
|
|
89
89
|
return validateRegex(rule, oldValue, updatedValue, filePath);
|
|
90
90
|
if (rule.type === 'regexFile')
|
|
91
91
|
return validateRegexFile(rule, oldValue, updatedValue, filePath, configDirectory);
|
|
92
|
-
|
|
93
|
-
return validateRegexFileKey(rule, oldValue, updatedValue, filePath, configDirectory);
|
|
92
|
+
return validateRegexFileKey(rule, oldValue, updatedValue, filePath, configDirectory);
|
|
94
93
|
}
|
|
95
94
|
else {
|
|
96
95
|
if (rule.type === 'regex')
|
|
97
96
|
return validateRegexGlobal(rule, oldData, updatedData, filePath);
|
|
98
97
|
if (rule.type === 'regexFile')
|
|
99
98
|
return validateRegexFileGlobal(rule, oldData, updatedData, filePath, configDirectory);
|
|
100
|
-
|
|
101
|
-
return validateRegexFileKeyGlobal(rule, oldData, updatedData, filePath, configDirectory);
|
|
99
|
+
return validateRegexFileKeyGlobal(rule, oldData, updatedData, filePath, configDirectory);
|
|
102
100
|
}
|
|
103
101
|
if (!rule.path)
|
|
104
102
|
return undefined;
|
|
@@ -33,31 +33,31 @@ const getFormattingRules = (filePath, outputFormat) => {
|
|
|
33
33
|
const arraySort = [];
|
|
34
34
|
const quoteValues = [];
|
|
35
35
|
const allPatterns = new Set();
|
|
36
|
-
if (outputFormat
|
|
36
|
+
if (outputFormat.keyOrders)
|
|
37
37
|
for (const pattern of Object.keys(outputFormat.keyOrders))
|
|
38
38
|
allPatterns.add(pattern);
|
|
39
|
-
if (outputFormat
|
|
39
|
+
if (outputFormat.keySort)
|
|
40
40
|
for (const pattern of Object.keys(outputFormat.keySort))
|
|
41
41
|
allPatterns.add(pattern);
|
|
42
|
-
if (outputFormat
|
|
42
|
+
if (outputFormat.arraySort)
|
|
43
43
|
for (const pattern of Object.keys(outputFormat.arraySort))
|
|
44
44
|
allPatterns.add(pattern);
|
|
45
|
-
if (outputFormat
|
|
45
|
+
if (outputFormat.quoteValues)
|
|
46
46
|
for (const pattern of Object.keys(outputFormat.quoteValues))
|
|
47
47
|
allPatterns.add(pattern);
|
|
48
48
|
for (const pattern of allPatterns) {
|
|
49
49
|
if (!patternMatcher_1.globalMatcher.match(filePath, pattern))
|
|
50
50
|
continue;
|
|
51
|
-
const keyOrder = outputFormat
|
|
51
|
+
const keyOrder = outputFormat.keyOrders?.[pattern];
|
|
52
52
|
if (keyOrder)
|
|
53
53
|
keyOrders.push(keyOrder);
|
|
54
|
-
const keySortRule = outputFormat
|
|
54
|
+
const keySortRule = outputFormat.keySort?.[pattern];
|
|
55
55
|
if (keySortRule)
|
|
56
56
|
keySort.push(keySortRule);
|
|
57
|
-
const arrayRule = outputFormat
|
|
57
|
+
const arrayRule = outputFormat.arraySort?.[pattern];
|
|
58
58
|
if (arrayRule)
|
|
59
59
|
arraySort.push(arrayRule);
|
|
60
|
-
const quoteValue = outputFormat
|
|
60
|
+
const quoteValue = outputFormat.quoteValues?.[pattern];
|
|
61
61
|
if (quoteValue)
|
|
62
62
|
quoteValues.push(quoteValue);
|
|
63
63
|
}
|
|
@@ -317,7 +317,7 @@ const isPotentialMatch = (currentPath, targetPath) => {
|
|
|
317
317
|
return true;
|
|
318
318
|
};
|
|
319
319
|
const sortYamlSeq = (seq, sortByField, order) => {
|
|
320
|
-
if (
|
|
320
|
+
if (seq.items.length === 0)
|
|
321
321
|
return;
|
|
322
322
|
const firstItem = seq.items.find((item) => item != undefined);
|
|
323
323
|
if (firstItem !== undefined) {
|
|
@@ -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);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Config } from '../config';
|
|
2
|
-
import { FileDiffResult } from '../pipeline';
|
|
1
|
+
import { type Config } from '../config';
|
|
2
|
+
import { type FileDiffResult } from '../pipeline';
|
|
3
3
|
export declare const showConsoleDiff: (diffResult: FileDiffResult, config: Config) => void;
|