@nmakarov/cli-toolkit 0.8.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/args.cjs +20 -9
- package/dist/args.cjs.map +1 -1
- package/dist/args.js +20 -9
- package/dist/args.js.map +1 -1
- package/dist/index.cjs +21 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -10
- package/dist/index.js.map +1 -1
- package/dist/init.cjs +21 -10
- package/dist/init.cjs.map +1 -1
- package/dist/init.js +21 -10
- package/dist/init.js.map +1 -1
- package/dist/logger.cjs +1 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/params.cjs.map +1 -1
- package/dist/params.js.map +1 -1
- package/package.json +1 -1
package/dist/logger.cjs
CHANGED
package/dist/logger.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger/index.ts","../src/logger/transports.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport util from \"util\";\n\nimport {\n Logger,\n LoggerOptions,\n LoggerProgressOptions,\n LogPayload,\n LevelName,\n LoggerTransport,\n LoggerMode\n} from \"./types.js\";\nimport { ConsoleTransport, ParentProcessTransport } from \"./transports.js\";\nimport type { Context } from \"../init/types.js\";\n\nconst ALL_LEVELS: LevelName[] = [\n \"silly\",\n \"debug\",\n \"logic\",\n \"info\",\n \"notice\",\n \"warn\",\n \"error\",\n \"results\",\n \"request\",\n \"response\",\n \"progress\"\n];\n\n// Calculate maximum level name length for alignment\nconst MAX_LEVEL_LENGTH = Math.max(...ALL_LEVELS.map(level => level.toUpperCase().length));\n\nconst LEVEL_COLORS: Record<LevelName, chalk.Chalk> = {\n error: chalk.red.bold,\n warn: chalk.rgb(255, 165, 0),\n notice: chalk.cyan,\n info: chalk.white.bold,\n logic: chalk.gray,\n debug: chalk.gray,\n silly: chalk.gray,\n request: chalk.green,\n response: chalk.yellow,\n progress: chalk.green,\n results: chalk.magenta\n};\n\ninterface NormalizedOptions {\n mode: LoggerMode;\n route: \"console\" | \"ipc\";\n prefix?: string;\n silent: boolean;\n showLevel: boolean;\n timestamp: boolean;\n levels: LevelName[];\n progressTimes: boolean;\n progressThrottle?: number;\n}\n\nexport class Logger implements Logger {\n private context: any; // Partial context during initialization\n private options: NormalizedOptions;\n private transport: LoggerTransport;\n private readonly startTimes: Record<string, number> = {};\n private readonly lastProgressTimes: Record<string, number> = {};\n\n constructor(context: any, options: LoggerOptions = {}) {\n this.context = context;\n // Set defaults first\n this.options = this.getDefaultOptions();\n // Apply configuration\n if (options) {\n this.configure(options);\n }\n // Initialize transport\n this.updateTransport();\n }\n\n /**\n * Configure logger options\n * Only parameters present in options are updated\n */\n configure(options: Partial<LoggerOptions>): void {\n if (options.mode !== undefined) {\n this.options.mode = this.isValidMode(options.mode) ? options.mode : \"text\";\n }\n if (options.route !== undefined) {\n this.options.route = options.route;\n this.updateTransport();\n }\n if (options.prefix !== undefined) {\n this.options.prefix = options.prefix;\n }\n if (options.silent !== undefined) {\n this.options.silent = options.silent;\n }\n if (options.showLevel !== undefined) {\n this.options.showLevel = options.showLevel;\n }\n if (options.timestamp !== undefined) {\n this.options.timestamp = options.timestamp;\n }\n if (options.levels !== undefined) {\n this.options.levels = this.normalizeLevels(options.levels);\n }\n if (options.progress !== undefined) {\n if (options.progress.withTimes !== undefined) {\n this.options.progressTimes = options.progress.withTimes;\n }\n if (options.progress.throttleMs !== undefined) {\n this.options.progressThrottle = options.progress.throttleMs;\n }\n }\n }\n\n /**\n * Initialize logger from context and CLI parameters\n */\n static init(context: any, options?: LoggerOptions): Logger {\n // Define parameter definitions for CLI (with defaults to make them optional)\n const paramDefs = {\n mode: \"string default text\",\n route: \"string default console\",\n prefix: \"string\",\n silent: \"boolean default false\",\n showLevel: \"boolean default true\",\n timestamp: \"boolean default false\",\n levels: \"string\",\n progressWithTimes: \"boolean default false\",\n progressThrottleMs: \"number\",\n };\n\n // Collect parameters from CLI\n const cliParams = context.params.getAll(paramDefs);\n\n // Merge CLI params with options (options take precedence)\n const config: LoggerOptions = {\n mode: options?.mode ?? cliParams.mode,\n route: options?.route ?? cliParams.route,\n prefix: options?.prefix ?? cliParams.prefix,\n silent: options?.silent ?? cliParams.silent,\n showLevel: options?.showLevel ?? cliParams.showLevel,\n timestamp: options?.timestamp ?? cliParams.timestamp,\n levels: options?.levels ?? (cliParams.levels ? cliParams.levels.split(\",\") : undefined),\n progress: options?.progress ?? {\n withTimes: cliParams.progressWithTimes,\n throttleMs: cliParams.progressThrottleMs,\n },\n };\n\n\n // Create and return instance\n const logger = new Logger(context, config);\n context.logger = logger; // Update context with the new logger instance\n return logger;\n }\n\n private getDefaultOptions(): NormalizedOptions {\n return {\n mode: \"text\",\n route: this.shouldUseIpcRoute() ? \"ipc\" : \"console\",\n prefix: undefined,\n silent: false,\n showLevel: true,\n timestamp: false,\n levels: ALL_LEVELS,\n progressTimes: false,\n progressThrottle: undefined,\n };\n }\n\n private updateTransport(): void {\n this.transport = this.options.route === \"ipc\"\n ? new ParentProcessTransport()\n : new ConsoleTransport();\n }\n\n setMode(mode: LoggerMode): void {\n if (!this.isValidMode(mode)) {\n throw new Error(`Unsupported logger mode: ${mode}`);\n }\n this.options.mode = mode;\n }\n\n debug(message?: any, ...chunks: any[]): void {\n this.out({ level: \"debug\", message, chunks });\n }\n\n info(message?: any, ...chunks: any[]): void {\n this.out({ level: \"info\", message, chunks });\n }\n\n notice(message?: any, ...chunks: any[]): void {\n this.out({ level: \"notice\", message, chunks });\n }\n\n warn(message?: any, ...chunks: any[]): void {\n this.out({ level: \"warn\", message, chunks });\n }\n\n error(message?: any, ...chunks: any[]): void {\n this.out({ level: \"error\", message, chunks });\n }\n\n logic(message?: any, ...chunks: any[]): void {\n this.out({ level: \"logic\", message, chunks });\n }\n\n silly(message?: any, ...chunks: any[]): void {\n this.out({ level: \"silly\", message, chunks });\n }\n\n results(results: unknown): void {\n this.out({ level: \"results\", message: \"results\", results });\n }\n\n request(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"request\", message });\n }\n\n response(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"response\", message });\n }\n\n progress(message: string, opts: LoggerProgressOptions): void {\n const { prefix, count, total } = opts;\n const paddedTotal = String(total).length;\n const paddedCount = String(count).padStart(paddedTotal, \" \");\n const payload: LogPayload = {\n level: \"progress\",\n message,\n count: paddedCount,\n total,\n prefix\n };\n\n if (!this.startTimes[prefix ?? \"\"]) {\n this.startTimes[prefix ?? \"\"] = Date.now();\n }\n if (this.options.progressTimes) {\n const elapsedSeconds = (Date.now() - this.startTimes[prefix ?? \"\"]) / 1000;\n let remaining = -1;\n if (count > 1) {\n const rate = elapsedSeconds / (count - 1);\n remaining = (total - count) * rate;\n }\n payload.elapsed = this.round(elapsedSeconds, 2);\n payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;\n }\n\n if (count >= total) {\n delete this.startTimes[prefix ?? \"\"];\n delete this.lastProgressTimes[prefix ?? \"\"];\n }\n\n if (this.shouldOutputProgress(prefix ?? \"\", count, total)) {\n this.out(payload);\n if (this.options.progressThrottle && prefix) {\n this.lastProgressTimes[prefix] = Date.now();\n }\n }\n }\n\n private shouldOutputProgress(prefix: string, count: number, total: number): boolean {\n if (!this.options.progressThrottle) {\n return true;\n }\n if (count === 1 || count === total || !prefix) {\n return true;\n }\n const lastTime = this.lastProgressTimes[prefix];\n if (!lastTime) {\n return true;\n }\n return Date.now() - lastTime >= this.options.progressThrottle;\n }\n\n private out(struct: LogPayload): void {\n if (this.options.silent) {\n return;\n }\n if (!this.options.levels.includes(struct.level)) {\n return;\n }\n\n if (this.options.prefix && !struct.prefix) {\n struct.prefix = this.options.prefix;\n }\n\n const output = this.options.mode === \"json\"\n ? struct\n : this.formatLog(struct);\n\n this.transport.write(output);\n }\n\n private formatLog(struct: LogPayload): string {\n const parts: string[] = [];\n const now = new Date();\n\n if (this.options.timestamp) {\n parts.push(now.toISOString());\n }\n\n if (this.options.showLevel) {\n parts.push(struct.level.toUpperCase().padEnd(MAX_LEVEL_LENGTH));\n }\n\n if (struct.level === \"progress\") {\n if (struct.prefix) {\n parts.push(LEVEL_COLORS[struct.level].bold(struct.prefix));\n }\n if (struct.count !== undefined && struct.total !== undefined) {\n parts.push(LEVEL_COLORS[struct.level](`${struct.count}/${struct.total}`));\n }\n } else if (struct.prefix) {\n parts.push(chalk.cyan(`[${struct.prefix}]`));\n }\n\n if (struct.message) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter.bold(struct.message));\n }\n\n if (struct.level === \"progress\") {\n if (struct.elapsed !== undefined && struct.remaining !== undefined) {\n const formatter = LEVEL_COLORS[struct.level];\n parts.push(formatter(`${struct.elapsed}/${struct.remaining}`));\n }\n }\n\n if (struct.chunks && struct.chunks.length) {\n parts.push(this.inspectChunks(struct.chunks));\n }\n\n if (struct.results) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter(JSON.stringify(struct.results, null, 4)));\n }\n\n return parts.join(\" \");\n }\n\n private inspectChunks(chunks: any[]): string {\n return chunks\n .map(chunk => util.inspect(chunk, { colors: true, depth: null }))\n .join(\" \");\n }\n\n private shouldUseIpcRoute(): boolean {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n return false;\n }\n // Only use IPC if process.send exists AND we're connected to a parent\n // In Vitest workers, process.send exists but process.connected is undefined/false\n // process.connected is only true in actual child processes created with fork()\n return typeof process.send === \"function\" && process.connected === true;\n }\n\n private normalizeLevels(levels?: string[]): LevelName[] {\n if (!levels || !levels.length) {\n return ALL_LEVELS;\n }\n\n const includes = levels.filter(level => !level.startsWith(\"-\")) as LevelName[];\n const excludes = levels\n .filter(level => level.startsWith(\"-\"))\n .map(level => level.slice(1)) as LevelName[];\n\n const unknown = [...includes, ...excludes].filter(level => !ALL_LEVELS.includes(level));\n if (unknown.length) {\n console.warn(`[Logger] Unknown level(s): ${unknown.join(\", \")}`);\n }\n\n const base = includes.length ? includes : ALL_LEVELS;\n return base.filter(level => !excludes.includes(level));\n }\n\n private isValidMode(mode?: string | null): mode is LoggerMode | undefined {\n return mode === undefined || mode === null || mode === \"text\" || mode === \"json\";\n }\n\n private round(value: number, places: number): number {\n const factor = Math.pow(10, places);\n return Math.round(value * factor) / factor;\n }\n}\n\n","import { LoggerTransport } from \"./types.js\";\n\nexport class ConsoleTransport implements LoggerTransport {\n write(payload: any): void {\n console.info(payload);\n }\n}\n\nexport class ParentProcessTransport implements LoggerTransport {\n write(payload: any): void {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n console.info(payload);\n return;\n }\n // Only use process.send if we're actually connected to a parent process\n // In Vitest workers, process.send exists but shouldn't be used\n if (typeof process.send === \"function\" && process.connected === true) {\n process.send(payload);\n } else {\n console.info(payload);\n }\n }\n}\n\n\n"],"mappings":"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","names":["chalk","util"]}
|
|
1
|
+
{"version":3,"sources":["../src/logger/index.ts","../src/logger/transports.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport util from \"util\";\n\nimport {\n Logger,\n LoggerOptions,\n LoggerProgressOptions,\n LogPayload,\n LevelName,\n LoggerTransport,\n LoggerMode\n} from \"./types.js\";\nimport { ConsoleTransport, ParentProcessTransport } from \"./transports.js\";\nimport type { Context } from \"../init/types.js\";\n\nconst ALL_LEVELS: LevelName[] = [\n \"silly\",\n \"debug\",\n \"logic\",\n \"info\",\n \"notice\",\n \"warn\",\n \"error\",\n \"results\",\n \"request\",\n \"response\",\n \"progress\"\n];\n\n// Calculate maximum level name length for alignment\nconst MAX_LEVEL_LENGTH = Math.max(...ALL_LEVELS.map(level => level.toUpperCase().length));\n\nconst LEVEL_COLORS: Record<LevelName, chalk.Chalk> = {\n error: chalk.red.bold,\n warn: chalk.rgb(255, 165, 0),\n notice: chalk.cyan,\n info: chalk.white.bold,\n logic: chalk.gray,\n debug: chalk.gray,\n silly: chalk.gray,\n request: chalk.green,\n response: chalk.yellow,\n progress: chalk.green,\n results: chalk.magenta\n};\n\ninterface NormalizedOptions {\n mode: LoggerMode;\n route: \"console\" | \"ipc\";\n prefix?: string;\n silent: boolean;\n showLevel: boolean;\n timestamp: boolean;\n levels: LevelName[];\n progressTimes: boolean;\n progressThrottle?: number;\n}\n\nexport class Logger implements Logger {\n private context: any; // Partial context during initialization\n private options: NormalizedOptions;\n private transport: LoggerTransport;\n private readonly startTimes: Record<string, number> = {};\n private readonly lastProgressTimes: Record<string, number> = {};\n\n constructor(context: any, options: LoggerOptions = {}) {\n this.context = context;\n // Set defaults first\n this.options = this.getDefaultOptions();\n // Apply configuration\n if (options) {\n this.configure(options);\n }\n // Initialize transport\n this.updateTransport();\n }\n\n /**\n * Configure logger options\n * Only parameters present in options are updated\n */\n configure(options: Partial<LoggerOptions>): void {\n if (options.mode !== undefined) {\n this.options.mode = this.isValidMode(options.mode) ? options.mode : \"text\";\n }\n if (options.route !== undefined) {\n this.options.route = options.route;\n this.updateTransport();\n }\n if (options.prefix !== undefined) {\n this.options.prefix = options.prefix;\n }\n if (options.silent !== undefined) {\n this.options.silent = options.silent;\n }\n if (options.showLevel !== undefined) {\n this.options.showLevel = options.showLevel;\n }\n if (options.timestamp !== undefined) {\n this.options.timestamp = options.timestamp;\n }\n if (options.levels !== undefined) {\n this.options.levels = this.normalizeLevels(options.levels);\n }\n if (options.progress !== undefined) {\n if (options.progress.withTimes !== undefined) {\n this.options.progressTimes = options.progress.withTimes;\n }\n if (options.progress.throttleMs !== undefined) {\n this.options.progressThrottle = options.progress.throttleMs;\n }\n }\n }\n\n /**\n * Initialize logger from context and CLI parameters\n */\n static init(context: any, options?: LoggerOptions): Logger {\n // Define parameter definitions for CLI (with defaults to make them optional)\n const paramDefs = {\n mode: \"string default text\",\n route: \"string default console\",\n prefix: \"string\",\n silent: \"boolean default false\",\n showLevel: \"boolean default true\",\n timestamp: \"boolean default false\",\n levels: \"string\",\n progressWithTimes: \"boolean default false\",\n progressThrottleMs: \"number\",\n };\n\n // Collect parameters from CLI\n const cliParams = context.params.getAll(paramDefs);\n\n // Merge CLI params with options (options take precedence)\n const config: LoggerOptions = {\n mode: options?.mode ?? cliParams.mode,\n route: options?.route ?? cliParams.route,\n prefix: options?.prefix ?? cliParams.prefix,\n silent: options?.silent ?? cliParams.silent,\n showLevel: options?.showLevel ?? cliParams.showLevel,\n timestamp: options?.timestamp ?? cliParams.timestamp,\n levels: options?.levels ?? (cliParams.levels ? cliParams.levels.split(\",\") : undefined),\n progress: options?.progress ?? {\n withTimes: cliParams.progressWithTimes,\n throttleMs: cliParams.progressThrottleMs,\n },\n };\n\n\n // Create and return instance\n const logger = new Logger(context, config);\n context.logger = logger; // Update context with the new logger instance\n return logger;\n }\n\n private getDefaultOptions(): NormalizedOptions {\n return {\n mode: \"text\",\n route: this.shouldUseIpcRoute() ? \"ipc\" : \"console\",\n prefix: undefined,\n silent: false,\n showLevel: false,\n timestamp: false,\n levels: ALL_LEVELS,\n progressTimes: false,\n progressThrottle: undefined,\n };\n }\n\n private updateTransport(): void {\n this.transport = this.options.route === \"ipc\"\n ? new ParentProcessTransport()\n : new ConsoleTransport();\n }\n\n setMode(mode: LoggerMode): void {\n if (!this.isValidMode(mode)) {\n throw new Error(`Unsupported logger mode: ${mode}`);\n }\n this.options.mode = mode;\n }\n\n debug(message?: any, ...chunks: any[]): void {\n this.out({ level: \"debug\", message, chunks });\n }\n\n info(message?: any, ...chunks: any[]): void {\n this.out({ level: \"info\", message, chunks });\n }\n\n notice(message?: any, ...chunks: any[]): void {\n this.out({ level: \"notice\", message, chunks });\n }\n\n warn(message?: any, ...chunks: any[]): void {\n this.out({ level: \"warn\", message, chunks });\n }\n\n error(message?: any, ...chunks: any[]): void {\n this.out({ level: \"error\", message, chunks });\n }\n\n logic(message?: any, ...chunks: any[]): void {\n this.out({ level: \"logic\", message, chunks });\n }\n\n silly(message?: any, ...chunks: any[]): void {\n this.out({ level: \"silly\", message, chunks });\n }\n\n results(results: unknown): void {\n this.out({ level: \"results\", message: \"results\", results });\n }\n\n request(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"request\", message });\n }\n\n response(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"response\", message });\n }\n\n progress(message: string, opts: LoggerProgressOptions): void {\n const { prefix, count, total } = opts;\n const paddedTotal = String(total).length;\n const paddedCount = String(count).padStart(paddedTotal, \" \");\n const payload: LogPayload = {\n level: \"progress\",\n message,\n count: paddedCount,\n total,\n prefix\n };\n\n if (!this.startTimes[prefix ?? \"\"]) {\n this.startTimes[prefix ?? \"\"] = Date.now();\n }\n if (this.options.progressTimes) {\n const elapsedSeconds = (Date.now() - this.startTimes[prefix ?? \"\"]) / 1000;\n let remaining = -1;\n if (count > 1) {\n const rate = elapsedSeconds / (count - 1);\n remaining = (total - count) * rate;\n }\n payload.elapsed = this.round(elapsedSeconds, 2);\n payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;\n }\n\n if (count >= total) {\n delete this.startTimes[prefix ?? \"\"];\n delete this.lastProgressTimes[prefix ?? \"\"];\n }\n\n if (this.shouldOutputProgress(prefix ?? \"\", count, total)) {\n this.out(payload);\n if (this.options.progressThrottle && prefix) {\n this.lastProgressTimes[prefix] = Date.now();\n }\n }\n }\n\n private shouldOutputProgress(prefix: string, count: number, total: number): boolean {\n if (!this.options.progressThrottle) {\n return true;\n }\n if (count === 1 || count === total || !prefix) {\n return true;\n }\n const lastTime = this.lastProgressTimes[prefix];\n if (!lastTime) {\n return true;\n }\n return Date.now() - lastTime >= this.options.progressThrottle;\n }\n\n private out(struct: LogPayload): void {\n if (this.options.silent) {\n return;\n }\n if (!this.options.levels.includes(struct.level)) {\n return;\n }\n\n if (this.options.prefix && !struct.prefix) {\n struct.prefix = this.options.prefix;\n }\n\n const output = this.options.mode === \"json\"\n ? struct\n : this.formatLog(struct);\n\n this.transport.write(output);\n }\n\n private formatLog(struct: LogPayload): string {\n const parts: string[] = [];\n const now = new Date();\n\n if (this.options.timestamp) {\n parts.push(now.toISOString());\n }\n\n if (this.options.showLevel) {\n parts.push(struct.level.toUpperCase().padEnd(MAX_LEVEL_LENGTH));\n }\n\n if (struct.level === \"progress\") {\n if (struct.prefix) {\n parts.push(LEVEL_COLORS[struct.level].bold(struct.prefix));\n }\n if (struct.count !== undefined && struct.total !== undefined) {\n parts.push(LEVEL_COLORS[struct.level](`${struct.count}/${struct.total}`));\n }\n } else if (struct.prefix) {\n parts.push(chalk.cyan(`[${struct.prefix}]`));\n }\n\n if (struct.message) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter.bold(struct.message));\n }\n\n if (struct.level === \"progress\") {\n if (struct.elapsed !== undefined && struct.remaining !== undefined) {\n const formatter = LEVEL_COLORS[struct.level];\n parts.push(formatter(`${struct.elapsed}/${struct.remaining}`));\n }\n }\n\n if (struct.chunks && struct.chunks.length) {\n parts.push(this.inspectChunks(struct.chunks));\n }\n\n if (struct.results) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter(JSON.stringify(struct.results, null, 4)));\n }\n\n return parts.join(\" \");\n }\n\n private inspectChunks(chunks: any[]): string {\n return chunks\n .map(chunk => util.inspect(chunk, { colors: true, depth: null }))\n .join(\" \");\n }\n\n private shouldUseIpcRoute(): boolean {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n return false;\n }\n // Only use IPC if process.send exists AND we're connected to a parent\n // In Vitest workers, process.send exists but process.connected is undefined/false\n // process.connected is only true in actual child processes created with fork()\n return typeof process.send === \"function\" && process.connected === true;\n }\n\n private normalizeLevels(levels?: string[]): LevelName[] {\n if (!levels || !levels.length) {\n return ALL_LEVELS;\n }\n\n const includes = levels.filter(level => !level.startsWith(\"-\")) as LevelName[];\n const excludes = levels\n .filter(level => level.startsWith(\"-\"))\n .map(level => level.slice(1)) as LevelName[];\n\n const unknown = [...includes, ...excludes].filter(level => !ALL_LEVELS.includes(level));\n if (unknown.length) {\n console.warn(`[Logger] Unknown level(s): ${unknown.join(\", \")}`);\n }\n\n const base = includes.length ? includes : ALL_LEVELS;\n return base.filter(level => !excludes.includes(level));\n }\n\n private isValidMode(mode?: string | null): mode is LoggerMode | undefined {\n return mode === undefined || mode === null || mode === \"text\" || mode === \"json\";\n }\n\n private round(value: number, places: number): number {\n const factor = Math.pow(10, places);\n return Math.round(value * factor) / factor;\n }\n}\n\n","import { LoggerTransport } from \"./types.js\";\n\nexport class ConsoleTransport implements LoggerTransport {\n write(payload: any): void {\n console.info(payload);\n }\n}\n\nexport class ParentProcessTransport implements LoggerTransport {\n write(payload: any): void {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n console.info(payload);\n return;\n }\n // Only use process.send if we're actually connected to a parent process\n // In Vitest workers, process.send exists but shouldn't be used\n if (typeof process.send === \"function\" && process.connected === true) {\n process.send(payload);\n } else {\n console.info(payload);\n }\n }\n}\n\n\n"],"mappings":"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","names":["chalk","util"]}
|
package/dist/logger.js
CHANGED
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger/index.ts","../src/logger/transports.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport util from \"util\";\n\nimport {\n Logger,\n LoggerOptions,\n LoggerProgressOptions,\n LogPayload,\n LevelName,\n LoggerTransport,\n LoggerMode\n} from \"./types.js\";\nimport { ConsoleTransport, ParentProcessTransport } from \"./transports.js\";\nimport type { Context } from \"../init/types.js\";\n\nconst ALL_LEVELS: LevelName[] = [\n \"silly\",\n \"debug\",\n \"logic\",\n \"info\",\n \"notice\",\n \"warn\",\n \"error\",\n \"results\",\n \"request\",\n \"response\",\n \"progress\"\n];\n\n// Calculate maximum level name length for alignment\nconst MAX_LEVEL_LENGTH = Math.max(...ALL_LEVELS.map(level => level.toUpperCase().length));\n\nconst LEVEL_COLORS: Record<LevelName, chalk.Chalk> = {\n error: chalk.red.bold,\n warn: chalk.rgb(255, 165, 0),\n notice: chalk.cyan,\n info: chalk.white.bold,\n logic: chalk.gray,\n debug: chalk.gray,\n silly: chalk.gray,\n request: chalk.green,\n response: chalk.yellow,\n progress: chalk.green,\n results: chalk.magenta\n};\n\ninterface NormalizedOptions {\n mode: LoggerMode;\n route: \"console\" | \"ipc\";\n prefix?: string;\n silent: boolean;\n showLevel: boolean;\n timestamp: boolean;\n levels: LevelName[];\n progressTimes: boolean;\n progressThrottle?: number;\n}\n\nexport class Logger implements Logger {\n private context: any; // Partial context during initialization\n private options: NormalizedOptions;\n private transport: LoggerTransport;\n private readonly startTimes: Record<string, number> = {};\n private readonly lastProgressTimes: Record<string, number> = {};\n\n constructor(context: any, options: LoggerOptions = {}) {\n this.context = context;\n // Set defaults first\n this.options = this.getDefaultOptions();\n // Apply configuration\n if (options) {\n this.configure(options);\n }\n // Initialize transport\n this.updateTransport();\n }\n\n /**\n * Configure logger options\n * Only parameters present in options are updated\n */\n configure(options: Partial<LoggerOptions>): void {\n if (options.mode !== undefined) {\n this.options.mode = this.isValidMode(options.mode) ? options.mode : \"text\";\n }\n if (options.route !== undefined) {\n this.options.route = options.route;\n this.updateTransport();\n }\n if (options.prefix !== undefined) {\n this.options.prefix = options.prefix;\n }\n if (options.silent !== undefined) {\n this.options.silent = options.silent;\n }\n if (options.showLevel !== undefined) {\n this.options.showLevel = options.showLevel;\n }\n if (options.timestamp !== undefined) {\n this.options.timestamp = options.timestamp;\n }\n if (options.levels !== undefined) {\n this.options.levels = this.normalizeLevels(options.levels);\n }\n if (options.progress !== undefined) {\n if (options.progress.withTimes !== undefined) {\n this.options.progressTimes = options.progress.withTimes;\n }\n if (options.progress.throttleMs !== undefined) {\n this.options.progressThrottle = options.progress.throttleMs;\n }\n }\n }\n\n /**\n * Initialize logger from context and CLI parameters\n */\n static init(context: any, options?: LoggerOptions): Logger {\n // Define parameter definitions for CLI (with defaults to make them optional)\n const paramDefs = {\n mode: \"string default text\",\n route: \"string default console\",\n prefix: \"string\",\n silent: \"boolean default false\",\n showLevel: \"boolean default true\",\n timestamp: \"boolean default false\",\n levels: \"string\",\n progressWithTimes: \"boolean default false\",\n progressThrottleMs: \"number\",\n };\n\n // Collect parameters from CLI\n const cliParams = context.params.getAll(paramDefs);\n\n // Merge CLI params with options (options take precedence)\n const config: LoggerOptions = {\n mode: options?.mode ?? cliParams.mode,\n route: options?.route ?? cliParams.route,\n prefix: options?.prefix ?? cliParams.prefix,\n silent: options?.silent ?? cliParams.silent,\n showLevel: options?.showLevel ?? cliParams.showLevel,\n timestamp: options?.timestamp ?? cliParams.timestamp,\n levels: options?.levels ?? (cliParams.levels ? cliParams.levels.split(\",\") : undefined),\n progress: options?.progress ?? {\n withTimes: cliParams.progressWithTimes,\n throttleMs: cliParams.progressThrottleMs,\n },\n };\n\n\n // Create and return instance\n const logger = new Logger(context, config);\n context.logger = logger; // Update context with the new logger instance\n return logger;\n }\n\n private getDefaultOptions(): NormalizedOptions {\n return {\n mode: \"text\",\n route: this.shouldUseIpcRoute() ? \"ipc\" : \"console\",\n prefix: undefined,\n silent: false,\n showLevel: true,\n timestamp: false,\n levels: ALL_LEVELS,\n progressTimes: false,\n progressThrottle: undefined,\n };\n }\n\n private updateTransport(): void {\n this.transport = this.options.route === \"ipc\"\n ? new ParentProcessTransport()\n : new ConsoleTransport();\n }\n\n setMode(mode: LoggerMode): void {\n if (!this.isValidMode(mode)) {\n throw new Error(`Unsupported logger mode: ${mode}`);\n }\n this.options.mode = mode;\n }\n\n debug(message?: any, ...chunks: any[]): void {\n this.out({ level: \"debug\", message, chunks });\n }\n\n info(message?: any, ...chunks: any[]): void {\n this.out({ level: \"info\", message, chunks });\n }\n\n notice(message?: any, ...chunks: any[]): void {\n this.out({ level: \"notice\", message, chunks });\n }\n\n warn(message?: any, ...chunks: any[]): void {\n this.out({ level: \"warn\", message, chunks });\n }\n\n error(message?: any, ...chunks: any[]): void {\n this.out({ level: \"error\", message, chunks });\n }\n\n logic(message?: any, ...chunks: any[]): void {\n this.out({ level: \"logic\", message, chunks });\n }\n\n silly(message?: any, ...chunks: any[]): void {\n this.out({ level: \"silly\", message, chunks });\n }\n\n results(results: unknown): void {\n this.out({ level: \"results\", message: \"results\", results });\n }\n\n request(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"request\", message });\n }\n\n response(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"response\", message });\n }\n\n progress(message: string, opts: LoggerProgressOptions): void {\n const { prefix, count, total } = opts;\n const paddedTotal = String(total).length;\n const paddedCount = String(count).padStart(paddedTotal, \" \");\n const payload: LogPayload = {\n level: \"progress\",\n message,\n count: paddedCount,\n total,\n prefix\n };\n\n if (!this.startTimes[prefix ?? \"\"]) {\n this.startTimes[prefix ?? \"\"] = Date.now();\n }\n if (this.options.progressTimes) {\n const elapsedSeconds = (Date.now() - this.startTimes[prefix ?? \"\"]) / 1000;\n let remaining = -1;\n if (count > 1) {\n const rate = elapsedSeconds / (count - 1);\n remaining = (total - count) * rate;\n }\n payload.elapsed = this.round(elapsedSeconds, 2);\n payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;\n }\n\n if (count >= total) {\n delete this.startTimes[prefix ?? \"\"];\n delete this.lastProgressTimes[prefix ?? \"\"];\n }\n\n if (this.shouldOutputProgress(prefix ?? \"\", count, total)) {\n this.out(payload);\n if (this.options.progressThrottle && prefix) {\n this.lastProgressTimes[prefix] = Date.now();\n }\n }\n }\n\n private shouldOutputProgress(prefix: string, count: number, total: number): boolean {\n if (!this.options.progressThrottle) {\n return true;\n }\n if (count === 1 || count === total || !prefix) {\n return true;\n }\n const lastTime = this.lastProgressTimes[prefix];\n if (!lastTime) {\n return true;\n }\n return Date.now() - lastTime >= this.options.progressThrottle;\n }\n\n private out(struct: LogPayload): void {\n if (this.options.silent) {\n return;\n }\n if (!this.options.levels.includes(struct.level)) {\n return;\n }\n\n if (this.options.prefix && !struct.prefix) {\n struct.prefix = this.options.prefix;\n }\n\n const output = this.options.mode === \"json\"\n ? struct\n : this.formatLog(struct);\n\n this.transport.write(output);\n }\n\n private formatLog(struct: LogPayload): string {\n const parts: string[] = [];\n const now = new Date();\n\n if (this.options.timestamp) {\n parts.push(now.toISOString());\n }\n\n if (this.options.showLevel) {\n parts.push(struct.level.toUpperCase().padEnd(MAX_LEVEL_LENGTH));\n }\n\n if (struct.level === \"progress\") {\n if (struct.prefix) {\n parts.push(LEVEL_COLORS[struct.level].bold(struct.prefix));\n }\n if (struct.count !== undefined && struct.total !== undefined) {\n parts.push(LEVEL_COLORS[struct.level](`${struct.count}/${struct.total}`));\n }\n } else if (struct.prefix) {\n parts.push(chalk.cyan(`[${struct.prefix}]`));\n }\n\n if (struct.message) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter.bold(struct.message));\n }\n\n if (struct.level === \"progress\") {\n if (struct.elapsed !== undefined && struct.remaining !== undefined) {\n const formatter = LEVEL_COLORS[struct.level];\n parts.push(formatter(`${struct.elapsed}/${struct.remaining}`));\n }\n }\n\n if (struct.chunks && struct.chunks.length) {\n parts.push(this.inspectChunks(struct.chunks));\n }\n\n if (struct.results) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter(JSON.stringify(struct.results, null, 4)));\n }\n\n return parts.join(\" \");\n }\n\n private inspectChunks(chunks: any[]): string {\n return chunks\n .map(chunk => util.inspect(chunk, { colors: true, depth: null }))\n .join(\" \");\n }\n\n private shouldUseIpcRoute(): boolean {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n return false;\n }\n // Only use IPC if process.send exists AND we're connected to a parent\n // In Vitest workers, process.send exists but process.connected is undefined/false\n // process.connected is only true in actual child processes created with fork()\n return typeof process.send === \"function\" && process.connected === true;\n }\n\n private normalizeLevels(levels?: string[]): LevelName[] {\n if (!levels || !levels.length) {\n return ALL_LEVELS;\n }\n\n const includes = levels.filter(level => !level.startsWith(\"-\")) as LevelName[];\n const excludes = levels\n .filter(level => level.startsWith(\"-\"))\n .map(level => level.slice(1)) as LevelName[];\n\n const unknown = [...includes, ...excludes].filter(level => !ALL_LEVELS.includes(level));\n if (unknown.length) {\n console.warn(`[Logger] Unknown level(s): ${unknown.join(\", \")}`);\n }\n\n const base = includes.length ? includes : ALL_LEVELS;\n return base.filter(level => !excludes.includes(level));\n }\n\n private isValidMode(mode?: string | null): mode is LoggerMode | undefined {\n return mode === undefined || mode === null || mode === \"text\" || mode === \"json\";\n }\n\n private round(value: number, places: number): number {\n const factor = Math.pow(10, places);\n return Math.round(value * factor) / factor;\n }\n}\n\n","import { LoggerTransport } from \"./types.js\";\n\nexport class ConsoleTransport implements LoggerTransport {\n write(payload: any): void {\n console.info(payload);\n }\n}\n\nexport class ParentProcessTransport implements LoggerTransport {\n write(payload: any): void {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n console.info(payload);\n return;\n }\n // Only use process.send if we're actually connected to a parent process\n // In Vitest workers, process.send exists but shouldn't be used\n if (typeof process.send === \"function\" && process.connected === true) {\n process.send(payload);\n } else {\n console.info(payload);\n }\n }\n}\n\n\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/logger/index.ts","../src/logger/transports.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport util from \"util\";\n\nimport {\n Logger,\n LoggerOptions,\n LoggerProgressOptions,\n LogPayload,\n LevelName,\n LoggerTransport,\n LoggerMode\n} from \"./types.js\";\nimport { ConsoleTransport, ParentProcessTransport } from \"./transports.js\";\nimport type { Context } from \"../init/types.js\";\n\nconst ALL_LEVELS: LevelName[] = [\n \"silly\",\n \"debug\",\n \"logic\",\n \"info\",\n \"notice\",\n \"warn\",\n \"error\",\n \"results\",\n \"request\",\n \"response\",\n \"progress\"\n];\n\n// Calculate maximum level name length for alignment\nconst MAX_LEVEL_LENGTH = Math.max(...ALL_LEVELS.map(level => level.toUpperCase().length));\n\nconst LEVEL_COLORS: Record<LevelName, chalk.Chalk> = {\n error: chalk.red.bold,\n warn: chalk.rgb(255, 165, 0),\n notice: chalk.cyan,\n info: chalk.white.bold,\n logic: chalk.gray,\n debug: chalk.gray,\n silly: chalk.gray,\n request: chalk.green,\n response: chalk.yellow,\n progress: chalk.green,\n results: chalk.magenta\n};\n\ninterface NormalizedOptions {\n mode: LoggerMode;\n route: \"console\" | \"ipc\";\n prefix?: string;\n silent: boolean;\n showLevel: boolean;\n timestamp: boolean;\n levels: LevelName[];\n progressTimes: boolean;\n progressThrottle?: number;\n}\n\nexport class Logger implements Logger {\n private context: any; // Partial context during initialization\n private options: NormalizedOptions;\n private transport: LoggerTransport;\n private readonly startTimes: Record<string, number> = {};\n private readonly lastProgressTimes: Record<string, number> = {};\n\n constructor(context: any, options: LoggerOptions = {}) {\n this.context = context;\n // Set defaults first\n this.options = this.getDefaultOptions();\n // Apply configuration\n if (options) {\n this.configure(options);\n }\n // Initialize transport\n this.updateTransport();\n }\n\n /**\n * Configure logger options\n * Only parameters present in options are updated\n */\n configure(options: Partial<LoggerOptions>): void {\n if (options.mode !== undefined) {\n this.options.mode = this.isValidMode(options.mode) ? options.mode : \"text\";\n }\n if (options.route !== undefined) {\n this.options.route = options.route;\n this.updateTransport();\n }\n if (options.prefix !== undefined) {\n this.options.prefix = options.prefix;\n }\n if (options.silent !== undefined) {\n this.options.silent = options.silent;\n }\n if (options.showLevel !== undefined) {\n this.options.showLevel = options.showLevel;\n }\n if (options.timestamp !== undefined) {\n this.options.timestamp = options.timestamp;\n }\n if (options.levels !== undefined) {\n this.options.levels = this.normalizeLevels(options.levels);\n }\n if (options.progress !== undefined) {\n if (options.progress.withTimes !== undefined) {\n this.options.progressTimes = options.progress.withTimes;\n }\n if (options.progress.throttleMs !== undefined) {\n this.options.progressThrottle = options.progress.throttleMs;\n }\n }\n }\n\n /**\n * Initialize logger from context and CLI parameters\n */\n static init(context: any, options?: LoggerOptions): Logger {\n // Define parameter definitions for CLI (with defaults to make them optional)\n const paramDefs = {\n mode: \"string default text\",\n route: \"string default console\",\n prefix: \"string\",\n silent: \"boolean default false\",\n showLevel: \"boolean default true\",\n timestamp: \"boolean default false\",\n levels: \"string\",\n progressWithTimes: \"boolean default false\",\n progressThrottleMs: \"number\",\n };\n\n // Collect parameters from CLI\n const cliParams = context.params.getAll(paramDefs);\n\n // Merge CLI params with options (options take precedence)\n const config: LoggerOptions = {\n mode: options?.mode ?? cliParams.mode,\n route: options?.route ?? cliParams.route,\n prefix: options?.prefix ?? cliParams.prefix,\n silent: options?.silent ?? cliParams.silent,\n showLevel: options?.showLevel ?? cliParams.showLevel,\n timestamp: options?.timestamp ?? cliParams.timestamp,\n levels: options?.levels ?? (cliParams.levels ? cliParams.levels.split(\",\") : undefined),\n progress: options?.progress ?? {\n withTimes: cliParams.progressWithTimes,\n throttleMs: cliParams.progressThrottleMs,\n },\n };\n\n\n // Create and return instance\n const logger = new Logger(context, config);\n context.logger = logger; // Update context with the new logger instance\n return logger;\n }\n\n private getDefaultOptions(): NormalizedOptions {\n return {\n mode: \"text\",\n route: this.shouldUseIpcRoute() ? \"ipc\" : \"console\",\n prefix: undefined,\n silent: false,\n showLevel: false,\n timestamp: false,\n levels: ALL_LEVELS,\n progressTimes: false,\n progressThrottle: undefined,\n };\n }\n\n private updateTransport(): void {\n this.transport = this.options.route === \"ipc\"\n ? new ParentProcessTransport()\n : new ConsoleTransport();\n }\n\n setMode(mode: LoggerMode): void {\n if (!this.isValidMode(mode)) {\n throw new Error(`Unsupported logger mode: ${mode}`);\n }\n this.options.mode = mode;\n }\n\n debug(message?: any, ...chunks: any[]): void {\n this.out({ level: \"debug\", message, chunks });\n }\n\n info(message?: any, ...chunks: any[]): void {\n this.out({ level: \"info\", message, chunks });\n }\n\n notice(message?: any, ...chunks: any[]): void {\n this.out({ level: \"notice\", message, chunks });\n }\n\n warn(message?: any, ...chunks: any[]): void {\n this.out({ level: \"warn\", message, chunks });\n }\n\n error(message?: any, ...chunks: any[]): void {\n this.out({ level: \"error\", message, chunks });\n }\n\n logic(message?: any, ...chunks: any[]): void {\n this.out({ level: \"logic\", message, chunks });\n }\n\n silly(message?: any, ...chunks: any[]): void {\n this.out({ level: \"silly\", message, chunks });\n }\n\n results(results: unknown): void {\n this.out({ level: \"results\", message: \"results\", results });\n }\n\n request(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"request\", message });\n }\n\n response(operation: string, ...chunks: any[]): void {\n const message = this.inspectChunks([operation, ...chunks]);\n this.out({ level: \"response\", message });\n }\n\n progress(message: string, opts: LoggerProgressOptions): void {\n const { prefix, count, total } = opts;\n const paddedTotal = String(total).length;\n const paddedCount = String(count).padStart(paddedTotal, \" \");\n const payload: LogPayload = {\n level: \"progress\",\n message,\n count: paddedCount,\n total,\n prefix\n };\n\n if (!this.startTimes[prefix ?? \"\"]) {\n this.startTimes[prefix ?? \"\"] = Date.now();\n }\n if (this.options.progressTimes) {\n const elapsedSeconds = (Date.now() - this.startTimes[prefix ?? \"\"]) / 1000;\n let remaining = -1;\n if (count > 1) {\n const rate = elapsedSeconds / (count - 1);\n remaining = (total - count) * rate;\n }\n payload.elapsed = this.round(elapsedSeconds, 2);\n payload.remaining = remaining >= 0 ? this.round(remaining, 2) : remaining;\n }\n\n if (count >= total) {\n delete this.startTimes[prefix ?? \"\"];\n delete this.lastProgressTimes[prefix ?? \"\"];\n }\n\n if (this.shouldOutputProgress(prefix ?? \"\", count, total)) {\n this.out(payload);\n if (this.options.progressThrottle && prefix) {\n this.lastProgressTimes[prefix] = Date.now();\n }\n }\n }\n\n private shouldOutputProgress(prefix: string, count: number, total: number): boolean {\n if (!this.options.progressThrottle) {\n return true;\n }\n if (count === 1 || count === total || !prefix) {\n return true;\n }\n const lastTime = this.lastProgressTimes[prefix];\n if (!lastTime) {\n return true;\n }\n return Date.now() - lastTime >= this.options.progressThrottle;\n }\n\n private out(struct: LogPayload): void {\n if (this.options.silent) {\n return;\n }\n if (!this.options.levels.includes(struct.level)) {\n return;\n }\n\n if (this.options.prefix && !struct.prefix) {\n struct.prefix = this.options.prefix;\n }\n\n const output = this.options.mode === \"json\"\n ? struct\n : this.formatLog(struct);\n\n this.transport.write(output);\n }\n\n private formatLog(struct: LogPayload): string {\n const parts: string[] = [];\n const now = new Date();\n\n if (this.options.timestamp) {\n parts.push(now.toISOString());\n }\n\n if (this.options.showLevel) {\n parts.push(struct.level.toUpperCase().padEnd(MAX_LEVEL_LENGTH));\n }\n\n if (struct.level === \"progress\") {\n if (struct.prefix) {\n parts.push(LEVEL_COLORS[struct.level].bold(struct.prefix));\n }\n if (struct.count !== undefined && struct.total !== undefined) {\n parts.push(LEVEL_COLORS[struct.level](`${struct.count}/${struct.total}`));\n }\n } else if (struct.prefix) {\n parts.push(chalk.cyan(`[${struct.prefix}]`));\n }\n\n if (struct.message) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter.bold(struct.message));\n }\n\n if (struct.level === \"progress\") {\n if (struct.elapsed !== undefined && struct.remaining !== undefined) {\n const formatter = LEVEL_COLORS[struct.level];\n parts.push(formatter(`${struct.elapsed}/${struct.remaining}`));\n }\n }\n\n if (struct.chunks && struct.chunks.length) {\n parts.push(this.inspectChunks(struct.chunks));\n }\n\n if (struct.results) {\n const formatter = LEVEL_COLORS[struct.level] ?? chalk.white;\n parts.push(formatter(JSON.stringify(struct.results, null, 4)));\n }\n\n return parts.join(\" \");\n }\n\n private inspectChunks(chunks: any[]): string {\n return chunks\n .map(chunk => util.inspect(chunk, { colors: true, depth: null }))\n .join(\" \");\n }\n\n private shouldUseIpcRoute(): boolean {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n return false;\n }\n // Only use IPC if process.send exists AND we're connected to a parent\n // In Vitest workers, process.send exists but process.connected is undefined/false\n // process.connected is only true in actual child processes created with fork()\n return typeof process.send === \"function\" && process.connected === true;\n }\n\n private normalizeLevels(levels?: string[]): LevelName[] {\n if (!levels || !levels.length) {\n return ALL_LEVELS;\n }\n\n const includes = levels.filter(level => !level.startsWith(\"-\")) as LevelName[];\n const excludes = levels\n .filter(level => level.startsWith(\"-\"))\n .map(level => level.slice(1)) as LevelName[];\n\n const unknown = [...includes, ...excludes].filter(level => !ALL_LEVELS.includes(level));\n if (unknown.length) {\n console.warn(`[Logger] Unknown level(s): ${unknown.join(\", \")}`);\n }\n\n const base = includes.length ? includes : ALL_LEVELS;\n return base.filter(level => !excludes.includes(level));\n }\n\n private isValidMode(mode?: string | null): mode is LoggerMode | undefined {\n return mode === undefined || mode === null || mode === \"text\" || mode === \"json\";\n }\n\n private round(value: number, places: number): number {\n const factor = Math.pow(10, places);\n return Math.round(value * factor) / factor;\n }\n}\n\n","import { LoggerTransport } from \"./types.js\";\n\nexport class ConsoleTransport implements LoggerTransport {\n write(payload: any): void {\n console.info(payload);\n }\n}\n\nexport class ParentProcessTransport implements LoggerTransport {\n write(payload: any): void {\n // Don't use IPC in test environments (Vitest workers interfere with process.send)\n if (process.env.VITEST || process.env.NODE_ENV === \"test\") {\n console.info(payload);\n return;\n }\n // Only use process.send if we're actually connected to a parent process\n // In Vitest workers, process.send exists but shouldn't be used\n if (typeof process.send === \"function\" && process.connected === true) {\n process.send(payload);\n } else {\n console.info(payload);\n }\n }\n}\n\n\n"],"mappings":"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","names":[]}
|
package/dist/params.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/params.ts","../src/params/index.ts","../src/errors.ts","../src/params/custom-types.ts"],"sourcesContent":["// Re-export everything from the params module directory\nexport * from \"./params/index.js\";\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors\";\nimport { joiEdateType, joiStringArrayType } from \"./custom-types\";\n\n/**\n * Parameter definition types\n */\nexport type ParamDefinition = \n | string \n | Joi.Schema \n | { \n type?: string | Joi.Schema; \n values?: any[]; \n [key: string]: any; \n };\n\nexport type ParamGetter = (key: string, definition?: any) => any;\nexport type ParamSetter = (key: string, value: any) => boolean;\n\n/**\n * Args instance interface\n */\nexport interface ArgsInstance {\n get(key: string): any;\n}\n\n/**\n * Params constructor options\n */\nexport interface ParamsOptions {\n [key: string]: any;\n}\n\n/**\n * Tracked parameter information for --stopAfter=init\n */\ninterface TrackedParam {\n key: string;\n definition: ParamDefinition;\n value: any;\n source: \"cli\" | \"options\" | \"default\";\n}\n\n/**\n * Params class for parameter validation and type checking\n * Built on top of Args library with Joi validation\n */\nexport class Params {\n private context: any; // Partial context during initialization\n private params: Record<string, any> = {};\n private definitions: Record<string, any> = {};\n private args: ArgsInstance;\n private paramSetters: ParamSetter[] = [];\n private paramGetters: ParamGetter[] = [];\n private trackedParams: TrackedParam[] = [];\n\n constructor(context: any, options: ParamsOptions = {}) {\n // Context might be partial during initialization\n this.context = context;\n this.args = context.args;\n\n // Apply initial configuration\n if (Object.keys(options).length > 0) {\n this.configure(options);\n }\n }\n\n /**\n * Configure parameters\n * Only parameters present in options are updated\n */\n configure(options: ParamsOptions): void {\n for (const [k, v] of Object.entries(options)) {\n // TODO: opt values might be an object with definitions in it, so perhaps `this.set` should be used\n this.params[k] = v;\n }\n }\n\n /**\n * Initialize Params from context and CLI parameters\n * Note: Params is special - it's initialized early with partial context\n */\n static init(context: any, options?: ParamsOptions): Params {\n return new Params(context, options || {});\n }\n\n /**\n * Track a parameter request for --stopAfter=init feature\n */\n private trackParam(key: string, definition: ParamDefinition, value: any, source: \"cli\" | \"options\" | \"default\"): void {\n this.trackedParams.push({\n key,\n definition,\n value,\n source\n });\n }\n\n /**\n * Get all tracked parameters (for --stopAfter=init)\n */\n getTrackedParams(): TrackedParam[] {\n return [...this.trackedParams];\n }\n\n /**\n * Get all figured parameters as a record\n * Returns all parameters that were collected during initialization,\n * whether from CLI args, options, or defaults\n */\n getAllFigured(): Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> {\n const result: Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> = {};\n for (const param of this.trackedParams) {\n result[param.key] = {\n value: param.value,\n source: param.source,\n };\n }\n return result;\n }\n\n /**\n * Clear tracked parameters\n */\n clearTrackedParams(): void {\n this.trackedParams = [];\n }\n\n /**\n * Assign a parameter definition\n */\n assignDefinition(key: string, definition?: ParamDefinition): any {\n if (this.definitions[key] && !definition) {\n return this.definitions[key];\n }\n\n let type: Joi.Schema;\n if (!definition) {\n type = Joi.string();\n } else if (Joi.isSchema(definition)) {\n type = definition;\n } else if (Joi.isSchema(definition.type)) {\n type = definition.type;\n } else if (typeof definition === \"string\") {\n type = this.toJoi(definition);\n } else if (typeof definition.type === \"string\") {\n type = this.toJoi(definition.type);\n } else if (!definition.type) {\n type = Joi.string();\n } else {\n type = Joi.string();\n }\n\n if (!this.definitions[key]) {\n this.definitions[key] = {};\n }\n this.definitions[key].type = type;\n\n if (definition && definition.values) {\n if (Array.isArray(definition.values)) {\n this.definitions[key].values = definition.values;\n }\n }\n return this.definitions[key];\n }\n\n /**\n * Convert string definition to Joi schema\n */\n toJoi(str: string): Joi.Schema {\n let type: Joi.Schema;\n \n if (str.match(/^string|^text/i)) {\n type = Joi.string();\n } else if (str.match(/^number|^integer|^int/i)) {\n type = Joi.number();\n } else if (str.match(/^boolean|^bool/i)) {\n type = Joi.boolean();\n } else if (str.match(/^date/i)) {\n type = Joi.custom(joiEdateType);\n } else if (str.match(/^duration/i)) {\n type = Joi.string().isoDuration();\n } else if (str.match(/^array/i)) {\n let elementTypes = \"string\";\n const tmp = str.match(/\\((.*)\\)/);\n if (tmp && tmp[1].match(/string/i)) {\n elementTypes = \"string\";\n } else if (tmp && tmp[1].match(/number|integer|int/i)) {\n elementTypes = \"number\";\n } else if (tmp && tmp[1].match(/boolean|bool/i)) {\n elementTypes = \"boolean\";\n }\n type = Joi.custom(joiStringArrayType(elementTypes));\n } else {\n type = Joi.string();\n }\n\n // Handle default values\n const regexForDefault = /\\bdefault\\s+([^\\s]+)/;\n const matchForDefault = str.match(regexForDefault);\n if (matchForDefault) {\n const defValObj = type.validate(matchForDefault[1]);\n if (defValObj.error) {\n throw new ParamError(`default value \"${defValObj.value}\" type mismatch`);\n }\n // Joi's default() automatically allows undefined and applies the default\n type = type.default(defValObj.value);\n } else if (str.match(/required/)) {\n type = type.required();\n } else {\n // If not required and no default, make it optional\n type = type.optional();\n }\n\n return type;\n }\n\n /**\n * Validate a value against a definition\n */\n validate(key: string, val: any, def: any): any {\n // Convert null to undefined so Joi defaults can be applied\n // Joi's .default() only works with undefined, not null\n const normalizedVal = val === null ? undefined : val;\n \n // Pass current params as context to support cross-parameter references (e.g., @startTime+2h)\n // Use abortEarly: false to get all errors, and allowUnknown: false for strict validation\n const { value, error } = def.type.validate(normalizedVal, { \n context: { params: this.params },\n abortEarly: false,\n allowUnknown: false,\n });\n if (error) {\n const errs = error.details.map((el: any) => el.message).join(\", \");\n throw new ParamError(`\"${key}\" validation error: ${errs}`);\n }\n return value;\n }\n\n /**\n * Get a parameter value with validation\n */\n get(key: string, definition?: ParamDefinition): any {\n const def = this.assignDefinition(key, definition);\n let valFromGetters: any = undefined;\n \n if (def.volatile || true) {\n valFromGetters = this.runAllRegisteredGetters(key);\n }\n \n const valFromArgs = this.args.get(key);\n const valFromParams = this.params[key];\n\n let source: \"cli\" | \"options\" | \"default\" = \"default\";\n let value: any;\n\n if (valFromGetters !== undefined && valFromGetters !== null) {\n value = this.validate(key, valFromGetters, def);\n source = \"options\";\n } else if (valFromArgs !== undefined && valFromArgs !== null) {\n value = this.validate(key, valFromArgs, def);\n source = \"cli\";\n } else if (valFromParams !== undefined && valFromParams !== null) {\n value = this.validate(key, valFromParams, def);\n source = \"options\";\n } else {\n // Use default from definition - Joi will apply default when value is undefined\n // We need to pass undefined explicitly so Joi can apply the default\n value = this.validate(key, undefined, def);\n source = \"default\";\n }\n\n // Track parameter for --stopAfter=init\n this.trackParam(key, definition || \"string\", value, source);\n\n if (value !== undefined && def.values && !def.values.includes(value)) {\n throw new ParamError(`key ${key} should be one of ${def.values}`);\n }\n return value;\n }\n\n /**\n * Set a parameter value with validation\n */\n set(key: string, val: any, definition?: ParamDefinition): void {\n // TODO: check if there's a test for this:\n if (val && val.type && val.value) {\n definition = val;\n val = val.value;\n }\n const def = this.assignDefinition(key, definition);\n\n if (!this.runAllRegisteredSetters(key, val)) {\n this.params[key] = val;\n }\n }\n\n /**\n * Get all parameters from definitions\n * Processes parameters left-to-right to support cross-parameter references\n */\n getAll(defs: Record<string, ParamDefinition>): Record<string, any> {\n const res: Record<string, any> = {};\n for (const [k, def] of Object.entries(defs)) {\n const value = this.get(k, def);\n res[k] = value;\n // Store validated value in params so subsequent params can reference it\n if (value !== undefined) {\n this.params[k] = value;\n }\n }\n return res;\n }\n\n /**\n * Run all registered getters for a key\n */\n runAllRegisteredGetters(key: string): any {\n let val: any = undefined;\n for (const getter of this.paramGetters) {\n val = getter(key, this.definitions[key]);\n if (val !== undefined && val !== null) {\n break;\n }\n }\n return val;\n }\n\n /**\n * Run all registered setters for a key\n */\n runAllRegisteredSetters(key: string, value: any): boolean {\n let setterUsed: boolean = false;\n for (const setter of this.paramSetters) {\n setterUsed = setter(key, value);\n if (setterUsed) {\n break;\n }\n }\n return setterUsed;\n }\n\n /**\n * Register a parameter getter\n */\n registerParamGetter(fn: ParamGetter): void {\n this.paramGetters.push(fn);\n }\n\n /**\n * Register a parameter setter\n */\n registerParamSetter(fn: ParamSetter): void {\n this.paramSetters.push(fn);\n }\n}\n\n// Export custom types for external use\nexport { joiEdateType, joiStringArrayType };\n\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors.js\";\n\n/**\n * Custom Joi type for enhanced date parsing with relative time support\n * Supports:\n * - ISO8601 strings: \"2025-01-01T01:01:01Z\"\n * - Relative time: \"-2h\", \"+1d\", \"now\"\n * - Cross-parameter references: \"@startTime+2h\", \"@endDate-30m\"\n * \n * Internal representation: UTC ISO8601 string (YYYY-MM-DDTHH:mm:ssZ)\n * \n * @param value - Date value to parse\n * @param helpers - Joi helpers (includes context with other params)\n * @returns ISO8601 string in UTC timezone\n */\nexport const joiEdateType = (value: any, helpers: Joi.CustomHelpers): string => {\n // If value is already a string in ISO format, validate and return\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/.test(value)) {\n const testDate = new Date(value);\n if (!isNaN(testDate.getTime())) {\n return value;\n }\n }\n\n // If value is a Date object, convert to ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // If value is not a string, try to convert it\n if (typeof value !== \"string\") {\n value = String(value);\n }\n\n // Handle special keyword \"now\"\n if (value.toLowerCase() === \"now\") {\n return new Date().toISOString();\n }\n\n // Check for cross-parameter reference with relative time: @paramName+2h, @paramName-30m\n const referenceRegex = /^@(\\w+)([+-]\\d+[smhdwy])$/i;\n const referenceMatch = value.match(referenceRegex);\n \n if (referenceMatch) {\n const [, paramName, relativeExpr] = referenceMatch;\n \n // Get the referenced parameter from context (if available via helpers.state.ancestors)\n // For now, we'll use helpers.prefs.context which Joi provides\n const context = (helpers as any).prefs?.context;\n \n if (!context || !context.params) {\n throw new ParamError(`Cannot resolve cross-parameter reference @${paramName}: context not available. Ensure parameters are processed with proper context.`);\n }\n\n const referencedValue = context.params[paramName];\n \n if (referencedValue === undefined || referencedValue === null) {\n throw new ParamError(`Cannot resolve @${paramName}: parameter \"${paramName}\" is not defined or has no value. Parameters are evaluated left-to-right.`);\n }\n\n // Referenced value should be an ISO string or Date\n let referenceDate: Date;\n if (referencedValue instanceof Date) {\n referenceDate = referencedValue;\n } else if (typeof referencedValue === \"string\") {\n referenceDate = new Date(referencedValue);\n if (isNaN(referenceDate.getTime())) {\n throw new ParamError(`Referenced parameter @${paramName} has invalid date value: ${referencedValue}`);\n }\n } else {\n throw new ParamError(`Referenced parameter @${paramName} is not a valid date type (found: ${typeof referencedValue})`);\n }\n\n // Parse the relative expression and apply to reference date\n const relativeMatch = relativeExpr.match(/^([+-])(\\d+)([smhdwy])$/i);\n if (!relativeMatch) {\n throw new ParamError(`Invalid relative time expression in @${paramName}${relativeExpr}`);\n }\n\n const [, sign, amount, unit] = relativeMatch;\n const offset = calculateTimeOffset(parseInt(amount, 10), unit, sign);\n const resultDate = new Date(referenceDate.getTime() + offset);\n \n return resultDate.toISOString();\n }\n\n // Check for relative time expressions like \"-2h\", \"+1d\", \"-30m\", etc.\n const relativeTimeRegex = /^([+-])(\\d+)([smhdwy])$/i;\n const relativeMatch = value.match(relativeTimeRegex);\n \n if (relativeMatch) {\n const [, sign, amount, unit] = relativeMatch;\n const numAmount = parseInt(amount, 10);\n \n if (isNaN(numAmount)) {\n throw new ParamError(`Invalid relative time amount: ${amount}`);\n }\n\n const offset = calculateTimeOffset(numAmount, unit, sign);\n const resultDate = new Date(Date.now() + offset);\n \n return resultDate.toISOString();\n }\n\n // Try to parse as a regular date string\n const parsedDate = new Date(value);\n \n // Check if the parsed date is valid\n if (isNaN(parsedDate.getTime())) {\n throw new ParamError(`Invalid date format: ${value}. Expected a valid date string, \"now\", relative time expression (e.g., \"-2h\", \"+1d\"), or cross-parameter reference (e.g., \"@startTime+2h\")`);\n }\n\n return parsedDate.toISOString();\n};\n\n/**\n * Calculate time offset in milliseconds\n */\nfunction calculateTimeOffset(amount: number, unit: string, sign: string): number {\n let multiplier = 1;\n \n // Convert to milliseconds based on unit\n switch (unit.toLowerCase()) {\n case \"s\": // seconds\n multiplier = 1000;\n break;\n case \"m\": // minutes\n multiplier = 60 * 1000;\n break;\n case \"h\": // hours\n multiplier = 60 * 60 * 1000;\n break;\n case \"d\": // days\n multiplier = 24 * 60 * 60 * 1000;\n break;\n case \"w\": // weeks\n multiplier = 7 * 24 * 60 * 60 * 1000;\n break;\n case \"y\": // years (approximate)\n multiplier = 365 * 24 * 60 * 60 * 1000;\n break;\n default:\n throw new ParamError(`Invalid time unit: ${unit}. Supported units: s, m, h, d, w, y`);\n }\n\n return sign === \"+\" ? amount * multiplier : -amount * multiplier;\n}\n\n/**\n * Custom Joi type for string array parsing\n * Converts comma-separated strings to typed arrays\n */\nexport const joiStringArrayType = (type: string) => (value: any, helpers: Joi.CustomHelpers): any[] => {\n if (value === undefined || typeof value === \"function\") {\n return [];\n }\n \n const arr = value.split(/,\\s*/).map((el: string) => {\n if (type === \"number\") {\n const v = parseInt(el, 10);\n if (isNaN(v)) {\n throw new ParamError(`array element \"${el}\" should be numeric`);\n }\n return v;\n } else if (type === \"boolean\") {\n const v = el.match(/true|t|yes|1/i) ? true :\n el.match(/false|f|no|0/i) ? false : null;\n if (v === null) {\n throw new ParamError(`array element \"${el}\" should be boolean`);\n }\n return v;\n } else if (type === \"string\") {\n return el;\n } else {\n throw new ParamError(`unknown type \"${type}\" for array elements`);\n }\n });\n \n return arr;\n};\n\n"],"mappings":"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","names":["relativeMatch","Joi"]}
|
|
1
|
+
{"version":3,"sources":["../src/params.ts","../src/params/index.ts","../src/errors.ts","../src/params/custom-types.ts"],"sourcesContent":["// Re-export everything from the params module directory\nexport * from \"./params/index.js\";\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors\";\nimport { joiEdateType, joiStringArrayType } from \"./custom-types\";\n\n/**\n * Parameter definition types\n */\nexport type ParamDefinition = \n | string \n | Joi.Schema \n | { \n type?: string | Joi.Schema; \n values?: any[]; \n [key: string]: any; \n };\n\nexport type ParamGetter = (key: string, definition?: any) => any;\nexport type ParamSetter = (key: string, value: any) => boolean;\n\n/**\n * Args instance interface\n */\nexport interface ArgsInstance {\n get(key: string): any;\n}\n\n/**\n * Params constructor options\n */\nexport interface ParamsOptions {\n [key: string]: any;\n}\n\n/**\n * Tracked parameter information for --stopAfter=init\n */\ninterface TrackedParam {\n key: string;\n definition: ParamDefinition;\n value: any;\n source: \"cli\" | \"options\" | \"default\";\n}\n\n/**\n * Params class for parameter validation and type checking\n * Built on top of Args library with Joi validation\n */\nexport class Params {\n private context: any; // Partial context during initialization\n private params: Record<string, any> = {};\n private definitions: Record<string, any> = {};\n private args: ArgsInstance;\n private paramSetters: ParamSetter[] = [];\n private paramGetters: ParamGetter[] = [];\n private trackedParams: TrackedParam[] = [];\n\n constructor(context: any, options: ParamsOptions = {}) {\n // Context might be partial during initialization\n this.context = context;\n this.args = context.args;\n\n // Apply initial configuration\n if (Object.keys(options).length > 0) {\n this.configure(options);\n }\n }\n\n /**\n * Configure parameters\n * Only parameters present in options are updated\n */\n configure(options: ParamsOptions): void {\n for (const [k, v] of Object.entries(options)) {\n // TODO: opt values might be an object with definitions in it, so perhaps `this.set` should be used\n this.params[k] = v;\n }\n }\n\n /**\n * Initialize Params from context and CLI parameters\n * Note: Params is special - it's initialized early with partial context\n */\n static init(context: any, options?: ParamsOptions): Params {\n return new Params(context, options || {});\n }\n\n /**\n * Track a parameter request for --stopAfter=init feature\n */\n private trackParam(key: string, definition: ParamDefinition, value: any, source: \"cli\" | \"options\" | \"default\"): void {\n this.trackedParams.push({\n key,\n definition,\n value,\n source\n });\n }\n\n /**\n * Get all tracked parameters (for --stopAfter=init)\n */\n getTrackedParams(): TrackedParam[] {\n return [...this.trackedParams];\n }\n\n /**\n * Get all figured parameters as a record\n * Returns all parameters that were collected during initialization,\n * whether from CLI args, options, or defaults\n */\n getAllFigured(): Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> {\n const result: Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> = {};\n for (const param of this.trackedParams) {\n result[param.key] = {\n value: param.value,\n source: param.source,\n };\n }\n return result;\n }\n\n /**\n * Clear tracked parameters\n */\n clearTrackedParams(): void {\n this.trackedParams = [];\n }\n\n /**\n * Assign a parameter definition\n */\n assignDefinition(key: string, definition?: ParamDefinition): any {\n if (this.definitions[key] && !definition) {\n return this.definitions[key];\n }\n\n let type: Joi.Schema;\n if (!definition) {\n type = Joi.string();\n } else if (Joi.isSchema(definition)) {\n type = definition;\n } else if (Joi.isSchema(definition.type)) {\n type = definition.type;\n } else if (typeof definition === \"string\") {\n type = this.toJoi(definition);\n } else if (typeof definition.type === \"string\") {\n type = this.toJoi(definition.type);\n } else if (!definition.type) {\n type = Joi.string();\n } else {\n type = Joi.string();\n }\n\n if (!this.definitions[key]) {\n this.definitions[key] = {};\n }\n this.definitions[key].type = type;\n\n if (definition && definition.values) {\n if (Array.isArray(definition.values)) {\n this.definitions[key].values = definition.values;\n }\n }\n return this.definitions[key];\n }\n\n /**\n * Convert string definition to Joi schema\n */\n toJoi(str: string): Joi.Schema {\n let type: Joi.Schema;\n \n if (str.match(/^string|^text/i)) {\n type = Joi.string();\n } else if (str.match(/^number|^integer|^int/i)) {\n type = Joi.number();\n } else if (str.match(/^boolean|^bool/i)) {\n type = Joi.boolean();\n } else if (str.match(/^date/i)) {\n type = Joi.custom(joiEdateType);\n } else if (str.match(/^duration/i)) {\n type = Joi.string().isoDuration();\n } else if (str.match(/^array/i)) {\n let elementTypes = \"string\";\n const tmp = str.match(/\\((.*)\\)/);\n if (tmp && tmp[1].match(/string/i)) {\n elementTypes = \"string\";\n } else if (tmp && tmp[1].match(/number|integer|int/i)) {\n elementTypes = \"number\";\n } else if (tmp && tmp[1].match(/boolean|bool/i)) {\n elementTypes = \"boolean\";\n }\n type = Joi.custom(joiStringArrayType(elementTypes));\n } else {\n type = Joi.string();\n }\n\n // Handle default values\n const regexForDefault = /\\bdefault\\s+([^\\s]+)/;\n const matchForDefault = str.match(regexForDefault);\n if (matchForDefault) {\n const defValObj = type.validate(matchForDefault[1]);\n if (defValObj.error) {\n throw new ParamError(`default value \"${defValObj.value}\" type mismatch`);\n }\n // Joi's default() automatically allows undefined and applies the default\n type = type.default(defValObj.value);\n } else if (str.match(/required/)) {\n type = type.required();\n } else {\n // If not required and no default, make it optional\n type = type.optional();\n }\n\n return type;\n }\n\n /**\n * Validate a value against a definition\n */\n validate(key: string, val: any, def: any): any {\n // Convert null to undefined so Joi defaults can be applied\n // Joi's .default() only works with undefined, not null\n const normalizedVal = val === null ? undefined : val;\n \n // Pass current params as context to support cross-parameter references (e.g., @startTime+2h)\n // Use abortEarly: false to get all errors, and allowUnknown: false for strict validation\n const { value, error } = def.type.validate(normalizedVal, { \n context: { params: this.params },\n abortEarly: false,\n allowUnknown: false,\n });\n if (error) {\n const errs = error.details.map((el: any) => el.message).join(\", \");\n throw new ParamError(`\"${key}\" validation error: ${errs}`);\n }\n return value;\n }\n\n /**\n * Get a parameter value with validation\n */\n get(key: string, definition?: ParamDefinition): any {\n const def = this.assignDefinition(key, definition);\n let valFromGetters: any = undefined;\n \n if (def.volatile || true) {\n valFromGetters = this.runAllRegisteredGetters(key);\n }\n \n // Always call args.get() to mark the key as used, even if it doesn't exist\n // This ensures flags are marked as used regardless of when they're parsed\n const valFromArgs = this.args.get(key);\n const valFromParams = this.params[key];\n\n let source: \"cli\" | \"options\" | \"default\" = \"default\";\n let value: any;\n\n if (valFromGetters !== undefined && valFromGetters !== null) {\n value = this.validate(key, valFromGetters, def);\n source = \"options\";\n } else if (valFromArgs !== undefined && valFromArgs !== null) {\n value = this.validate(key, valFromArgs, def);\n source = \"cli\";\n } else if (valFromParams !== undefined && valFromParams !== null) {\n value = this.validate(key, valFromParams, def);\n source = \"options\";\n } else {\n // Use default from definition - Joi will apply default when value is undefined\n // We need to pass undefined explicitly so Joi can apply the default\n value = this.validate(key, undefined, def);\n source = \"default\";\n }\n\n // Track parameter for --stopAfter=init\n this.trackParam(key, definition || \"string\", value, source);\n\n if (value !== undefined && def.values && !def.values.includes(value)) {\n throw new ParamError(`key ${key} should be one of ${def.values}`);\n }\n return value;\n }\n\n /**\n * Set a parameter value with validation\n */\n set(key: string, val: any, definition?: ParamDefinition): void {\n // TODO: check if there's a test for this:\n if (val && val.type && val.value) {\n definition = val;\n val = val.value;\n }\n const def = this.assignDefinition(key, definition);\n\n if (!this.runAllRegisteredSetters(key, val)) {\n this.params[key] = val;\n }\n }\n\n /**\n * Get all parameters from definitions\n * Processes parameters left-to-right to support cross-parameter references\n */\n getAll(defs: Record<string, ParamDefinition>): Record<string, any> {\n const res: Record<string, any> = {};\n for (const [k, def] of Object.entries(defs)) {\n const value = this.get(k, def);\n res[k] = value;\n // Store validated value in params so subsequent params can reference it\n if (value !== undefined) {\n this.params[k] = value;\n }\n }\n return res;\n }\n\n /**\n * Run all registered getters for a key\n */\n runAllRegisteredGetters(key: string): any {\n let val: any = undefined;\n for (const getter of this.paramGetters) {\n val = getter(key, this.definitions[key]);\n if (val !== undefined && val !== null) {\n break;\n }\n }\n return val;\n }\n\n /**\n * Run all registered setters for a key\n */\n runAllRegisteredSetters(key: string, value: any): boolean {\n let setterUsed: boolean = false;\n for (const setter of this.paramSetters) {\n setterUsed = setter(key, value);\n if (setterUsed) {\n break;\n }\n }\n return setterUsed;\n }\n\n /**\n * Register a parameter getter\n */\n registerParamGetter(fn: ParamGetter): void {\n this.paramGetters.push(fn);\n }\n\n /**\n * Register a parameter setter\n */\n registerParamSetter(fn: ParamSetter): void {\n this.paramSetters.push(fn);\n }\n}\n\n// Export custom types for external use\nexport { joiEdateType, joiStringArrayType };\n\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors.js\";\n\n/**\n * Custom Joi type for enhanced date parsing with relative time support\n * Supports:\n * - ISO8601 strings: \"2025-01-01T01:01:01Z\"\n * - Relative time: \"-2h\", \"+1d\", \"now\"\n * - Cross-parameter references: \"@startTime+2h\", \"@endDate-30m\"\n * \n * Internal representation: UTC ISO8601 string (YYYY-MM-DDTHH:mm:ssZ)\n * \n * @param value - Date value to parse\n * @param helpers - Joi helpers (includes context with other params)\n * @returns ISO8601 string in UTC timezone\n */\nexport const joiEdateType = (value: any, helpers: Joi.CustomHelpers): string => {\n // If value is already a string in ISO format, validate and return\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/.test(value)) {\n const testDate = new Date(value);\n if (!isNaN(testDate.getTime())) {\n return value;\n }\n }\n\n // If value is a Date object, convert to ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // If value is not a string, try to convert it\n if (typeof value !== \"string\") {\n value = String(value);\n }\n\n // Handle special keyword \"now\"\n if (value.toLowerCase() === \"now\") {\n return new Date().toISOString();\n }\n\n // Check for cross-parameter reference with relative time: @paramName+2h, @paramName-30m\n const referenceRegex = /^@(\\w+)([+-]\\d+[smhdwy])$/i;\n const referenceMatch = value.match(referenceRegex);\n \n if (referenceMatch) {\n const [, paramName, relativeExpr] = referenceMatch;\n \n // Get the referenced parameter from context (if available via helpers.state.ancestors)\n // For now, we'll use helpers.prefs.context which Joi provides\n const context = (helpers as any).prefs?.context;\n \n if (!context || !context.params) {\n throw new ParamError(`Cannot resolve cross-parameter reference @${paramName}: context not available. Ensure parameters are processed with proper context.`);\n }\n\n const referencedValue = context.params[paramName];\n \n if (referencedValue === undefined || referencedValue === null) {\n throw new ParamError(`Cannot resolve @${paramName}: parameter \"${paramName}\" is not defined or has no value. Parameters are evaluated left-to-right.`);\n }\n\n // Referenced value should be an ISO string or Date\n let referenceDate: Date;\n if (referencedValue instanceof Date) {\n referenceDate = referencedValue;\n } else if (typeof referencedValue === \"string\") {\n referenceDate = new Date(referencedValue);\n if (isNaN(referenceDate.getTime())) {\n throw new ParamError(`Referenced parameter @${paramName} has invalid date value: ${referencedValue}`);\n }\n } else {\n throw new ParamError(`Referenced parameter @${paramName} is not a valid date type (found: ${typeof referencedValue})`);\n }\n\n // Parse the relative expression and apply to reference date\n const relativeMatch = relativeExpr.match(/^([+-])(\\d+)([smhdwy])$/i);\n if (!relativeMatch) {\n throw new ParamError(`Invalid relative time expression in @${paramName}${relativeExpr}`);\n }\n\n const [, sign, amount, unit] = relativeMatch;\n const offset = calculateTimeOffset(parseInt(amount, 10), unit, sign);\n const resultDate = new Date(referenceDate.getTime() + offset);\n \n return resultDate.toISOString();\n }\n\n // Check for relative time expressions like \"-2h\", \"+1d\", \"-30m\", etc.\n const relativeTimeRegex = /^([+-])(\\d+)([smhdwy])$/i;\n const relativeMatch = value.match(relativeTimeRegex);\n \n if (relativeMatch) {\n const [, sign, amount, unit] = relativeMatch;\n const numAmount = parseInt(amount, 10);\n \n if (isNaN(numAmount)) {\n throw new ParamError(`Invalid relative time amount: ${amount}`);\n }\n\n const offset = calculateTimeOffset(numAmount, unit, sign);\n const resultDate = new Date(Date.now() + offset);\n \n return resultDate.toISOString();\n }\n\n // Try to parse as a regular date string\n const parsedDate = new Date(value);\n \n // Check if the parsed date is valid\n if (isNaN(parsedDate.getTime())) {\n throw new ParamError(`Invalid date format: ${value}. Expected a valid date string, \"now\", relative time expression (e.g., \"-2h\", \"+1d\"), or cross-parameter reference (e.g., \"@startTime+2h\")`);\n }\n\n return parsedDate.toISOString();\n};\n\n/**\n * Calculate time offset in milliseconds\n */\nfunction calculateTimeOffset(amount: number, unit: string, sign: string): number {\n let multiplier = 1;\n \n // Convert to milliseconds based on unit\n switch (unit.toLowerCase()) {\n case \"s\": // seconds\n multiplier = 1000;\n break;\n case \"m\": // minutes\n multiplier = 60 * 1000;\n break;\n case \"h\": // hours\n multiplier = 60 * 60 * 1000;\n break;\n case \"d\": // days\n multiplier = 24 * 60 * 60 * 1000;\n break;\n case \"w\": // weeks\n multiplier = 7 * 24 * 60 * 60 * 1000;\n break;\n case \"y\": // years (approximate)\n multiplier = 365 * 24 * 60 * 60 * 1000;\n break;\n default:\n throw new ParamError(`Invalid time unit: ${unit}. Supported units: s, m, h, d, w, y`);\n }\n\n return sign === \"+\" ? amount * multiplier : -amount * multiplier;\n}\n\n/**\n * Custom Joi type for string array parsing\n * Converts comma-separated strings to typed arrays\n */\nexport const joiStringArrayType = (type: string) => (value: any, helpers: Joi.CustomHelpers): any[] => {\n if (value === undefined || typeof value === \"function\") {\n return [];\n }\n \n const arr = value.split(/,\\s*/).map((el: string) => {\n if (type === \"number\") {\n const v = parseInt(el, 10);\n if (isNaN(v)) {\n throw new ParamError(`array element \"${el}\" should be numeric`);\n }\n return v;\n } else if (type === \"boolean\") {\n const v = el.match(/true|t|yes|1/i) ? true :\n el.match(/false|f|no|0/i) ? false : null;\n if (v === null) {\n throw new ParamError(`array element \"${el}\" should be boolean`);\n }\n return v;\n } else if (type === \"string\") {\n return el;\n } else {\n throw new ParamError(`unknown type \"${type}\" for array elements`);\n }\n });\n \n return arr;\n};\n\n"],"mappings":"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","names":["relativeMatch","Joi"]}
|
package/dist/params.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/params/index.ts","../src/errors.ts","../src/params/custom-types.ts"],"sourcesContent":["import Joi from \"joi\";\nimport { ParamError } from \"../errors\";\nimport { joiEdateType, joiStringArrayType } from \"./custom-types\";\n\n/**\n * Parameter definition types\n */\nexport type ParamDefinition = \n | string \n | Joi.Schema \n | { \n type?: string | Joi.Schema; \n values?: any[]; \n [key: string]: any; \n };\n\nexport type ParamGetter = (key: string, definition?: any) => any;\nexport type ParamSetter = (key: string, value: any) => boolean;\n\n/**\n * Args instance interface\n */\nexport interface ArgsInstance {\n get(key: string): any;\n}\n\n/**\n * Params constructor options\n */\nexport interface ParamsOptions {\n [key: string]: any;\n}\n\n/**\n * Tracked parameter information for --stopAfter=init\n */\ninterface TrackedParam {\n key: string;\n definition: ParamDefinition;\n value: any;\n source: \"cli\" | \"options\" | \"default\";\n}\n\n/**\n * Params class for parameter validation and type checking\n * Built on top of Args library with Joi validation\n */\nexport class Params {\n private context: any; // Partial context during initialization\n private params: Record<string, any> = {};\n private definitions: Record<string, any> = {};\n private args: ArgsInstance;\n private paramSetters: ParamSetter[] = [];\n private paramGetters: ParamGetter[] = [];\n private trackedParams: TrackedParam[] = [];\n\n constructor(context: any, options: ParamsOptions = {}) {\n // Context might be partial during initialization\n this.context = context;\n this.args = context.args;\n\n // Apply initial configuration\n if (Object.keys(options).length > 0) {\n this.configure(options);\n }\n }\n\n /**\n * Configure parameters\n * Only parameters present in options are updated\n */\n configure(options: ParamsOptions): void {\n for (const [k, v] of Object.entries(options)) {\n // TODO: opt values might be an object with definitions in it, so perhaps `this.set` should be used\n this.params[k] = v;\n }\n }\n\n /**\n * Initialize Params from context and CLI parameters\n * Note: Params is special - it's initialized early with partial context\n */\n static init(context: any, options?: ParamsOptions): Params {\n return new Params(context, options || {});\n }\n\n /**\n * Track a parameter request for --stopAfter=init feature\n */\n private trackParam(key: string, definition: ParamDefinition, value: any, source: \"cli\" | \"options\" | \"default\"): void {\n this.trackedParams.push({\n key,\n definition,\n value,\n source\n });\n }\n\n /**\n * Get all tracked parameters (for --stopAfter=init)\n */\n getTrackedParams(): TrackedParam[] {\n return [...this.trackedParams];\n }\n\n /**\n * Get all figured parameters as a record\n * Returns all parameters that were collected during initialization,\n * whether from CLI args, options, or defaults\n */\n getAllFigured(): Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> {\n const result: Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> = {};\n for (const param of this.trackedParams) {\n result[param.key] = {\n value: param.value,\n source: param.source,\n };\n }\n return result;\n }\n\n /**\n * Clear tracked parameters\n */\n clearTrackedParams(): void {\n this.trackedParams = [];\n }\n\n /**\n * Assign a parameter definition\n */\n assignDefinition(key: string, definition?: ParamDefinition): any {\n if (this.definitions[key] && !definition) {\n return this.definitions[key];\n }\n\n let type: Joi.Schema;\n if (!definition) {\n type = Joi.string();\n } else if (Joi.isSchema(definition)) {\n type = definition;\n } else if (Joi.isSchema(definition.type)) {\n type = definition.type;\n } else if (typeof definition === \"string\") {\n type = this.toJoi(definition);\n } else if (typeof definition.type === \"string\") {\n type = this.toJoi(definition.type);\n } else if (!definition.type) {\n type = Joi.string();\n } else {\n type = Joi.string();\n }\n\n if (!this.definitions[key]) {\n this.definitions[key] = {};\n }\n this.definitions[key].type = type;\n\n if (definition && definition.values) {\n if (Array.isArray(definition.values)) {\n this.definitions[key].values = definition.values;\n }\n }\n return this.definitions[key];\n }\n\n /**\n * Convert string definition to Joi schema\n */\n toJoi(str: string): Joi.Schema {\n let type: Joi.Schema;\n \n if (str.match(/^string|^text/i)) {\n type = Joi.string();\n } else if (str.match(/^number|^integer|^int/i)) {\n type = Joi.number();\n } else if (str.match(/^boolean|^bool/i)) {\n type = Joi.boolean();\n } else if (str.match(/^date/i)) {\n type = Joi.custom(joiEdateType);\n } else if (str.match(/^duration/i)) {\n type = Joi.string().isoDuration();\n } else if (str.match(/^array/i)) {\n let elementTypes = \"string\";\n const tmp = str.match(/\\((.*)\\)/);\n if (tmp && tmp[1].match(/string/i)) {\n elementTypes = \"string\";\n } else if (tmp && tmp[1].match(/number|integer|int/i)) {\n elementTypes = \"number\";\n } else if (tmp && tmp[1].match(/boolean|bool/i)) {\n elementTypes = \"boolean\";\n }\n type = Joi.custom(joiStringArrayType(elementTypes));\n } else {\n type = Joi.string();\n }\n\n // Handle default values\n const regexForDefault = /\\bdefault\\s+([^\\s]+)/;\n const matchForDefault = str.match(regexForDefault);\n if (matchForDefault) {\n const defValObj = type.validate(matchForDefault[1]);\n if (defValObj.error) {\n throw new ParamError(`default value \"${defValObj.value}\" type mismatch`);\n }\n // Joi's default() automatically allows undefined and applies the default\n type = type.default(defValObj.value);\n } else if (str.match(/required/)) {\n type = type.required();\n } else {\n // If not required and no default, make it optional\n type = type.optional();\n }\n\n return type;\n }\n\n /**\n * Validate a value against a definition\n */\n validate(key: string, val: any, def: any): any {\n // Convert null to undefined so Joi defaults can be applied\n // Joi's .default() only works with undefined, not null\n const normalizedVal = val === null ? undefined : val;\n \n // Pass current params as context to support cross-parameter references (e.g., @startTime+2h)\n // Use abortEarly: false to get all errors, and allowUnknown: false for strict validation\n const { value, error } = def.type.validate(normalizedVal, { \n context: { params: this.params },\n abortEarly: false,\n allowUnknown: false,\n });\n if (error) {\n const errs = error.details.map((el: any) => el.message).join(\", \");\n throw new ParamError(`\"${key}\" validation error: ${errs}`);\n }\n return value;\n }\n\n /**\n * Get a parameter value with validation\n */\n get(key: string, definition?: ParamDefinition): any {\n const def = this.assignDefinition(key, definition);\n let valFromGetters: any = undefined;\n \n if (def.volatile || true) {\n valFromGetters = this.runAllRegisteredGetters(key);\n }\n \n const valFromArgs = this.args.get(key);\n const valFromParams = this.params[key];\n\n let source: \"cli\" | \"options\" | \"default\" = \"default\";\n let value: any;\n\n if (valFromGetters !== undefined && valFromGetters !== null) {\n value = this.validate(key, valFromGetters, def);\n source = \"options\";\n } else if (valFromArgs !== undefined && valFromArgs !== null) {\n value = this.validate(key, valFromArgs, def);\n source = \"cli\";\n } else if (valFromParams !== undefined && valFromParams !== null) {\n value = this.validate(key, valFromParams, def);\n source = \"options\";\n } else {\n // Use default from definition - Joi will apply default when value is undefined\n // We need to pass undefined explicitly so Joi can apply the default\n value = this.validate(key, undefined, def);\n source = \"default\";\n }\n\n // Track parameter for --stopAfter=init\n this.trackParam(key, definition || \"string\", value, source);\n\n if (value !== undefined && def.values && !def.values.includes(value)) {\n throw new ParamError(`key ${key} should be one of ${def.values}`);\n }\n return value;\n }\n\n /**\n * Set a parameter value with validation\n */\n set(key: string, val: any, definition?: ParamDefinition): void {\n // TODO: check if there's a test for this:\n if (val && val.type && val.value) {\n definition = val;\n val = val.value;\n }\n const def = this.assignDefinition(key, definition);\n\n if (!this.runAllRegisteredSetters(key, val)) {\n this.params[key] = val;\n }\n }\n\n /**\n * Get all parameters from definitions\n * Processes parameters left-to-right to support cross-parameter references\n */\n getAll(defs: Record<string, ParamDefinition>): Record<string, any> {\n const res: Record<string, any> = {};\n for (const [k, def] of Object.entries(defs)) {\n const value = this.get(k, def);\n res[k] = value;\n // Store validated value in params so subsequent params can reference it\n if (value !== undefined) {\n this.params[k] = value;\n }\n }\n return res;\n }\n\n /**\n * Run all registered getters for a key\n */\n runAllRegisteredGetters(key: string): any {\n let val: any = undefined;\n for (const getter of this.paramGetters) {\n val = getter(key, this.definitions[key]);\n if (val !== undefined && val !== null) {\n break;\n }\n }\n return val;\n }\n\n /**\n * Run all registered setters for a key\n */\n runAllRegisteredSetters(key: string, value: any): boolean {\n let setterUsed: boolean = false;\n for (const setter of this.paramSetters) {\n setterUsed = setter(key, value);\n if (setterUsed) {\n break;\n }\n }\n return setterUsed;\n }\n\n /**\n * Register a parameter getter\n */\n registerParamGetter(fn: ParamGetter): void {\n this.paramGetters.push(fn);\n }\n\n /**\n * Register a parameter setter\n */\n registerParamSetter(fn: ParamSetter): void {\n this.paramSetters.push(fn);\n }\n}\n\n// Export custom types for external use\nexport { joiEdateType, joiStringArrayType };\n\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors.js\";\n\n/**\n * Custom Joi type for enhanced date parsing with relative time support\n * Supports:\n * - ISO8601 strings: \"2025-01-01T01:01:01Z\"\n * - Relative time: \"-2h\", \"+1d\", \"now\"\n * - Cross-parameter references: \"@startTime+2h\", \"@endDate-30m\"\n * \n * Internal representation: UTC ISO8601 string (YYYY-MM-DDTHH:mm:ssZ)\n * \n * @param value - Date value to parse\n * @param helpers - Joi helpers (includes context with other params)\n * @returns ISO8601 string in UTC timezone\n */\nexport const joiEdateType = (value: any, helpers: Joi.CustomHelpers): string => {\n // If value is already a string in ISO format, validate and return\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/.test(value)) {\n const testDate = new Date(value);\n if (!isNaN(testDate.getTime())) {\n return value;\n }\n }\n\n // If value is a Date object, convert to ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // If value is not a string, try to convert it\n if (typeof value !== \"string\") {\n value = String(value);\n }\n\n // Handle special keyword \"now\"\n if (value.toLowerCase() === \"now\") {\n return new Date().toISOString();\n }\n\n // Check for cross-parameter reference with relative time: @paramName+2h, @paramName-30m\n const referenceRegex = /^@(\\w+)([+-]\\d+[smhdwy])$/i;\n const referenceMatch = value.match(referenceRegex);\n \n if (referenceMatch) {\n const [, paramName, relativeExpr] = referenceMatch;\n \n // Get the referenced parameter from context (if available via helpers.state.ancestors)\n // For now, we'll use helpers.prefs.context which Joi provides\n const context = (helpers as any).prefs?.context;\n \n if (!context || !context.params) {\n throw new ParamError(`Cannot resolve cross-parameter reference @${paramName}: context not available. Ensure parameters are processed with proper context.`);\n }\n\n const referencedValue = context.params[paramName];\n \n if (referencedValue === undefined || referencedValue === null) {\n throw new ParamError(`Cannot resolve @${paramName}: parameter \"${paramName}\" is not defined or has no value. Parameters are evaluated left-to-right.`);\n }\n\n // Referenced value should be an ISO string or Date\n let referenceDate: Date;\n if (referencedValue instanceof Date) {\n referenceDate = referencedValue;\n } else if (typeof referencedValue === \"string\") {\n referenceDate = new Date(referencedValue);\n if (isNaN(referenceDate.getTime())) {\n throw new ParamError(`Referenced parameter @${paramName} has invalid date value: ${referencedValue}`);\n }\n } else {\n throw new ParamError(`Referenced parameter @${paramName} is not a valid date type (found: ${typeof referencedValue})`);\n }\n\n // Parse the relative expression and apply to reference date\n const relativeMatch = relativeExpr.match(/^([+-])(\\d+)([smhdwy])$/i);\n if (!relativeMatch) {\n throw new ParamError(`Invalid relative time expression in @${paramName}${relativeExpr}`);\n }\n\n const [, sign, amount, unit] = relativeMatch;\n const offset = calculateTimeOffset(parseInt(amount, 10), unit, sign);\n const resultDate = new Date(referenceDate.getTime() + offset);\n \n return resultDate.toISOString();\n }\n\n // Check for relative time expressions like \"-2h\", \"+1d\", \"-30m\", etc.\n const relativeTimeRegex = /^([+-])(\\d+)([smhdwy])$/i;\n const relativeMatch = value.match(relativeTimeRegex);\n \n if (relativeMatch) {\n const [, sign, amount, unit] = relativeMatch;\n const numAmount = parseInt(amount, 10);\n \n if (isNaN(numAmount)) {\n throw new ParamError(`Invalid relative time amount: ${amount}`);\n }\n\n const offset = calculateTimeOffset(numAmount, unit, sign);\n const resultDate = new Date(Date.now() + offset);\n \n return resultDate.toISOString();\n }\n\n // Try to parse as a regular date string\n const parsedDate = new Date(value);\n \n // Check if the parsed date is valid\n if (isNaN(parsedDate.getTime())) {\n throw new ParamError(`Invalid date format: ${value}. Expected a valid date string, \"now\", relative time expression (e.g., \"-2h\", \"+1d\"), or cross-parameter reference (e.g., \"@startTime+2h\")`);\n }\n\n return parsedDate.toISOString();\n};\n\n/**\n * Calculate time offset in milliseconds\n */\nfunction calculateTimeOffset(amount: number, unit: string, sign: string): number {\n let multiplier = 1;\n \n // Convert to milliseconds based on unit\n switch (unit.toLowerCase()) {\n case \"s\": // seconds\n multiplier = 1000;\n break;\n case \"m\": // minutes\n multiplier = 60 * 1000;\n break;\n case \"h\": // hours\n multiplier = 60 * 60 * 1000;\n break;\n case \"d\": // days\n multiplier = 24 * 60 * 60 * 1000;\n break;\n case \"w\": // weeks\n multiplier = 7 * 24 * 60 * 60 * 1000;\n break;\n case \"y\": // years (approximate)\n multiplier = 365 * 24 * 60 * 60 * 1000;\n break;\n default:\n throw new ParamError(`Invalid time unit: ${unit}. Supported units: s, m, h, d, w, y`);\n }\n\n return sign === \"+\" ? amount * multiplier : -amount * multiplier;\n}\n\n/**\n * Custom Joi type for string array parsing\n * Converts comma-separated strings to typed arrays\n */\nexport const joiStringArrayType = (type: string) => (value: any, helpers: Joi.CustomHelpers): any[] => {\n if (value === undefined || typeof value === \"function\") {\n return [];\n }\n \n const arr = value.split(/,\\s*/).map((el: string) => {\n if (type === \"number\") {\n const v = parseInt(el, 10);\n if (isNaN(v)) {\n throw new ParamError(`array element \"${el}\" should be numeric`);\n }\n return v;\n } else if (type === \"boolean\") {\n const v = el.match(/true|t|yes|1/i) ? true :\n el.match(/false|f|no|0/i) ? false : null;\n if (v === null) {\n throw new ParamError(`array element \"${el}\" should be boolean`);\n }\n return v;\n } else if (type === \"string\") {\n return el;\n } else {\n throw new ParamError(`unknown type \"${type}\" for array elements`);\n }\n });\n \n return arr;\n};\n\n"],"mappings":"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","names":["relativeMatch"]}
|
|
1
|
+
{"version":3,"sources":["../src/params/index.ts","../src/errors.ts","../src/params/custom-types.ts"],"sourcesContent":["import Joi from \"joi\";\nimport { ParamError } from \"../errors\";\nimport { joiEdateType, joiStringArrayType } from \"./custom-types\";\n\n/**\n * Parameter definition types\n */\nexport type ParamDefinition = \n | string \n | Joi.Schema \n | { \n type?: string | Joi.Schema; \n values?: any[]; \n [key: string]: any; \n };\n\nexport type ParamGetter = (key: string, definition?: any) => any;\nexport type ParamSetter = (key: string, value: any) => boolean;\n\n/**\n * Args instance interface\n */\nexport interface ArgsInstance {\n get(key: string): any;\n}\n\n/**\n * Params constructor options\n */\nexport interface ParamsOptions {\n [key: string]: any;\n}\n\n/**\n * Tracked parameter information for --stopAfter=init\n */\ninterface TrackedParam {\n key: string;\n definition: ParamDefinition;\n value: any;\n source: \"cli\" | \"options\" | \"default\";\n}\n\n/**\n * Params class for parameter validation and type checking\n * Built on top of Args library with Joi validation\n */\nexport class Params {\n private context: any; // Partial context during initialization\n private params: Record<string, any> = {};\n private definitions: Record<string, any> = {};\n private args: ArgsInstance;\n private paramSetters: ParamSetter[] = [];\n private paramGetters: ParamGetter[] = [];\n private trackedParams: TrackedParam[] = [];\n\n constructor(context: any, options: ParamsOptions = {}) {\n // Context might be partial during initialization\n this.context = context;\n this.args = context.args;\n\n // Apply initial configuration\n if (Object.keys(options).length > 0) {\n this.configure(options);\n }\n }\n\n /**\n * Configure parameters\n * Only parameters present in options are updated\n */\n configure(options: ParamsOptions): void {\n for (const [k, v] of Object.entries(options)) {\n // TODO: opt values might be an object with definitions in it, so perhaps `this.set` should be used\n this.params[k] = v;\n }\n }\n\n /**\n * Initialize Params from context and CLI parameters\n * Note: Params is special - it's initialized early with partial context\n */\n static init(context: any, options?: ParamsOptions): Params {\n return new Params(context, options || {});\n }\n\n /**\n * Track a parameter request for --stopAfter=init feature\n */\n private trackParam(key: string, definition: ParamDefinition, value: any, source: \"cli\" | \"options\" | \"default\"): void {\n this.trackedParams.push({\n key,\n definition,\n value,\n source\n });\n }\n\n /**\n * Get all tracked parameters (for --stopAfter=init)\n */\n getTrackedParams(): TrackedParam[] {\n return [...this.trackedParams];\n }\n\n /**\n * Get all figured parameters as a record\n * Returns all parameters that were collected during initialization,\n * whether from CLI args, options, or defaults\n */\n getAllFigured(): Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> {\n const result: Record<string, { value: any; source: \"cli\" | \"options\" | \"default\" }> = {};\n for (const param of this.trackedParams) {\n result[param.key] = {\n value: param.value,\n source: param.source,\n };\n }\n return result;\n }\n\n /**\n * Clear tracked parameters\n */\n clearTrackedParams(): void {\n this.trackedParams = [];\n }\n\n /**\n * Assign a parameter definition\n */\n assignDefinition(key: string, definition?: ParamDefinition): any {\n if (this.definitions[key] && !definition) {\n return this.definitions[key];\n }\n\n let type: Joi.Schema;\n if (!definition) {\n type = Joi.string();\n } else if (Joi.isSchema(definition)) {\n type = definition;\n } else if (Joi.isSchema(definition.type)) {\n type = definition.type;\n } else if (typeof definition === \"string\") {\n type = this.toJoi(definition);\n } else if (typeof definition.type === \"string\") {\n type = this.toJoi(definition.type);\n } else if (!definition.type) {\n type = Joi.string();\n } else {\n type = Joi.string();\n }\n\n if (!this.definitions[key]) {\n this.definitions[key] = {};\n }\n this.definitions[key].type = type;\n\n if (definition && definition.values) {\n if (Array.isArray(definition.values)) {\n this.definitions[key].values = definition.values;\n }\n }\n return this.definitions[key];\n }\n\n /**\n * Convert string definition to Joi schema\n */\n toJoi(str: string): Joi.Schema {\n let type: Joi.Schema;\n \n if (str.match(/^string|^text/i)) {\n type = Joi.string();\n } else if (str.match(/^number|^integer|^int/i)) {\n type = Joi.number();\n } else if (str.match(/^boolean|^bool/i)) {\n type = Joi.boolean();\n } else if (str.match(/^date/i)) {\n type = Joi.custom(joiEdateType);\n } else if (str.match(/^duration/i)) {\n type = Joi.string().isoDuration();\n } else if (str.match(/^array/i)) {\n let elementTypes = \"string\";\n const tmp = str.match(/\\((.*)\\)/);\n if (tmp && tmp[1].match(/string/i)) {\n elementTypes = \"string\";\n } else if (tmp && tmp[1].match(/number|integer|int/i)) {\n elementTypes = \"number\";\n } else if (tmp && tmp[1].match(/boolean|bool/i)) {\n elementTypes = \"boolean\";\n }\n type = Joi.custom(joiStringArrayType(elementTypes));\n } else {\n type = Joi.string();\n }\n\n // Handle default values\n const regexForDefault = /\\bdefault\\s+([^\\s]+)/;\n const matchForDefault = str.match(regexForDefault);\n if (matchForDefault) {\n const defValObj = type.validate(matchForDefault[1]);\n if (defValObj.error) {\n throw new ParamError(`default value \"${defValObj.value}\" type mismatch`);\n }\n // Joi's default() automatically allows undefined and applies the default\n type = type.default(defValObj.value);\n } else if (str.match(/required/)) {\n type = type.required();\n } else {\n // If not required and no default, make it optional\n type = type.optional();\n }\n\n return type;\n }\n\n /**\n * Validate a value against a definition\n */\n validate(key: string, val: any, def: any): any {\n // Convert null to undefined so Joi defaults can be applied\n // Joi's .default() only works with undefined, not null\n const normalizedVal = val === null ? undefined : val;\n \n // Pass current params as context to support cross-parameter references (e.g., @startTime+2h)\n // Use abortEarly: false to get all errors, and allowUnknown: false for strict validation\n const { value, error } = def.type.validate(normalizedVal, { \n context: { params: this.params },\n abortEarly: false,\n allowUnknown: false,\n });\n if (error) {\n const errs = error.details.map((el: any) => el.message).join(\", \");\n throw new ParamError(`\"${key}\" validation error: ${errs}`);\n }\n return value;\n }\n\n /**\n * Get a parameter value with validation\n */\n get(key: string, definition?: ParamDefinition): any {\n const def = this.assignDefinition(key, definition);\n let valFromGetters: any = undefined;\n \n if (def.volatile || true) {\n valFromGetters = this.runAllRegisteredGetters(key);\n }\n \n // Always call args.get() to mark the key as used, even if it doesn't exist\n // This ensures flags are marked as used regardless of when they're parsed\n const valFromArgs = this.args.get(key);\n const valFromParams = this.params[key];\n\n let source: \"cli\" | \"options\" | \"default\" = \"default\";\n let value: any;\n\n if (valFromGetters !== undefined && valFromGetters !== null) {\n value = this.validate(key, valFromGetters, def);\n source = \"options\";\n } else if (valFromArgs !== undefined && valFromArgs !== null) {\n value = this.validate(key, valFromArgs, def);\n source = \"cli\";\n } else if (valFromParams !== undefined && valFromParams !== null) {\n value = this.validate(key, valFromParams, def);\n source = \"options\";\n } else {\n // Use default from definition - Joi will apply default when value is undefined\n // We need to pass undefined explicitly so Joi can apply the default\n value = this.validate(key, undefined, def);\n source = \"default\";\n }\n\n // Track parameter for --stopAfter=init\n this.trackParam(key, definition || \"string\", value, source);\n\n if (value !== undefined && def.values && !def.values.includes(value)) {\n throw new ParamError(`key ${key} should be one of ${def.values}`);\n }\n return value;\n }\n\n /**\n * Set a parameter value with validation\n */\n set(key: string, val: any, definition?: ParamDefinition): void {\n // TODO: check if there's a test for this:\n if (val && val.type && val.value) {\n definition = val;\n val = val.value;\n }\n const def = this.assignDefinition(key, definition);\n\n if (!this.runAllRegisteredSetters(key, val)) {\n this.params[key] = val;\n }\n }\n\n /**\n * Get all parameters from definitions\n * Processes parameters left-to-right to support cross-parameter references\n */\n getAll(defs: Record<string, ParamDefinition>): Record<string, any> {\n const res: Record<string, any> = {};\n for (const [k, def] of Object.entries(defs)) {\n const value = this.get(k, def);\n res[k] = value;\n // Store validated value in params so subsequent params can reference it\n if (value !== undefined) {\n this.params[k] = value;\n }\n }\n return res;\n }\n\n /**\n * Run all registered getters for a key\n */\n runAllRegisteredGetters(key: string): any {\n let val: any = undefined;\n for (const getter of this.paramGetters) {\n val = getter(key, this.definitions[key]);\n if (val !== undefined && val !== null) {\n break;\n }\n }\n return val;\n }\n\n /**\n * Run all registered setters for a key\n */\n runAllRegisteredSetters(key: string, value: any): boolean {\n let setterUsed: boolean = false;\n for (const setter of this.paramSetters) {\n setterUsed = setter(key, value);\n if (setterUsed) {\n break;\n }\n }\n return setterUsed;\n }\n\n /**\n * Register a parameter getter\n */\n registerParamGetter(fn: ParamGetter): void {\n this.paramGetters.push(fn);\n }\n\n /**\n * Register a parameter setter\n */\n registerParamSetter(fn: ParamSetter): void {\n this.paramSetters.push(fn);\n }\n}\n\n// Export custom types for external use\nexport { joiEdateType, joiStringArrayType };\n\n","/**\n * Error classes for the CLI toolkit\n */\n\nexport class FrameworkError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrameworkError\";\n }\n}\n\nexport class ParamError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"ParamError\";\n }\n}\n\nexport class InitError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"InitError\";\n }\n}\n\nexport class CriticalRequestError extends FrameworkError {\n constructor(message: string) {\n super(message);\n this.name = \"CriticalRequestError\";\n }\n}\n\nexport class ControlFlowError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ControlFlowError\";\n }\n}\n\n","import Joi from \"joi\";\nimport { ParamError } from \"../errors.js\";\n\n/**\n * Custom Joi type for enhanced date parsing with relative time support\n * Supports:\n * - ISO8601 strings: \"2025-01-01T01:01:01Z\"\n * - Relative time: \"-2h\", \"+1d\", \"now\"\n * - Cross-parameter references: \"@startTime+2h\", \"@endDate-30m\"\n * \n * Internal representation: UTC ISO8601 string (YYYY-MM-DDTHH:mm:ssZ)\n * \n * @param value - Date value to parse\n * @param helpers - Joi helpers (includes context with other params)\n * @returns ISO8601 string in UTC timezone\n */\nexport const joiEdateType = (value: any, helpers: Joi.CustomHelpers): string => {\n // If value is already a string in ISO format, validate and return\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/.test(value)) {\n const testDate = new Date(value);\n if (!isNaN(testDate.getTime())) {\n return value;\n }\n }\n\n // If value is a Date object, convert to ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // If value is not a string, try to convert it\n if (typeof value !== \"string\") {\n value = String(value);\n }\n\n // Handle special keyword \"now\"\n if (value.toLowerCase() === \"now\") {\n return new Date().toISOString();\n }\n\n // Check for cross-parameter reference with relative time: @paramName+2h, @paramName-30m\n const referenceRegex = /^@(\\w+)([+-]\\d+[smhdwy])$/i;\n const referenceMatch = value.match(referenceRegex);\n \n if (referenceMatch) {\n const [, paramName, relativeExpr] = referenceMatch;\n \n // Get the referenced parameter from context (if available via helpers.state.ancestors)\n // For now, we'll use helpers.prefs.context which Joi provides\n const context = (helpers as any).prefs?.context;\n \n if (!context || !context.params) {\n throw new ParamError(`Cannot resolve cross-parameter reference @${paramName}: context not available. Ensure parameters are processed with proper context.`);\n }\n\n const referencedValue = context.params[paramName];\n \n if (referencedValue === undefined || referencedValue === null) {\n throw new ParamError(`Cannot resolve @${paramName}: parameter \"${paramName}\" is not defined or has no value. Parameters are evaluated left-to-right.`);\n }\n\n // Referenced value should be an ISO string or Date\n let referenceDate: Date;\n if (referencedValue instanceof Date) {\n referenceDate = referencedValue;\n } else if (typeof referencedValue === \"string\") {\n referenceDate = new Date(referencedValue);\n if (isNaN(referenceDate.getTime())) {\n throw new ParamError(`Referenced parameter @${paramName} has invalid date value: ${referencedValue}`);\n }\n } else {\n throw new ParamError(`Referenced parameter @${paramName} is not a valid date type (found: ${typeof referencedValue})`);\n }\n\n // Parse the relative expression and apply to reference date\n const relativeMatch = relativeExpr.match(/^([+-])(\\d+)([smhdwy])$/i);\n if (!relativeMatch) {\n throw new ParamError(`Invalid relative time expression in @${paramName}${relativeExpr}`);\n }\n\n const [, sign, amount, unit] = relativeMatch;\n const offset = calculateTimeOffset(parseInt(amount, 10), unit, sign);\n const resultDate = new Date(referenceDate.getTime() + offset);\n \n return resultDate.toISOString();\n }\n\n // Check for relative time expressions like \"-2h\", \"+1d\", \"-30m\", etc.\n const relativeTimeRegex = /^([+-])(\\d+)([smhdwy])$/i;\n const relativeMatch = value.match(relativeTimeRegex);\n \n if (relativeMatch) {\n const [, sign, amount, unit] = relativeMatch;\n const numAmount = parseInt(amount, 10);\n \n if (isNaN(numAmount)) {\n throw new ParamError(`Invalid relative time amount: ${amount}`);\n }\n\n const offset = calculateTimeOffset(numAmount, unit, sign);\n const resultDate = new Date(Date.now() + offset);\n \n return resultDate.toISOString();\n }\n\n // Try to parse as a regular date string\n const parsedDate = new Date(value);\n \n // Check if the parsed date is valid\n if (isNaN(parsedDate.getTime())) {\n throw new ParamError(`Invalid date format: ${value}. Expected a valid date string, \"now\", relative time expression (e.g., \"-2h\", \"+1d\"), or cross-parameter reference (e.g., \"@startTime+2h\")`);\n }\n\n return parsedDate.toISOString();\n};\n\n/**\n * Calculate time offset in milliseconds\n */\nfunction calculateTimeOffset(amount: number, unit: string, sign: string): number {\n let multiplier = 1;\n \n // Convert to milliseconds based on unit\n switch (unit.toLowerCase()) {\n case \"s\": // seconds\n multiplier = 1000;\n break;\n case \"m\": // minutes\n multiplier = 60 * 1000;\n break;\n case \"h\": // hours\n multiplier = 60 * 60 * 1000;\n break;\n case \"d\": // days\n multiplier = 24 * 60 * 60 * 1000;\n break;\n case \"w\": // weeks\n multiplier = 7 * 24 * 60 * 60 * 1000;\n break;\n case \"y\": // years (approximate)\n multiplier = 365 * 24 * 60 * 60 * 1000;\n break;\n default:\n throw new ParamError(`Invalid time unit: ${unit}. Supported units: s, m, h, d, w, y`);\n }\n\n return sign === \"+\" ? amount * multiplier : -amount * multiplier;\n}\n\n/**\n * Custom Joi type for string array parsing\n * Converts comma-separated strings to typed arrays\n */\nexport const joiStringArrayType = (type: string) => (value: any, helpers: Joi.CustomHelpers): any[] => {\n if (value === undefined || typeof value === \"function\") {\n return [];\n }\n \n const arr = value.split(/,\\s*/).map((el: string) => {\n if (type === \"number\") {\n const v = parseInt(el, 10);\n if (isNaN(v)) {\n throw new ParamError(`array element \"${el}\" should be numeric`);\n }\n return v;\n } else if (type === \"boolean\") {\n const v = el.match(/true|t|yes|1/i) ? true :\n el.match(/false|f|no|0/i) ? false : null;\n if (v === null) {\n throw new ParamError(`array element \"${el}\" should be boolean`);\n }\n return v;\n } else if (type === \"string\") {\n return el;\n } else {\n throw new ParamError(`unknown type \"${type}\" for array elements`);\n }\n });\n \n return arr;\n};\n\n"],"mappings":"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","names":["relativeMatch"]}
|