@theunwalked/cardigantime 0.0.21 → 0.0.22

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.
@@ -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, 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 isUnsafeKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype';\n}\n\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n\n // Prevent prototype pollution via special property names\n if (isUnsafeKey(lastKey) || keys.some(isUnsafeKey)) {\n return;\n }\n\n const target = keys.reduce((current, key) => {\n // Skip if this is an unsafe key (already checked above, but defensive)\n if (isUnsafeKey(key)) {\n return current;\n }\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 directories that actually contained valid configuration files */\n resolvedConfigDirs: 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 * Tries to find a config file with alternative extensions (.yaml or .yml).\n * \n * @param storage Storage instance to use for file operations\n * @param configDir The directory containing the config file\n * @param configFileName The base config file name (may have .yaml or .yml extension)\n * @param logger Optional logger for debugging\n * @returns Promise resolving to the found config file path or null if not found\n */\nasync function findConfigFileWithExtension(\n storage: any,\n configDir: string,\n configFileName: string,\n logger?: Logger\n): Promise<string | null> {\n const configFilePath = path.join(configDir, configFileName);\n \n // First try the exact filename as specified\n const exists = await storage.exists(configFilePath);\n if (exists) {\n const isReadable = await storage.isFileReadable(configFilePath);\n if (isReadable) {\n return configFilePath;\n }\n }\n \n // If the exact filename doesn't exist or isn't readable, try alternative extensions\n // Only do this if the filename has a .yaml or .yml extension\n const ext = path.extname(configFileName);\n if (ext === '.yaml' || ext === '.yml') {\n const baseName = path.basename(configFileName, ext);\n const alternativeExt = ext === '.yaml' ? '.yml' : '.yaml';\n const alternativePath = path.join(configDir, baseName + alternativeExt);\n \n logger?.debug(`Config file not found at ${configFilePath}, trying alternative: ${alternativePath}`);\n \n const altExists = await storage.exists(alternativePath);\n if (altExists) {\n const altIsReadable = await storage.isFileReadable(alternativePath);\n if (altIsReadable) {\n logger?.debug(`Found config file with alternative extension: ${alternativePath}`);\n return alternativePath;\n }\n }\n }\n \n return null;\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 \n try {\n logger?.verbose(`Attempting to load config file: ${path.join(configDir, configFileName)}`);\n\n // Try to find the config file with alternative extensions\n const configFilePath = await findConfigFileWithExtension(storage, configDir, configFileName, logger);\n \n if (!configFilePath) {\n logger?.debug(`Config file does not exist: ${path.join(configDir, configFileName)}`);\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 ${path.join(configDir, configFileName)}: ${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 resolvedConfigDirs: [],\n errors: []\n };\n }\n\n // Load configurations from each directory\n const configs: object[] = [];\n const resolvedConfigDirs: DiscoveredConfigDir[] = [];\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 resolvedConfigDirs.push(dir);\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 resolvedConfigDirs,\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","isUnsafeKey","keys","lastKey","pop","some","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","findConfigFileWithExtension","configFileName","configFilePath","isFileReadable","ext","extname","baseName","basename","alternativeExt","alternativePath","altExists","altIsReadable","loadConfigFromDirectory","encoding","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","resolvedConfigDirs","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 * as path from 'node: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 isUnsafeKey(key: string): boolean {\n return key === '__proto__' || key === 'constructor' || key === 'prototype';\n}\n\nfunction setNestedValue(obj: any, path: string, value: any): void {\n const keys = path.split('.');\n const lastKey = keys.pop()!;\n\n // Prevent prototype pollution via special property names\n if (isUnsafeKey(lastKey) || keys.some(isUnsafeKey)) {\n return;\n }\n\n const target = keys.reduce((current, key) => {\n // Skip if this is an unsafe key (already checked above, but defensive)\n if (isUnsafeKey(key)) {\n return current;\n }\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 directories that actually contained valid configuration files */\n resolvedConfigDirs: 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 * Tries to find a config file with alternative extensions (.yaml or .yml).\n * \n * @param storage Storage instance to use for file operations\n * @param configDir The directory containing the config file\n * @param configFileName The base config file name (may have .yaml or .yml extension)\n * @param logger Optional logger for debugging\n * @returns Promise resolving to the found config file path or null if not found\n */\nasync function findConfigFileWithExtension(\n storage: any,\n configDir: string,\n configFileName: string,\n logger?: Logger\n): Promise<string | null> {\n const configFilePath = path.join(configDir, configFileName);\n \n // First try the exact filename as specified\n const exists = await storage.exists(configFilePath);\n if (exists) {\n const isReadable = await storage.isFileReadable(configFilePath);\n if (isReadable) {\n return configFilePath;\n }\n }\n \n // If the exact filename doesn't exist or isn't readable, try alternative extensions\n // Only do this if the filename has a .yaml or .yml extension\n const ext = path.extname(configFileName);\n if (ext === '.yaml' || ext === '.yml') {\n const baseName = path.basename(configFileName, ext);\n const alternativeExt = ext === '.yaml' ? '.yml' : '.yaml';\n const alternativePath = path.join(configDir, baseName + alternativeExt);\n \n logger?.debug(`Config file not found at ${configFilePath}, trying alternative: ${alternativePath}`);\n \n const altExists = await storage.exists(alternativePath);\n if (altExists) {\n const altIsReadable = await storage.isFileReadable(alternativePath);\n if (altIsReadable) {\n logger?.debug(`Found config file with alternative extension: ${alternativePath}`);\n return alternativePath;\n }\n }\n }\n \n return null;\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 \n try {\n logger?.verbose(`Attempting to load config file: ${path.join(configDir, configFileName)}`);\n\n // Try to find the config file with alternative extensions\n const configFilePath = await findConfigFileWithExtension(storage, configDir, configFileName, logger);\n \n if (!configFilePath) {\n logger?.debug(`Config file does not exist: ${path.join(configDir, configFileName)}`);\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 ${path.join(configDir, configFileName)}: ${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 resolvedConfigDirs: [],\n errors: []\n };\n }\n\n // Load configurations from each directory\n const configs: object[] = [];\n const resolvedConfigDirs: DiscoveredConfigDir[] = [];\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 resolvedConfigDirs.push(dir);\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 resolvedConfigDirs,\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","isUnsafeKey","keys","lastKey","pop","some","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","findConfigFileWithExtension","configFileName","configFilePath","isFileReadable","ext","extname","baseName","basename","alternativeExt","alternativePath","altExists","altIsReadable","loadConfigFromDirectory","encoding","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","resolvedConfigDirs","errors","sortedDirs","sort","a","b","dir","errorMsg","mergedConfig"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import * as fs from 'fs';
1
+ import * as fs from 'node:fs';
2
2
  /**
3
3
  * This module exists to isolate filesystem operations from the rest of the codebase.
4
4
  * This makes testing easier by avoiding direct fs mocking in jest configuration.
@@ -1,10 +1,9 @@
1
- import * as fs from 'fs';
1
+ import * as fs from 'node:fs';
2
2
  import { glob } from 'glob';
3
- import path__default from 'path';
4
- import crypto from 'crypto';
3
+ import * as path from 'node:path';
4
+ import * as crypto from 'node:crypto';
5
5
  import { FileSystemError } from '../error/FileSystemError.js';
6
6
 
7
- // eslint-disable-next-line no-restricted-imports
8
7
  const create = (params)=>{
9
8
  // eslint-disable-next-line no-console
10
9
  const log = params.log || console.log;
@@ -116,7 +115,7 @@ const create = (params)=>{
116
115
  nodir: true
117
116
  });
118
117
  for (const file of files){
119
- await callback(path__default.join(directory, file));
118
+ await callback(path.join(directory, file));
120
119
  }
121
120
  } catch (err) {
122
121
  throw FileSystemError.operationFailed(`glob pattern ${options.pattern}`, directory, err);
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport * as fs from 'fs';\nimport { glob } from 'glob';\nimport path from 'path';\nimport crypto from 'crypto';\nimport { FileSystemError } from '../error/FileSystemError';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw FileSystemError.directoryCreationFailed(path, mkdirError);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n // Validate encoding parameter\n const validEncodings = ['utf8', 'utf-8', 'ascii', 'latin1', 'base64', 'hex', 'utf16le', 'ucs2', 'ucs-2'];\n if (!validEncodings.includes(encoding.toLowerCase())) {\n throw new Error('Invalid encoding specified');\n }\n\n // Check file size before reading to prevent DoS\n try {\n const stats = await fs.promises.stat(path);\n const maxFileSize = 10 * 1024 * 1024; // 10MB limit\n if (stats.size > maxFileSize) {\n throw new Error('File too large to process');\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw FileSystemError.fileNotFound(path);\n }\n throw error;\n }\n\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (directory: string, callback: (file: string) => Promise<void>, options: { pattern: string | string[] } = { pattern: '*.*' }): Promise<void> => {\n try {\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n for (const file of files) {\n await callback(path.join(directory, file));\n }\n } catch (err: any) {\n throw FileSystemError.operationFailed(`glob pattern ${options.pattern}`, directory, err);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","FileSystemError","directoryCreationFailed","readFile","encoding","validEncodings","includes","toLowerCase","Error","maxFileSize","size","code","fileNotFound","writeFile","data","forEachFileIn","directory","callback","options","pattern","files","glob","cwd","nodir","file","join","err","operationFailed","readStream","createReadStream","hashFile","length","crypto","createHash","update","digest","slice","listFiles","readdir"],"mappings":"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"}
1
+ {"version":3,"file":"storage.js","sources":["../../src/util/storage.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport { glob } from 'glob';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport { FileSystemError } from '../error/FileSystemError';\n/**\n * This module exists to isolate filesystem operations from the rest of the codebase.\n * This makes testing easier by avoiding direct fs mocking in jest configuration.\n * \n * Additionally, abstracting storage operations allows for future flexibility - \n * this export utility may need to work with storage systems other than the local filesystem\n * (e.g. S3, Google Cloud Storage, etc).\n */\n\nexport interface Utility {\n exists: (path: string) => Promise<boolean>;\n isDirectory: (path: string) => Promise<boolean>;\n isFile: (path: string) => Promise<boolean>;\n isReadable: (path: string) => Promise<boolean>;\n isWritable: (path: string) => Promise<boolean>;\n isFileReadable: (path: string) => Promise<boolean>;\n isDirectoryWritable: (path: string) => Promise<boolean>;\n isDirectoryReadable: (path: string) => Promise<boolean>;\n createDirectory: (path: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n readStream: (path: string) => Promise<fs.ReadStream>;\n writeFile: (path: string, data: string | Buffer, encoding: string) => Promise<void>;\n forEachFileIn: (directory: string, callback: (path: string) => Promise<void>, options?: { pattern: string }) => Promise<void>;\n hashFile: (path: string, length: number) => Promise<string>;\n listFiles: (directory: string) => Promise<string[]>;\n}\n\nexport const create = (params: { log?: (message: string, ...args: any[]) => void }): Utility => {\n\n // eslint-disable-next-line no-console\n const log = params.log || console.log;\n\n const exists = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.stat(path);\n return true;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error: any) {\n return false;\n }\n }\n\n const isDirectory = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isDirectory()) {\n log(`${path} is not a directory`);\n return false;\n }\n return true;\n }\n\n const isFile = async (path: string): Promise<boolean> => {\n const stats = await fs.promises.stat(path);\n if (!stats.isFile()) {\n log(`${path} is not a file`);\n return false;\n }\n return true;\n }\n\n const isReadable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.R_OK);\n } catch (error: any) {\n log(`${path} is not readable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isWritable = async (path: string): Promise<boolean> => {\n try {\n await fs.promises.access(path, fs.constants.W_OK);\n } catch (error: any) {\n log(`${path} is not writable: %s %s`, error.message, error.stack);\n return false;\n }\n return true;\n }\n\n const isFileReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isFile(path) && await isReadable(path);\n }\n\n const isDirectoryWritable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isWritable(path);\n }\n\n const isDirectoryReadable = async (path: string): Promise<boolean> => {\n return await exists(path) && await isDirectory(path) && await isReadable(path);\n }\n\n const createDirectory = async (path: string): Promise<void> => {\n try {\n await fs.promises.mkdir(path, { recursive: true });\n } catch (mkdirError: any) {\n throw FileSystemError.directoryCreationFailed(path, mkdirError);\n }\n }\n\n const readFile = async (path: string, encoding: string): Promise<string> => {\n // Validate encoding parameter\n const validEncodings = ['utf8', 'utf-8', 'ascii', 'latin1', 'base64', 'hex', 'utf16le', 'ucs2', 'ucs-2'];\n if (!validEncodings.includes(encoding.toLowerCase())) {\n throw new Error('Invalid encoding specified');\n }\n\n // Check file size before reading to prevent DoS\n try {\n const stats = await fs.promises.stat(path);\n const maxFileSize = 10 * 1024 * 1024; // 10MB limit\n if (stats.size > maxFileSize) {\n throw new Error('File too large to process');\n }\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw FileSystemError.fileNotFound(path);\n }\n throw error;\n }\n\n return await fs.promises.readFile(path, { encoding: encoding as BufferEncoding });\n }\n\n const writeFile = async (path: string, data: string | Buffer, encoding: string): Promise<void> => {\n await fs.promises.writeFile(path, data, { encoding: encoding as BufferEncoding });\n }\n\n const forEachFileIn = async (directory: string, callback: (file: string) => Promise<void>, options: { pattern: string | string[] } = { pattern: '*.*' }): Promise<void> => {\n try {\n const files = await glob(options.pattern, { cwd: directory, nodir: true });\n for (const file of files) {\n await callback(path.join(directory, file));\n }\n } catch (err: any) {\n throw FileSystemError.operationFailed(`glob pattern ${options.pattern}`, directory, err);\n }\n }\n\n const readStream = async (path: string): Promise<fs.ReadStream> => {\n return fs.createReadStream(path);\n }\n\n const hashFile = async (path: string, length: number): Promise<string> => {\n const file = await readFile(path, 'utf8');\n return crypto.createHash('sha256').update(file).digest('hex').slice(0, length);\n }\n\n const listFiles = async (directory: string): Promise<string[]> => {\n return await fs.promises.readdir(directory);\n }\n\n return {\n exists,\n isDirectory,\n isFile,\n isReadable,\n isWritable,\n isFileReadable,\n isDirectoryWritable,\n isDirectoryReadable,\n createDirectory,\n readFile,\n readStream,\n writeFile,\n forEachFileIn,\n hashFile,\n listFiles,\n };\n}"],"names":["create","params","log","console","exists","path","fs","promises","stat","error","isDirectory","stats","isFile","isReadable","access","constants","R_OK","message","stack","isWritable","W_OK","isFileReadable","isDirectoryWritable","isDirectoryReadable","createDirectory","mkdir","recursive","mkdirError","FileSystemError","directoryCreationFailed","readFile","encoding","validEncodings","includes","toLowerCase","Error","maxFileSize","size","code","fileNotFound","writeFile","data","forEachFileIn","directory","callback","options","pattern","files","glob","cwd","nodir","file","join","err","operationFailed","readStream","createReadStream","hashFile","length","crypto","createHash","update","digest","slice","listFiles","readdir"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theunwalked/cardigantime",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "cardigantime is a tool to help you time your cardigans.",
5
5
  "type": "module",
6
6
  "main": "./dist/cardigantime.cjs",