helm-env-delta 1.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/LICENSE +15 -0
- package/README.md +1128 -0
- package/bin/index.js +2 -0
- package/dist/ZodError.d.ts +8 -0
- package/dist/ZodError.js +33 -0
- package/dist/arrayDiffer.d.ts +8 -0
- package/dist/arrayDiffer.js +47 -0
- package/dist/commandLine.d.ts +9 -0
- package/dist/commandLine.js +32 -0
- package/dist/configFile.d.ts +148 -0
- package/dist/configFile.js +135 -0
- package/dist/configLoader.d.ts +3 -0
- package/dist/configLoader.js +12 -0
- package/dist/configMerger.d.ts +21 -0
- package/dist/configMerger.js +190 -0
- package/dist/consoleDiffReporter.d.ts +3 -0
- package/dist/consoleDiffReporter.js +172 -0
- package/dist/consoleFormatter.d.ts +10 -0
- package/dist/consoleFormatter.js +103 -0
- package/dist/fileDiff.d.ts +41 -0
- package/dist/fileDiff.js +163 -0
- package/dist/fileLoader.d.ts +25 -0
- package/dist/fileLoader.js +105 -0
- package/dist/fileUpdater.d.ts +27 -0
- package/dist/fileUpdater.js +264 -0
- package/dist/htmlReporter.d.ts +27 -0
- package/dist/htmlReporter.js +600 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +91 -0
- package/dist/jsonReporter.d.ts +70 -0
- package/dist/jsonReporter.js +122 -0
- package/dist/stopRulesValidator.d.ts +33 -0
- package/dist/stopRulesValidator.js +168 -0
- package/dist/utils/deepEqual.d.ts +1 -0
- package/dist/utils/deepEqual.js +48 -0
- package/dist/utils/diffGenerator.d.ts +1 -0
- package/dist/utils/diffGenerator.js +8 -0
- package/dist/utils/errors.d.ts +23 -0
- package/dist/utils/errors.js +39 -0
- package/dist/utils/fileType.d.ts +1 -0
- package/dist/utils/fileType.js +8 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/jsonPath.d.ts +2 -0
- package/dist/utils/jsonPath.js +29 -0
- package/dist/utils/serialization.d.ts +2 -0
- package/dist/utils/serialization.js +40 -0
- package/dist/utils/transformer.d.ts +21 -0
- package/dist/utils/transformer.js +60 -0
- package/dist/yamlFormatter.d.ts +20 -0
- package/dist/yamlFormatter.js +315 -0
- package/package.json +89 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Config } from './configFile';
|
|
2
|
+
import { FileDiffResult } from './fileDiff';
|
|
3
|
+
import { ValidationResult } from './stopRulesValidator';
|
|
4
|
+
declare const JsonReporterErrorClass: {
|
|
5
|
+
new (message: string, options?: import("./utils/errors").ErrorOptions): {
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
readonly code?: string;
|
|
8
|
+
readonly path?: string;
|
|
9
|
+
readonly cause?: Error;
|
|
10
|
+
name: string;
|
|
11
|
+
message: string;
|
|
12
|
+
stack?: string;
|
|
13
|
+
};
|
|
14
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
15
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
16
|
+
stackTraceLimit: number;
|
|
17
|
+
};
|
|
18
|
+
export declare class JsonReporterError extends JsonReporterErrorClass {
|
|
19
|
+
}
|
|
20
|
+
export declare const isJsonReporterError: (error: unknown) => error is JsonReporterError;
|
|
21
|
+
export interface JsonReportMetadata {
|
|
22
|
+
timestamp: string;
|
|
23
|
+
source: string;
|
|
24
|
+
destination: string;
|
|
25
|
+
dryRun: boolean;
|
|
26
|
+
version: string;
|
|
27
|
+
}
|
|
28
|
+
export interface JsonReportSummary {
|
|
29
|
+
added: number;
|
|
30
|
+
deleted: number;
|
|
31
|
+
changed: number;
|
|
32
|
+
formatted: number;
|
|
33
|
+
unchanged: number;
|
|
34
|
+
}
|
|
35
|
+
export interface FieldChange {
|
|
36
|
+
path: string;
|
|
37
|
+
oldValue: unknown;
|
|
38
|
+
updatedValue: unknown;
|
|
39
|
+
}
|
|
40
|
+
export interface ChangedFileDetail {
|
|
41
|
+
path: string;
|
|
42
|
+
diff: string;
|
|
43
|
+
changes: FieldChange[];
|
|
44
|
+
}
|
|
45
|
+
export interface JsonReportFiles {
|
|
46
|
+
added: string[];
|
|
47
|
+
deleted: string[];
|
|
48
|
+
changed: ChangedFileDetail[];
|
|
49
|
+
formatted: string[];
|
|
50
|
+
unchanged: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface StopRuleViolationJson {
|
|
53
|
+
file: string;
|
|
54
|
+
rule: {
|
|
55
|
+
type: string;
|
|
56
|
+
path: string;
|
|
57
|
+
};
|
|
58
|
+
path: string;
|
|
59
|
+
oldValue: unknown;
|
|
60
|
+
updatedValue: unknown;
|
|
61
|
+
message: string;
|
|
62
|
+
}
|
|
63
|
+
export interface JsonReport {
|
|
64
|
+
metadata: JsonReportMetadata;
|
|
65
|
+
summary: JsonReportSummary;
|
|
66
|
+
files: JsonReportFiles;
|
|
67
|
+
stopRuleViolations: StopRuleViolationJson[];
|
|
68
|
+
}
|
|
69
|
+
export declare const generateJsonReport: (diffResult: FileDiffResult, formattedFiles: string[], validationResult: ValidationResult, config: Config, dryRun: boolean, version: string) => void;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateJsonReport = exports.isJsonReporterError = exports.JsonReporterError = void 0;
|
|
4
|
+
const deepEqual_1 = require("./utils/deepEqual");
|
|
5
|
+
const diffGenerator_1 = require("./utils/diffGenerator");
|
|
6
|
+
const errors_1 = require("./utils/errors");
|
|
7
|
+
const JsonReporterErrorClass = (0, errors_1.createErrorClass)('JSON Reporter Error', {});
|
|
8
|
+
class JsonReporterError extends JsonReporterErrorClass {
|
|
9
|
+
}
|
|
10
|
+
exports.JsonReporterError = JsonReporterError;
|
|
11
|
+
exports.isJsonReporterError = (0, errors_1.createErrorTypeGuard)(JsonReporterError);
|
|
12
|
+
const isPrimitive = (value) => {
|
|
13
|
+
return value === undefined || value === null || typeof value !== 'object';
|
|
14
|
+
};
|
|
15
|
+
const isObject = (value) => {
|
|
16
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
17
|
+
};
|
|
18
|
+
const formatJsonPath = (path) => {
|
|
19
|
+
if (path.length === 0)
|
|
20
|
+
return '$';
|
|
21
|
+
return `$.${path.join('.')}`;
|
|
22
|
+
};
|
|
23
|
+
const detectDeepChanges = (oldData, updatedData, currentPath = []) => {
|
|
24
|
+
const changes = [];
|
|
25
|
+
if (isPrimitive(oldData) || isPrimitive(updatedData)) {
|
|
26
|
+
if (!(0, deepEqual_1.deepEqual)(oldData, updatedData))
|
|
27
|
+
changes.push({
|
|
28
|
+
path: formatJsonPath(currentPath),
|
|
29
|
+
oldValue: oldData,
|
|
30
|
+
updatedValue: updatedData
|
|
31
|
+
});
|
|
32
|
+
return changes;
|
|
33
|
+
}
|
|
34
|
+
if (Array.isArray(oldData) && Array.isArray(updatedData)) {
|
|
35
|
+
if (!(0, deepEqual_1.deepEqual)(oldData, updatedData))
|
|
36
|
+
changes.push({
|
|
37
|
+
path: formatJsonPath(currentPath),
|
|
38
|
+
oldValue: `Array with ${oldData.length} item(s)`,
|
|
39
|
+
updatedValue: `Array with ${updatedData.length} item(s)`
|
|
40
|
+
});
|
|
41
|
+
return changes;
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(oldData) !== Array.isArray(updatedData)) {
|
|
44
|
+
changes.push({
|
|
45
|
+
path: formatJsonPath(currentPath),
|
|
46
|
+
oldValue: Array.isArray(oldData) ? `Array with ${oldData.length} item(s)` : oldData,
|
|
47
|
+
updatedValue: Array.isArray(updatedData) ? `Array with ${updatedData.length} item(s)` : updatedData
|
|
48
|
+
});
|
|
49
|
+
return changes;
|
|
50
|
+
}
|
|
51
|
+
if (isObject(oldData) && isObject(updatedData)) {
|
|
52
|
+
const allKeys = new Set([...Object.keys(oldData), ...Object.keys(updatedData)]);
|
|
53
|
+
for (const key of allKeys) {
|
|
54
|
+
const oldValue = oldData[key];
|
|
55
|
+
const updatedValue = updatedData[key];
|
|
56
|
+
const subChanges = detectDeepChanges(oldValue, updatedValue, [...currentPath, key]);
|
|
57
|
+
changes.push(...subChanges);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return changes;
|
|
61
|
+
};
|
|
62
|
+
const generateChangedFileDetail = (file) => {
|
|
63
|
+
const diff = (0, diffGenerator_1.generateUnifiedDiff)(file.path, file.destinationContent, file.sourceContent);
|
|
64
|
+
const changes = detectDeepChanges(file.processedDestContent, file.processedSourceContent);
|
|
65
|
+
return {
|
|
66
|
+
path: file.path,
|
|
67
|
+
diff,
|
|
68
|
+
changes
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const generateJsonReport = (diffResult, formattedFiles, validationResult, config, dryRun, version) => {
|
|
72
|
+
try {
|
|
73
|
+
const metadata = {
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
source: config.source,
|
|
76
|
+
destination: config.destination,
|
|
77
|
+
dryRun,
|
|
78
|
+
version
|
|
79
|
+
};
|
|
80
|
+
const summary = {
|
|
81
|
+
added: diffResult.addedFiles.length,
|
|
82
|
+
deleted: diffResult.deletedFiles.length,
|
|
83
|
+
changed: diffResult.changedFiles.length,
|
|
84
|
+
formatted: formattedFiles.length,
|
|
85
|
+
unchanged: diffResult.unchangedFiles.length
|
|
86
|
+
};
|
|
87
|
+
const changedFileDetails = diffResult.changedFiles.map((file) => generateChangedFileDetail(file));
|
|
88
|
+
const files = {
|
|
89
|
+
added: diffResult.addedFiles,
|
|
90
|
+
deleted: diffResult.deletedFiles,
|
|
91
|
+
changed: changedFileDetails,
|
|
92
|
+
formatted: formattedFiles,
|
|
93
|
+
unchanged: diffResult.unchangedFiles
|
|
94
|
+
};
|
|
95
|
+
const stopRuleViolations = validationResult.violations.map((violation) => ({
|
|
96
|
+
file: violation.file,
|
|
97
|
+
rule: {
|
|
98
|
+
type: violation.rule.type,
|
|
99
|
+
path: violation.rule.path
|
|
100
|
+
},
|
|
101
|
+
path: violation.path,
|
|
102
|
+
oldValue: violation.oldValue,
|
|
103
|
+
updatedValue: violation.updatedValue,
|
|
104
|
+
message: violation.message
|
|
105
|
+
}));
|
|
106
|
+
const report = {
|
|
107
|
+
metadata,
|
|
108
|
+
summary,
|
|
109
|
+
files,
|
|
110
|
+
stopRuleViolations
|
|
111
|
+
};
|
|
112
|
+
console.log(JSON.stringify(report, undefined, 2));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error instanceof Error)
|
|
116
|
+
throw new JsonReporterError('Failed to generate JSON report', {
|
|
117
|
+
cause: error
|
|
118
|
+
});
|
|
119
|
+
throw new JsonReporterError('Failed to generate JSON report');
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
exports.generateJsonReport = generateJsonReport;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { StopRule } from './configFile';
|
|
2
|
+
import { FileDiffResult } from './fileDiff';
|
|
3
|
+
declare const StopRulesValidatorErrorClass: {
|
|
4
|
+
new (message: string, options?: import("./utils/errors").ErrorOptions): {
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
readonly code?: string;
|
|
7
|
+
readonly path?: string;
|
|
8
|
+
readonly cause?: Error;
|
|
9
|
+
name: string;
|
|
10
|
+
message: string;
|
|
11
|
+
stack?: string;
|
|
12
|
+
};
|
|
13
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
14
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
15
|
+
stackTraceLimit: number;
|
|
16
|
+
};
|
|
17
|
+
export declare class StopRulesValidatorError extends StopRulesValidatorErrorClass {
|
|
18
|
+
}
|
|
19
|
+
export declare const isStopRulesValidatorError: (error: unknown) => error is StopRulesValidatorError;
|
|
20
|
+
export interface StopRuleViolation {
|
|
21
|
+
file: string;
|
|
22
|
+
rule: StopRule;
|
|
23
|
+
path: string;
|
|
24
|
+
oldValue: unknown;
|
|
25
|
+
updatedValue: unknown;
|
|
26
|
+
message: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ValidationResult {
|
|
29
|
+
violations: StopRuleViolation[];
|
|
30
|
+
isValid: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare const validateStopRules: (diffResult: FileDiffResult, stopRulesConfig?: Record<string, StopRule[]>) => ValidationResult;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateStopRules = exports.isStopRulesValidatorError = exports.StopRulesValidatorError = void 0;
|
|
4
|
+
const picomatch_1 = require("picomatch");
|
|
5
|
+
const errors_1 = require("./utils/errors");
|
|
6
|
+
const jsonPath_1 = require("./utils/jsonPath");
|
|
7
|
+
const StopRulesValidatorErrorClass = (0, errors_1.createErrorClass)('Stop Rules Validator Error', {}, (message, options) => {
|
|
8
|
+
let fullMessage = `Stop Rules Validator Error: ${message}`;
|
|
9
|
+
if (options.code)
|
|
10
|
+
fullMessage += `\n Code: ${options.code}`;
|
|
11
|
+
if (options['violations'] && Array.isArray(options['violations']) && options['violations'].length > 0) {
|
|
12
|
+
fullMessage += `\n Violations (${options['violations'].length}):`;
|
|
13
|
+
for (const v of options['violations'])
|
|
14
|
+
fullMessage += `\n - ${v.file}:${v.path} (${v.rule.type})`;
|
|
15
|
+
}
|
|
16
|
+
if (options.cause)
|
|
17
|
+
fullMessage += `\n Cause: ${options.cause.message}`;
|
|
18
|
+
return fullMessage;
|
|
19
|
+
});
|
|
20
|
+
class StopRulesValidatorError extends StopRulesValidatorErrorClass {
|
|
21
|
+
}
|
|
22
|
+
exports.StopRulesValidatorError = StopRulesValidatorError;
|
|
23
|
+
exports.isStopRulesValidatorError = (0, errors_1.createErrorTypeGuard)(StopRulesValidatorError);
|
|
24
|
+
const validateStopRules = (diffResult, stopRulesConfig) => {
|
|
25
|
+
if (!stopRulesConfig)
|
|
26
|
+
return { violations: [], isValid: true };
|
|
27
|
+
const violations = [];
|
|
28
|
+
for (const changedFile of diffResult.changedFiles) {
|
|
29
|
+
const fileViolations = validateFileAgainstRules(changedFile, stopRulesConfig);
|
|
30
|
+
violations.push(...fileViolations);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
violations,
|
|
34
|
+
isValid: violations.length === 0
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
exports.validateStopRules = validateStopRules;
|
|
38
|
+
const validateFileAgainstRules = (changedFile, stopRulesConfig) => {
|
|
39
|
+
const violations = [];
|
|
40
|
+
const applicableRules = getApplicableRules(changedFile.path, stopRulesConfig);
|
|
41
|
+
if (applicableRules.length === 0)
|
|
42
|
+
return violations;
|
|
43
|
+
const oldData = changedFile.processedDestContent;
|
|
44
|
+
const updatedData = changedFile.processedSourceContent;
|
|
45
|
+
for (const rule of applicableRules) {
|
|
46
|
+
const violation = validateRule(rule, oldData, updatedData, changedFile.path);
|
|
47
|
+
if (violation)
|
|
48
|
+
violations.push(violation);
|
|
49
|
+
}
|
|
50
|
+
return violations;
|
|
51
|
+
};
|
|
52
|
+
const getApplicableRules = (filePath, stopRulesConfig) => {
|
|
53
|
+
const rules = [];
|
|
54
|
+
for (const [pattern, ruleList] of Object.entries(stopRulesConfig))
|
|
55
|
+
if ((0, picomatch_1.isMatch)(filePath, pattern))
|
|
56
|
+
rules.push(...ruleList);
|
|
57
|
+
return rules;
|
|
58
|
+
};
|
|
59
|
+
const validateRule = (rule, oldData, updatedData, filePath) => {
|
|
60
|
+
const pathParts = (0, jsonPath_1.parseJsonPath)(rule.path);
|
|
61
|
+
const oldValue = oldData ? (0, jsonPath_1.getValueAtPath)(oldData, pathParts) : undefined;
|
|
62
|
+
const updatedValue = updatedData ? (0, jsonPath_1.getValueAtPath)(updatedData, pathParts) : undefined;
|
|
63
|
+
if (oldValue === undefined && updatedValue === undefined)
|
|
64
|
+
return undefined;
|
|
65
|
+
switch (rule.type) {
|
|
66
|
+
case 'semverMajorUpgrade':
|
|
67
|
+
return validateSemverMajorUpgrade(rule, oldValue, updatedValue, filePath);
|
|
68
|
+
case 'semverDowngrade':
|
|
69
|
+
return validateSemverDowngrade(rule, oldValue, updatedValue, filePath);
|
|
70
|
+
case 'numeric':
|
|
71
|
+
return validateNumeric(rule, oldValue, updatedValue, filePath);
|
|
72
|
+
case 'regex':
|
|
73
|
+
return validateRegex(rule, oldValue, updatedValue, filePath);
|
|
74
|
+
default:
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const validateSemverMajorUpgrade = (rule, oldValue, updatedValue, filePath) => {
|
|
79
|
+
if (oldValue === undefined || updatedValue === undefined)
|
|
80
|
+
return undefined;
|
|
81
|
+
const oldVersion = String(oldValue);
|
|
82
|
+
const updatedVersion = String(updatedValue);
|
|
83
|
+
const oldMajor = parseMajorVersion(oldVersion);
|
|
84
|
+
const updatedMajor = parseMajorVersion(updatedVersion);
|
|
85
|
+
if (oldMajor === undefined || updatedMajor === undefined)
|
|
86
|
+
return undefined;
|
|
87
|
+
if (updatedMajor > oldMajor)
|
|
88
|
+
return {
|
|
89
|
+
file: filePath,
|
|
90
|
+
rule,
|
|
91
|
+
path: rule.path,
|
|
92
|
+
oldValue,
|
|
93
|
+
updatedValue,
|
|
94
|
+
message: `Major version upgrade detected: ${oldVersion} → ${updatedVersion}`
|
|
95
|
+
};
|
|
96
|
+
return undefined;
|
|
97
|
+
};
|
|
98
|
+
const validateSemverDowngrade = (rule, oldValue, updatedValue, filePath) => {
|
|
99
|
+
if (oldValue === undefined || updatedValue === undefined)
|
|
100
|
+
return undefined;
|
|
101
|
+
const oldVersion = String(oldValue);
|
|
102
|
+
const updatedVersion = String(updatedValue);
|
|
103
|
+
const oldMajor = parseMajorVersion(oldVersion);
|
|
104
|
+
const updatedMajor = parseMajorVersion(updatedVersion);
|
|
105
|
+
if (oldMajor === undefined || updatedMajor === undefined)
|
|
106
|
+
return undefined;
|
|
107
|
+
if (updatedMajor < oldMajor)
|
|
108
|
+
return {
|
|
109
|
+
file: filePath,
|
|
110
|
+
rule,
|
|
111
|
+
path: rule.path,
|
|
112
|
+
oldValue,
|
|
113
|
+
updatedValue,
|
|
114
|
+
message: `Major version downgrade detected: ${oldVersion} → ${updatedVersion}`
|
|
115
|
+
};
|
|
116
|
+
return undefined;
|
|
117
|
+
};
|
|
118
|
+
const validateNumeric = (rule, oldValue, updatedValue, filePath) => {
|
|
119
|
+
const valueToCheck = updatedValue === undefined ? oldValue : updatedValue;
|
|
120
|
+
if (valueToCheck === undefined)
|
|
121
|
+
return undefined;
|
|
122
|
+
const numberValue = Number(valueToCheck);
|
|
123
|
+
if (Number.isNaN(numberValue))
|
|
124
|
+
return undefined;
|
|
125
|
+
if (rule.min !== undefined && numberValue < rule.min)
|
|
126
|
+
return {
|
|
127
|
+
file: filePath,
|
|
128
|
+
rule,
|
|
129
|
+
path: rule.path,
|
|
130
|
+
oldValue,
|
|
131
|
+
updatedValue,
|
|
132
|
+
message: `Value ${numberValue} is below minimum ${rule.min}`
|
|
133
|
+
};
|
|
134
|
+
if (rule.max !== undefined && numberValue > rule.max)
|
|
135
|
+
return {
|
|
136
|
+
file: filePath,
|
|
137
|
+
rule,
|
|
138
|
+
path: rule.path,
|
|
139
|
+
oldValue,
|
|
140
|
+
updatedValue,
|
|
141
|
+
message: `Value ${numberValue} exceeds maximum ${rule.max}`
|
|
142
|
+
};
|
|
143
|
+
return undefined;
|
|
144
|
+
};
|
|
145
|
+
const validateRegex = (rule, oldValue, updatedValue, filePath) => {
|
|
146
|
+
const valueToCheck = updatedValue === undefined ? oldValue : updatedValue;
|
|
147
|
+
if (valueToCheck === undefined)
|
|
148
|
+
return undefined;
|
|
149
|
+
const stringValue = String(valueToCheck);
|
|
150
|
+
const pattern = new RegExp(rule.regex);
|
|
151
|
+
if (pattern.test(stringValue))
|
|
152
|
+
return {
|
|
153
|
+
file: filePath,
|
|
154
|
+
rule,
|
|
155
|
+
path: rule.path,
|
|
156
|
+
oldValue,
|
|
157
|
+
updatedValue,
|
|
158
|
+
message: `Value "${stringValue}" matches forbidden pattern ${rule.regex}`
|
|
159
|
+
};
|
|
160
|
+
return undefined;
|
|
161
|
+
};
|
|
162
|
+
const parseMajorVersion = (version) => {
|
|
163
|
+
const cleaned = version.startsWith('v') ? version.slice(1) : version;
|
|
164
|
+
const match = /^(\d+)/.exec(cleaned);
|
|
165
|
+
if (!match || !match[1])
|
|
166
|
+
return undefined;
|
|
167
|
+
return Number.parseInt(match[1], 10);
|
|
168
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deepEqual: (a: unknown, b: unknown) => boolean;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deepEqual = void 0;
|
|
4
|
+
const serialization_1 = require("./serialization");
|
|
5
|
+
const deepEqual = (a, b) => {
|
|
6
|
+
const normalizedA = (0, serialization_1.normalizeForComparison)(a);
|
|
7
|
+
const normalizedB = (0, serialization_1.normalizeForComparison)(b);
|
|
8
|
+
return deepEqualStructural(normalizedA, normalizedB);
|
|
9
|
+
};
|
|
10
|
+
exports.deepEqual = deepEqual;
|
|
11
|
+
const deepEqualStructural = (a, b) => {
|
|
12
|
+
if (a === b)
|
|
13
|
+
return true;
|
|
14
|
+
if (a === null || b === null)
|
|
15
|
+
return a === b;
|
|
16
|
+
if (a === undefined || b === undefined)
|
|
17
|
+
return a === b;
|
|
18
|
+
const typeA = typeof a;
|
|
19
|
+
const typeB = typeof b;
|
|
20
|
+
if (typeA !== typeB)
|
|
21
|
+
return false;
|
|
22
|
+
if (typeA === 'string' || typeA === 'number' || typeA === 'boolean')
|
|
23
|
+
return a === b;
|
|
24
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
25
|
+
if (a.length !== b.length)
|
|
26
|
+
return false;
|
|
27
|
+
for (let index = 0; index < a.length; index++)
|
|
28
|
+
if (!deepEqualStructural(a[index], b[index]))
|
|
29
|
+
return false;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (typeA === 'object' && typeB === 'object') {
|
|
33
|
+
const objectA = a;
|
|
34
|
+
const objectB = b;
|
|
35
|
+
const keysA = Object.keys(objectA).toSorted();
|
|
36
|
+
const keysB = Object.keys(objectB).toSorted();
|
|
37
|
+
if (keysA.length !== keysB.length)
|
|
38
|
+
return false;
|
|
39
|
+
for (const [index, key] of keysA.entries()) {
|
|
40
|
+
if (!key || key !== keysB[index])
|
|
41
|
+
return false;
|
|
42
|
+
if (!deepEqualStructural(objectA[key], objectB[key]))
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const generateUnifiedDiff: (filePath: string, destinationContent: string, sourceContent: string) => string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateUnifiedDiff = void 0;
|
|
4
|
+
const diff_1 = require("diff");
|
|
5
|
+
const generateUnifiedDiff = (filePath, destinationContent, sourceContent) => {
|
|
6
|
+
return (0, diff_1.createTwoFilesPatch)(filePath, filePath, destinationContent, sourceContent, 'Destination', 'Source');
|
|
7
|
+
};
|
|
8
|
+
exports.generateUnifiedDiff = generateUnifiedDiff;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ErrorOptions {
|
|
2
|
+
code?: string;
|
|
3
|
+
path?: string;
|
|
4
|
+
cause?: Error;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
type ErrorFormatter = (message: string, options: ErrorOptions) => string;
|
|
8
|
+
export declare const createErrorClass: (errorName: string, codeExplanations?: Record<string, string>, customFormatter?: ErrorFormatter) => {
|
|
9
|
+
new (message: string, options?: ErrorOptions): {
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
readonly code?: string;
|
|
12
|
+
readonly path?: string;
|
|
13
|
+
readonly cause?: Error;
|
|
14
|
+
name: string;
|
|
15
|
+
message: string;
|
|
16
|
+
stack?: string;
|
|
17
|
+
};
|
|
18
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
19
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
20
|
+
stackTraceLimit: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const createErrorTypeGuard: <T extends Error>(ErrorClass: new (...arguments_: any[]) => T) => (error: unknown) => error is T;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createErrorTypeGuard = exports.createErrorClass = void 0;
|
|
4
|
+
const createErrorClass = (errorName, codeExplanations = {}, customFormatter) => {
|
|
5
|
+
const formatMessage = (message, options) => {
|
|
6
|
+
if (customFormatter)
|
|
7
|
+
return customFormatter(message, options);
|
|
8
|
+
let fullMessage = `${errorName}: ${message}`;
|
|
9
|
+
if (options.path)
|
|
10
|
+
fullMessage += `\n Path: ${options.path}`;
|
|
11
|
+
if (options.code) {
|
|
12
|
+
const explanation = codeExplanations[options.code] || `Error (${options.code})`;
|
|
13
|
+
fullMessage += `\n Reason: ${explanation}`;
|
|
14
|
+
}
|
|
15
|
+
if (options.cause)
|
|
16
|
+
fullMessage += `\n Details: ${options.cause.message}`;
|
|
17
|
+
return fullMessage;
|
|
18
|
+
};
|
|
19
|
+
class CustomError extends Error {
|
|
20
|
+
code;
|
|
21
|
+
path;
|
|
22
|
+
cause;
|
|
23
|
+
constructor(message, options = {}) {
|
|
24
|
+
super(formatMessage(message, options));
|
|
25
|
+
this.name = 'CustomError';
|
|
26
|
+
Object.defineProperty(this, 'name', { value: errorName, enumerable: false });
|
|
27
|
+
this.code = options.code;
|
|
28
|
+
this.path = options.path;
|
|
29
|
+
this.cause = options.cause;
|
|
30
|
+
for (const [key, value] of Object.entries(options))
|
|
31
|
+
if (key !== 'code' && key !== 'path' && key !== 'cause')
|
|
32
|
+
this[key] = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return CustomError;
|
|
36
|
+
};
|
|
37
|
+
exports.createErrorClass = createErrorClass;
|
|
38
|
+
const createErrorTypeGuard = (ErrorClass) => (error) => error instanceof ErrorClass;
|
|
39
|
+
exports.createErrorTypeGuard = createErrorTypeGuard;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isYamlFile: (filePath: string) => boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isYamlFile = void 0;
|
|
4
|
+
const YAML_FILE_REGEX = /\.ya?ml$/i;
|
|
5
|
+
const isYamlFile = (filePath) => {
|
|
6
|
+
return YAML_FILE_REGEX.test(filePath);
|
|
7
|
+
};
|
|
8
|
+
exports.isYamlFile = isYamlFile;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { ErrorOptions } from './errors';
|
|
2
|
+
export { createErrorClass, createErrorTypeGuard } from './errors';
|
|
3
|
+
export { deepEqual } from './deepEqual';
|
|
4
|
+
export { normalizeForComparison, serializeForDiff } from './serialization';
|
|
5
|
+
export { getValueAtPath, parseJsonPath } from './jsonPath';
|
|
6
|
+
export { isYamlFile } from './fileType';
|
|
7
|
+
export { generateUnifiedDiff } from './diffGenerator';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateUnifiedDiff = exports.isYamlFile = exports.parseJsonPath = exports.getValueAtPath = exports.serializeForDiff = exports.normalizeForComparison = exports.deepEqual = exports.createErrorTypeGuard = exports.createErrorClass = void 0;
|
|
4
|
+
var errors_1 = require("./errors");
|
|
5
|
+
Object.defineProperty(exports, "createErrorClass", { enumerable: true, get: function () { return errors_1.createErrorClass; } });
|
|
6
|
+
Object.defineProperty(exports, "createErrorTypeGuard", { enumerable: true, get: function () { return errors_1.createErrorTypeGuard; } });
|
|
7
|
+
var deepEqual_1 = require("./deepEqual");
|
|
8
|
+
Object.defineProperty(exports, "deepEqual", { enumerable: true, get: function () { return deepEqual_1.deepEqual; } });
|
|
9
|
+
var serialization_1 = require("./serialization");
|
|
10
|
+
Object.defineProperty(exports, "normalizeForComparison", { enumerable: true, get: function () { return serialization_1.normalizeForComparison; } });
|
|
11
|
+
Object.defineProperty(exports, "serializeForDiff", { enumerable: true, get: function () { return serialization_1.serializeForDiff; } });
|
|
12
|
+
var jsonPath_1 = require("./jsonPath");
|
|
13
|
+
Object.defineProperty(exports, "getValueAtPath", { enumerable: true, get: function () { return jsonPath_1.getValueAtPath; } });
|
|
14
|
+
Object.defineProperty(exports, "parseJsonPath", { enumerable: true, get: function () { return jsonPath_1.parseJsonPath; } });
|
|
15
|
+
var fileType_1 = require("./fileType");
|
|
16
|
+
Object.defineProperty(exports, "isYamlFile", { enumerable: true, get: function () { return fileType_1.isYamlFile; } });
|
|
17
|
+
var diffGenerator_1 = require("./diffGenerator");
|
|
18
|
+
Object.defineProperty(exports, "generateUnifiedDiff", { enumerable: true, get: function () { return diffGenerator_1.generateUnifiedDiff; } });
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getValueAtPath = exports.parseJsonPath = void 0;
|
|
4
|
+
const parseJsonPath = (path) => {
|
|
5
|
+
return path
|
|
6
|
+
.replaceAll(/\[(\*|\d+)]/g, '.$1')
|
|
7
|
+
.split('.')
|
|
8
|
+
.filter((part) => part.length > 0);
|
|
9
|
+
};
|
|
10
|
+
exports.parseJsonPath = parseJsonPath;
|
|
11
|
+
const getValueAtPath = (object, path) => {
|
|
12
|
+
let current = object;
|
|
13
|
+
for (const part of path) {
|
|
14
|
+
if (!current || typeof current !== 'object')
|
|
15
|
+
return undefined;
|
|
16
|
+
if (Array.isArray(current)) {
|
|
17
|
+
if (part === '*')
|
|
18
|
+
return undefined;
|
|
19
|
+
const index = Number(part);
|
|
20
|
+
if (Number.isNaN(index))
|
|
21
|
+
return undefined;
|
|
22
|
+
current = current[index];
|
|
23
|
+
}
|
|
24
|
+
else
|
|
25
|
+
current = current[part];
|
|
26
|
+
}
|
|
27
|
+
return current;
|
|
28
|
+
};
|
|
29
|
+
exports.getValueAtPath = getValueAtPath;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeForComparison = exports.serializeForDiff = void 0;
|
|
7
|
+
const yaml_1 = __importDefault(require("yaml"));
|
|
8
|
+
const serializeForDiff = (content, isYaml) => {
|
|
9
|
+
if (!isYaml)
|
|
10
|
+
return String(content);
|
|
11
|
+
return yaml_1.default.stringify(content, {
|
|
12
|
+
indent: 2,
|
|
13
|
+
lineWidth: 0,
|
|
14
|
+
sortMapEntries: true
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
exports.serializeForDiff = serializeForDiff;
|
|
18
|
+
const normalizeForComparison = (value) => {
|
|
19
|
+
if (value === null || value === undefined)
|
|
20
|
+
return value;
|
|
21
|
+
const valueType = typeof value;
|
|
22
|
+
if (valueType === 'string' || valueType === 'number' || valueType === 'boolean')
|
|
23
|
+
return value;
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
const normalized = value.map((item) => (0, exports.normalizeForComparison)(item));
|
|
26
|
+
return normalized.toSorted((a, b) => {
|
|
27
|
+
const stringA = yaml_1.default.stringify(a, { sortMapEntries: true });
|
|
28
|
+
const stringB = yaml_1.default.stringify(b, { sortMapEntries: true });
|
|
29
|
+
return stringA.localeCompare(stringB);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (typeof value === 'object') {
|
|
33
|
+
const normalized = {};
|
|
34
|
+
for (const [key, value_] of Object.entries(value))
|
|
35
|
+
normalized[key] = (0, exports.normalizeForComparison)(value_);
|
|
36
|
+
return normalized;
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
40
|
+
exports.normalizeForComparison = normalizeForComparison;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { TransformRule } from '../configFile';
|
|
2
|
+
declare const TransformerErrorClass: {
|
|
3
|
+
new (message: string, options?: import("./errors").ErrorOptions): {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
readonly code?: string;
|
|
6
|
+
readonly path?: string;
|
|
7
|
+
readonly cause?: Error;
|
|
8
|
+
name: string;
|
|
9
|
+
message: string;
|
|
10
|
+
stack?: string;
|
|
11
|
+
};
|
|
12
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function): void;
|
|
13
|
+
prepareStackTrace(err: Error, stackTraces: NodeJS.CallSite[]): any;
|
|
14
|
+
stackTraceLimit: number;
|
|
15
|
+
};
|
|
16
|
+
export declare class TransformerError extends TransformerErrorClass {
|
|
17
|
+
}
|
|
18
|
+
export declare const isTransformerError: (error: unknown) => error is TransformerError;
|
|
19
|
+
export declare const getTransformsForFile: (filePath: string, transforms?: Record<string, TransformRule[]>) => TransformRule[];
|
|
20
|
+
export declare const applyTransforms: (data: unknown, filePath: string, transforms?: Record<string, TransformRule[]>) => unknown;
|
|
21
|
+
export {};
|