@theunwalked/cardigantime 0.0.10 → 0.0.12

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.
@@ -69,6 +69,10 @@ export { ConfigurationError } from './error/ConfigurationError.js';
69
69
  * // These paths will be resolved relative to ../config/ directory
70
70
  * ```
71
71
  */ const create = (pOptions)=>{
72
+ // Validate that configDirectory is a string
73
+ if (!pOptions.defaults.configDirectory || typeof pOptions.defaults.configDirectory !== 'string') {
74
+ throw new Error(`Configuration directory must be a string, received: ${typeof pOptions.defaults.configDirectory} (${JSON.stringify(pOptions.defaults.configDirectory)})`);
75
+ }
72
76
  const defaults = {
73
77
  ...DEFAULT_OPTIONS,
74
78
  ...pOptions.defaults
@@ -90,6 +94,10 @@ export { ConfigurationError } from './error/ConfigurationError.js';
90
94
  const targetDir = configDirectory || options.defaults.configDirectory;
91
95
  const configFile = options.defaults.configFile;
92
96
  const encoding = options.defaults.encoding;
97
+ // Validate that targetDir is a string
98
+ if (!targetDir || typeof targetDir !== 'string') {
99
+ throw new Error(`Configuration directory must be a string, received: ${typeof targetDir} (${JSON.stringify(targetDir)})`);
100
+ }
93
101
  logger.verbose(`Generating configuration file in: ${targetDir}`);
94
102
  // Create storage utility
95
103
  const storage = create$1({
@@ -113,7 +121,9 @@ export { ConfigurationError } from './error/ConfigurationError.js';
113
121
  // Build the full config file path
114
122
  const configFilePath = path.join(targetDir, configFile);
115
123
  // Generate default configuration
124
+ logger.debug(`Generating defaults for schema with keys: ${Object.keys(options.configShape).join(', ')}`);
116
125
  const defaultConfig = generateDefaultConfig(options.configShape);
126
+ logger.debug(`Generated default config: ${JSON.stringify(defaultConfig, null, 2)}`);
117
127
  // Convert to YAML with nice formatting
118
128
  const yamlContent = yaml.dump(defaultConfig, {
119
129
  indent: 2,
@@ -1 +1 @@
1
- {"version":3,"file":"cardigantime.js","sources":["../src/cardigantime.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { Args, DefaultOptions, Feature, Cardigantime, Logger, Options } from 'types';\nimport { z, ZodObject } from 'zod';\nimport { configure } from './configure';\nimport { DEFAULT_FEATURES, DEFAULT_LOGGER, DEFAULT_OPTIONS } from './constants';\nimport { read, checkConfig } from './read';\nimport { ConfigSchema } from 'types';\nimport { validate } from './validate';\nimport * as yaml from 'js-yaml';\nimport * as path from 'path';\nimport { generateDefaultConfig } from './util/schema-defaults';\nimport * as Storage from './util/storage';\nimport { FileSystemError } from './error/FileSystemError';\n\nexport * from './types';\nexport { ArgumentError, ConfigurationError, FileSystemError } from './validate';\n\n/**\n * Creates a new Cardigantime instance for configuration management.\n * \n * Cardigantime handles the complete configuration lifecycle including:\n * - Reading configuration from YAML files\n * - Validating configuration against Zod schemas\n * - Merging CLI arguments with file configuration and defaults\n * - Providing type-safe configuration objects\n * \n * @template T - The Zod schema shape type for your configuration\n * @param pOptions - Configuration options for the Cardigantime instance\n * @param pOptions.defaults - Default configuration settings\n * @param pOptions.defaults.configDirectory - Directory to search for configuration files (required)\n * @param pOptions.defaults.configFile - Name of the configuration file (optional, defaults to 'config.yaml')\n * @param pOptions.defaults.isRequired - Whether the config directory must exist (optional, defaults to false)\n * @param pOptions.defaults.encoding - File encoding for reading config files (optional, defaults to 'utf8')\n * @param pOptions.defaults.pathResolution - Configuration for resolving relative paths in config values relative to the config file's directory (optional)\n * @param pOptions.features - Array of features to enable (optional, defaults to ['config'])\n * @param pOptions.configShape - Zod schema shape defining your configuration structure (required)\n * @param pOptions.logger - Custom logger implementation (optional, defaults to console logger)\n * @returns A Cardigantime instance with methods for configure, read, validate, and setLogger\n * \n * @example\n * ```typescript\n * import { create } from '@theunwalked/cardigantime';\n * import { z } from 'zod';\n * \n * const MyConfigSchema = z.object({\n * apiKey: z.string().min(1),\n * timeout: z.number().default(5000),\n * debug: z.boolean().default(false),\n * contextDirectories: z.array(z.string()).optional(),\n * });\n * \n * const cardigantime = create({\n * defaults: {\n * configDirectory: './config',\n * configFile: 'myapp.yaml',\n * // Resolve relative paths in contextDirectories relative to config file location\n * pathResolution: {\n * pathFields: ['contextDirectories'],\n * resolvePathArray: ['contextDirectories']\n * },\n * // Configure how array fields are merged in hierarchical mode\n * fieldOverlaps: {\n * 'features': 'append', // Accumulate features from all levels\n * 'excludePatterns': 'prepend' // Higher precedence patterns come first\n * }\n * },\n * configShape: MyConfigSchema.shape,\n * features: ['config', 'hierarchical'], // Enable hierarchical discovery\n * });\n * \n * // If config file is at ../config/myapp.yaml and contains:\n * // contextDirectories: ['./context', './data']\n * // These paths will be resolved relative to ../config/ directory\n * ```\n */\nexport const create = <T extends z.ZodRawShape>(pOptions: {\n defaults: Pick<DefaultOptions, 'configDirectory'> & Partial<Omit<DefaultOptions, 'configDirectory'>>,\n features?: Feature[],\n configShape: T, // Make configShape mandatory\n logger?: Logger,\n}): Cardigantime<T> => {\n\n\n const defaults: DefaultOptions = { ...DEFAULT_OPTIONS, ...pOptions.defaults } as DefaultOptions;\n const features = pOptions.features || DEFAULT_FEATURES;\n const configShape = pOptions.configShape;\n let logger = pOptions.logger || DEFAULT_LOGGER;\n\n const options: Options<T> = {\n defaults,\n features,\n configShape, // Store the shape\n logger,\n }\n\n const setLogger = (pLogger: Logger) => {\n logger = pLogger;\n options.logger = pLogger;\n }\n\n const generateConfig = async (configDirectory?: string): Promise<void> => {\n const targetDir = configDirectory || options.defaults.configDirectory;\n const configFile = options.defaults.configFile;\n const encoding = options.defaults.encoding;\n\n logger.verbose(`Generating configuration file in: ${targetDir}`);\n\n // Create storage utility\n const storage = Storage.create({ log: logger.debug });\n\n // Ensure the target directory exists\n const dirExists = await storage.exists(targetDir);\n if (!dirExists) {\n logger.info(`Creating configuration directory: ${targetDir}`);\n try {\n await storage.createDirectory(targetDir);\n } catch (error: any) {\n throw FileSystemError.directoryCreationFailed(targetDir, error);\n }\n }\n\n // Check if directory is writable\n const isWritable = await storage.isDirectoryWritable(targetDir);\n if (!isWritable) {\n throw new FileSystemError('not_writable', 'Configuration directory is not writable', targetDir, 'directory_write');\n }\n\n // Build the full config file path\n const configFilePath = path.join(targetDir, configFile);\n\n // Generate default configuration\n const defaultConfig = generateDefaultConfig(options.configShape, targetDir);\n\n // Convert to YAML with nice formatting\n const yamlContent = yaml.dump(defaultConfig, {\n indent: 2,\n lineWidth: 120,\n noRefs: true,\n sortKeys: true\n });\n\n // Add header comment to the YAML file\n const header = `# Configuration file generated by Cardigantime\n# This file contains default values for your application configuration.\n# Modify the values below to customize your application's behavior.\n#\n# For more information about Cardigantime configuration:\n# https://github.com/SemicolonAmbulance/cardigantime\n\n`;\n\n const finalContent = header + yamlContent;\n\n // Check if config file already exists\n const configExists = await storage.exists(configFilePath);\n if (configExists) {\n logger.warn(`Configuration file already exists: ${configFilePath}`);\n logger.warn('This file was not overwritten, but here is what the default configuration looks like if you want to copy it:');\n logger.info('\\n' + '='.repeat(60));\n logger.info(finalContent.trim());\n logger.info('='.repeat(60));\n return;\n }\n\n // Write the configuration file\n try {\n await storage.writeFile(configFilePath, finalContent, encoding);\n logger.info(`Configuration file generated successfully: ${configFilePath}`);\n } catch (error: any) {\n throw FileSystemError.operationFailed('write configuration file', configFilePath, error);\n }\n };\n\n return {\n setLogger,\n configure: (command: Command) => configure(command, options),\n validate: (config: z.infer<ZodObject<T & typeof ConfigSchema.shape>>) => validate(config, options),\n read: (args: Args) => read(args, options),\n generateConfig,\n checkConfig: (args: Args) => checkConfig(args, options),\n }\n}\n\n\n\n\n\n"],"names":["create","pOptions","defaults","DEFAULT_OPTIONS","features","DEFAULT_FEATURES","configShape","logger","DEFAULT_LOGGER","options","setLogger","pLogger","generateConfig","configDirectory","targetDir","configFile","encoding","verbose","storage","Storage","log","debug","dirExists","exists","info","createDirectory","error","FileSystemError","directoryCreationFailed","isWritable","isDirectoryWritable","configFilePath","path","join","defaultConfig","generateDefaultConfig","yamlContent","yaml","dump","indent","lineWidth","noRefs","sortKeys","header","finalContent","configExists","warn","repeat","trim","writeFile","operationFailed","configure","command","validate","config","read","args","checkConfig"],"mappings":"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"}
1
+ {"version":3,"file":"cardigantime.js","sources":["../src/cardigantime.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { Args, DefaultOptions, Feature, Cardigantime, Logger, Options } from 'types';\nimport { z, ZodObject } from 'zod';\nimport { configure } from './configure';\nimport { DEFAULT_FEATURES, DEFAULT_LOGGER, DEFAULT_OPTIONS } from './constants';\nimport { read, checkConfig } from './read';\nimport { ConfigSchema } from 'types';\nimport { validate } from './validate';\nimport * as yaml from 'js-yaml';\nimport * as path from 'path';\nimport { generateDefaultConfig } from './util/schema-defaults';\nimport * as Storage from './util/storage';\nimport { FileSystemError } from './error/FileSystemError';\n\nexport * from './types';\nexport { ArgumentError, ConfigurationError, FileSystemError } from './validate';\n\n/**\n * Creates a new Cardigantime instance for configuration management.\n * \n * Cardigantime handles the complete configuration lifecycle including:\n * - Reading configuration from YAML files\n * - Validating configuration against Zod schemas\n * - Merging CLI arguments with file configuration and defaults\n * - Providing type-safe configuration objects\n * \n * @template T - The Zod schema shape type for your configuration\n * @param pOptions - Configuration options for the Cardigantime instance\n * @param pOptions.defaults - Default configuration settings\n * @param pOptions.defaults.configDirectory - Directory to search for configuration files (required)\n * @param pOptions.defaults.configFile - Name of the configuration file (optional, defaults to 'config.yaml')\n * @param pOptions.defaults.isRequired - Whether the config directory must exist (optional, defaults to false)\n * @param pOptions.defaults.encoding - File encoding for reading config files (optional, defaults to 'utf8')\n * @param pOptions.defaults.pathResolution - Configuration for resolving relative paths in config values relative to the config file's directory (optional)\n * @param pOptions.features - Array of features to enable (optional, defaults to ['config'])\n * @param pOptions.configShape - Zod schema shape defining your configuration structure (required)\n * @param pOptions.logger - Custom logger implementation (optional, defaults to console logger)\n * @returns A Cardigantime instance with methods for configure, read, validate, and setLogger\n * \n * @example\n * ```typescript\n * import { create } from '@theunwalked/cardigantime';\n * import { z } from 'zod';\n * \n * const MyConfigSchema = z.object({\n * apiKey: z.string().min(1),\n * timeout: z.number().default(5000),\n * debug: z.boolean().default(false),\n * contextDirectories: z.array(z.string()).optional(),\n * });\n * \n * const cardigantime = create({\n * defaults: {\n * configDirectory: './config',\n * configFile: 'myapp.yaml',\n * // Resolve relative paths in contextDirectories relative to config file location\n * pathResolution: {\n * pathFields: ['contextDirectories'],\n * resolvePathArray: ['contextDirectories']\n * },\n * // Configure how array fields are merged in hierarchical mode\n * fieldOverlaps: {\n * 'features': 'append', // Accumulate features from all levels\n * 'excludePatterns': 'prepend' // Higher precedence patterns come first\n * }\n * },\n * configShape: MyConfigSchema.shape,\n * features: ['config', 'hierarchical'], // Enable hierarchical discovery\n * });\n * \n * // If config file is at ../config/myapp.yaml and contains:\n * // contextDirectories: ['./context', './data']\n * // These paths will be resolved relative to ../config/ directory\n * ```\n */\nexport const create = <T extends z.ZodRawShape>(pOptions: {\n defaults: Pick<DefaultOptions, 'configDirectory'> & Partial<Omit<DefaultOptions, 'configDirectory'>>,\n features?: Feature[],\n configShape: T, // Make configShape mandatory\n logger?: Logger,\n}): Cardigantime<T> => {\n\n // Validate that configDirectory is a string\n if (!pOptions.defaults.configDirectory || typeof pOptions.defaults.configDirectory !== 'string') {\n throw new Error(`Configuration directory must be a string, received: ${typeof pOptions.defaults.configDirectory} (${JSON.stringify(pOptions.defaults.configDirectory)})`);\n }\n\n const defaults: DefaultOptions = { ...DEFAULT_OPTIONS, ...pOptions.defaults } as DefaultOptions;\n const features = pOptions.features || DEFAULT_FEATURES;\n const configShape = pOptions.configShape;\n let logger = pOptions.logger || DEFAULT_LOGGER;\n\n const options: Options<T> = {\n defaults,\n features,\n configShape, // Store the shape\n logger,\n }\n\n const setLogger = (pLogger: Logger) => {\n logger = pLogger;\n options.logger = pLogger;\n }\n\n const generateConfig = async (configDirectory?: string): Promise<void> => {\n const targetDir = configDirectory || options.defaults.configDirectory;\n const configFile = options.defaults.configFile;\n const encoding = options.defaults.encoding;\n\n // Validate that targetDir is a string\n if (!targetDir || typeof targetDir !== 'string') {\n throw new Error(`Configuration directory must be a string, received: ${typeof targetDir} (${JSON.stringify(targetDir)})`);\n }\n\n logger.verbose(`Generating configuration file in: ${targetDir}`);\n\n // Create storage utility\n const storage = Storage.create({ log: logger.debug });\n\n // Ensure the target directory exists\n const dirExists = await storage.exists(targetDir);\n if (!dirExists) {\n logger.info(`Creating configuration directory: ${targetDir}`);\n try {\n await storage.createDirectory(targetDir);\n } catch (error: any) {\n throw FileSystemError.directoryCreationFailed(targetDir, error);\n }\n }\n\n // Check if directory is writable\n const isWritable = await storage.isDirectoryWritable(targetDir);\n if (!isWritable) {\n throw new FileSystemError('not_writable', 'Configuration directory is not writable', targetDir, 'directory_write');\n }\n\n // Build the full config file path\n const configFilePath = path.join(targetDir, configFile);\n\n // Generate default configuration\n logger.debug(`Generating defaults for schema with keys: ${Object.keys(options.configShape).join(', ')}`);\n const defaultConfig = generateDefaultConfig(options.configShape, targetDir);\n logger.debug(`Generated default config: ${JSON.stringify(defaultConfig, null, 2)}`);\n\n // Convert to YAML with nice formatting\n const yamlContent = yaml.dump(defaultConfig, {\n indent: 2,\n lineWidth: 120,\n noRefs: true,\n sortKeys: true\n });\n\n // Add header comment to the YAML file\n const header = `# Configuration file generated by Cardigantime\n# This file contains default values for your application configuration.\n# Modify the values below to customize your application's behavior.\n#\n# For more information about Cardigantime configuration:\n# https://github.com/SemicolonAmbulance/cardigantime\n\n`;\n\n const finalContent = header + yamlContent;\n\n // Check if config file already exists\n const configExists = await storage.exists(configFilePath);\n if (configExists) {\n logger.warn(`Configuration file already exists: ${configFilePath}`);\n logger.warn('This file was not overwritten, but here is what the default configuration looks like if you want to copy it:');\n logger.info('\\n' + '='.repeat(60));\n logger.info(finalContent.trim());\n logger.info('='.repeat(60));\n return;\n }\n\n // Write the configuration file\n try {\n await storage.writeFile(configFilePath, finalContent, encoding);\n logger.info(`Configuration file generated successfully: ${configFilePath}`);\n } catch (error: any) {\n throw FileSystemError.operationFailed('write configuration file', configFilePath, error);\n }\n };\n\n return {\n setLogger,\n configure: (command: Command) => configure(command, options),\n validate: (config: z.infer<ZodObject<T & typeof ConfigSchema.shape>>) => validate(config, options),\n read: (args: Args) => read(args, options),\n generateConfig,\n checkConfig: (args: Args) => checkConfig(args, options),\n }\n}\n\n\n\n\n\n"],"names":["create","pOptions","defaults","configDirectory","Error","JSON","stringify","DEFAULT_OPTIONS","features","DEFAULT_FEATURES","configShape","logger","DEFAULT_LOGGER","options","setLogger","pLogger","generateConfig","targetDir","configFile","encoding","verbose","storage","Storage","log","debug","dirExists","exists","info","createDirectory","error","FileSystemError","directoryCreationFailed","isWritable","isDirectoryWritable","configFilePath","path","join","Object","keys","defaultConfig","generateDefaultConfig","yamlContent","yaml","dump","indent","lineWidth","noRefs","sortKeys","header","finalContent","configExists","warn","repeat","trim","writeFile","operationFailed","configure","command","validate","config","read","args","checkConfig"],"mappings":";;;;;;;;;;;;;AAiBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA0DO,MAAMA,MAAAA,GAAS,CAA0BC,QAAAA,GAAAA;;AAQ5C,IAAA,IAAI,CAACA,QAAAA,CAASC,QAAQ,CAACC,eAAe,IAAI,OAAOF,QAAAA,CAASC,QAAQ,CAACC,eAAe,KAAK,QAAA,EAAU;QAC7F,MAAM,IAAIC,MAAM,CAAC,oDAAoD,EAAE,OAAOH,QAAAA,CAASC,QAAQ,CAACC,eAAe,CAAC,EAAE,EAAEE,IAAAA,CAAKC,SAAS,CAACL,QAAAA,CAASC,QAAQ,CAACC,eAAe,CAAA,CAAE,CAAC,CAAC,CAAA;AAC5K;AAEA,IAAA,MAAMD,QAAAA,GAA2B;AAAE,QAAA,GAAGK,eAAe;AAAE,QAAA,GAAGN,SAASC;AAAS,KAAA;IAC5E,MAAMM,QAAAA,GAAWP,QAAAA,CAASO,QAAQ,IAAIC,gBAAAA;IACtC,MAAMC,WAAAA,GAAcT,SAASS,WAAW;IACxC,IAAIC,MAAAA,GAASV,QAAAA,CAASU,MAAM,IAAIC,cAAAA;AAEhC,IAAA,MAAMC,OAAAA,GAAsB;AACxBX,QAAAA,QAAAA;AACAM,QAAAA,QAAAA;AACAE,QAAAA,WAAAA;AACAC,QAAAA;AACJ,KAAA;AAEA,IAAA,MAAMG,YAAY,CAACC,OAAAA,GAAAA;QACfJ,MAAAA,GAASI,OAAAA;AACTF,QAAAA,OAAAA,CAAQF,MAAM,GAAGI,OAAAA;AACrB,KAAA;AAEA,IAAA,MAAMC,iBAAiB,OAAOb,eAAAA,GAAAA;AAC1B,QAAA,MAAMc,SAAAA,GAAYd,eAAAA,IAAmBU,OAAAA,CAAQX,QAAQ,CAACC,eAAe;AACrE,QAAA,MAAMe,UAAAA,GAAaL,OAAAA,CAAQX,QAAQ,CAACgB,UAAU;AAC9C,QAAA,MAAMC,QAAAA,GAAWN,OAAAA,CAAQX,QAAQ,CAACiB,QAAQ;;AAG1C,QAAA,IAAI,CAACF,SAAAA,IAAa,OAAOA,SAAAA,KAAc,QAAA,EAAU;AAC7C,YAAA,MAAM,IAAIb,KAAAA,CAAM,CAAC,oDAAoD,EAAE,OAAOa,SAAAA,CAAU,EAAE,EAAEZ,IAAAA,CAAKC,SAAS,CAACW,SAAAA,CAAAA,CAAW,CAAC,CAAC,CAAA;AAC5H;AAEAN,QAAAA,MAAAA,CAAOS,OAAO,CAAC,CAAC,kCAAkC,EAAEH,SAAAA,CAAAA,CAAW,CAAA;;QAG/D,MAAMI,OAAAA,GAAUC,QAAc,CAAC;AAAEC,YAAAA,GAAAA,EAAKZ,OAAOa;AAAM,SAAA,CAAA;;AAGnD,QAAA,MAAMC,SAAAA,GAAY,MAAMJ,OAAAA,CAAQK,MAAM,CAACT,SAAAA,CAAAA;AACvC,QAAA,IAAI,CAACQ,SAAAA,EAAW;AACZd,YAAAA,MAAAA,CAAOgB,IAAI,CAAC,CAAC,kCAAkC,EAAEV,SAAAA,CAAAA,CAAW,CAAA;YAC5D,IAAI;gBACA,MAAMI,OAAAA,CAAQO,eAAe,CAACX,SAAAA,CAAAA;AAClC,aAAA,CAAE,OAAOY,KAAAA,EAAY;gBACjB,MAAMC,eAAAA,CAAgBC,uBAAuB,CAACd,SAAAA,EAAWY,KAAAA,CAAAA;AAC7D;AACJ;;AAGA,QAAA,MAAMG,UAAAA,GAAa,MAAMX,OAAAA,CAAQY,mBAAmB,CAAChB,SAAAA,CAAAA;AACrD,QAAA,IAAI,CAACe,UAAAA,EAAY;AACb,YAAA,MAAM,IAAIF,eAAAA,CAAgB,cAAA,EAAgB,yCAAA,EAA2Cb,SAAAA,EAAW,iBAAA,CAAA;AACpG;;AAGA,QAAA,MAAMiB,cAAAA,GAAiBC,IAAAA,CAAKC,IAAI,CAACnB,SAAAA,EAAWC,UAAAA,CAAAA;;AAG5CP,QAAAA,MAAAA,CAAOa,KAAK,CAAC,CAAC,0CAA0C,EAAEa,MAAAA,CAAOC,IAAI,CAACzB,OAAAA,CAAQH,WAAW,CAAA,CAAE0B,IAAI,CAAC,IAAA,CAAA,CAAA,CAAO,CAAA;AACvG,QAAA,MAAMG,aAAAA,GAAgBC,qBAAAA,CAAsB3B,OAAAA,CAAQH,WAAaO,CAAAA;QACjEN,MAAAA,CAAOa,KAAK,CAAC,CAAC,0BAA0B,EAAEnB,KAAKC,SAAS,CAACiC,aAAAA,EAAe,IAAA,EAAM,CAAA,CAAA,CAAA,CAAI,CAAA;;AAGlF,QAAA,MAAME,WAAAA,GAAcC,IAAAA,CAAKC,IAAI,CAACJ,aAAAA,EAAe;YACzCK,MAAAA,EAAQ,CAAA;YACRC,SAAAA,EAAW,GAAA;YACXC,MAAAA,EAAQ,IAAA;YACRC,QAAAA,EAAU;AACd,SAAA,CAAA;;AAGA,QAAA,MAAMC,SAAS,CAAC;;;;;;;AAOxB,CAAC;AAEO,QAAA,MAAMC,eAAeD,MAAAA,GAASP,WAAAA;;AAG9B,QAAA,MAAMS,YAAAA,GAAe,MAAM7B,OAAAA,CAAQK,MAAM,CAACQ,cAAAA,CAAAA;AAC1C,QAAA,IAAIgB,YAAAA,EAAc;AACdvC,YAAAA,MAAAA,CAAOwC,IAAI,CAAC,CAAC,mCAAmC,EAAEjB,cAAAA,CAAAA,CAAgB,CAAA;AAClEvB,YAAAA,MAAAA,CAAOwC,IAAI,CAAC,8GAAA,CAAA;AACZxC,YAAAA,MAAAA,CAAOgB,IAAI,CAAC,IAAA,GAAO,GAAA,CAAIyB,MAAM,CAAC,EAAA,CAAA,CAAA;YAC9BzC,MAAAA,CAAOgB,IAAI,CAACsB,YAAAA,CAAaI,IAAI,EAAA,CAAA;AAC7B1C,YAAAA,MAAAA,CAAOgB,IAAI,CAAC,GAAA,CAAIyB,MAAM,CAAC,EAAA,CAAA,CAAA;AACvB,YAAA;AACJ;;QAGA,IAAI;AACA,YAAA,MAAM/B,OAAAA,CAAQiC,SAAS,CAACpB,cAAAA,EAAgBe,YAAAA,EAAc9B,QAAAA,CAAAA;AACtDR,YAAAA,MAAAA,CAAOgB,IAAI,CAAC,CAAC,2CAA2C,EAAEO,cAAAA,CAAAA,CAAgB,CAAA;AAC9E,SAAA,CAAE,OAAOL,KAAAA,EAAY;AACjB,YAAA,MAAMC,eAAAA,CAAgByB,eAAe,CAAC,0BAAA,EAA4BrB,cAAAA,EAAgBL,KAAAA,CAAAA;AACtF;AACJ,KAAA;IAEA,OAAO;AACHf,QAAAA,SAAAA;QACA0C,SAAAA,EAAW,CAACC,OAAAA,GAAqBD,SAAAA,CAAUC,OAAAA,EAAS5C,OAAAA,CAAAA;QACpD6C,QAAAA,EAAU,CAACC,MAAAA,GAA8DD,QAAAA,CAASC,MAAAA,EAAQ9C,OAAAA,CAAAA;QAC1F+C,IAAAA,EAAM,CAACC,IAAAA,GAAeD,IAAAA,CAAKC,IAAAA,EAAMhD,OAAAA,CAAAA;AACjCG,QAAAA,cAAAA;QACA8C,WAAAA,EAAa,CAACD,IAAAA,GAAeC,WAAAA,CAAYD,IAAAA,EAAMhD,OAAAA;AACnD,KAAA;AACJ;;;;"}
@@ -29,6 +29,11 @@ import { z } from 'zod';
29
29
  * ```
30
30
  */
31
31
  export declare const extractSchemaDefaults: (schema: z.ZodTypeAny) => any;
32
+ /**
33
+ * Extracts meaningful defaults for config file generation, including sensible defaults for optional fields.
34
+ * This is more generous than extractSchemaDefaults for the purpose of creating helpful config files.
35
+ */
36
+ export declare const extractConfigFileDefaults: (schema: z.ZodTypeAny) => any;
32
37
  /**
33
38
  * Generates a complete configuration object with all default values populated.
34
39
  *
@@ -34,10 +34,17 @@ import { z } from 'zod';
34
34
  const defaultSchema = schema;
35
35
  return defaultSchema._def.defaultValue();
36
36
  }
37
- // Handle ZodOptional and ZodNullable - unwrap and recurse
37
+ // Handle ZodOptional and ZodNullable - only recurse if there's an explicit default
38
38
  if (schema._def && (schema._def.typeName === 'ZodOptional' || schema._def.typeName === 'ZodNullable')) {
39
39
  const unwrappable = schema;
40
- return extractSchemaDefaults(unwrappable.unwrap());
40
+ const unwrapped = unwrappable.unwrap();
41
+ // Only provide defaults if the unwrapped schema has explicit defaults
42
+ // This prevents optional arrays/objects from automatically getting [] or {} defaults
43
+ if (unwrapped._def && unwrapped._def.typeName === 'ZodDefault') {
44
+ return extractSchemaDefaults(unwrapped);
45
+ }
46
+ // For optional fields without explicit defaults, return undefined
47
+ return undefined;
41
48
  }
42
49
  // Handle ZodObject - recursively process shape
43
50
  if (schema._def && schema._def.typeName === 'ZodObject') {
@@ -96,7 +103,7 @@ import { z } from 'zod';
96
103
  const fullSchema = z.object({
97
104
  ...configShape
98
105
  });
99
- // Extract defaults from the full schema
106
+ // Extract defaults from the full schema using only explicit defaults
100
107
  const defaults = extractSchemaDefaults(fullSchema);
101
108
  // Don't include configDirectory in the generated file since it's runtime-specific
102
109
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1 +1 @@
1
- {"version":3,"file":"schema-defaults.js","sources":["../../src/util/schema-defaults.ts"],"sourcesContent":["import { z, ZodObject } from 'zod';\n\n/**\n * Extracts default values from a Zod schema recursively.\n * \n * This function traverses a Zod schema and builds an object containing\n * all the default values defined in the schema. It handles:\n * - ZodDefault types with explicit default values\n * - ZodOptional/ZodNullable types by unwrapping them\n * - ZodObject types by recursively processing their shape\n * - ZodArray types by providing an empty array as default\n * \n * @param schema - The Zod schema to extract defaults from\n * @returns An object containing all default values from the schema\n * \n * @example\n * ```typescript\n * const schema = z.object({\n * name: z.string().default('app'),\n * port: z.number().default(3000),\n * debug: z.boolean().default(false),\n * database: z.object({\n * host: z.string().default('localhost'),\n * port: z.number().default(5432)\n * })\n * });\n * \n * const defaults = extractSchemaDefaults(schema);\n * // Returns: { name: 'app', port: 3000, debug: false, database: { host: 'localhost', port: 5432 } }\n * ```\n */\nexport const extractSchemaDefaults = (schema: z.ZodTypeAny): any => {\n // Handle ZodDefault - extract the default value\n if (schema._def && schema._def.typeName === 'ZodDefault') {\n const defaultSchema = schema as z.ZodDefault<any>;\n return defaultSchema._def.defaultValue();\n }\n\n // Handle ZodOptional and ZodNullable - unwrap and recurse\n if (schema._def && (schema._def.typeName === 'ZodOptional' || schema._def.typeName === 'ZodNullable')) {\n const unwrappable = schema as z.ZodOptional<any> | z.ZodNullable<any>;\n return extractSchemaDefaults(unwrappable.unwrap());\n }\n\n // Handle ZodObject - recursively process shape\n if (schema._def && schema._def.typeName === 'ZodObject') {\n const objectSchema = schema as z.ZodObject<any>;\n const result: any = {};\n\n for (const [key, subschema] of Object.entries(objectSchema.shape)) {\n const defaultValue = extractSchemaDefaults(subschema as z.ZodTypeAny);\n if (defaultValue !== undefined) {\n result[key] = defaultValue;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n }\n\n // Handle ZodArray - provide empty array as default\n if (schema._def && schema._def.typeName === 'ZodArray') {\n const arraySchema = schema as z.ZodArray<any>;\n const elementDefaults = extractSchemaDefaults(arraySchema.element);\n // Return an empty array, or an array with one example element if it has defaults\n return elementDefaults !== undefined ? [elementDefaults] : [];\n }\n\n // Handle ZodRecord - provide empty object as default\n if (schema._def && schema._def.typeName === 'ZodRecord') {\n return {};\n }\n\n // For other types, return undefined (no default available)\n return undefined;\n};\n\n/**\n * Generates a complete configuration object with all default values populated.\n * \n * This function combines the base ConfigSchema with a user-provided schema shape\n * and extracts all available default values to create a complete configuration\n * example that can be serialized to YAML.\n * \n * @template T - The Zod schema shape type\n * @param configShape - The user's configuration schema shape\n * @param configDirectory - The configuration directory to include in the defaults\n * @returns An object containing all default values suitable for YAML serialization\n * \n * @example\n * ```typescript\n * const shape = z.object({\n * apiKey: z.string().describe('Your API key'),\n * timeout: z.number().default(5000).describe('Request timeout in milliseconds'),\n * features: z.array(z.string()).default(['auth', 'logging'])\n * }).shape;\n * \n * const config = generateDefaultConfig(shape, './config');\n * // Returns: { timeout: 5000, features: ['auth', 'logging'] }\n * // Note: apiKey is not included since it has no default\n * ```\n */\nexport const generateDefaultConfig = <T extends z.ZodRawShape>(\n configShape: T,\n configDirectory: string\n): Record<string, any> => {\n // Create the full schema by combining base and user schema\n const fullSchema = z.object({\n ...configShape,\n });\n\n // Extract defaults from the full schema\n const defaults = extractSchemaDefaults(fullSchema);\n\n // Don't include configDirectory in the generated file since it's runtime-specific\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { configDirectory: _, ...configDefaults } = defaults || {};\n\n return configDefaults || {};\n}; "],"names":["extractSchemaDefaults","schema","_def","typeName","defaultSchema","defaultValue","unwrappable","unwrap","objectSchema","result","key","subschema","Object","entries","shape","undefined","keys","length","arraySchema","elementDefaults","element","generateDefaultConfig","configShape","configDirectory","fullSchema","z","object","defaults","_","configDefaults"],"mappings":";;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BO,MAAMA,qBAAAA,GAAwB,CAACC,MAAAA,GAAAA;;IAElC,IAAIA,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,YAAA,EAAc;AACtD,QAAA,MAAMC,aAAAA,GAAgBH,MAAAA;QACtB,OAAOG,aAAAA,CAAcF,IAAI,CAACG,YAAY,EAAA;AAC1C;;AAGA,IAAA,IAAIJ,OAAOC,IAAI,KAAKD,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,aAAA,IAAiBF,OAAOC,IAAI,CAACC,QAAQ,KAAK,aAAY,CAAA,EAAI;AACnG,QAAA,MAAMG,WAAAA,GAAcL,MAAAA;QACpB,OAAOD,qBAAAA,CAAsBM,YAAYC,MAAM,EAAA,CAAA;AACnD;;IAGA,IAAIN,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,WAAA,EAAa;AACrD,QAAA,MAAMK,YAAAA,GAAeP,MAAAA;AACrB,QAAA,MAAMQ,SAAc,EAAC;QAErB,KAAK,MAAM,CAACC,GAAAA,EAAKC,SAAAA,CAAU,IAAIC,OAAOC,OAAO,CAACL,YAAAA,CAAaM,KAAK,CAAA,CAAG;AAC/D,YAAA,MAAMT,eAAeL,qBAAAA,CAAsBW,SAAAA,CAAAA;AAC3C,YAAA,IAAIN,iBAAiBU,SAAAA,EAAW;gBAC5BN,MAAM,CAACC,IAAI,GAAGL,YAAAA;AAClB;AACJ;AAEA,QAAA,OAAOO,OAAOI,IAAI,CAACP,QAAQQ,MAAM,GAAG,IAAIR,MAAAA,GAASM,SAAAA;AACrD;;IAGA,IAAId,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,UAAA,EAAY;AACpD,QAAA,MAAMe,WAAAA,GAAcjB,MAAAA;QACpB,MAAMkB,eAAAA,GAAkBnB,qBAAAA,CAAsBkB,WAAAA,CAAYE,OAAO,CAAA;;AAEjE,QAAA,OAAOD,oBAAoBJ,SAAAA,GAAY;AAACI,YAAAA;AAAgB,SAAA,GAAG,EAAE;AACjE;;IAGA,IAAIlB,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,WAAA,EAAa;AACrD,QAAA,OAAO,EAAC;AACZ;;IAGA,OAAOY,SAAAA;AACX;AAEA;;;;;;;;;;;;;;;;;;;;;;;;AAwBC,IACM,MAAMM,qBAAAA,GAAwB,CACjCC,WAAAA,EACAC,eAAAA,GAAAA;;IAGA,MAAMC,UAAAA,GAAaC,CAAAA,CAAEC,MAAM,CAAC;AACxB,QAAA,GAAGJ;AACP,KAAA,CAAA;;AAGA,IAAA,MAAMK,WAAW3B,qBAAAA,CAAsBwB,UAAAA,CAAAA;;;IAIvC,MAAM,EAAED,iBAAiBK,CAAC,EAAE,GAAGC,cAAAA,EAAgB,GAAGF,YAAY,EAAC;AAE/D,IAAA,OAAOE,kBAAkB,EAAC;AAC9B;;;;"}
1
+ {"version":3,"file":"schema-defaults.js","sources":["../../src/util/schema-defaults.ts"],"sourcesContent":["import { z, ZodObject } from 'zod';\n\n/**\n * Extracts default values from a Zod schema recursively.\n * \n * This function traverses a Zod schema and builds an object containing\n * all the default values defined in the schema. It handles:\n * - ZodDefault types with explicit default values\n * - ZodOptional/ZodNullable types by unwrapping them\n * - ZodObject types by recursively processing their shape\n * - ZodArray types by providing an empty array as default\n * \n * @param schema - The Zod schema to extract defaults from\n * @returns An object containing all default values from the schema\n * \n * @example\n * ```typescript\n * const schema = z.object({\n * name: z.string().default('app'),\n * port: z.number().default(3000),\n * debug: z.boolean().default(false),\n * database: z.object({\n * host: z.string().default('localhost'),\n * port: z.number().default(5432)\n * })\n * });\n * \n * const defaults = extractSchemaDefaults(schema);\n * // Returns: { name: 'app', port: 3000, debug: false, database: { host: 'localhost', port: 5432 } }\n * ```\n */\nexport const extractSchemaDefaults = (schema: z.ZodTypeAny): any => {\n // Handle ZodDefault - extract the default value\n if (schema._def && schema._def.typeName === 'ZodDefault') {\n const defaultSchema = schema as z.ZodDefault<any>;\n return defaultSchema._def.defaultValue();\n }\n\n // Handle ZodOptional and ZodNullable - only recurse if there's an explicit default\n if (schema._def && (schema._def.typeName === 'ZodOptional' || schema._def.typeName === 'ZodNullable')) {\n const unwrappable = schema as z.ZodOptional<any> | z.ZodNullable<any>;\n const unwrapped = unwrappable.unwrap();\n\n // Only provide defaults if the unwrapped schema has explicit defaults\n // This prevents optional arrays/objects from automatically getting [] or {} defaults\n if (unwrapped._def && unwrapped._def.typeName === 'ZodDefault') {\n return extractSchemaDefaults(unwrapped);\n }\n\n // For optional fields without explicit defaults, return undefined\n return undefined;\n }\n\n // Handle ZodObject - recursively process shape\n if (schema._def && schema._def.typeName === 'ZodObject') {\n const objectSchema = schema as z.ZodObject<any>;\n const result: any = {};\n\n for (const [key, subschema] of Object.entries(objectSchema.shape)) {\n const defaultValue = extractSchemaDefaults(subschema as z.ZodTypeAny);\n if (defaultValue !== undefined) {\n result[key] = defaultValue;\n }\n }\n\n return Object.keys(result).length > 0 ? result : undefined;\n }\n\n // Handle ZodArray - provide empty array as default\n if (schema._def && schema._def.typeName === 'ZodArray') {\n const arraySchema = schema as z.ZodArray<any>;\n const elementDefaults = extractSchemaDefaults(arraySchema.element);\n // Return an empty array, or an array with one example element if it has defaults\n return elementDefaults !== undefined ? [elementDefaults] : [];\n }\n\n // Handle ZodRecord - provide empty object as default\n if (schema._def && schema._def.typeName === 'ZodRecord') {\n return {};\n }\n\n // For other types, return undefined (no default available)\n return undefined;\n};\n\n/**\n * Extracts meaningful defaults for config file generation, including sensible defaults for optional fields.\n * This is more generous than extractSchemaDefaults for the purpose of creating helpful config files.\n */\nexport const extractConfigFileDefaults = (schema: z.ZodTypeAny): any => {\n // Handle ZodDefault - extract the default value\n if (schema._def && schema._def.typeName === 'ZodDefault') {\n const defaultSchema = schema as z.ZodDefault<any>;\n return defaultSchema._def.defaultValue();\n }\n\n // Handle ZodOptional and ZodNullable - provide sensible defaults for config generation\n if (schema._def && (schema._def.typeName === 'ZodOptional' || schema._def.typeName === 'ZodNullable')) {\n const unwrappable = schema as z.ZodOptional<any> | z.ZodNullable<any>;\n const unwrapped = unwrappable.unwrap();\n\n // Recurse into the unwrapped schema to get its default or provide a sensible one\n const unwrappedDefault = extractConfigFileDefaults(unwrapped);\n if (unwrappedDefault !== undefined) {\n return unwrappedDefault;\n }\n\n // Provide sensible defaults for common types when generating config files\n if (unwrapped._def) {\n switch (unwrapped._def.typeName) {\n case 'ZodBoolean':\n return false;\n case 'ZodNumber':\n return 0;\n case 'ZodString':\n return '';\n case 'ZodArray':\n return [];\n case 'ZodRecord':\n return {};\n case 'ZodObject':\n return extractConfigFileDefaults(unwrapped);\n }\n }\n\n return undefined;\n }\n\n // Handle ZodObject - recursively process shape\n if (schema._def && schema._def.typeName === 'ZodObject') {\n const objectSchema = schema as z.ZodObject<any>;\n const result: any = {};\n\n for (const [key, subschema] of Object.entries(objectSchema.shape)) {\n const defaultValue = extractConfigFileDefaults(subschema as z.ZodTypeAny);\n if (defaultValue !== undefined) {\n result[key] = defaultValue;\n }\n }\n\n return Object.keys(result).length > 0 ? result : {};\n }\n\n // Handle ZodArray - provide empty array as default\n if (schema._def && schema._def.typeName === 'ZodArray') {\n return [];\n }\n\n // Handle ZodRecord - provide empty object as default\n if (schema._def && schema._def.typeName === 'ZodRecord') {\n return {};\n }\n\n // For other types, return undefined (no default available)\n return undefined;\n};\n\n/**\n * Generates a complete configuration object with all default values populated.\n * \n * This function combines the base ConfigSchema with a user-provided schema shape\n * and extracts all available default values to create a complete configuration\n * example that can be serialized to YAML.\n * \n * @template T - The Zod schema shape type\n * @param configShape - The user's configuration schema shape\n * @param configDirectory - The configuration directory to include in the defaults\n * @returns An object containing all default values suitable for YAML serialization\n * \n * @example\n * ```typescript\n * const shape = z.object({\n * apiKey: z.string().describe('Your API key'),\n * timeout: z.number().default(5000).describe('Request timeout in milliseconds'),\n * features: z.array(z.string()).default(['auth', 'logging'])\n * }).shape;\n * \n * const config = generateDefaultConfig(shape, './config');\n * // Returns: { timeout: 5000, features: ['auth', 'logging'] }\n * // Note: apiKey is not included since it has no default\n * ```\n */\nexport const generateDefaultConfig = <T extends z.ZodRawShape>(\n configShape: T,\n configDirectory: string\n): Record<string, any> => {\n // Create the full schema by combining base and user schema\n const fullSchema = z.object({\n ...configShape,\n });\n\n // Extract defaults from the full schema using only explicit defaults\n const defaults = extractSchemaDefaults(fullSchema);\n\n // Don't include configDirectory in the generated file since it's runtime-specific\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { configDirectory: _, ...configDefaults } = defaults || {};\n\n return configDefaults || {};\n}; "],"names":["extractSchemaDefaults","schema","_def","typeName","defaultSchema","defaultValue","unwrappable","unwrapped","unwrap","undefined","objectSchema","result","key","subschema","Object","entries","shape","keys","length","arraySchema","elementDefaults","element","generateDefaultConfig","configShape","configDirectory","fullSchema","z","object","defaults","_","configDefaults"],"mappings":";;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BO,MAAMA,qBAAAA,GAAwB,CAACC,MAAAA,GAAAA;;IAElC,IAAIA,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,YAAA,EAAc;AACtD,QAAA,MAAMC,aAAAA,GAAgBH,MAAAA;QACtB,OAAOG,aAAAA,CAAcF,IAAI,CAACG,YAAY,EAAA;AAC1C;;AAGA,IAAA,IAAIJ,OAAOC,IAAI,KAAKD,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,aAAA,IAAiBF,OAAOC,IAAI,CAACC,QAAQ,KAAK,aAAY,CAAA,EAAI;AACnG,QAAA,MAAMG,WAAAA,GAAcL,MAAAA;QACpB,MAAMM,SAAAA,GAAYD,YAAYE,MAAM,EAAA;;;QAIpC,IAAID,SAAAA,CAAUL,IAAI,IAAIK,SAAAA,CAAUL,IAAI,CAACC,QAAQ,KAAK,YAAA,EAAc;AAC5D,YAAA,OAAOH,qBAAAA,CAAsBO,SAAAA,CAAAA;AACjC;;QAGA,OAAOE,SAAAA;AACX;;IAGA,IAAIR,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,WAAA,EAAa;AACrD,QAAA,MAAMO,YAAAA,GAAeT,MAAAA;AACrB,QAAA,MAAMU,SAAc,EAAC;QAErB,KAAK,MAAM,CAACC,GAAAA,EAAKC,SAAAA,CAAU,IAAIC,OAAOC,OAAO,CAACL,YAAAA,CAAaM,KAAK,CAAA,CAAG;AAC/D,YAAA,MAAMX,eAAeL,qBAAAA,CAAsBa,SAAAA,CAAAA;AAC3C,YAAA,IAAIR,iBAAiBI,SAAAA,EAAW;gBAC5BE,MAAM,CAACC,IAAI,GAAGP,YAAAA;AAClB;AACJ;AAEA,QAAA,OAAOS,OAAOG,IAAI,CAACN,QAAQO,MAAM,GAAG,IAAIP,MAAAA,GAASF,SAAAA;AACrD;;IAGA,IAAIR,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,UAAA,EAAY;AACpD,QAAA,MAAMgB,WAAAA,GAAclB,MAAAA;QACpB,MAAMmB,eAAAA,GAAkBpB,qBAAAA,CAAsBmB,WAAAA,CAAYE,OAAO,CAAA;;AAEjE,QAAA,OAAOD,oBAAoBX,SAAAA,GAAY;AAACW,YAAAA;AAAgB,SAAA,GAAG,EAAE;AACjE;;IAGA,IAAInB,MAAAA,CAAOC,IAAI,IAAID,MAAAA,CAAOC,IAAI,CAACC,QAAQ,KAAK,WAAA,EAAa;AACrD,QAAA,OAAO,EAAC;AACZ;;IAGA,OAAOM,SAAAA;AACX;AA0EA;;;;;;;;;;;;;;;;;;;;;;;;AAwBC,IACM,MAAMa,qBAAAA,GAAwB,CACjCC,WAAAA,EACAC,eAAAA,GAAAA;;IAGA,MAAMC,UAAAA,GAAaC,CAAAA,CAAEC,MAAM,CAAC;AACxB,QAAA,GAAGJ;AACP,KAAA,CAAA;;AAGA,IAAA,MAAMK,WAAW5B,qBAAAA,CAAsByB,UAAAA,CAAAA;;;IAIvC,MAAM,EAAED,iBAAiBK,CAAC,EAAE,GAAGC,cAAAA,EAAgB,GAAGF,YAAY,EAAC;AAE/D,IAAA,OAAOE,kBAAkB,EAAC;AAC9B;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theunwalked/cardigantime",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "cardigantime is a tool to help you time your cardigans.",
5
5
  "type": "module",
6
6
  "main": "./dist/cardigantime.cjs",
@@ -43,7 +43,7 @@
43
43
  "@eslint/eslintrc": "^3.3.1",
44
44
  "@eslint/js": "^9.30.0",
45
45
  "@rollup/plugin-replace": "^6.0.2",
46
- "@swc/core": "^1.12.7",
46
+ "@swc/core": "^1.12.9",
47
47
  "@types/js-yaml": "^4.0.9",
48
48
  "@types/luxon": "^3.6.2",
49
49
  "@types/node": "^24.0.8",
@@ -52,7 +52,7 @@
52
52
  "@vitest/coverage-v8": "^3.2.4",
53
53
  "eslint": "^9.30.0",
54
54
  "eslint-plugin-import": "^2.32.0",
55
- "globals": "^16.2.0",
55
+ "globals": "^16.3.0",
56
56
  "typescript": "^5.8.3",
57
57
  "vite": "^7.0.0",
58
58
  "vite-plugin-dts": "^4.5.4",