helm-env-delta 1.12.0 → 1.13.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 CHANGED
@@ -413,10 +413,13 @@ exclude: # Optional: Exclude patterns
413
413
 
414
414
  prune: false # Optional: Delete dest files not in source
415
415
  confirmationDelay: 3000 # Optional: Delay in ms before sync (default: 3000, 0 to disable)
416
+ requiredVersion: '1.10.0' # Optional: Minimum tool version required to process this config
416
417
  ```
417
418
 
418
419
  **Note:** Source and destination paths cannot resolve to the same folder.
419
420
 
421
+ **`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.
422
+
420
423
  ---
421
424
 
422
425
  ### 🔒 Path Filtering (skipPath)
@@ -777,7 +780,7 @@ stopRules: # Add production safety rules
777
780
 
778
781
  **Merging:**
779
782
 
780
- - Primitives (`source`, `destination`, `prune`, `confirmationDelay`): Child overrides parent
783
+ - Primitives (`source`, `destination`, `prune`, `confirmationDelay`, `requiredVersion`): Child overrides parent
781
784
  - Arrays (`include`, `exclude`): Concatenated (parent + child)
782
785
  - Per-file Records (`skipPath`, `transforms`, `stopRules`, `fixedValues`): Keys merged, arrays concatenated
783
786
  - `outputFormat`: Shallow merged (child fields override parent)
@@ -102,6 +102,7 @@ declare const transformRulesSchema: z.ZodObject<{
102
102
  }, z.core.$strip>;
103
103
  declare const baseConfigSchema: z.ZodObject<{
104
104
  extends: z.ZodOptional<z.ZodString>;
105
+ requiredVersion: z.ZodOptional<z.ZodString>;
105
106
  source: z.ZodOptional<z.ZodString>;
106
107
  destination: z.ZodOptional<z.ZodString>;
107
108
  include: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -188,6 +189,7 @@ declare const finalConfigSchema: z.ZodObject<{
188
189
  contentFile: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
189
190
  filenameFile: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
190
191
  }, z.core.$strip>>>;
192
+ requiredVersion: z.ZodOptional<z.ZodString>;
191
193
  source: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
192
194
  destination: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
193
195
  skipPath: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
@@ -262,6 +264,7 @@ declare const formatOnlyConfigSchema: z.ZodObject<{
262
264
  contentFile: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
263
265
  filenameFile: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
264
266
  }, z.core.$strip>>>;
267
+ requiredVersion: z.ZodOptional<z.ZodString>;
265
268
  source: z.ZodOptional<z.ZodString>;
266
269
  destination: z.ZodNonOptional<z.ZodOptional<z.ZodString>>;
267
270
  skipPath: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>>;
@@ -116,6 +116,13 @@ const transformRulesSchema = zod_1.z
116
116
  });
