@theunwalked/cardigantime 0.0.7 → 0.0.9

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.
@@ -2,6 +2,62 @@ import path__default from 'path';
2
2
  import * as yaml from 'js-yaml';
3
3
  import { create } from './storage.js';
4
4
 
5
+ /**
6
+ * Resolves relative paths in configuration values relative to the configuration file's directory.
7
+ */ function resolveConfigPaths(config, configDir, pathFields = [], resolvePathArray = []) {
8
+ if (!config || typeof config !== 'object' || pathFields.length === 0) {
9
+ return config;
10
+ }
11
+ const resolvedConfig = {
12
+ ...config
13
+ };
14
+ for (const fieldPath of pathFields){
15
+ const value = getNestedValue(resolvedConfig, fieldPath);
16
+ if (value !== undefined) {
17
+ const shouldResolveArrayElements = resolvePathArray.includes(fieldPath);
18
+ const resolvedValue = resolvePathValue(value, configDir, shouldResolveArrayElements);
19
+ setNestedValue(resolvedConfig, fieldPath, resolvedValue);
20
+ }
21
+ }
22
+ return resolvedConfig;
23
+ }
24
+ /**
25
+ * Gets a nested value from an object using dot notation.
26
+ */ function getNestedValue(obj, path) {
27
+ return path.split('.').reduce((current, key)=>current === null || current === void 0 ? void 0 : current[key], obj);
28
+ }
29
+ /**
30
+ * Sets a nested value in an object using dot notation.
31
+ */ function setNestedValue(obj, path, value) {
32
+ const keys = path.split('.');
33
+ const lastKey = keys.pop();
34
+ const target = keys.reduce((current, key)=>{
35
+ if (!(key in current)) {
36
+ current[key] = {};
37
+ }
38
+ return current[key];
39
+ }, obj);
40
+ target[lastKey] = value;
41
+ }
42
+ /**
43
+ * Resolves a path value (string or array of strings) relative to the config directory.
44
+ */ function resolvePathValue(value, configDir, resolveArrayElements) {
45
+ if (typeof value === 'string') {
46
+ return resolveSinglePath(value, configDir);
47
+ }
48
+ if (Array.isArray(value) && resolveArrayElements) {
49
+ return value.map((item)=>typeof item === 'string' ? resolveSinglePath(item, configDir) : item);
50
+ }
51
+ return value;
52
+ }
53
+ /**
54
+ * Resolves a single path string relative to the config directory if it's a relative path.
55
+ */ function resolveSinglePath(pathStr, configDir) {
56
+ if (!pathStr || path__default.isAbsolute(pathStr)) {
57
+ return pathStr;
58
+ }
59
+ return path__default.resolve(configDir, pathStr);
60
+ }
5
61
  /**
6
62
  * Discovers configuration directories by traversing up the directory tree.
7
63
  *
@@ -80,8 +136,10 @@ import { create } from './storage.js';
80
136
  * @param configFileName Name of the configuration file
81
137
  * @param encoding File encoding
82
138
  * @param logger Optional logger
139
+ * @param pathFields Optional array of field names that contain paths to be resolved
140
+ * @param resolvePathArray Optional array of field names whose array elements should all be resolved as paths
83
141
  * @returns Promise resolving to parsed configuration object or null if not found
84
- */ async function loadConfigFromDirectory(configDir, configFileName, encoding = 'utf8', logger) {
142
+ */ async function loadConfigFromDirectory(configDir, configFileName, encoding = 'utf8', logger, pathFields, resolvePathArray) {
85
143
  const storage = create({
86
144
  log: (logger === null || logger === void 0 ? void 0 : logger.debug) || (()=>{})
87
145
  });
@@ -101,8 +159,13 @@ import { create } from './storage.js';
101
159
  const yamlContent = await storage.readFile(configFilePath, encoding);
102
160
  const parsedYaml = yaml.load(yamlContent);
103
161
  if (parsedYaml !== null && typeof parsedYaml === 'object') {
162
+ let config = parsedYaml;
163
+ // Apply path resolution if configured
164
+ if (pathFields && pathFields.length > 0) {
165
+ config = resolveConfigPaths(config, configDir, pathFields, resolvePathArray || []);
166
+ }
104
167
  logger === null || logger === void 0 ? void 0 : logger.verbose(`Successfully loaded config from: ${configFilePath}`);
105
- return parsedYaml;
168
+ return config;
106
169
  } else {
107
170
  logger === null || logger === void 0 ? void 0 : logger.debug(`Config file contains invalid format: ${configFilePath}`);
108
171
  return null;
@@ -113,24 +176,26 @@ import { create } from './storage.js';
113
176
  }
114
177
  }
115
178
  /**
116
- * Deep merges multiple configuration objects with proper precedence.
179
+ * Deep merges multiple configuration objects with proper precedence and configurable array overlap behavior.
117
180
  *
118
181
  * Objects are merged from lowest precedence to highest precedence,
119
182
  * meaning that properties in later objects override properties in earlier objects.
120
- * Arrays are replaced entirely (not merged).
183
+ * Arrays can be merged using different strategies based on the fieldOverlaps configuration.
121
184
  *
122
185
  * @param configs Array of configuration objects, ordered from lowest to highest precedence
186
+ * @param fieldOverlaps Configuration for how array fields should be merged (optional)
123
187
  * @returns Merged configuration object
124
188
  *
125
189
  * @example
126
190
  * ```typescript
127
191
  * const merged = deepMergeConfigs([
128
- * { api: { timeout: 5000 }, debug: true }, // Lower precedence
129
- * { api: { retries: 3 }, features: ['auth'] }, // Higher precedence
130
- * ]);
131
- * // Result: { api: { timeout: 5000, retries: 3 }, debug: true, features: ['auth'] }
192
+ * { api: { timeout: 5000 }, features: ['auth'] }, // Lower precedence
193
+ * { api: { retries: 3 }, features: ['analytics'] }, // Higher precedence
194
+ * ], {
195
+ * 'features': 'append' // Results in features: ['auth', 'analytics']
196
+ * });
132
197
  * ```
133
- */ function deepMergeConfigs(configs) {
198
+ */ function deepMergeConfigs(configs, fieldOverlaps) {
134
199
  if (configs.length === 0) {
135
200
  return {};
136
201
  }
@@ -140,16 +205,18 @@ import { create } from './storage.js';
140
205
  };
141
206
  }
142
207
  return configs.reduce((merged, current)=>{
143
- return deepMergeTwo(merged, current);
208
+ return deepMergeTwo(merged, current, fieldOverlaps);
144
209
  }, {});
145
210
  }