117
117
  const baseConfigSchema = zod_1.z.object({
118
118
  extends: zod_1.z.string().min(1).optional(),
119
+ requiredVersion: zod_1.z
120
+ .string()
121
+ .min(1)
122
+ .regex(/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/, {
123
+ message: 'Must be a valid semver version (e.g., "1.2.3" or "v1.2.3")'
124
+ })
125
+ .optional(),
119
126
  source: zod_1.z.string().min(1).optional(),
120
127
  destination: zod_1.z.string().min(1).optional(),
121
128
  include: zod_1.z.array(zod_1.z.string().min(1)).optional(),
@@ -1,6 +1,25 @@
1
1
  import { type FinalConfig, type FormatOnlyConfig } from './configFile';
2
+ declare const ConfigLoaderErrorClass: {
3
+ new (message: string, options?: import("./utils").ErrorOptions): {
4
+ [key: string]: unknown;
5
+ readonly code?: string;
6
+ readonly path?: string;
7
+ readonly cause?: Error;
8
+ readonly hints?: string[];
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 ConfigLoaderError extends ConfigLoaderErrorClass {
18
+ }
19
+ export declare const isConfigLoaderError: (error: unknown) => error is ConfigLoaderError;
2
20
  export type Config = FinalConfig;
3
21
  export type LoadConfigOptions = {
4
22
  formatOnly?: boolean;
5
23
  };
6
24
  export declare const loadConfigFile: (configPath: string, quiet?: boolean, logger?: import("./logger").Logger, options?: LoadConfigOptions) => FinalConfig | FormatOnlyConfig;
25
+ export {};
@@ -3,11 +3,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.loadConfigFile = void 0;
6
+ exports.loadConfigFile = exports.isConfigLoaderError = exports.ConfigLoaderError = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
+ const package_json_1 = __importDefault(require("../package.json"));
8
9
  const configFile_1 = require("./configFile");
9
10
  const configMerger_1 = require("./configMerger");
10
11
  const utils_1 = require("./utils");
12
+ const ConfigLoaderErrorClass = (0, utils_1.createErrorClass)('Config Loader Error', {
13
+ VERSION_REQUIREMENT: 'Installed version does not meet the required version'
14
+ }, (message, options) => {
15
+ let fullMessage = `Config Loader Error: ${message}`;
16
+ if (options['requiredVersion'])
17
+ fullMessage += `\n Required version: ${options['requiredVersion']}`;
18
+ if (options['currentVersion'])
19
+ fullMessage += `\n Current version: ${options['currentVersion']}`;
20
+ fullMessage += '\n\n Hint: Run "npm install" to update helm-env-delta to the required version.';
21
+ return fullMessage;
22
+ });
23
+ class ConfigLoaderError extends ConfigLoaderErrorClass {
24
+ }
25
+ exports.ConfigLoaderError = ConfigLoaderError;
26
+ exports.isConfigLoaderError = (0, utils_1.createErrorTypeGuard)(ConfigLoaderError);
27
+ const checkRequiredVersion = (requiredVersion) => {
28
+ const currentVersion = package_json_1.default.version;
29
+ if ((0, utils_1.isNewerVersion)(currentVersion, requiredVersion))
30
+ throw new ConfigLoaderError(`This config requires helm-env-delta v${requiredVersion} or newer`, {
31
+ code: 'VERSION_REQUIREMENT',
32
+ requiredVersion,
33
+ currentVersion
34
+ });
35
+ };
11
36
  const expandTransformFiles = (config, configDirectory) => {
12
37
  if (!config.transforms)
13
38
  return config;
@@ -34,6 +59,8 @@ const loadConfigFile = (configPath, quiet = false, logger, options = {}) => {
34
59
  const configDirectory = node_path_1.default.dirname(node_path_1.default.resolve(configPath));
35
60
  const mergedConfig = (0, configMerger_1.resolveConfigWithExtends)(configPath, new Set(), 0, logger);
36
61
  const expandedConfig = expandTransformFiles(mergedConfig, configDirectory);
62
+ if (expandedConfig.requiredVersion)
63
+ checkRequiredVersion(expandedConfig.requiredVersion);
37
64
  const config = options.formatOnly
38
65
  ? (0, configFile_1.parseFormatOnlyConfig)(expandedConfig, configPath)
39
66
  : (0, configFile_1.parseFinalConfig)(expandedConfig, configPath);
@@ -88,6 +88,10 @@ const mergeConfigs = (parent, child) => {
88
88
  merged.confirmationDelay = child.confirmationDelay;
89
89
  else if (parent.confirmationDelay !== undefined)
90
90
  merged.confirmationDelay = parent.confirmationDelay;
91
+ if (child.requiredVersion !== undefined)
92
+ merged.requiredVersion = child.requiredVersion;
93
+ else if (parent.requiredVersion !== undefined)
94
+ merged.requiredVersion = parent.requiredVersion;
91
95
  const parentInclude = parent.include ?? [];
92
96
  const childInclude = child.include ?? [];
93
97
  if (parentInclude.length > 0 || childInclude.length > 0)
package/dist/index.js CHANGED
@@ -337,6 +337,8 @@ const main = async () => {
337
337
  catch (error) {
338
338
  if ((0, configMerger_1.isConfigMergerError)(error))
339
339
  console.error(error.message);
340
+ else if ((0, configLoader_1.isConfigLoaderError)(error))
341
+ console.error(error.message);
340
342
  else if ((0, ZodError_1.isZodValidationError)(error))
341
343
  console.error(error.message);
342
344
  else if ((0, fileLoader_1.isFileLoaderError)(error))
@@ -7,7 +7,8 @@ export { clearJsonPathCache, getValueAtPath, isFilterSegment, matchesFilter, par
7
7
  export { isYamlFile } from './fileType';
8
8
  export { globalMatcher, PatternMatcher } from './patternMatcher';
9
9
  export { generateUnifiedDiff } from './diffGenerator';
10
- export { checkForUpdates, isVersionCheckerError, VersionCheckerError } from './versionChecker';
10
+ export type { SemverParts } from './versionChecker';
11
+ export { checkForUpdates, isNewerVersion, isVersionCheckerError, parseVersion, VersionCheckerError } from './versionChecker';
11
12
  export { escapeRegex, isYamlFileLoaderError, loadYamlFile, YamlFileLoaderError } from './yamlFileLoader';
12
13
  export { isTransformFileLoaderError, loadTransformFile, loadTransformFiles, TransformFileLoaderError } from './transformFileLoader';
13
14
  export { isRegexPatternFileLoaderError, loadRegexPatternArray, loadRegexPatternsFromKeys, RegexPatternFileLoaderError } from './regexPatternFileLoader';
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NUMERIC_MIN_MULTIPLIER = exports.NUMERIC_MIN_FLOOR = exports.MAX_EXAMPLES_PER_SUGGESTION = exports.ISO_TIMESTAMP_PATTERN = exports.FILTER_THRESHOLDS = exports.CONSTRAINT_FIELD_NAMES = exports.CONFIDENCE_DEFAULTS = exports.ARRAY_KEY_FIELDS = exports.ANTONYM_PAIRS = exports.isYamlSeq = exports.isYamlMap = exports.isYamlCollection = exports.isScalar = exports.extractScalarValue = exports.extractKeyValue = exports.validateVersionString = exports.applyRegexRulesSequentially = exports.validateTargetedRegex = exports.validatePathlessRegex = exports.getAllValuesRecursive = exports.RegexPatternFileLoaderError = exports.loadRegexPatternsFromKeys = exports.loadRegexPatternArray = exports.isRegexPatternFileLoaderError = exports.TransformFileLoaderError = exports.loadTransformFiles = exports.loadTransformFile = exports.isTransformFileLoaderError = exports.YamlFileLoaderError = exports.loadYamlFile = exports.isYamlFileLoaderError = exports.escapeRegex = exports.VersionCheckerError = exports.isVersionCheckerError = exports.checkForUpdates = exports.generateUnifiedDiff = exports.PatternMatcher = exports.globalMatcher = exports.isYamlFile = exports.parseJsonPath = exports.parseFilterSegment = exports.matchesFilter = exports.isFilterSegment = exports.getValueAtPath = exports.clearJsonPathCache = exports.serializeForDiff = exports.normalizeForComparison = exports.deepEqual = exports.createErrorTypeGuard = exports.createErrorClass = void 0;
4
- exports.parseFilterExpression = exports.isFilterParseError = exports.FilterParseError = exports.filterFileMaps = exports.filterFileMap = exports.fileMatchesFilter = exports.isCommentOnlyContent = exports.shouldPreserveItem = exports.itemMatchesAnyFilter = exports.getApplicableArrayFilters = exports.findMatchingTargetItem = exports.setValueAtPath = exports.getFixedValuesForFile = exports.applyFixedValues = exports.UUID_PATTERN = exports.SEMVER_PATTERN = exports.SEMANTIC_PATTERNS = exports.SEMANTIC_KEYWORDS = exports.PROBLEMATIC_REGEX_CHARS = void 0;
3
+ exports.MAX_EXAMPLES_PER_SUGGESTION = exports.ISO_TIMESTAMP_PATTERN = exports.FILTER_THRESHOLDS = exports.CONSTRAINT_FIELD_NAMES = exports.CONFIDENCE_DEFAULTS = exports.ARRAY_KEY_FIELDS = exports.ANTONYM_PAIRS = exports.isYamlSeq = exports.isYamlMap = exports.isYamlCollection = exports.isScalar = exports.extractScalarValue = exports.extractKeyValue = exports.validateVersionString = exports.applyRegexRulesSequentially = exports.validateTargetedRegex = exports.validatePathlessRegex = exports.getAllValuesRecursive = exports.RegexPatternFileLoaderError = exports.loadRegexPatternsFromKeys = exports.loadRegexPatternArray = exports.isRegexPatternFileLoaderError = exports.TransformFileLoaderError = exports.loadTransformFiles = exports.loadTransformFile = exports.isTransformFileLoaderError = exports.YamlFileLoaderError = exports.loadYamlFile = exports.isYamlFileLoaderError = exports.escapeRegex = exports.VersionCheckerError = exports.parseVersion = exports.isVersionCheckerError = exports.isNewerVersion = exports.checkForUpdates = exports.generateUnifiedDiff = exports.PatternMatcher = exports.globalMatcher = exports.isYamlFile = exports.parseJsonPath = exports.parseFilterSegment = exports.matchesFilter = exports.isFilterSegment = exports.getValueAtPath = exports.clearJsonPathCache = exports.serializeForDiff = exports.normalizeForComparison = exports.deepEqual = exports.createErrorTypeGuard = exports.createErrorClass = void 0;
4
+ exports.parseFilterExpression = exports.isFilterParseError = exports.FilterParseError = exports.filterFileMaps = exports.filterFileMap = exports.fileMatchesFilter = exports.isCommentOnlyContent = exports.shouldPreserveItem = exports.itemMatchesAnyFilter = exports.getApplicableArrayFilters = exports.findMatchingTargetItem = exports.setValueAtPath = exports.getFixedValuesForFile = exports.applyFixedValues = exports.UUID_PATTERN = exports.SEMVER_PATTERN = exports.SEMANTIC_PATTERNS = exports.SEMANTIC_KEYWORDS = exports.PROBLEMATIC_REGEX_CHARS = exports.NUMERIC_MIN_MULTIPLIER = exports.NUMERIC_MIN_FLOOR = void 0;
5
5
  var errors_1 = require("./errors");
6
6
  Object.defineProperty(exports, "createErrorClass", { enumerable: true, get: function () { return errors_1.createErrorClass; } });
7
7
  Object.defineProperty(exports, "createErrorTypeGuard", { enumerable: true, get: function () { return errors_1.createErrorTypeGuard; } });
@@ -26,7 +26,9 @@ var diffGenerator_1 = require("./diffGenerator");
26
26
  Object.defineProperty(exports, "generateUnifiedDiff", { enumerable: true, get: function () { return diffGenerator_1.generateUnifiedDiff; } });
27
27
  var versionChecker_1 = require("./versionChecker");
28
28
  Object.defineProperty(exports, "checkForUpdates", { enumerable: true, get: function () { return versionChecker_1.checkForUpdates; } });
29
+ Object.defineProperty(exports, "isNewerVersion", { enumerable: true, get: function () { return versionChecker_1.isNewerVersion; } });
29
30
  Object.defineProperty(exports, "isVersionCheckerError", { enumerable: true, get: function () { return versionChecker_1.isVersionCheckerError; } });
31
+ Object.defineProperty(exports, "parseVersion", { enumerable: true, get: function () { return versionChecker_1.parseVersion; } });
30
32
  Object.defineProperty(exports, "VersionCheckerError", { enumerable: true, get: function () { return versionChecker_1.VersionCheckerError; } });
31
33
  var yamlFileLoader_1 = require("./yamlFileLoader");
32
34
  Object.defineProperty(exports, "escapeRegex", { enumerable: true, get: function () { return yamlFileLoader_1.escapeRegex; } });
@@ -16,5 +16,12 @@ declare const VersionCheckerErrorClass: {
16
16
  export declare class VersionCheckerError extends VersionCheckerErrorClass {
17
17
  }
18
18
  export declare const isVersionCheckerError: (error: unknown) => error is VersionCheckerError;
19
+ export interface SemverParts {
20
+ major: number;
21
+ minor: number;
22
+ patch: number;
23
+ }
24
+ export declare const parseVersion: (version: string) => SemverParts | undefined;
25
+ export declare const isNewerVersion: (current: string, latest: string) => boolean;
19
26
  export declare const checkForUpdates: (currentVersion: string) => Promise<void>;
20
27
  export {};
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.checkForUpdates = exports.isVersionCheckerError = exports.VersionCheckerError = void 0;
6
+ exports.checkForUpdates = exports.isNewerVersion = exports.parseVersion = exports.isVersionCheckerError = exports.VersionCheckerError = void 0;
7
7
  const node_https_1 = __importDefault(require("node:https"));
8
8
  const chalk_1 = __importDefault(require("chalk"));
9
9
  const package_json_1 = __importDefault(require("../../package.json"));
@@ -44,9 +44,10 @@ const parseVersion = (version) => {
44
44
  patch: Number.parseInt(match[3], 10)
45
45
  };
46
46
  };
47
+ exports.parseVersion = parseVersion;
47
48
  const isNewerVersion = (current, latest) => {
48
- const currentParts = parseVersion(current);
49
- const latestParts = parseVersion(latest);
49
+ const currentParts = (0, exports.parseVersion)(current);
50
+ const latestParts = (0, exports.parseVersion)(latest);
50
51
  if (!currentParts || !latestParts)
51
52
  return false;
52
53
  if (latestParts.major > currentParts.major)
@@ -59,6 +60,7 @@ const isNewerVersion = (current, latest) => {
59
60
  return false;
60
61
  return latestParts.patch > currentParts.patch;
61
62
  };
63
+ exports.isNewerVersion = isNewerVersion;
62
64
  const fetchLatestVersion = (packageName, timeout) => {
63
65
  return new Promise((resolve, reject) => {
64
66
  const url = `https://registry.npmjs.org/${packageName}/latest`;
@@ -108,7 +110,7 @@ const checkForUpdates = async (currentVersion) => {
108
110
  return;
109
111
  try {
110
112
  const latestVersion = await fetchLatestVersion('helm-env-delta', 3000);
111
- if (isNewerVersion(currentVersion, latestVersion))
113
+ if ((0, exports.isNewerVersion)(currentVersion, latestVersion))
112
114
  displayUpdateNotification(currentVersion, latestVersion);
113
115
  }
114
116
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helm-env-delta",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "HelmEnvDelta – environment-aware YAML delta and sync for GitOps",
5
5
  "author": "BCsabaEngine",
6
6
  "license": "ISC",