146
211
  /**
147
- * Deep merges two objects with proper precedence.
212
+ * Deep merges two objects with proper precedence and configurable array overlap behavior.
148
213
  *
149
214
  * @param target Target object (lower precedence)
150
215
  * @param source Source object (higher precedence)
216
+ * @param fieldOverlaps Configuration for how array fields should be merged (optional)
217
+ * @param currentPath Current field path for nested merging (used internally)
151
218
  * @returns Merged object
152
- */ function deepMergeTwo(target, source) {
219
+ */ function deepMergeTwo(target, source, fieldOverlaps, currentPath = '') {
153
220
  // Handle null/undefined
154
221
  if (source == null) return target;
155
222
  if (target == null) return source;
@@ -157,11 +224,17 @@ import { create } from './storage.js';
157
224
  if (typeof source !== 'object' || typeof target !== 'object') {
158
225
  return source; // Source takes precedence
159
226
  }
160
- // Handle arrays - replace entirely, don't merge
227
+ // Handle arrays with configurable overlap behavior
161
228
  if (Array.isArray(source)) {
162
- return [
163
- ...source
164
- ];
229
+ if (Array.isArray(target) && fieldOverlaps) {
230
+ const overlapMode = getOverlapModeForPath(currentPath, fieldOverlaps);
231
+ return mergeArrays(target, source, overlapMode);
232
+ } else {
233
+ // Default behavior: replace entirely
234
+ return [
235
+ ...source
236
+ ];
237
+ }
165
238
  }
166
239
  if (Array.isArray(target)) {
167
240
  return source; // Source object replaces target array
@@ -172,17 +245,72 @@ import { create } from './storage.js';
172
245
  };
173
246
  for(const key in source){
174
247
  if (Object.prototype.hasOwnProperty.call(source, key)) {
248
+ const fieldPath = currentPath ? `${currentPath}.${key}` : key;
175
249
  if (Object.prototype.hasOwnProperty.call(result, key) && typeof result[key] === 'object' && typeof source[key] === 'object' && !Array.isArray(source[key]) && !Array.isArray(result[key])) {
176
250
  // Recursively merge nested objects
177
- result[key] = deepMergeTwo(result[key], source[key]);
251
+ result[key] = deepMergeTwo(result[key], source[key], fieldOverlaps, fieldPath);
178
252
  } else {
179
- // Replace with source value (higher precedence)
180
- result[key] = source[key];
253
+ // Handle arrays and primitives with overlap consideration
254
+ if (Array.isArray(source[key]) && Array.isArray(result[key]) && fieldOverlaps) {
255
+ const overlapMode = getOverlapModeForPath(fieldPath, fieldOverlaps);
256
+ result[key] = mergeArrays(result[key], source[key], overlapMode);
257
+ } else {
258
+ // Replace with source value (higher precedence)
259
+ result[key] = source[key];
260
+ }
181
261
  }
182
262
  }
183
263
  }
184
264
  return result;
185
265
  }
266
+ /**
267
+ * Determines the overlap mode for a given field path.
268
+ *
269
+ * @param fieldPath The current field path (dot notation)
270
+ * @param fieldOverlaps Configuration mapping field paths to overlap modes
271
+ * @returns The overlap mode to use for this field path
272
+ */ function getOverlapModeForPath(fieldPath, fieldOverlaps) {
273
+ // Check for exact match first
274
+ if (fieldPath in fieldOverlaps) {
275
+ return fieldOverlaps[fieldPath];
276
+ }
277
+ // Check for any parent path matches (for nested configurations)
278
+ const pathParts = fieldPath.split('.');
279
+ for(let i = pathParts.length - 1; i > 0; i--){
280
+ const parentPath = pathParts.slice(0, i).join('.');
281
+ if (parentPath in fieldOverlaps) {
282
+ return fieldOverlaps[parentPath];
283
+ }
284
+ }
285
+ // Default to override if no specific configuration found
286
+ return 'override';
287
+ }
288
+ /**
289
+ * Merges two arrays based on the specified overlap mode.
290
+ *
291
+ * @param targetArray The lower precedence array
292
+ * @param sourceArray The higher precedence array
293
+ * @param mode The overlap mode to use
294
+ * @returns The merged array
295
+ */ function mergeArrays(targetArray, sourceArray, mode) {
296
+ switch(mode){
297
+ case 'append':
298
+ return [
299
+ ...targetArray,
300
+ ...sourceArray
301
+ ];
302
+ case 'prepend':
303
+ return [
304
+ ...sourceArray,
305
+ ...targetArray
306
+ ];
307
+ case 'override':
308
+ default:
309
+ return [
310
+ ...sourceArray
311
+ ];
312
+ }
313
+ }
186
314
  /**
187
315
  * Loads configurations from multiple directories and merges them with proper precedence.
188
316
  *
@@ -201,15 +329,19 @@ import { create } from './storage.js';
201
329
  * configDirName: '.kodrdriv',
202
330
  * configFileName: 'config.yaml',
203
331
  * startingDir: '/project/subdir',
204
- * maxLevels: 5
332
+ * maxLevels: 5,
333
+ * fieldOverlaps: {
334
+ * 'features': 'append',
335
+ * 'excludePatterns': 'prepend'
336
+ * }
205
337
  * });
206
338
  *
207
- * // result.config contains merged configuration
339
+ * // result.config contains merged configuration with custom array merging
208
340
  * // result.discoveredDirs shows where configs were found
209
341
  * // result.errors contains any non-fatal errors
210
342
  * ```
211
343
  */ async function loadHierarchicalConfig(options) {
212
- const { configFileName, encoding = 'utf8', logger } = options;
344
+ const { configFileName, encoding = 'utf8', logger, pathFields, resolvePathArray, fieldOverlaps } = options;
213
345
  logger === null || logger === void 0 ? void 0 : logger.verbose('Starting hierarchical configuration loading');
214
346
  // Discover all configuration directories
215
347
  const discoveredDirs = await discoverConfigDirectories(options);
@@ -230,7 +362,7 @@ import { create } from './storage.js';
230
362
  ].sort((a, b)=>b.level - a.level);
231
363
  for (const dir of sortedDirs){
232
364
  try {
233
- const config = await loadConfigFromDirectory(dir.path, configFileName, encoding, logger);
365
+ const config = await loadConfigFromDirectory(dir.path, configFileName, encoding, logger, pathFields, resolvePathArray);
234
366
  if (config !== null) {
235
367
  configs.push(config);
236
368
  logger === null || logger === void 0 ? void 0 : logger.debug(`Loaded config from level ${dir.level}: ${dir.path}`);
@@ -243,8 +375,8 @@ import { create } from './storage.js';
243
375
  logger === null || logger === void 0 ? void 0 : logger.debug(errorMsg);
244
376
  }
245
377
  }
246
- // Merge all configurations with proper precedence
247
- const mergedConfig = deepMergeConfigs(configs);
378
+ // Merge all configurations with proper precedence and configurable array overlap
379
+ const mergedConfig = deepMergeConfigs(configs, fieldOverlaps);
248
380
  logger === null || logger === void 0 ? void 0 : logger.verbose(`Hierarchical loading complete. Merged ${configs.length} configurations`);
249
381
  return {
250
382
  config: mergedConfig,
@@ -1 +1 @@
1
- {"version":3,"file":"hierarchical.js","sources":["../../src/util/hierarchical.ts"],"sourcesContent":["import path from 'path';\nimport * as yaml from 'js-yaml';\nimport { create as createStorage } from './storage';\nimport { Logger } from '../types';\n\n/**\n * Represents a discovered configuration directory with its path and precedence level.\n */\nexport interface DiscoveredConfigDir {\n /** Absolute path to the configuration directory */\n path: string;\n /** Distance from the starting directory (0 = closest/highest precedence) */\n level: number;\n}\n\n/**\n * Options for hierarchical configuration discovery.\n */\nexport interface HierarchicalDiscoveryOptions {\n /** Name of the configuration directory to look for (e.g., '.kodrdriv') */\n configDirName: string;\n /** Name of the configuration file within each directory */\n configFileName: string;\n /** Maximum number of parent directories to traverse (default: 10) */\n maxLevels?: number;\n /** Starting directory for discovery (default: process.cwd()) */\n startingDir?: string;\n /** File encoding for reading configuration files */\n encoding?: string;\n /** Logger for debugging */\n logger?: Logger;\n}\n\n/**\n * Result of loading configurations from multiple directories.\n */\nexport interface HierarchicalConfigResult {\n /** Merged configuration object with proper precedence */\n config: object;\n /** Array of directories where configuration was found */\n discoveredDirs: DiscoveredConfigDir[];\n /** Array of any errors encountered during loading (non-fatal) */\n errors: string[];\n}\n\n/**\n * Discovers configuration directories by traversing up the directory tree.\n * \n * Starting from the specified directory (or current working directory),\n * this function searches for directories with the given name, continuing\n * up the directory tree until it reaches the filesystem root or the\n * maximum number of levels.\n * \n * @param options Configuration options for discovery\n * @returns Promise resolving to array of discovered configuration directories\n * \n * @example\n * ```typescript\n * const dirs = await discoverConfigDirectories({\n * configDirName: '.kodrdriv',\n * configFileName: 'config.yaml',\n * maxLevels: 5\n * });\n * // Returns: [\n * // { path: '/project/.kodrdriv', level: 0 },\n * // { path: '/project/parent/.kodrdriv', level: 1 }\n * // ]\n * ```\n */\nexport async function discoverConfigDirectories(\n options: HierarchicalDiscoveryOptions\n): Promise<DiscoveredConfigDir[]> {\n const {\n configDirName,\n maxLevels = 10,\n startingDir = process.cwd(),\n logger\n } = options;\n\n const storage = createStorage({ log: logger?.debug || (() => { }) });\n const discoveredDirs: DiscoveredConfigDir[] = [];\n\n let currentDir = path.resolve(startingDir);\n let level = 0;\n const visited = new Set<string>(); // Prevent infinite loops with symlinks\n\n logger?.debug(`Starting hierarchical discovery from: ${currentDir}`);\n\n while (level < maxLevels) {\n // Prevent infinite loops with symlinks\n const realPath = path.resolve(currentDir);\n if (visited.has(realPath)) {\n logger?.debug(`Already visited ${realPath}, stopping discovery`);\n break;\n }\n visited.add(realPath);\n\n const configDirPath = path.join(currentDir, configDirName);\n logger?.debug(`Checking for config directory: ${configDirPath}`);\n\n try {\n const exists = await storage.exists(configDirPath);\n const isReadable = exists && await storage.isDirectoryReadable(configDirPath);\n\n if (exists && isReadable) {\n discoveredDirs.push({\n path: configDirPath,\n level\n });\n logger?.debug(`Found config directory at level ${level}: ${configDirPath}`);\n } else if (exists && !isReadable) {\n logger?.debug(`Config directory exists but is not readable: ${configDirPath}`);\n }\n } catch (error: any) {\n logger?.debug(`Error checking config directory ${configDirPath}: ${error.message}`);\n }\n\n // Move up one directory level\n const parentDir = path.dirname(currentDir);\n\n // Check if we've reached the root directory\n if (parentDir === currentDir) {\n logger?.debug('Reached filesystem root, stopping discovery');\n break;\n }\n\n currentDir = parentDir;\n level++;\n }\n\n logger?.verbose(`Discovery complete. Found ${discoveredDirs.length} config directories`);\n return discoveredDirs;\n}\n\n/**\n * Loads and parses a configuration file from a directory.\n * \n * @param configDir Path to the configuration directory\n * @param configFileName Name of the configuration file\n * @param encoding File encoding\n * @param logger Optional logger\n * @returns Promise resolving to parsed configuration object or null if not found\n */\nexport async function loadConfigFromDirectory(\n configDir: string,\n configFileName: string,\n encoding: string = 'utf8',\n logger?: Logger\n): Promise<object | null> {\n const storage = createStorage({ log: logger?.debug || (() => { }) });\n const configFilePath = path.join(configDir, configFileName);\n\n try {\n logger?.verbose(`Attempting to load config file: ${configFilePath}`);\n\n const exists = await storage.exists(configFilePath);\n if (!exists) {\n logger?.debug(`Config file does not exist: ${configFilePath}`);\n return null;\n }\n\n const isReadable = await storage.isFileReadable(configFilePath);\n if (!isReadable) {\n logger?.debug(`Config file exists but is not readable: ${configFilePath}`);\n return null;\n }\n\n const yamlContent = await storage.readFile(configFilePath, encoding);\n const parsedYaml = yaml.load(yamlContent);\n\n if (parsedYaml !== null && typeof parsedYaml === 'object') {\n logger?.verbose(`Successfully loaded config from: ${configFilePath}`);\n return parsedYaml as object;\n } else {\n logger?.debug(`Config file contains invalid format: ${configFilePath}`);\n return null;\n }\n } catch (error: any) {\n logger?.debug(`Error loading config from ${configFilePath}: ${error.message}`);\n return null;\n }\n}\n\n/**\n * Deep merges multiple configuration objects with proper precedence.\n * \n * Objects are merged from lowest precedence to highest precedence,\n * meaning that properties in later objects override properties in earlier objects.\n * Arrays are replaced entirely (not merged).\n * \n * @param configs Array of configuration objects, ordered from lowest to highest precedence\n * @returns Merged configuration object\n * \n * @example\n * ```typescript\n * const merged = deepMergeConfigs([\n * { api: { timeout: 5000 }, debug: true }, // Lower precedence\n * { api: { retries: 3 }, features: ['auth'] }, // Higher precedence\n * ]);\n * // Result: { api: { timeout: 5000, retries: 3 }, debug: true, features: ['auth'] }\n * ```\n */\nexport function deepMergeConfigs(configs: object[]): object {\n if (configs.length === 0) {\n return {};\n }\n\n if (configs.length === 1) {\n return { ...configs[0] };\n }\n\n return configs.reduce((merged, current) => {\n return deepMergeTwo(merged, current);\n }, {});\n}\n\n/**\n * Deep merges two objects with proper precedence.\n * \n * @param target Target object (lower precedence)\n * @param source Source object (higher precedence)\n * @returns Merged object\n */\nfunction deepMergeTwo(target: any, source: any): any {\n // Handle null/undefined\n if (source == null) return target;\n if (target == null) return source;\n\n // Handle non-objects (primitives, arrays, functions, etc.)\n if (typeof source !== 'object' || typeof target !== 'object') {\n return source; // Source takes precedence\n }\n\n // Handle arrays - replace entirely, don't merge\n if (Array.isArray(source)) {\n return [...source];\n }\n\n if (Array.isArray(target)) {\n return source; // Source object replaces target array\n }\n\n // Deep merge objects\n const result = { ...target };\n\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n if (Object.prototype.hasOwnProperty.call(result, key) &&\n typeof result[key] === 'object' &&\n typeof source[key] === 'object' &&\n !Array.isArray(source[key]) &&\n !Array.isArray(result[key])) {\n // Recursively merge nested objects\n result[key] = deepMergeTwo(result[key], source[key]);\n } else {\n // Replace with source value (higher precedence)\n result[key] = source[key];\n }\n }\n }\n\n return result;\n}\n\n/**\n * Loads configurations from multiple directories and merges them with proper precedence.\n * \n * This is the main function for hierarchical configuration loading. It:\n * 1. Discovers configuration directories up the directory tree\n * 2. Loads configuration files from each discovered directory\n * 3. Merges them with proper precedence (closer directories win)\n * 4. Returns the merged configuration with metadata\n * \n * @param options Configuration options for hierarchical loading\n * @returns Promise resolving to hierarchical configuration result\n * \n * @example\n * ```typescript\n * const result = await loadHierarchicalConfig({\n * configDirName: '.kodrdriv',\n * configFileName: 'config.yaml',\n * startingDir: '/project/subdir',\n * maxLevels: 5\n * });\n * \n * // result.config contains merged configuration\n * // result.discoveredDirs shows where configs were found\n * // result.errors contains any non-fatal errors\n * ```\n */\nexport async function loadHierarchicalConfig(\n options: HierarchicalDiscoveryOptions\n): Promise<HierarchicalConfigResult> {\n const { configFileName, encoding = 'utf8', logger } = options;\n\n logger?.verbose('Starting hierarchical configuration loading');\n\n // Discover all configuration directories\n const discoveredDirs = await discoverConfigDirectories(options);\n\n if (discoveredDirs.length === 0) {\n logger?.verbose('No configuration directories found');\n return {\n config: {},\n discoveredDirs: [],\n errors: []\n };\n }\n\n // Load configurations from each directory\n const configs: object[] = [];\n const errors: string[] = [];\n\n // Sort by level (highest level first = lowest precedence first)\n const sortedDirs = [...discoveredDirs].sort((a, b) => b.level - a.level);\n\n for (const dir of sortedDirs) {\n try {\n const config = await loadConfigFromDirectory(\n dir.path,\n configFileName,\n encoding,\n logger\n );\n\n if (config !== null) {\n configs.push(config);\n logger?.debug(`Loaded config from level ${dir.level}: ${dir.path}`);\n } else {\n logger?.debug(`No valid config found at level ${dir.level}: ${dir.path}`);\n }\n } catch (error: any) {\n const errorMsg = `Failed to load config from ${dir.path}: ${error.message}`;\n errors.push(errorMsg);\n logger?.debug(errorMsg);\n }\n }\n\n // Merge all configurations with proper precedence\n const mergedConfig = deepMergeConfigs(configs);\n\n logger?.verbose(`Hierarchical loading complete. Merged ${configs.length} configurations`);\n\n return {\n config: mergedConfig,\n discoveredDirs,\n errors\n };\n} "],"names":["discoverConfigDirectories","options","configDirName","maxLevels","startingDir","process","cwd","logger","storage","createStorage","log","debug","discoveredDirs","currentDir","path","resolve","level","visited","Set","realPath","has","add","configDirPath","join","exists","isReadable","isDirectoryReadable","push","error","message","parentDir","dirname","verbose","length","loadConfigFromDirectory","configDir","configFileName","encoding","configFilePath","isFileReadable","yamlContent","readFile","parsedYaml","yaml","load","deepMergeConfigs","configs","reduce","merged","current","deepMergeTwo","target","source","Array","isArray","result","key","Object","prototype","hasOwnProperty","call","loadHierarchicalConfig","config","errors","sortedDirs","sort","a","b","dir","errorMsg","mergedConfig"],"mappings":"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"}
1
+ {"version":3,"file":"hierarchical.js","sources":["../../src/util/hierarchical.ts"],"sourcesContent":["import path from 'path';\nimport * as yaml from 'js-yaml';\nimport { create as createStorage } from './storage';\nimport { Logger, FieldOverlapOptions, ArrayOverlapMode } from '../types';\n\n/**\n * Resolves relative paths in configuration values relative to the configuration file's directory.\n */\nfunction resolveConfigPaths(\n config: any,\n configDir: string,\n pathFields: string[] = [],\n resolvePathArray: string[] = []\n): any {\n if (!config || typeof config !== 'object' || pathFields.length === 0) {\n return config;\n }\n\n const resolvedConfig = { ...config };\n\n for (const fieldPath of pathFields) {\n const value = getNestedValue(resolvedConfig, fieldPath);\n if (value !== undefined) {\n const shouldResolveArrayElements = resolvePathArray.includes(fieldPath);\n const resolvedValue = resolvePathValue(value, configDir, shouldResolveArrayElements);\n setNestedValue(resolvedConfig, fieldPath, resolvedValue);\n }\n }\n\n return resolvedConfig;\n}\n\n/**\n * Gets a nested value from an object using dot notation.\n */\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj);\n}\n\n/**\n * Sets a nested value in an object using dot notation.\n */\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n const target = keys.reduce((current, key) => {\n if (!(key in current)) {\n current[key] = {};\n }\n return current[key];\n }, obj);\n target[lastKey] = value;\n}\n\n/**\n * Resolves a path value (string or array of strings) relative to the config directory.\n */\nfunction resolvePathValue(value: any, configDir: string, resolveArrayElements: boolean): any {\n if (typeof value === 'string') {\n return resolveSinglePath(value, configDir);\n }\n\n if (Array.isArray(value) && resolveArrayElements) {\n return value.map(item =>\n typeof item === 'string' ? resolveSinglePath(item, configDir) : item\n );\n }\n\n return value;\n}\n\n/**\n * Resolves a single path string relative to the config directory if it's a relative path.\n */\nfunction resolveSinglePath(pathStr: string, configDir: string): string {\n if (!pathStr || path.isAbsolute(pathStr)) {\n return pathStr;\n }\n\n return path.resolve(configDir, pathStr);\n}\n\n/**\n * Represents a discovered configuration directory with its path and precedence level.\n */\nexport interface DiscoveredConfigDir {\n /** Absolute path to the configuration directory */\n path: string;\n /** Distance from the starting directory (0 = closest/highest precedence) */\n level: number;\n}\n\n/**\n * Options for hierarchical configuration discovery.\n */\nexport interface HierarchicalDiscoveryOptions {\n /** Name of the configuration directory to look for (e.g., '.kodrdriv') */\n configDirName: string;\n /** Name of the configuration file within each directory */\n configFileName: string;\n /** Maximum number of parent directories to traverse (default: 10) */\n maxLevels?: number;\n /** Starting directory for discovery (default: process.cwd()) */\n startingDir?: string;\n /** File encoding for reading configuration files */\n encoding?: string;\n /** Logger for debugging */\n logger?: Logger;\n /** Array of field names that contain paths to be resolved */\n pathFields?: string[];\n /** Array of field names whose array elements should all be resolved as paths */\n resolvePathArray?: string[];\n /** Configuration for how array fields should be merged in hierarchical mode */\n fieldOverlaps?: FieldOverlapOptions;\n}\n\n/**\n * Result of loading configurations from multiple directories.\n */\nexport interface HierarchicalConfigResult {\n /** Merged configuration object with proper precedence */\n config: object;\n /** Array of directories where configuration was found */\n discoveredDirs: DiscoveredConfigDir[];\n /** Array of any errors encountered during loading (non-fatal) */\n errors: string[];\n}\n\n/**\n * Discovers configuration directories by traversing up the directory tree.\n * \n * Starting from the specified directory (or current working directory),\n * this function searches for directories with the given name, continuing\n * up the directory tree until it reaches the filesystem root or the\n * maximum number of levels.\n * \n * @param options Configuration options for discovery\n * @returns Promise resolving to array of discovered configuration directories\n * \n * @example\n * ```typescript\n * const dirs = await discoverConfigDirectories({\n * configDirName: '.kodrdriv',\n * configFileName: 'config.yaml',\n * maxLevels: 5\n * });\n * // Returns: [\n * // { path: '/project/.kodrdriv', level: 0 },\n * // { path: '/project/parent/.kodrdriv', level: 1 }\n * // ]\n * ```\n */\nexport async function discoverConfigDirectories(\n options: HierarchicalDiscoveryOptions\n): Promise<DiscoveredConfigDir[]> {\n const {\n configDirName,\n maxLevels = 10,\n startingDir = process.cwd(),\n logger\n } = options;\n\n const storage = createStorage({ log: logger?.debug || (() => { }) });\n const discoveredDirs: DiscoveredConfigDir[] = [];\n\n let currentDir = path.resolve(startingDir);\n let level = 0;\n const visited = new Set<string>(); // Prevent infinite loops with symlinks\n\n logger?.debug(`Starting hierarchical discovery from: ${currentDir}`);\n\n while (level < maxLevels) {\n // Prevent infinite loops with symlinks\n const realPath = path.resolve(currentDir);\n if (visited.has(realPath)) {\n logger?.debug(`Already visited ${realPath}, stopping discovery`);\n break;\n }\n visited.add(realPath);\n\n const configDirPath = path.join(currentDir, configDirName);\n logger?.debug(`Checking for config directory: ${configDirPath}`);\n\n try {\n const exists = await storage.exists(configDirPath);\n const isReadable = exists && await storage.isDirectoryReadable(configDirPath);\n\n if (exists && isReadable) {\n discoveredDirs.push({\n path: configDirPath,\n level\n });\n logger?.debug(`Found config directory at level ${level}: ${configDirPath}`);\n } else if (exists && !isReadable) {\n logger?.debug(`Config directory exists but is not readable: ${configDirPath}`);\n }\n } catch (error: any) {\n logger?.debug(`Error checking config directory ${configDirPath}: ${error.message}`);\n }\n\n // Move up one directory level\n const parentDir = path.dirname(currentDir);\n\n // Check if we've reached the root directory\n if (parentDir === currentDir) {\n logger?.debug('Reached filesystem root, stopping discovery');\n break;\n }\n\n currentDir = parentDir;\n level++;\n }\n\n logger?.verbose(`Discovery complete. Found ${discoveredDirs.length} config directories`);\n return discoveredDirs;\n}\n\n/**\n * Loads and parses a configuration file from a directory.\n * \n * @param configDir Path to the configuration directory\n * @param configFileName Name of the configuration file\n * @param encoding File encoding\n * @param logger Optional logger\n * @param pathFields Optional array of field names that contain paths to be resolved\n * @param resolvePathArray Optional array of field names whose array elements should all be resolved as paths\n * @returns Promise resolving to parsed configuration object or null if not found\n */\nexport async function loadConfigFromDirectory(\n configDir: string,\n configFileName: string,\n encoding: string = 'utf8',\n logger?: Logger,\n pathFields?: string[],\n resolvePathArray?: string[]\n): Promise<object | null> {\n const storage = createStorage({ log: logger?.debug || (() => { }) });\n const configFilePath = path.join(configDir, configFileName);\n\n try {\n logger?.verbose(`Attempting to load config file: ${configFilePath}`);\n\n const exists = await storage.exists(configFilePath);\n if (!exists) {\n logger?.debug(`Config file does not exist: ${configFilePath}`);\n return null;\n }\n\n const isReadable = await storage.isFileReadable(configFilePath);\n if (!isReadable) {\n logger?.debug(`Config file exists but is not readable: ${configFilePath}`);\n return null;\n }\n\n const yamlContent = await storage.readFile(configFilePath, encoding);\n const parsedYaml = yaml.load(yamlContent);\n\n if (parsedYaml !== null && typeof parsedYaml === 'object') {\n let config = parsedYaml as object;\n\n // Apply path resolution if configured\n if (pathFields && pathFields.length > 0) {\n config = resolveConfigPaths(config, configDir, pathFields, resolvePathArray || []);\n }\n\n logger?.verbose(`Successfully loaded config from: ${configFilePath}`);\n return config;\n } else {\n logger?.debug(`Config file contains invalid format: ${configFilePath}`);\n return null;\n }\n } catch (error: any) {\n logger?.debug(`Error loading config from ${configFilePath}: ${error.message}`);\n return null;\n }\n}\n\n/**\n * Deep merges multiple configuration objects with proper precedence and configurable array overlap behavior.\n * \n * Objects are merged from lowest precedence to highest precedence,\n * meaning that properties in later objects override properties in earlier objects.\n * Arrays can be merged using different strategies based on the fieldOverlaps configuration.\n * \n * @param configs Array of configuration objects, ordered from lowest to highest precedence\n * @param fieldOverlaps Configuration for how array fields should be merged (optional)\n * @returns Merged configuration object\n * \n * @example\n * ```typescript\n * const merged = deepMergeConfigs([\n * { api: { timeout: 5000 }, features: ['auth'] }, // Lower precedence\n * { api: { retries: 3 }, features: ['analytics'] }, // Higher precedence\n * ], {\n * 'features': 'append' // Results in features: ['auth', 'analytics']\n * });\n * ```\n */\nexport function deepMergeConfigs(configs: object[], fieldOverlaps?: FieldOverlapOptions): object {\n if (configs.length === 0) {\n return {};\n }\n\n if (configs.length === 1) {\n return { ...configs[0] };\n }\n\n return configs.reduce((merged, current) => {\n return deepMergeTwo(merged, current, fieldOverlaps);\n }, {});\n}\n\n/**\n * Deep merges two objects with proper precedence and configurable array overlap behavior.\n * \n * @param target Target object (lower precedence)\n * @param source Source object (higher precedence)\n * @param fieldOverlaps Configuration for how array fields should be merged (optional)\n * @param currentPath Current field path for nested merging (used internally)\n * @returns Merged object\n */\nfunction deepMergeTwo(target: any, source: any, fieldOverlaps?: FieldOverlapOptions, currentPath: string = ''): any {\n // Handle null/undefined\n if (source == null) return target;\n if (target == null) return source;\n\n // Handle non-objects (primitives, arrays, functions, etc.)\n if (typeof source !== 'object' || typeof target !== 'object') {\n return source; // Source takes precedence\n }\n\n // Handle arrays with configurable overlap behavior\n if (Array.isArray(source)) {\n if (Array.isArray(target) && fieldOverlaps) {\n const overlapMode = getOverlapModeForPath(currentPath, fieldOverlaps);\n return mergeArrays(target, source, overlapMode);\n } else {\n // Default behavior: replace entirely\n return [...source];\n }\n }\n\n if (Array.isArray(target)) {\n return source; // Source object replaces target array\n }\n\n // Deep merge objects\n const result = { ...target };\n\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const fieldPath = currentPath ? `${currentPath}.${key}` : key;\n\n if (Object.prototype.hasOwnProperty.call(result, key) &&\n typeof result[key] === 'object' &&\n typeof source[key] === 'object' &&\n !Array.isArray(source[key]) &&\n !Array.isArray(result[key])) {\n // Recursively merge nested objects\n result[key] = deepMergeTwo(result[key], source[key], fieldOverlaps, fieldPath);\n } else {\n // Handle arrays and primitives with overlap consideration\n if (Array.isArray(source[key]) && Array.isArray(result[key]) && fieldOverlaps) {\n const overlapMode = getOverlapModeForPath(fieldPath, fieldOverlaps);\n result[key] = mergeArrays(result[key], source[key], overlapMode);\n } else {\n // Replace with source value (higher precedence)\n result[key] = source[key];\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Determines the overlap mode for a given field path.\n * \n * @param fieldPath The current field path (dot notation)\n * @param fieldOverlaps Configuration mapping field paths to overlap modes\n * @returns The overlap mode to use for this field path\n */\nfunction getOverlapModeForPath(fieldPath: string, fieldOverlaps: FieldOverlapOptions): ArrayOverlapMode {\n // Check for exact match first\n if (fieldPath in fieldOverlaps) {\n return fieldOverlaps[fieldPath];\n }\n\n // Check for any parent path matches (for nested configurations)\n const pathParts = fieldPath.split('.');\n for (let i = pathParts.length - 1; i > 0; i--) {\n const parentPath = pathParts.slice(0, i).join('.');\n if (parentPath in fieldOverlaps) {\n return fieldOverlaps[parentPath];\n }\n }\n\n // Default to override if no specific configuration found\n return 'override';\n}\n\n/**\n * Merges two arrays based on the specified overlap mode.\n * \n * @param targetArray The lower precedence array\n * @param sourceArray The higher precedence array\n * @param mode The overlap mode to use\n * @returns The merged array\n */\nfunction mergeArrays(targetArray: any[], sourceArray: any[], mode: ArrayOverlapMode): any[] {\n switch (mode) {\n case 'append':\n return [...targetArray, ...sourceArray];\n case 'prepend':\n return [...sourceArray, ...targetArray];\n case 'override':\n default:\n return [...sourceArray];\n }\n}\n\n/**\n * Loads configurations from multiple directories and merges them with proper precedence.\n * \n * This is the main function for hierarchical configuration loading. It:\n * 1. Discovers configuration directories up the directory tree\n * 2. Loads configuration files from each discovered directory\n * 3. Merges them with proper precedence (closer directories win)\n * 4. Returns the merged configuration with metadata\n * \n * @param options Configuration options for hierarchical loading\n * @returns Promise resolving to hierarchical configuration result\n * \n * @example\n * ```typescript\n * const result = await loadHierarchicalConfig({\n * configDirName: '.kodrdriv',\n * configFileName: 'config.yaml',\n * startingDir: '/project/subdir',\n * maxLevels: 5,\n * fieldOverlaps: {\n * 'features': 'append',\n * 'excludePatterns': 'prepend'\n * }\n * });\n * \n * // result.config contains merged configuration with custom array merging\n * // result.discoveredDirs shows where configs were found\n * // result.errors contains any non-fatal errors\n * ```\n */\nexport async function loadHierarchicalConfig(\n options: HierarchicalDiscoveryOptions\n): Promise<HierarchicalConfigResult> {\n const { configFileName, encoding = 'utf8', logger, pathFields, resolvePathArray, fieldOverlaps } = options;\n\n logger?.verbose('Starting hierarchical configuration loading');\n\n // Discover all configuration directories\n const discoveredDirs = await discoverConfigDirectories(options);\n\n if (discoveredDirs.length === 0) {\n logger?.verbose('No configuration directories found');\n return {\n config: {},\n discoveredDirs: [],\n errors: []\n };\n }\n\n // Load configurations from each directory\n const configs: object[] = [];\n const errors: string[] = [];\n\n // Sort by level (highest level first = lowest precedence first)\n const sortedDirs = [...discoveredDirs].sort((a, b) => b.level - a.level);\n\n for (const dir of sortedDirs) {\n try {\n const config = await loadConfigFromDirectory(\n dir.path,\n configFileName,\n encoding,\n logger,\n pathFields,\n resolvePathArray\n );\n\n if (config !== null) {\n configs.push(config);\n logger?.debug(`Loaded config from level ${dir.level}: ${dir.path}`);\n } else {\n logger?.debug(`No valid config found at level ${dir.level}: ${dir.path}`);\n }\n } catch (error: any) {\n const errorMsg = `Failed to load config from ${dir.path}: ${error.message}`;\n errors.push(errorMsg);\n logger?.debug(errorMsg);\n }\n }\n\n // Merge all configurations with proper precedence and configurable array overlap\n const mergedConfig = deepMergeConfigs(configs, fieldOverlaps);\n\n logger?.verbose(`Hierarchical loading complete. Merged ${configs.length} configurations`);\n\n return {\n config: mergedConfig,\n discoveredDirs,\n errors\n };\n} "],"names":["resolveConfigPaths","config","configDir","pathFields","resolvePathArray","length","resolvedConfig","fieldPath","value","getNestedValue","undefined","shouldResolveArrayElements","includes","resolvedValue","resolvePathValue","setNestedValue","obj","path","split","reduce","current","key","keys","lastKey","pop","target","resolveArrayElements","resolveSinglePath","Array","isArray","map","item","pathStr","isAbsolute","resolve","discoverConfigDirectories","options","configDirName","maxLevels","startingDir","process","cwd","logger","storage","createStorage","log","debug","discoveredDirs","currentDir","level","visited","Set","realPath","has","add","configDirPath","join","exists","isReadable","isDirectoryReadable","push","error","message","parentDir","dirname","verbose","loadConfigFromDirectory","configFileName","encoding","configFilePath","isFileReadable","yamlContent","readFile","parsedYaml","yaml","load","deepMergeConfigs","configs","fieldOverlaps","merged","deepMergeTwo","source","currentPath","overlapMode","getOverlapModeForPath","mergeArrays","result","Object","prototype","hasOwnProperty","call","pathParts","i","parentPath","slice","targetArray","sourceArray","mode","loadHierarchicalConfig","errors","sortedDirs","sort","a","b","dir","errorMsg","mergedConfig"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theunwalked/cardigantime",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "cardigantime is a tool to help you time your cardigans.",
5
5
  "type": "module",
6
6
  "main": "./dist/cardigantime.cjs",