@curl-runner/cli 1.22.0 → 1.23.1
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/cli.js +528 -0
- package/dist/cli.js.map +65 -0
- package/package.json +5 -2
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../node_modules/picocolors/picocolors.js", "../../../node_modules/sisteransi/src/index.js", "../src/cli.ts", "../src/utils/colors.ts", "../src/utils/installation-detector.ts", "../src/version.ts", "../src/commands/upgrade.ts", "../src/commands/validate.ts", "../src/core/interpolator/variable-resolver.ts", "../src/parser/yaml.ts", "../src/convert/batch-parser.ts", "../src/convert/curl-generator.ts", "../src/convert/tokenizer.ts", "../src/convert/curl-parser.ts", "../src/convert/normalizer.ts", "../src/convert/yaml-serializer.ts", "../src/convert/yaml-to-ir.ts", "../src/convert/convert-command.ts", "../src/core/config/cli-parser.ts", "../src/core/config/env-file-loader.ts", "../src/core/config/env-loader.ts", "../src/core/config/file-loader.ts", "../src/utils/secret-redactor.ts", "../src/core/config/resolver.ts", "../src/diff/baseline-manager.ts", "../src/core/format/formatters.ts", "../src/core/format/tree-renderer.ts", "../src/diff/diff-formatter.ts", "../src/diff/response-differ.ts", "../src/core/curl/types.ts", "../src/core/curl/args-builder.ts", "../src/core/curl/body-parser.ts", "../src/core/curl/response-parser.ts", "../src/utils/curl-builder.ts", "../src/snapshot/snapshot-formatter.ts", "../src/utils/stats.ts", "../src/utils/logger.ts", "../src/executor/profile-executor.ts", "../src/core/validation/validators.ts", "../src/core/execution/post-processor.ts", "../src/core/execution/retry.ts", "../src/snapshot/snapshot-manager.ts", "../src/snapshot/snapshot-differ.ts", "../src/utils/response-store.ts", "../src/utils/condition-evaluator.ts", "../src/executor/pooled-curl-executor.ts", "../src/executor/request-executor.ts", "../src/utils/version-checker.ts", "../src/watcher/file-watcher.ts", "../../../node_modules/@clack/core/dist/index.mjs", "../../../node_modules/@clack/prompts/dist/index.mjs", "../src/wizard/parser.ts", "../src/wizard/templates.ts", "../src/wizard/prompts.ts", "../src/wizard/yaml-builder.ts", "../src/wizard/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n",
|
|
6
|
+
"'use strict';\n\nconst ESC = '\\x1B';\nconst CSI = `${ESC}[`;\nconst beep = '\\u0007';\n\nconst cursor = {\n to(x, y) {\n if (!y) return `${CSI}${x + 1}G`;\n return `${CSI}${y + 1};${x + 1}H`;\n },\n move(x, y) {\n let ret = '';\n\n if (x < 0) ret += `${CSI}${-x}D`;\n else if (x > 0) ret += `${CSI}${x}C`;\n\n if (y < 0) ret += `${CSI}${-y}A`;\n else if (y > 0) ret += `${CSI}${y}B`;\n\n return ret;\n },\n up: (count = 1) => `${CSI}${count}A`,\n down: (count = 1) => `${CSI}${count}B`,\n forward: (count = 1) => `${CSI}${count}C`,\n backward: (count = 1) => `${CSI}${count}D`,\n nextLine: (count = 1) => `${CSI}E`.repeat(count),\n prevLine: (count = 1) => `${CSI}F`.repeat(count),\n left: `${CSI}G`,\n hide: `${CSI}?25l`,\n show: `${CSI}?25h`,\n save: `${ESC}7`,\n restore: `${ESC}8`\n}\n\nconst scroll = {\n up: (count = 1) => `${CSI}S`.repeat(count),\n down: (count = 1) => `${CSI}T`.repeat(count)\n}\n\nconst erase = {\n screen: `${CSI}2J`,\n up: (count = 1) => `${CSI}1J`.repeat(count),\n down: (count = 1) => `${CSI}J`.repeat(count),\n line: `${CSI}2K`,\n lineEnd: `${CSI}K`,\n lineStart: `${CSI}1K`,\n lines(count) {\n let clear = '';\n for (let i = 0; i < count; i++)\n clear += this.line + (i < count - 1 ? cursor.up() : '');\n if (count)\n clear += cursor.left;\n return clear;\n }\n}\n\nmodule.exports = { cursor, scroll, erase, beep };\n",
|
|
7
|
+
"#!/usr/bin/env bun\n\nimport { Glob } from 'bun';\nimport { showUpgradeHelp, UpgradeCommand } from './commands/upgrade';\nimport { showValidateHelp, ValidateCommand } from './commands/validate';\nimport {\n convertCurlToYaml,\n convertFileToYaml,\n convertYamlToCurl,\n parseConvertArgs,\n} from './convert';\nimport {\n buildProfileConfig,\n buildWatchConfig,\n type CLIOptions,\n mergeGlobalConfigs,\n parseEditArgs,\n parseInitArgs,\n resolveConfig,\n} from './core/config';\nimport { BaselineManager, DiffFormatter, DiffOrchestrator } from './diff';\nimport { ProfileExecutor } from './executor/profile-executor';\nimport { RequestExecutor } from './executor/request-executor';\nimport { YamlParser } from './parser/yaml';\nimport type {\n DiffConfig,\n ExecutionResult,\n ExecutionSummary,\n GlobalConfig,\n GlobalDiffConfig,\n ProfileConfig,\n RequestConfig,\n} from './types/config';\nimport { Logger } from './utils/logger';\nimport { exportToCSV, exportToJSON } from './utils/stats';\nimport { VersionChecker } from './utils/version-checker';\nimport { getVersion } from './version';\nimport { FileWatcher } from './watcher/file-watcher';\nimport { quickInit, runWizard } from './wizard';\n\nclass CurlRunnerCLI {\n private logger = new Logger();\n\n async run(args: string[]): Promise<void> {\n try {\n // Resolve config from all sources (CLI, env, file)\n const resolved = await resolveConfig(args, {\n onInfo: (msg) => this.logger.logInfo(msg),\n onWarning: (msg) => this.logger.logWarning(msg),\n });\n\n const { config, cliOptions, mode, rawArgs } = resolved;\n\n // Check for updates in background (non-blocking)\n if (mode !== 'version' && mode !== 'help') {\n new VersionChecker().checkForUpdates().catch(() => {});\n }\n\n // Handle execution modes\n switch (mode) {\n case 'help':\n this.showHelp();\n return;\n\n case 'version':\n console.log(`curl-runner v${getVersion()}`);\n return;\n\n case 'upgrade':\n if (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n showUpgradeHelp();\n return;\n }\n await new UpgradeCommand().run(rawArgs.slice(1));\n return;\n\n case 'validate':\n if (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n showValidateHelp();\n return;\n }\n await new ValidateCommand().run(rawArgs.slice(1));\n return;\n\n case 'diff-subcommand':\n await this.executeDiffSubcommand(rawArgs.slice(1), cliOptions);\n return;\n\n case 'convert':\n await this.executeConvert(rawArgs);\n return;\n\n case 'init':\n await this.executeInit(rawArgs);\n return;\n\n case 'edit':\n await this.executeEdit(rawArgs);\n return;\n\n case 'profile':\n case 'watch':\n case 'normal':\n await this.executeMain(cliOptions, config, mode);\n return;\n }\n } catch (error) {\n this.logger.logError(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n }\n\n private async executeMain(\n cliOptions: CLIOptions,\n globalConfig: GlobalConfig,\n mode: 'normal' | 'watch' | 'profile',\n ): Promise<void> {\n // Find YAML files\n const yamlFiles = await this.findYamlFiles(cliOptions.files, cliOptions.all);\n\n if (yamlFiles.length === 0) {\n this.logger.logError('No YAML files found');\n process.exit(1);\n }\n\n this.logger.logInfo(`Found ${yamlFiles.length} YAML file(s)`);\n\n // Process YAML files and collect requests\n const allRequests: RequestConfig[] = [];\n let mergedConfig = globalConfig;\n\n for (const file of yamlFiles) {\n this.logger.logInfo(`Processing: ${file}`);\n const { requests, config } = await this.processYamlFile(file);\n\n const fileOutputConfig = config?.output || {};\n const requestsWithSource = requests.map((request) => ({\n ...request,\n sourceOutputConfig: fileOutputConfig,\n sourceFile: file,\n }));\n\n if (config) {\n mergedConfig = mergeGlobalConfigs(mergedConfig, config);\n }\n\n allRequests.push(...requestsWithSource);\n }\n\n if (allRequests.length === 0) {\n this.logger.logError('No requests found in YAML files');\n process.exit(1);\n }\n\n // Execute based on mode\n if (mode === 'profile') {\n const profileConfig = buildProfileConfig(cliOptions, mergedConfig);\n await this.executeProfileMode(allRequests, mergedConfig, profileConfig);\n } else if (mode === 'watch') {\n const watchConfig = buildWatchConfig(cliOptions, mergedConfig);\n const watcher = new FileWatcher({\n files: yamlFiles,\n config: watchConfig,\n logger: this.logger,\n onRun: async () => {\n await this.executeRequests(yamlFiles, mergedConfig);\n },\n });\n await watcher.start();\n } else {\n const summary = await this.executeRequests(yamlFiles, mergedConfig);\n const exitCode = this.determineExitCode(summary, mergedConfig);\n process.exit(exitCode);\n }\n }\n\n private async executeProfileMode(\n requests: RequestConfig[],\n globalConfig: GlobalConfig,\n profileConfig: ProfileConfig,\n ): Promise<void> {\n const profileExecutor = new ProfileExecutor(globalConfig, profileConfig);\n const results = await profileExecutor.profileRequests(requests);\n\n this.logger.logProfileSummary(results);\n\n if (profileConfig.exportFile) {\n const exportData: string[] = [];\n const isCSV = profileConfig.exportFile.endsWith('.csv');\n\n for (const result of results) {\n const name = result.request.name || result.request.url;\n exportData.push(isCSV ? exportToCSV(result.stats, name) : exportToJSON(result.stats, name));\n }\n\n const content = isCSV ? exportData.join('\\n\\n') : `[${exportData.join(',\\n')}]`;\n await Bun.write(profileConfig.exportFile, content);\n this.logger.logInfo(`Profile results exported to ${profileConfig.exportFile}`);\n }\n\n const totalFailures = results.reduce((sum, r) => sum + r.stats.failures, 0);\n const totalIterations = results.reduce(\n (sum, r) => sum + r.stats.iterations + r.stats.warmup,\n 0,\n );\n\n process.exit(totalFailures > 0 && totalFailures / totalIterations > 0.5 ? 1 : 0);\n }\n\n private async executeRequests(\n yamlFiles: string[],\n globalConfig: GlobalConfig,\n ): Promise<ExecutionSummary> {\n const fileGroups: Array<{ file: string; requests: RequestConfig[]; config?: GlobalConfig }> =\n [];\n const allRequests: RequestConfig[] = [];\n\n for (const file of yamlFiles) {\n const { requests, config } = await this.processYamlFile(file);\n\n const fileOutputConfig = config?.output || {};\n const requestsWithSource = requests.map((request) => ({\n ...request,\n sourceOutputConfig: fileOutputConfig,\n sourceFile: file,\n }));\n\n fileGroups.push({ file, requests: requestsWithSource, config });\n allRequests.push(...requestsWithSource);\n }\n\n const executor = new RequestExecutor(globalConfig);\n let summary: ExecutionSummary;\n\n if (fileGroups.length > 1) {\n const allResults: ExecutionResult[] = [];\n let totalDuration = 0;\n\n for (let i = 0; i < fileGroups.length; i++) {\n const group = fileGroups[i];\n this.logger.logFileHeader(group.file, group.requests.length);\n\n const fileSummary = await executor.execute(group.requests);\n allResults.push(...fileSummary.results);\n totalDuration += fileSummary.duration;\n\n if (i < fileGroups.length - 1) {\n console.log();\n }\n }\n\n const successful = allResults.filter((r) => r.success && !r.skipped).length;\n const failed = allResults.filter((r) => !r.success && !r.skipped).length;\n const skipped = allResults.filter((r) => r.skipped).length;\n\n summary = {\n total: allResults.length,\n successful,\n failed,\n skipped,\n duration: totalDuration,\n results: allResults,\n };\n this.logger.logSummary(summary, true);\n } else {\n summary = await executor.execute(allRequests);\n }\n\n if (globalConfig.diff?.enabled || globalConfig.diff?.save || globalConfig.diff?.compareWith) {\n await this.handleDiffMode(yamlFiles[0], summary.results, globalConfig.diff);\n }\n\n return summary;\n }\n\n private async handleDiffMode(\n yamlPath: string,\n results: ExecutionResult[],\n diffConfig: GlobalDiffConfig,\n ): Promise<void> {\n const orchestrator = new DiffOrchestrator(diffConfig);\n const formatter = new DiffFormatter(diffConfig.outputFormat || 'terminal');\n const config: DiffConfig = BaselineManager.mergeConfig(diffConfig, true) || {};\n\n const currentLabel = diffConfig.label || 'current';\n const compareLabel = diffConfig.compareWith;\n\n if (diffConfig.save) {\n await orchestrator.saveBaseline(yamlPath, currentLabel, results, config);\n this.logger.logInfo(`Baseline saved as '${currentLabel}'`);\n }\n\n if (compareLabel) {\n const diffSummary = await orchestrator.compareWithBaseline(\n yamlPath,\n results,\n currentLabel,\n compareLabel,\n config,\n );\n\n if (diffSummary.newBaselines === diffSummary.totalRequests) {\n this.logger.logWarning(\n `No baseline '${compareLabel}' found. Saving current run as baseline.`,\n );\n await orchestrator.saveBaseline(yamlPath, compareLabel, results, config);\n return;\n }\n\n console.log(formatter.formatSummary(diffSummary, compareLabel, currentLabel));\n\n if (diffConfig.save) {\n await orchestrator.saveBaseline(yamlPath, currentLabel, results, config);\n }\n } else if (diffConfig.enabled && !diffConfig.save) {\n const labels = await orchestrator.listLabels(yamlPath);\n\n if (labels.length === 0) {\n await orchestrator.saveBaseline(yamlPath, 'baseline', results, config);\n this.logger.logInfo(`No baselines found. Saved current run as 'baseline'.`);\n } else if (labels.length === 1) {\n const diffSummary = await orchestrator.compareWithBaseline(\n yamlPath,\n results,\n currentLabel,\n labels[0],\n config,\n );\n console.log(formatter.formatSummary(diffSummary, labels[0], currentLabel));\n } else {\n this.logger.logInfo(`Available baselines: ${labels.join(', ')}`);\n this.logger.logInfo(`Use --diff-compare <label> to compare against a specific baseline.`);\n }\n }\n }\n\n private async executeConvert(rawArgs: string[]): Promise<void> {\n if (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n this.showConvertHelp();\n return;\n }\n\n const parsed = parseConvertArgs(rawArgs);\n if (!parsed) {\n this.showConvertHelp();\n process.exit(1);\n }\n\n let result: { output: string; warnings: string[]; debug?: unknown };\n\n switch (parsed.subcommand) {\n case 'curl':\n result = convertCurlToYaml(parsed.input, parsed.options);\n break;\n case 'file':\n result = await convertFileToYaml(parsed.input, parsed.options);\n break;\n case 'yaml':\n result = await convertYamlToCurl(parsed.input, parsed.options);\n break;\n }\n\n if (parsed.options.debug && result.debug) {\n console.log(this.logger.color('DEBUG:', 'yellow'));\n console.log(JSON.stringify(result.debug, null, 2));\n console.log();\n }\n\n if (result.warnings.length > 0 && !parsed.options.output) {\n for (const w of result.warnings) {\n this.logger.logWarning(w);\n }\n }\n\n if (parsed.options.output) {\n await Bun.write(parsed.options.output, result.output);\n this.logger.logInfo(`Written to ${parsed.options.output}`);\n } else {\n console.log(result.output);\n }\n }\n\n private async executeInit(rawArgs: string[]): Promise<void> {\n const options = parseInitArgs(rawArgs);\n\n if (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n this.showInitHelp();\n return;\n }\n\n if (options.wizard) {\n await runWizard({ outputPath: options.outputPath });\n } else {\n await quickInit(options.url);\n }\n }\n\n private async executeEdit(rawArgs: string[]): Promise<void> {\n const options = parseEditArgs(rawArgs);\n\n if (rawArgs.includes('--help') || rawArgs.includes('-h')) {\n this.showEditHelp();\n return;\n }\n\n if (!options.file) {\n this.logger.logError('Usage: curl-runner edit <file.yaml>');\n process.exit(1);\n }\n\n await runWizard({\n editFile: options.file,\n outputPath: options.outputPath,\n });\n }\n\n private async executeDiffSubcommand(args: string[], options: CLIOptions): Promise<void> {\n const label1 = args[0];\n const label2 = args[1];\n let yamlFile = args[2];\n\n if (!yamlFile) {\n const yamlFiles = await this.findYamlFiles([], options.all);\n if (yamlFiles.length === 0) {\n this.logger.logError(\n 'No YAML files found. Specify a file: curl-runner diff <label1> <label2> <file.yaml>',\n );\n process.exit(1);\n }\n if (yamlFiles.length > 1) {\n this.logger.logError('Multiple YAML files found. Specify which file to use.');\n process.exit(1);\n }\n yamlFile = yamlFiles[0];\n }\n\n const diffConfig: GlobalDiffConfig = {\n dir: options.diffDir || '__baselines__',\n outputFormat: options.diffOutput || 'terminal',\n };\n\n const orchestrator = new DiffOrchestrator(diffConfig);\n const formatter = new DiffFormatter(diffConfig.outputFormat || 'terminal');\n const config: DiffConfig = { exclude: [], match: {} };\n\n try {\n const diffSummary = await orchestrator.compareTwoBaselines(yamlFile, label1, label2, config);\n console.log(formatter.formatSummary(diffSummary, label1, label2));\n process.exit(diffSummary.changed > 0 ? 1 : 0);\n } catch (error) {\n this.logger.logError(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n }\n\n private async findYamlFiles(patterns: string[], all?: boolean): Promise<string[]> {\n const files: Set<string> = new Set();\n let searchPatterns: string[] = [];\n\n if (patterns.length === 0) {\n searchPatterns = all ? ['**/*.yaml', '**/*.yml'] : ['*.yaml', '*.yml'];\n } else {\n for (const pattern of patterns) {\n try {\n const fs = await import('node:fs/promises');\n const stat = await fs.stat(pattern);\n\n if (stat.isDirectory()) {\n searchPatterns.push(`${pattern}/*.yaml`, `${pattern}/*.yml`);\n if (all) {\n searchPatterns.push(`${pattern}/**/*.yaml`, `${pattern}/**/*.yml`);\n }\n } else if (stat.isFile()) {\n searchPatterns.push(pattern);\n }\n } catch {\n searchPatterns.push(pattern);\n }\n }\n }\n\n for (const pattern of searchPatterns) {\n const globber = new Glob(pattern);\n for await (const file of globber.scan('.')) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n files.add(file);\n }\n }\n }\n\n return Array.from(files).sort();\n }\n\n private async processYamlFile(\n filepath: string,\n ): Promise<{ requests: RequestConfig[]; config?: GlobalConfig }> {\n const yamlContent = await YamlParser.parseFile(filepath);\n const requests: RequestConfig[] = [];\n let globalConfig: GlobalConfig | undefined;\n\n if (yamlContent.global) {\n globalConfig = yamlContent.global;\n }\n\n const variables = { ...yamlContent.global?.variables, ...yamlContent.collection?.variables };\n const defaults = { ...yamlContent.global?.defaults, ...yamlContent.collection?.defaults };\n\n if (yamlContent.request) {\n requests.push(this.prepareRequest(yamlContent.request, variables, defaults));\n }\n\n if (yamlContent.requests) {\n for (const req of yamlContent.requests) {\n requests.push(this.prepareRequest(req, variables, defaults));\n }\n }\n\n if (yamlContent.collection?.requests) {\n for (const req of yamlContent.collection.requests) {\n requests.push(this.prepareRequest(req, variables, defaults));\n }\n }\n\n return { requests, config: globalConfig };\n }\n\n private prepareRequest(\n request: RequestConfig,\n variables: Record<string, string>,\n defaults: Partial<RequestConfig>,\n ): RequestConfig {\n const interpolated = YamlParser.interpolateVariables(request, variables) as RequestConfig;\n return YamlParser.mergeConfigs(defaults, interpolated);\n }\n\n private determineExitCode(summary: ExecutionSummary, config: GlobalConfig): number {\n const { failed, total } = summary;\n const ci = config.ci;\n\n if (failed === 0) {\n return 0;\n }\n\n if (ci) {\n if (ci.strictExit) {\n return 1;\n }\n if (ci.failOn !== undefined && failed > ci.failOn) {\n return 1;\n }\n if (ci.failOnPercentage !== undefined && total > 0) {\n if ((failed / total) * 100 > ci.failOnPercentage) {\n return 1;\n }\n }\n if (ci.failOn !== undefined || ci.failOnPercentage !== undefined) {\n return 0;\n }\n }\n\n return !config.continueOnError ? 1 : 0;\n }\n\n private showInitHelp(): void {\n console.log(`\n${this.logger.color('🚀 CURL RUNNER - INIT', 'bright')}\n\n${this.logger.color('USAGE:', 'yellow')}\n curl-runner init [url] [options]\n\n${this.logger.color('OPTIONS:', 'yellow')}\n -w, --wizard Launch full interactive wizard\n -o, --output <file> Output file path (default: request.yaml)\n -h, --help Show this help\n\n${this.logger.color('EXAMPLES:', 'yellow')}\n # Quick init with prompts\n curl-runner init\n\n # Quick init with URL\n curl-runner init https://api.example.com/users\n\n # Full wizard mode\n curl-runner init --wizard\n\n # Wizard with custom output\n curl-runner init -w -o api-test.yaml\n`);\n }\n\n private showEditHelp(): void {\n console.log(`\n${this.logger.color('🚀 CURL RUNNER - EDIT', 'bright')}\n\n${this.logger.color('USAGE:', 'yellow')}\n curl-runner edit <file.yaml> [options]\n\n${this.logger.color('OPTIONS:', 'yellow')}\n -o, --output <file> Save to different file (default: overwrite original)\n -h, --help Show this help\n\n${this.logger.color('EXAMPLES:', 'yellow')}\n # Edit existing file\n curl-runner edit api-test.yaml\n\n # Edit and save to new file\n curl-runner edit api-test.yaml -o api-test-v2.yaml\n`);\n }\n\n private showConvertHelp(): void {\n console.log(`\n${this.logger.color('CURL RUNNER - CONVERT', 'bright')}\n\n${this.logger.color('USAGE:', 'yellow')}\n curl-runner convert curl \"<curl command>\" Convert curl → YAML\n curl-runner convert file <script.sh> Convert shell script → YAML\n curl-runner convert yaml <test.yaml> Convert YAML → curl\n\n${this.logger.color('OPTIONS:', 'yellow')}\n -o, --output <file> Write output to file\n --pretty Pretty-print output (default for YAML)\n --loss-report Show warnings for unsupported features (default)\n --debug Show token stream, AST, and IR\n -h, --help Show this help\n\n${this.logger.color('EXAMPLES:', 'yellow')}\n # Convert inline curl to YAML\n curl-runner convert curl \"curl -X POST https://api.example.com -d '{\"name\":\"Alex\"}'\"\n\n # Convert and save to file\n curl-runner convert curl \"curl https://api.example.com\" -o test.yaml\n\n # Convert shell script (batch)\n curl-runner convert file scripts/api-tests.sh\n\n # Convert YAML back to curl\n curl-runner convert yaml test.yaml\n\n # Debug mode\n curl-runner convert curl \"curl https://example.com\" --debug\n`);\n }\n\n private showHelp(): void {\n console.log(`\n${this.logger.color('🚀 CURL RUNNER', 'bright')}\n\n${this.logger.color('USAGE:', 'yellow')}\n curl-runner [files...] [options]\n\n${this.logger.color('OPTIONS:', 'yellow')}\n -h, --help Show this help message\n -n, --dry-run Show curl commands without executing\n --http2 Use HTTP/2 protocol with multiplexing\n --connection-pool Enable TCP connection pooling with HTTP/2 multiplexing\n --max-streams <n> Max concurrent streams per host (default: 10)\n --keepalive-time <sec> TCP keepalive time in seconds (default: 60)\n --connect-timeout <sec> Connection timeout in seconds (default: 30)\n -v, --verbose Enable verbose output\n -q, --quiet Suppress non-error output\n -p, --execution parallel Execute requests in parallel\n --max-concurrent <n> Limit concurrent requests in parallel mode\n -c, --continue-on-error Continue execution on errors\n -o, --output <file> Save results to file\n --all Find all YAML files recursively\n --timeout <ms> Set request timeout in milliseconds\n --retries <count> Set maximum retry attempts\n --retry-delay <ms> Set delay between retries in milliseconds\n --no-retry Disable retry mechanism\n --output-format <format> Set output format (json|pretty|raw)\n --pretty-level <level> Set pretty format level (minimal|standard|detailed)\n --show-headers Include response headers in output\n --show-body Include response body in output\n --show-metrics Include performance metrics in output\n --version Show version\n\n${this.logger.color('WATCH MODE:', 'yellow')}\n -w, --watch Watch files and re-run on changes\n --watch-debounce <ms> Debounce delay for watch mode (default: 300)\n --no-watch-clear Don't clear screen between watch runs\n\n${this.logger.color('PROFILE MODE:', 'yellow')}\n -P, --profile <n> Run each request N times for latency stats\n --profile-warmup <n> Warmup iterations to exclude from stats (default: 1)\n --profile-concurrency <n> Concurrent iterations (default: 1 = sequential)\n --profile-histogram Show ASCII histogram of latency distribution\n --profile-export <file> Export raw timings to file (.json or .csv)\n\n${this.logger.color('CI/CD OPTIONS:', 'yellow')}\n --strict-exit Exit with code 1 if any validation fails (for CI/CD)\n --fail-on <count> Exit with code 1 if failures exceed this count\n --fail-on-percentage <pct> Exit with code 1 if failure percentage exceeds this value\n\n${this.logger.color('SNAPSHOT OPTIONS:', 'yellow')}\n -s, --snapshot Enable snapshot testing\n -u, --update-snapshots Update all snapshots\n --update-failing Update only failing snapshots\n --snapshot-dir <dir> Custom snapshot directory (default: __snapshots__)\n --ci-snapshot Fail if snapshot is missing (CI mode)\n\n${this.logger.color('DIFF OPTIONS:', 'yellow')}\n -d, --diff Enable response diffing (compare with baseline)\n --diff-save Save current run as baseline\n --diff-label <name> Label for current run (e.g., 'staging', 'v1.0')\n --diff-compare <label> Compare against this baseline label\n --diff-dir <dir> Baseline storage directory (default: __baselines__)\n --diff-output <format> Output format (terminal|json|markdown)\n\n${this.logger.color('DIFF SUBCOMMAND:', 'yellow')}\n curl-runner diff <label1> <label2> [file.yaml]\n Compare two stored baselines without making requests\n\n${this.logger.color('UPGRADE:', 'yellow')}\n curl-runner upgrade Upgrade to latest version (auto-detects install method)\n curl-runner upgrade --dry-run Preview upgrade command without executing\n curl-runner upgrade --force Force reinstall even if up to date\n\n${this.logger.color('VALIDATE:', 'yellow')}\n curl-runner validate Validate YAML files against curl-runner schema\n curl-runner validate --fix Validate and auto-fix issues where possible\n curl-runner validate -q Only show files with issues\n\n${this.logger.color('CONVERT:', 'yellow')}\n curl-runner convert curl \"<cmd>\" Convert curl command to YAML\n curl-runner convert file <sh> Convert shell script to YAML (batch)\n curl-runner convert yaml <yaml> Convert YAML to curl command(s)\n\n${this.logger.color('WIZARD:', 'yellow')}\n curl-runner init Quick create a new YAML file\n curl-runner init --wizard Full interactive wizard\n curl-runner init <url> Quick create with URL\n curl-runner edit <file.yaml> Edit existing YAML file\n\n${this.logger.color('EXAMPLES:', 'yellow')}\n # Run all YAML files in current directory\n curl-runner\n\n # Run specific file\n curl-runner api-tests.yaml\n\n # Run all files in a directory\n curl-runner examples/\n\n # Run all files in multiple directories\n curl-runner tests/ examples/\n\n # Run all files recursively in parallel\n curl-runner --all -p\n\n # Run in parallel with max 5 concurrent requests\n curl-runner -p --max-concurrent 5 tests.yaml\n\n # Run directory recursively\n curl-runner --all examples/\n\n # Run with verbose output and continue on errors\n curl-runner tests/*.yaml -vc\n\n # Dry run - show curl commands without executing\n curl-runner api.yaml --dry-run\n\n # Use HTTP/2 for all requests\n curl-runner api.yaml --http2\n\n # Enable connection pooling with HTTP/2 multiplexing\n curl-runner api.yaml -p --connection-pool\n\n # Connection pooling with custom settings\n curl-runner api.yaml -p --connection-pool --max-streams 20\n\n # Run with minimal pretty output (only status and errors)\n curl-runner --output-format pretty --pretty-level minimal test.yaml\n\n # Run with detailed pretty output (show all information)\n curl-runner --output-format pretty --pretty-level detailed test.yaml\n\n # CI/CD: Fail if any validation fails (strict mode)\n curl-runner tests/ --strict-exit\n\n # CI/CD: Run all tests but fail if any validation fails\n curl-runner tests/ --continue-on-error --strict-exit\n\n # CI/CD: Allow up to 2 failures\n curl-runner tests/ --fail-on 2\n\n # CI/CD: Allow up to 10% failures\n curl-runner tests/ --fail-on-percentage 10\n\n # Watch mode - re-run on file changes\n curl-runner api.yaml --watch\n\n # Watch with custom debounce\n curl-runner tests/ -w --watch-debounce 500\n\n # Profile mode - run request 100 times for latency stats\n curl-runner api.yaml -P 100\n\n # Profile with 5 warmup iterations and histogram\n curl-runner api.yaml --profile 50 --profile-warmup 5 --profile-histogram\n\n # Profile with concurrent iterations and export\n curl-runner api.yaml -P 100 --profile-concurrency 10 --profile-export results.json\n\n # Snapshot testing - save and compare responses\n curl-runner api.yaml --snapshot\n\n # Update all snapshots\n curl-runner api.yaml -su\n\n # CI mode - fail if snapshot missing\n curl-runner api.yaml --snapshot --ci-snapshot\n\n # Response diffing - save baseline for staging\n curl-runner api.yaml --diff-save --diff-label staging\n\n # Compare current run against staging baseline\n curl-runner api.yaml --diff --diff-compare staging\n\n # Compare staging vs production baselines (offline)\n curl-runner diff staging production api.yaml\n\n # Auto-diff: creates baseline on first run, compares on subsequent runs\n curl-runner api.yaml --diff\n\n # Diff with JSON output for CI\n curl-runner api.yaml --diff --diff-compare staging --diff-output json\n\n # Create new YAML file with wizard\n curl-runner init --wizard\n\n # Quick create with URL\n curl-runner init https://api.example.com/users\n\n # Edit existing YAML file\n curl-runner edit api-test.yaml\n\n${this.logger.color('YAML STRUCTURE:', 'yellow')}\n Single request:\n request:\n url: https://api.example.com\n method: GET\n\n Multiple requests:\n requests:\n - url: https://api.example.com/users\n method: GET\n - url: https://api.example.com/posts\n method: POST\n body: { title: \"Test\" }\n\n With global config:\n global:\n execution: parallel\n variables:\n BASE_URL: https://api.example.com\n requests:\n - url: \\${BASE_URL}/users\n method: GET\n`);\n }\n}\n\nconst cli = new CurlRunnerCLI();\ncli.run(process.argv.slice(2));\n",
|
|
8
|
+
"const colors = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n underscore: '\\x1b[4m',\n\n black: '\\x1b[30m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n\n bgBlack: '\\x1b[40m',\n bgRed: '\\x1b[41m',\n bgGreen: '\\x1b[42m',\n bgYellow: '\\x1b[43m',\n bgBlue: '\\x1b[44m',\n bgMagenta: '\\x1b[45m',\n bgCyan: '\\x1b[46m',\n bgWhite: '\\x1b[47m',\n};\n\nexport function color(text: string, colorName: keyof typeof colors): string {\n return `${colors[colorName]}${text}${colors.reset}`;\n}\n\nexport type Color = keyof typeof colors;\n",
|
|
9
|
+
"// Installation source detection for curl-runner upgrade command\n\nexport type InstallationSource = 'bun' | 'npm' | 'curl' | 'standalone';\n\nexport interface DetectionResult {\n source: InstallationSource;\n path: string;\n canAutoUpgrade: boolean;\n}\n\nconst CURL_INSTALL_PATHS = [\n `${process.env.HOME}/.local/bin/curl-runner`,\n `${process.env.USERPROFILE}\\\\.local\\\\bin\\\\curl-runner.exe`,\n];\n\nexport function detectInstallationSource(): DetectionResult {\n const execPath = process.execPath;\n const argv0 = process.argv[0];\n\n // Check for bun installation\n if (isBunInstall(execPath)) {\n return {\n source: 'bun',\n path: execPath,\n canAutoUpgrade: true,\n };\n }\n\n // Check for npm installation\n if (isNpmInstall(execPath, argv0)) {\n return {\n source: 'npm',\n path: execPath,\n canAutoUpgrade: true,\n };\n }\n\n // Check for curl installation (binary in ~/.local/bin)\n if (isCurlInstall(execPath)) {\n return {\n source: 'curl',\n path: execPath,\n canAutoUpgrade: true,\n };\n }\n\n // Standalone binary\n return {\n source: 'standalone',\n path: execPath,\n canAutoUpgrade: true,\n };\n}\n\nfunction isBunInstall(execPath: string): boolean {\n // Check if running from bun's global install directory\n if (execPath.includes('.bun')) {\n return true;\n }\n if (process.env.BUN_INSTALL && execPath.includes(process.env.BUN_INSTALL)) {\n return true;\n }\n\n // Check for bun-specific paths\n const bunPaths = ['/bun/install/', '/.bun/bin/', '/bun/bin/'];\n return bunPaths.some((p) => execPath.includes(p));\n}\n\nfunction isNpmInstall(execPath: string, argv0: string): boolean {\n // Check for npm global install indicators\n if (execPath.includes('node_modules')) {\n return true;\n }\n if (argv0.includes('node_modules')) {\n return true;\n }\n\n // Check for npm config env vars (set when running via npm)\n if (process.env.npm_config_prefix) {\n return true;\n }\n if (process.env.npm_execpath) {\n return true;\n }\n\n // Check common npm global paths\n const npmPaths = ['/lib/node_modules/', '/node_modules/.bin/'];\n return npmPaths.some((p) => execPath.includes(p) || argv0.includes(p));\n}\n\nfunction isCurlInstall(execPath: string): boolean {\n // Check if binary is in curl installer's default location\n return CURL_INSTALL_PATHS.some((p) => execPath === p || execPath.startsWith(p));\n}\n\nexport function getUpgradeCommand(source: InstallationSource): string {\n switch (source) {\n case 'bun':\n return 'bun install -g @curl-runner/cli@latest';\n case 'npm':\n return 'npm install -g @curl-runner/cli@latest';\n case 'curl':\n return 'curl -fsSL https://www.curl-runner.com/install.sh | bash';\n case 'standalone':\n return 'curl -fsSL https://www.curl-runner.com/install.sh | bash';\n }\n}\n\nexport function getUpgradeCommandWindows(source: InstallationSource): string {\n switch (source) {\n case 'bun':\n return 'bun install -g @curl-runner/cli@latest';\n case 'npm':\n return 'npm install -g @curl-runner/cli@latest';\n case 'curl':\n case 'standalone':\n return 'irm https://www.curl-runner.com/install.ps1 | iex';\n }\n}\n\nexport function isWindows(): boolean {\n return process.platform === 'win32';\n}\n",
|
|
10
|
+
"// Version management for curl-runner CLI\n// This file handles version detection for both development and compiled binaries\n\ndeclare const BUILD_VERSION: string | undefined;\n\nexport function getVersion(): string {\n // Check compile-time constant first (set by --define flag during build)\n if (typeof BUILD_VERSION !== 'undefined') {\n return BUILD_VERSION;\n }\n\n // Check environment variable (for local builds with our script)\n if (process.env.CURL_RUNNER_VERSION) {\n return process.env.CURL_RUNNER_VERSION;\n }\n\n // In development or npm installation, try to read from package.json\n try {\n // Try multiple paths to find package.json\n const possiblePaths = [\n '../package.json', // Development or npm installation\n './package.json', // In case we're at root\n '../../package.json', // In case of different directory structure\n ];\n\n for (const path of possiblePaths) {\n try {\n const packageJson = require(path);\n if (packageJson.name === '@curl-runner/cli' && packageJson.version) {\n return packageJson.version;\n }\n } catch {\n // Try next path\n }\n }\n\n // If no package.json found, return default\n return '0.0.0';\n } catch {\n // If all else fails, return a default version\n return '0.0.0';\n }\n}\n",
|
|
11
|
+
"// Upgrade command for curl-runner\n// Automatically detects installation source and upgrades to latest version\n\nimport { color } from '../utils/colors';\nimport {\n type DetectionResult,\n detectInstallationSource,\n getUpgradeCommand,\n getUpgradeCommandWindows,\n type InstallationSource,\n isWindows,\n} from '../utils/installation-detector';\nimport { getVersion } from '../version';\n\nconst NPM_REGISTRY_URL = 'https://registry.npmjs.org/@curl-runner/cli/latest';\nconst GITHUB_API_URL = 'https://api.github.com/repos/alexvcasillas/curl-runner/releases/latest';\n\ninterface UpgradeOptions {\n dryRun?: boolean;\n force?: boolean;\n}\n\nexport class UpgradeCommand {\n async run(args: string[]): Promise<void> {\n const options = this.parseArgs(args);\n\n console.log();\n console.log(color('curl-runner upgrade', 'bright'));\n console.log();\n\n // Detect installation source\n const detection = detectInstallationSource();\n console.log(`${color('Installation:', 'cyan')} ${this.formatSource(detection.source)}`);\n console.log(`${color('Current version:', 'cyan')} ${getVersion()}`);\n\n // Fetch latest version\n const latestVersion = await this.fetchLatestVersion(detection.source);\n if (!latestVersion) {\n console.log(color('Failed to fetch latest version', 'red'));\n process.exit(1);\n }\n console.log(`${color('Latest version:', 'cyan')} ${latestVersion}`);\n console.log();\n\n // Compare versions\n const currentVersion = getVersion();\n if (!options.force && !this.isNewerVersion(currentVersion, latestVersion)) {\n console.log(color('Already up to date!', 'green'));\n return;\n }\n\n // Get upgrade command\n const upgradeCmd = isWindows()\n ? getUpgradeCommandWindows(detection.source)\n : getUpgradeCommand(detection.source);\n\n if (options.dryRun) {\n console.log(color('Dry run - would execute:', 'yellow'));\n console.log(` ${color(upgradeCmd, 'cyan')}`);\n return;\n }\n\n // Execute upgrade\n console.log(`${color('Upgrading...', 'yellow')}`);\n console.log();\n\n await this.executeUpgrade(detection, upgradeCmd);\n }\n\n private parseArgs(args: string[]): UpgradeOptions {\n const options: UpgradeOptions = {};\n\n for (const arg of args) {\n if (arg === '--dry-run' || arg === '-n') {\n options.dryRun = true;\n } else if (arg === '--force' || arg === '-f') {\n options.force = true;\n }\n }\n\n return options;\n }\n\n private formatSource(source: InstallationSource): string {\n switch (source) {\n case 'bun':\n return 'bun (global)';\n case 'npm':\n return 'npm (global)';\n case 'curl':\n return 'curl installer';\n case 'standalone':\n return 'standalone binary';\n }\n }\n\n private async fetchLatestVersion(source: InstallationSource): Promise<string | null> {\n try {\n // For npm/bun, use npm registry\n if (source === 'bun' || source === 'npm') {\n const response = await fetch(NPM_REGISTRY_URL, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n return null;\n }\n const data = (await response.json()) as { version: string };\n return data.version;\n }\n\n // For curl/standalone, use GitHub releases\n const response = await fetch(GITHUB_API_URL, {\n signal: AbortSignal.timeout(5000),\n headers: {\n Accept: 'application/vnd.github.v3+json',\n },\n });\n if (!response.ok) {\n return null;\n }\n const data = (await response.json()) as { tag_name: string };\n const tag = data.tag_name;\n const match = tag.match(/(\\d+\\.\\d+\\.\\d+)/);\n return match ? match[1] : tag.replace(/^v/, '');\n } catch {\n return null;\n }\n }\n\n private isNewerVersion(current: string, latest: string): boolean {\n const currentVersion = current.replace(/^v/, '');\n const latestVersion = latest.replace(/^v/, '');\n\n const currentParts = currentVersion.split('.').map(Number);\n const latestParts = latestVersion.split('.').map(Number);\n\n for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {\n const currentPart = currentParts[i] || 0;\n const latestPart = latestParts[i] || 0;\n\n if (latestPart > currentPart) {\n return true;\n }\n if (latestPart < currentPart) {\n return false;\n }\n }\n\n return false;\n }\n\n private async executeUpgrade(detection: DetectionResult, upgradeCmd: string): Promise<void> {\n const { source } = detection;\n\n try {\n if (source === 'bun') {\n await this.runBunUpgrade();\n } else if (source === 'npm') {\n await this.runNpmUpgrade();\n } else {\n // curl or standalone - run shell command\n await this.runShellUpgrade(upgradeCmd);\n }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n\n // Check for permission errors\n if (errorMsg.includes('EACCES') || errorMsg.includes('permission')) {\n console.log();\n console.log(color('Permission denied. Try running with sudo:', 'yellow'));\n console.log(` ${color(`sudo ${upgradeCmd}`, 'cyan')}`);\n process.exit(1);\n }\n\n console.log(color(`Upgrade failed: ${errorMsg}`, 'red'));\n console.log();\n console.log(color('Manual upgrade:', 'yellow'));\n console.log(` ${color(upgradeCmd, 'cyan')}`);\n process.exit(1);\n }\n }\n\n private async runBunUpgrade(): Promise<void> {\n const proc = Bun.spawn(['bun', 'install', '-g', '@curl-runner/cli@latest'], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`bun install failed with exit code ${exitCode}`);\n }\n\n this.showSuccess();\n }\n\n private async runNpmUpgrade(): Promise<void> {\n const proc = Bun.spawn(['npm', 'install', '-g', '@curl-runner/cli@latest'], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`npm install failed with exit code ${exitCode}`);\n }\n\n this.showSuccess();\n }\n\n private async runShellUpgrade(cmd: string): Promise<void> {\n let proc: ReturnType<typeof Bun.spawn>;\n\n if (isWindows()) {\n // PowerShell for Windows\n proc = Bun.spawn(['powershell', '-Command', cmd], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n } else {\n // Bash for Unix\n proc = Bun.spawn(['bash', '-c', cmd], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n }\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Upgrade script failed with exit code ${exitCode}`);\n }\n\n this.showSuccess();\n }\n\n private showSuccess(): void {\n console.log();\n console.log(color('Upgrade complete!', 'green'));\n console.log();\n console.log('Run `curl-runner --version` to verify.');\n }\n}\n\nexport function showUpgradeHelp(): void {\n console.log(`\n${color('curl-runner upgrade', 'bright')}\n\nAutomatically upgrade curl-runner to the latest version.\nDetects installation source (bun, npm, curl) and uses appropriate method.\n\n${color('USAGE:', 'yellow')}\n curl-runner upgrade [options]\n\n${color('OPTIONS:', 'yellow')}\n -n, --dry-run Show what would be executed without running\n -f, --force Force upgrade even if already on latest version\n -h, --help Show this help message\n\n${color('EXAMPLES:', 'yellow')}\n curl-runner upgrade # Upgrade to latest\n curl-runner upgrade --dry-run # Preview upgrade command\n curl-runner upgrade --force # Force reinstall latest\n`);\n}\n",
|
|
12
|
+
"// Validate command for curl-runner\n// Validates YAML files against curl-runner schema and proposes/applies fixes\n\nimport { Glob } from 'bun';\nimport { YamlParser } from '../parser/yaml';\nimport type {\n GlobalConfig,\n RequestConfig,\n SSLConfig,\n WhenCondition,\n YamlFile,\n} from '../types/config';\nimport { color } from '../utils/colors';\n\ninterface ValidateOptions {\n fix?: boolean;\n quiet?: boolean;\n strict?: boolean;\n}\n\ninterface ValidationIssue {\n file: string;\n path: string;\n severity: 'error' | 'warning' | 'info';\n message: string;\n fix?: {\n description: string;\n apply: () => unknown;\n };\n}\n\ninterface ValidationResult {\n file: string;\n valid: boolean;\n issues: ValidationIssue[];\n fixedContent?: string;\n}\n\n// Valid HTTP methods\nconst VALID_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as const;\n\n// Valid auth types\nconst VALID_AUTH_TYPES = ['basic', 'bearer', 'digest', 'ntlm', 'oauth2'] as const;\n\n// Valid execution modes\nconst VALID_EXECUTION_MODES = ['sequential', 'parallel'] as const;\n\n// Valid output formats\nconst VALID_OUTPUT_FORMATS = ['json', 'pretty', 'raw'] as const;\n\n// Valid pretty levels\nconst VALID_PRETTY_LEVELS = ['minimal', 'standard', 'detailed'] as const;\n\n// Valid condition operators\nconst VALID_OPERATORS = [\n '==',\n '!=',\n '>',\n '<',\n '>=',\n '<=',\n 'contains',\n 'matches',\n 'exists',\n 'not-exists',\n] as const;\n\n// Valid snapshot update modes\nconst VALID_SNAPSHOT_UPDATE_MODES = ['none', 'all', 'failing'] as const;\n\n// Valid diff output formats\nconst VALID_DIFF_OUTPUT_FORMATS = ['terminal', 'json', 'markdown'] as const;\n\n// Common URL typos\nconst URL_TYPOS: Record<string, string> = {\n htpp: 'http',\n htps: 'https',\n htp: 'http',\n 'http:/': 'http://',\n 'https:/': 'https://',\n locahost: 'localhost',\n localhsot: 'localhost',\n loaclhost: 'localhost',\n localost: 'localhost',\n '127.0.0.0': '127.0.0.1',\n};\n\n// Standard HTTP headers with proper casing\nconst STANDARD_HEADERS: Record<string, string> = {\n 'content-type': 'Content-Type',\n 'content-length': 'Content-Length',\n 'content-encoding': 'Content-Encoding',\n 'content-language': 'Content-Language',\n 'content-disposition': 'Content-Disposition',\n accept: 'Accept',\n 'accept-encoding': 'Accept-Encoding',\n 'accept-language': 'Accept-Language',\n 'accept-charset': 'Accept-Charset',\n authorization: 'Authorization',\n 'cache-control': 'Cache-Control',\n connection: 'Connection',\n cookie: 'Cookie',\n 'set-cookie': 'Set-Cookie',\n host: 'Host',\n origin: 'Origin',\n referer: 'Referer',\n 'user-agent': 'User-Agent',\n 'x-requested-with': 'X-Requested-With',\n 'x-forwarded-for': 'X-Forwarded-For',\n 'x-forwarded-proto': 'X-Forwarded-Proto',\n 'x-api-key': 'X-API-Key',\n 'x-auth-token': 'X-Auth-Token',\n 'x-csrf-token': 'X-CSRF-Token',\n 'x-request-id': 'X-Request-ID',\n 'x-correlation-id': 'X-Correlation-ID',\n etag: 'ETag',\n 'if-match': 'If-Match',\n 'if-none-match': 'If-None-Match',\n 'if-modified-since': 'If-Modified-Since',\n 'if-unmodified-since': 'If-Unmodified-Since',\n 'last-modified': 'Last-Modified',\n location: 'Location',\n pragma: 'Pragma',\n 'proxy-authorization': 'Proxy-Authorization',\n range: 'Range',\n 'content-range': 'Content-Range',\n te: 'TE',\n trailer: 'Trailer',\n 'transfer-encoding': 'Transfer-Encoding',\n upgrade: 'Upgrade',\n vary: 'Vary',\n via: 'Via',\n warning: 'Warning',\n 'www-authenticate': 'WWW-Authenticate',\n 'access-control-allow-origin': 'Access-Control-Allow-Origin',\n 'access-control-allow-methods': 'Access-Control-Allow-Methods',\n 'access-control-allow-headers': 'Access-Control-Allow-Headers',\n 'access-control-allow-credentials': 'Access-Control-Allow-Credentials',\n 'access-control-expose-headers': 'Access-Control-Expose-Headers',\n 'access-control-max-age': 'Access-Control-Max-Age',\n 'strict-transport-security': 'Strict-Transport-Security',\n 'x-content-type-options': 'X-Content-Type-Options',\n 'x-frame-options': 'X-Frame-Options',\n 'x-xss-protection': 'X-XSS-Protection',\n};\n\n// Known valid request config keys\nconst VALID_REQUEST_KEYS = [\n 'name',\n 'url',\n 'method',\n 'headers',\n 'params',\n 'body',\n 'formData',\n 'timeout',\n 'followRedirects',\n 'maxRedirects',\n 'auth',\n 'proxy',\n 'insecure',\n 'ssl',\n 'output',\n 'http2',\n 'retry',\n 'variables',\n 'store',\n 'when',\n 'expect',\n 'snapshot',\n 'diff',\n 'sourceOutputConfig',\n 'sourceFile',\n];\n\n// Known valid global config keys\nconst VALID_GLOBAL_KEYS = [\n 'execution',\n 'maxConcurrency',\n 'continueOnError',\n 'dryRun',\n 'http2',\n 'connectionPool',\n 'ci',\n 'ssl',\n 'watch',\n 'profile',\n 'snapshot',\n 'diff',\n 'variables',\n 'output',\n 'defaults',\n];\n\n// Known valid collection keys\nconst VALID_COLLECTION_KEYS = ['name', 'description', 'variables', 'defaults', 'requests'];\n\n// Sensitive patterns that shouldn't be hardcoded\nconst SENSITIVE_PATTERNS = [\n /^(password|passwd|pwd|secret|api[_-]?key|apikey|token|auth|credential|private[_-]?key)$/i,\n /Bearer\\s+[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+\\.[A-Za-z0-9\\-_]+/i, // JWT\n /^[A-Fa-f0-9]{32,}$/, // Hex keys\n /^sk[-_]live[-_]/i, // Stripe keys\n /^AKIA[0-9A-Z]{16}$/i, // AWS keys\n];\n\nexport class ValidateCommand {\n private issues: ValidationIssue[] = [];\n private currentFile = '';\n private definedVariables: Set<string> = new Set();\n private storedVariables: Set<string> = new Set();\n private requestNames: Set<string> = new Set();\n\n async run(args: string[]): Promise<void> {\n const options = this.parseArgs(args);\n const patterns = args.filter((a) => !a.startsWith('-'));\n\n if (patterns.length === 0) {\n patterns.push('*.yaml', '*.yml');\n }\n\n console.log();\n console.log(color('curl-runner validate', 'bright'));\n console.log();\n\n const files = await this.findYamlFiles(patterns);\n\n if (files.length === 0) {\n console.log(color('No YAML files found', 'yellow'));\n return;\n }\n\n console.log(`${color('Files:', 'cyan')} ${files.length} found`);\n console.log();\n\n let totalIssues = 0;\n let totalFixed = 0;\n let invalidFiles = 0;\n\n for (const file of files) {\n const result = await this.validateFile(file, options);\n const errors = result.issues.filter((i) => i.severity === 'error');\n const warnings = result.issues.filter((i) => i.severity === 'warning');\n const infos = result.issues.filter((i) => i.severity === 'info');\n\n if (!result.valid || (options.strict && warnings.length > 0)) {\n invalidFiles++;\n totalIssues += result.issues.length;\n\n console.log(`${color('✗', 'red')} ${file}`);\n for (const issue of result.issues) {\n const icon =\n issue.severity === 'error'\n ? color('●', 'red')\n : issue.severity === 'warning'\n ? color('●', 'yellow')\n : color('●', 'blue');\n console.log(` ${icon} ${issue.path}: ${issue.message}`);\n if (issue.fix && !options.fix) {\n console.log(` ${color('fix:', 'cyan')} ${issue.fix.description}`);\n }\n }\n\n if (options.fix && result.fixedContent) {\n await Bun.write(file, result.fixedContent);\n const fixedCount = result.issues.filter((i) => i.fix).length;\n totalFixed += fixedCount;\n console.log(` ${color('✓', 'green')} Fixed ${fixedCount} issue(s)`);\n }\n\n // Show summary per file\n const parts = [];\n if (errors.length > 0) {\n parts.push(`${errors.length} error(s)`);\n }\n if (warnings.length > 0) {\n parts.push(`${warnings.length} warning(s)`);\n }\n if (infos.length > 0) {\n parts.push(`${infos.length} info`);\n }\n if (parts.length > 0) {\n console.log(` ${color('→', 'dim')} ${parts.join(', ')}`);\n }\n console.log();\n } else if (!options.quiet) {\n console.log(`${color('✓', 'green')} ${file}`);\n }\n }\n\n console.log();\n if (invalidFiles === 0) {\n console.log(color('All files valid!', 'green'));\n } else {\n console.log(\n `${color('Summary:', 'cyan')} ${invalidFiles} file(s) with ${totalIssues} issue(s)`,\n );\n if (options.fix) {\n console.log(`${color('Fixed:', 'green')} ${totalFixed} issue(s)`);\n }\n process.exit(1);\n }\n }\n\n private parseArgs(args: string[]): ValidateOptions {\n const options: ValidateOptions = {};\n\n for (const arg of args) {\n if (arg === '--fix' || arg === '-f') {\n options.fix = true;\n } else if (arg === '--quiet' || arg === '-q') {\n options.quiet = true;\n } else if (arg === '--strict' || arg === '-s') {\n options.strict = true;\n }\n }\n\n return options;\n }\n\n private async findYamlFiles(patterns: string[]): Promise<string[]> {\n const files: Set<string> = new Set();\n const fs = await import('node:fs/promises');\n\n for (const pattern of patterns) {\n try {\n const stat = await fs.stat(pattern);\n if (stat.isDirectory()) {\n const globber = new Glob(`${pattern}/**/*.{yaml,yml}`);\n for await (const file of globber.scan('.')) {\n files.add(file);\n }\n } else if (stat.isFile() && (pattern.endsWith('.yaml') || pattern.endsWith('.yml'))) {\n files.add(pattern);\n }\n } catch {\n // Treat as glob pattern\n const globber = new Glob(pattern);\n for await (const file of globber.scan('.')) {\n if (file.endsWith('.yaml') || file.endsWith('.yml')) {\n files.add(file);\n }\n }\n }\n }\n\n return Array.from(files).sort();\n }\n\n private async validateFile(file: string, options: ValidateOptions): Promise<ValidationResult> {\n this.issues = [];\n this.currentFile = file;\n this.definedVariables = new Set();\n this.storedVariables = new Set();\n this.requestNames = new Set();\n\n let content: YamlFile;\n\n try {\n content = await YamlParser.parseFile(file);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n this.addIssue('', 'error', `Failed to parse YAML: ${msg}`);\n return { file, valid: false, issues: this.issues };\n }\n\n // Collect defined variables first\n this.collectDefinedVariables(content);\n\n // Validate structure\n this.validateYamlStructure(content);\n\n // Validate global config\n if (content.global) {\n this.validateGlobalConfig(content.global, 'global');\n }\n\n // Validate collection\n if (content.collection) {\n this.validateCollection(content.collection, 'collection');\n }\n\n // Validate single request\n if (content.request) {\n this.validateRequest(content.request, 'request');\n }\n\n // Validate requests array\n if (content.requests) {\n if (!Array.isArray(content.requests)) {\n this.addIssue('requests', 'error', 'Must be an array');\n } else {\n content.requests.forEach((req, i) => {\n this.validateRequest(req, `requests[${i}]`);\n });\n }\n }\n\n // Check for duplicate request names\n this.checkDuplicateRequestNames();\n\n // Build fixed content if needed\n let fixedContent: string | undefined;\n if (options.fix && this.issues.some((i) => i.fix)) {\n const fixedData = JSON.parse(JSON.stringify(content));\n for (const issue of this.issues) {\n if (issue.fix) {\n const result = issue.fix.apply();\n this.applyFix(fixedData, issue.path, result);\n }\n }\n fixedContent = this.toYaml(fixedData);\n }\n\n const errors = this.issues.filter((i) => i.severity === 'error');\n\n return {\n file,\n valid: errors.length === 0,\n issues: this.issues,\n fixedContent,\n };\n }\n\n private collectDefinedVariables(content: YamlFile): void {\n // Global variables\n if (content.global?.variables) {\n for (const key of Object.keys(content.global.variables)) {\n this.definedVariables.add(key);\n }\n }\n\n // Collection variables\n if (content.collection?.variables) {\n for (const key of Object.keys(content.collection.variables)) {\n this.definedVariables.add(key);\n }\n }\n\n // Environment variables are always available\n this.definedVariables.add('env');\n\n // Request variables (individual requests)\n const allRequests = [\n ...(content.requests || []),\n ...(content.collection?.requests || []),\n content.request,\n ].filter(Boolean) as RequestConfig[];\n\n for (const req of allRequests) {\n if (req.variables) {\n for (const key of Object.keys(req.variables)) {\n this.definedVariables.add(key);\n }\n }\n // Store variables become available after the request\n if (req.store) {\n for (const key of Object.keys(req.store)) {\n this.storedVariables.add(key);\n }\n }\n }\n }\n\n private validateYamlStructure(content: YamlFile): void {\n const hasRequest = 'request' in content;\n const hasRequests = 'requests' in content;\n const hasCollection = 'collection' in content;\n\n if (!hasRequest && !hasRequests && !hasCollection) {\n this.addIssue(\n '',\n 'error',\n 'Missing request(s). Must have \"request\", \"requests\", or \"collection\"',\n );\n }\n\n if (hasRequest && hasRequests) {\n this.addIssue('', 'warning', 'Both \"request\" and \"requests\" defined; both will be executed');\n }\n\n if (hasCollection && (hasRequest || hasRequests)) {\n this.addIssue('', 'warning', 'Collection mixed with request/requests; may cause confusion');\n }\n\n // Check for unknown top-level keys\n const validKeys = ['version', 'global', 'collection', 'requests', 'request'];\n for (const key of Object.keys(content)) {\n if (!validKeys.includes(key)) {\n this.addIssue(key, 'warning', `Unknown top-level key \"${key}\"`, {\n description: `Remove unknown key \"${key}\"`,\n apply: () => undefined,\n });\n }\n }\n\n // Validate version if present\n if (content.version !== undefined) {\n if (typeof content.version !== 'string') {\n this.addIssue('version', 'warning', 'Version should be a string');\n }\n }\n }\n\n private validateGlobalConfig(config: GlobalConfig, path: string): void {\n // Check for unknown keys\n this.checkUnknownKeys(config as unknown as Record<string, unknown>, VALID_GLOBAL_KEYS, path);\n\n // Execution mode\n if (config.execution && !VALID_EXECUTION_MODES.includes(config.execution)) {\n const suggestion = this.findClosestMatch(config.execution, [...VALID_EXECUTION_MODES]);\n this.addIssue(\n `${path}.execution`,\n 'error',\n `Invalid execution mode \"${config.execution}\". Must be: ${VALID_EXECUTION_MODES.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n }\n\n // Max concurrency\n if (config.maxConcurrency !== undefined) {\n if (typeof config.maxConcurrency !== 'number' || config.maxConcurrency < 1) {\n this.addIssue(`${path}.maxConcurrency`, 'error', 'Must be a positive number');\n }\n if (config.execution === 'sequential') {\n this.addIssue(\n `${path}.maxConcurrency`,\n 'warning',\n 'maxConcurrency has no effect with sequential execution',\n );\n }\n }\n\n // Boolean fields\n const configRecord = config as unknown as Record<string, unknown>;\n this.validateBooleanField(configRecord, 'continueOnError', path);\n this.validateBooleanField(configRecord, 'dryRun', path);\n this.validateBooleanField(configRecord, 'http2', path);\n\n // Output config\n if (config.output) {\n this.validateOutputConfig(config.output, `${path}.output`);\n }\n\n // Connection pool\n if (config.connectionPool) {\n this.validateConnectionPool(config.connectionPool, `${path}.connectionPool`);\n }\n\n // CI config\n if (config.ci) {\n this.validateCIConfig(config.ci, `${path}.ci`);\n }\n\n // SSL config\n if (config.ssl) {\n this.validateSSLConfig(config.ssl, `${path}.ssl`);\n }\n\n // Watch config\n if (config.watch) {\n this.validateWatchConfig(config.watch, `${path}.watch`);\n }\n\n // Profile config\n if (config.profile) {\n this.validateProfileConfig(config.profile, `${path}.profile`);\n }\n\n // Snapshot config\n if (config.snapshot) {\n this.validateSnapshotConfig(config.snapshot, `${path}.snapshot`);\n }\n\n // Diff config\n if (config.diff) {\n this.validateDiffConfig(config.diff, `${path}.diff`);\n }\n\n // Variables\n if (config.variables) {\n this.validateVariables(config.variables, `${path}.variables`);\n }\n\n // Defaults\n if (config.defaults) {\n this.validateRequestConfig(config.defaults, `${path}.defaults`, true);\n }\n }\n\n private validateBooleanField(obj: Record<string, unknown>, field: string, path: string): void {\n if (obj[field] !== undefined && typeof obj[field] !== 'boolean') {\n const strVal = String(obj[field]).toLowerCase();\n if (strVal === 'true' || strVal === 'false') {\n this.addIssue(\n `${path}.${field}`,\n 'warning',\n `Should be boolean, not string \"${obj[field]}\"`,\n {\n description: `Convert to ${strVal}`,\n apply: () => strVal === 'true',\n },\n );\n } else {\n this.addIssue(`${path}.${field}`, 'error', 'Must be a boolean');\n }\n }\n }\n\n private validateVariables(variables: Record<string, string>, path: string): void {\n if (typeof variables !== 'object' || Array.isArray(variables)) {\n this.addIssue(path, 'error', 'Must be an object');\n return;\n }\n\n for (const [key, value] of Object.entries(variables)) {\n // Check variable naming\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n 'Variable names should use alphanumeric characters and underscores',\n );\n }\n\n // Check for sensitive values\n if (typeof value === 'string' && this.isSensitiveValue(key, value)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n 'Potentially sensitive value hardcoded. Consider using environment variables like \"$' +\n '{env.VAR}\"',\n );\n }\n }\n }\n\n private validateOutputConfig(output: NonNullable<GlobalConfig['output']>, path: string): void {\n const validKeys = [\n 'verbose',\n 'showHeaders',\n 'showBody',\n 'showMetrics',\n 'format',\n 'prettyLevel',\n 'saveToFile',\n 'dryRun',\n ];\n this.checkUnknownKeys(output, validKeys, path);\n\n if (output.format && !VALID_OUTPUT_FORMATS.includes(output.format)) {\n const suggestion = this.findClosestMatch(output.format, [...VALID_OUTPUT_FORMATS]);\n this.addIssue(\n `${path}.format`,\n 'error',\n `Invalid format \"${output.format}\". Must be: ${VALID_OUTPUT_FORMATS.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n }\n\n if (output.prettyLevel && !VALID_PRETTY_LEVELS.includes(output.prettyLevel)) {\n const suggestion = this.findClosestMatch(output.prettyLevel, [...VALID_PRETTY_LEVELS]);\n this.addIssue(\n `${path}.prettyLevel`,\n 'error',\n `Invalid prettyLevel \"${output.prettyLevel}\". Must be: ${VALID_PRETTY_LEVELS.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n }\n\n // Boolean fields\n this.validateBooleanField(output as Record<string, unknown>, 'verbose', path);\n this.validateBooleanField(output as Record<string, unknown>, 'showHeaders', path);\n this.validateBooleanField(output as Record<string, unknown>, 'showBody', path);\n this.validateBooleanField(output as Record<string, unknown>, 'showMetrics', path);\n }\n\n private validateConnectionPool(\n pool: NonNullable<GlobalConfig['connectionPool']>,\n path: string,\n ): void {\n const validKeys = ['enabled', 'maxStreamsPerHost', 'keepaliveTime', 'connectTimeout'];\n this.checkUnknownKeys(pool as unknown as Record<string, unknown>, validKeys, path);\n\n this.validateBooleanField(pool as Record<string, unknown>, 'enabled', path);\n\n if (pool.maxStreamsPerHost !== undefined) {\n if (typeof pool.maxStreamsPerHost !== 'number' || pool.maxStreamsPerHost < 1) {\n this.addIssue(`${path}.maxStreamsPerHost`, 'error', 'Must be a positive number');\n } else if (pool.maxStreamsPerHost > 100) {\n this.addIssue(\n `${path}.maxStreamsPerHost`,\n 'warning',\n 'Very high stream count may cause issues with some servers',\n );\n }\n }\n if (pool.keepaliveTime !== undefined) {\n if (typeof pool.keepaliveTime !== 'number' || pool.keepaliveTime < 0) {\n this.addIssue(`${path}.keepaliveTime`, 'error', 'Must be a non-negative number');\n }\n }\n if (pool.connectTimeout !== undefined) {\n if (typeof pool.connectTimeout !== 'number' || pool.connectTimeout < 0) {\n this.addIssue(`${path}.connectTimeout`, 'error', 'Must be a non-negative number');\n }\n }\n }\n\n private validateCIConfig(ci: NonNullable<GlobalConfig['ci']>, path: string): void {\n const validKeys = ['strictExit', 'failOn', 'failOnPercentage'];\n this.checkUnknownKeys(ci as unknown as Record<string, unknown>, validKeys, path);\n\n this.validateBooleanField(ci as Record<string, unknown>, 'strictExit', path);\n\n if (ci.failOn !== undefined && (typeof ci.failOn !== 'number' || ci.failOn < 0)) {\n this.addIssue(`${path}.failOn`, 'error', 'Must be a non-negative number');\n }\n if (ci.failOnPercentage !== undefined) {\n if (\n typeof ci.failOnPercentage !== 'number' ||\n ci.failOnPercentage < 0 ||\n ci.failOnPercentage > 100\n ) {\n this.addIssue(`${path}.failOnPercentage`, 'error', 'Must be a number between 0 and 100');\n }\n }\n\n // Warn if both failOn and failOnPercentage are set\n if (ci.failOn !== undefined && ci.failOnPercentage !== undefined) {\n this.addIssue(\n path,\n 'info',\n 'Both failOn and failOnPercentage are set; failOn takes precedence',\n );\n }\n }\n\n private validateSSLConfig(ssl: SSLConfig, path: string): void {\n const validKeys = ['verify', 'ca', 'cert', 'key'];\n this.checkUnknownKeys(ssl as Record<string, unknown>, validKeys, path);\n\n this.validateBooleanField(ssl as Record<string, unknown>, 'verify', path);\n\n if (ssl.ca && typeof ssl.ca !== 'string') {\n this.addIssue(`${path}.ca`, 'error', 'Must be a string path');\n }\n if (ssl.cert && typeof ssl.cert !== 'string') {\n this.addIssue(`${path}.cert`, 'error', 'Must be a string path');\n }\n if (ssl.key && typeof ssl.key !== 'string') {\n this.addIssue(`${path}.key`, 'error', 'Must be a string path');\n }\n if (ssl.cert && !ssl.key) {\n this.addIssue(`${path}`, 'warning', 'cert provided without key; mTLS may fail');\n }\n if (ssl.key && !ssl.cert) {\n this.addIssue(`${path}`, 'warning', 'key provided without cert; mTLS may fail');\n }\n\n // Verify path patterns\n if (ssl.ca && typeof ssl.ca === 'string') {\n this.validateFilePath(ssl.ca, `${path}.ca`);\n }\n if (ssl.cert && typeof ssl.cert === 'string') {\n this.validateFilePath(ssl.cert, `${path}.cert`);\n }\n if (ssl.key && typeof ssl.key === 'string') {\n this.validateFilePath(ssl.key, `${path}.key`);\n }\n }\n\n private validateFilePath(filePath: string, path: string): void {\n // Skip if it's a variable reference\n if (filePath.includes('${')) {\n return;\n }\n\n // Check for suspicious patterns\n if (filePath.includes('..')) {\n this.addIssue(path, 'info', 'Path contains \"..\"; ensure this is intentional');\n }\n }\n\n private validateWatchConfig(watch: NonNullable<GlobalConfig['watch']>, path: string): void {\n const validKeys = ['enabled', 'debounce', 'clear'];\n this.checkUnknownKeys(watch as unknown as Record<string, unknown>, validKeys, path);\n\n if (watch.debounce !== undefined) {\n if (typeof watch.debounce !== 'number' || watch.debounce < 0) {\n this.addIssue(`${path}.debounce`, 'error', 'Must be a non-negative number');\n }\n }\n\n this.validateBooleanField(watch as unknown as Record<string, unknown>, 'enabled', path);\n this.validateBooleanField(watch as unknown as Record<string, unknown>, 'clear', path);\n }\n\n private validateProfileConfig(profile: NonNullable<GlobalConfig['profile']>, path: string): void {\n const validKeys = ['iterations', 'warmup', 'concurrency', 'percentiles'];\n this.checkUnknownKeys(profile as unknown as Record<string, unknown>, validKeys, path);\n\n if (profile.iterations !== undefined) {\n if (typeof profile.iterations !== 'number' || profile.iterations < 1) {\n this.addIssue(`${path}.iterations`, 'error', 'Must be a positive number');\n } else if (profile.iterations > 10000) {\n this.addIssue(`${path}.iterations`, 'warning', 'Very high iteration count may take long');\n }\n }\n if (profile.warmup !== undefined) {\n if (typeof profile.warmup !== 'number' || profile.warmup < 0) {\n this.addIssue(`${path}.warmup`, 'error', 'Must be a non-negative number');\n }\n }\n if (profile.concurrency !== undefined) {\n if (typeof profile.concurrency !== 'number' || profile.concurrency < 1) {\n this.addIssue(`${path}.concurrency`, 'error', 'Must be a positive number');\n }\n }\n }\n\n private validateSnapshotConfig(\n snapshot: NonNullable<GlobalConfig['snapshot']>,\n path: string,\n ): void {\n const validKeys = ['updateMode', 'dir', 'ignoreFields', 'ignoreHeaders'];\n this.checkUnknownKeys(snapshot as Record<string, unknown>, validKeys, path);\n\n if (snapshot.updateMode && !VALID_SNAPSHOT_UPDATE_MODES.includes(snapshot.updateMode)) {\n this.addIssue(\n `${path}.updateMode`,\n 'error',\n `Invalid updateMode \"${snapshot.updateMode}\". Must be: ${VALID_SNAPSHOT_UPDATE_MODES.join(', ')}`,\n );\n }\n if (snapshot.dir && typeof snapshot.dir !== 'string') {\n this.addIssue(`${path}.dir`, 'error', 'Must be a string');\n }\n }\n\n private validateDiffConfig(diff: NonNullable<GlobalConfig['diff']>, path: string): void {\n const validKeys = ['outputFormat', 'dir', 'ignoreFields', 'ignoreHeaders', 'baselineUrl'];\n this.checkUnknownKeys(diff as Record<string, unknown>, validKeys, path);\n\n if (diff.outputFormat && !VALID_DIFF_OUTPUT_FORMATS.includes(diff.outputFormat)) {\n this.addIssue(\n `${path}.outputFormat`,\n 'error',\n `Invalid outputFormat \"${diff.outputFormat}\". Must be: ${VALID_DIFF_OUTPUT_FORMATS.join(', ')}`,\n );\n }\n if (diff.dir && typeof diff.dir !== 'string') {\n this.addIssue(`${path}.dir`, 'error', 'Must be a string');\n }\n }\n\n private validateCollection(collection: NonNullable<YamlFile['collection']>, path: string): void {\n this.checkUnknownKeys(\n collection as unknown as Record<string, unknown>,\n VALID_COLLECTION_KEYS,\n path,\n );\n\n if (!collection.name) {\n this.addIssue(`${path}.name`, 'warning', 'Collection name is recommended');\n }\n\n if (!collection.requests || !Array.isArray(collection.requests)) {\n this.addIssue(`${path}.requests`, 'error', 'Collection must have a requests array');\n } else {\n if (collection.requests.length === 0) {\n this.addIssue(`${path}.requests`, 'warning', 'Collection has no requests');\n }\n collection.requests.forEach((req, i) => {\n this.validateRequest(req, `${path}.requests[${i}]`);\n });\n }\n\n if (collection.variables) {\n this.validateVariables(collection.variables, `${path}.variables`);\n }\n\n if (collection.defaults) {\n this.validateRequestConfig(collection.defaults, `${path}.defaults`, true);\n }\n }\n\n private validateRequest(request: RequestConfig, path: string): void {\n this.validateRequestConfig(request, path, false);\n }\n\n private validateRequestConfig(\n request: Partial<RequestConfig>,\n path: string,\n isDefaults: boolean,\n ): void {\n // Check for unknown keys\n this.checkUnknownKeys(request as Record<string, unknown>, VALID_REQUEST_KEYS, path);\n\n // Track request name\n if (request.name) {\n this.requestNames.add(`${path}:${request.name}`);\n }\n\n // URL is required for non-defaults\n if (!isDefaults && !request.url) {\n this.addIssue(`${path}.url`, 'error', 'URL is required');\n }\n\n // URL validation\n if (request.url) {\n this.validateURL(request.url, `${path}.url`);\n }\n\n // Method validation\n if (request.method) {\n this.validateMethod(request.method, `${path}.method`);\n }\n\n // Headers validation\n if (request.headers) {\n this.validateHeaders(request.headers, `${path}.headers`, request);\n }\n\n // Params validation\n if (request.params) {\n if (typeof request.params !== 'object' || Array.isArray(request.params)) {\n this.addIssue(`${path}.params`, 'error', 'Params must be an object');\n }\n }\n\n // Body and formData mutual exclusion\n if (request.body !== undefined && request.formData !== undefined) {\n this.addIssue(`${path}`, 'error', 'Cannot use both \"body\" and \"formData\"');\n }\n\n // Body validation\n if (request.body !== undefined) {\n this.validateBody(request.body, `${path}.body`, request);\n }\n\n // FormData validation\n if (request.formData) {\n this.validateFormData(request.formData, `${path}.formData`);\n }\n\n // Timeout validation\n if (request.timeout !== undefined) {\n this.validateTimeout(request.timeout, `${path}.timeout`);\n }\n\n // Auth validation\n if (request.auth) {\n this.validateAuth(request.auth, `${path}.auth`);\n }\n\n // SSL validation\n if (request.ssl) {\n this.validateSSLConfig(request.ssl, `${path}.ssl`);\n }\n\n // Insecure validation\n if (request.insecure !== undefined) {\n this.validateBooleanField(request as Record<string, unknown>, 'insecure', path);\n if (request.insecure === true) {\n this.addIssue(`${path}.insecure`, 'warning', 'Insecure mode disables SSL verification');\n }\n }\n\n // Proxy validation\n if (request.proxy) {\n this.validateProxyURL(request.proxy, `${path}.proxy`);\n }\n\n // Retry validation\n if (request.retry) {\n this.validateRetry(request.retry, `${path}.retry`, request.method);\n }\n\n // When condition validation\n if (request.when) {\n this.validateWhenCondition(request.when, `${path}.when`);\n }\n\n // Expect validation\n if (request.expect) {\n this.validateExpect(request.expect, `${path}.expect`);\n }\n\n // Store validation\n if (request.store) {\n this.validateStore(request.store, `${path}.store`);\n }\n\n // Max redirects validation\n if (request.maxRedirects !== undefined) {\n if (typeof request.maxRedirects !== 'number' || request.maxRedirects < 0) {\n this.addIssue(`${path}.maxRedirects`, 'error', 'Must be a non-negative number');\n } else if (request.maxRedirects > 50) {\n this.addIssue(`${path}.maxRedirects`, 'warning', 'Very high redirect limit');\n }\n }\n\n // followRedirects validation\n this.validateBooleanField(request as Record<string, unknown>, 'followRedirects', path);\n this.validateBooleanField(request as Record<string, unknown>, 'http2', path);\n\n // Snapshot/diff validation\n if (request.snapshot !== undefined && typeof request.snapshot === 'object') {\n this.validateSnapshotConfig(\n request.snapshot as NonNullable<GlobalConfig['snapshot']>,\n `${path}.snapshot`,\n );\n }\n\n if (request.diff !== undefined && typeof request.diff === 'object') {\n this.validateDiffConfig(request.diff as NonNullable<GlobalConfig['diff']>, `${path}.diff`);\n }\n }\n\n private validateURL(url: string, path: string): void {\n if (typeof url !== 'string') {\n this.addIssue(path, 'error', 'URL must be a string');\n return;\n }\n\n // Skip extensive validation if URL contains variables\n const hasVariables = url.includes('${');\n\n // Check for common typos\n let fixedUrl = url;\n let hasTypo = false;\n for (const [typo, fix] of Object.entries(URL_TYPOS)) {\n if (url.toLowerCase().includes(typo)) {\n fixedUrl = url.replace(new RegExp(typo, 'gi'), fix);\n hasTypo = true;\n this.addIssue(path, 'error', `URL contains typo \"${typo}\"`, {\n description: `Fix to \"${fix}\"`,\n apply: () => fixedUrl,\n });\n break;\n }\n }\n\n // Check for missing protocol\n if (!hasTypo && !url.startsWith('http') && !hasVariables) {\n this.addIssue(path, 'warning', 'URL should start with http:// or https://', {\n description: 'Prepend https://',\n apply: () => `https://${url}`,\n });\n }\n\n // Check for double slashes in path (not protocol)\n if (!hasVariables && url.match(/https?:\\/\\/[^/]+\\/\\/+/)) {\n const fixed = url.replace(/(https?:\\/\\/[^/]+)(\\/+)/g, '$1/');\n this.addIssue(path, 'warning', 'URL contains double slashes in path', {\n description: 'Remove extra slashes',\n apply: () => fixed,\n });\n }\n\n // Check for spaces in URL\n if (url.includes(' ')) {\n const fixed = url.replace(/ /g, '%20');\n this.addIssue(path, 'error', 'URL contains spaces', {\n description: 'Encode spaces as %20',\n apply: () => fixed,\n });\n }\n\n // Security warning for http in production\n if (url.startsWith('http://') && !url.includes('localhost') && !url.includes('127.0.0.1')) {\n this.addIssue(path, 'info', 'Using HTTP instead of HTTPS; consider using HTTPS for security');\n }\n\n // Validate port number if present\n if (!hasVariables) {\n const portMatch = url.match(/:(\\d+)/);\n if (portMatch) {\n const port = parseInt(portMatch[1], 10);\n if (port < 1 || port > 65535) {\n this.addIssue(path, 'error', `Invalid port number ${port}. Must be 1-65535`);\n }\n }\n }\n }\n\n private validateProxyURL(proxy: string, path: string): void {\n if (typeof proxy !== 'string') {\n this.addIssue(path, 'error', 'Proxy must be a string URL');\n return;\n }\n\n if (!proxy.includes('${') && !proxy.match(/^(https?|socks[45]?):\\/\\//i)) {\n this.addIssue(\n path,\n 'error',\n 'Proxy URL should start with http://, https://, socks4://, or socks5://',\n );\n }\n }\n\n private validateMethod(method: string, path: string): void {\n const upperMethod = method.toUpperCase();\n if (!VALID_METHODS.includes(upperMethod as (typeof VALID_METHODS)[number])) {\n const suggestion = this.findClosestMatch(upperMethod, [...VALID_METHODS]);\n this.addIssue(\n path,\n 'error',\n `Invalid method \"${method}\". Must be: ${VALID_METHODS.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n } else if (method !== upperMethod) {\n this.addIssue(path, 'warning', `Method should be uppercase: \"${upperMethod}\"`, {\n description: `Change to \"${upperMethod}\"`,\n apply: () => upperMethod,\n });\n }\n }\n\n private validateHeaders(\n headers: Record<string, string>,\n path: string,\n request: Partial<RequestConfig>,\n ): void {\n if (typeof headers !== 'object' || Array.isArray(headers)) {\n this.addIssue(path, 'error', 'Headers must be an object');\n return;\n }\n\n const seenHeaders = new Map<string, string>();\n\n for (const [key, value] of Object.entries(headers)) {\n // Check for proper header casing\n const lowerKey = key.toLowerCase();\n const standardCasing = STANDARD_HEADERS[lowerKey];\n\n if (standardCasing && key !== standardCasing) {\n this.addIssue(\n `${path}.${key}`,\n 'info',\n `Header \"${key}\" should be \"${standardCasing}\" for consistency`,\n {\n description: `Rename to \"${standardCasing}\"`,\n apply: () => ({ rename: standardCasing, value }),\n },\n );\n }\n\n // Check for duplicate headers (case-insensitive)\n if (seenHeaders.has(lowerKey)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n `Duplicate header \"${key}\" (case-insensitive match with \"${seenHeaders.get(lowerKey)}\")`,\n );\n }\n seenHeaders.set(lowerKey, key);\n\n // Check header value\n if (typeof value !== 'string' && typeof value !== 'number') {\n this.addIssue(`${path}.${key}`, 'error', 'Header value must be a string or number');\n }\n\n // Check for sensitive values in headers\n if (typeof value === 'string' && this.isSensitiveValue(key, value)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n 'Potentially sensitive header value. Consider using variables like \"$' + '{env.TOKEN}\"',\n );\n }\n }\n\n // Check Content-Type consistency with body\n const contentType = this.getHeaderValue(headers, 'content-type');\n if (request.body !== undefined && !contentType) {\n this.addIssue(path, 'info', 'Body present but no Content-Type header; consider adding one');\n }\n\n // Warn if both auth block and Authorization header exist\n const hasAuthHeader = this.getHeaderValue(headers, 'authorization');\n if (request.auth && hasAuthHeader) {\n this.addIssue(\n path,\n 'warning',\n 'Both auth block and Authorization header present; auth block may be ignored',\n );\n }\n }\n\n private getHeaderValue(headers: Record<string, string>, name: string): string | undefined {\n const lowerName = name.toLowerCase();\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() === lowerName) {\n return value;\n }\n }\n return undefined;\n }\n\n private validateBody(body: unknown, path: string, request: Partial<RequestConfig>): void {\n // Check if method supports body\n const method = (request.method || 'GET').toUpperCase();\n if (['GET', 'HEAD', 'OPTIONS'].includes(method)) {\n this.addIssue(path, 'warning', `Body with ${method} method may be ignored by some servers`);\n }\n\n // If body is a string, check if it looks like JSON\n if (typeof body === 'string') {\n const trimmed = body.trim();\n if (\n (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))\n ) {\n try {\n JSON.parse(trimmed);\n } catch {\n this.addIssue(path, 'warning', 'Body looks like JSON but is invalid; check syntax');\n }\n }\n }\n }\n\n private validateFormData(formData: NonNullable<RequestConfig['formData']>, path: string): void {\n if (typeof formData !== 'object' || Array.isArray(formData)) {\n this.addIssue(path, 'error', 'FormData must be an object');\n return;\n }\n\n for (const [key, value] of Object.entries(formData)) {\n if (typeof value === 'object' && value !== null && 'file' in value) {\n if (typeof value.file !== 'string') {\n this.addIssue(`${path}.${key}.file`, 'error', 'File path must be a string');\n } else {\n this.validateFilePath(value.file, `${path}.${key}.file`);\n }\n if (value.contentType && typeof value.contentType !== 'string') {\n this.addIssue(`${path}.${key}.contentType`, 'error', 'contentType must be a string');\n }\n if (value.filename && typeof value.filename !== 'string') {\n this.addIssue(`${path}.${key}.filename`, 'error', 'filename must be a string');\n }\n }\n }\n }\n\n private validateTimeout(timeout: unknown, path: string): void {\n if (typeof timeout !== 'number') {\n // Try to parse string\n if (typeof timeout === 'string') {\n const parsed = parseInt(timeout, 10);\n if (!Number.isNaN(parsed) && parsed > 0) {\n this.addIssue(path, 'warning', 'Timeout should be a number, not string', {\n description: `Convert to ${parsed}`,\n apply: () => parsed,\n });\n return;\n }\n }\n this.addIssue(path, 'error', 'Timeout must be a positive number');\n return;\n }\n\n if (timeout <= 0) {\n this.addIssue(path, 'error', 'Timeout must be a positive number');\n } else if (timeout < 100) {\n this.addIssue(path, 'warning', 'Very short timeout (<100ms) may cause failures');\n } else if (timeout > 300000) {\n this.addIssue(path, 'warning', 'Very long timeout (>5min) - is this intentional?');\n }\n }\n\n private validateAuth(auth: NonNullable<RequestConfig['auth']>, path: string): void {\n const validKeys = ['type', 'username', 'password', 'token'];\n this.checkUnknownKeys(auth as Record<string, unknown>, validKeys, path);\n\n if (!auth.type) {\n this.addIssue(`${path}.type`, 'error', 'Auth type is required');\n return;\n }\n\n if (!VALID_AUTH_TYPES.includes(auth.type as (typeof VALID_AUTH_TYPES)[number])) {\n const suggestion = this.findClosestMatch(auth.type, [...VALID_AUTH_TYPES]);\n this.addIssue(\n `${path}.type`,\n 'error',\n `Invalid auth type \"${auth.type}\". Must be: ${VALID_AUTH_TYPES.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n return;\n }\n\n if (auth.type === 'basic') {\n if (!auth.username) {\n this.addIssue(`${path}.username`, 'error', 'Username required for basic auth');\n }\n if (!auth.password) {\n this.addIssue(`${path}.password`, 'warning', 'Password missing for basic auth');\n }\n // Check for hardcoded credentials\n if (auth.password && typeof auth.password === 'string' && !auth.password.includes('${')) {\n this.addIssue(\n `${path}.password`,\n 'warning',\n 'Hardcoded password. Consider using \"$' + '{env.PASSWORD}\"',\n );\n }\n }\n\n if (auth.type === 'bearer') {\n if (!auth.token) {\n this.addIssue(`${path}.token`, 'error', 'Token required for bearer auth');\n }\n // Check for hardcoded token\n if (auth.token && typeof auth.token === 'string' && !auth.token.includes('${')) {\n this.addIssue(\n `${path}.token`,\n 'warning',\n 'Hardcoded token. Consider using \"$' + '{env.TOKEN}\"',\n );\n }\n }\n }\n\n private validateRetry(\n retry: NonNullable<RequestConfig['retry']>,\n path: string,\n method?: string,\n ): void {\n const validKeys = ['count', 'delay', 'backoff'];\n this.checkUnknownKeys(retry as Record<string, unknown>, validKeys, path);\n\n if (retry.count === undefined) {\n this.addIssue(`${path}.count`, 'error', 'Retry count is required');\n } else if (typeof retry.count !== 'number' || retry.count < 0) {\n this.addIssue(`${path}.count`, 'error', 'Retry count must be a non-negative number');\n } else if (retry.count > 10) {\n this.addIssue(`${path}.count`, 'warning', 'High retry count (>10) may cause long delays');\n }\n\n if (retry.delay !== undefined) {\n if (typeof retry.delay !== 'number' || retry.delay < 0) {\n this.addIssue(`${path}.delay`, 'error', 'Retry delay must be a non-negative number');\n }\n }\n\n if (retry.backoff !== undefined) {\n if (typeof retry.backoff !== 'number' || retry.backoff < 1) {\n this.addIssue(`${path}.backoff`, 'error', 'Retry backoff must be >= 1');\n } else if (retry.backoff > 5) {\n this.addIssue(\n `${path}.backoff`,\n 'warning',\n 'High backoff multiplier may cause very long delays',\n );\n }\n }\n\n // Warn about retrying non-idempotent methods\n if (\n method &&\n ['POST', 'PATCH'].includes(method.toUpperCase()) &&\n retry.count &&\n retry.count > 0\n ) {\n this.addIssue(path, 'info', `Retrying ${method} requests may cause duplicate operations`);\n }\n }\n\n private validateWhenCondition(when: WhenCondition | string, path: string): void {\n if (typeof when === 'string') {\n // String shorthand - validate syntax\n this.validateWhenString(when, path);\n return;\n }\n\n // Object form\n const hasAll = 'all' in when && when.all;\n const hasAny = 'any' in when && when.any;\n const hasSingle = 'left' in when;\n\n if (!hasAll && !hasAny && !hasSingle) {\n this.addIssue(path, 'error', 'When condition must have \"all\", \"any\", or \"left\"');\n return;\n }\n\n if ((hasAll && hasAny) || (hasAll && hasSingle) || (hasAny && hasSingle)) {\n this.addIssue(\n path,\n 'warning',\n 'When condition has multiple forms; behavior may be unexpected',\n );\n }\n\n if (hasAll) {\n if (!Array.isArray(when.all)) {\n this.addIssue(`${path}.all`, 'error', 'Must be an array');\n } else {\n if (when.all.length === 0) {\n this.addIssue(`${path}.all`, 'warning', 'Empty \"all\" array - condition always true');\n }\n when.all.forEach((cond, i) => {\n this.validateConditionExpression(cond, `${path}.all[${i}]`);\n });\n }\n }\n\n if (hasAny) {\n if (!Array.isArray(when.any)) {\n this.addIssue(`${path}.any`, 'error', 'Must be an array');\n } else {\n if (when.any.length === 0) {\n this.addIssue(`${path}.any`, 'warning', 'Empty \"any\" array - condition always false');\n }\n when.any.forEach((cond, i) => {\n this.validateConditionExpression(cond, `${path}.any[${i}]`);\n });\n }\n }\n\n if (hasSingle) {\n this.validateConditionExpression(\n when as { left?: string; operator?: string; right?: unknown },\n path,\n );\n }\n }\n\n private validateWhenString(when: string, path: string): void {\n // Check for common patterns\n if (!when.includes('store.') && !when.includes('env.')) {\n this.addIssue(path, 'warning', 'When string should reference store.* or env.* values');\n }\n\n // Check for valid operator\n const operatorPattern = /\\s*(==|!=|>=|<=|>|<|contains|matches|exists|not-exists)\\s*/;\n if (!operatorPattern.test(when)) {\n this.addIssue(\n path,\n 'warning',\n 'When string should contain a valid operator (==, !=, >, <, >=, <=, contains, matches, exists)',\n );\n }\n }\n\n private validateConditionExpression(\n cond: { left?: string; operator?: string; right?: unknown },\n path: string,\n ): void {\n if (!cond.left) {\n this.addIssue(`${path}.left`, 'error', 'Left operand is required');\n } else {\n // Validate left references store or env\n if (!cond.left.startsWith('store.') && !cond.left.startsWith('env.')) {\n this.addIssue(\n `${path}.left`,\n 'warning',\n 'Left operand should start with \"store.\" or \"env.\"',\n );\n }\n }\n\n if (!cond.operator) {\n this.addIssue(`${path}.operator`, 'error', 'Operator is required');\n } else if (!VALID_OPERATORS.includes(cond.operator as (typeof VALID_OPERATORS)[number])) {\n const suggestion = this.findClosestMatch(cond.operator, [...VALID_OPERATORS]);\n this.addIssue(\n `${path}.operator`,\n 'error',\n `Invalid operator \"${cond.operator}\". Must be: ${VALID_OPERATORS.join(', ')}`,\n suggestion\n ? {\n description: `Change to \"${suggestion}\"`,\n apply: () => suggestion,\n }\n : undefined,\n );\n }\n\n // exists/not-exists don't need right operand\n if (cond.operator !== 'exists' && cond.operator !== 'not-exists') {\n if (cond.right === undefined) {\n this.addIssue(`${path}.right`, 'error', 'Right operand is required');\n }\n }\n }\n\n private validateExpect(expect: NonNullable<RequestConfig['expect']>, path: string): void {\n const validKeys = ['failure', 'status', 'headers', 'body', 'responseTime'];\n this.checkUnknownKeys(expect as Record<string, unknown>, validKeys, path);\n\n this.validateBooleanField(expect as Record<string, unknown>, 'failure', path);\n\n // Status validation\n if (expect.status !== undefined) {\n this.validateExpectStatus(expect.status, `${path}.status`);\n }\n\n // Headers validation\n if (expect.headers) {\n if (typeof expect.headers !== 'object' || Array.isArray(expect.headers)) {\n this.addIssue(`${path}.headers`, 'error', 'Expected headers must be an object');\n }\n }\n\n // Response time validation\n if (expect.responseTime !== undefined) {\n this.validateResponseTime(expect.responseTime, `${path}.responseTime`);\n }\n }\n\n private validateExpectStatus(status: number | number[], path: string): void {\n if (Array.isArray(status)) {\n if (status.length === 0) {\n this.addIssue(path, 'warning', 'Empty status array - no status will match');\n }\n for (const s of status) {\n if (typeof s !== 'number' || s < 100 || s > 599) {\n this.addIssue(path, 'error', 'Status codes must be numbers between 100-599');\n break;\n }\n }\n } else if (typeof status === 'string') {\n // Handle string status\n const parsed = parseInt(status, 10);\n if (!Number.isNaN(parsed) && parsed >= 100 && parsed <= 599) {\n this.addIssue(path, 'warning', 'Status should be a number, not string', {\n description: `Convert to ${parsed}`,\n apply: () => parsed,\n });\n } else {\n this.addIssue(path, 'error', 'Status code must be a number between 100-599');\n }\n } else if (typeof status !== 'number' || status < 100 || status > 599) {\n this.addIssue(path, 'error', 'Status code must be a number between 100-599');\n }\n }\n\n private validateResponseTime(responseTime: unknown, path: string): void {\n if (typeof responseTime !== 'string') {\n this.addIssue(path, 'error', 'Response time must be a string (e.g., \"< 1000\")');\n return;\n }\n\n const pattern = /^[<>]=?\\s*(\\d+|\\$\\{[^}]+\\})(\\s*,\\s*[<>]=?\\s*(\\d+|\\$\\{[^}]+\\}))?$/;\n if (!responseTime.match(pattern)) {\n this.addIssue(path, 'warning', 'Response time should be like \"< 1000\", \"> 500, < 2000\"');\n }\n }\n\n private validateStore(store: Record<string, string>, path: string): void {\n if (typeof store !== 'object' || Array.isArray(store)) {\n this.addIssue(path, 'error', 'Store must be an object');\n return;\n }\n\n for (const [key, value] of Object.entries(store)) {\n // Validate variable name\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n 'Store variable names should use alphanumeric characters and underscores',\n );\n }\n\n // Validate JSON path\n if (typeof value !== 'string') {\n this.addIssue(`${path}.${key}`, 'error', 'Store path must be a string');\n } else {\n // Check for valid response paths\n const validPaths = ['body', 'status', 'headers', 'responseTime'];\n const firstPart = value.split('.')[0];\n if (!validPaths.includes(firstPart)) {\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n `Store path should start with: ${validPaths.join(', ')}`,\n );\n }\n }\n }\n }\n\n private checkDuplicateRequestNames(): void {\n const names = new Map<string, string[]>();\n\n for (const entry of this.requestNames) {\n const [path, name] = entry.split(':');\n if (!names.has(name)) {\n names.set(name, []);\n }\n names.get(name)!.push(path);\n }\n\n for (const [name, paths] of names) {\n if (paths.length > 1) {\n this.addIssue(\n paths[1],\n 'warning',\n `Duplicate request name \"${name}\" (also at ${paths[0]})`,\n );\n }\n }\n }\n\n private checkUnknownKeys(obj: Record<string, unknown>, validKeys: string[], path: string): void {\n for (const key of Object.keys(obj)) {\n if (!validKeys.includes(key)) {\n const suggestion = this.findClosestMatch(key, validKeys);\n this.addIssue(\n `${path}.${key}`,\n 'warning',\n `Unknown key \"${key}\"`,\n suggestion\n ? {\n description: `Did you mean \"${suggestion}\"?`,\n apply: () => ({ rename: suggestion }),\n }\n : undefined,\n );\n }\n }\n }\n\n private findClosestMatch(input: string, options: string[]): string | null {\n const lowerInput = input.toLowerCase();\n let bestMatch: string | null = null;\n let bestScore = 3; // Maximum edit distance to consider\n\n for (const option of options) {\n const lowerOption = option.toLowerCase();\n\n // Exact match (case-insensitive)\n if (lowerInput === lowerOption) {\n return option;\n }\n\n // Check if starts with same prefix\n if (lowerOption.startsWith(lowerInput) || lowerInput.startsWith(lowerOption)) {\n return option;\n }\n\n // Simple edit distance\n const distance = this.editDistance(lowerInput, lowerOption);\n if (distance < bestScore) {\n bestScore = distance;\n bestMatch = option;\n }\n }\n\n return bestMatch;\n }\n\n private editDistance(a: string, b: string): number {\n if (a.length === 0) {\n return b.length;\n }\n if (b.length === 0) {\n return a.length;\n }\n\n const matrix: number[][] = [];\n\n for (let i = 0; i <= b.length; i++) {\n matrix[i] = [i];\n }\n for (let j = 0; j <= a.length; j++) {\n matrix[0][j] = j;\n }\n\n for (let i = 1; i <= b.length; i++) {\n for (let j = 1; j <= a.length; j++) {\n if (b.charAt(i - 1) === a.charAt(j - 1)) {\n matrix[i][j] = matrix[i - 1][j - 1];\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j - 1] + 1,\n matrix[i][j - 1] + 1,\n matrix[i - 1][j] + 1,\n );\n }\n }\n }\n\n return matrix[b.length][a.length];\n }\n\n private isSensitiveValue(key: string, value: string): boolean {\n // Skip if it's a variable reference\n if (value.includes('${')) {\n return false;\n }\n\n // Check key name\n for (const pattern of SENSITIVE_PATTERNS) {\n if (pattern.test(key)) {\n return true;\n }\n }\n\n // Check value patterns\n for (const pattern of SENSITIVE_PATTERNS) {\n if (pattern.test(value)) {\n return true;\n }\n }\n\n return false;\n }\n\n private addIssue(\n path: string,\n severity: 'error' | 'warning' | 'info',\n message: string,\n fix?: ValidationIssue['fix'],\n ): void {\n this.issues.push({\n file: this.currentFile,\n path: path || '(root)',\n severity,\n message,\n fix,\n });\n }\n\n private applyFix(data: Record<string, unknown>, path: string, value: unknown): void {\n if (!path || path === '(root)') {\n return;\n }\n\n const parts = path.split('.').flatMap((p) => {\n const match = p.match(/^(\\w+)\\[(\\d+)\\]$/);\n return match ? [match[1], Number(match[2])] : p;\n });\n\n let current: unknown = data;\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n if (typeof current === 'object' && current !== null) {\n current = (current as Record<string, unknown>)[key as string];\n }\n }\n\n if (typeof current === 'object' && current !== null) {\n const lastKey = parts[parts.length - 1];\n\n // Handle rename operations\n if (typeof value === 'object' && value !== null && 'rename' in value) {\n const renameValue = value as { rename: string; value?: unknown };\n const oldValue =\n renameValue.value ?? (current as Record<string, unknown>)[lastKey as string];\n delete (current as Record<string, unknown>)[lastKey as string];\n (current as Record<string, unknown>)[renameValue.rename] = oldValue;\n } else if (value === undefined) {\n // Delete the key\n delete (current as Record<string, unknown>)[lastKey as string];\n } else {\n (current as Record<string, unknown>)[lastKey as string] = value;\n }\n }\n }\n\n private toYaml(data: YamlFile): string {\n return this.serializeYaml(data);\n }\n\n private serializeYaml(obj: unknown, indent = 0): string {\n const spaces = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) {\n return 'null';\n }\n\n if (typeof obj === 'string') {\n // Check if string needs quoting\n if (\n obj.includes('\\n') ||\n obj.includes(':') ||\n obj.includes('#') ||\n obj.startsWith('$') ||\n obj.match(/^[0-9]/) ||\n obj === '' ||\n obj === 'true' ||\n obj === 'false' ||\n obj === 'null'\n ) {\n return JSON.stringify(obj);\n }\n return obj;\n }\n\n if (typeof obj === 'number' || typeof obj === 'boolean') {\n return String(obj);\n }\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) {\n return '[]';\n }\n return obj\n .map((item) => {\n if (typeof item === 'object' && item !== null) {\n const serialized = this.serializeYaml(item, indent + 1);\n const lines = serialized.split('\\n');\n return `${spaces}- ${lines[0]}\\n${lines\n .slice(1)\n .map((l) => `${spaces} ${l}`)\n .join('\\n')}`.trimEnd();\n }\n return `${spaces}- ${this.serializeYaml(item, indent)}`;\n })\n .join('\\n');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj).filter(([, v]) => v !== undefined);\n if (entries.length === 0) {\n return '{}';\n }\n return entries\n .map(([key, value]) => {\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const serialized = this.serializeYaml(value, indent + 1);\n return `${spaces}${key}:\\n${serialized\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n')}`;\n }\n if (Array.isArray(value)) {\n return `${spaces}${key}:\\n${this.serializeYaml(value, indent + 1)}`;\n }\n return `${spaces}${key}: ${this.serializeYaml(value, indent)}`;\n })\n .join('\\n');\n }\n\n return String(obj);\n }\n}\n\nexport function showValidateHelp(): void {\n console.log(`\n${color('curl-runner validate', 'bright')}\n\nValidate YAML files against curl-runner schema and curl options.\nDiscovers issues and proposes fixes, or auto-fixes with --fix.\n\n${color('USAGE:', 'yellow')}\n curl-runner validate [files...] [options]\n\n${color('OPTIONS:', 'yellow')}\n -f, --fix Auto-fix issues where possible\n -q, --quiet Only show files with issues\n -s, --strict Treat warnings as errors\n -h, --help Show this help message\n\n${color('ARGUMENTS:', 'yellow')}\n files File paths or glob patterns (default: *.yaml, *.yml)\n\n${color('EXAMPLES:', 'yellow')}\n curl-runner validate # Validate all YAML in current dir\n curl-runner validate api.yaml # Validate single file\n curl-runner validate \"tests/**/*.yaml\" # Validate with glob pattern\n curl-runner validate --fix # Validate and auto-fix issues\n curl-runner validate -fq # Fix quietly (only show errors)\n curl-runner validate --strict # Fail on warnings too\n\n${color('VALIDATION CATEGORIES:', 'yellow')}\n\n ${color('Structure', 'cyan')}\n • YAML syntax and parsing\n • Required fields (url, auth.type, etc.)\n • Unknown/misspelled keys with suggestions\n • Duplicate request names\n\n ${color('URLs', 'cyan')}\n • Valid URL syntax\n • Common typos (htpp, localhsot, etc.)\n • Double slashes in paths\n • Missing protocol (http/https)\n • Valid port numbers (1-65535)\n • Spaces in URLs\n\n ${color('HTTP', 'cyan')}\n • Valid methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)\n • Method casing (lowercase → UPPERCASE)\n • Headers casing (content-type → Content-Type)\n • Content-Type consistency with body\n • Duplicate headers\n\n ${color('Auth & Security', 'cyan')}\n • Valid auth types (basic, bearer)\n • Required auth fields (username, password, token)\n • Hardcoded credentials warning\n • Insecure mode warnings\n • HTTP vs HTTPS warnings\n\n ${color('Configuration', 'cyan')}\n • Boolean string values (\"true\" → true)\n • Numeric string values\n • Valid execution modes\n • Valid output formats\n • SSL certificate consistency\n\n ${color('Timeouts & Retries', 'cyan')}\n • Positive timeout values\n • Reasonable timeout ranges\n • Retry count limits\n • Non-idempotent retry warnings\n\n ${color('Conditions & Expectations', 'cyan')}\n • When condition operators\n • Store path references\n • Status code ranges (100-599)\n • Response time format\n\n${color('AUTO-FIXABLE ISSUES:', 'yellow')}\n • Lowercase HTTP methods → UPPERCASE\n • Missing https:// prefix on URLs\n • URL typos (htpp → http, localhsot → localhost)\n • Double slashes in URL paths\n • Spaces in URLs (→ %20)\n • Header casing (content-type → Content-Type)\n • Boolean strings (\"true\" → true)\n • Numeric strings (timeout: \"5000\" → 5000)\n • Status code strings (\"200\" → 200)\n • Execution mode typos\n • Unknown keys (with suggestions)\n`);\n}\n",
|
|
13
|
+
"/**\n * Variable interpolation and resolution logic.\n * Supports static variables, dynamic variables, store context, defaults, and transforms.\n */\n\nimport type { InterpolateOptions, StoreContext, VariableRef, Variables } from './types';\n\n/**\n * Reserved prefixes for dynamic variable generation.\n * These cannot be used as regular variable names with default values.\n */\nconst DYNAMIC_PREFIXES = ['DATE', 'TIME', 'UUID', 'RANDOM'] as const;\n\n/**\n * Interpolates variables in an object recursively.\n *\n * Supports:\n * - Static variables: ${VAR_NAME}\n * - Dynamic variables: ${UUID}, ${TIMESTAMP}, ${DATE:format}, ${TIME:format}\n * - Stored response values: ${store.variableName}\n * - Default values: ${VAR_NAME:default}\n * - Nested defaults: ${VAR1:${VAR2:fallback}}\n * - String transforms: ${VAR:upper}, ${VAR:lower}\n */\nexport function interpolate(obj: unknown, options: InterpolateOptions = {}): unknown {\n const { variables = {}, storeContext, resolveEnv = true } = options;\n\n if (typeof obj === 'string') {\n return interpolateString(obj, variables, storeContext, resolveEnv);\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => interpolate(item, options));\n }\n\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = interpolate(value, options);\n }\n return result;\n }\n\n return obj;\n}\n\n/**\n * Interpolates variables in a string.\n */\nfunction interpolateString(\n str: string,\n variables: Variables,\n storeContext?: StoreContext,\n resolveEnv = true,\n): unknown {\n const refs = extractVariables(str);\n\n if (refs.length === 0) {\n return str;\n }\n\n // Single variable spanning entire string - preserve type\n if (refs.length === 1 && refs[0].start === 0 && refs[0].end === str.length) {\n const resolved = resolveVariable(refs[0].name, variables, storeContext, resolveEnv);\n return resolved !== null ? resolved : str;\n }\n\n // Multiple variables or partial string - concatenate as string\n let result = '';\n let lastEnd = 0;\n\n for (const ref of refs) {\n result += str.slice(lastEnd, ref.start);\n const resolved = resolveVariable(ref.name, variables, storeContext, resolveEnv);\n result += resolved !== null ? resolved : str.slice(ref.start, ref.end);\n lastEnd = ref.end;\n }\n\n result += str.slice(lastEnd);\n return result;\n}\n\n/**\n * Resolves a single variable reference.\n *\n * Priority:\n * 1. Store context (${store.variableName})\n * 2. String transforms (${VAR:upper}, ${VAR:lower})\n * 3. Variables with defaults (${VAR:default})\n * 4. Dynamic variables (${UUID}, ${TIMESTAMP}, etc.)\n * 5. Static variables\n * 6. Environment variables (if enabled)\n */\nexport function resolveVariable(\n varName: string,\n variables: Variables,\n storeContext?: StoreContext,\n resolveEnv = true,\n): string | null {\n // 1. Store context\n if (varName.startsWith('store.') && storeContext) {\n const storeKey = varName.slice(6);\n if (storeKey in storeContext) {\n return storeContext[storeKey];\n }\n return null;\n }\n\n // 2. String transforms\n const transformMatch = varName.match(/^([^:]+):(upper|lower)$/);\n if (transformMatch) {\n const [, baseVar, transform] = transformMatch;\n const baseValue = variables[baseVar] ?? (resolveEnv ? process.env[baseVar] : undefined);\n\n if (baseValue) {\n return transform === 'upper' ? baseValue.toUpperCase() : baseValue.toLowerCase();\n }\n return null;\n }\n\n // 3. Default value syntax\n const colonIdx = varName.indexOf(':');\n if (colonIdx !== -1) {\n const actualVar = varName.slice(0, colonIdx);\n const defaultVal = varName.slice(colonIdx + 1);\n\n // Skip if it's a dynamic prefix\n if (!DYNAMIC_PREFIXES.includes(actualVar as (typeof DYNAMIC_PREFIXES)[number])) {\n const resolved = resolveVariable(actualVar, variables, storeContext, resolveEnv);\n if (resolved !== null) {\n return resolved;\n }\n\n // Handle nested variable in default\n if (defaultVal.startsWith('${')) {\n const nestedVar = defaultVal.endsWith('}') ? defaultVal.slice(2, -1) : defaultVal.slice(2);\n const nestedResolved = resolveVariable(nestedVar, variables, storeContext, resolveEnv);\n return nestedResolved !== null ? nestedResolved : defaultVal;\n }\n\n return defaultVal;\n }\n }\n\n // 4. Dynamic variables\n const dynamicValue = resolveDynamicVariable(varName);\n if (dynamicValue !== null) {\n return dynamicValue;\n }\n\n // 5. Static variables\n if (varName in variables) {\n return variables[varName];\n }\n\n // 6. Environment variables\n if (resolveEnv && varName in process.env) {\n return process.env[varName]!;\n }\n\n return null;\n}\n\n/**\n * Resolves dynamic variable patterns.\n */\nexport function resolveDynamicVariable(varName: string): string | null {\n // UUID generation\n if (varName === 'UUID') {\n return crypto.randomUUID();\n }\n\n // UUID:short - first segment (8 chars)\n if (varName === 'UUID:short') {\n return crypto.randomUUID().split('-')[0];\n }\n\n // RANDOM:min-max\n const rangeMatch = varName.match(/^RANDOM:(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const min = Number(rangeMatch[1]);\n const max = Number(rangeMatch[2]);\n return String(Math.floor(Math.random() * (max - min + 1)) + min);\n }\n\n // RANDOM:string:length\n const stringMatch = varName.match(/^RANDOM:string:(\\d+)$/);\n if (stringMatch) {\n const length = Number(stringMatch[1]);\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n return Array.from({ length }, () =>\n chars.charAt(Math.floor(Math.random() * chars.length)),\n ).join('');\n }\n\n // Timestamp\n if (varName === 'CURRENT_TIME' || varName === 'TIMESTAMP') {\n return Date.now().toString();\n }\n\n // DATE:format\n if (varName.startsWith('DATE:')) {\n return formatDate(new Date(), varName.slice(5));\n }\n\n // TIME:format\n if (varName.startsWith('TIME:')) {\n return formatTime(new Date(), varName.slice(5));\n }\n\n return null;\n}\n\n/**\n * Formats a date using a format string.\n * Supports: YYYY, MM, DD\n */\nexport function formatDate(date: Date, format: string): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n\n return format.replace('YYYY', year.toString()).replace('MM', month).replace('DD', day);\n}\n\n/**\n * Formats a time using a format string.\n * Supports: HH, mm, ss\n */\nexport function formatTime(date: Date, format: string): string {\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n\n return format.replace('HH', hours).replace('mm', minutes).replace('ss', seconds);\n}\n\n/**\n * Extracts variable references from a string with proper brace matching.\n * Handles nested braces like ${VAR:${OTHER:default}}.\n */\nexport function extractVariables(str: string): VariableRef[] {\n const refs: VariableRef[] = [];\n let i = 0;\n\n while (i < str.length) {\n if (str[i] === '$' && str[i + 1] === '{') {\n const start = i;\n i += 2;\n let braceCount = 1;\n const nameStart = i;\n\n while (i < str.length && braceCount > 0) {\n if (str[i] === '{') {\n braceCount++;\n } else if (str[i] === '}') {\n braceCount--;\n }\n i++;\n }\n\n if (braceCount === 0) {\n refs.push({\n start,\n end: i,\n name: str.slice(nameStart, i - 1),\n });\n }\n } else {\n i++;\n }\n }\n\n return refs;\n}\n",
|
|
14
|
+
"import { interpolate } from '../core/interpolator';\nimport type { RequestConfig, ResponseStoreContext, YamlFile } from '../types/config';\n\n/**\n * YAML file parser with variable interpolation support.\n * Uses core/interpolator for variable resolution.\n */\nexport class YamlParser {\n static async parseFile(filepath: string): Promise<YamlFile> {\n const file = Bun.file(filepath);\n const content = await file.text();\n return Bun.YAML.parse(content) as YamlFile;\n }\n\n static parse(content: string): YamlFile {\n return Bun.YAML.parse(content) as YamlFile;\n }\n\n /**\n * Interpolates variables in an object.\n * Delegates to core/interpolator for the actual work.\n */\n static interpolateVariables(\n obj: unknown,\n variables: Record<string, string>,\n storeContext?: ResponseStoreContext,\n ): unknown {\n return interpolate(obj, { variables, storeContext });\n }\n\n static mergeConfigs(base: Partial<RequestConfig>, override: RequestConfig): RequestConfig {\n return {\n ...base,\n ...override,\n headers: { ...base.headers, ...override.headers },\n params: { ...base.params, ...override.params },\n variables: { ...base.variables, ...override.variables },\n };\n }\n}\n",
|
|
15
|
+
"/**\n * Batch script parser: extracts curl commands from shell scripts.\n * Uses heuristic detection to find curl invocations.\n */\n\n/**\n * Extract curl command strings from a shell script.\n * Handles multiline commands (backslash continuations) and basic pipe chains.\n */\nexport function extractCurlCommands(script: string): string[] {\n const commands: string[] = [];\n const lines = script.split('\\n');\n let i = 0;\n\n while (i < lines.length) {\n const trimmed = lines[i].trim();\n\n // Skip empty, comments, shebangs\n if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('//')) {\n i++;\n continue;\n }\n\n // Detect line starting with curl or containing curl invocation\n const curlStart = findCurlStart(trimmed);\n if (curlStart >= 0) {\n let cmd = trimmed.slice(curlStart);\n\n // Collect continuation lines\n while (cmd.endsWith('\\\\') && i + 1 < lines.length) {\n cmd = cmd.slice(0, -1); // remove trailing backslash\n i++;\n cmd += ` ${lines[i].trim()}`;\n }\n\n // Strip trailing pipe and everything after (e.g., | jq .)\n const pipeIdx = findUnquotedPipe(cmd);\n if (pipeIdx > 0) {\n cmd = cmd.slice(0, pipeIdx).trim();\n }\n\n // Strip trailing semicolons\n cmd = cmd.replace(/;\\s*$/, '').trim();\n\n if (cmd.length > 4) {\n commands.push(cmd);\n }\n }\n\n i++;\n }\n\n return commands;\n}\n\n/**\n * Find the index of 'curl ' (or 'curl\\t') at the start of a line or after\n * common shell constructs like $(), ``, &&, ||, ;, etc.\n */\nfunction findCurlStart(line: string): number {\n // Direct curl command\n if (line.startsWith('curl ') || line === 'curl') {\n return 0;\n }\n\n // After shell operators: &&, ||, ;, |, $(, `\n const patterns = [/(?:^|&&\\s*|;\\s*|\\|\\|\\s*|\\$\\(\\s*|`\\s*)curl\\s/];\n\n for (const p of patterns) {\n const match = p.exec(line);\n if (match) {\n const idx = line.indexOf('curl', match.index);\n if (idx >= 0) {\n return idx;\n }\n }\n }\n\n return -1;\n}\n\n/**\n * Find unquoted pipe character for stripping piped output.\n */\nfunction findUnquotedPipe(s: string): number {\n let inSingle = false;\n let inDouble = false;\n\n for (let i = 0; i < s.length; i++) {\n const ch = s[i];\n\n if (ch === '\\\\' && !inSingle) {\n i++; // skip escaped char\n continue;\n }\n\n if (ch === \"'\" && !inDouble) {\n inSingle = !inSingle;\n continue;\n }\n\n if (ch === '\"' && !inSingle) {\n inDouble = !inDouble;\n continue;\n }\n\n if (ch === '|' && !inSingle && !inDouble) {\n return i;\n }\n }\n\n return -1;\n}\n",
|
|
16
|
+
"/**\n * Curl generator: YAML (RequestConfig) → canonical curl command string.\n * Produces deterministic, shell-safe curl commands.\n */\n\nimport type { RequestConfig } from '../types/config';\nimport type { CurlRunnerIR } from './types';\n\n/**\n * Generate a curl command from a RequestConfig (YAML parsed).\n */\nexport function generateCurlFromYaml(config: RequestConfig): string {\n const segments: string[] = ['curl'];\n\n const method = config.method || 'GET';\n if (method !== 'GET' || config.body || config.formData) {\n segments.push(`-X ${method}`);\n }\n\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n segments.push(`-H ${shellQuote(`${key}: ${value}`)}`);\n }\n }\n\n if (config.auth) {\n if (config.auth.type === 'basic' && config.auth.username) {\n segments.push(`-u ${shellQuote(`${config.auth.username}:${config.auth.password || ''}`)}`);\n } else if (config.auth.type === 'bearer' && config.auth.token) {\n segments.push(`-H ${shellQuote(`Authorization: Bearer ${config.auth.token}`)}`);\n }\n }\n\n if (config.formData) {\n for (const [fieldName, fieldValue] of Object.entries(config.formData)) {\n if (typeof fieldValue === 'object' && fieldValue !== null && 'file' in fieldValue) {\n let fileSpec = `@${fieldValue.file}`;\n if (fieldValue.filename) {\n fileSpec += `;filename=${fieldValue.filename}`;\n }\n if (fieldValue.contentType) {\n fileSpec += `;type=${fieldValue.contentType}`;\n }\n segments.push(`-F ${shellQuote(`${fieldName}=${fileSpec}`)}`);\n } else {\n segments.push(`--form-string ${shellQuote(`${fieldName}=${String(fieldValue)}`)}`);\n }\n }\n } else if (config.body !== undefined) {\n const bodyStr = typeof config.body === 'string' ? config.body : JSON.stringify(config.body);\n segments.push(`-d ${shellQuote(bodyStr)}`);\n if (!config.headers?.['Content-Type'] && typeof config.body !== 'string') {\n segments.push(`-H ${shellQuote('Content-Type: application/json')}`);\n }\n }\n\n if (config.timeout) {\n segments.push(`--max-time ${Math.ceil(config.timeout / 1000)}`);\n }\n\n if (config.followRedirects !== false) {\n segments.push('-L');\n }\n if (config.maxRedirects) {\n segments.push(`--max-redirs ${config.maxRedirects}`);\n }\n\n if (config.proxy) {\n segments.push(`-x ${shellQuote(config.proxy)}`);\n }\n if (config.insecure) {\n segments.push('-k');\n }\n if (config.ssl) {\n if (config.ssl.verify === false) {\n segments.push('-k');\n }\n if (config.ssl.ca) {\n segments.push(`--cacert ${shellQuote(config.ssl.ca)}`);\n }\n if (config.ssl.cert) {\n segments.push(`--cert ${shellQuote(config.ssl.cert)}`);\n }\n if (config.ssl.key) {\n segments.push(`--key ${shellQuote(config.ssl.key)}`);\n }\n }\n if (config.http2) {\n segments.push('--http2');\n }\n if (config.output) {\n segments.push(`-o ${shellQuote(config.output)}`);\n }\n\n let url = config.url;\n if (config.params && Object.keys(config.params).length > 0) {\n const qs = new URLSearchParams(config.params).toString();\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n segments.push(shellQuote(url));\n\n return segments.join(' \\\\\\n ');\n}\n\n/**\n * Generate a curl command from a CurlRunnerIR.\n */\nexport function generateCurlFromIR(ir: CurlRunnerIR): string {\n const segments: string[] = ['curl'];\n\n if (ir.method !== 'GET' || ir.body || ir.formData) {\n segments.push(`-X ${ir.method}`);\n }\n\n for (const [key, value] of Object.entries(ir.headers)) {\n segments.push(`-H ${shellQuote(`${key}: ${value}`)}`);\n }\n\n if (ir.auth) {\n if (ir.auth.type === 'basic') {\n segments.push(`-u ${shellQuote(`${ir.auth.username || ''}:${ir.auth.password || ''}`)}`);\n } else if (ir.auth.type === 'bearer') {\n segments.push(`-H ${shellQuote(`Authorization: Bearer ${ir.auth.token || ''}`)}`);\n }\n }\n\n if (ir.formData) {\n for (const [fieldName, fieldValue] of Object.entries(ir.formData)) {\n if (typeof fieldValue === 'string') {\n segments.push(`--form-string ${shellQuote(`${fieldName}=${fieldValue}`)}`);\n } else {\n let fileSpec = `@${fieldValue.file}`;\n if (fieldValue.filename) {\n fileSpec += `;filename=${fieldValue.filename}`;\n }\n if (fieldValue.contentType) {\n fileSpec += `;type=${fieldValue.contentType}`;\n }\n segments.push(`-F ${shellQuote(`${fieldName}=${fileSpec}`)}`);\n }\n }\n } else if (ir.body) {\n if (ir.body.type === 'json') {\n segments.push(`-d ${shellQuote(JSON.stringify(ir.body.content))}`);\n if (!ir.headers['Content-Type']) {\n segments.push(`-H ${shellQuote('Content-Type: application/json')}`);\n }\n } else if (ir.body.type === 'urlencoded') {\n segments.push(`--data-urlencode ${shellQuote(String(ir.body.content))}`);\n } else if (ir.body.type === 'binary') {\n segments.push(`--data-binary ${shellQuote(String(ir.body.content))}`);\n } else {\n segments.push(`-d ${shellQuote(String(ir.body.content))}`);\n }\n }\n\n if (ir.timeout !== undefined) {\n segments.push(`--max-time ${Math.ceil(ir.timeout / 1000)}`);\n }\n\n if (ir.followRedirects) {\n segments.push('-L');\n }\n if (ir.maxRedirects !== undefined) {\n segments.push(`--max-redirs ${ir.maxRedirects}`);\n }\n if (ir.proxy) {\n segments.push(`-x ${shellQuote(ir.proxy)}`);\n }\n if (ir.insecure) {\n segments.push('-k');\n }\n if (ir.http2) {\n segments.push('--http2');\n }\n if (ir.output) {\n segments.push(`-o ${shellQuote(ir.output)}`);\n }\n\n if (ir.ssl) {\n if (ir.ssl.ca) {\n segments.push(`--cacert ${shellQuote(ir.ssl.ca)}`);\n }\n if (ir.ssl.cert) {\n segments.push(`--cert ${shellQuote(ir.ssl.cert)}`);\n }\n if (ir.ssl.key) {\n segments.push(`--key ${shellQuote(ir.ssl.key)}`);\n }\n }\n\n let url = ir.url;\n if (ir.params && Object.keys(ir.params).length > 0) {\n const qs = new URLSearchParams(ir.params).toString();\n url += (url.includes('?') ? '&' : '?') + qs;\n }\n segments.push(shellQuote(url));\n\n return segments.join(' \\\\\\n ');\n}\n\n/** Shell-safe quoting for a value */\nfunction shellQuote(s: string): string {\n // If it contains single quotes, use double quoting with escapes\n if (s.includes(\"'\")) {\n return `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\$/g, '\\\\$').replace(/`/g, '\\\\`')}\"`;\n }\n // If it contains spaces or special chars that need quoting, use single quotes\n if (/[^a-zA-Z0-9_./:@=,+%-]/.test(s)) {\n return `'${s}'`;\n }\n return s;\n}\n",
|
|
17
|
+
"/**\n * Shell-safe tokenizer for curl commands.\n * Handles single quotes, double quotes, escapes, backslash line continuations.\n */\n\n/** Tokenize a shell command string into an array of tokens. */\nexport function tokenize(input: string): string[] {\n const tokens: string[] = [];\n let current = '';\n let i = 0;\n const len = input.length;\n\n while (i < len) {\n const ch = input[i];\n\n // Backslash continuation (\\ followed by newline)\n if (ch === '\\\\' && i + 1 < len && (input[i + 1] === '\\n' || input[i + 1] === '\\r')) {\n i += 2;\n // Skip \\r\\n\n if (i < len && input[i] === '\\n') {\n i++;\n }\n // Skip leading whitespace on next line\n while (i < len && (input[i] === ' ' || input[i] === '\\t')) {\n i++;\n }\n continue;\n }\n\n // Whitespace outside quotes = token boundary\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r') {\n if (current.length > 0) {\n tokens.push(current);\n current = '';\n }\n i++;\n continue;\n }\n\n // Single-quoted string (no escape processing inside)\n if (ch === \"'\") {\n i++;\n while (i < len && input[i] !== \"'\") {\n current += input[i];\n i++;\n }\n if (i < len) {\n i++; // skip closing quote\n }\n continue;\n }\n\n // Double-quoted string (with escape processing)\n if (ch === '\"') {\n i++;\n while (i < len && input[i] !== '\"') {\n if (input[i] === '\\\\' && i + 1 < len) {\n const next = input[i + 1];\n // Only these chars are special in double quotes\n if (next === '\"' || next === '\\\\' || next === '$' || next === '`' || next === '\\n') {\n if (next === '\\n') {\n // line continuation inside double quotes\n i += 2;\n continue;\n }\n current += next;\n i += 2;\n continue;\n }\n }\n current += input[i];\n i++;\n }\n if (i < len) {\n i++; // skip closing quote\n }\n continue;\n }\n\n // Backslash escape outside quotes\n if (ch === '\\\\' && i + 1 < len) {\n current += input[i + 1];\n i += 2;\n continue;\n }\n\n // Regular character\n current += ch;\n i++;\n }\n\n if (current.length > 0) {\n tokens.push(current);\n }\n\n return tokens;\n}\n",
|
|
18
|
+
"/**\n * Curl semantic parser: maps shell tokens to a structured CurlAST.\n */\n\nimport { tokenize } from './tokenizer';\nimport type { CurlAST } from './types';\n\n/** Flags that take a value argument */\nconst VALUE_FLAGS = new Set([\n '-X',\n '--request',\n '-H',\n '--header',\n '-d',\n '--data',\n '--data-raw',\n '--data-binary',\n '--data-ascii',\n '--data-urlencode',\n '-F',\n '--form',\n '--form-string',\n '-u',\n '--user',\n '-o',\n '--output',\n '-x',\n '--proxy',\n '--max-time',\n '-m',\n '--max-redirs',\n '--cacert',\n '--cert',\n '--key',\n '-b',\n '--cookie',\n '-c',\n '--cookie-jar',\n '-A',\n '--user-agent',\n '-e',\n '--referer',\n '--connect-timeout',\n '--retry',\n '--retry-delay',\n '-w',\n '--write-out',\n '--resolve',\n '--interface',\n '--local-port',\n '--limit-rate',\n '--ciphers',\n '--proto',\n '--tlsv1.2',\n '--tlsv1.3',\n]);\n\n/** Flags that are boolean (no value) */\nconst BOOLEAN_FLAGS = new Set([\n '-G',\n '--get',\n '-I',\n '--head',\n '-L',\n '--location',\n '-k',\n '--insecure',\n '-s',\n '--silent',\n '-S',\n '--show-error',\n '-v',\n '--verbose',\n '--compressed',\n '--http2',\n '--http2-prior-knowledge',\n '--http1.1',\n '-N',\n '--no-buffer',\n '--raw',\n '-f',\n '--fail',\n '--fail-early',\n '--globoff',\n '-#',\n '--progress-bar',\n '--tr-encoding',\n '--tcp-nodelay',\n '--tcp-fastopen',\n]);\n\n/**\n * Parse a raw curl command string into a CurlAST.\n * Handles \"curl ...\" prefix and all common flags.\n */\nexport function parseCurl(input: string): CurlAST {\n const tokens = tokenize(input.trim());\n return parseTokens(tokens);\n}\n\n/**\n * Parse pre-tokenized tokens into CurlAST.\n */\nexport function parseTokens(tokens: string[]): CurlAST {\n const ast: CurlAST = {\n url: '',\n headers: [],\n unsupportedFlags: [],\n };\n\n const dataEntries: string[] = [];\n const dataRawEntries: string[] = [];\n const dataBinaryEntries: string[] = [];\n const dataUrlencodeEntries: string[] = [];\n const formEntries: string[] = [];\n const formStringEntries: string[] = [];\n\n let i = 0;\n\n // Skip \"curl\" command if present\n if (tokens.length > 0 && tokens[0] === 'curl') {\n i = 1;\n }\n\n while (i < tokens.length) {\n const token = tokens[i];\n\n // URL (non-flag argument)\n if (!token.startsWith('-')) {\n if (!ast.url) {\n ast.url = token;\n }\n i++;\n continue;\n }\n\n // Handle combined short flags like -sSL\n if (token.startsWith('-') && !token.startsWith('--') && token.length > 2) {\n // Check if this is a known value flag (e.g., -XPOST, -d'data')\n const firstFlag = `-${token[1]}`;\n if (VALUE_FLAGS.has(firstFlag)) {\n // e.g., -XPOST → -X POST\n const value = token.slice(2);\n i = processFlag(\n firstFlag,\n value,\n tokens,\n i,\n ast,\n dataEntries,\n dataRawEntries,\n dataBinaryEntries,\n dataUrlencodeEntries,\n formEntries,\n formStringEntries,\n );\n continue;\n }\n\n // Combined boolean short flags like -sSL\n let allBoolean = true;\n for (let j = 1; j < token.length; j++) {\n const f = `-${token[j]}`;\n if (!BOOLEAN_FLAGS.has(f)) {\n allBoolean = false;\n break;\n }\n }\n\n if (allBoolean) {\n for (let j = 1; j < token.length; j++) {\n i = processFlag(\n `-${token[j]}`,\n undefined,\n tokens,\n i,\n ast,\n dataEntries,\n dataRawEntries,\n dataBinaryEntries,\n dataUrlencodeEntries,\n formEntries,\n formStringEntries,\n );\n }\n i++;\n continue;\n }\n }\n\n // Value flags\n if (VALUE_FLAGS.has(token)) {\n const value = tokens[i + 1];\n i = processFlag(\n token,\n value,\n tokens,\n i,\n ast,\n dataEntries,\n dataRawEntries,\n dataBinaryEntries,\n dataUrlencodeEntries,\n formEntries,\n formStringEntries,\n );\n continue;\n }\n\n // Boolean flags\n if (BOOLEAN_FLAGS.has(token)) {\n i = processFlag(\n token,\n undefined,\n tokens,\n i,\n ast,\n dataEntries,\n dataRawEntries,\n dataBinaryEntries,\n dataUrlencodeEntries,\n formEntries,\n formStringEntries,\n );\n continue;\n }\n\n // Unknown flag\n if (token.startsWith('-')) {\n // Check if next token looks like a value (doesn't start with -)\n const next = tokens[i + 1];\n if (next && !next.startsWith('-')) {\n ast.unsupportedFlags.push({ flag: token, value: next });\n i += 2;\n } else {\n ast.unsupportedFlags.push({ flag: token });\n i++;\n }\n continue;\n }\n\n i++;\n }\n\n if (dataEntries.length > 0) {\n ast.data = dataEntries;\n }\n if (dataRawEntries.length > 0) {\n ast.dataRaw = dataRawEntries;\n }\n if (dataBinaryEntries.length > 0) {\n ast.dataBinary = dataBinaryEntries;\n }\n if (dataUrlencodeEntries.length > 0) {\n ast.dataUrlencode = dataUrlencodeEntries;\n }\n if (formEntries.length > 0) {\n ast.form = formEntries;\n }\n if (formStringEntries.length > 0) {\n ast.formString = formStringEntries;\n }\n\n return ast;\n}\n\nfunction processFlag(\n flag: string,\n value: string | undefined,\n _tokens: string[],\n i: number,\n ast: CurlAST,\n data: string[],\n dataRaw: string[],\n dataBinary: string[],\n dataUrlencode: string[],\n form: string[],\n formString: string[],\n): number {\n switch (flag) {\n case '-X':\n case '--request':\n ast.method = value?.toUpperCase();\n return i + 2;\n\n case '-H':\n case '--header': {\n if (value) {\n const colonIdx = value.indexOf(':');\n if (colonIdx > 0) {\n ast.headers.push({\n key: value.slice(0, colonIdx).trim(),\n value: value.slice(colonIdx + 1).trim(),\n });\n }\n }\n return i + 2;\n }\n\n case '-d':\n case '--data':\n case '--data-ascii':\n if (value !== undefined) {\n data.push(value);\n }\n return i + 2;\n\n case '--data-raw':\n if (value !== undefined) {\n dataRaw.push(value);\n }\n return i + 2;\n\n case '--data-binary':\n if (value !== undefined) {\n dataBinary.push(value);\n }\n return i + 2;\n\n case '--data-urlencode':\n if (value !== undefined) {\n dataUrlencode.push(value);\n }\n return i + 2;\n\n case '-F':\n case '--form':\n if (value !== undefined) {\n form.push(value);\n }\n return i + 2;\n\n case '--form-string':\n if (value !== undefined) {\n formString.push(value);\n }\n return i + 2;\n\n case '-u':\n case '--user':\n ast.user = value;\n return i + 2;\n\n case '-o':\n case '--output':\n ast.output = value;\n return i + 2;\n\n case '-x':\n case '--proxy':\n ast.proxy = value;\n return i + 2;\n\n case '--max-time':\n case '-m':\n if (value) {\n ast.maxTime = Number(value);\n }\n return i + 2;\n\n case '--max-redirs':\n if (value) {\n ast.maxRedirs = Number(value);\n }\n return i + 2;\n\n case '--cacert':\n ast.cacert = value;\n return i + 2;\n\n case '--cert':\n ast.cert = value;\n return i + 2;\n\n case '--key':\n ast.key = value;\n return i + 2;\n\n case '-b':\n case '--cookie':\n ast.cookie = value;\n return i + 2;\n\n case '-c':\n case '--cookie-jar':\n ast.cookieJar = value;\n return i + 2;\n\n case '-A':\n case '--user-agent':\n ast.userAgent = value;\n return i + 2;\n\n case '-e':\n case '--referer':\n ast.referer = value;\n return i + 2;\n\n case '-G':\n case '--get':\n ast.get = true;\n return i + 1;\n\n case '-I':\n case '--head':\n ast.head = true;\n return i + 1;\n\n case '-L':\n case '--location':\n ast.location = true;\n return i + 1;\n\n case '-k':\n case '--insecure':\n ast.insecure = true;\n return i + 1;\n\n case '--compressed':\n ast.compressed = true;\n return i + 1;\n\n case '--http2':\n ast.http2 = true;\n return i + 1;\n\n case '-s':\n case '--silent':\n ast.silent = true;\n return i + 1;\n\n case '-v':\n case '--verbose':\n ast.verbose = true;\n return i + 1;\n\n default:\n // Skip other known value flags\n if (VALUE_FLAGS.has(flag)) {\n return i + 2;\n }\n return i + 1;\n }\n}\n",
|
|
19
|
+
"/**\n * Normalization layer: CurlAST → CurlRunnerIR.\n * Infers methods, detects body types, canonicalizes headers, parses query strings.\n */\n\nimport type { AuthIR, BodyIR, CurlAST, CurlRunnerIR, FormFieldIR, FormFileIR } from './types';\n\n/**\n * Normalize a CurlAST into the canonical CurlRunnerIR.\n */\nexport function normalize(ast: CurlAST): CurlRunnerIR {\n const warnings: string[] = [];\n\n // Parse URL and extract query params\n const { url, params } = parseUrl(ast.url);\n\n // Normalize headers (canonical casing)\n const headers = normalizeHeaders(ast);\n\n // Detect auth from headers or -u flag\n const auth = detectAuth(ast, headers);\n\n // Detect body\n const { body, formData } = detectBody(ast, warnings);\n\n // Infer method\n const method = inferMethod(ast, body, formData);\n\n // SSL\n const ssl = detectSsl(ast);\n\n // Unsupported flags → warnings\n for (const f of ast.unsupportedFlags) {\n warnings.push(`Unsupported curl flag: ${f.flag}${f.value ? ` ${f.value}` : ''}`);\n }\n if (ast.compressed) {\n warnings.push('Flag --compressed has no YAML equivalent; curl handles decompression natively');\n }\n if (ast.cookie) {\n warnings.push(`Cookie flag (-b ${ast.cookie}) stored as header; manual review recommended`);\n headers.Cookie = ast.cookie;\n }\n if (ast.cookieJar) {\n warnings.push(`Cookie jar flag (-c ${ast.cookieJar}) has no YAML equivalent`);\n }\n if (ast.userAgent && !headers['User-Agent']) {\n headers['User-Agent'] = ast.userAgent;\n }\n if (ast.referer && !headers.Referer) {\n headers.Referer = ast.referer;\n }\n\n const ir: CurlRunnerIR = {\n method,\n url,\n headers,\n metadata: {\n source: 'curl',\n warnings,\n unsupportedFlags: ast.unsupportedFlags.length > 0 ? ast.unsupportedFlags : undefined,\n },\n };\n\n if (Object.keys(params).length > 0) {\n ir.params = params;\n }\n if (body) {\n ir.body = body;\n }\n if (formData) {\n ir.formData = formData;\n }\n if (auth) {\n ir.auth = auth;\n }\n if (ast.insecure) {\n ir.insecure = true;\n }\n if (ast.location) {\n ir.followRedirects = true;\n }\n if (ast.maxRedirs !== undefined) {\n ir.maxRedirects = ast.maxRedirs;\n }\n if (ast.maxTime !== undefined) {\n ir.timeout = ast.maxTime * 1000; // seconds → ms\n }\n if (ast.proxy) {\n ir.proxy = ast.proxy;\n }\n if (ast.output) {\n ir.output = ast.output;\n }\n if (ast.http2) {\n ir.http2 = true;\n }\n if (ssl) {\n ir.ssl = ssl;\n }\n\n return ir;\n}\n\nfunction parseUrl(rawUrl: string): { url: string; params: Record<string, string> } {\n const params: Record<string, string> = {};\n if (!rawUrl) {\n return { url: '', params };\n }\n\n const qIdx = rawUrl.indexOf('?');\n if (qIdx === -1) {\n return { url: rawUrl, params };\n }\n\n const base = rawUrl.slice(0, qIdx);\n const query = rawUrl.slice(qIdx + 1);\n\n for (const pair of query.split('&')) {\n const eqIdx = pair.indexOf('=');\n if (eqIdx > 0) {\n const key = decodeURIComponent(pair.slice(0, eqIdx));\n const val = decodeURIComponent(pair.slice(eqIdx + 1));\n params[key] = val;\n } else if (pair.length > 0) {\n params[decodeURIComponent(pair)] = '';\n }\n }\n\n return { url: base, params };\n}\n\nfunction normalizeHeaders(ast: CurlAST): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const h of ast.headers) {\n // Skip auth headers that will be detected separately\n const lower = h.key.toLowerCase();\n if (lower === 'authorization') {\n // Keep for auth detection but don't add to headers\n continue;\n }\n headers[canonicalHeaderCase(h.key)] = h.value;\n }\n return headers;\n}\n\n/** Canonical HTTP header casing: content-type → Content-Type */\nfunction canonicalHeaderCase(header: string): string {\n return header\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join('-');\n}\n\nfunction detectAuth(ast: CurlAST, headers: Record<string, string>): AuthIR | undefined {\n // Check -u flag\n if (ast.user) {\n const colonIdx = ast.user.indexOf(':');\n if (colonIdx > 0) {\n return {\n type: 'basic',\n username: ast.user.slice(0, colonIdx),\n password: ast.user.slice(colonIdx + 1),\n };\n }\n return { type: 'basic', username: ast.user, password: '' };\n }\n\n // Check Authorization header\n for (const h of ast.headers) {\n if (h.key.toLowerCase() === 'authorization') {\n const value = h.value.trim();\n if (value.toLowerCase().startsWith('bearer ')) {\n return { type: 'bearer', token: value.slice(7).trim() };\n }\n if (value.toLowerCase().startsWith('basic ')) {\n // Decode basic auth\n try {\n const decoded = atob(value.slice(6).trim());\n const colonIdx = decoded.indexOf(':');\n if (colonIdx > 0) {\n return {\n type: 'basic',\n username: decoded.slice(0, colonIdx),\n password: decoded.slice(colonIdx + 1),\n };\n }\n } catch {\n // Can't decode, store as-is in header\n headers.Authorization = value;\n }\n } else {\n // Unknown auth scheme, keep as header\n headers.Authorization = value;\n }\n }\n }\n\n return undefined;\n}\n\nfunction detectBody(\n ast: CurlAST,\n _warnings: string[],\n): { body?: BodyIR; formData?: Record<string, FormFieldIR> } {\n // Form data (-F)\n if (ast.form && ast.form.length > 0) {\n const formData: Record<string, FormFieldIR> = {};\n for (const entry of ast.form) {\n parseFormEntry(entry, formData);\n }\n if (ast.formString) {\n for (const entry of ast.formString) {\n const eqIdx = entry.indexOf('=');\n if (eqIdx > 0) {\n formData[entry.slice(0, eqIdx)] = entry.slice(eqIdx + 1);\n }\n }\n }\n return { formData };\n }\n\n // URL-encoded data (--data-urlencode)\n if (ast.dataUrlencode && ast.dataUrlencode.length > 0) {\n const parts = ast.dataUrlencode.map((d) => encodeURIComponent(d));\n return { body: { type: 'urlencoded', content: parts.join('&') } };\n }\n\n // Binary data (--data-binary)\n if (ast.dataBinary && ast.dataBinary.length > 0) {\n if (ast.dataBinary[0].startsWith('@')) {\n return { body: { type: 'binary', content: ast.dataBinary[0] } };\n }\n return { body: { type: 'raw', content: ast.dataBinary.join('') } };\n }\n\n // Regular data (-d / --data / --data-raw)\n const allData = [...(ast.data || []), ...(ast.dataRaw || [])];\n if (allData.length > 0) {\n const combined = allData.join('&');\n\n // Try JSON parse\n try {\n const parsed = JSON.parse(combined);\n return { body: { type: 'json', content: parsed } };\n } catch {\n // Not JSON — check if form-urlencoded\n if (looksLikeFormUrlencoded(combined)) {\n return { body: { type: 'urlencoded', content: combined } };\n }\n return { body: { type: 'raw', content: combined } };\n }\n }\n\n return {};\n}\n\nfunction parseFormEntry(entry: string, formData: Record<string, FormFieldIR>): void {\n const eqIdx = entry.indexOf('=');\n if (eqIdx <= 0) {\n return;\n }\n\n const key = entry.slice(0, eqIdx);\n const value = entry.slice(eqIdx + 1);\n\n if (value.startsWith('@')) {\n // File attachment: field=@path;filename=x;type=y\n const parts = value.slice(1).split(';');\n const file: FormFileIR = { file: parts[0] };\n for (let i = 1; i < parts.length; i++) {\n const [k, v] = parts[i].split('=');\n if (k === 'filename') {\n file.filename = v;\n } else if (k === 'type') {\n file.contentType = v;\n }\n }\n formData[key] = file;\n } else {\n formData[key] = value;\n }\n}\n\nfunction looksLikeFormUrlencoded(s: string): boolean {\n // Simple heuristic: contains key=value pairs separated by &\n return /^[^=&]+=[^&]*(&[^=&]+=[^&]*)*$/.test(s);\n}\n\nfunction inferMethod(ast: CurlAST, body?: BodyIR, formData?: Record<string, FormFieldIR>): string {\n // Explicit -X overrides everything\n if (ast.method) {\n return ast.method;\n }\n // --head / -I\n if (ast.head) {\n return 'HEAD';\n }\n // --get / -G forces GET even with data\n if (ast.get) {\n return 'GET';\n }\n // Data implies POST\n if (body || formData) {\n return 'POST';\n }\n // Default\n return 'GET';\n}\n\nfunction detectSsl(ast: CurlAST): { ca?: string; cert?: string; key?: string } | undefined {\n if (!ast.cacert && !ast.cert && !ast.key) {\n return undefined;\n }\n const ssl: { ca?: string; cert?: string; key?: string } = {};\n if (ast.cacert) {\n ssl.ca = ast.cacert;\n }\n if (ast.cert) {\n ssl.cert = ast.cert;\n }\n if (ast.key) {\n ssl.key = ast.key;\n }\n return ssl;\n}\n",
|
|
20
|
+
"/**\n * YAML serializer: CurlRunnerIR → curl-runner YAML string.\n * Produces human-readable YAML with stable key ordering and loss comments.\n */\n\nimport type { CurlRunnerIR } from './types';\n\n/**\n * Serialize a single IR to YAML string.\n */\nexport function serializeToYaml(\n ir: CurlRunnerIR,\n options?: { pretty?: boolean; lossReport?: boolean },\n): string {\n const lines: string[] = [];\n const pretty = options?.pretty ?? true;\n const lossReport = options?.lossReport ?? true;\n\n // Loss report as comments\n if (lossReport && ir.metadata.warnings.length > 0) {\n for (const w of ir.metadata.warnings) {\n lines.push(`# Warning: ${w}`);\n }\n lines.push('');\n }\n\n lines.push('request:');\n if (ir.name) {\n lines.push(` name: ${yamlStr(ir.name)}`);\n }\n lines.push(` method: ${ir.method}`);\n lines.push(` url: ${yamlStr(ir.url)}`);\n\n // Params\n if (ir.params && Object.keys(ir.params).length > 0) {\n lines.push(' params:');\n for (const [k, v] of sortedEntries(ir.params)) {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n }\n }\n\n // Headers\n if (Object.keys(ir.headers).length > 0) {\n lines.push(' headers:');\n for (const [k, v] of sortedEntries(ir.headers)) {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n }\n }\n\n // Auth\n if (ir.auth) {\n lines.push(' auth:');\n lines.push(` type: ${ir.auth.type}`);\n if (ir.auth.type === 'basic') {\n lines.push(` username: ${yamlStr(ir.auth.username || '')}`);\n lines.push(` password: ${yamlStr(ir.auth.password || '')}`);\n } else if (ir.auth.type === 'bearer') {\n lines.push(` token: ${yamlStr(ir.auth.token || '')}`);\n }\n }\n\n // Body\n if (ir.body) {\n lines.push(' body:');\n if (ir.body.type === 'json') {\n if (pretty) {\n const jsonLines = serializeJsonToYaml(ir.body.content, 4);\n lines.push(...jsonLines);\n } else {\n lines.push(` json: ${JSON.stringify(ir.body.content)}`);\n }\n } else if (ir.body.type === 'urlencoded') {\n lines.push(` form: ${yamlStr(String(ir.body.content))}`);\n } else if (ir.body.type === 'binary') {\n lines.push(` binary: ${yamlStr(String(ir.body.content))}`);\n } else {\n lines.push(` raw: ${yamlStr(String(ir.body.content))}`);\n }\n }\n\n // Form data\n if (ir.formData && Object.keys(ir.formData).length > 0) {\n lines.push(' formData:');\n for (const [k, v] of sortedEntries(ir.formData)) {\n if (typeof v === 'string') {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n } else {\n lines.push(` ${yamlKey(k)}:`);\n lines.push(` file: ${yamlStr(v.file)}`);\n if (v.filename) {\n lines.push(` filename: ${yamlStr(v.filename)}`);\n }\n if (v.contentType) {\n lines.push(` contentType: ${yamlStr(v.contentType)}`);\n }\n }\n }\n }\n\n // Optional fields\n if (ir.timeout !== undefined) {\n lines.push(` timeout: ${ir.timeout}`);\n }\n if (ir.followRedirects) {\n lines.push(' followRedirects: true');\n }\n if (ir.maxRedirects !== undefined) {\n lines.push(` maxRedirects: ${ir.maxRedirects}`);\n }\n if (ir.proxy) {\n lines.push(` proxy: ${yamlStr(ir.proxy)}`);\n }\n if (ir.insecure) {\n lines.push(' insecure: true');\n }\n if (ir.http2) {\n lines.push(' http2: true');\n }\n if (ir.output) {\n lines.push(` output: ${yamlStr(ir.output)}`);\n }\n\n // SSL\n if (ir.ssl) {\n lines.push(' ssl:');\n if (ir.ssl.ca) {\n lines.push(` ca: ${yamlStr(ir.ssl.ca)}`);\n }\n if (ir.ssl.cert) {\n lines.push(` cert: ${yamlStr(ir.ssl.cert)}`);\n }\n if (ir.ssl.key) {\n lines.push(` key: ${yamlStr(ir.ssl.key)}`);\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/**\n * Serialize multiple IRs to a collection YAML string.\n */\nexport function serializeBatchToYaml(\n irs: CurlRunnerIR[],\n options?: { pretty?: boolean; lossReport?: boolean },\n): string {\n const lines: string[] = [];\n const pretty = options?.pretty ?? true;\n const lossReport = options?.lossReport ?? true;\n\n // Collect all warnings\n if (lossReport) {\n const allWarnings = irs.flatMap((ir) => ir.metadata.warnings);\n if (allWarnings.length > 0) {\n for (const w of allWarnings) {\n lines.push(`# Warning: ${w}`);\n }\n lines.push('');\n }\n }\n\n lines.push('requests:');\n\n for (let idx = 0; idx < irs.length; idx++) {\n const ir = irs[idx];\n if (idx > 0) {\n lines.push('');\n }\n\n if (ir.name) {\n lines.push(` - name: ${yamlStr(ir.name)}`);\n } else {\n lines.push(` - name: request_${idx + 1}`);\n }\n\n lines.push(` method: ${ir.method}`);\n lines.push(` url: ${yamlStr(ir.url)}`);\n\n if (ir.params && Object.keys(ir.params).length > 0) {\n lines.push(' params:');\n for (const [k, v] of sortedEntries(ir.params)) {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n }\n }\n\n if (Object.keys(ir.headers).length > 0) {\n lines.push(' headers:');\n for (const [k, v] of sortedEntries(ir.headers)) {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n }\n }\n\n if (ir.auth) {\n lines.push(' auth:');\n lines.push(` type: ${ir.auth.type}`);\n if (ir.auth.type === 'basic') {\n lines.push(` username: ${yamlStr(ir.auth.username || '')}`);\n lines.push(` password: ${yamlStr(ir.auth.password || '')}`);\n } else if (ir.auth.type === 'bearer') {\n lines.push(` token: ${yamlStr(ir.auth.token || '')}`);\n }\n }\n\n if (ir.body) {\n lines.push(' body:');\n if (ir.body.type === 'json') {\n if (pretty) {\n const jsonLines = serializeJsonToYaml(ir.body.content, 6);\n lines.push(...jsonLines);\n } else {\n lines.push(` json: ${JSON.stringify(ir.body.content)}`);\n }\n } else if (ir.body.type === 'urlencoded') {\n lines.push(` form: ${yamlStr(String(ir.body.content))}`);\n } else if (ir.body.type === 'binary') {\n lines.push(` binary: ${yamlStr(String(ir.body.content))}`);\n } else {\n lines.push(` raw: ${yamlStr(String(ir.body.content))}`);\n }\n }\n\n if (ir.formData && Object.keys(ir.formData).length > 0) {\n lines.push(' formData:');\n for (const [k, v] of sortedEntries(ir.formData)) {\n if (typeof v === 'string') {\n lines.push(` ${yamlKey(k)}: ${yamlStr(v)}`);\n } else {\n lines.push(` ${yamlKey(k)}:`);\n lines.push(` file: ${yamlStr(v.file)}`);\n if (v.filename) {\n lines.push(` filename: ${yamlStr(v.filename)}`);\n }\n if (v.contentType) {\n lines.push(` contentType: ${yamlStr(v.contentType)}`);\n }\n }\n }\n }\n\n if (ir.timeout !== undefined) {\n lines.push(` timeout: ${ir.timeout}`);\n }\n if (ir.followRedirects) {\n lines.push(' followRedirects: true');\n }\n if (ir.maxRedirects !== undefined) {\n lines.push(` maxRedirects: ${ir.maxRedirects}`);\n }\n if (ir.proxy) {\n lines.push(` proxy: ${yamlStr(ir.proxy)}`);\n }\n if (ir.insecure) {\n lines.push(' insecure: true');\n }\n if (ir.http2) {\n lines.push(' http2: true');\n }\n if (ir.output) {\n lines.push(` output: ${yamlStr(ir.output)}`);\n }\n\n if (ir.ssl) {\n lines.push(' ssl:');\n if (ir.ssl.ca) {\n lines.push(` ca: ${yamlStr(ir.ssl.ca)}`);\n }\n if (ir.ssl.cert) {\n lines.push(` cert: ${yamlStr(ir.ssl.cert)}`);\n }\n if (ir.ssl.key) {\n lines.push(` key: ${yamlStr(ir.ssl.key)}`);\n }\n }\n }\n\n return `${lines.join('\\n')}\\n`;\n}\n\n/** Serialize JSON value to YAML inline, with proper indentation */\nfunction serializeJsonToYaml(value: unknown, indent: number): string[] {\n const pad = ' '.repeat(indent);\n\n if (value === null || value === undefined) {\n return [`${pad}json: null`];\n }\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return [`${pad}json: ${JSON.stringify(value)}`];\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return [`${pad}json: []`];\n }\n // For simple arrays, use inline\n if (value.every((v) => typeof v !== 'object' || v === null)) {\n return [`${pad}json: [${value.map((v) => JSON.stringify(v)).join(', ')}]`];\n }\n // Complex arrays\n return [`${pad}json: ${JSON.stringify(value)}`];\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj);\n if (keys.length === 0) {\n return [`${pad}json: {}`];\n }\n\n // Use block style for readability\n const lines: string[] = [];\n lines.push(`${pad}json:`);\n for (const key of keys) {\n const v = obj[key];\n if (v === null) {\n lines.push(`${pad} ${yamlKey(key)}: null`);\n } else if (typeof v === 'object' && !Array.isArray(v)) {\n // Nested object → inline JSON\n lines.push(`${pad} ${yamlKey(key)}: ${JSON.stringify(v)}`);\n } else if (Array.isArray(v)) {\n lines.push(`${pad} ${yamlKey(key)}: ${JSON.stringify(v)}`);\n } else {\n lines.push(`${pad} ${yamlKey(key)}: ${yamlValue(v)}`);\n }\n }\n return lines;\n }\n\n return [`${pad}json: ${JSON.stringify(value)}`];\n}\n\n/** Quote a YAML string value if necessary */\nfunction yamlStr(s: string): string {\n if (s === '') {\n return '\"\"';\n }\n // Must quote if contains special chars or looks like a YAML keyword\n if (needsQuoting(s)) {\n return `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n }\n return s;\n}\n\n/** Quote a YAML key if necessary */\nfunction yamlKey(s: string): string {\n if (/^[a-zA-Z_][a-zA-Z0-9_-]*$/.test(s)) {\n return s;\n }\n return `\"${s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/** Format a YAML primitive value */\nfunction yamlValue(v: unknown): string {\n if (typeof v === 'string') {\n return yamlStr(v);\n }\n if (typeof v === 'number' || typeof v === 'boolean') {\n return String(v);\n }\n return JSON.stringify(v);\n}\n\nfunction needsQuoting(s: string): boolean {\n // YAML special characters that need quoting (colon only when followed by space)\n if (/[{}[\\],&*?|>!%#@`]/.test(s)) {\n return true;\n }\n // Colon followed by space or at end of string is a YAML indicator\n if (/: /.test(s) || s.endsWith(':')) {\n return true;\n }\n // Starts with quote char\n if (s.startsWith(\"'\") || s.startsWith('\"')) {\n return true;\n }\n // YAML keywords\n const lower = s.toLowerCase();\n if (['true', 'false', 'null', 'yes', 'no', 'on', 'off'].includes(lower)) {\n return true;\n }\n // Pure number\n if (/^-?\\d+(\\.\\d+)?$/.test(s)) {\n return true;\n }\n // Starts with special\n if (s.startsWith(' ') || s.endsWith(' ')) {\n return true;\n }\n return false;\n}\n\nfunction sortedEntries<T>(obj: Record<string, T>): [string, T][] {\n return Object.entries(obj).sort(([a], [b]) => a.localeCompare(b));\n}\n",
|
|
21
|
+
"/**\n * YAML → IR converter: parses a curl-runner YAML file into CurlRunnerIR.\n */\n\nimport type { RequestConfig } from '../types/config';\nimport type { CurlRunnerIR, FormFieldIR } from './types';\n\n/**\n * Convert a RequestConfig (parsed from YAML) to CurlRunnerIR.\n */\nexport function yamlToIR(config: RequestConfig): CurlRunnerIR {\n const warnings: string[] = [];\n const headers: Record<string, string> = {};\n\n if (config.headers) {\n for (const [k, v] of Object.entries(config.headers)) {\n headers[k] = v;\n }\n }\n\n const ir: CurlRunnerIR = {\n method: config.method || 'GET',\n url: config.url,\n headers,\n metadata: { source: 'yaml', warnings },\n };\n\n if (config.name) {\n ir.name = config.name;\n }\n if (config.params) {\n ir.params = { ...config.params };\n }\n\n // Auth\n if (config.auth) {\n ir.auth = {\n type: config.auth.type,\n username: config.auth.username,\n password: config.auth.password,\n token: config.auth.token,\n };\n }\n\n // Body\n if (config.body !== undefined) {\n if (typeof config.body === 'object' && config.body !== null && !Array.isArray(config.body)) {\n const bodyObj = config.body as Record<string, unknown>;\n if ('json' in bodyObj) {\n ir.body = { type: 'json', content: bodyObj.json };\n } else if ('form' in bodyObj) {\n ir.body = { type: 'urlencoded', content: String(bodyObj.form) };\n } else if ('raw' in bodyObj) {\n ir.body = { type: 'raw', content: String(bodyObj.raw) };\n } else if ('binary' in bodyObj) {\n ir.body = { type: 'binary', content: String(bodyObj.binary) };\n } else {\n // Treat entire object as JSON body\n ir.body = { type: 'json', content: config.body };\n }\n } else {\n // Primitive or array body → JSON\n ir.body = { type: 'json', content: config.body };\n }\n }\n\n // Form data\n if (config.formData) {\n const formData: Record<string, FormFieldIR> = {};\n for (const [k, v] of Object.entries(config.formData)) {\n if (typeof v === 'object' && v !== null && 'file' in v) {\n formData[k] = {\n file: v.file,\n filename: v.filename,\n contentType: v.contentType,\n };\n } else {\n formData[k] = String(v);\n }\n }\n ir.formData = formData;\n }\n\n if (config.timeout) {\n ir.timeout = config.timeout;\n }\n if (config.followRedirects !== undefined) {\n ir.followRedirects = config.followRedirects;\n }\n if (config.maxRedirects) {\n ir.maxRedirects = config.maxRedirects;\n }\n if (config.proxy) {\n ir.proxy = config.proxy;\n }\n if (config.insecure) {\n ir.insecure = true;\n }\n if (config.http2) {\n ir.http2 = true;\n }\n if (config.output) {\n ir.output = config.output;\n }\n\n if (config.ssl) {\n ir.ssl = {};\n if (config.ssl.ca) {\n ir.ssl.ca = config.ssl.ca;\n }\n if (config.ssl.cert) {\n ir.ssl.cert = config.ssl.cert;\n }\n if (config.ssl.key) {\n ir.ssl.key = config.ssl.key;\n }\n }\n\n // Warn about YAML-only features that don't map to curl\n if (config.expect) {\n warnings.push('expect block has no curl equivalent');\n }\n if (config.store) {\n warnings.push('store block has no curl equivalent');\n }\n if (config.when) {\n warnings.push('when condition has no curl equivalent');\n }\n if (config.retry) {\n warnings.push('retry config simplified in curl output');\n }\n if (config.snapshot) {\n warnings.push('snapshot config has no curl equivalent');\n }\n if (config.diff) {\n warnings.push('diff config has no curl equivalent');\n }\n\n return ir;\n}\n",
|
|
22
|
+
"/**\n * Convert command handler.\n * Routes: convert curl \"...\", convert file script.sh, convert yaml test.yaml\n */\n\nimport type { RequestConfig, YamlFile } from '../types/config';\nimport { extractCurlCommands } from './batch-parser';\nimport { generateCurlFromIR } from './curl-generator';\nimport { parseCurl } from './curl-parser';\nimport { normalize } from './normalizer';\nimport { tokenize } from './tokenizer';\nimport type { ConvertOptions, CurlRunnerIR } from './types';\nimport { serializeBatchToYaml, serializeToYaml } from './yaml-serializer';\nimport { yamlToIR } from './yaml-to-ir';\n\nexport interface ConvertResult {\n output: string;\n warnings: string[];\n debug?: {\n tokens?: string[];\n ast?: unknown;\n ir?: CurlRunnerIR | CurlRunnerIR[];\n };\n}\n\n/**\n * Convert a curl command string → YAML.\n */\nexport function convertCurlToYaml(curlCmd: string, options?: ConvertOptions): ConvertResult {\n const ast = parseCurl(curlCmd);\n const ir = normalize(ast);\n\n const output = serializeToYaml(ir, {\n pretty: options?.pretty ?? true,\n lossReport: options?.lossReport ?? true,\n });\n\n const result: ConvertResult = { output, warnings: ir.metadata.warnings };\n\n if (options?.debug) {\n result.debug = {\n tokens: tokenize(curlCmd.trim()),\n ast,\n ir,\n };\n }\n\n return result;\n}\n\n/**\n * Convert a shell script file → YAML (batch).\n */\nexport async function convertFileToYaml(\n filePath: string,\n options?: ConvertOptions,\n): Promise<ConvertResult> {\n const content = await Bun.file(filePath).text();\n const curlCommands = extractCurlCommands(content);\n\n if (curlCommands.length === 0) {\n return { output: '', warnings: ['No curl commands found in file'] };\n }\n\n const irs: CurlRunnerIR[] = [];\n const allWarnings: string[] = [];\n\n for (let idx = 0; idx < curlCommands.length; idx++) {\n const ast = parseCurl(curlCommands[idx]);\n const ir = normalize(ast);\n ir.name = `request_${idx + 1}`;\n irs.push(ir);\n allWarnings.push(...ir.metadata.warnings);\n }\n\n if (irs.length === 1) {\n const output = serializeToYaml(irs[0], {\n pretty: options?.pretty ?? true,\n lossReport: options?.lossReport ?? true,\n });\n const result: ConvertResult = { output, warnings: allWarnings };\n if (options?.debug) {\n result.debug = { ir: irs[0] };\n }\n return result;\n }\n\n const output = serializeBatchToYaml(irs, {\n pretty: options?.pretty ?? true,\n lossReport: options?.lossReport ?? true,\n });\n\n const result: ConvertResult = { output, warnings: allWarnings };\n if (options?.debug) {\n result.debug = { ir: irs };\n }\n return result;\n}\n\n/**\n * Convert a YAML file → curl command(s).\n */\nexport async function convertYamlToCurl(\n filePath: string,\n _options?: ConvertOptions,\n): Promise<ConvertResult> {\n const content = await Bun.file(filePath).text();\n const yaml = Bun.YAML.parse(content) as YamlFile;\n const requests: RequestConfig[] = [];\n\n if (yaml.request) {\n requests.push(yaml.request);\n }\n if (yaml.requests) {\n requests.push(...yaml.requests);\n }\n if (yaml.collection?.requests) {\n requests.push(...yaml.collection.requests);\n }\n\n if (requests.length === 0) {\n return { output: '', warnings: ['No requests found in YAML file'] };\n }\n\n const allWarnings: string[] = [];\n const curlCommands: string[] = [];\n\n for (const req of requests) {\n const ir = yamlToIR(req);\n allWarnings.push(...ir.metadata.warnings);\n curlCommands.push(generateCurlFromIR(ir));\n }\n\n const output = curlCommands.join('\\n\\n');\n\n return { output, warnings: allWarnings };\n}\n\n/**\n * Parse convert subcommand args.\n */\nexport interface ConvertArgs {\n subcommand: 'curl' | 'file' | 'yaml';\n input: string;\n options: ConvertOptions;\n}\n\nexport function parseConvertArgs(args: string[]): ConvertArgs | null {\n // args[0] is 'convert', args[1] is subcommand\n if (args.length < 3) {\n return null;\n }\n\n const sub = args[1];\n if (sub !== 'curl' && sub !== 'file' && sub !== 'yaml') {\n return null;\n }\n\n const input = args[2];\n const options: ConvertOptions = {};\n\n for (let i = 3; i < args.length; i++) {\n const arg = args[i];\n switch (arg) {\n case '--output':\n case '-o':\n options.output = args[++i];\n break;\n case '--pretty':\n options.pretty = true;\n break;\n case '--normalize':\n options.normalize = true;\n break;\n case '--loss-report':\n options.lossReport = true;\n break;\n case '--batch':\n options.batch = true;\n break;\n case '--env-detect':\n options.envDetect = true;\n break;\n case '--debug':\n options.debug = true;\n break;\n }\n }\n\n return { subcommand: sub, input, options };\n}\n",
|
|
23
|
+
"/**\n * Type-safe CLI argument parser.\n * Manual parsing to ensure compatibility with compiled Bun binaries (no external deps).\n */\n\nexport interface CLIOptions {\n // Files & Discovery\n files: string[];\n all?: boolean;\n\n // Environment\n env?: string;\n noRedact?: boolean;\n\n // Execution Mode\n execution?: 'sequential' | 'parallel';\n maxConcurrency?: number;\n continueOnError?: boolean;\n dryRun?: boolean;\n http2?: boolean;\n\n // Connection Pool\n connectionPool?: boolean;\n maxStreams?: number;\n keepaliveTime?: number;\n connectTimeout?: number;\n\n // Output\n verbose?: boolean;\n quiet?: boolean;\n output?: string;\n outputFormat?: 'json' | 'pretty' | 'raw';\n prettyLevel?: 'minimal' | 'standard' | 'detailed';\n showHeaders?: boolean;\n showBody?: boolean;\n showMetrics?: boolean;\n\n // Timeouts & Retries\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n noRetry?: boolean;\n\n // Watch Mode\n watch?: boolean;\n watchDebounce?: number;\n watchClear?: boolean;\n\n // Profile Mode\n profile?: number;\n profileWarmup?: number;\n profileConcurrency?: number;\n profileHistogram?: boolean;\n profileExport?: string;\n\n // Snapshot\n snapshot?: boolean;\n snapshotUpdate?: 'none' | 'all' | 'failing';\n snapshotDir?: string;\n snapshotCi?: boolean;\n\n // Diff\n diff?: boolean;\n diffSave?: boolean;\n diffLabel?: string;\n diffCompare?: string;\n diffDir?: string;\n diffOutput?: 'terminal' | 'json' | 'markdown';\n\n // CI Exit Codes\n strictExit?: boolean;\n failOn?: number;\n failOnPercentage?: number;\n\n // Meta\n help?: boolean;\n version?: boolean;\n}\n\n/**\n * Parses command-line arguments into typed CLIOptions.\n * Handles both long flags (--flag) and short flags (-f).\n */\nexport function parseCliArgs(args: string[]): CLIOptions {\n const options: CLIOptions = { files: [] };\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n const nextArg = args[i + 1];\n const hasNextArg = nextArg !== undefined && !nextArg.startsWith('-');\n\n if (arg.startsWith('--')) {\n i += parseLongFlag(arg.slice(2), nextArg, hasNextArg, options);\n } else if (arg.startsWith('-')) {\n i += parseShortFlags(arg.slice(1), nextArg, hasNextArg, options);\n } else {\n options.files.push(arg);\n }\n }\n\n return options;\n}\n\nfunction parseLongFlag(\n key: string,\n nextArg: string | undefined,\n hasNextArg: boolean,\n options: CLIOptions,\n): number {\n // Boolean flags (no value needed)\n switch (key) {\n case 'help':\n options.help = true;\n return 0;\n case 'version':\n options.version = true;\n return 0;\n case 'all':\n options.all = true;\n return 0;\n case 'dry-run':\n options.dryRun = true;\n return 0;\n case 'http2':\n options.http2 = true;\n return 0;\n case 'connection-pool':\n options.connectionPool = true;\n return 0;\n case 'quiet':\n options.quiet = true;\n return 0;\n case 'show-headers':\n options.showHeaders = true;\n return 0;\n case 'show-body':\n options.showBody = true;\n return 0;\n case 'show-metrics':\n options.showMetrics = true;\n return 0;\n case 'no-retry':\n options.noRetry = true;\n return 0;\n case 'watch':\n options.watch = true;\n return 0;\n case 'watch-clear':\n options.watchClear = true;\n return 0;\n case 'no-watch-clear':\n options.watchClear = false;\n return 0;\n case 'profile-histogram':\n options.profileHistogram = true;\n return 0;\n case 'snapshot':\n options.snapshot = true;\n return 0;\n case 'update-snapshots':\n options.snapshotUpdate = 'all';\n return 0;\n case 'update-failing':\n options.snapshotUpdate = 'failing';\n return 0;\n case 'ci-snapshot':\n options.snapshotCi = true;\n return 0;\n case 'diff':\n options.diff = true;\n return 0;\n case 'diff-save':\n options.diffSave = true;\n return 0;\n case 'strict-exit':\n options.strictExit = true;\n return 0;\n case 'no-redact':\n options.noRedact = true;\n return 0;\n }\n\n // Flags that require a value\n if (!hasNextArg) {\n // Handle boolean-like flags that can be used without value\n if (key === 'verbose') {\n options.verbose = true;\n return 0;\n }\n if (key === 'continue-on-error') {\n options.continueOnError = true;\n return 0;\n }\n return 0;\n }\n\n switch (key) {\n // Environment\n case 'env':\n options.env = nextArg;\n return 1;\n\n // Execution\n case 'execution':\n if (nextArg === 'sequential' || nextArg === 'parallel') {\n options.execution = nextArg;\n }\n return 1;\n case 'max-concurrent': {\n const maxConcurrent = Number.parseInt(nextArg!, 10);\n if (maxConcurrent > 0) {\n options.maxConcurrency = maxConcurrent;\n }\n return 1;\n }\n\n // Connection Pool\n case 'max-streams': {\n const maxStreams = Number.parseInt(nextArg!, 10);\n if (maxStreams > 0) {\n options.maxStreams = maxStreams;\n }\n return 1;\n }\n case 'keepalive-time':\n options.keepaliveTime = Number.parseInt(nextArg!, 10);\n return 1;\n case 'connect-timeout':\n options.connectTimeout = Number.parseInt(nextArg!, 10);\n return 1;\n\n // Output\n case 'verbose':\n options.verbose = nextArg === 'true';\n return 1;\n case 'output':\n options.output = nextArg;\n return 1;\n case 'output-format':\n if (['json', 'pretty', 'raw'].includes(nextArg!)) {\n options.outputFormat = nextArg as 'json' | 'pretty' | 'raw';\n }\n return 1;\n case 'pretty-level':\n if (['minimal', 'standard', 'detailed'].includes(nextArg!)) {\n options.prettyLevel = nextArg as 'minimal' | 'standard' | 'detailed';\n }\n return 1;\n\n // Timeouts & Retries\n case 'timeout':\n options.timeout = Number.parseInt(nextArg!, 10);\n return 1;\n case 'retries':\n options.retries = Number.parseInt(nextArg!, 10);\n return 1;\n case 'retry-delay':\n options.retryDelay = Number.parseInt(nextArg!, 10);\n return 1;\n case 'continue-on-error':\n options.continueOnError = nextArg === 'true';\n return 1;\n\n // Watch\n case 'watch-debounce':\n options.watchDebounce = Number.parseInt(nextArg!, 10);\n return 1;\n\n // Profile\n case 'profile':\n options.profile = Number.parseInt(nextArg!, 10);\n return 1;\n case 'profile-warmup':\n options.profileWarmup = Number.parseInt(nextArg!, 10);\n return 1;\n case 'profile-concurrency':\n options.profileConcurrency = Number.parseInt(nextArg!, 10);\n return 1;\n case 'profile-export':\n options.profileExport = nextArg;\n return 1;\n\n // Snapshot\n case 'snapshot-dir':\n options.snapshotDir = nextArg;\n return 1;\n\n // Diff\n case 'diff-label':\n options.diffLabel = nextArg;\n return 1;\n case 'diff-compare':\n options.diffCompare = nextArg;\n return 1;\n case 'diff-dir':\n options.diffDir = nextArg;\n return 1;\n case 'diff-output':\n if (['terminal', 'json', 'markdown'].includes(nextArg!)) {\n options.diffOutput = nextArg as 'terminal' | 'json' | 'markdown';\n }\n return 1;\n\n // CI\n case 'fail-on':\n options.failOn = Number.parseInt(nextArg!, 10);\n return 1;\n case 'fail-on-percentage': {\n const percentage = Number.parseFloat(nextArg!);\n if (percentage >= 0 && percentage <= 100) {\n options.failOnPercentage = percentage;\n }\n return 1;\n }\n\n default:\n // Unknown flag with value - skip the value\n return 1;\n }\n}\n\nfunction parseShortFlags(\n flags: string,\n nextArg: string | undefined,\n hasNextArg: boolean,\n options: CLIOptions,\n): number {\n let consumed = 0;\n\n for (const flag of flags) {\n switch (flag) {\n case 'h':\n options.help = true;\n break;\n case 'v':\n options.verbose = true;\n break;\n case 'p':\n options.execution = 'parallel';\n break;\n case 'c':\n // Continue on error - handled at resolver level\n break;\n case 'q':\n options.quiet = true;\n break;\n case 'w':\n options.watch = true;\n break;\n case 's':\n options.snapshot = true;\n break;\n case 'u':\n options.snapshotUpdate = 'all';\n break;\n case 'd':\n options.diff = true;\n break;\n case 'n':\n options.dryRun = true;\n break;\n case 'o':\n if (hasNextArg) {\n options.output = nextArg;\n consumed = 1;\n }\n break;\n case 'P':\n if (hasNextArg) {\n options.profile = Number.parseInt(nextArg!, 10);\n consumed = 1;\n }\n break;\n case 'e':\n if (hasNextArg) {\n options.env = nextArg;\n consumed = 1;\n }\n break;\n }\n }\n\n return consumed;\n}\n\nexport interface InitOptions {\n wizard?: boolean;\n url?: string;\n outputPath?: string;\n}\n\nexport interface EditOptions {\n file: string;\n outputPath?: string;\n}\n\n/**\n * Checks if the args indicate a subcommand that should bypass normal config resolution.\n */\nexport function detectSubcommand(\n args: string[],\n): 'upgrade' | 'diff-subcommand' | 'init' | 'edit' | 'validate' | 'convert' | null {\n if (args[0] === 'upgrade') {\n return 'upgrade';\n }\n if (args[0] === 'validate') {\n return 'validate';\n }\n if (args[0] === 'convert') {\n return 'convert';\n }\n if (args[0] === 'diff' && args.length >= 3) {\n return 'diff-subcommand';\n }\n if (args[0] === 'init') {\n return 'init';\n }\n if (args[0] === 'edit') {\n return 'edit';\n }\n return null;\n}\n\n/**\n * Parses init subcommand options.\n */\nexport function parseInitArgs(args: string[]): InitOptions {\n const options: InitOptions = {};\n\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n const nextArg = args[i + 1];\n\n if (arg === '--wizard' || arg === '-w') {\n options.wizard = true;\n } else if (arg === '-o' || arg === '--output') {\n if (nextArg && !nextArg.startsWith('-')) {\n options.outputPath = nextArg;\n i++;\n }\n } else if (!arg.startsWith('-') && !options.url) {\n options.url = arg;\n }\n }\n\n return options;\n}\n\n/**\n * Parses edit subcommand options.\n */\nexport function parseEditArgs(args: string[]): EditOptions {\n const options: EditOptions = { file: '' };\n\n for (let i = 1; i < args.length; i++) {\n const arg = args[i];\n const nextArg = args[i + 1];\n\n if (arg === '-o' || arg === '--output') {\n if (nextArg && !nextArg.startsWith('-')) {\n options.outputPath = nextArg;\n i++;\n }\n } else if (!arg.startsWith('-') && !options.file) {\n options.file = arg;\n }\n }\n\n return options;\n}\n\n/**\n * Checks if help or version flags are present (early exit scenarios).\n */\nexport function detectEarlyExit(options: CLIOptions): 'help' | 'version' | null {\n if (options.help) {\n return 'help';\n }\n if (options.version) {\n return 'version';\n }\n return null;\n}\n",
|
|
24
|
+
"/**\n * .env file loader with environment-specific overrides.\n * Loads .env, then .env.{environment} (if specified).\n * Variables prefixed with SECRET_ are marked for redaction.\n */\n\nimport { join } from 'node:path';\n\nexport interface EnvFileResult {\n /** All loaded variables */\n variables: Record<string, string>;\n /** Keys that should be redacted in output (SECRET_* prefix) */\n secretKeys: string[];\n}\n\n/**\n * Parses .env file content into key-value pairs.\n * Handles quotes, multiline values, and comments.\n */\nfunction parseEnvContent(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n const lines = content.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip empty lines and comments\n if (!trimmed || trimmed.startsWith('#')) {\n continue;\n }\n\n const eqIdx = trimmed.indexOf('=');\n if (eqIdx === -1) {\n continue;\n }\n\n const key = trimmed.slice(0, eqIdx).trim();\n let value = trimmed.slice(eqIdx + 1).trim();\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n // Handle escape sequences in double-quoted strings\n if (\n trimmed\n .slice(eqIdx + 1)\n .trim()\n .startsWith('\"')\n ) {\n value = value\n .replace(/\\\\n/g, '\\n')\n .replace(/\\\\r/g, '\\r')\n .replace(/\\\\t/g, '\\t')\n .replace(/\\\\\\\\/g, '\\\\');\n }\n\n if (key) {\n result[key] = value;\n }\n }\n\n return result;\n}\n\n/**\n * Loads .env file from given path.\n */\nasync function loadEnvFile(filePath: string): Promise<Record<string, string>> {\n const file = Bun.file(filePath);\n if (!(await file.exists())) {\n return {};\n }\n\n try {\n const content = await file.text();\n return parseEnvContent(content);\n } catch {\n return {};\n }\n}\n\n/**\n * Extracts secret keys (variables starting with SECRET_).\n */\nfunction extractSecretKeys(variables: Record<string, string>): string[] {\n return Object.keys(variables).filter((key) => key.startsWith('SECRET_'));\n}\n\n/**\n * Loads environment variables from .env files.\n *\n * Priority (highest to lowest):\n * 1. .env.{environment}.local (if env specified)\n * 2. .env.{environment} (if env specified)\n * 3. .env.local\n * 4. .env\n *\n * @param cwd Working directory to search for .env files\n * @param environment Optional environment name (e.g., 'production', 'staging')\n */\nexport async function loadEnvFiles(\n cwd: string = process.cwd(),\n environment?: string,\n): Promise<EnvFileResult> {\n const filesToLoad: string[] = [join(cwd, '.env'), join(cwd, '.env.local')];\n\n if (environment) {\n filesToLoad.push(join(cwd, `.env.${environment}`), join(cwd, `.env.${environment}.local`));\n }\n\n let variables: Record<string, string> = {};\n\n // Load files in order, later files override earlier ones\n for (const filePath of filesToLoad) {\n const fileVars = await loadEnvFile(filePath);\n variables = { ...variables, ...fileVars };\n }\n\n return {\n variables,\n secretKeys: extractSecretKeys(variables),\n };\n}\n\n/**\n * Gets list of .env files that exist and would be loaded.\n * Useful for logging/debugging.\n */\nexport async function getEnvFilePaths(cwd: string, environment?: string): Promise<string[]> {\n const paths = [join(cwd, '.env'), join(cwd, '.env.local')];\n\n if (environment) {\n paths.push(join(cwd, `.env.${environment}`), join(cwd, `.env.${environment}.local`));\n }\n\n const existing: string[] = [];\n for (const p of paths) {\n if (await Bun.file(p).exists()) {\n existing.push(p);\n }\n }\n return existing;\n}\n",
|
|
25
|
+
"/**\n * Environment variable loader for curl-runner configuration.\n * All CURL_RUNNER_* environment variables are processed here.\n */\n\nimport type { GlobalConfig } from '../../types/config';\n\n/**\n * Loads configuration from environment variables.\n * Environment variables are prefixed with CURL_RUNNER_.\n */\nexport function loadEnvironmentConfig(): Partial<GlobalConfig> {\n const config: Partial<GlobalConfig> = {};\n\n // Execution\n loadExecutionEnvVars(config);\n\n // Connection Pool\n loadConnectionPoolEnvVars(config);\n\n // Output\n loadOutputEnvVars(config);\n\n // CI Exit Codes\n loadCIEnvVars(config);\n\n // Watch Mode\n loadWatchEnvVars(config);\n\n // Profile Mode\n loadProfileEnvVars(config);\n\n // Snapshot\n loadSnapshotEnvVars(config);\n\n // Diff\n loadDiffEnvVars(config);\n\n // Timeouts & Retries\n loadRetryEnvVars(config);\n\n return config;\n}\n\nfunction loadExecutionEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_EXECUTION) {\n config.execution = process.env.CURL_RUNNER_EXECUTION as 'sequential' | 'parallel';\n }\n\n if (process.env.CURL_RUNNER_CONTINUE_ON_ERROR) {\n config.continueOnError = process.env.CURL_RUNNER_CONTINUE_ON_ERROR.toLowerCase() === 'true';\n }\n\n if (process.env.CURL_RUNNER_DRY_RUN) {\n config.dryRun = process.env.CURL_RUNNER_DRY_RUN.toLowerCase() === 'true';\n }\n\n if (process.env.CURL_RUNNER_HTTP2) {\n config.http2 = process.env.CURL_RUNNER_HTTP2.toLowerCase() === 'true';\n }\n\n if (process.env.CURL_RUNNER_MAX_CONCURRENCY) {\n const maxConcurrency = Number.parseInt(process.env.CURL_RUNNER_MAX_CONCURRENCY, 10);\n if (maxConcurrency > 0) {\n config.maxConcurrency = maxConcurrency;\n }\n }\n}\n\nfunction loadConnectionPoolEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_CONNECTION_POOL) {\n config.connectionPool = {\n ...config.connectionPool,\n enabled: process.env.CURL_RUNNER_CONNECTION_POOL.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_MAX_STREAMS_PER_HOST) {\n config.connectionPool = {\n ...config.connectionPool,\n maxStreamsPerHost: Number.parseInt(process.env.CURL_RUNNER_MAX_STREAMS_PER_HOST, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_KEEPALIVE_TIME) {\n config.connectionPool = {\n ...config.connectionPool,\n keepaliveTime: Number.parseInt(process.env.CURL_RUNNER_KEEPALIVE_TIME, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_CONNECT_TIMEOUT) {\n config.connectionPool = {\n ...config.connectionPool,\n connectTimeout: Number.parseInt(process.env.CURL_RUNNER_CONNECT_TIMEOUT, 10),\n };\n }\n}\n\nfunction loadOutputEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_VERBOSE) {\n config.output = {\n ...config.output,\n verbose: process.env.CURL_RUNNER_VERBOSE.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_OUTPUT_FORMAT) {\n const format = process.env.CURL_RUNNER_OUTPUT_FORMAT;\n if (['json', 'pretty', 'raw'].includes(format)) {\n config.output = { ...config.output, format: format as 'json' | 'pretty' | 'raw' };\n }\n }\n\n if (process.env.CURL_RUNNER_PRETTY_LEVEL) {\n const level = process.env.CURL_RUNNER_PRETTY_LEVEL;\n if (['minimal', 'standard', 'detailed'].includes(level)) {\n config.output = {\n ...config.output,\n prettyLevel: level as 'minimal' | 'standard' | 'detailed',\n };\n }\n }\n\n if (process.env.CURL_RUNNER_OUTPUT_FILE) {\n config.output = { ...config.output, saveToFile: process.env.CURL_RUNNER_OUTPUT_FILE };\n }\n}\n\nfunction loadCIEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_STRICT_EXIT) {\n config.ci = {\n ...config.ci,\n strictExit: process.env.CURL_RUNNER_STRICT_EXIT.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_FAIL_ON) {\n config.ci = {\n ...config.ci,\n failOn: Number.parseInt(process.env.CURL_RUNNER_FAIL_ON, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_FAIL_ON_PERCENTAGE) {\n const percentage = Number.parseFloat(process.env.CURL_RUNNER_FAIL_ON_PERCENTAGE);\n if (percentage >= 0 && percentage <= 100) {\n config.ci = {\n ...config.ci,\n failOnPercentage: percentage,\n };\n }\n }\n}\n\nfunction loadWatchEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_WATCH) {\n config.watch = {\n ...config.watch,\n enabled: process.env.CURL_RUNNER_WATCH.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_WATCH_DEBOUNCE) {\n config.watch = {\n ...config.watch,\n debounce: Number.parseInt(process.env.CURL_RUNNER_WATCH_DEBOUNCE, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_WATCH_CLEAR) {\n config.watch = {\n ...config.watch,\n clear: process.env.CURL_RUNNER_WATCH_CLEAR.toLowerCase() !== 'false',\n };\n }\n}\n\nfunction loadProfileEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_PROFILE) {\n const iterations = Number.parseInt(process.env.CURL_RUNNER_PROFILE, 10);\n if (iterations > 0) {\n config.profile = {\n ...config.profile,\n iterations,\n };\n }\n }\n\n if (process.env.CURL_RUNNER_PROFILE_WARMUP) {\n config.profile = {\n ...config.profile,\n iterations: config.profile?.iterations ?? 10,\n warmup: Number.parseInt(process.env.CURL_RUNNER_PROFILE_WARMUP, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_PROFILE_CONCURRENCY) {\n config.profile = {\n ...config.profile,\n iterations: config.profile?.iterations ?? 10,\n concurrency: Number.parseInt(process.env.CURL_RUNNER_PROFILE_CONCURRENCY, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_PROFILE_HISTOGRAM) {\n config.profile = {\n ...config.profile,\n iterations: config.profile?.iterations ?? 10,\n histogram: process.env.CURL_RUNNER_PROFILE_HISTOGRAM.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_PROFILE_EXPORT) {\n config.profile = {\n ...config.profile,\n iterations: config.profile?.iterations ?? 10,\n exportFile: process.env.CURL_RUNNER_PROFILE_EXPORT,\n };\n }\n}\n\nfunction loadSnapshotEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_SNAPSHOT) {\n config.snapshot = {\n ...config.snapshot,\n enabled: process.env.CURL_RUNNER_SNAPSHOT.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_SNAPSHOT_UPDATE) {\n const mode = process.env.CURL_RUNNER_SNAPSHOT_UPDATE.toLowerCase();\n if (['none', 'all', 'failing'].includes(mode)) {\n config.snapshot = {\n ...config.snapshot,\n updateMode: mode as 'none' | 'all' | 'failing',\n };\n }\n }\n\n if (process.env.CURL_RUNNER_SNAPSHOT_DIR) {\n config.snapshot = {\n ...config.snapshot,\n dir: process.env.CURL_RUNNER_SNAPSHOT_DIR,\n };\n }\n\n if (process.env.CURL_RUNNER_SNAPSHOT_CI) {\n config.snapshot = {\n ...config.snapshot,\n ci: process.env.CURL_RUNNER_SNAPSHOT_CI.toLowerCase() === 'true',\n };\n }\n}\n\nfunction loadDiffEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_DIFF) {\n config.diff = {\n ...config.diff,\n enabled: process.env.CURL_RUNNER_DIFF.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_DIFF_SAVE) {\n config.diff = {\n ...config.diff,\n save: process.env.CURL_RUNNER_DIFF_SAVE.toLowerCase() === 'true',\n };\n }\n\n if (process.env.CURL_RUNNER_DIFF_LABEL) {\n config.diff = {\n ...config.diff,\n label: process.env.CURL_RUNNER_DIFF_LABEL,\n };\n }\n\n if (process.env.CURL_RUNNER_DIFF_COMPARE) {\n config.diff = {\n ...config.diff,\n compareWith: process.env.CURL_RUNNER_DIFF_COMPARE,\n };\n }\n\n if (process.env.CURL_RUNNER_DIFF_DIR) {\n config.diff = {\n ...config.diff,\n dir: process.env.CURL_RUNNER_DIFF_DIR,\n };\n }\n\n if (process.env.CURL_RUNNER_DIFF_OUTPUT) {\n const format = process.env.CURL_RUNNER_DIFF_OUTPUT.toLowerCase();\n if (['terminal', 'json', 'markdown'].includes(format)) {\n config.diff = {\n ...config.diff,\n outputFormat: format as 'terminal' | 'json' | 'markdown',\n };\n }\n }\n}\n\nfunction loadRetryEnvVars(config: Partial<GlobalConfig>): void {\n if (process.env.CURL_RUNNER_TIMEOUT) {\n config.defaults = {\n ...config.defaults,\n timeout: Number.parseInt(process.env.CURL_RUNNER_TIMEOUT, 10),\n };\n }\n\n if (process.env.CURL_RUNNER_RETRIES) {\n config.defaults = {\n ...config.defaults,\n retry: {\n ...config.defaults?.retry,\n count: Number.parseInt(process.env.CURL_RUNNER_RETRIES, 10),\n },\n };\n }\n\n if (process.env.CURL_RUNNER_RETRY_DELAY) {\n config.defaults = {\n ...config.defaults,\n retry: {\n ...config.defaults?.retry,\n delay: Number.parseInt(process.env.CURL_RUNNER_RETRY_DELAY, 10),\n },\n };\n }\n}\n",
|
|
26
|
+
"/**\n * Configuration file loader for curl-runner.\n * Discovers and loads configuration from standard config file paths.\n */\n\nimport { YamlParser } from '../../parser/yaml';\nimport type { GlobalConfig } from '../../types/config';\n\n/**\n * Standard configuration file paths searched in order.\n */\nexport const CONFIG_FILE_PATHS = [\n 'curl-runner.yaml',\n 'curl-runner.yml',\n '.curl-runner.yaml',\n '.curl-runner.yml',\n] as const;\n\nexport interface ConfigFileResult {\n config: Partial<GlobalConfig>;\n path: string | null;\n}\n\n/**\n * Loads configuration from the first found config file.\n * Searches standard paths in order and returns the first valid config.\n *\n * @param logger Optional logger for info/warning messages\n * @returns Configuration object and path (or null if not found)\n */\nexport async function loadConfigFile(\n onInfo?: (msg: string) => void,\n onWarning?: (msg: string) => void,\n): Promise<ConfigFileResult> {\n for (const filename of CONFIG_FILE_PATHS) {\n try {\n const file = Bun.file(filename);\n if (await file.exists()) {\n const yamlContent = await YamlParser.parseFile(filename);\n const config = yamlContent.global || {};\n onInfo?.(`Loaded configuration from ${filename}`);\n return { config: config as Partial<GlobalConfig>, path: filename };\n }\n } catch (error) {\n onWarning?.(`Failed to load configuration from ${filename}: ${error}`);\n }\n }\n\n return { config: {}, path: null };\n}\n",
|
|
27
|
+
"/**\n * Secret redaction utility for masking sensitive values in output.\n * Replaces secret values with [REDACTED] to prevent accidental exposure.\n */\n\nconst REDACTED = '[REDACTED]';\n\n/**\n * Common secret patterns to auto-detect.\n * These match known API key formats from popular services.\n */\nconst SECRET_PATTERNS: RegExp[] = [\n // Stripe\n /sk_live_[a-zA-Z0-9]{24,}/g,\n /sk_test_[a-zA-Z0-9]{24,}/g,\n /pk_live_[a-zA-Z0-9]{24,}/g,\n /pk_test_[a-zA-Z0-9]{24,}/g,\n /rk_live_[a-zA-Z0-9]{24,}/g,\n /rk_test_[a-zA-Z0-9]{24,}/g,\n // AWS\n /AKIA[0-9A-Z]{16}/g,\n // GitHub\n /ghp_[a-zA-Z0-9]{36,}/g,\n /gho_[a-zA-Z0-9]{36,}/g,\n /ghu_[a-zA-Z0-9]{36,}/g,\n /ghs_[a-zA-Z0-9]{36,}/g,\n /ghr_[a-zA-Z0-9]{36,}/g,\n // NPM\n /npm_[a-zA-Z0-9]{36,}/g,\n // Slack\n /xox[baprs]-[a-zA-Z0-9-]{10,}/g,\n // Paddle\n /pdl_[a-zA-Z0-9]{20,}/g,\n // OpenAI\n /sk-[a-zA-Z0-9]{48,}/g,\n // Anthropic\n /sk-ant-[a-zA-Z0-9-]{40,}/g,\n // Generic Bearer tokens (long alphanumeric)\n /Bearer [a-zA-Z0-9_-]{40,}/g,\n];\n\nexport class SecretRedactor {\n private secrets: Map<string, string> = new Map();\n private sortedSecrets: string[] = [];\n private patternRedaction = true;\n\n /**\n * Registers secrets for redaction.\n * Longer secrets are matched first to handle overlapping values.\n */\n addSecrets(secrets: Record<string, string>): void {\n for (const [key, value] of Object.entries(secrets)) {\n if (value && value.length > 0) {\n this.secrets.set(key, value);\n }\n }\n this.updateSortedSecrets();\n }\n\n /**\n * Registers a single secret value.\n */\n addSecret(key: string, value: string): void {\n if (value && value.length > 0) {\n this.secrets.set(key, value);\n this.updateSortedSecrets();\n }\n }\n\n /**\n * Enable/disable pattern-based redaction.\n */\n setPatternRedaction(enabled: boolean): void {\n this.patternRedaction = enabled;\n }\n\n /**\n * Clears all registered secrets.\n */\n clear(): void {\n this.secrets.clear();\n this.sortedSecrets = [];\n }\n\n /**\n * Updates sorted secrets list (longest first for proper replacement).\n */\n private updateSortedSecrets(): void {\n this.sortedSecrets = Array.from(this.secrets.values())\n .filter((v) => v.length > 0)\n .sort((a, b) => b.length - a.length);\n }\n\n /**\n * Redacts all registered secret values from a string.\n * Also applies pattern-based redaction for common API key formats.\n */\n redact(input: string): string {\n let result = input;\n\n // First, redact explicit secrets (longest first)\n for (const secret of this.sortedSecrets) {\n result = result.split(secret).join(REDACTED);\n }\n\n // Then apply pattern-based redaction\n if (this.patternRedaction) {\n for (const pattern of SECRET_PATTERNS) {\n // Reset lastIndex for global regexes\n pattern.lastIndex = 0;\n result = result.replace(pattern, REDACTED);\n }\n }\n\n return result;\n }\n\n /**\n * Returns true if any secrets are registered.\n */\n hasSecrets(): boolean {\n return this.secrets.size > 0;\n }\n\n /**\n * Returns count of registered secrets.\n */\n get secretCount(): number {\n return this.secrets.size;\n }\n}\n\n// Global singleton for easy access\nlet globalRedactor: SecretRedactor | null = null;\n\nexport function getGlobalRedactor(): SecretRedactor {\n if (!globalRedactor) {\n globalRedactor = new SecretRedactor();\n }\n return globalRedactor;\n}\n\nexport function resetGlobalRedactor(): void {\n globalRedactor = null;\n}\n",
|
|
28
|
+
"/**\n * Configuration resolver that merges all config sources.\n * Priority order: CLI options > Environment variables > Config file > Defaults\n */\n\nimport type { GlobalConfig, ProfileConfig, WatchConfig } from '../../types/config';\nimport { getGlobalRedactor } from '../../utils/secret-redactor';\nimport { type CLIOptions, detectEarlyExit, detectSubcommand, parseCliArgs } from './cli-parser';\nimport { loadEnvFiles } from './env-file-loader';\nimport { loadEnvironmentConfig } from './env-loader';\nimport { loadConfigFile } from './file-loader';\n\nexport type ExecutionMode =\n | 'normal'\n | 'watch'\n | 'profile'\n | 'diff-subcommand'\n | 'upgrade'\n | 'init'\n | 'edit'\n | 'validate'\n | 'convert'\n | 'help'\n | 'version';\n\nexport interface ResolvedConfig {\n /** Merged global configuration */\n config: GlobalConfig;\n /** CLI options (typed) */\n cliOptions: CLIOptions;\n /** Files to process */\n files: string[];\n /** Execution mode determined from options */\n mode: ExecutionMode;\n /** Raw args for subcommand passthrough */\n rawArgs: string[];\n /** Keys marked as secrets (for redaction) */\n secretKeys: string[];\n}\n\nexport interface ResolverCallbacks {\n onInfo?: (msg: string) => void;\n onWarning?: (msg: string) => void;\n}\n\n/**\n * Resolves configuration from all sources (CLI, env, file) and determines execution mode.\n */\nexport async function resolveConfig(\n args: string[],\n callbacks?: ResolverCallbacks,\n): Promise<ResolvedConfig> {\n // Check for subcommands first (bypass normal config loading)\n const subcommand = detectSubcommand(args);\n if (subcommand === 'upgrade') {\n return {\n config: {},\n cliOptions: { files: [] },\n files: [],\n mode: 'upgrade',\n rawArgs: args,\n secretKeys: [],\n };\n }\n if (subcommand === 'init') {\n return {\n config: {},\n cliOptions: { files: [] },\n files: [],\n mode: 'init',\n rawArgs: args,\n secretKeys: [],\n };\n }\n if (subcommand === 'edit') {\n return {\n config: {},\n cliOptions: { files: [] },\n files: [],\n mode: 'edit',\n rawArgs: args,\n secretKeys: [],\n };\n }\n if (subcommand === 'validate') {\n return {\n config: {},\n cliOptions: { files: [] },\n files: [],\n mode: 'validate',\n rawArgs: args,\n secretKeys: [],\n };\n }\n if (subcommand === 'convert') {\n return {\n config: {},\n cliOptions: { files: [] },\n files: [],\n mode: 'convert',\n rawArgs: args,\n secretKeys: [],\n };\n }\n\n // Parse CLI arguments\n const cliOptions = parseCliArgs(args);\n\n // Check for early exit (help/version)\n const earlyExit = detectEarlyExit(cliOptions);\n if (earlyExit) {\n return {\n config: {},\n cliOptions,\n files: cliOptions.files,\n mode: earlyExit,\n rawArgs: args,\n secretKeys: [],\n };\n }\n\n // Handle diff subcommand\n if (subcommand === 'diff-subcommand') {\n return {\n config: {},\n cliOptions,\n files: args.slice(1), // Pass remaining args (label1, label2, optional file)\n mode: 'diff-subcommand',\n rawArgs: args,\n secretKeys: [],\n };\n }\n\n // Load config from all sources\n const envConfig = loadEnvironmentConfig();\n const { config: fileConfig } = await loadConfigFile(callbacks?.onInfo, callbacks?.onWarning);\n\n // Merge configs: file -> env -> CLI (CLI wins)\n let globalConfig = mergeGlobalConfigs(fileConfig, envConfig);\n globalConfig = applyCliOptionsToConfig(globalConfig, cliOptions);\n\n // Load .env files\n const environment = cliOptions.env ?? globalConfig.env?.environment;\n const { variables: envFileVars, secretKeys } = await loadEnvFiles(process.cwd(), environment);\n\n // Merge env file variables into global config (lower priority than explicit variables)\n globalConfig.variables = { ...envFileVars, ...globalConfig.variables };\n\n // Set up secret redaction (unless disabled)\n const redactSecrets = !cliOptions.noRedact && globalConfig.env?.redactSecrets !== false;\n if (redactSecrets && secretKeys.length > 0) {\n const redactor = getGlobalRedactor();\n const secretValues: Record<string, string> = {};\n for (const key of secretKeys) {\n if (globalConfig.variables?.[key]) {\n secretValues[key] = globalConfig.variables[key];\n }\n }\n redactor.addSecrets(secretValues);\n }\n\n // Determine execution mode\n const mode = determineExecutionMode(cliOptions, globalConfig);\n\n return {\n config: globalConfig,\n cliOptions,\n files: cliOptions.files,\n mode,\n rawArgs: args,\n secretKeys,\n };\n}\n\n/**\n * Merges two GlobalConfig objects with proper nested merging.\n */\nexport function mergeGlobalConfigs(\n base: Partial<GlobalConfig>,\n override: Partial<GlobalConfig>,\n): GlobalConfig {\n return {\n ...base,\n ...override,\n env: { ...base.env, ...override.env },\n variables: { ...base.variables, ...override.variables },\n output: { ...base.output, ...override.output },\n defaults: { ...base.defaults, ...override.defaults },\n ci: { ...base.ci, ...override.ci },\n watch: { ...base.watch, ...override.watch },\n snapshot: { ...base.snapshot, ...override.snapshot },\n diff: { ...base.diff, ...override.diff },\n connectionPool: { ...base.connectionPool, ...override.connectionPool },\n } as GlobalConfig;\n}\n\n/**\n * Applies CLI options to global config (highest priority).\n */\nfunction applyCliOptionsToConfig(config: GlobalConfig, options: CLIOptions): GlobalConfig {\n const result = { ...config };\n\n // Environment\n if (options.env) {\n result.env = { ...result.env, environment: options.env };\n }\n if (options.noRedact) {\n result.env = { ...result.env, redactSecrets: false };\n }\n\n // Execution\n if (options.execution) {\n result.execution = options.execution;\n }\n if (options.maxConcurrency !== undefined) {\n result.maxConcurrency = options.maxConcurrency;\n }\n if (options.continueOnError !== undefined) {\n result.continueOnError = options.continueOnError;\n }\n if (options.dryRun !== undefined) {\n result.dryRun = options.dryRun;\n result.output = { ...result.output, dryRun: options.dryRun };\n }\n if (options.http2 !== undefined) {\n result.http2 = options.http2;\n result.defaults = { ...result.defaults, http2: options.http2 };\n }\n\n // Connection pooling\n if (options.connectionPool !== undefined) {\n result.connectionPool = { ...result.connectionPool, enabled: options.connectionPool };\n }\n if (options.maxStreams !== undefined) {\n result.connectionPool = {\n ...result.connectionPool,\n enabled: true,\n maxStreamsPerHost: options.maxStreams,\n };\n }\n if (options.keepaliveTime !== undefined) {\n result.connectionPool = {\n ...result.connectionPool,\n enabled: true,\n keepaliveTime: options.keepaliveTime,\n };\n }\n if (options.connectTimeout !== undefined) {\n result.connectionPool = {\n ...result.connectionPool,\n enabled: true,\n connectTimeout: options.connectTimeout,\n };\n }\n\n // Output\n if (options.verbose !== undefined) {\n result.output = { ...result.output, verbose: options.verbose };\n }\n if (options.quiet) {\n result.output = { ...result.output, verbose: false };\n }\n if (options.output) {\n result.output = { ...result.output, saveToFile: options.output };\n }\n if (options.outputFormat) {\n result.output = { ...result.output, format: options.outputFormat };\n }\n if (options.prettyLevel) {\n result.output = { ...result.output, prettyLevel: options.prettyLevel };\n }\n if (options.showHeaders !== undefined) {\n result.output = { ...result.output, showHeaders: options.showHeaders };\n }\n if (options.showBody !== undefined) {\n result.output = { ...result.output, showBody: options.showBody };\n }\n if (options.showMetrics !== undefined) {\n result.output = { ...result.output, showMetrics: options.showMetrics };\n }\n\n // Timeouts & Retries\n if (options.timeout) {\n result.defaults = { ...result.defaults, timeout: options.timeout };\n }\n if (options.retries || options.noRetry) {\n const retryCount = options.noRetry ? 0 : options.retries || 0;\n result.defaults = {\n ...result.defaults,\n retry: { ...result.defaults?.retry, count: retryCount },\n };\n }\n if (options.retryDelay) {\n result.defaults = {\n ...result.defaults,\n retry: { ...result.defaults?.retry, delay: options.retryDelay },\n };\n }\n\n // CI\n if (options.strictExit !== undefined) {\n result.ci = { ...result.ci, strictExit: options.strictExit };\n }\n if (options.failOn !== undefined) {\n result.ci = { ...result.ci, failOn: options.failOn };\n }\n if (options.failOnPercentage !== undefined) {\n result.ci = { ...result.ci, failOnPercentage: options.failOnPercentage };\n }\n\n // Snapshot\n if (options.snapshot !== undefined) {\n result.snapshot = { ...result.snapshot, enabled: options.snapshot };\n }\n if (options.snapshotUpdate !== undefined) {\n result.snapshot = { ...result.snapshot, enabled: true, updateMode: options.snapshotUpdate };\n }\n if (options.snapshotDir !== undefined) {\n result.snapshot = { ...result.snapshot, dir: options.snapshotDir };\n }\n if (options.snapshotCi !== undefined) {\n result.snapshot = { ...result.snapshot, ci: options.snapshotCi };\n }\n\n // Diff\n if (options.diff !== undefined) {\n result.diff = { ...result.diff, enabled: options.diff };\n }\n if (options.diffSave !== undefined) {\n result.diff = { ...result.diff, enabled: true, save: options.diffSave };\n }\n if (options.diffLabel !== undefined) {\n result.diff = { ...result.diff, label: options.diffLabel };\n }\n if (options.diffCompare !== undefined) {\n result.diff = { ...result.diff, enabled: true, compareWith: options.diffCompare };\n }\n if (options.diffDir !== undefined) {\n result.diff = { ...result.diff, dir: options.diffDir };\n }\n if (options.diffOutput !== undefined) {\n result.diff = { ...result.diff, outputFormat: options.diffOutput };\n }\n\n return result;\n}\n\n/**\n * Determines execution mode based on CLI options and global config.\n */\nfunction determineExecutionMode(options: CLIOptions, config: GlobalConfig): ExecutionMode {\n const watchEnabled = options.watch || config.watch?.enabled;\n const profileIterations = options.profile ?? config.profile?.iterations;\n const profileEnabled = profileIterations && profileIterations > 0;\n\n if (profileEnabled) {\n return 'profile';\n }\n if (watchEnabled) {\n return 'watch';\n }\n return 'normal';\n}\n\n/**\n * Builds ProfileConfig from CLI options and global config.\n */\nexport function buildProfileConfig(options: CLIOptions, config: GlobalConfig): ProfileConfig {\n return {\n iterations: options.profile ?? config.profile?.iterations ?? 10,\n warmup: options.profileWarmup ?? config.profile?.warmup ?? 1,\n concurrency: options.profileConcurrency ?? config.profile?.concurrency ?? 1,\n histogram: options.profileHistogram ?? config.profile?.histogram ?? false,\n exportFile: options.profileExport ?? config.profile?.exportFile,\n };\n}\n\n/**\n * Builds WatchConfig from CLI options and global config.\n */\nexport function buildWatchConfig(options: CLIOptions, config: GlobalConfig): WatchConfig {\n return {\n enabled: true,\n debounce: options.watchDebounce ?? config.watch?.debounce ?? 300,\n clear: options.watchClear ?? config.watch?.clear ?? true,\n };\n}\n",
|
|
29
|
+
"import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n Baseline,\n BaselineFile,\n DiffConfig,\n ExecutionResult,\n GlobalDiffConfig,\n} from '../types/config';\n\nconst BASELINE_VERSION = 1;\nconst DEFAULT_BASELINE_DIR = '__baselines__';\n\n/**\n * Manages baseline files: reading, writing, and listing.\n */\nexport class BaselineManager {\n private baselineDir: string;\n private writeLocks: Map<string, Promise<void>> = new Map();\n\n constructor(globalConfig: GlobalDiffConfig = {}) {\n this.baselineDir = globalConfig.dir || DEFAULT_BASELINE_DIR;\n }\n\n /**\n * Gets the baseline file path for a label.\n */\n getBaselinePath(yamlPath: string, label: string): string {\n const dir = path.dirname(yamlPath);\n const basename = path.basename(yamlPath, path.extname(yamlPath));\n return path.join(dir, this.baselineDir, `${basename}.${label}.baseline.json`);\n }\n\n /**\n * Gets the baseline directory for a YAML file.\n */\n getBaselineDir(yamlPath: string): string {\n return path.join(path.dirname(yamlPath), this.baselineDir);\n }\n\n /**\n * Loads baseline file for a specific label.\n */\n async load(yamlPath: string, label: string): Promise<BaselineFile | null> {\n const baselinePath = this.getBaselinePath(yamlPath, label);\n try {\n const file = Bun.file(baselinePath);\n if (!(await file.exists())) {\n return null;\n }\n const content = await file.text();\n return JSON.parse(content) as BaselineFile;\n } catch {\n return null;\n }\n }\n\n /**\n * Saves baseline file with write queue for parallel safety.\n */\n async save(yamlPath: string, label: string, data: BaselineFile): Promise<void> {\n const baselinePath = this.getBaselinePath(yamlPath, label);\n\n const existingLock = this.writeLocks.get(baselinePath);\n const writePromise = (async () => {\n if (existingLock) {\n await existingLock;\n }\n\n const dir = path.dirname(baselinePath);\n await fs.mkdir(dir, { recursive: true });\n\n const content = JSON.stringify(data, null, 2);\n await Bun.write(baselinePath, content);\n })();\n\n this.writeLocks.set(baselinePath, writePromise);\n await writePromise;\n this.writeLocks.delete(baselinePath);\n }\n\n /**\n * Gets a single baseline by request name.\n */\n async get(yamlPath: string, label: string, requestName: string): Promise<Baseline | null> {\n const file = await this.load(yamlPath, label);\n return file?.baselines[requestName] || null;\n }\n\n /**\n * Lists all available baseline labels for a YAML file.\n */\n async listLabels(yamlPath: string): Promise<string[]> {\n const dir = this.getBaselineDir(yamlPath);\n const basename = path.basename(yamlPath, path.extname(yamlPath));\n\n try {\n const files = await fs.readdir(dir);\n const labels: string[] = [];\n\n for (const file of files) {\n const match = file.match(new RegExp(`^${basename}\\\\.(.+)\\\\.baseline\\\\.json$`));\n if (match) {\n labels.push(match[1]);\n }\n }\n\n return labels.sort();\n } catch {\n return [];\n }\n }\n\n /**\n * Creates a baseline from execution result.\n */\n createBaseline(result: ExecutionResult, config: DiffConfig): Baseline {\n const baseline: Baseline = {\n hash: '',\n capturedAt: new Date().toISOString(),\n };\n\n if (result.status !== undefined) {\n baseline.status = result.status;\n }\n\n if (result.headers) {\n baseline.headers = this.normalizeHeaders(result.headers);\n }\n\n if (result.body !== undefined) {\n baseline.body = result.body;\n }\n\n if (config.includeTimings && result.metrics?.duration !== undefined) {\n baseline.timing = result.metrics.duration;\n }\n\n baseline.hash = this.hash(baseline);\n\n return baseline;\n }\n\n /**\n * Normalizes headers for consistent comparison.\n */\n private normalizeHeaders(headers: Record<string, string>): Record<string, string> {\n const normalized: Record<string, string> = {};\n const sortedKeys = Object.keys(headers).sort();\n for (const key of sortedKeys) {\n normalized[key.toLowerCase()] = headers[key];\n }\n return normalized;\n }\n\n /**\n * Generates a hash for baseline content.\n */\n hash(content: unknown): string {\n const str = JSON.stringify(content);\n const hasher = new Bun.CryptoHasher('md5');\n hasher.update(str);\n return hasher.digest('hex').slice(0, 8);\n }\n\n /**\n * Saves execution results as a baseline.\n */\n async saveBaseline(\n yamlPath: string,\n label: string,\n results: ExecutionResult[],\n config: DiffConfig,\n ): Promise<void> {\n const baselines: Record<string, Baseline> = {};\n\n for (const result of results) {\n if (result.skipped || !result.success) {\n continue;\n }\n const name = result.request.name || result.request.url;\n baselines[name] = this.createBaseline(result, config);\n }\n\n const file: BaselineFile = {\n version: BASELINE_VERSION,\n label,\n capturedAt: new Date().toISOString(),\n baselines,\n };\n\n await this.save(yamlPath, label, file);\n }\n\n /**\n * Deletes baselines older than specified days.\n */\n async cleanOldBaselines(yamlPath: string, olderThanDays: number): Promise<number> {\n const dir = this.getBaselineDir(yamlPath);\n const cutoff = Date.now() - olderThanDays * 24 * 60 * 60 * 1000;\n let deleted = 0;\n\n try {\n const files = await fs.readdir(dir);\n\n for (const file of files) {\n if (!file.endsWith('.baseline.json')) {\n continue;\n }\n\n const filePath = path.join(dir, file);\n const stat = await fs.stat(filePath);\n\n if (stat.mtimeMs < cutoff) {\n await fs.unlink(filePath);\n deleted++;\n }\n }\n } catch {\n // Directory doesn't exist or other error\n }\n\n return deleted;\n }\n\n /**\n * Merges request-level config with global config.\n */\n static mergeConfig(\n globalConfig: GlobalDiffConfig | undefined,\n requestConfig: DiffConfig | boolean | undefined,\n ): DiffConfig | null {\n if (!requestConfig && !globalConfig?.enabled) {\n return null;\n }\n\n if (requestConfig === true) {\n return {\n enabled: true,\n exclude: globalConfig?.exclude || [],\n match: globalConfig?.match || {},\n includeTimings: globalConfig?.includeTimings || false,\n };\n }\n\n if (typeof requestConfig === 'object' && requestConfig.enabled !== false) {\n return {\n enabled: true,\n exclude: [...(globalConfig?.exclude || []), ...(requestConfig.exclude || [])],\n match: { ...(globalConfig?.match || {}), ...(requestConfig.match || {}) },\n includeTimings: requestConfig.includeTimings ?? globalConfig?.includeTimings ?? false,\n };\n }\n\n if (globalConfig?.enabled && requestConfig === undefined) {\n return {\n enabled: true,\n exclude: globalConfig.exclude || [],\n match: globalConfig.match || {},\n includeTimings: globalConfig.includeTimings || false,\n };\n }\n\n return null;\n }\n}\n",
|
|
30
|
+
"/**\n * Output formatting utilities.\n */\n\nimport type { AnsiColors, ColorName } from './types';\n\n/**\n * ANSI color codes for terminal output.\n */\nexport const ANSI_COLORS: AnsiColors = {\n reset: '\\x1b[0m',\n bright: '\\x1b[1m',\n dim: '\\x1b[2m',\n underscore: '\\x1b[4m',\n black: '\\x1b[30m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n bgBlack: '\\x1b[40m',\n bgRed: '\\x1b[41m',\n bgGreen: '\\x1b[42m',\n bgYellow: '\\x1b[43m',\n bgBlue: '\\x1b[44m',\n bgMagenta: '\\x1b[45m',\n bgCyan: '\\x1b[46m',\n bgWhite: '\\x1b[47m',\n};\n\n/**\n * Wraps text with ANSI color codes.\n */\nexport function colorize(text: string, color: ColorName): string {\n return `${ANSI_COLORS[color]}${text}${ANSI_COLORS.reset}`;\n}\n\n/**\n * Formats duration in milliseconds to human-readable string.\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms.toFixed(0)}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Formats latency with microsecond precision.\n */\nexport function formatLatency(ms: number): string {\n if (ms < 1) {\n return `${(ms * 1000).toFixed(0)}µs`;\n }\n if (ms < 1000) {\n return `${ms.toFixed(1)}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Formats byte size to human-readable string.\n */\nexport function formatSize(bytes: number | undefined): string {\n if (!bytes) {\n return '0 B';\n }\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return `${(bytes / 1024 ** i).toFixed(2)} ${sizes[i]}`;\n}\n\n/**\n * Formats JSON data based on format type.\n */\nexport function formatJson(data: unknown, format: 'raw' | 'json' | 'pretty' = 'pretty'): string {\n if (format === 'raw') {\n return typeof data === 'string' ? data : JSON.stringify(data);\n }\n if (format === 'json') {\n return JSON.stringify(data);\n }\n return JSON.stringify(data, null, 2);\n}\n\n/**\n * Truncates a string to max length with ellipsis.\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) {\n return str;\n }\n return `${str.slice(0, maxLength - 3)}...`;\n}\n\n/**\n * Extracts short filename from path.\n */\nexport function getShortFilename(filePath: string): string {\n return filePath.replace(/.*\\//, '').replace('.yaml', '');\n}\n\n/**\n * Formats a percentage value.\n */\nexport function formatPercent(value: number, decimals: number = 1): string {\n return `${(value * 100).toFixed(decimals)}%`;\n}\n\n/**\n * Pads string to fixed width.\n */\nexport function padStart(str: string, width: number): string {\n return str.padStart(width);\n}\n\n/**\n * Pads string to fixed width (end).\n */\nexport function padEnd(str: string, width: number): string {\n return str.padEnd(width);\n}\n\n/**\n * Creates a repeated character line.\n */\nexport function repeatChar(char: string, count: number): string {\n return char.repeat(count);\n}\n",
|
|
31
|
+
"/**\n * Tree-style console output renderer.\n */\n\nimport { ANSI_COLORS, colorize } from './formatters';\nimport type { ColorName } from './types';\n\nexport interface TreeNode {\n label: string;\n value?: string;\n children?: TreeNode[];\n color?: string;\n}\n\n/**\n * Renders tree-structured output to console.\n */\nexport class TreeRenderer {\n private color(text: string, colorName: string): string {\n if (!colorName || !(colorName in ANSI_COLORS)) {\n return text;\n }\n return colorize(text, colorName as ColorName);\n }\n\n render(nodes: TreeNode[], basePrefix: string = ' '): void {\n nodes.forEach((node, index) => {\n const isLast = index === nodes.length - 1;\n const prefix = isLast ? `${basePrefix}└─` : `${basePrefix}├─`;\n\n if (node.label && node.value) {\n // Regular labeled node with value\n const displayValue = node.color ? this.color(node.value, node.color) : node.value;\n\n // Handle multiline values (like Response Body)\n const lines = displayValue.split('\\n');\n if (lines.length === 1) {\n console.log(`${prefix} ${node.label}: ${displayValue}`);\n } else {\n console.log(`${prefix} ${node.label}:`);\n const contentPrefix = isLast ? `${basePrefix} ` : `${basePrefix}│ `;\n for (const line of lines) {\n console.log(`${contentPrefix}${line}`);\n }\n }\n } else if (node.label && !node.value) {\n // Section header (like \"Headers:\" or \"Metrics:\")\n console.log(`${prefix} ${node.label}:`);\n } else if (!node.label && node.value) {\n // Content line without label (like response body lines)\n const continuationPrefix = isLast ? `${basePrefix} ` : `${basePrefix}│ `;\n console.log(`${continuationPrefix}${node.value}`);\n }\n\n if (node.children && node.children.length > 0) {\n const childPrefix = isLast ? `${basePrefix} ` : `${basePrefix}│ `;\n this.render(node.children, childPrefix);\n }\n });\n }\n}\n",
|
|
32
|
+
"import type { ColorName } from '../core/format';\nimport { colorize } from '../core/format';\nimport type { DiffCompareResult, DiffSummary, ResponseDiff } from '../types/config';\n\n/**\n * Formats diff comparison results for various outputs.\n */\nexport class DiffFormatter {\n private outputFormat: 'terminal' | 'json' | 'markdown';\n\n constructor(outputFormat: 'terminal' | 'json' | 'markdown' = 'terminal') {\n this.outputFormat = outputFormat;\n }\n\n private color(text: string, color: ColorName): string {\n if (this.outputFormat !== 'terminal') {\n return text;\n }\n return colorize(text, color);\n }\n\n /**\n * Formats the complete diff summary.\n */\n formatSummary(summary: DiffSummary, baselineLabel: string, currentLabel: string): string {\n switch (this.outputFormat) {\n case 'json':\n return this.formatSummaryJson(summary);\n case 'markdown':\n return this.formatSummaryMarkdown(summary, baselineLabel, currentLabel);\n default:\n return this.formatSummaryTerminal(summary, baselineLabel, currentLabel);\n }\n }\n\n /**\n * Terminal format for summary.\n */\n private formatSummaryTerminal(\n summary: DiffSummary,\n baselineLabel: string,\n currentLabel: string,\n ): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push(\n `${this.color('Response Diff:', 'bright')} ${this.color(baselineLabel, 'cyan')} → ${this.color(currentLabel, 'cyan')}`,\n );\n lines.push('');\n\n for (const result of summary.results) {\n lines.push(this.formatResultTerminal(result));\n lines.push('');\n }\n\n lines.push(this.formatStatsSummary(summary));\n\n return lines.join('\\n');\n }\n\n /**\n * JSON format for summary.\n */\n private formatSummaryJson(summary: DiffSummary): string {\n return JSON.stringify(\n {\n summary: {\n total: summary.totalRequests,\n unchanged: summary.unchanged,\n changed: summary.changed,\n newBaselines: summary.newBaselines,\n },\n results: summary.results.map((r) => ({\n request: r.requestName,\n status: r.hasDifferences ? 'changed' : r.isNewBaseline ? 'new' : 'unchanged',\n differences: r.differences,\n timingDiff: r.timingDiff,\n })),\n },\n null,\n 2,\n );\n }\n\n /**\n * Markdown format for summary.\n */\n private formatSummaryMarkdown(\n summary: DiffSummary,\n baselineLabel: string,\n currentLabel: string,\n ): string {\n const lines: string[] = [];\n\n lines.push(`# Response Diff: ${baselineLabel} → ${currentLabel}`);\n lines.push('');\n lines.push(`| Metric | Count |`);\n lines.push(`|--------|-------|`);\n lines.push(`| Total Requests | ${summary.totalRequests} |`);\n lines.push(`| Unchanged | ${summary.unchanged} |`);\n lines.push(`| Changed | ${summary.changed} |`);\n lines.push(`| New Baselines | ${summary.newBaselines} |`);\n lines.push('');\n\n if (summary.changed > 0) {\n lines.push('## Changes');\n lines.push('');\n\n for (const result of summary.results) {\n if (result.hasDifferences) {\n lines.push(this.formatResultMarkdown(result));\n }\n }\n }\n\n if (summary.newBaselines > 0) {\n lines.push('## New Requests');\n lines.push('');\n for (const result of summary.results) {\n if (result.isNewBaseline) {\n lines.push(`- \\`${result.requestName}\\``);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Formats a single result for terminal.\n */\n formatResultTerminal(result: DiffCompareResult): string {\n const lines: string[] = [];\n\n if (result.isNewBaseline) {\n lines.push(` ${this.color('NEW', 'cyan')} ${this.color(result.requestName, 'bright')}`);\n return lines.join('\\n');\n }\n\n if (!result.hasDifferences) {\n lines.push(\n ` ${this.color('✓', 'green')} ${this.color(result.requestName, 'bright')} ${this.color('(no changes)', 'dim')}`,\n );\n return lines.join('\\n');\n }\n\n lines.push(` ${this.color('✗', 'red')} ${this.color(result.requestName, 'bright')}`);\n\n for (const diff of result.differences) {\n lines.push(this.formatDifferenceTerminal(diff));\n }\n\n if (result.timingDiff) {\n const { baseline, current, changePercent } = result.timingDiff;\n const sign = changePercent >= 0 ? '+' : '';\n const color = changePercent > 20 ? 'red' : changePercent < -20 ? 'green' : 'yellow';\n lines.push(\n ` ${this.color('timing:', 'cyan')} ${baseline}ms → ${current}ms ${this.color(`(${sign}${changePercent.toFixed(0)}%)`, color)}`,\n );\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Formats a single difference for terminal.\n */\n private formatDifferenceTerminal(diff: ResponseDiff): string {\n const lines: string[] = [];\n const path = diff.path || '(root)';\n\n switch (diff.type) {\n case 'added':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`+ ${this.stringify(diff.current)}`, 'green')}`);\n break;\n\n case 'removed':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`- ${this.stringify(diff.baseline)}`, 'red')}`);\n break;\n\n case 'changed':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`- ${this.stringify(diff.baseline)}`, 'red')}`);\n lines.push(` ${this.color(`+ ${this.stringify(diff.current)}`, 'green')}`);\n break;\n\n case 'type_mismatch':\n lines.push(` ${this.color(path, 'cyan')} (type mismatch):`);\n lines.push(\n ` ${this.color(`- ${this.stringify(diff.baseline)} (${typeof diff.baseline})`, 'red')}`,\n );\n lines.push(\n ` ${this.color(`+ ${this.stringify(diff.current)} (${typeof diff.current})`, 'green')}`,\n );\n break;\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Formats a single result for markdown.\n */\n private formatResultMarkdown(result: DiffCompareResult): string {\n const lines: string[] = [];\n\n lines.push(`### \\`${result.requestName}\\``);\n lines.push('');\n lines.push('```diff');\n\n for (const diff of result.differences) {\n lines.push(this.formatDifferenceMarkdown(diff));\n }\n\n lines.push('```');\n\n if (result.timingDiff) {\n const { baseline, current, changePercent } = result.timingDiff;\n const sign = changePercent >= 0 ? '+' : '';\n lines.push('');\n lines.push(`**Timing:** ${baseline}ms → ${current}ms (${sign}${changePercent.toFixed(0)}%)`);\n }\n\n lines.push('');\n\n return lines.join('\\n');\n }\n\n /**\n * Formats a single difference for markdown.\n */\n private formatDifferenceMarkdown(diff: ResponseDiff): string {\n const lines: string[] = [];\n const path = diff.path || '(root)';\n\n switch (diff.type) {\n case 'added':\n lines.push(`# ${path}:`);\n lines.push(`+ ${this.stringify(diff.current)}`);\n break;\n\n case 'removed':\n lines.push(`# ${path}:`);\n lines.push(`- ${this.stringify(diff.baseline)}`);\n break;\n\n case 'changed':\n lines.push(`# ${path}:`);\n lines.push(`- ${this.stringify(diff.baseline)}`);\n lines.push(`+ ${this.stringify(diff.current)}`);\n break;\n\n case 'type_mismatch':\n lines.push(`# ${path} (type mismatch):`);\n lines.push(`- ${this.stringify(diff.baseline)} (${typeof diff.baseline})`);\n lines.push(`+ ${this.stringify(diff.current)} (${typeof diff.current})`);\n break;\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Formats stats summary for terminal.\n */\n private formatStatsSummary(summary: DiffSummary): string {\n const parts: string[] = [];\n\n if (summary.unchanged > 0) {\n parts.push(this.color(`${summary.unchanged} unchanged`, 'green'));\n }\n if (summary.changed > 0) {\n parts.push(this.color(`${summary.changed} changed`, 'red'));\n }\n if (summary.newBaselines > 0) {\n parts.push(this.color(`${summary.newBaselines} new`, 'cyan'));\n }\n\n return `Summary: ${parts.join(', ')} (${summary.totalRequests} total)`;\n }\n\n /**\n * Converts value to display string.\n */\n private stringify(value: unknown): string {\n if (value === undefined) {\n return 'undefined';\n }\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'string') {\n return `\"${value}\"`;\n }\n if (typeof value === 'object') {\n const str = JSON.stringify(value);\n if (str.length > 80) {\n return `${str.slice(0, 77)}...`;\n }\n return str;\n }\n return String(value);\n }\n}\n",
|
|
33
|
+
"import type {\n Baseline,\n DiffCompareResult,\n DiffConfig,\n DiffSummary,\n ExecutionResult,\n GlobalDiffConfig,\n JsonValue,\n ResponseDiff,\n} from '../types/config';\nimport { BaselineManager } from './baseline-manager';\n\n/**\n * Compares responses against baselines with support for exclusions and match rules.\n */\nexport class ResponseDiffer {\n private excludePaths: Set<string>;\n private matchRules: Map<string, string>;\n private includeTimings: boolean;\n\n constructor(config: DiffConfig) {\n this.excludePaths = new Set(config.exclude || []);\n this.matchRules = new Map(Object.entries(config.match || {}));\n this.includeTimings = config.includeTimings || false;\n }\n\n /**\n * Compares current response against baseline.\n */\n compare(\n baseline: Baseline,\n current: Baseline,\n baselineLabel: string,\n currentLabel: string,\n requestName: string,\n ): DiffCompareResult {\n const differences: ResponseDiff[] = [];\n\n // Compare status\n if (baseline.status !== undefined || current.status !== undefined) {\n if (baseline.status !== current.status && !this.isExcluded('status')) {\n differences.push({\n path: 'status',\n baseline: baseline.status,\n current: current.status,\n type: 'changed',\n });\n }\n }\n\n // Compare headers\n if (baseline.headers || current.headers) {\n const headerDiffs = this.compareObjects(\n baseline.headers || {},\n current.headers || {},\n 'headers',\n );\n differences.push(...headerDiffs);\n }\n\n // Compare body\n if (baseline.body !== undefined || current.body !== undefined) {\n const bodyDiffs = this.deepCompare(baseline.body, current.body, 'body');\n differences.push(...bodyDiffs);\n }\n\n const result: DiffCompareResult = {\n requestName,\n hasDifferences: differences.length > 0,\n isNewBaseline: false,\n baselineLabel,\n currentLabel,\n differences,\n };\n\n // Add timing diff if enabled\n if (this.includeTimings && baseline.timing !== undefined && current.timing !== undefined) {\n const changePercent = ((current.timing - baseline.timing) / baseline.timing) * 100;\n result.timingDiff = {\n baseline: baseline.timing,\n current: current.timing,\n changePercent,\n };\n }\n\n return result;\n }\n\n /**\n * Deep comparison of two values with path tracking.\n */\n deepCompare(baseline: unknown, current: unknown, path: string): ResponseDiff[] {\n if (this.isExcluded(path)) {\n return [];\n }\n\n if (this.matchesRule(path, current)) {\n return [];\n }\n\n if (baseline === null && current === null) {\n return [];\n }\n if (baseline === undefined && current === undefined) {\n return [];\n }\n\n const baselineType = this.getType(baseline);\n const currentType = this.getType(current);\n\n if (baselineType !== currentType) {\n return [\n {\n path,\n baseline,\n current,\n type: 'type_mismatch',\n },\n ];\n }\n\n if (baselineType !== 'object' && baselineType !== 'array') {\n if (baseline !== current) {\n return [\n {\n path,\n baseline,\n current,\n type: 'changed',\n },\n ];\n }\n return [];\n }\n\n if (baselineType === 'array') {\n return this.compareArrays(baseline as JsonValue[], current as JsonValue[], path);\n }\n\n return this.compareObjects(\n baseline as Record<string, unknown>,\n current as Record<string, unknown>,\n path,\n );\n }\n\n /**\n * Compares two arrays.\n */\n private compareArrays(baseline: JsonValue[], current: JsonValue[], path: string): ResponseDiff[] {\n const differences: ResponseDiff[] = [];\n const maxLen = Math.max(baseline.length, current.length);\n\n for (let i = 0; i < maxLen; i++) {\n const itemPath = `${path}[${i}]`;\n\n if (i >= baseline.length) {\n if (!this.isExcluded(itemPath)) {\n differences.push({\n path: itemPath,\n baseline: undefined,\n current: current[i],\n type: 'added',\n });\n }\n } else if (i >= current.length) {\n if (!this.isExcluded(itemPath)) {\n differences.push({\n path: itemPath,\n baseline: baseline[i],\n current: undefined,\n type: 'removed',\n });\n }\n } else {\n const itemDiffs = this.deepCompare(baseline[i], current[i], itemPath);\n differences.push(...itemDiffs);\n }\n }\n\n return differences;\n }\n\n /**\n * Compares two objects.\n */\n private compareObjects(\n baseline: Record<string, unknown>,\n current: Record<string, unknown>,\n path: string,\n ): ResponseDiff[] {\n const differences: ResponseDiff[] = [];\n const allKeys = new Set([...Object.keys(baseline), ...Object.keys(current)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n const hasBaseline = key in baseline;\n const hasCurrent = key in current;\n\n if (!hasBaseline && hasCurrent) {\n if (!this.isExcluded(keyPath)) {\n differences.push({\n path: keyPath,\n baseline: undefined,\n current: current[key],\n type: 'added',\n });\n }\n } else if (hasBaseline && !hasCurrent) {\n if (!this.isExcluded(keyPath)) {\n differences.push({\n path: keyPath,\n baseline: baseline[key],\n current: undefined,\n type: 'removed',\n });\n }\n } else {\n const keyDiffs = this.deepCompare(baseline[key], current[key], keyPath);\n differences.push(...keyDiffs);\n }\n }\n\n return differences;\n }\n\n /**\n * Checks if a path should be excluded from comparison.\n */\n isExcluded(path: string): boolean {\n if (this.excludePaths.has(path)) {\n return true;\n }\n\n for (const pattern of this.excludePaths) {\n if (pattern.startsWith('*.')) {\n const suffix = pattern.slice(2);\n if (path.endsWith(`.${suffix}`)) {\n return true;\n }\n const lastPart = path.split('.').pop();\n if (lastPart === suffix) {\n return true;\n }\n }\n\n if (pattern.includes('[*]')) {\n const regex = new RegExp(\n `^${pattern.replace(/\\[\\*\\]/g, '\\\\[\\\\d+\\\\]').replace(/\\./g, '\\\\.')}$`,\n );\n if (regex.test(path)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Checks if a value matches a custom rule for its path.\n */\n matchesRule(path: string, value: unknown): boolean {\n const rule = this.matchRules.get(path);\n if (!rule) {\n return false;\n }\n\n if (rule === '*') {\n return true;\n }\n\n if (rule.startsWith('regex:')) {\n const pattern = rule.slice(6);\n try {\n const regex = new RegExp(pattern);\n return regex.test(String(value));\n } catch {\n return false;\n }\n }\n\n return false;\n }\n\n /**\n * Gets the type of a value for comparison.\n */\n private getType(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n return typeof value;\n }\n}\n\n/**\n * Orchestrates response diffing between runs.\n */\nexport class DiffOrchestrator {\n private manager: BaselineManager;\n\n constructor(globalConfig: GlobalDiffConfig = {}) {\n this.manager = new BaselineManager(globalConfig);\n }\n\n /**\n * Compares execution results against a baseline.\n */\n async compareWithBaseline(\n yamlPath: string,\n results: ExecutionResult[],\n currentLabel: string,\n baselineLabel: string,\n config: DiffConfig,\n ): Promise<DiffSummary> {\n const baselineFile = await this.manager.load(yamlPath, baselineLabel);\n const diffResults: DiffCompareResult[] = [];\n\n for (const result of results) {\n if (result.skipped || !result.success) {\n continue;\n }\n\n const requestName = result.request.name || result.request.url;\n const currentBaseline = this.manager.createBaseline(result, config);\n\n if (!baselineFile) {\n // No baseline exists - mark as new\n diffResults.push({\n requestName,\n hasDifferences: false,\n isNewBaseline: true,\n baselineLabel,\n currentLabel,\n differences: [],\n });\n continue;\n }\n\n const storedBaseline = baselineFile.baselines[requestName];\n\n if (!storedBaseline) {\n // Request not in baseline - mark as new\n diffResults.push({\n requestName,\n hasDifferences: false,\n isNewBaseline: true,\n baselineLabel,\n currentLabel,\n differences: [],\n });\n continue;\n }\n\n const differ = new ResponseDiffer(config);\n const compareResult = differ.compare(\n storedBaseline,\n currentBaseline,\n baselineLabel,\n currentLabel,\n requestName,\n );\n diffResults.push(compareResult);\n }\n\n return {\n totalRequests: diffResults.length,\n unchanged: diffResults.filter((r) => !r.hasDifferences && !r.isNewBaseline).length,\n changed: diffResults.filter((r) => r.hasDifferences).length,\n newBaselines: diffResults.filter((r) => r.isNewBaseline).length,\n results: diffResults,\n };\n }\n\n /**\n * Compares two stored baselines (offline comparison).\n */\n async compareTwoBaselines(\n yamlPath: string,\n label1: string,\n label2: string,\n config: DiffConfig,\n ): Promise<DiffSummary> {\n const file1 = await this.manager.load(yamlPath, label1);\n const file2 = await this.manager.load(yamlPath, label2);\n\n if (!file1) {\n throw new Error(`Baseline '${label1}' not found`);\n }\n if (!file2) {\n throw new Error(`Baseline '${label2}' not found`);\n }\n\n const allRequestNames = new Set([\n ...Object.keys(file1.baselines),\n ...Object.keys(file2.baselines),\n ]);\n\n const diffResults: DiffCompareResult[] = [];\n const differ = new ResponseDiffer(config);\n\n for (const requestName of allRequestNames) {\n const baseline1 = file1.baselines[requestName];\n const baseline2 = file2.baselines[requestName];\n\n if (!baseline1) {\n diffResults.push({\n requestName,\n hasDifferences: true,\n isNewBaseline: false,\n baselineLabel: label1,\n currentLabel: label2,\n differences: [\n {\n path: '',\n baseline: undefined,\n current: 'exists',\n type: 'added',\n },\n ],\n });\n continue;\n }\n\n if (!baseline2) {\n diffResults.push({\n requestName,\n hasDifferences: true,\n isNewBaseline: false,\n baselineLabel: label1,\n currentLabel: label2,\n differences: [\n {\n path: '',\n baseline: 'exists',\n current: undefined,\n type: 'removed',\n },\n ],\n });\n continue;\n }\n\n const compareResult = differ.compare(baseline1, baseline2, label1, label2, requestName);\n diffResults.push(compareResult);\n }\n\n return {\n totalRequests: diffResults.length,\n unchanged: diffResults.filter((r) => !r.hasDifferences).length,\n changed: diffResults.filter((r) => r.hasDifferences).length,\n newBaselines: 0,\n results: diffResults,\n };\n }\n\n /**\n * Saves current results as baseline.\n */\n async saveBaseline(\n yamlPath: string,\n label: string,\n results: ExecutionResult[],\n config: DiffConfig,\n ): Promise<void> {\n await this.manager.saveBaseline(yamlPath, label, results, config);\n }\n\n /**\n * Lists available baseline labels.\n */\n async listLabels(yamlPath: string): Promise<string[]> {\n return this.manager.listLabels(yamlPath);\n }\n\n /**\n * Gets the baseline manager instance.\n */\n getManager(): BaselineManager {\n return this.manager;\n }\n}\n",
|
|
34
|
+
"/**\n * Shared types for curl command building and response parsing.\n */\n\nimport type { FileAttachment, FormFieldValue } from '../../types/config';\n\n/**\n * Raw metrics returned by curl's JSON write-out format.\n */\nexport interface CurlMetrics {\n response_code?: number;\n http_code?: number;\n time_total?: number;\n size_download?: number;\n time_namelookup?: number;\n time_connect?: number;\n time_appconnect?: number;\n time_starttransfer?: number;\n}\n\n/**\n * Processed metrics with human-friendly naming (in milliseconds).\n */\nexport interface ProcessedMetrics {\n duration: number;\n size?: number;\n dnsLookup?: number;\n tcpConnection?: number;\n tlsHandshake?: number;\n firstByte?: number;\n download?: number;\n}\n\n/**\n * Options for building curl arguments.\n */\nexport interface CurlArgsOptions {\n /** Custom write-out format marker (for batching) */\n writeOutMarker?: string;\n /** Whether to include -s -S flags */\n includeSilentFlags?: boolean;\n /** Whether to include HTTP/2 flag from config */\n includeHttp2Flag?: boolean;\n /** Whether to include output file flag */\n includeOutputFlag?: boolean;\n}\n\n/**\n * Result of building curl arguments.\n */\nexport interface CurlArgsResult {\n args: string[];\n url: string;\n}\n\n/**\n * Result of executing curl.\n */\nexport interface CurlExecutionResult {\n success: boolean;\n status?: number;\n headers?: Record<string, string>;\n body?: string;\n metrics?: ProcessedMetrics;\n error?: string;\n}\n\n/**\n * Type guard to check if a form field value is a file attachment.\n */\nexport function isFileAttachment(value: FormFieldValue): value is FileAttachment {\n return typeof value === 'object' && value !== null && 'file' in value;\n}\n",
|
|
35
|
+
"/**\n * Shared curl argument building logic.\n * Used by both CurlBuilder (single requests) and PooledCurlExecutor (batched requests).\n */\n\nimport type { RequestConfig } from '../../types/config';\nimport { type CurlArgsOptions, type CurlArgsResult, isFileAttachment } from './types';\n\nconst DEFAULT_WRITE_OUT = '\\n__CURL_METRICS_START__%{json}__CURL_METRICS_END__';\n\n/**\n * Builds curl command-line arguments from a request config.\n * This is the core shared logic used by all curl execution paths.\n */\nexport function buildCurlArgs(\n config: RequestConfig,\n options: CurlArgsOptions = {},\n): CurlArgsResult {\n const {\n writeOutMarker = DEFAULT_WRITE_OUT,\n includeSilentFlags = true,\n includeHttp2Flag = true,\n includeOutputFlag = true,\n } = options;\n\n const args: string[] = [];\n\n // HTTP method\n args.push('-X', config.method || 'GET');\n\n // Write-out format for metrics\n args.push('-w', writeOutMarker);\n\n // Headers\n if (config.headers) {\n for (const [key, value] of Object.entries(config.headers)) {\n args.push('-H', `${key}: ${value}`);\n }\n }\n\n // Authentication\n if (config.auth) {\n if (config.auth.type === 'basic' && config.auth.username && config.auth.password) {\n args.push('-u', `${config.auth.username}:${config.auth.password}`);\n } else if (config.auth.type === 'bearer' && config.auth.token) {\n args.push('-H', `Authorization: Bearer ${config.auth.token}`);\n }\n }\n\n // Body or form data\n if (config.formData) {\n for (const [fieldName, fieldValue] of Object.entries(config.formData)) {\n if (isFileAttachment(fieldValue)) {\n // File attachment: -F \"field=@filepath;filename=name;type=mimetype\"\n let fileSpec = `@${fieldValue.file}`;\n if (fieldValue.filename) {\n fileSpec += `;filename=${fieldValue.filename}`;\n }\n if (fieldValue.contentType) {\n fileSpec += `;type=${fieldValue.contentType}`;\n }\n args.push('-F', `${fieldName}=${fileSpec}`);\n } else {\n // Regular form field: --form-string prevents @ and < interpretation\n const strValue = String(fieldValue);\n args.push('--form-string', `${fieldName}=${strValue}`);\n }\n }\n } else if (config.body) {\n const bodyStr = typeof config.body === 'string' ? config.body : JSON.stringify(config.body);\n args.push('-d', bodyStr);\n\n // Auto-add Content-Type if not present\n if (!config.headers?.['Content-Type']) {\n args.push('-H', 'Content-Type: application/json');\n }\n }\n\n // Timeout\n if (config.timeout) {\n args.push('--max-time', config.timeout.toString());\n }\n\n // Follow redirects\n if (config.followRedirects !== false) {\n args.push('-L');\n if (config.maxRedirects) {\n args.push('--max-redirs', config.maxRedirects.toString());\n }\n }\n\n // Proxy\n if (config.proxy) {\n args.push('-x', config.proxy);\n }\n\n // SSL/TLS configuration\n if (config.insecure || config.ssl?.verify === false) {\n args.push('-k');\n }\n\n if (config.ssl) {\n if (config.ssl.ca) {\n args.push('--cacert', config.ssl.ca);\n }\n if (config.ssl.cert) {\n args.push('--cert', config.ssl.cert);\n }\n if (config.ssl.key) {\n args.push('--key', config.ssl.key);\n }\n }\n\n // Output file\n if (includeOutputFlag && config.output) {\n args.push('-o', config.output);\n }\n\n // HTTP/2\n if (includeHttp2Flag && config.http2) {\n args.push('--http2');\n }\n\n // Silent mode (suppress progress but show errors)\n if (includeSilentFlags) {\n args.push('-s', '-S');\n }\n\n // Build final URL with query params\n let url = config.url;\n if (config.params && Object.keys(config.params).length > 0) {\n const queryString = new URLSearchParams(config.params).toString();\n url += (url.includes('?') ? '&' : '?') + queryString;\n }\n\n return { args, url };\n}\n\n/**\n * Formats curl args array as shell-safe command string for display/debugging.\n */\nexport function formatArgsForDisplay(args: string[]): string {\n return ['curl', ...args]\n .map((arg) =>\n arg.includes(' ') || arg.includes('\"') || arg.includes(\"'\")\n ? `'${arg.replace(/'/g, \"'\\\\''\")}'`\n : arg,\n )\n .join(' ');\n}\n\n/**\n * Creates a write-out marker for batched requests.\n */\nexport function createBatchMarker(requestIndex: number): string {\n return `\\n__CURL_BATCH_${requestIndex}_START__%{json}__CURL_BATCH_${requestIndex}_END__\\n`;\n}\n\n/**\n * Marker constants for parsing.\n */\nexport const METRICS_MARKER_START = '__CURL_METRICS_START__';\nexport const METRICS_MARKER_END = '__CURL_METRICS_END__';\n",
|
|
36
|
+
"/**\n * Response body parsing utilities.\n */\n\nimport type { JsonValue } from '../../types/config';\n\n/**\n * Parses response body, auto-detecting JSON content.\n * Returns parsed JSON if content is JSON, otherwise returns raw string.\n */\nexport function parseResponseBody(\n body: string | undefined,\n contentType?: string,\n): JsonValue | string | undefined {\n if (!body) {\n return body;\n }\n\n try {\n const isJsonContentType = contentType?.includes('application/json');\n const looksLikeJson = body.trim().startsWith('{') || body.trim().startsWith('[');\n\n if (isJsonContentType || looksLikeJson) {\n return JSON.parse(body) as JsonValue;\n }\n } catch {\n // Keep as string if JSON parse fails\n }\n\n return body;\n}\n\n/**\n * Checks if content type indicates JSON.\n */\nexport function isJsonContentType(contentType?: string): boolean {\n return contentType?.includes('application/json') ?? false;\n}\n\n/**\n * Checks if string looks like JSON (starts with { or [).\n */\nexport function looksLikeJson(str: string): boolean {\n const trimmed = str.trim();\n return trimmed.startsWith('{') || trimmed.startsWith('[');\n}\n",
|
|
37
|
+
"/**\n * Shared curl response and metrics parsing logic.\n */\n\nimport { METRICS_MARKER_END, METRICS_MARKER_START } from './args-builder';\nimport type { CurlMetrics, ProcessedMetrics } from './types';\n\n/**\n * Parses raw curl metrics JSON into processed metrics (in milliseconds).\n */\nexport function parseMetrics(raw: CurlMetrics): ProcessedMetrics {\n return {\n duration: (raw.time_total || 0) * 1000,\n size: raw.size_download,\n dnsLookup: (raw.time_namelookup || 0) * 1000,\n tcpConnection: (raw.time_connect || 0) * 1000,\n tlsHandshake: (raw.time_appconnect || 0) * 1000,\n firstByte: (raw.time_starttransfer || 0) * 1000,\n download: (raw.time_total || 0) * 1000,\n };\n}\n\n/**\n * Extracts metrics JSON from curl output using standard markers.\n * Returns the raw metrics and the response body (with markers removed).\n */\nexport function extractMetricsFromOutput(stdout: string): {\n body: string;\n metrics: CurlMetrics;\n} {\n const metricsMatch = stdout.match(\n new RegExp(`${METRICS_MARKER_START}(.+?)${METRICS_MARKER_END}`),\n );\n\n if (!metricsMatch) {\n return { body: stdout, metrics: {} };\n }\n\n const body = stdout\n .replace(new RegExp(`${METRICS_MARKER_START}.+?${METRICS_MARKER_END}`), '')\n .trim();\n\n let metrics: CurlMetrics = {};\n try {\n metrics = JSON.parse(metricsMatch[1]);\n } catch {\n // Ignore parse errors, return empty metrics\n }\n\n return { body, metrics };\n}\n\n/**\n * Extracts metrics from batched curl output using index-specific markers.\n */\nexport function extractBatchMetrics(\n stdout: string,\n requestIndex: number,\n): {\n found: boolean;\n metricsJson: string;\n startIdx: number;\n endIdx: number;\n} {\n const markerStart = `__CURL_BATCH_${requestIndex}_START__`;\n const markerEnd = `__CURL_BATCH_${requestIndex}_END__`;\n\n const startIdx = stdout.indexOf(markerStart);\n const endIdx = stdout.indexOf(markerEnd);\n\n if (startIdx === -1 || endIdx === -1) {\n return { found: false, metricsJson: '', startIdx: -1, endIdx: -1 };\n }\n\n const metricsJson = stdout.substring(startIdx + markerStart.length, endIdx);\n return { found: true, metricsJson, startIdx, endIdx };\n}\n\n/**\n * Parses headers from curl stderr output.\n */\nexport function parseHeadersFromStderr(stderr: string): Record<string, string> {\n const headers: Record<string, string> = {};\n const headerLines = stderr.split('\\n').filter((line) => line.includes(':'));\n\n for (const line of headerLines) {\n const [key, ...valueParts] = line.split(':');\n if (key && valueParts.length > 0) {\n headers[key.trim()] = valueParts.join(':').trim();\n }\n }\n\n return headers;\n}\n\n/**\n * Gets the status code from curl metrics.\n */\nexport function getStatusCode(metrics: CurlMetrics): number | undefined {\n return metrics.response_code || metrics.http_code;\n}\n\n/**\n * Determines if a response is successful based on status code.\n */\nexport function isSuccessStatus(statusCode: number | undefined): boolean {\n if (statusCode === undefined) {\n return false;\n }\n return statusCode >= 200 && statusCode < 400;\n}\n",
|
|
38
|
+
"import {\n buildCurlArgs,\n type CurlExecutionResult,\n extractMetricsFromOutput,\n formatArgsForDisplay,\n getStatusCode,\n parseHeadersFromStderr,\n parseMetrics,\n} from '../core/curl';\nimport type { RequestConfig } from '../types/config';\n\n/**\n * Builds and executes curl commands for single requests.\n * Uses shared argument building logic from core/curl.\n */\nexport class CurlBuilder {\n /**\n * Builds curl command-line arguments from a request config.\n */\n static buildCommand(config: RequestConfig): string[] {\n const { args, url } = buildCurlArgs(config, {\n includeSilentFlags: true,\n includeHttp2Flag: true,\n includeOutputFlag: true,\n });\n\n // Add URL as the last argument\n args.push(url);\n return args;\n }\n\n /**\n * Formats args array as shell-safe command string for display/debugging.\n */\n static formatCommandForDisplay(args: string[]): string {\n return formatArgsForDisplay(args);\n }\n\n /**\n * Executes a curl command with the given arguments.\n */\n static async executeCurl(args: string[]): Promise<CurlExecutionResult> {\n try {\n const proc = Bun.spawn(['curl', ...args], {\n stdout: 'pipe',\n stderr: 'pipe',\n });\n\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n\n await proc.exited;\n\n if (proc.exitCode !== 0 && !stdout) {\n return {\n success: false,\n error: stderr || `Command failed with exit code ${proc.exitCode}`,\n };\n }\n\n const { body, metrics: rawMetrics } = extractMetricsFromOutput(stdout);\n const statusCode = getStatusCode(rawMetrics);\n const headers = statusCode ? parseHeadersFromStderr(stderr) : {};\n const metrics = parseMetrics(rawMetrics);\n\n return {\n success: true,\n status: statusCode,\n headers,\n body,\n metrics,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n",
|
|
39
|
+
"import type { ColorName } from '../core/format';\nimport { colorize } from '../core/format';\nimport type { SnapshotCompareResult, SnapshotDiff } from '../types/config';\n\n/**\n * Formats snapshot comparison results for terminal output.\n */\nexport class SnapshotFormatter {\n private color(text: string, color: ColorName): string {\n return colorize(text, color);\n }\n\n /**\n * Formats the snapshot result for display.\n */\n formatResult(requestName: string, result: SnapshotCompareResult): string {\n const lines: string[] = [];\n\n if (result.isNew && result.updated) {\n lines.push(\n ` ${this.color('NEW', 'cyan')} Snapshot created for \"${this.color(requestName, 'bright')}\"`,\n );\n return lines.join('\\n');\n }\n\n if (result.updated) {\n lines.push(\n ` ${this.color('UPDATED', 'yellow')} Snapshot updated for \"${this.color(requestName, 'bright')}\"`,\n );\n return lines.join('\\n');\n }\n\n if (result.match) {\n lines.push(\n ` ${this.color('PASS', 'green')} Snapshot matches for \"${this.color(requestName, 'bright')}\"`,\n );\n return lines.join('\\n');\n }\n\n // Mismatch\n lines.push(\n ` ${this.color('FAIL', 'red')} Snapshot mismatch for \"${this.color(requestName, 'bright')}\"`,\n );\n lines.push('');\n lines.push(this.formatDiff(result.differences));\n lines.push('');\n lines.push(this.color(' Run with --update-snapshots (-u) to update', 'dim'));\n\n return lines.join('\\n');\n }\n\n /**\n * Formats differences for display.\n */\n formatDiff(differences: SnapshotDiff[]): string {\n const lines: string[] = [];\n lines.push(` ${this.color('- Expected', 'red')}`);\n lines.push(` ${this.color('+ Received', 'green')}`);\n lines.push('');\n\n for (const diff of differences) {\n lines.push(this.formatDifference(diff));\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Formats a single difference.\n */\n private formatDifference(diff: SnapshotDiff): string {\n const lines: string[] = [];\n const path = diff.path || '(root)';\n\n switch (diff.type) {\n case 'added':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`+ ${this.stringify(diff.received)}`, 'green')}`);\n break;\n\n case 'removed':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`- ${this.stringify(diff.expected)}`, 'red')}`);\n break;\n\n case 'changed':\n lines.push(` ${this.color(path, 'cyan')}:`);\n lines.push(` ${this.color(`- ${this.stringify(diff.expected)}`, 'red')}`);\n lines.push(` ${this.color(`+ ${this.stringify(diff.received)}`, 'green')}`);\n break;\n\n case 'type_mismatch':\n lines.push(` ${this.color(path, 'cyan')} (type mismatch):`);\n lines.push(\n ` ${this.color(`- ${this.stringify(diff.expected)} (${typeof diff.expected})`, 'red')}`,\n );\n lines.push(\n ` ${this.color(`+ ${this.stringify(diff.received)} (${typeof diff.received})`, 'green')}`,\n );\n break;\n }\n\n return lines.join('\\n');\n }\n\n /**\n * Converts value to display string.\n */\n private stringify(value: unknown): string {\n if (value === undefined) {\n return 'undefined';\n }\n if (value === null) {\n return 'null';\n }\n if (typeof value === 'string') {\n return `\"${value}\"`;\n }\n if (typeof value === 'object') {\n const str = JSON.stringify(value);\n // Truncate long values\n if (str.length > 80) {\n return `${str.slice(0, 77)}...`;\n }\n return str;\n }\n return String(value);\n }\n\n /**\n * Formats summary statistics.\n */\n formatSummary(stats: SnapshotStats): string {\n const parts: string[] = [];\n\n if (stats.passed > 0) {\n parts.push(this.color(`${stats.passed} passed`, 'green'));\n }\n if (stats.failed > 0) {\n parts.push(this.color(`${stats.failed} failed`, 'red'));\n }\n if (stats.updated > 0) {\n parts.push(this.color(`${stats.updated} updated`, 'yellow'));\n }\n if (stats.created > 0) {\n parts.push(this.color(`${stats.created} created`, 'cyan'));\n }\n\n if (parts.length === 0) {\n return '';\n }\n\n return `Snapshots: ${parts.join(', ')}`;\n }\n}\n\nexport interface SnapshotStats {\n passed: number;\n failed: number;\n updated: number;\n created: number;\n}\n",
|
|
40
|
+
"import type { ProfileStats } from '../types/config';\n\n/**\n * Calculate percentile from sorted array.\n * Uses linear interpolation for non-integer indices.\n */\nexport function calculatePercentile(sorted: number[], percentile: number): number {\n if (sorted.length === 0) {\n return 0;\n }\n if (sorted.length === 1) {\n return sorted[0];\n }\n\n const index = (percentile / 100) * (sorted.length - 1);\n const lower = Math.floor(index);\n const upper = Math.ceil(index);\n const fraction = index - lower;\n\n if (lower === upper) {\n return sorted[lower];\n }\n return sorted[lower] * (1 - fraction) + sorted[upper] * fraction;\n}\n\n/**\n * Calculate arithmetic mean.\n */\nexport function calculateMean(values: number[]): number {\n if (values.length === 0) {\n return 0;\n }\n return values.reduce((sum, v) => sum + v, 0) / values.length;\n}\n\n/**\n * Calculate standard deviation.\n */\nexport function calculateStdDev(values: number[], mean: number): number {\n if (values.length <= 1) {\n return 0;\n }\n const squaredDiffs = values.map((v) => (v - mean) ** 2);\n const variance = squaredDiffs.reduce((sum, v) => sum + v, 0) / values.length;\n return Math.sqrt(variance);\n}\n\n/**\n * Calculate profile statistics from raw timings.\n */\nexport function calculateProfileStats(\n timings: number[],\n warmup: number,\n failures: number,\n): ProfileStats {\n // Exclude warmup iterations\n const effectiveTimings = timings.slice(warmup);\n const sorted = [...effectiveTimings].sort((a, b) => a - b);\n\n const mean = calculateMean(sorted);\n const totalIterations = timings.length;\n const effectiveIterations = effectiveTimings.length;\n\n return {\n iterations: effectiveIterations,\n warmup,\n min: sorted.length > 0 ? sorted[0] : 0,\n max: sorted.length > 0 ? sorted[sorted.length - 1] : 0,\n mean: Math.round(mean * 100) / 100,\n median: Math.round(calculatePercentile(sorted, 50) * 100) / 100,\n p50: Math.round(calculatePercentile(sorted, 50) * 100) / 100,\n p95: Math.round(calculatePercentile(sorted, 95) * 100) / 100,\n p99: Math.round(calculatePercentile(sorted, 99) * 100) / 100,\n stdDev: Math.round(calculateStdDev(sorted, mean) * 100) / 100,\n failures,\n failureRate: totalIterations > 0 ? Math.round((failures / totalIterations) * 10000) / 100 : 0,\n timings: effectiveTimings,\n };\n}\n\n/**\n * Generate ASCII histogram for latency distribution.\n */\nexport function generateHistogram(timings: number[], buckets = 10, width = 40): string[] {\n if (timings.length === 0) {\n return ['No data'];\n }\n\n const min = Math.min(...timings);\n const max = Math.max(...timings);\n const range = max - min || 1;\n const bucketSize = range / buckets;\n\n // Count values per bucket\n const counts = new Array(buckets).fill(0);\n for (const t of timings) {\n const bucket = Math.min(Math.floor((t - min) / bucketSize), buckets - 1);\n counts[bucket]++;\n }\n\n const maxCount = Math.max(...counts);\n const lines: string[] = [];\n\n for (let i = 0; i < buckets; i++) {\n const bucketMin = min + i * bucketSize;\n const bucketMax = min + (i + 1) * bucketSize;\n const barLength = maxCount > 0 ? Math.round((counts[i] / maxCount) * width) : 0;\n const bar = '█'.repeat(barLength);\n const label = `${bucketMin.toFixed(0).padStart(6)}ms - ${bucketMax.toFixed(0).padStart(6)}ms`;\n lines.push(`${label} │${bar} ${counts[i]}`);\n }\n\n return lines;\n}\n\n/**\n * Export stats to CSV format.\n */\nexport function exportToCSV(stats: ProfileStats, _requestName: string): string {\n const headers = ['iteration', 'latency_ms'];\n const rows = stats.timings.map((t, i) => `${i + 1},${t}`);\n return [headers.join(','), ...rows].join('\\n');\n}\n\n/**\n * Export stats to JSON format.\n */\nexport function exportToJSON(stats: ProfileStats, requestName: string): string {\n return JSON.stringify(\n {\n request: requestName,\n summary: {\n iterations: stats.iterations,\n warmup: stats.warmup,\n failures: stats.failures,\n failureRate: stats.failureRate,\n min: stats.min,\n max: stats.max,\n mean: stats.mean,\n median: stats.median,\n p50: stats.p50,\n p95: stats.p95,\n p99: stats.p99,\n stdDev: stats.stdDev,\n },\n timings: stats.timings,\n },\n null,\n 2,\n );\n}\n",
|
|
41
|
+
"import type { ANSI_COLORS, TreeNode } from '../core/format';\nimport {\n colorize,\n formatDuration,\n formatJson,\n formatLatency,\n formatSize,\n getShortFilename,\n TreeRenderer,\n} from '../core/format';\nimport { SnapshotFormatter } from '../snapshot/snapshot-formatter';\nimport type {\n ExecutionResult,\n ExecutionSummary,\n GlobalConfig,\n ProfileResult,\n RequestConfig,\n} from '../types/config';\nimport { getGlobalRedactor } from './secret-redactor';\nimport { generateHistogram } from './stats';\n\nexport class Logger {\n private config: GlobalConfig['output'];\n private redactor = getGlobalRedactor();\n\n constructor(config: GlobalConfig['output'] = {}) {\n this.config = {\n verbose: false,\n showHeaders: false,\n showBody: true,\n showMetrics: false,\n format: 'pretty',\n prettyLevel: 'minimal',\n ...config,\n };\n }\n\n /**\n * Redacts secret values from output string.\n * Only used for URLs and curl commands (user's secrets).\n */\n private redact(text: string): string {\n return this.redactor.redact(text);\n }\n\n color(text: string, color: keyof typeof ANSI_COLORS): string {\n return colorize(text, color);\n }\n\n private shouldShowOutput(): boolean {\n if (this.config.format === 'raw') {\n return false;\n }\n if (this.config.format === 'pretty') {\n return true; // Pretty format should always show output\n }\n return this.config.verbose !== false; // For other formats, respect verbose flag\n }\n\n private shouldShowHeaders(): boolean {\n if (this.config.format !== 'pretty') {\n return this.config.showHeaders || false;\n }\n\n const level = this.config.prettyLevel || 'standard';\n switch (level) {\n case 'minimal':\n return false;\n case 'standard':\n return this.config.showHeaders || false;\n case 'detailed':\n return true;\n default:\n return this.config.showHeaders || false;\n }\n }\n\n private shouldShowBody(): boolean {\n if (this.config.format !== 'pretty') {\n return this.config.showBody !== false;\n }\n\n const level = this.config.prettyLevel || 'standard';\n switch (level) {\n case 'minimal':\n return false; // Minimal never shows body\n case 'standard':\n return this.config.showBody !== false;\n case 'detailed':\n return true; // Detailed always shows body\n default:\n return this.config.showBody !== false;\n }\n }\n\n private shouldShowMetrics(): boolean {\n if (this.config.format !== 'pretty') {\n return this.config.showMetrics || false;\n }\n\n const level = this.config.prettyLevel || 'standard';\n switch (level) {\n case 'minimal':\n return false; // Minimal never shows metrics\n case 'standard':\n return this.config.showMetrics || false;\n case 'detailed':\n return true; // Detailed always shows metrics\n default:\n return this.config.showMetrics || false;\n }\n }\n\n private shouldShowRequestDetails(): boolean {\n if (this.config.format !== 'pretty') {\n return this.config.verbose || false;\n }\n\n const level = this.config.prettyLevel || 'standard';\n switch (level) {\n case 'minimal':\n return false;\n case 'standard':\n return this.config.verbose || false;\n case 'detailed':\n return true;\n default:\n return this.config.verbose || false;\n }\n }\n\n private shouldShowSeparators(): boolean {\n if (this.config.format !== 'pretty') {\n return true;\n }\n\n const level = this.config.prettyLevel || 'standard';\n switch (level) {\n case 'minimal':\n return false;\n case 'standard':\n return true;\n case 'detailed':\n return true;\n default:\n return true;\n }\n }\n\n private colorStatusCode(statusStr: string): string {\n // For expected status codes in validation errors, use yellow to distinguish from red actual values\n return this.color(statusStr, 'yellow');\n }\n\n private logValidationErrors(errorString: string): void {\n // Check if this is a validation error with multiple parts (separated by ';')\n const errors = errorString.split('; ');\n\n if (errors.length === 1) {\n // Single error - check if it's a status error for special formatting\n const trimmedError = errors[0].trim();\n const statusMatch = trimmedError.match(/^Expected status (.+?), got (.+)$/);\n if (statusMatch) {\n const [, expected, actual] = statusMatch;\n const expectedStatus = this.colorStatusCode(expected.replace(' or ', '|'));\n const actualStatus = this.color(actual, 'red'); // Always red for incorrect actual values\n console.log(\n ` ${this.color('✗', 'red')} ${this.color('Error:', 'red')} Expected ${this.color('status', 'yellow')} ${expectedStatus}, got ${actualStatus}`,\n );\n } else {\n console.log(` ${this.color('✗', 'red')} ${this.color('Error:', 'red')} ${trimmedError}`);\n }\n } else {\n // Multiple validation errors - show them nicely formatted\n console.log(` ${this.color('✗', 'red')} ${this.color('Validation Errors:', 'red')}`);\n for (const error of errors) {\n const trimmedError = error.trim();\n if (trimmedError) {\n // Parse different error formats for better formatting\n if (trimmedError.startsWith('Expected ')) {\n // Format 1: \"Expected status 201, got 200\"\n const statusMatch = trimmedError.match(/^Expected status (.+?), got (.+)$/);\n if (statusMatch) {\n const [, expected, actual] = statusMatch;\n const expectedStatus = this.colorStatusCode(expected.replace(' or ', '|'));\n const actualStatus = this.color(actual, 'red'); // Always red for incorrect actual values\n console.log(\n ` ${this.color('•', 'red')} ${this.color('status', 'yellow')}: expected ${expectedStatus}, got ${actualStatus}`,\n );\n } else {\n // Format 2: \"Expected field to be value, got value\"\n const fieldMatch = trimmedError.match(/^Expected (.+?) to be (.+?), got (.+)$/);\n if (fieldMatch) {\n const [, field, expected, actual] = fieldMatch;\n console.log(\n ` ${this.color('•', 'red')} ${this.color(field, 'yellow')}: expected ${this.color(expected, 'green')}, got ${this.color(actual, 'red')}`,\n );\n } else {\n console.log(` ${this.color('•', 'red')} ${trimmedError}`);\n }\n }\n } else {\n console.log(` ${this.color('•', 'red')} ${trimmedError}`);\n }\n }\n }\n }\n }\n\n logExecutionStart(count: number, mode: string): void {\n if (!this.shouldShowOutput()) {\n return;\n }\n\n if (this.shouldShowSeparators()) {\n console.log(); // Add spacing before the execution header\n console.log(this.color(`Executing ${count} request(s) in ${mode} mode`, 'dim'));\n console.log();\n } else {\n // For minimal format, still add spacing after processing info\n console.log();\n }\n }\n\n logRequestStart(_config: RequestConfig, _index: number): void {\n // In the new format, we show everything in logRequestComplete\n // This method is kept for compatibility but simplified\n return;\n }\n\n logCommand(command: string): void {\n // Always show command in dry-run mode\n if (this.config.dryRun || this.shouldShowRequestDetails()) {\n console.log(this.color(' Command:', 'dim'));\n console.log(this.color(` ${this.redact(command)}`, 'dim'));\n }\n }\n\n logRetry(attempt: number, maxRetries: number): void {\n console.log(this.color(` ↻ Retry ${attempt}/${maxRetries}...`, 'yellow'));\n }\n\n logRequestComplete(result: ExecutionResult): void {\n // Handle raw format output - only show response body\n if (this.config.format === 'raw') {\n if (result.success && this.config.showBody && result.body) {\n const bodyStr = formatJson(result.body, this.config.format);\n console.log(bodyStr);\n }\n return;\n }\n\n // Handle JSON format output - structured JSON only\n if (this.config.format === 'json') {\n const jsonResult = {\n request: {\n name: result.request.name,\n url: this.redact(result.request.url),\n method: result.request.method || 'GET',\n },\n success: result.success,\n ...(result.dryRun ? { dryRun: true } : { status: result.status }),\n ...(this.shouldShowHeaders() && result.headers ? { headers: result.headers } : {}),\n ...(this.shouldShowBody() && result.body ? { body: result.body } : {}),\n ...(result.error ? { error: result.error } : {}),\n ...(this.shouldShowMetrics() && result.metrics ? { metrics: result.metrics } : {}),\n };\n console.log(JSON.stringify(jsonResult, null, 2));\n return;\n }\n\n // Pretty format output (default behavior)\n if (!this.shouldShowOutput()) {\n return;\n }\n\n const level = this.config.prettyLevel || 'minimal';\n const statusColor = result.success ? 'green' : 'red';\n const statusIcon = result.success ? '✓' : 'x';\n const name = result.request.name || 'Request';\n\n if (level === 'minimal') {\n // Minimal format: clean tree structure but compact\n const fileTag = result.request.sourceFile\n ? getShortFilename(result.request.sourceFile)\n : 'inline';\n console.log(\n `${this.color(statusIcon, statusColor)} ${this.color(name, 'bright')} [${fileTag}]`,\n );\n\n const treeNodes: TreeNode[] = [];\n const renderer = new TreeRenderer();\n\n treeNodes.push({\n label: result.request.method || 'GET',\n value: this.redact(result.request.url),\n color: 'blue',\n });\n\n const statusText = result.dryRun ? 'DRY-RUN' : result.status ? `${result.status}` : 'ERROR';\n treeNodes.push({\n label: `${statusIcon} Status`,\n value: statusText,\n color: result.dryRun ? 'cyan' : statusColor,\n });\n\n if (result.metrics) {\n const durationSize = `${formatDuration(result.metrics.duration)} | ${formatSize(result.metrics.size)}`;\n treeNodes.push({\n label: 'Duration',\n value: durationSize,\n color: 'cyan',\n });\n }\n\n renderer.render(treeNodes);\n\n if (result.error) {\n console.log();\n this.logValidationErrors(result.error);\n }\n\n // Show snapshot result\n if (result.snapshotResult) {\n console.log();\n this.logSnapshotResult(result.request.name || 'Request', result.snapshotResult);\n }\n\n console.log();\n return;\n }\n\n // Standard and detailed formats: use clean tree structure\n console.log(`${this.color(statusIcon, statusColor)} ${this.color(name, 'bright')}`);\n\n // Build tree structure\n const treeNodes: TreeNode[] = [];\n const renderer = new TreeRenderer();\n\n // Main info nodes\n treeNodes.push({ label: 'URL', value: this.redact(result.request.url), color: 'blue' });\n treeNodes.push({ label: 'Method', value: result.request.method || 'GET', color: 'yellow' });\n treeNodes.push({\n label: 'Status',\n value: result.dryRun ? 'DRY-RUN' : String(result.status || 'ERROR'),\n color: result.dryRun ? 'cyan' : statusColor,\n });\n\n if (result.metrics) {\n treeNodes.push({\n label: 'Duration',\n value: formatDuration(result.metrics.duration),\n color: 'cyan',\n });\n }\n\n // Add response headers section if needed (no redaction - server data)\n if (this.shouldShowHeaders() && result.headers && Object.keys(result.headers).length > 0) {\n const headerChildren: TreeNode[] = Object.entries(result.headers).map(([key, value]) => ({\n label: this.color(key, 'dim'),\n value: String(value),\n }));\n\n treeNodes.push({\n label: 'Headers',\n children: headerChildren,\n });\n }\n\n // Add body section if needed (no redaction - server data)\n if (this.shouldShowBody() && result.body) {\n const bodyStr = formatJson(result.body, this.config.format);\n const lines = bodyStr.split('\\n');\n const maxLines = this.shouldShowRequestDetails() ? Infinity : 10;\n const bodyLines = lines.slice(0, maxLines);\n\n if (lines.length > maxLines) {\n bodyLines.push(this.color(`... (${lines.length - maxLines} more lines)`, 'dim'));\n }\n\n treeNodes.push({\n label: 'Response Body',\n value: bodyLines.join('\\n'),\n });\n }\n\n // Add detailed metrics section if needed\n if (this.shouldShowMetrics() && result.metrics && level === 'detailed') {\n const metrics = result.metrics;\n const metricChildren: TreeNode[] = [];\n\n metricChildren.push({\n label: 'Request Duration',\n value: formatDuration(metrics.duration),\n color: 'cyan',\n });\n\n if (metrics.size !== undefined) {\n metricChildren.push({\n label: 'Response Size',\n value: formatSize(metrics.size),\n color: 'cyan',\n });\n }\n\n if (metrics.dnsLookup) {\n metricChildren.push({\n label: 'DNS Lookup',\n value: formatDuration(metrics.dnsLookup),\n color: 'cyan',\n });\n }\n\n if (metrics.tcpConnection) {\n metricChildren.push({\n label: 'TCP Connection',\n value: formatDuration(metrics.tcpConnection),\n color: 'cyan',\n });\n }\n\n if (metrics.tlsHandshake) {\n metricChildren.push({\n label: 'TLS Handshake',\n value: formatDuration(metrics.tlsHandshake),\n color: 'cyan',\n });\n }\n\n if (metrics.firstByte) {\n metricChildren.push({\n label: 'Time to First Byte',\n value: formatDuration(metrics.firstByte),\n color: 'cyan',\n });\n }\n\n treeNodes.push({\n label: 'Metrics',\n children: metricChildren,\n });\n }\n\n // Render the tree\n renderer.render(treeNodes);\n\n if (result.error) {\n console.log();\n this.logValidationErrors(result.error);\n }\n\n // Show snapshot result\n if (result.snapshotResult) {\n console.log();\n this.logSnapshotResult(result.request.name || 'Request', result.snapshotResult);\n }\n\n console.log();\n }\n\n /**\n * Logs snapshot comparison result.\n */\n private logSnapshotResult(requestName: string, result: ExecutionResult['snapshotResult']): void {\n if (!result) {\n return;\n }\n\n const formatter = new SnapshotFormatter();\n console.log(formatter.formatResult(requestName, result));\n }\n\n logSummary(summary: ExecutionSummary, isGlobal: boolean = false): void {\n // For raw format, don't show summary\n if (this.config.format === 'raw') {\n return;\n }\n\n // For JSON format, output structured summary\n if (this.config.format === 'json') {\n const jsonSummary = {\n summary: {\n total: summary.total,\n successful: summary.successful,\n failed: summary.failed,\n skipped: summary.skipped,\n duration: summary.duration,\n },\n results: summary.results.map((result) => ({\n request: {\n name: result.request.name,\n url: this.redact(result.request.url),\n method: result.request.method || 'GET',\n },\n success: result.success,\n ...(result.dryRun ? { dryRun: true } : { status: result.status }),\n ...(this.shouldShowHeaders() && result.headers ? { headers: result.headers } : {}),\n ...(this.shouldShowBody() && result.body ? { body: result.body } : {}),\n ...(result.error ? { error: result.error } : {}),\n ...(this.shouldShowMetrics() && result.metrics ? { metrics: result.metrics } : {}),\n })),\n };\n console.log(JSON.stringify(jsonSummary, null, 2));\n return;\n }\n\n // Pretty format summary (default behavior)\n if (!this.shouldShowOutput()) {\n return;\n }\n\n const level = this.config.prettyLevel || 'minimal';\n\n // Add spacing for global summary\n if (isGlobal) {\n console.log(); // Extra spacing before global summary\n }\n\n if (level === 'minimal') {\n // Simple one-line summary for minimal, similar to docs example\n const statusColor = summary.failed === 0 ? 'green' : 'red';\n const skippedText = summary.skipped > 0 ? `, ${summary.skipped} skipped` : '';\n const successText =\n summary.failed === 0\n ? `${summary.total} request${summary.total === 1 ? '' : 's'} completed successfully${skippedText}`\n : `${summary.successful}/${summary.total} request${summary.total === 1 ? '' : 's'} completed, ${summary.failed} failed${skippedText}`;\n\n const summaryPrefix = isGlobal ? '◆ Global Summary' : 'Summary';\n console.log(`${summaryPrefix}: ${this.color(successText, statusColor)}`);\n return;\n }\n\n // Compact summary for standard/detailed - much simpler\n const _successRate = ((summary.successful / summary.total) * 100).toFixed(1);\n const statusColor = summary.failed === 0 ? 'green' : 'red';\n const skippedText = summary.skipped > 0 ? `, ${summary.skipped} skipped` : '';\n const successText =\n summary.failed === 0\n ? `${summary.total} request${summary.total === 1 ? '' : 's'} completed successfully${skippedText}`\n : `${summary.successful}/${summary.total} request${summary.total === 1 ? '' : 's'} completed, ${summary.failed} failed${skippedText}`;\n\n const summaryPrefix = isGlobal ? '◆ Global Summary' : 'Summary';\n console.log();\n console.log(\n `${summaryPrefix}: ${this.color(successText, statusColor)} (${this.color(formatDuration(summary.duration), 'cyan')})`,\n );\n\n if (summary.failed > 0 && this.shouldShowRequestDetails()) {\n summary.results\n .filter((r) => !r.success)\n .forEach((r) => {\n const name = r.request.name || this.redact(r.request.url);\n console.log(` ${this.color('•', 'red')} ${name}: ${r.error || ''}`);\n });\n }\n }\n\n logError(message: string): void {\n console.error(this.color(`✗ ${message}`, 'red'));\n }\n\n logWarning(message: string): void {\n console.warn(this.color(`⚠ ${message}`, 'yellow'));\n }\n\n logInfo(message: string): void {\n console.log(this.color(`ℹ ${message}`, 'blue'));\n }\n\n logSuccess(message: string): void {\n console.log(this.color(`✓ ${message}`, 'green'));\n }\n\n logSkipped(config: RequestConfig, index: number, reason?: string): void {\n if (!this.shouldShowOutput()) {\n return;\n }\n\n const name = config.name || `Request ${index}`;\n\n if (this.config.format === 'json') {\n const jsonResult = {\n request: {\n name: config.name,\n url: this.redact(config.url),\n method: config.method || 'GET',\n },\n skipped: true,\n reason: reason || 'condition not met',\n };\n console.log(JSON.stringify(jsonResult, null, 2));\n return;\n }\n\n // Pretty format\n console.log(\n `${this.color('⊘', 'yellow')} ${this.color(name, 'bright')} ${this.color('[SKIP]', 'yellow')}`,\n );\n\n if (reason) {\n const treeNodes: TreeNode[] = [{ label: 'Reason', value: reason, color: 'yellow' }];\n const renderer = new TreeRenderer();\n renderer.render(treeNodes);\n }\n\n console.log();\n }\n\n logFileHeader(fileName: string, requestCount: number): void {\n if (!this.shouldShowOutput() || this.config.format !== 'pretty') {\n return;\n }\n\n const shortName = fileName.replace(/.*\\//, '').replace('.yaml', '');\n console.log();\n console.log(\n this.color(`▶ ${shortName}.yaml`, 'bright') +\n this.color(` (${requestCount} request${requestCount === 1 ? '' : 's'})`, 'dim'),\n );\n }\n\n logWatch(files: string[]): void {\n console.log();\n console.log(\n `${this.color('Watching for changes...', 'cyan')} ${this.color('(press Ctrl+C to stop)', 'dim')}`,\n );\n const fileList = files.length <= 3 ? files.join(', ') : `${files.length} files`;\n console.log(this.color(` Files: ${fileList}`, 'dim'));\n console.log();\n }\n\n logWatchReady(): void {\n console.log();\n console.log(this.color('Watching for changes...', 'cyan'));\n }\n\n logFileChanged(filename: string): void {\n const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false });\n console.log(this.color('-'.repeat(50), 'dim'));\n console.log(\n `${this.color(`[${timestamp}]`, 'dim')} File changed: ${this.color(filename, 'yellow')}`,\n );\n console.log();\n }\n\n logProfileStart(\n requestName: string,\n iterations: number,\n warmup: number,\n concurrency: number,\n ): void {\n if (!this.shouldShowOutput()) {\n return;\n }\n\n console.log();\n console.log(`${this.color('⚡ PROFILING', 'magenta')} ${this.color(requestName, 'bright')}`);\n console.log(\n this.color(\n ` ${iterations} iterations, ${warmup} warmup, concurrency: ${concurrency}`,\n 'dim',\n ),\n );\n }\n\n logProfileResult(result: ProfileResult, showHistogram: boolean): void {\n const { stats, request } = result;\n const name = request.name || request.url;\n\n if (this.config.format === 'json') {\n console.log(\n JSON.stringify({\n request: { name, url: request.url, method: request.method || 'GET' },\n stats: {\n iterations: stats.iterations,\n warmup: stats.warmup,\n failures: stats.failures,\n failureRate: stats.failureRate,\n min: stats.min,\n max: stats.max,\n mean: stats.mean,\n median: stats.median,\n p50: stats.p50,\n p95: stats.p95,\n p99: stats.p99,\n stdDev: stats.stdDev,\n },\n }),\n );\n return;\n }\n\n if (this.config.format === 'raw') {\n // Raw format: just print the key stats\n console.log(`${stats.p50}\\t${stats.p95}\\t${stats.p99}\\t${stats.mean}`);\n return;\n }\n\n // Pretty format\n console.log();\n const statusIcon = stats.failures === 0 ? this.color('✓', 'green') : this.color('⚠', 'yellow');\n console.log(`${statusIcon} ${this.color(name, 'bright')}`);\n\n // Latency stats table\n console.log(this.color(' ┌─────────────────────────────────────┐', 'dim'));\n console.log(\n ` │ ${this.color('p50', 'cyan')} ${formatLatency(stats.p50).padStart(10)} │ ${this.color('min', 'dim')} ${formatLatency(stats.min).padStart(10)} │`,\n );\n console.log(\n ` │ ${this.color('p95', 'yellow')} ${formatLatency(stats.p95).padStart(10)} │ ${this.color('max', 'dim')} ${formatLatency(stats.max).padStart(10)} │`,\n );\n console.log(\n ` │ ${this.color('p99', 'red')} ${formatLatency(stats.p99).padStart(10)} │ ${this.color('mean', 'dim')} ${formatLatency(stats.mean).padStart(10)} │`,\n );\n console.log(this.color(' └─────────────────────────────────────┘', 'dim'));\n\n // Additional stats\n console.log(\n this.color(\n ` σ ${stats.stdDev.toFixed(2)}ms | ${stats.iterations} samples | ${stats.failures} failures (${stats.failureRate}%)`,\n 'dim',\n ),\n );\n\n // Optional histogram\n if (showHistogram && stats.timings.length > 0) {\n console.log();\n console.log(this.color(' Distribution:', 'dim'));\n const histogramLines = generateHistogram(stats.timings, 8, 30);\n for (const line of histogramLines) {\n console.log(` ${this.color(line, 'dim')}`);\n }\n }\n }\n\n logProfileSummary(results: ProfileResult[]): void {\n if (!this.shouldShowOutput()) {\n return;\n }\n\n const totalIterations = results.reduce((sum, r) => sum + r.stats.iterations, 0);\n const totalFailures = results.reduce((sum, r) => sum + r.stats.failures, 0);\n\n console.log();\n console.log(this.color('─'.repeat(50), 'dim'));\n console.log(\n `${this.color('⚡ Profile Summary:', 'magenta')} ${results.length} request${results.length === 1 ? '' : 's'}, ${totalIterations} total iterations`,\n );\n\n if (totalFailures > 0) {\n console.log(this.color(` ${totalFailures} total failures`, 'yellow'));\n }\n }\n}\n",
|
|
42
|
+
"import { parseResponseBody } from '../core/curl';\nimport type {\n ExecutionResult,\n GlobalConfig,\n ProfileConfig,\n ProfileResult,\n RequestConfig,\n} from '../types/config';\nimport { CurlBuilder } from '../utils/curl-builder';\nimport { Logger } from '../utils/logger';\nimport { calculateProfileStats } from '../utils/stats';\n\nexport class ProfileExecutor {\n private logger: Logger;\n private profileConfig: ProfileConfig;\n\n constructor(globalConfig: GlobalConfig, profileConfig: ProfileConfig) {\n this.profileConfig = profileConfig;\n this.logger = new Logger(globalConfig.output);\n }\n\n /**\n * Execute a single iteration of the request (minimal overhead version).\n * Skips logging and validation for accurate timing.\n */\n private async executeSingleIteration(config: RequestConfig): Promise<ExecutionResult> {\n const startTime = performance.now();\n const command = CurlBuilder.buildCommand(config);\n const result = await CurlBuilder.executeCurl(command);\n\n if (result.success) {\n return {\n request: config,\n success: true,\n status: result.status,\n headers: result.headers,\n body: parseResponseBody(result.body, result.headers?.['content-type']),\n metrics: {\n ...result.metrics,\n duration: performance.now() - startTime,\n },\n };\n }\n\n return {\n request: config,\n success: false,\n error: result.error,\n metrics: {\n duration: performance.now() - startTime,\n },\n };\n }\n\n /**\n * Execute iterations in chunks for controlled concurrency.\n */\n private async executeWithConcurrency(\n config: RequestConfig,\n iterations: number,\n concurrency: number,\n ): Promise<ExecutionResult[]> {\n const results: ExecutionResult[] = [];\n\n for (let i = 0; i < iterations; i += concurrency) {\n const chunkSize = Math.min(concurrency, iterations - i);\n const chunk = await Promise.all(\n Array.from({ length: chunkSize }, () => this.executeSingleIteration(config)),\n );\n results.push(...chunk);\n }\n\n return results;\n }\n\n /**\n * Profile a single request by running it multiple times.\n */\n async profileRequest(config: RequestConfig, index = 0): Promise<ProfileResult> {\n const iterations = this.profileConfig.iterations;\n const warmup = this.profileConfig.warmup ?? 1;\n const concurrency = this.profileConfig.concurrency ?? 1;\n const requestName = config.name || `Request ${index + 1}`;\n\n this.logger.logProfileStart(requestName, iterations, warmup, concurrency);\n\n const results =\n concurrency === 1\n ? await this.executeSequentially(config, iterations)\n : await this.executeWithConcurrency(config, iterations, concurrency);\n\n // Collect timings and count failures\n const timings: number[] = [];\n let failures = 0;\n\n for (const result of results) {\n if (result.success && result.metrics?.duration !== undefined) {\n timings.push(result.metrics.duration);\n } else {\n failures++;\n // Use 0 as placeholder for failed requests (excluded from stats)\n timings.push(0);\n }\n }\n\n // Filter out failed timings (0s) for stats calculation\n const successfulTimings = timings\n .map((t, i) => (results[i].success ? t : -1))\n .filter((t) => t >= 0);\n\n // Recalculate stats with only successful timings\n const stats = calculateProfileStats(\n successfulTimings,\n Math.min(warmup, successfulTimings.length),\n failures,\n );\n\n return {\n request: config,\n stats,\n iterations: results,\n };\n }\n\n /**\n * Execute iterations sequentially (default behavior).\n */\n private async executeSequentially(\n config: RequestConfig,\n iterations: number,\n ): Promise<ExecutionResult[]> {\n const results: ExecutionResult[] = [];\n\n for (let i = 0; i < iterations; i++) {\n const result = await this.executeSingleIteration(config);\n results.push(result);\n }\n\n return results;\n }\n\n /**\n * Profile multiple requests.\n */\n async profileRequests(requests: RequestConfig[]): Promise<ProfileResult[]> {\n const results: ProfileResult[] = [];\n\n for (let i = 0; i < requests.length; i++) {\n const result = await this.profileRequest(requests[i], i);\n results.push(result);\n this.logger.logProfileResult(result, this.profileConfig.histogram ?? false);\n }\n\n return results;\n }\n}\n",
|
|
43
|
+
"/**\n * Response validation utilities.\n */\n\nimport type {\n ExpectConfig,\n JsonValue,\n ResponseData,\n ValidationResult,\n ValueValidationResult,\n} from './types';\n\n/**\n * Validates a response against expected values.\n */\nexport function validateResponse(result: ResponseData, expect: ExpectConfig): ValidationResult {\n if (!expect) {\n return { success: true };\n }\n\n const errors: string[] = [];\n\n // Validate status\n if (expect.status !== undefined) {\n const statusErrors = validateStatus(result.status, expect.status);\n errors.push(...statusErrors);\n }\n\n // Validate headers\n if (expect.headers) {\n const headerErrors = validateHeaders(result.headers, expect.headers);\n errors.push(...headerErrors);\n }\n\n // Validate body\n if (expect.body !== undefined) {\n const bodyErrors = validateBodyProperties(result.body, expect.body, '');\n errors.push(...bodyErrors);\n }\n\n // Validate response time\n if (expect.responseTime !== undefined && result.metrics) {\n const responseTimeMs = result.metrics.duration;\n if (!validateRangePattern(responseTimeMs, expect.responseTime)) {\n errors.push(\n `Expected response time to match ${expect.responseTime}ms, got ${responseTimeMs.toFixed(2)}ms`,\n );\n }\n }\n\n const hasValidationErrors = errors.length > 0;\n\n // Handle failure expectation (negative testing)\n if (expect.failure === true) {\n if (hasValidationErrors) {\n return { success: false, error: errors.join('; ') };\n }\n\n const status = result.status || 0;\n if (status >= 400) {\n return { success: true };\n }\n return {\n success: false,\n error: `Expected request to fail (4xx/5xx) but got status ${status}`,\n };\n }\n\n // Normal case: expect success\n if (hasValidationErrors) {\n return { success: false, error: errors.join('; ') };\n }\n return { success: true };\n}\n\n/**\n * Validates HTTP status code.\n */\nexport function validateStatus(actual: number | undefined, expected: number | number[]): string[] {\n const expectedStatuses = Array.isArray(expected) ? expected : [expected];\n if (!expectedStatuses.includes(actual || 0)) {\n return [`Expected status ${expectedStatuses.join(' or ')}, got ${actual}`];\n }\n return [];\n}\n\n/**\n * Validates HTTP headers.\n */\nexport function validateHeaders(\n actual: Record<string, string> | undefined,\n expected: Record<string, string>,\n): string[] {\n const errors: string[] = [];\n for (const [key, value] of Object.entries(expected)) {\n const actualValue = actual?.[key] || actual?.[key.toLowerCase()];\n if (actualValue !== value) {\n errors.push(`Expected header ${key}=\"${value}\", got \"${actualValue}\"`);\n }\n }\n return errors;\n}\n\n/**\n * Validates body properties recursively.\n */\nexport function validateBodyProperties(\n actualBody: JsonValue,\n expectedBody: JsonValue,\n path: string,\n): string[] {\n const errors: string[] = [];\n\n if (typeof expectedBody !== 'object' || expectedBody === null) {\n const validationResult = validateValue(actualBody, expectedBody, path || 'body');\n if (!validationResult.isValid) {\n errors.push(validationResult.error!);\n }\n return errors;\n }\n\n // Array validation\n if (Array.isArray(expectedBody)) {\n if (Array.isArray(actualBody)) {\n // Element-wise: each expected item must find a matching actual item\n for (let i = 0; i < expectedBody.length; i++) {\n const expectedItem = expectedBody[i];\n const itemPath = `${path || 'body'}[${i}]`;\n\n if (typeof expectedItem === 'object' && expectedItem !== null) {\n const found = actualBody.some((actualItem) => {\n const itemErrors = validateBodyProperties(actualItem, expectedItem, itemPath);\n return itemErrors.length === 0;\n });\n if (!found) {\n errors.push(\n `Expected ${path || 'body'} to contain item matching ${JSON.stringify(expectedItem)}, but no match found`,\n );\n }\n } else {\n const found = actualBody.some((actualItem) => {\n const result = validateValue(actualItem, expectedItem, itemPath);\n return result.isValid;\n });\n if (!found) {\n errors.push(\n `Expected ${path || 'body'} to contain item matching ${JSON.stringify(expectedItem)}, but no match found`,\n );\n }\n }\n }\n return errors;\n }\n\n // Actual is scalar, expected is array → \"one of\" matching\n const validationResult = validateValue(actualBody, expectedBody, path || 'body');\n if (!validationResult.isValid) {\n errors.push(validationResult.error!);\n }\n return errors;\n }\n\n // Object property comparison with array selector support\n for (const [key, expectedValue] of Object.entries(expectedBody)) {\n const currentPath = path ? `${path}.${key}` : key;\n let actualValue: JsonValue;\n\n // Handle array selectors like [0], [-1], *, slice(0,3)\n if (Array.isArray(actualBody) && isArraySelector(key)) {\n actualValue = getArrayValue(actualBody, key);\n } else {\n actualValue = (actualBody as Record<string, JsonValue>)?.[key];\n }\n\n if (typeof expectedValue === 'object' && expectedValue !== null) {\n // Recursive validation for nested objects and arrays\n const nestedErrors = validateBodyProperties(actualValue, expectedValue, currentPath);\n errors.push(...nestedErrors);\n } else {\n // Value validation\n const validationResult = validateValue(actualValue, expectedValue, currentPath);\n if (!validationResult.isValid) {\n errors.push(validationResult.error!);\n }\n }\n }\n\n return errors;\n}\n\n/**\n * Validates a single value against expected value.\n */\nexport function validateValue(\n actualValue: JsonValue,\n expectedValue: JsonValue,\n path: string,\n): ValueValidationResult {\n // Wildcard - accept any value\n if (expectedValue === '*') {\n return { isValid: true };\n }\n\n // Multiple acceptable values (array)\n if (Array.isArray(expectedValue)) {\n const isMatch = expectedValue.some((expected) => {\n if (expected === '*') {\n return true;\n }\n if (typeof expected === 'string' && isRegexPattern(expected)) {\n return validateRegexPattern(actualValue, expected);\n }\n if (typeof expected === 'string' && isRangePattern(expected)) {\n return validateRangePattern(actualValue, expected);\n }\n return actualValue === expected;\n });\n\n if (!isMatch) {\n return {\n isValid: false,\n error: `Expected ${path} to match one of ${JSON.stringify(expectedValue)}, got ${JSON.stringify(actualValue)}`,\n };\n }\n return { isValid: true };\n }\n\n // Regex pattern validation\n if (typeof expectedValue === 'string' && isRegexPattern(expectedValue)) {\n if (!validateRegexPattern(actualValue, expectedValue)) {\n return {\n isValid: false,\n error: `Expected ${path} to match pattern ${expectedValue}, got ${JSON.stringify(actualValue)}`,\n };\n }\n return { isValid: true };\n }\n\n // Numeric range validation\n if (typeof expectedValue === 'string' && isRangePattern(expectedValue)) {\n if (!validateRangePattern(actualValue, expectedValue)) {\n return {\n isValid: false,\n error: `Expected ${path} to match range ${expectedValue}, got ${JSON.stringify(actualValue)}`,\n };\n }\n return { isValid: true };\n }\n\n // Null handling\n if (expectedValue === 'null' || expectedValue === null) {\n if (actualValue !== null) {\n return {\n isValid: false,\n error: `Expected ${path} to be null, got ${JSON.stringify(actualValue)}`,\n };\n }\n return { isValid: true };\n }\n\n // Exact value comparison\n if (actualValue !== expectedValue) {\n return {\n isValid: false,\n error: `Expected ${path} to be ${JSON.stringify(expectedValue)}, got ${JSON.stringify(actualValue)}`,\n };\n }\n\n return { isValid: true };\n}\n\n/**\n * Checks if a string is a regex pattern.\n */\nexport function isRegexPattern(pattern: string): boolean {\n return (\n pattern.startsWith('^') ||\n pattern.endsWith('$') ||\n pattern.includes('\\\\d') ||\n pattern.includes('\\\\w') ||\n pattern.includes('\\\\s') ||\n pattern.includes('[') ||\n pattern.includes('*') ||\n pattern.includes('+') ||\n pattern.includes('?')\n );\n}\n\n/**\n * Validates a value against a regex pattern.\n */\nexport function validateRegexPattern(actualValue: JsonValue, pattern: string): boolean {\n const stringValue = String(actualValue);\n try {\n const regex = new RegExp(pattern);\n return regex.test(stringValue);\n } catch {\n return false;\n }\n}\n\n/**\n * Checks if a string is a range pattern.\n */\nexport function isRangePattern(pattern: string): boolean {\n return /^(>=?|<=?|>|<)\\s*[\\d.-]+(\\s*,\\s*(>=?|<=?|>|<)\\s*[\\d.-]+)*$/.test(pattern);\n}\n\n/**\n * Validates a value against a numeric range pattern.\n */\nexport function validateRangePattern(actualValue: JsonValue, pattern: string): boolean {\n const numValue = Number(actualValue);\n if (Number.isNaN(numValue)) {\n return false;\n }\n\n // Handle range like \"10 - 50\" or \"10-50\"\n const rangeMatch = pattern.match(/^([\\d.-]+)\\s*-\\s*([\\d.-]+)$/);\n if (rangeMatch) {\n const min = Number(rangeMatch[1]);\n const max = Number(rangeMatch[2]);\n return numValue >= min && numValue <= max;\n }\n\n // Handle comma-separated conditions like \">= 0, <= 100\"\n const conditions = pattern.split(',').map((c) => c.trim());\n return conditions.every((condition) => {\n const match = condition.match(/^(>=?|<=?|>|<)\\s*([\\d.-]+)$/);\n if (!match) {\n return false;\n }\n\n const operator = match[1];\n const targetValue = Number(match[2]);\n\n switch (operator) {\n case '>':\n return numValue > targetValue;\n case '>=':\n return numValue >= targetValue;\n case '<':\n return numValue < targetValue;\n case '<=':\n return numValue <= targetValue;\n default:\n return false;\n }\n });\n}\n\n/**\n * Checks if a key is an array selector.\n */\nexport function isArraySelector(key: string): boolean {\n return /^\\[.*\\]$/.test(key) || key === '*' || key.startsWith('slice(');\n}\n\n/**\n * Gets a value from an array using a selector.\n */\nexport function getArrayValue(array: JsonValue[], selector: string): JsonValue {\n if (selector === '*') {\n return array;\n }\n\n if (selector.startsWith('[') && selector.endsWith(']')) {\n const index = selector.slice(1, -1);\n if (index === '*') {\n return array;\n }\n\n const numIndex = Number(index);\n if (!Number.isNaN(numIndex)) {\n return numIndex >= 0 ? array[numIndex] : array[array.length + numIndex];\n }\n }\n\n if (selector.startsWith('slice(')) {\n const match = selector.match(/slice\\((\\d+)(?:,(\\d+))?\\)/);\n if (match) {\n const start = Number(match[1]);\n const end = match[2] ? Number(match[2]) : undefined;\n return array.slice(start, end);\n }\n }\n\n return undefined as unknown as JsonValue;\n}\n",
|
|
44
|
+
"/**\n * Response post-processing: validation and snapshot testing.\n */\n\nimport type { SnapshotManager } from '../../snapshot/snapshot-manager';\nimport type { ExecutionResult, RequestConfig, SnapshotConfig } from '../../types/config';\nimport { validateResponse } from '../validation';\n\nexport interface PostProcessOptions {\n snapshotManager?: SnapshotManager;\n snapshotConfig?: SnapshotConfig | null;\n}\n\n/**\n * Applies validation and snapshot testing to an execution result.\n * Mutates the result in place and returns it for chaining.\n */\nexport async function postProcessResult(\n result: ExecutionResult,\n config: RequestConfig,\n options: PostProcessOptions = {},\n): Promise<ExecutionResult> {\n // Apply validation if configured\n if (result.success && config.expect) {\n const validationResult = validateResponse(result, config.expect);\n if (!validationResult.success) {\n result.success = false;\n result.error = validationResult.error;\n }\n }\n\n // Snapshot testing\n const { snapshotManager, snapshotConfig } = options;\n if (snapshotManager && snapshotConfig && config.sourceFile && result.success) {\n const snapshotResult = await snapshotManager.compareAndUpdate(\n config.sourceFile,\n config.name || 'Request',\n result,\n snapshotConfig,\n );\n result.snapshotResult = snapshotResult;\n\n if (!snapshotResult.match && !snapshotResult.updated) {\n result.success = false;\n if (!result.error) {\n result.error = 'Snapshot mismatch';\n }\n }\n }\n\n return result;\n}\n",
|
|
45
|
+
"/**\n * Retry execution logic with exponential backoff.\n */\n\nimport type { RetryConfig, RetryOptions, RetryResult } from './types';\n\n/**\n * Calculates delay for a retry attempt with exponential backoff.\n */\nexport function calculateBackoffDelay(\n attempt: number,\n baseDelay: number,\n backoffMultiplier: number,\n): number {\n // attempt is 1-indexed (1st retry, 2nd retry, etc.)\n return baseDelay * backoffMultiplier ** (attempt - 1);\n}\n\n/**\n * Executes an async operation with retry logic.\n *\n * @param operation - The async operation to execute\n * @param options - Retry options\n * @returns RetryResult with value, success status, and attempt count\n */\nexport async function withRetry<T>(\n operation: () => Promise<T>,\n options: RetryOptions<T> = {},\n): Promise<RetryResult<T>> {\n const { config, shouldRetry, onRetry } = options;\n const maxAttempts = (config?.count ?? 0) + 1;\n const delay = config?.delay ?? 0;\n const backoff = config?.backoff ?? 1;\n\n let attempt = 0;\n let lastError: string | undefined;\n\n while (attempt < maxAttempts) {\n // Log retry attempt (not the first attempt)\n if (attempt > 0 && onRetry) {\n onRetry(attempt, config?.count ?? 0);\n }\n\n // Wait before retry (not the first attempt)\n if (attempt > 0 && delay > 0) {\n const waitTime = calculateBackoffDelay(attempt, delay, backoff);\n await Bun.sleep(waitTime);\n }\n\n attempt++;\n\n try {\n const result = await operation();\n\n // Check if we should retry based on result\n if (shouldRetry?.(result)) {\n lastError = 'Operation returned retriable result';\n continue;\n }\n\n return {\n value: result,\n success: true,\n attempts: attempt,\n };\n } catch (error) {\n lastError = error instanceof Error ? error.message : String(error);\n }\n }\n\n return {\n success: false,\n attempts: attempt,\n error: lastError,\n };\n}\n\n/**\n * Creates retry options from a retry config.\n */\nexport function createRetryOptions<T>(\n config?: RetryConfig,\n shouldRetry?: (result: T) => boolean,\n onRetry?: (attempt: number, maxAttempts: number) => void,\n): RetryOptions<T> {\n return { config, shouldRetry, onRetry };\n}\n",
|
|
46
|
+
"import * as path from 'node:path';\nimport type {\n ExecutionResult,\n GlobalSnapshotConfig,\n JsonValue,\n Snapshot,\n SnapshotCompareResult,\n SnapshotConfig,\n SnapshotFile,\n} from '../types/config';\nimport { SnapshotDiffer } from './snapshot-differ';\n\nconst SNAPSHOT_VERSION = 1;\nconst DEFAULT_SNAPSHOT_DIR = '__snapshots__';\n\n/**\n * Manages snapshot files: reading, writing, comparing, and updating.\n */\nexport class SnapshotManager {\n private snapshotDir: string;\n private globalConfig: GlobalSnapshotConfig;\n private writeLocks: Map<string, Promise<void>> = new Map();\n\n constructor(globalConfig: GlobalSnapshotConfig = {}) {\n this.globalConfig = globalConfig;\n this.snapshotDir = globalConfig.dir || DEFAULT_SNAPSHOT_DIR;\n }\n\n /**\n * Gets the snapshot file path for a YAML file.\n */\n getSnapshotPath(yamlPath: string): string {\n const dir = path.dirname(yamlPath);\n const basename = path.basename(yamlPath, path.extname(yamlPath));\n return path.join(dir, this.snapshotDir, `${basename}.snap.json`);\n }\n\n /**\n * Loads snapshot file for a YAML file.\n */\n async load(yamlPath: string): Promise<SnapshotFile | null> {\n const snapshotPath = this.getSnapshotPath(yamlPath);\n try {\n const file = Bun.file(snapshotPath);\n if (!(await file.exists())) {\n return null;\n }\n const content = await file.text();\n return JSON.parse(content) as SnapshotFile;\n } catch {\n return null;\n }\n }\n\n /**\n * Saves snapshot file with write queue for parallel safety.\n */\n async save(yamlPath: string, data: SnapshotFile): Promise<void> {\n const snapshotPath = this.getSnapshotPath(yamlPath);\n\n // Queue writes to prevent race conditions\n const existingLock = this.writeLocks.get(snapshotPath);\n const writePromise = (async () => {\n if (existingLock) {\n await existingLock;\n }\n\n // Ensure directory exists\n const dir = path.dirname(snapshotPath);\n const fs = await import('node:fs/promises');\n await fs.mkdir(dir, { recursive: true });\n\n // Write with pretty formatting\n const content = JSON.stringify(data, null, 2);\n await Bun.write(snapshotPath, content);\n })();\n\n this.writeLocks.set(snapshotPath, writePromise);\n await writePromise;\n this.writeLocks.delete(snapshotPath);\n }\n\n /**\n * Gets a single snapshot by request name.\n */\n async get(yamlPath: string, requestName: string): Promise<Snapshot | null> {\n const file = await this.load(yamlPath);\n return file?.snapshots[requestName] || null;\n }\n\n /**\n * Creates a snapshot from execution result.\n */\n createSnapshot(result: ExecutionResult, config: SnapshotConfig): Snapshot {\n const include = config.include || ['body'];\n const snapshot: Snapshot = {\n hash: '',\n updatedAt: new Date().toISOString(),\n };\n\n if (include.includes('status') && result.status !== undefined) {\n snapshot.status = result.status;\n }\n\n if (include.includes('headers') && result.headers) {\n // Normalize headers: lowercase keys, sorted\n snapshot.headers = this.normalizeHeaders(result.headers);\n }\n\n if (include.includes('body') && result.body !== undefined) {\n snapshot.body = result.body;\n }\n\n // Generate hash from content\n snapshot.hash = this.hash(snapshot);\n\n return snapshot;\n }\n\n /**\n * Normalizes headers for consistent comparison.\n */\n private normalizeHeaders(headers: Record<string, string>): Record<string, string> {\n const normalized: Record<string, string> = {};\n const sortedKeys = Object.keys(headers).sort();\n for (const key of sortedKeys) {\n normalized[key.toLowerCase()] = headers[key];\n }\n return normalized;\n }\n\n /**\n * Generates a hash for snapshot content.\n */\n hash(content: unknown): string {\n const str = JSON.stringify(content);\n const hasher = new Bun.CryptoHasher('md5');\n hasher.update(str);\n return hasher.digest('hex').slice(0, 8);\n }\n\n /**\n * Compares execution result against stored snapshot and optionally updates.\n */\n async compareAndUpdate(\n yamlPath: string,\n requestName: string,\n result: ExecutionResult,\n config: SnapshotConfig,\n ): Promise<SnapshotCompareResult> {\n const snapshotName = config.name || requestName;\n const existingSnapshot = await this.get(yamlPath, snapshotName);\n const newSnapshot = this.createSnapshot(result, config);\n\n // No existing snapshot\n if (!existingSnapshot) {\n if (this.globalConfig.ci) {\n // CI mode: fail on missing snapshot\n return {\n match: false,\n isNew: true,\n updated: false,\n differences: [\n {\n path: '',\n expected: 'snapshot',\n received: 'none',\n type: 'removed',\n },\n ],\n };\n }\n\n // Create new snapshot\n await this.updateSnapshot(yamlPath, snapshotName, newSnapshot);\n return {\n match: true,\n isNew: true,\n updated: true,\n differences: [],\n };\n }\n\n // Compare snapshots\n const differ = new SnapshotDiffer(config);\n const diffResult = differ.compare(existingSnapshot, newSnapshot);\n\n if (diffResult.match) {\n return {\n match: true,\n isNew: false,\n updated: false,\n differences: [],\n };\n }\n\n // Handle update modes\n const updateMode = this.globalConfig.updateMode || 'none';\n if (updateMode === 'all' || updateMode === 'failing') {\n await this.updateSnapshot(yamlPath, snapshotName, newSnapshot);\n return {\n match: true,\n isNew: false,\n updated: true,\n differences: diffResult.differences,\n };\n }\n\n return {\n match: false,\n isNew: false,\n updated: false,\n differences: diffResult.differences,\n };\n }\n\n /**\n * Updates a single snapshot in the file.\n */\n private async updateSnapshot(\n yamlPath: string,\n snapshotName: string,\n snapshot: Snapshot,\n ): Promise<void> {\n let file = await this.load(yamlPath);\n if (!file) {\n file = {\n version: SNAPSHOT_VERSION,\n snapshots: {},\n };\n }\n\n file.snapshots[snapshotName] = snapshot;\n await this.save(yamlPath, file);\n }\n\n /**\n * Merges request-level config with global config.\n */\n static mergeConfig(\n globalConfig: GlobalSnapshotConfig | undefined,\n requestConfig: SnapshotConfig | boolean | undefined,\n ): SnapshotConfig | null {\n // Not enabled\n if (!requestConfig && !globalConfig?.enabled) {\n return null;\n }\n\n // Simple boolean enable\n if (requestConfig === true) {\n return {\n enabled: true,\n include: globalConfig?.include || ['body'],\n exclude: globalConfig?.exclude || [],\n match: globalConfig?.match || {},\n };\n }\n\n // Detailed config\n if (typeof requestConfig === 'object' && requestConfig.enabled !== false) {\n return {\n enabled: true,\n name: requestConfig.name,\n include: requestConfig.include || globalConfig?.include || ['body'],\n exclude: [...(globalConfig?.exclude || []), ...(requestConfig.exclude || [])],\n match: { ...(globalConfig?.match || {}), ...(requestConfig.match || {}) },\n };\n }\n\n // Global enabled but request not specified\n if (globalConfig?.enabled && requestConfig === undefined) {\n return {\n enabled: true,\n include: globalConfig.include || ['body'],\n exclude: globalConfig.exclude || [],\n match: globalConfig.match || {},\n };\n }\n\n return null;\n }\n}\n\n/**\n * Extracts body content for snapshot, applying exclusions.\n */\nexport function filterSnapshotBody(body: JsonValue, exclude: string[]): JsonValue {\n if (body === null || typeof body !== 'object') {\n return body;\n }\n\n const bodyExcludes = exclude.filter((p) => p.startsWith('body.')).map((p) => p.slice(5)); // Remove 'body.' prefix\n\n if (bodyExcludes.length === 0) {\n return body;\n }\n\n return filterObject(body, bodyExcludes, '');\n}\n\nfunction filterObject(obj: JsonValue, excludes: string[], currentPath: string): JsonValue {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item, index) => {\n const itemPath = currentPath ? `${currentPath}[${index}]` : `[${index}]`;\n return filterObject(item, excludes, itemPath);\n });\n }\n\n const result: Record<string, JsonValue> = {};\n for (const [key, value] of Object.entries(obj)) {\n const fullPath = currentPath ? `${currentPath}.${key}` : key;\n\n // Check if this path should be excluded\n const shouldExclude = excludes.some((pattern) => {\n // Exact match\n if (pattern === fullPath) {\n return true;\n }\n // Wildcard match (e.g., '*.timestamp' matches 'user.timestamp')\n if (pattern.startsWith('*.')) {\n const suffix = pattern.slice(2);\n return fullPath.endsWith(`.${suffix}`) || fullPath === suffix;\n }\n // Array wildcard (e.g., '[*].id')\n if (pattern.includes('[*]')) {\n const regex = new RegExp(`^${pattern.replace(/\\[\\*\\]/g, '\\\\[\\\\d+\\\\]')}$`);\n return regex.test(fullPath);\n }\n return false;\n });\n\n if (!shouldExclude) {\n result[key] = filterObject(value, excludes, fullPath);\n }\n }\n\n return result;\n}\n",
|
|
47
|
+
"import type { JsonValue, Snapshot, SnapshotConfig, SnapshotDiff } from '../types/config';\n\ninterface DiffResult {\n match: boolean;\n differences: SnapshotDiff[];\n}\n\n/**\n * Compares snapshots with support for exclusions, wildcards, and regex patterns.\n */\nexport class SnapshotDiffer {\n private excludePaths: Set<string>;\n private matchRules: Map<string, string>;\n\n constructor(config: SnapshotConfig) {\n this.excludePaths = new Set(config.exclude || []);\n this.matchRules = new Map(Object.entries(config.match || {}));\n }\n\n /**\n * Compares two snapshots and returns differences.\n */\n compare(expected: Snapshot, received: Snapshot): DiffResult {\n const differences: SnapshotDiff[] = [];\n\n // Compare status\n if (expected.status !== undefined || received.status !== undefined) {\n if (expected.status !== received.status && !this.isExcluded('status')) {\n differences.push({\n path: 'status',\n expected: expected.status,\n received: received.status,\n type: 'changed',\n });\n }\n }\n\n // Compare headers\n if (expected.headers || received.headers) {\n const headerDiffs = this.compareObjects(\n expected.headers || {},\n received.headers || {},\n 'headers',\n );\n differences.push(...headerDiffs);\n }\n\n // Compare body\n if (expected.body !== undefined || received.body !== undefined) {\n const bodyDiffs = this.deepCompare(expected.body, received.body, 'body');\n differences.push(...bodyDiffs);\n }\n\n return {\n match: differences.length === 0,\n differences,\n };\n }\n\n /**\n * Deep comparison of two values with path tracking.\n */\n deepCompare(expected: unknown, received: unknown, path: string): SnapshotDiff[] {\n // Check if path is excluded\n if (this.isExcluded(path)) {\n return [];\n }\n\n // Check match rules (wildcards, regex)\n if (this.matchesRule(path, received)) {\n return [];\n }\n\n // Both null/undefined\n if (expected === null && received === null) {\n return [];\n }\n if (expected === undefined && received === undefined) {\n return [];\n }\n\n // Type mismatch\n const expectedType = this.getType(expected);\n const receivedType = this.getType(received);\n if (expectedType !== receivedType) {\n return [\n {\n path,\n expected,\n received,\n type: 'type_mismatch',\n },\n ];\n }\n\n // Primitives\n if (expectedType !== 'object' && expectedType !== 'array') {\n if (expected !== received) {\n return [\n {\n path,\n expected,\n received,\n type: 'changed',\n },\n ];\n }\n return [];\n }\n\n // Arrays\n if (expectedType === 'array') {\n return this.compareArrays(expected as JsonValue[], received as JsonValue[], path);\n }\n\n // Objects\n return this.compareObjects(\n expected as Record<string, unknown>,\n received as Record<string, unknown>,\n path,\n );\n }\n\n /**\n * Compares two arrays.\n */\n private compareArrays(\n expected: JsonValue[],\n received: JsonValue[],\n path: string,\n ): SnapshotDiff[] {\n const differences: SnapshotDiff[] = [];\n\n // Check length difference\n const maxLen = Math.max(expected.length, received.length);\n\n for (let i = 0; i < maxLen; i++) {\n const itemPath = `${path}[${i}]`;\n\n if (i >= expected.length) {\n // Added item\n if (!this.isExcluded(itemPath)) {\n differences.push({\n path: itemPath,\n expected: undefined,\n received: received[i],\n type: 'added',\n });\n }\n } else if (i >= received.length) {\n // Removed item\n if (!this.isExcluded(itemPath)) {\n differences.push({\n path: itemPath,\n expected: expected[i],\n received: undefined,\n type: 'removed',\n });\n }\n } else {\n // Compare items\n const itemDiffs = this.deepCompare(expected[i], received[i], itemPath);\n differences.push(...itemDiffs);\n }\n }\n\n return differences;\n }\n\n /**\n * Compares two objects.\n */\n private compareObjects(\n expected: Record<string, unknown>,\n received: Record<string, unknown>,\n path: string,\n ): SnapshotDiff[] {\n const differences: SnapshotDiff[] = [];\n const allKeys = new Set([...Object.keys(expected), ...Object.keys(received)]);\n\n for (const key of allKeys) {\n const keyPath = path ? `${path}.${key}` : key;\n const hasExpected = key in expected;\n const hasReceived = key in received;\n\n if (!hasExpected && hasReceived) {\n // Added key\n if (!this.isExcluded(keyPath)) {\n differences.push({\n path: keyPath,\n expected: undefined,\n received: received[key],\n type: 'added',\n });\n }\n } else if (hasExpected && !hasReceived) {\n // Removed key\n if (!this.isExcluded(keyPath)) {\n differences.push({\n path: keyPath,\n expected: expected[key],\n received: undefined,\n type: 'removed',\n });\n }\n } else {\n // Compare values\n const keyDiffs = this.deepCompare(expected[key], received[key], keyPath);\n differences.push(...keyDiffs);\n }\n }\n\n return differences;\n }\n\n /**\n * Checks if a path should be excluded from comparison.\n */\n isExcluded(path: string): boolean {\n // Exact match\n if (this.excludePaths.has(path)) {\n return true;\n }\n\n for (const pattern of this.excludePaths) {\n // Wildcard prefix (e.g., '*.timestamp')\n if (pattern.startsWith('*.')) {\n const suffix = pattern.slice(2);\n if (path.endsWith(`.${suffix}`)) {\n return true;\n }\n // Also match root level (e.g., 'timestamp' matches '*.timestamp')\n const lastPart = path.split('.').pop();\n if (lastPart === suffix) {\n return true;\n }\n }\n\n // Array wildcard (e.g., 'body[*].id')\n if (pattern.includes('[*]')) {\n const regex = new RegExp(\n `^${pattern.replace(/\\[\\*\\]/g, '\\\\[\\\\d+\\\\]').replace(/\\./g, '\\\\.')}$`,\n );\n if (regex.test(path)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Checks if a value matches a custom rule for its path.\n */\n matchesRule(path: string, value: unknown): boolean {\n const rule = this.matchRules.get(path);\n if (!rule) {\n return false;\n }\n\n // Wildcard: accept any value\n if (rule === '*') {\n return true;\n }\n\n // Regex pattern\n if (rule.startsWith('regex:')) {\n const pattern = rule.slice(6);\n try {\n const regex = new RegExp(pattern);\n return regex.test(String(value));\n } catch {\n return false;\n }\n }\n\n return false;\n }\n\n /**\n * Gets the type of a value for comparison.\n */\n private getType(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n return typeof value;\n }\n}\n",
|
|
48
|
+
"import type { ExecutionResult, ResponseStoreContext, StoreConfig } from '../types/config';\n\n/**\n * Extracts a value from an object using a dot-notation path.\n * Supports paths like: \"body.id\", \"body.data.token\", \"headers.content-type\", \"status\"\n *\n * @param obj - The object to extract from\n * @param path - Dot-notation path to the value\n * @returns The extracted value or undefined if not found\n */\nexport function getValueByPath(obj: unknown, path: string): unknown {\n const parts = path.split('.');\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) {\n return undefined;\n }\n\n if (typeof current !== 'object') {\n return undefined;\n }\n\n // Handle array index access like \"items.0.id\" or \"items[0].id\"\n const arrayMatch = part.match(/^(\\w+)\\[(\\d+)\\]$/);\n if (arrayMatch) {\n const [, key, indexStr] = arrayMatch;\n const index = Number.parseInt(indexStr, 10);\n current = (current as Record<string, unknown>)[key];\n if (Array.isArray(current)) {\n current = current[index];\n } else {\n return undefined;\n }\n } else if (/^\\d+$/.test(part) && Array.isArray(current)) {\n // Direct numeric index for arrays\n current = current[Number.parseInt(part, 10)];\n } else {\n current = (current as Record<string, unknown>)[part];\n }\n }\n\n return current;\n}\n\n/**\n * Converts a value to a string for storage.\n * Objects and arrays are JSON stringified.\n */\nexport function valueToString(value: unknown): string {\n if (value === undefined || value === null) {\n return '';\n }\n if (typeof value === 'string') {\n return value;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n return JSON.stringify(value);\n}\n\n/**\n * Extracts values from an execution result based on the store configuration.\n *\n * @param result - The execution result to extract from\n * @param storeConfig - Configuration mapping variable names to JSON paths\n * @returns Object containing the extracted values as strings\n */\nexport function extractStoreValues(\n result: ExecutionResult,\n storeConfig: StoreConfig,\n): ResponseStoreContext {\n const extracted: ResponseStoreContext = {};\n\n // Build an object that represents the full response structure\n const responseObj: Record<string, unknown> = {\n status: result.status,\n headers: result.headers || {},\n body: result.body,\n metrics: result.metrics,\n };\n\n for (const [varName, path] of Object.entries(storeConfig)) {\n const value = getValueByPath(responseObj, path);\n extracted[varName] = valueToString(value);\n }\n\n return extracted;\n}\n\n/**\n * Creates a new response store context.\n */\nexport function createStoreContext(): ResponseStoreContext {\n return {};\n}\n\n/**\n * Merges new values into an existing store context.\n * New values override existing ones with the same key.\n */\nexport function mergeStoreContext(\n existing: ResponseStoreContext,\n newValues: ResponseStoreContext,\n): ResponseStoreContext {\n return { ...existing, ...newValues };\n}\n",
|
|
49
|
+
"import type {\n ConditionExpression,\n ConditionOperator,\n ResponseStoreContext,\n WhenCondition,\n} from '../types/config';\nimport { getValueByPath, valueToString } from './response-store';\n\n/**\n * Result of evaluating a condition.\n */\nexport interface ConditionResult {\n shouldRun: boolean;\n reason?: string;\n}\n\n/**\n * Parses a string shorthand condition into a ConditionExpression.\n * Supports formats like:\n * - \"store.status == 200\"\n * - \"store.userId exists\"\n * - \"store.body.type contains user\"\n * - \"store.version >= 2\"\n *\n * @param condition - String condition to parse\n * @returns Parsed ConditionExpression or null if invalid\n */\nexport function parseStringCondition(condition: string): ConditionExpression | null {\n const trimmed = condition.trim();\n\n // Check for exists/not-exists operators first (unary)\n const existsMatch = trimmed.match(/^(.+?)\\s+(exists|not-exists)$/i);\n if (existsMatch) {\n return {\n left: existsMatch[1].trim(),\n operator: existsMatch[2].toLowerCase() as ConditionOperator,\n };\n }\n\n // Binary operators pattern\n const operatorPattern = /^(.+?)\\s*(==|!=|>=|<=|>|<|contains|matches)\\s*(.+)$/i;\n const match = trimmed.match(operatorPattern);\n\n if (!match) {\n return null;\n }\n\n const [, left, operator, right] = match;\n const rightValue = parseRightValue(right.trim());\n\n return {\n left: left.trim(),\n operator: operator.toLowerCase() as ConditionOperator,\n right: rightValue,\n };\n}\n\n/**\n * Parses the right-hand value, converting to appropriate type.\n */\nfunction parseRightValue(value: string): string | number | boolean {\n // Boolean\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n\n // Number\n const num = Number(value);\n if (!Number.isNaN(num) && value !== '') {\n return num;\n }\n\n // String - remove quotes if present\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n\n return value;\n}\n\n/**\n * Gets a value from the store context using a path.\n * Handles \"store.x\" prefix by stripping it.\n */\nfunction getStoreValue(path: string, context: ResponseStoreContext): unknown {\n // Strip \"store.\" prefix if present\n const normalizedPath = path.startsWith('store.') ? path.slice(6) : path;\n\n // First check if it's a direct key in context\n if (normalizedPath in context) {\n const value = context[normalizedPath];\n // Try to parse JSON if it looks like an object/array\n if (value.startsWith('{') || value.startsWith('[')) {\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n // Try to parse as number\n const num = Number(value);\n if (!Number.isNaN(num) && value !== '') {\n return num;\n }\n // Try to parse as boolean\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n return value;\n }\n\n // Handle nested paths like \"body.data.id\" where context has \"body\" as JSON string\n const parts = normalizedPath.split('.');\n const rootKey = parts[0];\n\n if (rootKey in context) {\n const rootValue = context[rootKey];\n // Try to parse as JSON and navigate\n try {\n const parsed = JSON.parse(rootValue);\n return getValueByPath(parsed, parts.slice(1).join('.'));\n } catch {\n // Not JSON, can't navigate further\n return undefined;\n }\n }\n\n return undefined;\n}\n\n/**\n * Compares two values based on case sensitivity setting.\n */\nfunction compareStrings(a: string, b: string, caseSensitive: boolean): boolean {\n if (caseSensitive) {\n return a === b;\n }\n return a.toLowerCase() === b.toLowerCase();\n}\n\n/**\n * Evaluates a single condition expression against the store context.\n */\nexport function evaluateExpression(\n expr: ConditionExpression,\n context: ResponseStoreContext,\n): { passed: boolean; description: string } {\n const leftValue = getStoreValue(expr.left, context);\n const caseSensitive = expr.caseSensitive ?? false;\n\n const formatValue = (v: unknown): string => {\n if (v === undefined) {\n return 'undefined';\n }\n if (v === null) {\n return 'null';\n }\n if (typeof v === 'string') {\n return `\"${v}\"`;\n }\n return String(v);\n };\n\n const description = `${expr.left} ${expr.operator}${expr.right !== undefined ? ` ${formatValue(expr.right)}` : ''}`;\n\n switch (expr.operator) {\n case 'exists': {\n const passed = leftValue !== undefined && leftValue !== null && leftValue !== '';\n return { passed, description };\n }\n\n case 'not-exists': {\n const passed = leftValue === undefined || leftValue === null || leftValue === '';\n return { passed, description };\n }\n\n case '==': {\n let passed: boolean;\n if (typeof leftValue === 'string' && typeof expr.right === 'string') {\n passed = compareStrings(leftValue, expr.right, caseSensitive);\n } else {\n // biome-ignore lint/suspicious/noDoubleEquals: intentional loose equality for type coercion\n passed = leftValue == expr.right;\n }\n return { passed, description };\n }\n\n case '!=': {\n let passed: boolean;\n if (typeof leftValue === 'string' && typeof expr.right === 'string') {\n passed = !compareStrings(leftValue, expr.right, caseSensitive);\n } else {\n // biome-ignore lint/suspicious/noDoubleEquals: intentional loose equality for type coercion\n passed = leftValue != expr.right;\n }\n return { passed, description };\n }\n\n case '>': {\n const passed = Number(leftValue) > Number(expr.right);\n return { passed, description };\n }\n\n case '<': {\n const passed = Number(leftValue) < Number(expr.right);\n return { passed, description };\n }\n\n case '>=': {\n const passed = Number(leftValue) >= Number(expr.right);\n return { passed, description };\n }\n\n case '<=': {\n const passed = Number(leftValue) <= Number(expr.right);\n return { passed, description };\n }\n\n case 'contains': {\n const leftStr = valueToString(leftValue);\n const rightStr = String(expr.right ?? '');\n const passed = caseSensitive\n ? leftStr.includes(rightStr)\n : leftStr.toLowerCase().includes(rightStr.toLowerCase());\n return { passed, description };\n }\n\n case 'matches': {\n const leftStr = valueToString(leftValue);\n const pattern = String(expr.right ?? '');\n try {\n const flags = caseSensitive ? '' : 'i';\n const regex = new RegExp(pattern, flags);\n const passed = regex.test(leftStr);\n return { passed, description };\n } catch {\n // Invalid regex pattern\n return { passed: false, description: `${description} (invalid regex)` };\n }\n }\n\n default:\n return { passed: false, description: `unknown operator: ${expr.operator}` };\n }\n}\n\n/**\n * Evaluates a WhenCondition against the store context.\n *\n * @param condition - The condition to evaluate\n * @param context - The store context with values from previous requests\n * @returns Result indicating whether the request should run\n */\nexport function evaluateCondition(\n condition: WhenCondition | string,\n context: ResponseStoreContext,\n): ConditionResult {\n // Handle string shorthand\n if (typeof condition === 'string') {\n const parsed = parseStringCondition(condition);\n if (!parsed) {\n return { shouldRun: false, reason: `invalid condition syntax: \"${condition}\"` };\n }\n const result = evaluateExpression(parsed, context);\n return {\n shouldRun: result.passed,\n reason: result.passed ? undefined : `condition not met: ${result.description}`,\n };\n }\n\n // Handle compound \"all\" condition (AND logic with short-circuit)\n if (condition.all && condition.all.length > 0) {\n for (const expr of condition.all) {\n const result = evaluateExpression(expr, context);\n if (!result.passed) {\n return {\n shouldRun: false,\n reason: `condition not met: ${result.description}`,\n };\n }\n }\n return { shouldRun: true };\n }\n\n // Handle compound \"any\" condition (OR logic with short-circuit)\n if (condition.any && condition.any.length > 0) {\n const descriptions: string[] = [];\n for (const expr of condition.any) {\n const result = evaluateExpression(expr, context);\n if (result.passed) {\n return { shouldRun: true };\n }\n descriptions.push(result.description);\n }\n return {\n shouldRun: false,\n reason: `no conditions met: ${descriptions.join(', ')}`,\n };\n }\n\n // Handle single condition (inline left/operator/right)\n if (condition.left && condition.operator) {\n const expr: ConditionExpression = {\n left: condition.left,\n operator: condition.operator,\n right: condition.right,\n caseSensitive: condition.caseSensitive,\n };\n const result = evaluateExpression(expr, context);\n return {\n shouldRun: result.passed,\n reason: result.passed ? undefined : `condition not met: ${result.description}`,\n };\n }\n\n // No valid condition found - default to run\n return { shouldRun: true };\n}\n",
|
|
50
|
+
"import {\n buildCurlArgs,\n type CurlMetrics,\n createBatchMarker,\n extractBatchMetrics,\n formatArgsForDisplay,\n getStatusCode,\n isSuccessStatus,\n parseMetrics,\n parseResponseBody,\n} from '../core/curl';\nimport type { ConnectionPoolConfig, ExecutionResult, RequestConfig } from '../types/config';\n\ninterface BatchedRequest {\n index: number;\n config: RequestConfig;\n}\n\ninterface HostGroup {\n host: string;\n requests: BatchedRequest[];\n}\n\n/**\n * Executes curl requests with TCP connection pooling and HTTP/2 multiplexing.\n * Groups requests by host and batches them into single curl processes.\n * Uses shared argument building logic from core/curl.\n */\nexport class PooledCurlExecutor {\n private poolConfig: ConnectionPoolConfig;\n\n constructor(poolConfig: ConnectionPoolConfig = {}) {\n this.poolConfig = {\n enabled: true,\n maxStreamsPerHost: 10,\n keepaliveTime: 60,\n connectTimeout: 30,\n ...poolConfig,\n };\n }\n\n /**\n * Extracts host key (scheme://host:port) from URL for grouping.\n */\n private getHostKey(url: string): string {\n try {\n const parsed = new URL(url);\n return `${parsed.protocol}//${parsed.host}`;\n } catch {\n return url;\n }\n }\n\n /**\n * Groups requests by their host for batched execution.\n */\n groupRequestsByHost(requests: RequestConfig[]): HostGroup[] {\n const groups = new Map<string, BatchedRequest[]>();\n\n requests.forEach((config, index) => {\n const hostKey = this.getHostKey(config.url);\n const existing = groups.get(hostKey) || [];\n existing.push({ index, config });\n groups.set(hostKey, existing);\n });\n\n return Array.from(groups.entries()).map(([host, reqs]) => ({\n host,\n requests: reqs,\n }));\n }\n\n /**\n * Builds curl args for a single request within a batch.\n * Uses shared buildCurlArgs with batch-specific marker.\n */\n private buildRequestArgs(config: RequestConfig, requestIndex: number): string[] {\n const { args, url } = buildCurlArgs(config, {\n writeOutMarker: createBatchMarker(requestIndex),\n includeSilentFlags: false, // Added at batch level\n includeHttp2Flag: false, // Added at batch level\n includeOutputFlag: false, // Not used in batching\n });\n\n args.push(url);\n return args;\n }\n\n /**\n * Builds a batched curl command for a host group.\n * Uses -Z for parallel execution and --next to separate requests.\n */\n buildBatchedCommand(group: HostGroup): string[] {\n const args: string[] = [];\n\n // Global flags for connection pooling\n args.push('-Z'); // Enable parallel transfers\n args.push('--parallel-max', this.poolConfig.maxStreamsPerHost!.toString());\n args.push('--http2'); // Enable HTTP/2 multiplexing\n args.push('--keepalive-time', this.poolConfig.keepaliveTime!.toString());\n args.push('--connect-timeout', this.poolConfig.connectTimeout!.toString());\n args.push('-s', '-S'); // Silent but show errors\n\n // Add each request with --next separator\n group.requests.forEach((req, i) => {\n if (i > 0) {\n args.push('--next');\n }\n const requestArgs = this.buildRequestArgs(req.config, req.index);\n args.push(...requestArgs);\n });\n\n return args;\n }\n\n /**\n * Parses batched curl output into individual results.\n */\n parseBatchedOutput(\n stdout: string,\n stderr: string,\n group: HostGroup,\n exitCode: number,\n ): Map<number, ExecutionResult> {\n const results = new Map<number, ExecutionResult>();\n\n for (const req of group.requests) {\n const { found, metricsJson, startIdx } = extractBatchMetrics(stdout, req.index);\n\n if (!found) {\n results.set(req.index, {\n request: req.config,\n success: false,\n error: stderr || `Request failed (exit code: ${exitCode})`,\n metrics: { duration: 0 },\n });\n continue;\n }\n\n let rawMetrics: CurlMetrics = {};\n try {\n rawMetrics = JSON.parse(metricsJson);\n } catch {\n // Ignore parse errors\n }\n\n // Extract body: everything before the marker for this request\n const bodyEnd = startIdx;\n let bodyStart = 0;\n\n // Find the end of the previous request's marker (if any)\n for (const otherReq of group.requests) {\n if (otherReq.index === req.index) {\n continue;\n }\n const otherEnd = `__CURL_BATCH_${otherReq.index}_END__`;\n const otherEndIdx = stdout.indexOf(otherEnd);\n if (\n otherEndIdx !== -1 &&\n otherEndIdx < bodyEnd &&\n otherEndIdx + otherEnd.length > bodyStart\n ) {\n bodyStart = otherEndIdx + otherEnd.length;\n }\n }\n\n const body: string | undefined = stdout.substring(bodyStart, bodyEnd).trim();\n const statusCode = getStatusCode(rawMetrics);\n const metrics = parseMetrics(rawMetrics);\n\n results.set(req.index, {\n request: req.config,\n success: isSuccessStatus(statusCode),\n status: statusCode,\n body: parseResponseBody(body),\n metrics,\n });\n }\n\n return results;\n }\n\n /**\n * Executes a batched curl command for a host group.\n */\n async executeBatch(group: HostGroup): Promise<Map<number, ExecutionResult>> {\n const args = this.buildBatchedCommand(group);\n\n try {\n const proc = Bun.spawn(['curl', ...args], {\n stdout: 'pipe',\n stderr: 'pipe',\n });\n\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n await proc.exited;\n\n return this.parseBatchedOutput(stdout, stderr, group, proc.exitCode || 0);\n } catch (error) {\n const results = new Map<number, ExecutionResult>();\n for (const req of group.requests) {\n results.set(req.index, {\n request: req.config,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n metrics: { duration: 0 },\n });\n }\n return results;\n }\n }\n\n /**\n * Executes all requests with connection pooling.\n * Groups by host and executes each group as a batch.\n */\n async executeAll(requests: RequestConfig[]): Promise<ExecutionResult[]> {\n const groups = this.groupRequestsByHost(requests);\n const allResults = new Map<number, ExecutionResult>();\n\n const batchPromises = groups.map((group) => this.executeBatch(group));\n const batchResults = await Promise.all(batchPromises);\n\n for (const resultMap of batchResults) {\n for (const [index, result] of resultMap) {\n allResults.set(index, result);\n }\n }\n\n return requests.map((_, index) => {\n return (\n allResults.get(index) || {\n request: requests[index],\n success: false,\n error: 'Request not executed',\n metrics: { duration: 0 },\n }\n );\n });\n }\n\n /**\n * Formats the batched command for display/debugging.\n */\n formatBatchedCommandForDisplay(group: HostGroup): string {\n const args = this.buildBatchedCommand(group);\n return formatArgsForDisplay(args);\n }\n}\n",
|
|
51
|
+
"import type { CurlExecutionResult } from '../core/curl';\nimport { parseResponseBody } from '../core/curl';\nimport { postProcessResult, withRetry } from '../core/execution';\nimport { YamlParser } from '../parser/yaml';\nimport { SnapshotManager } from '../snapshot/snapshot-manager';\nimport type {\n ExecutionResult,\n ExecutionSummary,\n FileAttachment,\n FormFieldValue,\n GlobalConfig,\n RequestConfig,\n ResponseStoreContext,\n SnapshotConfig,\n} from '../types/config';\nimport { evaluateCondition } from '../utils/condition-evaluator';\nimport { CurlBuilder } from '../utils/curl-builder';\nimport { Logger } from '../utils/logger';\nimport { createStoreContext, extractStoreValues } from '../utils/response-store';\nimport { PooledCurlExecutor } from './pooled-curl-executor';\n\nexport class RequestExecutor {\n private logger: Logger;\n private globalConfig: GlobalConfig;\n private snapshotManager: SnapshotManager;\n private pooledExecutor: PooledCurlExecutor | null = null;\n\n constructor(globalConfig: GlobalConfig = {}) {\n this.globalConfig = globalConfig;\n this.logger = new Logger(globalConfig.output);\n this.snapshotManager = new SnapshotManager(globalConfig.snapshot);\n\n // Initialize pooled executor if connection pooling is enabled\n if (globalConfig.connectionPool?.enabled) {\n this.pooledExecutor = new PooledCurlExecutor(globalConfig.connectionPool);\n }\n }\n\n private mergeOutputConfig(config: RequestConfig): GlobalConfig['output'] {\n // Precedence: Individual YAML file > curl-runner.yaml > CLI options > env vars > defaults\n return {\n ...this.globalConfig.output, // CLI options, env vars, and defaults (lowest priority)\n ...config.sourceOutputConfig, // Individual file's output config (highest priority)\n };\n }\n\n /**\n * Gets the effective snapshot config for a request.\n */\n private getSnapshotConfig(config: RequestConfig): SnapshotConfig | null {\n return SnapshotManager.mergeConfig(this.globalConfig.snapshot, config.snapshot);\n }\n\n /**\n * Checks if a form field value is a file attachment.\n */\n private isFileAttachment(value: FormFieldValue): value is FileAttachment {\n return typeof value === 'object' && value !== null && 'file' in value;\n }\n\n /**\n * Validates that all file attachments in formData exist.\n * Returns an error message if any file is missing, or undefined if all files exist.\n */\n private async validateFileAttachments(config: RequestConfig): Promise<string | undefined> {\n if (!config.formData) {\n return undefined;\n }\n\n const missingFiles: string[] = [];\n\n for (const [fieldName, fieldValue] of Object.entries(config.formData)) {\n if (this.isFileAttachment(fieldValue)) {\n const filePath = fieldValue.file;\n const file = Bun.file(filePath);\n const exists = await file.exists();\n if (!exists) {\n missingFiles.push(`${fieldName}: ${filePath}`);\n }\n }\n }\n\n if (missingFiles.length > 0) {\n return `File(s) not found: ${missingFiles.join(', ')}`;\n }\n\n return undefined;\n }\n\n async executeRequest(config: RequestConfig, index: number = 0): Promise<ExecutionResult> {\n const startTime = performance.now();\n\n // Create per-request logger with merged output configuration\n const outputConfig = this.mergeOutputConfig(config);\n const requestLogger = new Logger(outputConfig);\n\n requestLogger.logRequestStart(config, index);\n\n // Validate file attachments exist before executing\n const fileError = await this.validateFileAttachments(config);\n if (fileError) {\n const failedResult: ExecutionResult = {\n request: config,\n success: false,\n error: fileError,\n metrics: {\n duration: performance.now() - startTime,\n },\n };\n requestLogger.logRequestComplete(failedResult);\n return failedResult;\n }\n\n const args = CurlBuilder.buildCommand(config);\n requestLogger.logCommand(CurlBuilder.formatCommandForDisplay(args));\n\n // Dry run mode: show command and return mock result\n if (this.globalConfig.dryRun) {\n const dryRunResult: ExecutionResult = {\n request: config,\n success: true,\n dryRun: true,\n metrics: {\n duration: 0,\n },\n };\n requestLogger.logRequestComplete(dryRunResult);\n return dryRunResult;\n }\n\n // Execute curl with retry logic\n const retryResult = await withRetry<CurlExecutionResult>(() => CurlBuilder.executeCurl(args), {\n config: config.retry,\n shouldRetry: (result) => !result.success,\n onRetry: (attempt, max) => requestLogger.logRetry(attempt, max),\n });\n\n // Handle curl execution failure (all retries exhausted)\n if (!retryResult.success || !retryResult.value?.success) {\n const failedResult: ExecutionResult = {\n request: config,\n success: false,\n error: retryResult.error || retryResult.value?.error,\n metrics: {\n duration: performance.now() - startTime,\n },\n };\n requestLogger.logRequestComplete(failedResult);\n return failedResult;\n }\n\n // Process successful curl result\n const curlResult = retryResult.value;\n const executionResult = this.processCurlResult(config, curlResult, startTime);\n\n // Apply validation and snapshot testing\n await postProcessResult(executionResult, config, {\n snapshotManager: this.snapshotManager,\n snapshotConfig: this.getSnapshotConfig(config),\n });\n\n requestLogger.logRequestComplete(executionResult);\n return executionResult;\n }\n\n /**\n * Processes a successful curl result into an execution result.\n */\n private processCurlResult(\n config: RequestConfig,\n curlResult: CurlExecutionResult,\n startTime: number,\n ): ExecutionResult {\n const body = parseResponseBody(curlResult.body, curlResult.headers?.['content-type']);\n\n return {\n request: config,\n success: true,\n status: curlResult.status,\n headers: curlResult.headers,\n body,\n metrics: {\n ...curlResult.metrics,\n duration: performance.now() - startTime,\n },\n };\n }\n\n async executeSequential(requests: RequestConfig[]): Promise<ExecutionSummary> {\n const startTime = performance.now();\n const results: ExecutionResult[] = [];\n const storeContext = createStoreContext();\n\n for (let i = 0; i < requests.length; i++) {\n // Interpolate store variables before execution\n const interpolatedRequest = this.interpolateStoreVariables(requests[i], storeContext);\n\n // Evaluate `when` condition if present\n if (interpolatedRequest.when) {\n const conditionResult = evaluateCondition(interpolatedRequest.when, storeContext);\n if (!conditionResult.shouldRun) {\n const skippedResult: ExecutionResult = {\n request: interpolatedRequest,\n success: true, // Skipped requests are not failures\n skipped: true,\n skipReason: conditionResult.reason,\n };\n results.push(skippedResult);\n this.logger.logSkipped(interpolatedRequest, i + 1, conditionResult.reason);\n continue;\n }\n }\n\n const result = await this.executeRequest(interpolatedRequest, i + 1);\n results.push(result);\n\n // Store values from successful responses\n if (result.success && interpolatedRequest.store) {\n const storedValues = extractStoreValues(result, interpolatedRequest.store);\n Object.assign(storeContext, storedValues);\n this.logStoredValues(storedValues);\n }\n\n if (!result.success && !this.globalConfig.continueOnError) {\n this.logger.logError('Stopping execution due to error');\n break;\n }\n }\n\n return this.createSummary(results, performance.now() - startTime);\n }\n\n /**\n * Interpolates store variables (${store.variableName}) in a request config.\n * This is called at execution time to resolve values from previous responses.\n */\n private interpolateStoreVariables(\n request: RequestConfig,\n storeContext: ResponseStoreContext,\n ): RequestConfig {\n // Only interpolate if there are stored values\n if (Object.keys(storeContext).length === 0) {\n return request;\n }\n\n // Re-interpolate the request with store context\n // We pass empty variables since static variables were already resolved\n return YamlParser.interpolateVariables(request, {}, storeContext) as RequestConfig;\n }\n\n /**\n * Logs stored values for debugging purposes.\n */\n private logStoredValues(values: ResponseStoreContext): void {\n if (Object.keys(values).length === 0) {\n return;\n }\n\n const entries = Object.entries(values);\n for (const [key, value] of entries) {\n const displayValue = value.length > 50 ? `${value.substring(0, 50)}...` : value;\n this.logger.logInfo(`Stored: ${key} = \"${displayValue}\"`);\n }\n }\n\n async executeParallel(requests: RequestConfig[]): Promise<ExecutionSummary> {\n const startTime = performance.now();\n\n // Use pooled execution if enabled (HTTP/2 multiplexing + connection reuse)\n if (this.pooledExecutor && !this.globalConfig.dryRun) {\n return this.executePooled(requests, startTime);\n }\n\n const maxConcurrency = this.globalConfig.maxConcurrency;\n\n // If no concurrency limit, execute all requests simultaneously\n if (!maxConcurrency || maxConcurrency >= requests.length) {\n const promises = requests.map((request, index) => this.executeRequest(request, index + 1));\n const results = await Promise.all(promises);\n return this.createSummary(results, performance.now() - startTime);\n }\n\n // Execute in chunks with limited concurrency\n const results: ExecutionResult[] = [];\n for (let i = 0; i < requests.length; i += maxConcurrency) {\n const chunk = requests.slice(i, i + maxConcurrency);\n const chunkPromises = chunk.map((request, chunkIndex) =>\n this.executeRequest(request, i + chunkIndex + 1),\n );\n const chunkResults = await Promise.all(chunkPromises);\n results.push(...chunkResults);\n\n // Check if we should stop on error\n const hasError = chunkResults.some((r) => !r.success);\n if (hasError && !this.globalConfig.continueOnError) {\n this.logger.logError('Stopping execution due to error');\n break;\n }\n }\n\n return this.createSummary(results, performance.now() - startTime);\n }\n\n /**\n * Executes requests using connection pooling with HTTP/2 multiplexing.\n * Groups requests by host and batches them into single curl processes.\n */\n private async executePooled(\n requests: RequestConfig[],\n startTime: number,\n ): Promise<ExecutionSummary> {\n this.logger.logInfo(\n `Using connection pooling (HTTP/2 multiplexing) for ${requests.length} requests`,\n );\n\n // Log host groups for visibility\n const groups = this.pooledExecutor!.groupRequestsByHost(requests);\n for (const group of groups) {\n this.logger.logInfo(` ${group.host}: ${group.requests.length} request(s) batched`);\n }\n\n // Execute all batches\n const rawResults = await this.pooledExecutor!.executeAll(requests);\n\n // Post-process results: validation, snapshots, logging\n const results: ExecutionResult[] = [];\n for (let i = 0; i < rawResults.length; i++) {\n const result = rawResults[i];\n const config = requests[i];\n\n // Create per-request logger with merged output configuration\n const outputConfig = this.mergeOutputConfig(config);\n const requestLogger = new Logger(outputConfig);\n\n requestLogger.logRequestStart(config, i + 1);\n\n // Apply validation and snapshot testing\n await postProcessResult(result, config, {\n snapshotManager: this.snapshotManager,\n snapshotConfig: this.getSnapshotConfig(config),\n });\n\n requestLogger.logRequestComplete(result);\n results.push(result);\n\n // Check if we should stop on error\n if (!result.success && !this.globalConfig.continueOnError) {\n this.logger.logError('Stopping execution due to error');\n break;\n }\n }\n\n return this.createSummary(results, performance.now() - startTime);\n }\n\n async execute(requests: RequestConfig[]): Promise<ExecutionSummary> {\n this.logger.logExecutionStart(requests.length, this.globalConfig.execution || 'sequential');\n\n const summary =\n this.globalConfig.execution === 'parallel'\n ? await this.executeParallel(requests)\n : await this.executeSequential(requests);\n\n this.logger.logSummary(summary);\n\n if (this.globalConfig.output?.saveToFile) {\n await this.saveSummaryToFile(summary);\n }\n\n return summary;\n }\n\n private createSummary(results: ExecutionResult[], duration: number): ExecutionSummary {\n const skipped = results.filter((r) => r.skipped).length;\n const successful = results.filter((r) => r.success && !r.skipped).length;\n const failed = results.filter((r) => !r.success).length;\n\n return {\n total: results.length,\n successful,\n failed,\n skipped,\n duration,\n results,\n };\n }\n\n private async saveSummaryToFile(summary: ExecutionSummary): Promise<void> {\n const file = this.globalConfig.output?.saveToFile;\n if (!file) {\n return;\n }\n\n const content = JSON.stringify(summary, null, 2);\n await Bun.write(file, content);\n this.logger.logInfo(`Results saved to ${file}`);\n }\n}\n",
|
|
52
|
+
"import { getVersion } from '../version';\nimport { color } from './colors';\n\ninterface VersionCheckCache {\n lastCheck: number;\n latestVersion: string;\n}\n\nconst CACHE_FILE = `${process.env.HOME}/.curl-runner-version-cache.json`;\nconst CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours\nconst NPM_REGISTRY_URL = 'https://registry.npmjs.org/@curl-runner/cli/latest';\n\nexport class VersionChecker {\n async checkForUpdates(skipCache = false): Promise<void> {\n try {\n // Don't check in CI environments\n if (process.env.CI) {\n return;\n }\n\n const currentVersion = getVersion();\n\n // Don't check for development versions\n if (currentVersion === '0.0.0') {\n return;\n }\n\n // Check cache first\n if (!skipCache) {\n const cached = await this.getCachedVersion();\n if (cached && Date.now() - cached.lastCheck < CACHE_DURATION) {\n this.compareVersions(currentVersion, cached.latestVersion);\n return;\n }\n }\n\n // Fetch latest version from npm registry\n const latestVersion = await this.fetchLatestVersion();\n if (latestVersion) {\n // Update cache\n await this.setCachedVersion(latestVersion);\n\n // Compare versions\n this.compareVersions(currentVersion, latestVersion);\n }\n } catch {\n // Silently fail - we don't want to interrupt the CLI usage\n // due to version check failures\n }\n }\n\n private async fetchLatestVersion(): Promise<string | null> {\n try {\n const response = await fetch(NPM_REGISTRY_URL, {\n signal: AbortSignal.timeout(3000), // 3 second timeout\n });\n\n if (!response.ok) {\n return null;\n }\n\n const data = (await response.json()) as { version: string };\n return data.version;\n } catch {\n return null;\n }\n }\n\n private compareVersions(current: string, latest: string): void {\n if (this.isNewerVersion(current, latest)) {\n console.log();\n console.log(color('╭───────────────────────────────────────────────╮', 'yellow'));\n console.log(\n color('│', 'yellow') +\n ' ' +\n color('│', 'yellow'),\n );\n console.log(\n color('│', 'yellow') +\n ' ' +\n color('Update available!', 'bright') +\n ` ${color(current, 'red')} → ${color(latest, 'green')}` +\n ' ' +\n color('│', 'yellow'),\n );\n console.log(\n color('│', 'yellow') +\n ' ' +\n color('│', 'yellow'),\n );\n console.log(\n color('│', 'yellow') +\n ' Run ' +\n color('curl-runner upgrade', 'cyan') +\n ' to update ' +\n color('│', 'yellow'),\n );\n console.log(\n color('│', 'yellow') +\n ' ' +\n color('│', 'yellow'),\n );\n console.log(color('╰───────────────────────────────────────────────╯', 'yellow'));\n console.log();\n }\n }\n\n private isNewerVersion(current: string, latest: string): boolean {\n try {\n // Remove 'v' prefix if present\n const currentVersion = current.replace(/^v/, '');\n const latestVersion = latest.replace(/^v/, '');\n\n const currentParts = currentVersion.split('.').map(Number);\n const latestParts = latestVersion.split('.').map(Number);\n\n for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {\n const currentPart = currentParts[i] || 0;\n const latestPart = latestParts[i] || 0;\n\n if (latestPart > currentPart) {\n return true;\n }\n if (latestPart < currentPart) {\n return false;\n }\n }\n\n return false;\n } catch {\n return false;\n }\n }\n\n private async getCachedVersion(): Promise<VersionCheckCache | null> {\n try {\n const file = Bun.file(CACHE_FILE);\n if (await file.exists()) {\n return JSON.parse(await file.text());\n }\n } catch {\n // Ignore cache read errors\n }\n return null;\n }\n\n private async setCachedVersion(latestVersion: string): Promise<void> {\n try {\n const cache: VersionCheckCache = {\n lastCheck: Date.now(),\n latestVersion,\n };\n await Bun.write(CACHE_FILE, JSON.stringify(cache));\n } catch {\n // Ignore cache write errors\n }\n }\n}\n",
|
|
53
|
+
"import { type FSWatcher, watch } from 'node:fs';\nimport type { WatchConfig } from '../types/config';\nimport type { Logger } from '../utils/logger';\n\nexport interface WatcherOptions {\n files: string[];\n config: WatchConfig;\n onRun: () => Promise<void>;\n logger: Logger;\n}\n\nexport class FileWatcher {\n private watchers: FSWatcher[] = [];\n private debounceTimer: Timer | null = null;\n private isRunning = false;\n private pendingRun = false;\n private options: WatcherOptions;\n\n constructor(options: WatcherOptions) {\n this.options = options;\n }\n\n async start(): Promise<void> {\n const { files, logger } = this.options;\n\n // Initial run\n await this.runRequests();\n\n // Setup watchers for each file\n for (const file of files) {\n try {\n const watcher = watch(file, (event) => {\n if (event === 'change') {\n this.handleFileChange(file);\n }\n });\n\n watcher.on('error', (error) => {\n logger.logWarning(`Watch error on ${file}: ${error.message}`);\n });\n\n this.watchers.push(watcher);\n } catch (error) {\n logger.logWarning(\n `Failed to watch ${file}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n // Log watching status\n logger.logWatch(files);\n\n // Handle graceful shutdown\n this.setupSignalHandlers();\n\n // Keep process alive\n await this.keepAlive();\n }\n\n private handleFileChange(filename: string): void {\n const { config, logger } = this.options;\n const debounce = config.debounce ?? 300;\n\n // Clear existing debounce timer\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n\n // Debounce the run\n this.debounceTimer = setTimeout(async () => {\n // If already running, queue for after completion\n if (this.isRunning) {\n this.pendingRun = true;\n return;\n }\n\n if (config.clear !== false) {\n console.clear();\n }\n\n logger.logFileChanged(filename);\n await this.runRequests();\n }, debounce);\n }\n\n private async runRequests(): Promise<void> {\n const { onRun, logger } = this.options;\n\n this.isRunning = true;\n\n try {\n await onRun();\n } catch (error) {\n logger.logError(error instanceof Error ? error.message : String(error));\n }\n\n this.isRunning = false;\n\n // Check for pending runs\n if (this.pendingRun) {\n this.pendingRun = false;\n const { config } = this.options;\n if (config.clear !== false) {\n console.clear();\n }\n logger.logFileChanged('(queued change)');\n await this.runRequests();\n } else {\n logger.logWatchReady();\n }\n }\n\n private setupSignalHandlers(): void {\n const cleanup = () => {\n this.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n }\n\n private async keepAlive(): Promise<never> {\n while (true) {\n await Bun.sleep(1000);\n }\n }\n\n stop(): void {\n for (const watcher of this.watchers) {\n watcher.close();\n }\n this.watchers = [];\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n}\n",
|
|
54
|
+
"import w from\"picocolors\";import{stdout as R,stdin as q}from\"node:process\";import*as k from\"node:readline\";import ot from\"node:readline\";import{cursor as I,erase as N}from\"sisteransi\";import{ReadStream as J}from\"node:tty\";const at=t=>t===161||t===164||t===167||t===168||t===170||t===173||t===174||t>=176&&t<=180||t>=182&&t<=186||t>=188&&t<=191||t===198||t===208||t===215||t===216||t>=222&&t<=225||t===230||t>=232&&t<=234||t===236||t===237||t===240||t===242||t===243||t>=247&&t<=250||t===252||t===254||t===257||t===273||t===275||t===283||t===294||t===295||t===299||t>=305&&t<=307||t===312||t>=319&&t<=322||t===324||t>=328&&t<=331||t===333||t===338||t===339||t===358||t===359||t===363||t===462||t===464||t===466||t===468||t===470||t===472||t===474||t===476||t===593||t===609||t===708||t===711||t>=713&&t<=715||t===717||t===720||t>=728&&t<=731||t===733||t===735||t>=768&&t<=879||t>=913&&t<=929||t>=931&&t<=937||t>=945&&t<=961||t>=963&&t<=969||t===1025||t>=1040&&t<=1103||t===1105||t===8208||t>=8211&&t<=8214||t===8216||t===8217||t===8220||t===8221||t>=8224&&t<=8226||t>=8228&&t<=8231||t===8240||t===8242||t===8243||t===8245||t===8251||t===8254||t===8308||t===8319||t>=8321&&t<=8324||t===8364||t===8451||t===8453||t===8457||t===8467||t===8470||t===8481||t===8482||t===8486||t===8491||t===8531||t===8532||t>=8539&&t<=8542||t>=8544&&t<=8555||t>=8560&&t<=8569||t===8585||t>=8592&&t<=8601||t===8632||t===8633||t===8658||t===8660||t===8679||t===8704||t===8706||t===8707||t===8711||t===8712||t===8715||t===8719||t===8721||t===8725||t===8730||t>=8733&&t<=8736||t===8739||t===8741||t>=8743&&t<=8748||t===8750||t>=8756&&t<=8759||t===8764||t===8765||t===8776||t===8780||t===8786||t===8800||t===8801||t>=8804&&t<=8807||t===8810||t===8811||t===8814||t===8815||t===8834||t===8835||t===8838||t===8839||t===8853||t===8857||t===8869||t===8895||t===8978||t>=9312&&t<=9449||t>=9451&&t<=9547||t>=9552&&t<=9587||t>=9600&&t<=9615||t>=9618&&t<=9621||t===9632||t===9633||t>=9635&&t<=9641||t===9650||t===9651||t===9654||t===9655||t===9660||t===9661||t===9664||t===9665||t>=9670&&t<=9672||t===9675||t>=9678&&t<=9681||t>=9698&&t<=9701||t===9711||t===9733||t===9734||t===9737||t===9742||t===9743||t===9756||t===9758||t===9792||t===9794||t===9824||t===9825||t>=9827&&t<=9829||t>=9831&&t<=9834||t===9836||t===9837||t===9839||t===9886||t===9887||t===9919||t>=9926&&t<=9933||t>=9935&&t<=9939||t>=9941&&t<=9953||t===9955||t===9960||t===9961||t>=9963&&t<=9969||t===9972||t>=9974&&t<=9977||t===9979||t===9980||t===9982||t===9983||t===10045||t>=10102&&t<=10111||t>=11094&&t<=11097||t>=12872&&t<=12879||t>=57344&&t<=63743||t>=65024&&t<=65039||t===65533||t>=127232&&t<=127242||t>=127248&&t<=127277||t>=127280&&t<=127337||t>=127344&&t<=127373||t===127375||t===127376||t>=127387&&t<=127404||t>=917760&&t<=917999||t>=983040&&t<=1048573||t>=1048576&&t<=1114109,lt=t=>t===12288||t>=65281&&t<=65376||t>=65504&&t<=65510,ht=t=>t>=4352&&t<=4447||t===8986||t===8987||t===9001||t===9002||t>=9193&&t<=9196||t===9200||t===9203||t===9725||t===9726||t===9748||t===9749||t>=9800&&t<=9811||t===9855||t===9875||t===9889||t===9898||t===9899||t===9917||t===9918||t===9924||t===9925||t===9934||t===9940||t===9962||t===9970||t===9971||t===9973||t===9978||t===9981||t===9989||t===9994||t===9995||t===10024||t===10060||t===10062||t>=10067&&t<=10069||t===10071||t>=10133&&t<=10135||t===10160||t===10175||t===11035||t===11036||t===11088||t===11093||t>=11904&&t<=11929||t>=11931&&t<=12019||t>=12032&&t<=12245||t>=12272&&t<=12287||t>=12289&&t<=12350||t>=12353&&t<=12438||t>=12441&&t<=12543||t>=12549&&t<=12591||t>=12593&&t<=12686||t>=12688&&t<=12771||t>=12783&&t<=12830||t>=12832&&t<=12871||t>=12880&&t<=19903||t>=19968&&t<=42124||t>=42128&&t<=42182||t>=43360&&t<=43388||t>=44032&&t<=55203||t>=63744&&t<=64255||t>=65040&&t<=65049||t>=65072&&t<=65106||t>=65108&&t<=65126||t>=65128&&t<=65131||t>=94176&&t<=94180||t===94192||t===94193||t>=94208&&t<=100343||t>=100352&&t<=101589||t>=101632&&t<=101640||t>=110576&&t<=110579||t>=110581&&t<=110587||t===110589||t===110590||t>=110592&&t<=110882||t===110898||t>=110928&&t<=110930||t===110933||t>=110948&&t<=110951||t>=110960&&t<=111355||t===126980||t===127183||t===127374||t>=127377&&t<=127386||t>=127488&&t<=127490||t>=127504&&t<=127547||t>=127552&&t<=127560||t===127568||t===127569||t>=127584&&t<=127589||t>=127744&&t<=127776||t>=127789&&t<=127797||t>=127799&&t<=127868||t>=127870&&t<=127891||t>=127904&&t<=127946||t>=127951&&t<=127955||t>=127968&&t<=127984||t===127988||t>=127992&&t<=128062||t===128064||t>=128066&&t<=128252||t>=128255&&t<=128317||t>=128331&&t<=128334||t>=128336&&t<=128359||t===128378||t===128405||t===128406||t===128420||t>=128507&&t<=128591||t>=128640&&t<=128709||t===128716||t>=128720&&t<=128722||t>=128725&&t<=128727||t>=128732&&t<=128735||t===128747||t===128748||t>=128756&&t<=128764||t>=128992&&t<=129003||t===129008||t>=129292&&t<=129338||t>=129340&&t<=129349||t>=129351&&t<=129535||t>=129648&&t<=129660||t>=129664&&t<=129672||t>=129680&&t<=129725||t>=129727&&t<=129733||t>=129742&&t<=129755||t>=129760&&t<=129768||t>=129776&&t<=129784||t>=131072&&t<=196605||t>=196608&&t<=262141,O=/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/y,y=/[\\x00-\\x08\\x0A-\\x1F\\x7F-\\x9F]{1,1000}/y,M=/\\t{1,1000}/y,P=/[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*/yu,L=/(?:[\\x20-\\x7E\\xA0-\\xFF](?!\\uFE0F)){1,1000}/y,ct=/\\p{M}+/gu,pt={limit:1/0,ellipsis:\"\"},X=(t,e={},s={})=>{const i=e.limit??1/0,r=e.ellipsis??\"\",n=e?.ellipsisWidth??(r?X(r,pt,s).width:0),u=s.ansiWidth??0,a=s.controlWidth??0,l=s.tabWidth??8,E=s.ambiguousWidth??1,g=s.emojiWidth??2,m=s.fullWidthWidth??2,A=s.regularWidth??1,V=s.wideWidth??2;let h=0,o=0,f=t.length,v=0,F=!1,d=f,b=Math.max(0,i-n),C=0,B=0,c=0,p=0;t:for(;;){if(B>C||o>=f&&o>h){const ut=t.slice(C,B)||t.slice(h,o);v=0;for(const Y of ut.replaceAll(ct,\"\")){const $=Y.codePointAt(0)||0;if(lt($)?p=m:ht($)?p=V:E!==A&&at($)?p=E:p=A,c+p>b&&(d=Math.min(d,Math.max(C,h)+v)),c+p>i){F=!0;break t}v+=Y.length,c+=p}C=B=0}if(o>=f)break;if(L.lastIndex=o,L.test(t)){if(v=L.lastIndex-o,p=v*A,c+p>b&&(d=Math.min(d,o+Math.floor((b-c)/A))),c+p>i){F=!0;break}c+=p,C=h,B=o,o=h=L.lastIndex;continue}if(O.lastIndex=o,O.test(t)){if(c+u>b&&(d=Math.min(d,o)),c+u>i){F=!0;break}c+=u,C=h,B=o,o=h=O.lastIndex;continue}if(y.lastIndex=o,y.test(t)){if(v=y.lastIndex-o,p=v*a,c+p>b&&(d=Math.min(d,o+Math.floor((b-c)/a))),c+p>i){F=!0;break}c+=p,C=h,B=o,o=h=y.lastIndex;continue}if(M.lastIndex=o,M.test(t)){if(v=M.lastIndex-o,p=v*l,c+p>b&&(d=Math.min(d,o+Math.floor((b-c)/l))),c+p>i){F=!0;break}c+=p,C=h,B=o,o=h=M.lastIndex;continue}if(P.lastIndex=o,P.test(t)){if(c+g>b&&(d=Math.min(d,o)),c+g>i){F=!0;break}c+=g,C=h,B=o,o=h=P.lastIndex;continue}o+=1}return{width:F?b:c,index:F?d:f,truncated:F,ellipsed:F&&i>=n}},ft={limit:1/0,ellipsis:\"\",ellipsisWidth:0},S=(t,e={})=>X(t,ft,e).width,W=\"\\x1B\",Z=\"\\x9B\",Ft=39,j=\"\\x07\",Q=\"[\",dt=\"]\",tt=\"m\",U=`${dt}8;;`,et=new RegExp(`(?:\\\\${Q}(?<code>\\\\d+)m|\\\\${U}(?<uri>.*)${j})`,\"y\"),mt=t=>{if(t>=30&&t<=37||t>=90&&t<=97)return 39;if(t>=40&&t<=47||t>=100&&t<=107)return 49;if(t===1||t===2)return 22;if(t===3)return 23;if(t===4)return 24;if(t===7)return 27;if(t===8)return 28;if(t===9)return 29;if(t===0)return 0},st=t=>`${W}${Q}${t}${tt}`,it=t=>`${W}${U}${t}${j}`,gt=t=>t.map(e=>S(e)),G=(t,e,s)=>{const i=e[Symbol.iterator]();let r=!1,n=!1,u=t.at(-1),a=u===void 0?0:S(u),l=i.next(),E=i.next(),g=0;for(;!l.done;){const m=l.value,A=S(m);a+A<=s?t[t.length-1]+=m:(t.push(m),a=0),(m===W||m===Z)&&(r=!0,n=e.startsWith(U,g+1)),r?n?m===j&&(r=!1,n=!1):m===tt&&(r=!1):(a+=A,a===s&&!E.done&&(t.push(\"\"),a=0)),l=E,E=i.next(),g+=m.length}u=t.at(-1),!a&&u!==void 0&&u.length>0&&t.length>1&&(t[t.length-2]+=t.pop())},vt=t=>{const e=t.split(\" \");let s=e.length;for(;s>0&&!(S(e[s-1])>0);)s--;return s===e.length?t:e.slice(0,s).join(\" \")+e.slice(s).join(\"\")},Et=(t,e,s={})=>{if(s.trim!==!1&&t.trim()===\"\")return\"\";let i=\"\",r,n;const u=t.split(\" \"),a=gt(u);let l=[\"\"];for(const[h,o]of u.entries()){s.trim!==!1&&(l[l.length-1]=(l.at(-1)??\"\").trimStart());let f=S(l.at(-1)??\"\");if(h!==0&&(f>=e&&(s.wordWrap===!1||s.trim===!1)&&(l.push(\"\"),f=0),(f>0||s.trim===!1)&&(l[l.length-1]+=\" \",f++)),s.hard&&a[h]>e){const v=e-f,F=1+Math.floor((a[h]-v-1)/e);Math.floor((a[h]-1)/e)<F&&l.push(\"\"),G(l,o,e);continue}if(f+a[h]>e&&f>0&&a[h]>0){if(s.wordWrap===!1&&f<e){G(l,o,e);continue}l.push(\"\")}if(f+a[h]>e&&s.wordWrap===!1){G(l,o,e);continue}l[l.length-1]+=o}s.trim!==!1&&(l=l.map(h=>vt(h)));const E=l.join(`\n`),g=E[Symbol.iterator]();let m=g.next(),A=g.next(),V=0;for(;!m.done;){const h=m.value,o=A.value;if(i+=h,h===W||h===Z){et.lastIndex=V+1;const F=et.exec(E)?.groups;if(F?.code!==void 0){const d=Number.parseFloat(F.code);r=d===Ft?void 0:d}else F?.uri!==void 0&&(n=F.uri.length===0?void 0:F.uri)}const f=r?mt(r):void 0;o===`\n`?(n&&(i+=it(\"\")),r&&f&&(i+=st(f))):h===`\n`&&(r&&f&&(i+=st(r)),n&&(i+=it(n))),V+=h.length,m=A,A=g.next()}return i};function K(t,e,s){return String(t).normalize().replaceAll(`\\r\n`,`\n`).split(`\n`).map(i=>Et(i,e,s)).join(`\n`)}const At=[\"up\",\"down\",\"left\",\"right\",\"space\",\"enter\",\"cancel\"],_={actions:new Set(At),aliases:new Map([[\"k\",\"up\"],[\"j\",\"down\"],[\"h\",\"left\"],[\"l\",\"right\"],[\"\u0003\",\"cancel\"],[\"escape\",\"cancel\"]]),messages:{cancel:\"Canceled\",error:\"Something went wrong\"},withGuide:!0};function It(t){if(t.aliases!==void 0){const e=t.aliases;for(const s in e){if(!Object.hasOwn(e,s))continue;const i=e[s];_.actions.has(i)&&(_.aliases.has(s)||_.aliases.set(s,i))}}if(t.messages!==void 0){const e=t.messages;e.cancel!==void 0&&(_.messages.cancel=e.cancel),e.error!==void 0&&(_.messages.error=e.error)}t.withGuide!==void 0&&(_.withGuide=t.withGuide!==!1)}function H(t,e){if(typeof t==\"string\")return _.aliases.get(t)===e;for(const s of t)if(s!==void 0&&H(s,e))return!0;return!1}function _t(t,e){if(t===e)return;const s=t.split(`\n`),i=e.split(`\n`),r=Math.max(s.length,i.length),n=[];for(let u=0;u<r;u++)s[u]!==i[u]&&n.push(u);return{lines:n,numLinesBefore:s.length,numLinesAfter:i.length,numLines:r}}const bt=globalThis.process.platform.startsWith(\"win\"),z=Symbol(\"clack:cancel\");function Ct(t){return t===z}function T(t,e){const s=t;s.isTTY&&s.setRawMode(e)}function xt({input:t=q,output:e=R,overwrite:s=!0,hideCursor:i=!0}={}){const r=k.createInterface({input:t,output:e,prompt:\"\",tabSize:1});k.emitKeypressEvents(t,r),t instanceof J&&t.isTTY&&t.setRawMode(!0);const n=(u,{name:a,sequence:l})=>{const E=String(u);if(H([E,a,l],\"cancel\")){i&&e.write(I.show),process.exit(0);return}if(!s)return;const g=a===\"return\"?0:-1,m=a===\"return\"?-1:0;k.moveCursor(e,g,m,()=>{k.clearLine(e,1,()=>{t.once(\"keypress\",n)})})};return i&&e.write(I.hide),t.once(\"keypress\",n),()=>{t.off(\"keypress\",n),i&&e.write(I.show),t instanceof J&&t.isTTY&&!bt&&t.setRawMode(!1),r.terminal=!1,r.close()}}const rt=t=>\"columns\"in t&&typeof t.columns==\"number\"?t.columns:80,nt=t=>\"rows\"in t&&typeof t.rows==\"number\"?t.rows:20;function Bt(t,e,s,i=s){const r=rt(t??R);return K(e,r-s.length,{hard:!0,trim:!1}).split(`\n`).map((n,u)=>`${u===0?i:s}${n}`).join(`\n`)}class x{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame=\"\";_subscribers=new Map;_cursor=0;state=\"initial\";error=\"\";value;userInput=\"\";constructor(e,s=!0){const{input:i=q,output:r=R,render:n,signal:u,...a}=e;this.opts=a,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=n.bind(this),this._track=s,this._abortSignal=u,this.input=i,this.output=r}unsubscribe(){this._subscribers.clear()}setSubscriber(e,s){const i=this._subscribers.get(e)??[];i.push(s),this._subscribers.set(e,i)}on(e,s){this.setSubscriber(e,{cb:s})}once(e,s){this.setSubscriber(e,{cb:s,once:!0})}emit(e,...s){const i=this._subscribers.get(e)??[],r=[];for(const n of i)n.cb(...s),n.once&&r.push(()=>i.splice(i.indexOf(n),1));for(const n of r)n()}prompt(){return new Promise(e=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state=\"cancel\",this.close(),e(z);this._abortSignal.addEventListener(\"abort\",()=>{this.state=\"cancel\",this.close()},{once:!0})}this.rl=ot.createInterface({input:this.input,tabSize:2,prompt:\"\",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on(\"keypress\",this.onKeypress),T(this.input,!0),this.output.on(\"resize\",this.render),this.render(),this.once(\"submit\",()=>{this.output.write(I.show),this.output.off(\"resize\",this.render),T(this.input,!1),e(this.value)}),this.once(\"cancel\",()=>{this.output.write(I.show),this.output.off(\"resize\",this.render),T(this.input,!1),e(z)})})}_isActionKey(e,s){return e===\"\t\"}_setValue(e){this.value=e,this.emit(\"value\",this.value)}_setUserInput(e,s){this.userInput=e??\"\",this.emit(\"userInput\",this.userInput),s&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:\"u\"}),this._setUserInput(\"\")}onKeypress(e,s){if(this._track&&s.name!==\"return\"&&(s.name&&this._isActionKey(e,s)&&this.rl?.write(null,{ctrl:!0,name:\"h\"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state===\"error\"&&(this.state=\"active\"),s?.name&&(!this._track&&_.aliases.has(s.name)&&this.emit(\"cursor\",_.aliases.get(s.name)),_.actions.has(s.name)&&this.emit(\"cursor\",s.name)),e&&(e.toLowerCase()===\"y\"||e.toLowerCase()===\"n\")&&this.emit(\"confirm\",e.toLowerCase()===\"y\"),this.emit(\"key\",e?.toLowerCase(),s),s?.name===\"return\"){if(this.opts.validate){const i=this.opts.validate(this.value);i&&(this.error=i instanceof Error?i.message:i,this.state=\"error\",this.rl?.write(this.userInput))}this.state!==\"error\"&&(this.state=\"submit\")}H([e,s?.name,s?.sequence],\"cancel\")&&(this.state=\"cancel\"),(this.state===\"submit\"||this.state===\"cancel\")&&this.emit(\"finalize\"),this.render(),(this.state===\"submit\"||this.state===\"cancel\")&&this.close()}close(){this.input.unpipe(),this.input.removeListener(\"keypress\",this.onKeypress),this.output.write(`\n`),T(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){const e=K(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`\n`).length-1;this.output.write(I.move(-999,e*-1))}render(){const e=K(this._render(this)??\"\",process.stdout.columns,{hard:!0,trim:!1});if(e!==this._prevFrame){if(this.state===\"initial\")this.output.write(I.hide);else{const s=_t(this._prevFrame,e),i=nt(this.output);if(this.restoreCursor(),s){const r=Math.max(0,s.numLinesAfter-i),n=Math.max(0,s.numLinesBefore-i);let u=s.lines.find(a=>a>=r);if(u===void 0){this._prevFrame=e;return}if(s.lines.length===1){this.output.write(I.move(0,u-n)),this.output.write(N.lines(1));const a=e.split(`\n`);this.output.write(a[u]),this._prevFrame=e,this.output.write(I.move(0,a.length-u-1));return}else if(s.lines.length>1){if(r<n)u=r;else{const l=u-n;l>0&&this.output.write(I.move(0,l))}this.output.write(N.down());const a=e.split(`\n`).slice(u);this.output.write(a.join(`\n`)),this._prevFrame=e;return}}this.output.write(N.down())}this.output.write(e),this.state===\"initial\"&&(this.state=\"active\"),this._prevFrame=e}}}function wt(t,e){if(t===void 0||e.length===0)return 0;const s=e.findIndex(i=>i.value===t);return s!==-1?s:0}function Dt(t,e){return(e.label??String(e.value)).toLowerCase().includes(t.toLowerCase())}function St(t,e){if(e)return t?e:e[0]}class Vt extends x{filteredOptions;multiple;isNavigating=!1;selectedValues=[];focusedValue;#t=0;#s=\"\";#i;#e;get cursor(){return this.#t}get userInputWithCursor(){if(!this.userInput)return w.inverse(w.hidden(\"_\"));if(this._cursor>=this.userInput.length)return`${this.userInput}\\u2588`;const e=this.userInput.slice(0,this._cursor),[s,...i]=this.userInput.slice(this._cursor);return`${e}${w.inverse(s)}${i.join(\"\")}`}get options(){return typeof this.#e==\"function\"?this.#e():this.#e}constructor(e){super(e),this.#e=e.options;const s=this.options;this.filteredOptions=[...s],this.multiple=e.multiple===!0,this.#i=e.filter??Dt;let i;if(e.initialValue&&Array.isArray(e.initialValue)?this.multiple?i=e.initialValue:i=e.initialValue.slice(0,1):!this.multiple&&this.options.length>0&&(i=[this.options[0].value]),i)for(const r of i){const n=s.findIndex(u=>u.value===r);n!==-1&&(this.toggleSelected(r),this.#t=n)}this.focusedValue=this.options[this.#t]?.value,this.on(\"key\",(r,n)=>this.#r(r,n)),this.on(\"userInput\",r=>this.#n(r))}_isActionKey(e,s){return e===\"\t\"||this.multiple&&this.isNavigating&&s.name===\"space\"&&e!==void 0&&e!==\"\"}#r(e,s){const i=s.name===\"up\",r=s.name===\"down\",n=s.name===\"return\";i||r?(this.#t=Math.max(0,Math.min(this.#t+(i?-1:1),this.filteredOptions.length-1)),this.focusedValue=this.filteredOptions[this.#t]?.value,this.multiple||(this.selectedValues=[this.focusedValue]),this.isNavigating=!0):n?this.value=St(this.multiple,this.selectedValues):this.multiple?this.focusedValue!==void 0&&(s.name===\"tab\"||this.isNavigating&&s.name===\"space\")?this.toggleSelected(this.focusedValue):this.isNavigating=!1:(this.focusedValue&&(this.selectedValues=[this.focusedValue]),this.isNavigating=!1)}deselectAll(){this.selectedValues=[]}toggleSelected(e){this.filteredOptions.length!==0&&(this.multiple?this.selectedValues.includes(e)?this.selectedValues=this.selectedValues.filter(s=>s!==e):this.selectedValues=[...this.selectedValues,e]:this.selectedValues=[e])}#n(e){if(e!==this.#s){this.#s=e;const s=this.options;e?this.filteredOptions=s.filter(i=>this.#i(e,i)):this.filteredOptions=[...s],this.#t=wt(this.focusedValue,this.filteredOptions),this.focusedValue=this.filteredOptions[this.#t]?.value,this.multiple||(this.focusedValue!==void 0?this.toggleSelected(this.focusedValue):this.deselectAll())}}}class kt extends x{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(e){super(e,!1),this.value=!!e.initialValue,this.on(\"userInput\",()=>{this.value=this._value}),this.on(\"confirm\",s=>{this.output.write(I.move(0,-1)),this.value=s,this.state=\"submit\",this.close()}),this.on(\"cursor\",()=>{this.value=!this.value})}}class yt extends x{options;cursor=0;#t;getGroupItems(e){return this.options.filter(s=>s.group===e)}isGroupSelected(e){const s=this.getGroupItems(e),i=this.value;return i===void 0?!1:s.every(r=>i.includes(r.value))}toggleValue(){const e=this.options[this.cursor];if(this.value===void 0&&(this.value=[]),e.group===!0){const s=e.value,i=this.getGroupItems(s);this.isGroupSelected(s)?this.value=this.value.filter(r=>i.findIndex(n=>n.value===r)===-1):this.value=[...this.value,...i.map(r=>r.value)],this.value=Array.from(new Set(this.value))}else{const s=this.value.includes(e.value);this.value=s?this.value.filter(i=>i!==e.value):[...this.value,e.value]}}constructor(e){super(e,!1);const{options:s}=e;this.#t=e.selectableGroups!==!1,this.options=Object.entries(s).flatMap(([i,r])=>[{value:i,group:!0,label:i},...r.map(n=>({...n,group:i}))]),this.value=[...e.initialValues??[]],this.cursor=Math.max(this.options.findIndex(({value:i})=>i===e.cursorAt),this.#t?0:1),this.on(\"cursor\",i=>{switch(i){case\"left\":case\"up\":{this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;const r=this.options[this.cursor]?.group===!0;!this.#t&&r&&(this.cursor=this.cursor===0?this.options.length-1:this.cursor-1);break}case\"down\":case\"right\":{this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;const r=this.options[this.cursor]?.group===!0;!this.#t&&r&&(this.cursor=this.cursor===this.options.length-1?0:this.cursor+1);break}case\"space\":this.toggleValue();break}})}}function D(t,e,s){const i=t+e,r=Math.max(s.length-1,0),n=i<0?r:i>r?0:i;return s[n].disabled?D(n,e<0?-1:1,s):n}class Mt extends x{options;cursor=0;get _value(){return this.options[this.cursor].value}get _enabledOptions(){return this.options.filter(e=>e.disabled!==!0)}toggleAll(){const e=this._enabledOptions,s=this.value!==void 0&&this.value.length===e.length;this.value=s?[]:e.map(i=>i.value)}toggleInvert(){const e=this.value;if(!e)return;const s=this._enabledOptions.filter(i=>!e.includes(i.value));this.value=s.map(i=>i.value)}toggleValue(){this.value===void 0&&(this.value=[]);const e=this.value.includes(this._value);this.value=e?this.value.filter(s=>s!==this._value):[...this.value,this._value]}constructor(e){super(e,!1),this.options=e.options,this.value=[...e.initialValues??[]];const s=Math.max(this.options.findIndex(({value:i})=>i===e.cursorAt),0);this.cursor=this.options[s].disabled?D(s,1,this.options):s,this.on(\"key\",i=>{i===\"a\"&&this.toggleAll(),i===\"i\"&&this.toggleInvert()}),this.on(\"cursor\",i=>{switch(i){case\"left\":case\"up\":this.cursor=D(this.cursor,-1,this.options);break;case\"down\":case\"right\":this.cursor=D(this.cursor,1,this.options);break;case\"space\":this.toggleValue();break}})}}let Lt=class extends x{_mask=\"\\u2022\";get cursor(){return this._cursor}get masked(){return this.userInput.replaceAll(/./g,this._mask)}get userInputWithCursor(){if(this.state===\"submit\"||this.state===\"cancel\")return this.masked;const e=this.userInput;if(this.cursor>=e.length)return`${this.masked}${w.inverse(w.hidden(\"_\"))}`;const s=this.masked,i=s.slice(0,this.cursor),r=s.slice(this.cursor);return`${i}${w.inverse(r[0])}${r.slice(1)}`}clear(){this._clearUserInput()}constructor({mask:e,...s}){super(s),this._mask=e??\"\\u2022\",this.on(\"userInput\",i=>{this._setValue(i)})}};class Wt extends x{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){this.value=this._selectedValue.value}constructor(e){super(e,!1),this.options=e.options;const s=this.options.findIndex(({value:r})=>r===e.initialValue),i=s===-1?0:s;this.cursor=this.options[i].disabled?D(i,1,this.options):i,this.changeValue(),this.on(\"cursor\",r=>{switch(r){case\"left\":case\"up\":this.cursor=D(this.cursor,-1,this.options);break;case\"down\":case\"right\":this.cursor=D(this.cursor,1,this.options);break}this.changeValue()})}}class Tt extends x{options;cursor=0;constructor(e){super(e,!1),this.options=e.options;const s=e.caseSensitive===!0,i=this.options.map(({value:[r]})=>s?r:r?.toLowerCase());this.cursor=Math.max(i.indexOf(e.initialValue),0),this.on(\"key\",(r,n)=>{if(!r)return;const u=s&&n.shift?r.toUpperCase():r;if(!i.includes(u))return;const a=this.options.find(({value:[l]})=>s?l===u:l?.toLowerCase()===r);a&&(this.value=a.value,this.state=\"submit\",this.emit(\"submit\"))})}}class $t extends x{get userInputWithCursor(){if(this.state===\"submit\")return this.userInput;const e=this.userInput;if(this.cursor>=e.length)return`${this.userInput}\\u2588`;const s=e.slice(0,this.cursor),[i,...r]=e.slice(this.cursor);return`${s}${w.inverse(i)}${r.join(\"\")}`}get cursor(){return this._cursor}constructor(e){super({...e,initialUserInput:e.initialUserInput??e.initialValue}),this.on(\"userInput\",s=>{this._setValue(s)}),this.on(\"finalize\",()=>{this.value||(this.value=e.defaultValue),this.value===void 0&&(this.value=\"\")})}}export{Vt as AutocompletePrompt,kt as ConfirmPrompt,yt as GroupMultiSelectPrompt,Mt as MultiSelectPrompt,Lt as PasswordPrompt,x as Prompt,Tt as SelectKeyPrompt,Wt as SelectPrompt,$t as TextPrompt,xt as block,rt as getColumns,nt as getRows,Ct as isCancel,_ as settings,It as updateSettings,Bt as wrapTextWithPrefix};\n//# sourceMappingURL=index.mjs.map\n",
|
|
55
|
+
"import{getColumns as X,getRows as et,AutocompletePrompt as Be,settings as U,ConfirmPrompt as tt,isCancel as st,GroupMultiSelectPrompt as rt,MultiSelectPrompt as it,wrapTextWithPrefix as V,PasswordPrompt as nt,block as at,SelectPrompt as ot,SelectKeyPrompt as lt,TextPrompt as ut}from\"@clack/core\";export{isCancel,settings,updateSettings}from\"@clack/core\";import t from\"picocolors\";import P from\"node:process\";import{readdirSync as ct,existsSync as dt,lstatSync as be}from\"node:fs\";import{dirname as xe,join as $t}from\"node:path\";import{cursor as _e,erase as De}from\"sisteransi\";import{stripVTControlCharacters as le}from\"node:util\";function ht(){return P.platform!==\"win32\"?P.env.TERM!==\"linux\":!!P.env.CI||!!P.env.WT_SESSION||!!P.env.TERMINUS_SUBLIME||P.env.ConEmuTask===\"{cmd::Cmder}\"||P.env.TERM_PROGRAM===\"Terminus-Sublime\"||P.env.TERM_PROGRAM===\"vscode\"||P.env.TERM===\"xterm-256color\"||P.env.TERM===\"alacritty\"||P.env.TERMINAL_EMULATOR===\"JetBrains-JediTerm\"}const ee=ht(),ue=()=>process.env.CI===\"true\",Te=e=>e.isTTY===!0,w=(e,r)=>ee?e:r,Me=w(\"\\u25C6\",\"*\"),ce=w(\"\\u25A0\",\"x\"),de=w(\"\\u25B2\",\"x\"),k=w(\"\\u25C7\",\"o\"),$e=w(\"\\u250C\",\"T\"),h=w(\"\\u2502\",\"|\"),x=w(\"\\u2514\",\"\\u2014\"),Re=w(\"\\u2510\",\"T\"),Oe=w(\"\\u2518\",\"\\u2014\"),Y=w(\"\\u25CF\",\">\"),K=w(\"\\u25CB\",\" \"),te=w(\"\\u25FB\",\"[\\u2022]\"),G=w(\"\\u25FC\",\"[+]\"),z=w(\"\\u25FB\",\"[ ]\"),Pe=w(\"\\u25AA\",\"\\u2022\"),se=w(\"\\u2500\",\"-\"),he=w(\"\\u256E\",\"+\"),Ne=w(\"\\u251C\",\"+\"),me=w(\"\\u256F\",\"+\"),pe=w(\"\\u2570\",\"+\"),We=w(\"\\u256D\",\"+\"),ge=w(\"\\u25CF\",\"\\u2022\"),fe=w(\"\\u25C6\",\"*\"),Fe=w(\"\\u25B2\",\"!\"),ye=w(\"\\u25A0\",\"x\"),N=e=>{switch(e){case\"initial\":case\"active\":return t.cyan(Me);case\"cancel\":return t.red(ce);case\"error\":return t.yellow(de);case\"submit\":return t.green(k)}},Ee=e=>{switch(e){case\"initial\":case\"active\":return t.cyan(h);case\"cancel\":return t.red(h);case\"error\":return t.yellow(h);case\"submit\":return t.green(h)}},mt=e=>e===161||e===164||e===167||e===168||e===170||e===173||e===174||e>=176&&e<=180||e>=182&&e<=186||e>=188&&e<=191||e===198||e===208||e===215||e===216||e>=222&&e<=225||e===230||e>=232&&e<=234||e===236||e===237||e===240||e===242||e===243||e>=247&&e<=250||e===252||e===254||e===257||e===273||e===275||e===283||e===294||e===295||e===299||e>=305&&e<=307||e===312||e>=319&&e<=322||e===324||e>=328&&e<=331||e===333||e===338||e===339||e===358||e===359||e===363||e===462||e===464||e===466||e===468||e===470||e===472||e===474||e===476||e===593||e===609||e===708||e===711||e>=713&&e<=715||e===717||e===720||e>=728&&e<=731||e===733||e===735||e>=768&&e<=879||e>=913&&e<=929||e>=931&&e<=937||e>=945&&e<=961||e>=963&&e<=969||e===1025||e>=1040&&e<=1103||e===1105||e===8208||e>=8211&&e<=8214||e===8216||e===8217||e===8220||e===8221||e>=8224&&e<=8226||e>=8228&&e<=8231||e===8240||e===8242||e===8243||e===8245||e===8251||e===8254||e===8308||e===8319||e>=8321&&e<=8324||e===8364||e===8451||e===8453||e===8457||e===8467||e===8470||e===8481||e===8482||e===8486||e===8491||e===8531||e===8532||e>=8539&&e<=8542||e>=8544&&e<=8555||e>=8560&&e<=8569||e===8585||e>=8592&&e<=8601||e===8632||e===8633||e===8658||e===8660||e===8679||e===8704||e===8706||e===8707||e===8711||e===8712||e===8715||e===8719||e===8721||e===8725||e===8730||e>=8733&&e<=8736||e===8739||e===8741||e>=8743&&e<=8748||e===8750||e>=8756&&e<=8759||e===8764||e===8765||e===8776||e===8780||e===8786||e===8800||e===8801||e>=8804&&e<=8807||e===8810||e===8811||e===8814||e===8815||e===8834||e===8835||e===8838||e===8839||e===8853||e===8857||e===8869||e===8895||e===8978||e>=9312&&e<=9449||e>=9451&&e<=9547||e>=9552&&e<=9587||e>=9600&&e<=9615||e>=9618&&e<=9621||e===9632||e===9633||e>=9635&&e<=9641||e===9650||e===9651||e===9654||e===9655||e===9660||e===9661||e===9664||e===9665||e>=9670&&e<=9672||e===9675||e>=9678&&e<=9681||e>=9698&&e<=9701||e===9711||e===9733||e===9734||e===9737||e===9742||e===9743||e===9756||e===9758||e===9792||e===9794||e===9824||e===9825||e>=9827&&e<=9829||e>=9831&&e<=9834||e===9836||e===9837||e===9839||e===9886||e===9887||e===9919||e>=9926&&e<=9933||e>=9935&&e<=9939||e>=9941&&e<=9953||e===9955||e===9960||e===9961||e>=9963&&e<=9969||e===9972||e>=9974&&e<=9977||e===9979||e===9980||e===9982||e===9983||e===10045||e>=10102&&e<=10111||e>=11094&&e<=11097||e>=12872&&e<=12879||e>=57344&&e<=63743||e>=65024&&e<=65039||e===65533||e>=127232&&e<=127242||e>=127248&&e<=127277||e>=127280&&e<=127337||e>=127344&&e<=127373||e===127375||e===127376||e>=127387&&e<=127404||e>=917760&&e<=917999||e>=983040&&e<=1048573||e>=1048576&&e<=1114109,pt=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,gt=e=>e>=4352&&e<=4447||e===8986||e===8987||e===9001||e===9002||e>=9193&&e<=9196||e===9200||e===9203||e===9725||e===9726||e===9748||e===9749||e>=9800&&e<=9811||e===9855||e===9875||e===9889||e===9898||e===9899||e===9917||e===9918||e===9924||e===9925||e===9934||e===9940||e===9962||e===9970||e===9971||e===9973||e===9978||e===9981||e===9989||e===9994||e===9995||e===10024||e===10060||e===10062||e>=10067&&e<=10069||e===10071||e>=10133&&e<=10135||e===10160||e===10175||e===11035||e===11036||e===11088||e===11093||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=94176&&e<=94180||e===94192||e===94193||e>=94208&&e<=100343||e>=100352&&e<=101589||e>=101632&&e<=101640||e>=110576&&e<=110579||e>=110581&&e<=110587||e===110589||e===110590||e>=110592&&e<=110882||e===110898||e>=110928&&e<=110930||e===110933||e>=110948&&e<=110951||e>=110960&&e<=111355||e===126980||e===127183||e===127374||e>=127377&&e<=127386||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e===127568||e===127569||e>=127584&&e<=127589||e>=127744&&e<=127776||e>=127789&&e<=127797||e>=127799&&e<=127868||e>=127870&&e<=127891||e>=127904&&e<=127946||e>=127951&&e<=127955||e>=127968&&e<=127984||e===127988||e>=127992&&e<=128062||e===128064||e>=128066&&e<=128252||e>=128255&&e<=128317||e>=128331&&e<=128334||e>=128336&&e<=128359||e===128378||e===128405||e===128406||e===128420||e>=128507&&e<=128591||e>=128640&&e<=128709||e===128716||e>=128720&&e<=128722||e>=128725&&e<=128727||e>=128732&&e<=128735||e===128747||e===128748||e>=128756&&e<=128764||e>=128992&&e<=129003||e===129008||e>=129292&&e<=129338||e>=129340&&e<=129349||e>=129351&&e<=129535||e>=129648&&e<=129660||e>=129664&&e<=129672||e>=129680&&e<=129725||e>=129727&&e<=129733||e>=129742&&e<=129755||e>=129760&&e<=129768||e>=129776&&e<=129784||e>=131072&&e<=196605||e>=196608&&e<=262141,ve=/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/y,re=/[\\x00-\\x08\\x0A-\\x1F\\x7F-\\x9F]{1,1000}/y,ie=/\\t{1,1000}/y,Ae=/[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*/yu,ne=/(?:[\\x20-\\x7E\\xA0-\\xFF](?!\\uFE0F)){1,1000}/y,ft=/\\p{M}+/gu,Ft={limit:1/0,ellipsis:\"\"},Le=(e,r={},s={})=>{const i=r.limit??1/0,n=r.ellipsis??\"\",o=r?.ellipsisWidth??(n?Le(n,Ft,s).width:0),u=s.ansiWidth??0,l=s.controlWidth??0,a=s.tabWidth??8,d=s.ambiguousWidth??1,g=s.emojiWidth??2,E=s.fullWidthWidth??2,p=s.regularWidth??1,y=s.wideWidth??2;let $=0,c=0,m=e.length,f=0,F=!1,v=m,S=Math.max(0,i-o),B=0,b=0,A=0,C=0;e:for(;;){if(b>B||c>=m&&c>$){const _=e.slice(B,b)||e.slice($,c);f=0;for(const D of _.replaceAll(ft,\"\")){const T=D.codePointAt(0)||0;if(pt(T)?C=E:gt(T)?C=y:d!==p&&mt(T)?C=d:C=p,A+C>S&&(v=Math.min(v,Math.max(B,$)+f)),A+C>i){F=!0;break e}f+=D.length,A+=C}B=b=0}if(c>=m)break;if(ne.lastIndex=c,ne.test(e)){if(f=ne.lastIndex-c,C=f*p,A+C>S&&(v=Math.min(v,c+Math.floor((S-A)/p))),A+C>i){F=!0;break}A+=C,B=$,b=c,c=$=ne.lastIndex;continue}if(ve.lastIndex=c,ve.test(e)){if(A+u>S&&(v=Math.min(v,c)),A+u>i){F=!0;break}A+=u,B=$,b=c,c=$=ve.lastIndex;continue}if(re.lastIndex=c,re.test(e)){if(f=re.lastIndex-c,C=f*l,A+C>S&&(v=Math.min(v,c+Math.floor((S-A)/l))),A+C>i){F=!0;break}A+=C,B=$,b=c,c=$=re.lastIndex;continue}if(ie.lastIndex=c,ie.test(e)){if(f=ie.lastIndex-c,C=f*a,A+C>S&&(v=Math.min(v,c+Math.floor((S-A)/a))),A+C>i){F=!0;break}A+=C,B=$,b=c,c=$=ie.lastIndex;continue}if(Ae.lastIndex=c,Ae.test(e)){if(A+g>S&&(v=Math.min(v,c)),A+g>i){F=!0;break}A+=g,B=$,b=c,c=$=Ae.lastIndex;continue}c+=1}return{width:F?S:A,index:F?v:m,truncated:F,ellipsed:F&&i>=o}},yt={limit:1/0,ellipsis:\"\",ellipsisWidth:0},M=(e,r={})=>Le(e,yt,r).width,ae=\"\\x1B\",je=\"\\x9B\",Et=39,Ce=\"\\x07\",Ve=\"[\",vt=\"]\",ke=\"m\",we=`${vt}8;;`,Ge=new RegExp(`(?:\\\\${Ve}(?<code>\\\\d+)m|\\\\${we}(?<uri>.*)${Ce})`,\"y\"),At=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},He=e=>`${ae}${Ve}${e}${ke}`,Ue=e=>`${ae}${we}${e}${Ce}`,Ct=e=>e.map(r=>M(r)),Se=(e,r,s)=>{const i=r[Symbol.iterator]();let n=!1,o=!1,u=e.at(-1),l=u===void 0?0:M(u),a=i.next(),d=i.next(),g=0;for(;!a.done;){const E=a.value,p=M(E);l+p<=s?e[e.length-1]+=E:(e.push(E),l=0),(E===ae||E===je)&&(n=!0,o=r.startsWith(we,g+1)),n?o?E===Ce&&(n=!1,o=!1):E===ke&&(n=!1):(l+=p,l===s&&!d.done&&(e.push(\"\"),l=0)),a=d,d=i.next(),g+=E.length}u=e.at(-1),!l&&u!==void 0&&u.length>0&&e.length>1&&(e[e.length-2]+=e.pop())},wt=e=>{const r=e.split(\" \");let s=r.length;for(;s>0&&!(M(r[s-1])>0);)s--;return s===r.length?e:r.slice(0,s).join(\" \")+r.slice(s).join(\"\")},St=(e,r,s={})=>{if(s.trim!==!1&&e.trim()===\"\")return\"\";let i=\"\",n,o;const u=e.split(\" \"),l=Ct(u);let a=[\"\"];for(const[$,c]of u.entries()){s.trim!==!1&&(a[a.length-1]=(a.at(-1)??\"\").trimStart());let m=M(a.at(-1)??\"\");if($!==0&&(m>=r&&(s.wordWrap===!1||s.trim===!1)&&(a.push(\"\"),m=0),(m>0||s.trim===!1)&&(a[a.length-1]+=\" \",m++)),s.hard&&l[$]>r){const f=r-m,F=1+Math.floor((l[$]-f-1)/r);Math.floor((l[$]-1)/r)<F&&a.push(\"\"),Se(a,c,r);continue}if(m+l[$]>r&&m>0&&l[$]>0){if(s.wordWrap===!1&&m<r){Se(a,c,r);continue}a.push(\"\")}if(m+l[$]>r&&s.wordWrap===!1){Se(a,c,r);continue}a[a.length-1]+=c}s.trim!==!1&&(a=a.map($=>wt($)));const d=a.join(`\n`),g=d[Symbol.iterator]();let E=g.next(),p=g.next(),y=0;for(;!E.done;){const $=E.value,c=p.value;if(i+=$,$===ae||$===je){Ge.lastIndex=y+1;const F=Ge.exec(d)?.groups;if(F?.code!==void 0){const v=Number.parseFloat(F.code);n=v===Et?void 0:v}else F?.uri!==void 0&&(o=F.uri.length===0?void 0:F.uri)}const m=n?At(n):void 0;c===`\n`?(o&&(i+=Ue(\"\")),n&&m&&(i+=He(m))):$===`\n`&&(n&&m&&(i+=He(n)),o&&(i+=Ue(o))),y+=$.length,E=p,p=g.next()}return i};function q(e,r,s){return String(e).normalize().replaceAll(`\\r\n`,`\n`).split(`\n`).map(i=>St(i,r,s)).join(`\n`)}const It=(e,r,s,i,n)=>{let o=r,u=0;for(let l=s;l<i;l++){const a=e[l];if(o=o-a.length,u++,o<=n)break}return{lineCount:o,removals:u}},J=e=>{const{cursor:r,options:s,style:i}=e,n=e.output??process.stdout,o=X(n),u=e.columnPadding??0,l=e.rowPadding??4,a=o-u,d=et(n),g=t.dim(\"...\"),E=e.maxItems??Number.POSITIVE_INFINITY,p=Math.max(d-l,0),y=Math.max(Math.min(E,p),5);let $=0;r>=y-3&&($=Math.max(Math.min(r-y+3,s.length-y),0));let c=y<s.length&&$>0,m=y<s.length&&$+y<s.length;const f=Math.min($+y,s.length),F=[];let v=0;c&&v++,m&&v++;const S=$+(c?1:0),B=f-(m?1:0);for(let A=S;A<B;A++){const C=q(i(s[A],A===r),a,{hard:!0,trim:!1}).split(`\n`);F.push(C),v+=C.length}if(v>p){let A=0,C=0,_=v;const D=r-S,T=(W,I)=>It(F,_,W,I,p);c?({lineCount:_,removals:A}=T(0,D),_>p&&({lineCount:_,removals:C}=T(D+1,F.length))):({lineCount:_,removals:C}=T(D+1,F.length),_>p&&({lineCount:_,removals:A}=T(0,D))),A>0&&(c=!0,F.splice(0,A)),C>0&&(m=!0,F.splice(F.length-C,C))}const b=[];c&&b.push(g);for(const A of F)for(const C of A)b.push(C);return m&&b.push(g),b};function Ke(e){return e.label??String(e.value??\"\")}function qe(e,r){if(!e)return!0;const s=(r.label??String(r.value??\"\")).toLowerCase(),i=(r.hint??\"\").toLowerCase(),n=String(r.value).toLowerCase(),o=e.toLowerCase();return s.includes(o)||i.includes(o)||n.includes(o)}function Bt(e,r){const s=[];for(const i of r)e.includes(i.value)&&s.push(i);return s}const Je=e=>new Be({options:e.options,initialValue:e.initialValue?[e.initialValue]:void 0,initialUserInput:e.initialUserInput,filter:e.filter??((r,s)=>qe(r,s)),signal:e.signal,input:e.input,output:e.output,validate:e.validate,render(){const r=[`${t.gray(h)}`,`${N(this.state)} ${e.message}`],s=this.userInput,i=this.options,n=e.placeholder,o=s===\"\"&&n!==void 0;switch(this.state){case\"submit\":{const u=Bt(this.selectedValues,i),l=u.length>0?` ${t.dim(u.map(Ke).join(\", \"))}`:\"\";return`${r.join(`\n`)}\n${t.gray(h)}${l}`}case\"cancel\":{const u=s?` ${t.strikethrough(t.dim(s))}`:\"\";return`${r.join(`\n`)}\n${t.gray(h)}${u}`}default:{const u=`${(this.state===\"error\"?t.yellow:t.cyan)(h)} `,l=(this.state===\"error\"?t.yellow:t.cyan)(x);let a=\"\";if(this.isNavigating||o){const c=o?n:s;a=c!==\"\"?` ${t.dim(c)}`:\"\"}else a=` ${this.userInputWithCursor}`;const d=this.filteredOptions.length!==i.length?t.dim(` (${this.filteredOptions.length} match${this.filteredOptions.length===1?\"\":\"es\"})`):\"\",g=this.filteredOptions.length===0&&s?[`${u}${t.yellow(\"No matches found\")}`]:[],E=this.state===\"error\"?[`${u}${t.yellow(this.error)}`]:[];r.push(`${u.trimEnd()}`,`${u}${t.dim(\"Search:\")}${a}${d}`,...g,...E);const p=[`${t.dim(\"\\u2191/\\u2193\")} to select`,`${t.dim(\"Enter:\")} confirm`,`${t.dim(\"Type:\")} to search`],y=[`${u}${t.dim(p.join(\" \\u2022 \"))}`,`${l}`],$=this.filteredOptions.length===0?[]:J({cursor:this.cursor,options:this.filteredOptions,columnPadding:3,rowPadding:r.length+y.length,style:(c,m)=>{const f=Ke(c),F=c.hint&&c.value===this.focusedValue?t.dim(` (${c.hint})`):\"\";return m?`${t.green(Y)} ${f}${F}`:`${t.dim(K)} ${t.dim(f)}${F}`},maxItems:e.maxItems,output:e.output});return[...r,...$.map(c=>`${u}${c}`),...y].join(`\n`)}}}}).prompt(),bt=e=>{const r=(i,n,o,u)=>{const l=o.includes(i.value),a=i.label??String(i.value??\"\"),d=i.hint&&u!==void 0&&i.value===u?t.dim(` (${i.hint})`):\"\",g=l?t.green(G):t.dim(z);return n?`${g} ${a}${d}`:`${g} ${t.dim(a)}`},s=new Be({options:e.options,multiple:!0,filter:e.filter??((i,n)=>qe(i,n)),validate:()=>{if(e.required&&s.selectedValues.length===0)return\"Please select at least one item\"},initialValue:e.initialValues,signal:e.signal,input:e.input,output:e.output,render(){const i=`${t.gray(h)}\n${N(this.state)} ${e.message}\n`,n=this.userInput,o=e.placeholder,u=n===\"\"&&o!==void 0,l=this.isNavigating||u?t.dim(u?o:n):this.userInputWithCursor,a=this.options,d=this.filteredOptions.length!==a.length?t.dim(` (${this.filteredOptions.length} match${this.filteredOptions.length===1?\"\":\"es\"})`):\"\";switch(this.state){case\"submit\":return`${i}${t.gray(h)} ${t.dim(`${this.selectedValues.length} items selected`)}`;case\"cancel\":return`${i}${t.gray(h)} ${t.strikethrough(t.dim(n))}`;default:{const g=this.state===\"error\"?t.yellow:t.cyan,E=[`${t.dim(\"\\u2191/\\u2193\")} to navigate`,`${t.dim(this.isNavigating?\"Space/Tab:\":\"Tab:\")} select`,`${t.dim(\"Enter:\")} confirm`,`${t.dim(\"Type:\")} to search`],p=this.filteredOptions.length===0&&n?[`${g(h)} ${t.yellow(\"No matches found\")}`]:[],y=this.state===\"error\"?[`${g(h)} ${t.yellow(this.error)}`]:[],$=[...`${i}${g(h)}`.split(`\n`),`${g(h)} ${t.dim(\"Search:\")} ${l}${d}`,...p,...y],c=[`${g(h)} ${t.dim(E.join(\" \\u2022 \"))}`,`${g(x)}`],m=J({cursor:this.cursor,options:this.filteredOptions,style:(f,F)=>r(f,F,this.selectedValues,this.focusedValue),maxItems:e.maxItems,output:e.output,rowPadding:$.length+c.length});return[...$,...m.map(f=>`${g(h)} ${f}`),...c].join(`\n`)}}}});return s.prompt()},xt=[We,he,pe,me],_t=[$e,Re,x,Oe];function Xe(e,r,s,i){let n=s,o=s;return i===\"center\"?n=Math.floor((r-e)/2):i===\"right\"&&(n=r-e-s),o=r-n-e,[n,o]}const Dt=e=>e,Tt=(e=\"\",r=\"\",s)=>{const i=s?.output??process.stdout,n=X(i),o=2,u=s?.titlePadding??1,l=s?.contentPadding??2,a=s?.width===void 0||s.width===\"auto\"?1:Math.min(1,s.width),d=(s?.withGuide??U.withGuide)!==!1?`${h} `:\"\",g=s?.formatBorder??Dt,E=(s?.rounded?xt:_t).map(g),p=g(se),y=g(h),$=M(d),c=M(r),m=n-$;let f=Math.floor(n*a)-$;if(s?.width===\"auto\"){const _=e.split(`\n`);let D=c+u*2;for(const W of _){const I=M(W)+l*2;I>D&&(D=I)}const T=D+o;T<f&&(f=T)}f%2!==0&&(f<m?f++:f--);const F=f-o,v=F-u*2,S=c>v?`${r.slice(0,v-3)}...`:r,[B,b]=Xe(M(S),F,u,s?.titleAlign),A=q(e,F-l*2,{hard:!0,trim:!1});i.write(`${d}${E[0]}${p.repeat(B)}${S}${p.repeat(b)}${E[1]}\n`);const C=A.split(`\n`);for(const _ of C){const[D,T]=Xe(M(_),F,l,s?.contentAlign);i.write(`${d}${y}${\" \".repeat(D)}${_}${\" \".repeat(T)}${y}\n`)}i.write(`${d}${E[2]}${p.repeat(F)}${E[3]}\n`)},Mt=e=>{const r=e.active??\"Yes\",s=e.inactive??\"No\";return new tt({active:r,inactive:s,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue??!0,render(){const i=`${t.gray(h)}\n${N(this.state)} ${e.message}\n`,n=this.value?r:s;switch(this.state){case\"submit\":return`${i}${t.gray(h)} ${t.dim(n)}`;case\"cancel\":return`${i}${t.gray(h)} ${t.strikethrough(t.dim(n))}\n${t.gray(h)}`;default:return`${i}${t.cyan(h)} ${this.value?`${t.green(Y)} ${r}`:`${t.dim(K)} ${t.dim(r)}`} ${t.dim(\"/\")} ${this.value?`${t.dim(K)} ${t.dim(s)}`:`${t.green(Y)} ${s}`}\n${t.cyan(x)}\n`}}}).prompt()},Rt=async(e,r)=>{const s={},i=Object.keys(e);for(const n of i){const o=e[n],u=await o({results:s})?.catch(l=>{throw l});if(typeof r?.onCancel==\"function\"&&st(u)){s[n]=\"canceled\",r.onCancel({results:s});continue}s[n]=u}return s},Ot=e=>{const{selectableGroups:r=!0,groupSpacing:s=0}=e,i=(o,u,l=[])=>{const a=o.label??String(o.value),d=typeof o.group==\"string\",g=d&&(l[l.indexOf(o)+1]??{group:!0}),E=d&&g&&g.group===!0,p=d?r?`${E?x:h} `:\" \":\"\";let y=\"\";if(s>0&&!d){const c=`\n${t.cyan(h)}`;y=`${c.repeat(s-1)}${c} `}if(u===\"active\")return`${y}${t.dim(p)}${t.cyan(te)} ${a}${o.hint?` ${t.dim(`(${o.hint})`)}`:\"\"}`;if(u===\"group-active\")return`${y}${p}${t.cyan(te)} ${t.dim(a)}`;if(u===\"group-active-selected\")return`${y}${p}${t.green(G)} ${t.dim(a)}`;if(u===\"selected\"){const c=d||r?t.green(G):\"\";return`${y}${t.dim(p)}${c} ${t.dim(a)}${o.hint?` ${t.dim(`(${o.hint})`)}`:\"\"}`}if(u===\"cancelled\")return`${t.strikethrough(t.dim(a))}`;if(u===\"active-selected\")return`${y}${t.dim(p)}${t.green(G)} ${a}${o.hint?` ${t.dim(`(${o.hint})`)}`:\"\"}`;if(u===\"submitted\")return`${t.dim(a)}`;const $=d||r?t.dim(z):\"\";return`${y}${t.dim(p)}${$} ${t.dim(a)}`},n=e.required??!0;return new rt({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValues:e.initialValues,required:n,cursorAt:e.cursorAt,selectableGroups:r,validate(o){if(n&&(o===void 0||o.length===0))return`Please select at least one option.\n${t.reset(t.dim(`Press ${t.gray(t.bgWhite(t.inverse(\" space \")))} to select, ${t.gray(t.bgWhite(t.inverse(\" enter \")))} to submit`))}`},render(){const o=`${t.gray(h)}\n${N(this.state)} ${e.message}\n`,u=this.value??[];switch(this.state){case\"submit\":{const l=this.options.filter(({value:d})=>u.includes(d)).map(d=>i(d,\"submitted\")),a=l.length===0?\"\":` ${l.join(t.dim(\", \"))}`;return`${o}${t.gray(h)}${a}`}case\"cancel\":{const l=this.options.filter(({value:a})=>u.includes(a)).map(a=>i(a,\"cancelled\")).join(t.dim(\", \"));return`${o}${t.gray(h)} ${l.trim()?`${l}\n${t.gray(h)}`:\"\"}`}case\"error\":{const l=this.error.split(`\n`).map((a,d)=>d===0?`${t.yellow(x)} ${t.yellow(a)}`:` ${a}`).join(`\n`);return`${o}${t.yellow(h)} ${this.options.map((a,d,g)=>{const E=u.includes(a.value)||a.group===!0&&this.isGroupSelected(`${a.value}`),p=d===this.cursor;return!p&&typeof a.group==\"string\"&&this.options[this.cursor].value===a.group?i(a,E?\"group-active-selected\":\"group-active\",g):p&&E?i(a,\"active-selected\",g):E?i(a,\"selected\",g):i(a,p?\"active\":\"inactive\",g)}).join(`\n${t.yellow(h)} `)}\n${l}\n`}default:{const l=this.options.map((d,g,E)=>{const p=u.includes(d.value)||d.group===!0&&this.isGroupSelected(`${d.value}`),y=g===this.cursor,$=!y&&typeof d.group==\"string\"&&this.options[this.cursor].value===d.group;let c=\"\";return $?c=i(d,p?\"group-active-selected\":\"group-active\",E):y&&p?c=i(d,\"active-selected\",E):p?c=i(d,\"selected\",E):c=i(d,y?\"active\":\"inactive\",E),`${g!==0&&!c.startsWith(`\n`)?\" \":\"\"}${c}`}).join(`\n${t.cyan(h)}`),a=l.startsWith(`\n`)?\"\":\" \";return`${o}${t.cyan(h)}${a}${l}\n${t.cyan(x)}\n`}}}}).prompt()},R={message:(e=[],{symbol:r=t.gray(h),secondarySymbol:s=t.gray(h),output:i=process.stdout,spacing:n=1,withGuide:o}={})=>{const u=[],l=(o??U.withGuide)!==!1,a=l?s:\"\",d=l?`${r} `:\"\",g=l?`${s} `:\"\";for(let p=0;p<n;p++)u.push(a);const E=Array.isArray(e)?e:e.split(`\n`);if(E.length>0){const[p,...y]=E;p.length>0?u.push(`${d}${p}`):u.push(l?r:\"\");for(const $ of y)$.length>0?u.push(`${g}${$}`):u.push(l?s:\"\")}i.write(`${u.join(`\n`)}\n`)},info:(e,r)=>{R.message(e,{...r,symbol:t.blue(ge)})},success:(e,r)=>{R.message(e,{...r,symbol:t.green(fe)})},step:(e,r)=>{R.message(e,{...r,symbol:t.green(k)})},warn:(e,r)=>{R.message(e,{...r,symbol:t.yellow(Fe)})},warning:(e,r)=>{R.warn(e,r)},error:(e,r)=>{R.message(e,{...r,symbol:t.red(ye)})}},Pt=(e=\"\",r)=>{(r?.output??process.stdout).write(`${t.gray(x)} ${t.red(e)}\n\n`)},Nt=(e=\"\",r)=>{(r?.output??process.stdout).write(`${t.gray($e)} ${e}\n`)},Wt=(e=\"\",r)=>{(r?.output??process.stdout).write(`${t.gray(h)}\n${t.gray(x)} ${e}\n\n`)},Q=(e,r)=>e.split(`\n`).map(s=>r(s)).join(`\n`),Lt=e=>{const r=(i,n)=>{const o=i.label??String(i.value);return n===\"disabled\"?`${t.gray(z)} ${Q(o,u=>t.strikethrough(t.gray(u)))}${i.hint?` ${t.dim(`(${i.hint??\"disabled\"})`)}`:\"\"}`:n===\"active\"?`${t.cyan(te)} ${o}${i.hint?` ${t.dim(`(${i.hint})`)}`:\"\"}`:n===\"selected\"?`${t.green(G)} ${Q(o,t.dim)}${i.hint?` ${t.dim(`(${i.hint})`)}`:\"\"}`:n===\"cancelled\"?`${Q(o,u=>t.strikethrough(t.dim(u)))}`:n===\"active-selected\"?`${t.green(G)} ${o}${i.hint?` ${t.dim(`(${i.hint})`)}`:\"\"}`:n===\"submitted\"?`${Q(o,t.dim)}`:`${t.dim(z)} ${Q(o,t.dim)}`},s=e.required??!0;return new it({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValues:e.initialValues,required:s,cursorAt:e.cursorAt,validate(i){if(s&&(i===void 0||i.length===0))return`Please select at least one option.\n${t.reset(t.dim(`Press ${t.gray(t.bgWhite(t.inverse(\" space \")))} to select, ${t.gray(t.bgWhite(t.inverse(\" enter \")))} to submit`))}`},render(){const i=V(e.output,e.message,`${Ee(this.state)} `,`${N(this.state)} `),n=`${t.gray(h)}\n${i}\n`,o=this.value??[],u=(l,a)=>{if(l.disabled)return r(l,\"disabled\");const d=o.includes(l.value);return a&&d?r(l,\"active-selected\"):d?r(l,\"selected\"):r(l,a?\"active\":\"inactive\")};switch(this.state){case\"submit\":{const l=this.options.filter(({value:d})=>o.includes(d)).map(d=>r(d,\"submitted\")).join(t.dim(\", \"))||t.dim(\"none\"),a=V(e.output,l,`${t.gray(h)} `);return`${n}${a}`}case\"cancel\":{const l=this.options.filter(({value:d})=>o.includes(d)).map(d=>r(d,\"cancelled\")).join(t.dim(\", \"));if(l.trim()===\"\")return`${n}${t.gray(h)}`;const a=V(e.output,l,`${t.gray(h)} `);return`${n}${a}\n${t.gray(h)}`}case\"error\":{const l=`${t.yellow(h)} `,a=this.error.split(`\n`).map((E,p)=>p===0?`${t.yellow(x)} ${t.yellow(E)}`:` ${E}`).join(`\n`),d=n.split(`\n`).length,g=a.split(`\n`).length+1;return`${n}${l}${J({output:e.output,options:this.options,cursor:this.cursor,maxItems:e.maxItems,columnPadding:l.length,rowPadding:d+g,style:u}).join(`\n${l}`)}\n${a}\n`}default:{const l=`${t.cyan(h)} `,a=n.split(`\n`).length;return`${n}${l}${J({output:e.output,options:this.options,cursor:this.cursor,maxItems:e.maxItems,columnPadding:l.length,rowPadding:a+2,style:u}).join(`\n${l}`)}\n${t.cyan(x)}\n`}}}}).prompt()},jt=e=>t.dim(e),Vt=(e,r,s)=>{const i={hard:!0,trim:!1},n=q(e,r,i).split(`\n`),o=n.reduce((a,d)=>Math.max(M(d),a),0),u=n.map(s).reduce((a,d)=>Math.max(M(d),a),0),l=r-(u-o);return q(e,l,i)},kt=(e=\"\",r=\"\",s)=>{const i=s?.output??P.stdout,n=(s?.withGuide??U.withGuide)!==!1,o=s?.format??jt,u=[\"\",...Vt(e,X(i)-6,o).split(`\n`).map(o),\"\"],l=M(r),a=Math.max(u.reduce((p,y)=>{const $=M(y);return $>p?$:p},0),l)+2,d=u.map(p=>`${t.gray(h)} ${p}${\" \".repeat(a-M(p))}${t.gray(h)}`).join(`\n`),g=n?`${t.gray(h)}\n`:\"\",E=n?Ne:pe;i.write(`${g}${t.green(k)} ${t.reset(r)} ${t.gray(se.repeat(Math.max(a-l-1,1))+he)}\n${d}\n${t.gray(E+se.repeat(a+2)+me)}\n`)},Gt=e=>new nt({validate:e.validate,mask:e.mask??Pe,signal:e.signal,input:e.input,output:e.output,render(){const r=`${t.gray(h)}\n${N(this.state)} ${e.message}\n`,s=this.userInputWithCursor,i=this.masked;switch(this.state){case\"error\":{const n=i?` ${i}`:\"\";return e.clearOnError&&this.clear(),`${r.trim()}\n${t.yellow(h)}${n}\n${t.yellow(x)} ${t.yellow(this.error)}\n`}case\"submit\":{const n=i?` ${t.dim(i)}`:\"\";return`${r}${t.gray(h)}${n}`}case\"cancel\":{const n=i?` ${t.strikethrough(t.dim(i))}`:\"\";return`${r}${t.gray(h)}${n}${i?`\n${t.gray(h)}`:\"\"}`}default:return`${r}${t.cyan(h)} ${s}\n${t.cyan(x)}\n`}}}).prompt(),Ht=e=>{const r=e.validate;return Je({...e,initialUserInput:e.initialValue??e.root??process.cwd(),maxItems:5,validate(s){if(!Array.isArray(s)){if(!s)return\"Please select a path\";if(r)return r(s)}},options(){const s=this.userInput;if(s===\"\")return[];try{let i;return dt(s)?be(s).isDirectory()?i=s:i=xe(s):i=xe(s),ct(i).map(n=>{const o=$t(i,n),u=be(o);return{name:n,path:o,isDirectory:u.isDirectory()}}).filter(({path:n,isDirectory:o})=>n.startsWith(s)&&(e.directory||!o)).map(n=>({value:n.path}))}catch{return[]}}})},Ut=t.magenta,Ie=({indicator:e=\"dots\",onCancel:r,output:s=process.stdout,cancelMessage:i,errorMessage:n,frames:o=ee?[\"\\u25D2\",\"\\u25D0\",\"\\u25D3\",\"\\u25D1\"]:[\"\\u2022\",\"o\",\"O\",\"0\"],delay:u=ee?80:120,signal:l,...a}={})=>{const d=ue();let g,E,p=!1,y=!1,$=\"\",c,m=performance.now();const f=X(s),F=a?.styleFrame??Ut,v=I=>{const O=I>1?n??U.messages.error:i??U.messages.cancel;y=I===1,p&&(W(O,I),y&&typeof r==\"function\"&&r())},S=()=>v(2),B=()=>v(1),b=()=>{process.on(\"uncaughtExceptionMonitor\",S),process.on(\"unhandledRejection\",S),process.on(\"SIGINT\",B),process.on(\"SIGTERM\",B),process.on(\"exit\",v),l&&l.addEventListener(\"abort\",B)},A=()=>{process.removeListener(\"uncaughtExceptionMonitor\",S),process.removeListener(\"unhandledRejection\",S),process.removeListener(\"SIGINT\",B),process.removeListener(\"SIGTERM\",B),process.removeListener(\"exit\",v),l&&l.removeEventListener(\"abort\",B)},C=()=>{if(c===void 0)return;d&&s.write(`\n`);const I=q(c,f,{hard:!0,trim:!1}).split(`\n`);I.length>1&&s.write(_e.up(I.length-1)),s.write(_e.to(0)),s.write(De.down())},_=I=>I.replace(/\\.+$/,\"\"),D=I=>{const O=(performance.now()-I)/1e3,L=Math.floor(O/60),j=Math.floor(O%60);return L>0?`[${L}m ${j}s]`:`[${j}s]`},T=(I=\"\")=>{p=!0,g=at({output:s}),$=_(I),m=performance.now(),s.write(`${t.gray(h)}\n`);let O=0,L=0;b(),E=setInterval(()=>{if(d&&$===c)return;C(),c=$;const j=F(o[O]);let Z;if(d)Z=`${j} ${$}...`;else if(e===\"timer\")Z=`${j} ${$} ${D(m)}`;else{const Ze=\".\".repeat(Math.floor(L)).slice(0,3);Z=`${j} ${$}${Ze}`}const Qe=q(Z,f,{hard:!0,trim:!1});s.write(Qe),O=O+1<o.length?O+1:0,L=L<4?L+.125:0},u)},W=(I=\"\",O=0,L=!1)=>{if(!p)return;p=!1,clearInterval(E),C();const j=O===0?t.green(k):O===1?t.red(ce):t.red(de);$=I??$,L||(e===\"timer\"?s.write(`${j} ${$} ${D(m)}\n`):s.write(`${j} ${$}\n`)),A(),g()};return{start:T,stop:(I=\"\")=>W(I,0),message:(I=\"\")=>{$=_(I??$)},cancel:(I=\"\")=>W(I,1),error:(I=\"\")=>W(I,2),clear:()=>W(\"\",0,!0),get isCancelled(){return y}}},Ye={light:w(\"\\u2500\",\"-\"),heavy:w(\"\\u2501\",\"=\"),block:w(\"\\u2588\",\"#\")};function Kt({style:e=\"heavy\",max:r=100,size:s=40,...i}={}){const n=Ie(i);let o=0,u=\"\";const l=Math.max(1,r),a=Math.max(1,s),d=y=>{switch(y){case\"initial\":case\"active\":return t.magenta;case\"error\":case\"cancel\":return t.red;case\"submit\":return t.green;default:return t.magenta}},g=(y,$)=>{const c=Math.floor(o/l*a);return`${d(y)(Ye[e].repeat(c))}${t.dim(Ye[e].repeat(a-c))} ${$}`},E=(y=\"\")=>{u=y,n.start(g(\"initial\",y))},p=(y=1,$)=>{o=Math.min(l,y+o),n.message(g(\"active\",$??u)),u=$??u};return{start:E,stop:n.stop,cancel:n.cancel,error:n.error,clear:n.clear,advance:p,isCancelled:n.isCancelled,message:y=>p(0,y)}}const oe=(e,r)=>e.includes(`\n`)?e.split(`\n`).map(s=>r(s)).join(`\n`):r(e),qt=e=>{const r=(s,i)=>{const n=s.label??String(s.value);switch(i){case\"disabled\":return`${t.gray(K)} ${oe(n,t.gray)}${s.hint?` ${t.dim(`(${s.hint??\"disabled\"})`)}`:\"\"}`;case\"selected\":return`${oe(n,t.dim)}`;case\"active\":return`${t.green(Y)} ${n}${s.hint?` ${t.dim(`(${s.hint})`)}`:\"\"}`;case\"cancelled\":return`${oe(n,o=>t.strikethrough(t.dim(o)))}`;default:return`${t.dim(K)} ${oe(n,t.dim)}`}};return new ot({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue,render(){const s=`${N(this.state)} `,i=`${Ee(this.state)} `,n=V(e.output,e.message,i,s),o=`${t.gray(h)}\n${n}\n`;switch(this.state){case\"submit\":{const u=`${t.gray(h)} `,l=V(e.output,r(this.options[this.cursor],\"selected\"),u);return`${o}${l}`}case\"cancel\":{const u=`${t.gray(h)} `,l=V(e.output,r(this.options[this.cursor],\"cancelled\"),u);return`${o}${l}\n${t.gray(h)}`}default:{const u=`${t.cyan(h)} `,l=o.split(`\n`).length;return`${o}${u}${J({output:e.output,cursor:this.cursor,options:this.options,maxItems:e.maxItems,columnPadding:u.length,rowPadding:l+2,style:(a,d)=>r(a,a.disabled?\"disabled\":d?\"active\":\"inactive\")}).join(`\n${u}`)}\n${t.cyan(x)}\n`}}}}).prompt()},Jt=e=>{const r=(s,i=\"inactive\")=>{const n=s.label??String(s.value);return i===\"selected\"?`${t.dim(n)}`:i===\"cancelled\"?`${t.strikethrough(t.dim(n))}`:i===\"active\"?`${t.bgCyan(t.gray(` ${s.value} `))} ${n}${s.hint?` ${t.dim(`(${s.hint})`)}`:\"\"}`:`${t.gray(t.bgWhite(t.inverse(` ${s.value} `)))} ${n}${s.hint?` ${t.dim(`(${s.hint})`)}`:\"\"}`};return new lt({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue,caseSensitive:e.caseSensitive,render(){const s=`${t.gray(h)}\n${N(this.state)} ${e.message}\n`;switch(this.state){case\"submit\":{const i=`${t.gray(h)} `,n=this.options.find(u=>u.value===this.value)??e.options[0],o=V(e.output,r(n,\"selected\"),i);return`${s}${o}`}case\"cancel\":{const i=`${t.gray(h)} `,n=V(e.output,r(this.options[0],\"cancelled\"),i);return`${s}${n}\n${t.gray(h)}`}default:{const i=`${t.cyan(h)} `,n=this.options.map((o,u)=>V(e.output,r(o,u===this.cursor?\"active\":\"inactive\"),i)).join(`\n`);return`${s}${n}\n${t.cyan(x)}\n`}}}}).prompt()},ze=`${t.gray(h)} `,H={message:async(e,{symbol:r=t.gray(h)}={})=>{process.stdout.write(`${t.gray(h)}\n${r} `);let s=3;for await(let i of e){i=i.replace(/\\n/g,`\n${ze}`),i.includes(`\n`)&&(s=3+le(i.slice(i.lastIndexOf(`\n`))).length);const n=le(i).length;s+n<process.stdout.columns?(s+=n,process.stdout.write(i)):(process.stdout.write(`\n${ze}${i.trimStart()}`),s=3+le(i.trimStart()).length)}process.stdout.write(`\n`)},info:e=>H.message(e,{symbol:t.blue(ge)}),success:e=>H.message(e,{symbol:t.green(fe)}),step:e=>H.message(e,{symbol:t.green(k)}),warn:e=>H.message(e,{symbol:t.yellow(Fe)}),warning:e=>H.warn(e),error:e=>H.message(e,{symbol:t.red(ye)})},Xt=async(e,r)=>{for(const s of e){if(s.enabled===!1)continue;const i=Ie(r);i.start(s.title);const n=await s.task(i.message);i.stop(n||s.title)}},Yt=e=>e.replace(/\\x1b\\[(?:\\d+;)*\\d*[ABCDEFGHfJKSTsu]|\\x1b\\[(s|u)/g,\"\"),zt=e=>{const r=e.output??process.stdout,s=X(r),i=t.gray(h),n=e.spacing??1,o=3,u=e.retainLog===!0,l=!ue()&&Te(r);r.write(`${i}\n`),r.write(`${t.green(k)} ${e.title}\n`);for(let m=0;m<n;m++)r.write(`${i}\n`);const a=[{value:\"\",full:\"\"}];let d=!1;const g=m=>{if(a.length===0)return;let f=0;m&&(f+=n+2);for(const F of a){const{value:v,result:S}=F;let B=S?.message??v;if(B.length===0)continue;S===void 0&&F.header!==void 0&&F.header!==\"\"&&(B+=`\n${F.header}`);const b=B.split(`\n`).reduce((A,C)=>C===\"\"?A+1:A+Math.ceil((C.length+o)/s),0);f+=b}f>0&&(f+=1,r.write(De.lines(f)))},E=(m,f,F)=>{const v=F?`${m.full}\n${m.value}`:m.value;m.header!==void 0&&m.header!==\"\"&&R.message(m.header.split(`\n`).map(t.bold),{output:r,secondarySymbol:i,symbol:i,spacing:0}),R.message(v.split(`\n`).map(t.dim),{output:r,secondarySymbol:i,symbol:i,spacing:f??n})},p=()=>{for(const m of a){const{header:f,value:F,full:v}=m;(f===void 0||f.length===0)&&F.length===0||E(m,void 0,u===!0&&v.length>0)}},y=(m,f,F)=>{if(g(!1),(F?.raw!==!0||!d)&&m.value!==\"\"&&(m.value+=`\n`),m.value+=Yt(f),d=F?.raw===!0,e.limit!==void 0){const v=m.value.split(`\n`),S=v.length-e.limit;if(S>0){const B=v.splice(0,S);u&&(m.full+=(m.full===\"\"?\"\":`\n`)+B.join(`\n`))}m.value=v.join(`\n`)}l&&$()},$=()=>{for(const m of a)m.result?m.result.status===\"error\"?R.error(m.result.message,{output:r,secondarySymbol:i,spacing:0}):R.success(m.result.message,{output:r,secondarySymbol:i,spacing:0}):m.value!==\"\"&&E(m,0)},c=(m,f)=>{g(!1),m.result=f,l&&$()};return{message(m,f){y(a[0],m,f)},group(m){const f={header:m,value:\"\",full:\"\"};return a.push(f),{message(F,v){y(f,F,v)},error(F){c(f,{status:\"error\",message:F})},success(F){c(f,{status:\"success\",message:F})}}},error(m,f){g(!0),R.error(m,{output:r,secondarySymbol:i,spacing:1}),f?.showLog!==!1&&p(),a.splice(1,a.length-1),a[0].value=\"\",a[0].full=\"\"},success(m,f){g(!0),R.success(m,{output:r,secondarySymbol:i,spacing:1}),f?.showLog===!0&&p(),a.splice(1,a.length-1),a[0].value=\"\",a[0].full=\"\"}}},Qt=e=>new ut({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,output:e.output,signal:e.signal,input:e.input,render(){const r=(e?.withGuide??U.withGuide)!==!1,s=`${`${r?`${t.gray(h)}\n`:\"\"}${N(this.state)} `}${e.message}\n`,i=e.placeholder?t.inverse(e.placeholder[0])+t.dim(e.placeholder.slice(1)):t.inverse(t.hidden(\"_\")),n=this.userInput?this.userInputWithCursor:i,o=this.value??\"\";switch(this.state){case\"error\":{const u=this.error?` ${t.yellow(this.error)}`:\"\",l=r?`${t.yellow(h)} `:\"\",a=r?t.yellow(x):\"\";return`${s.trim()}\n${l}${n}\n${a}${u}\n`}case\"submit\":{const u=o?` ${t.dim(o)}`:\"\",l=r?t.gray(h):\"\";return`${s}${l}${u}`}case\"cancel\":{const u=o?` ${t.strikethrough(t.dim(o))}`:\"\",l=r?t.gray(h):\"\";return`${s}${l}${u}${o.trim()?`\n${l}`:\"\"}`}default:{const u=r?`${t.cyan(h)} `:\"\",l=r?t.cyan(x):\"\";return`${s}${u}${n}\n${l}\n`}}}}).prompt();export{h as S_BAR,x as S_BAR_END,Oe as S_BAR_END_RIGHT,se as S_BAR_H,$e as S_BAR_START,Re as S_BAR_START_RIGHT,te as S_CHECKBOX_ACTIVE,z as S_CHECKBOX_INACTIVE,G as S_CHECKBOX_SELECTED,Ne as S_CONNECT_LEFT,pe as S_CORNER_BOTTOM_LEFT,me as S_CORNER_BOTTOM_RIGHT,We as S_CORNER_TOP_LEFT,he as S_CORNER_TOP_RIGHT,ye as S_ERROR,ge as S_INFO,Pe as S_PASSWORD_MASK,Y as S_RADIO_ACTIVE,K as S_RADIO_INACTIVE,Me as S_STEP_ACTIVE,ce as S_STEP_CANCEL,de as S_STEP_ERROR,k as S_STEP_SUBMIT,fe as S_SUCCESS,Fe as S_WARN,Je as autocomplete,bt as autocompleteMultiselect,Tt as box,Pt as cancel,Mt as confirm,Rt as group,Ot as groupMultiselect,Nt as intro,ue as isCI,Te as isTTY,J as limitOptions,R as log,Lt as multiselect,kt as note,Wt as outro,Gt as password,Ht as path,Kt as progress,qt as select,Jt as selectKey,Ie as spinner,H as stream,N as symbol,Ee as symbolBar,zt as taskLog,Xt as tasks,Qt as text,ee as unicode,w as unicodeOr};\n//# sourceMappingURL=index.mjs.map\n",
|
|
56
|
+
"/**\n * Parser for loading existing YAML files into wizard answers (edit mode).\n */\n\nimport { YamlParser } from '../parser/yaml';\nimport type { RequestConfig } from '../types/config';\nimport type { WizardAnswers } from './types';\n\n/**\n * Loads a YAML file and converts it to WizardAnswers for editing.\n */\nexport async function loadYamlFile(filePath: string): Promise<WizardAnswers> {\n const content = await YamlParser.parseFile(filePath);\n\n // Find the request config\n let request: RequestConfig | undefined;\n\n if (content.request) {\n request = content.request;\n } else if (content.requests && content.requests.length > 0) {\n request = content.requests[0];\n } else if (content.collection?.requests && content.collection.requests.length > 0) {\n request = content.collection.requests[0];\n }\n\n if (!request) {\n throw new Error('No request found in YAML file');\n }\n\n return requestToAnswers(request);\n}\n\n/**\n * Converts a RequestConfig to WizardAnswers.\n */\nexport function requestToAnswers(request: RequestConfig): WizardAnswers {\n const answers: WizardAnswers = {\n url: request.url,\n method: request.method || 'GET',\n };\n\n // Name\n if (request.name) {\n answers.name = request.name;\n }\n\n // Headers\n if (request.headers && Object.keys(request.headers).length > 0) {\n answers.headers = request.headers;\n }\n\n // Query params\n if (request.params && Object.keys(request.params).length > 0) {\n answers.params = request.params;\n }\n\n // Body\n if (request.body !== undefined) {\n if (typeof request.body === 'object' && request.body !== null) {\n answers.bodyType = 'json';\n answers.body = request.body;\n } else {\n answers.bodyType = 'raw';\n answers.body = request.body;\n }\n } else if (request.formData) {\n answers.bodyType = 'form';\n answers.formData = request.formData as Record<string, string | { file: string }>;\n } else {\n answers.bodyType = 'none';\n }\n\n // Auth\n if (request.auth) {\n if (request.auth.type === 'bearer') {\n answers.authType = 'bearer';\n answers.token = request.auth.token;\n } else if (request.auth.type === 'basic') {\n answers.authType = 'basic';\n answers.username = request.auth.username;\n answers.password = request.auth.password;\n }\n } else {\n answers.authType = 'none';\n }\n\n // Advanced\n if (request.timeout) {\n answers.timeout = request.timeout;\n }\n if (request.followRedirects !== undefined) {\n answers.followRedirects = request.followRedirects;\n }\n if (request.maxRedirects) {\n answers.maxRedirects = request.maxRedirects;\n }\n if (request.insecure) {\n answers.insecure = request.insecure;\n }\n if (request.http2) {\n answers.http2 = request.http2;\n }\n\n // Retry\n if (request.retry) {\n answers.retryEnabled = true;\n answers.retryCount = request.retry.count;\n answers.retryDelay = request.retry.delay;\n answers.retryBackoff = request.retry.backoff;\n }\n\n // Validation\n if (request.expect) {\n if (request.expect.status) {\n answers.expectStatus = request.expect.status;\n }\n if (request.expect.responseTime) {\n answers.expectResponseTime = request.expect.responseTime;\n }\n }\n\n // Output\n if (request.output) {\n answers.outputFile = request.output;\n }\n\n return answers;\n}\n\n/**\n * Checks if a file exists.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n const file = Bun.file(filePath);\n return await file.exists();\n } catch {\n return false;\n }\n}\n",
|
|
57
|
+
"/**\n * Wizard templates for common use cases.\n */\n\nimport type { TemplateConfig, WizardTemplate } from './types';\n\nexport const TEMPLATES: Record<WizardTemplate, TemplateConfig> = {\n 'basic-get': {\n name: 'Basic GET Request',\n description: 'Simple GET request to fetch data',\n defaults: {\n method: 'GET',\n followRedirects: true,\n },\n },\n 'basic-post': {\n name: 'Basic POST Request',\n description: 'POST request with JSON body',\n defaults: {\n method: 'POST',\n bodyType: 'json',\n headers: { 'Content-Type': 'application/json' },\n },\n },\n 'api-test': {\n name: 'API Test',\n description: 'Request with validation and response time check',\n defaults: {\n method: 'GET',\n expectStatus: 200,\n expectResponseTime: '< 2000',\n verbose: true,\n showHeaders: true,\n },\n },\n 'file-upload': {\n name: 'File Upload',\n description: 'Multipart form upload request',\n defaults: {\n method: 'POST',\n bodyType: 'form',\n },\n },\n 'auth-flow': {\n name: 'Auth Flow',\n description: 'Request with authentication',\n defaults: {\n method: 'POST',\n authType: 'bearer',\n headers: { 'Content-Type': 'application/json' },\n },\n },\n};\n\nexport function getTemplate(name: WizardTemplate): TemplateConfig {\n return TEMPLATES[name];\n}\n\nexport function getTemplateChoices(): { value: WizardTemplate; label: string; hint: string }[] {\n return Object.entries(TEMPLATES).map(([key, config]) => ({\n value: key as WizardTemplate,\n label: config.name,\n hint: config.description,\n }));\n}\n",
|
|
58
|
+
"/**\n * Interactive prompts for the wizard using @clack/prompts.\n */\n\nimport * as p from '@clack/prompts';\nimport { getTemplateChoices } from './templates';\nimport type { WizardAnswers, WizardTemplate } from './types';\n\nconst HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as const;\n\n/**\n * Prompts for template selection.\n */\nexport async function promptTemplate(): Promise<WizardTemplate | 'blank' | symbol> {\n const choices = [\n { value: 'blank' as const, label: 'Blank', hint: 'Start from scratch' },\n ...getTemplateChoices(),\n ];\n\n return p.select({\n message: 'Start from a template?',\n options: choices,\n });\n}\n\n/**\n * Prompts for request basics (URL, method, name).\n */\nexport async function promptBasics(\n defaults?: Partial<WizardAnswers>,\n): Promise<Pick<WizardAnswers, 'name' | 'url' | 'method'> | symbol> {\n const result = await p.group(\n {\n url: () =>\n p.text({\n message: 'Request URL',\n placeholder: 'https://api.example.com/endpoint',\n initialValue: defaults?.url || '',\n validate: (value) => {\n if (!value) {\n return 'URL is required';\n }\n try {\n new URL(value);\n } catch {\n return 'Invalid URL format';\n }\n },\n }),\n method: () =>\n p.select({\n message: 'HTTP method',\n initialValue: defaults?.method || 'GET',\n options: HTTP_METHODS.map((m) => ({ value: m, label: m })),\n }),\n name: () =>\n p.text({\n message: 'Request name (optional)',\n placeholder: 'My API Request',\n initialValue: defaults?.name || '',\n }),\n },\n {\n onCancel: () => {\n p.cancel('Wizard cancelled');\n process.exit(0);\n },\n },\n );\n\n return result as Pick<WizardAnswers, 'name' | 'url' | 'method'>;\n}\n\n/**\n * Prompts for headers configuration.\n */\nexport async function promptHeaders(\n defaults?: Record<string, string>,\n): Promise<Record<string, string> | undefined | symbol> {\n const addHeaders = await p.confirm({\n message: 'Add headers?',\n initialValue: defaults ? Object.keys(defaults).length > 0 : false,\n });\n\n if (p.isCancel(addHeaders) || !addHeaders) {\n return p.isCancel(addHeaders) ? addHeaders : defaults;\n }\n\n const headers: Record<string, string> = { ...defaults };\n let addMore = true;\n\n // Common header presets\n const presets = await p.multiselect({\n message: 'Add common headers (space to select)',\n options: [\n { value: 'content-type-json', label: 'Content-Type: application/json' },\n { value: 'accept-json', label: 'Accept: application/json' },\n { value: 'user-agent', label: 'User-Agent: curl-runner' },\n ],\n required: false,\n });\n\n if (p.isCancel(presets)) {\n return presets;\n }\n\n if (Array.isArray(presets)) {\n for (const preset of presets) {\n if (preset === 'content-type-json') {\n headers['Content-Type'] = 'application/json';\n }\n if (preset === 'accept-json') {\n headers.Accept = 'application/json';\n }\n if (preset === 'user-agent') {\n headers['User-Agent'] = 'curl-runner';\n }\n }\n }\n\n // Custom headers\n while (addMore) {\n const addCustom = await p.confirm({\n message: 'Add custom header?',\n initialValue: false,\n });\n\n if (p.isCancel(addCustom)) {\n return addCustom;\n }\n if (!addCustom) {\n break;\n }\n\n const header = await p.group({\n key: () =>\n p.text({\n message: 'Header name',\n placeholder: 'X-Custom-Header',\n validate: (v) => (!v ? 'Header name required' : undefined),\n }),\n value: () =>\n p.text({\n message: 'Header value',\n placeholder: 'value',\n validate: (v) => (!v ? 'Header value required' : undefined),\n }),\n });\n\n if (header.key && header.value) {\n headers[header.key] = header.value;\n }\n\n addMore = true;\n }\n\n return Object.keys(headers).length > 0 ? headers : undefined;\n}\n\n/**\n * Prompts for request body configuration.\n */\nexport async function promptBody(\n defaults?: Partial<WizardAnswers>,\n): Promise<Pick<WizardAnswers, 'bodyType' | 'body' | 'formData'> | symbol> {\n const bodyType = await p.select({\n message: 'Request body type',\n initialValue: defaults?.bodyType || 'none',\n options: [\n { value: 'none', label: 'None', hint: 'No request body' },\n { value: 'json', label: 'JSON', hint: 'JSON object' },\n { value: 'form', label: 'Form Data', hint: 'Multipart form / file upload' },\n { value: 'raw', label: 'Raw', hint: 'Plain text or other' },\n ],\n });\n\n if (p.isCancel(bodyType)) {\n return bodyType;\n }\n\n if (bodyType === 'none') {\n return { bodyType: 'none' };\n }\n\n if (bodyType === 'json') {\n const bodyText = await p.text({\n message: 'JSON body (or press enter for interactive)',\n placeholder: '{\"key\": \"value\"}',\n initialValue: defaults?.body ? JSON.stringify(defaults.body) : '',\n });\n\n if (p.isCancel(bodyText)) {\n return bodyText;\n }\n\n if (bodyText) {\n try {\n const parsed = JSON.parse(bodyText);\n return { bodyType: 'json', body: parsed };\n } catch {\n p.log.warn('Invalid JSON, storing as raw string');\n return { bodyType: 'raw', body: bodyText };\n }\n }\n\n // Interactive JSON builder\n const jsonBody: Record<string, unknown> = {};\n let addMore = true;\n\n while (addMore) {\n const field = await p.group({\n key: () =>\n p.text({\n message: 'Field name',\n placeholder: 'key',\n }),\n value: () =>\n p.text({\n message: 'Field value',\n placeholder: 'value',\n }),\n type: () =>\n p.select({\n message: 'Value type',\n options: [\n { value: 'string', label: 'String' },\n { value: 'number', label: 'Number' },\n { value: 'boolean', label: 'Boolean' },\n ],\n }),\n });\n\n if (field.key) {\n if (field.type === 'number') {\n jsonBody[field.key] = Number(field.value);\n } else if (field.type === 'boolean') {\n jsonBody[field.key] = field.value === 'true';\n } else {\n jsonBody[field.key] = field.value;\n }\n }\n\n const more = await p.confirm({\n message: 'Add another field?',\n initialValue: false,\n });\n\n if (p.isCancel(more)) {\n return more;\n }\n addMore = more;\n }\n\n return { bodyType: 'json', body: jsonBody };\n }\n\n if (bodyType === 'form') {\n const formData: Record<string, string | { file: string }> = {};\n let addMore = true;\n\n while (addMore) {\n const fieldType = await p.select({\n message: 'Field type',\n options: [\n { value: 'text', label: 'Text field' },\n { value: 'file', label: 'File upload' },\n ],\n });\n\n if (p.isCancel(fieldType)) {\n return fieldType;\n }\n\n const fieldName = await p.text({\n message: 'Field name',\n placeholder: fieldType === 'file' ? 'file' : 'field',\n validate: (v) => (!v ? 'Field name required' : undefined),\n });\n\n if (p.isCancel(fieldName)) {\n return fieldName;\n }\n\n if (fieldType === 'file') {\n const filePath = await p.text({\n message: 'File path',\n placeholder: './upload.txt',\n validate: (v) => (!v ? 'File path required' : undefined),\n });\n\n if (p.isCancel(filePath)) {\n return filePath;\n }\n formData[fieldName] = { file: filePath };\n } else {\n const fieldValue = await p.text({\n message: 'Field value',\n placeholder: 'value',\n });\n\n if (p.isCancel(fieldValue)) {\n return fieldValue;\n }\n formData[fieldName] = fieldValue;\n }\n\n const more = await p.confirm({\n message: 'Add another field?',\n initialValue: false,\n });\n\n if (p.isCancel(more)) {\n return more;\n }\n addMore = more;\n }\n\n return { bodyType: 'form', formData };\n }\n\n // Raw body\n const rawBody = await p.text({\n message: 'Raw body content',\n placeholder: 'Your content here',\n initialValue: (defaults?.body as string) || '',\n });\n\n if (p.isCancel(rawBody)) {\n return rawBody;\n }\n return { bodyType: 'raw', body: rawBody };\n}\n\n/**\n * Prompts for authentication configuration.\n */\nexport async function promptAuth(\n defaults?: Partial<WizardAnswers>,\n): Promise<Pick<WizardAnswers, 'authType' | 'username' | 'password' | 'token'> | symbol> {\n const authType = await p.select({\n message: 'Authentication',\n initialValue: defaults?.authType || 'none',\n options: [\n { value: 'none', label: 'None' },\n { value: 'bearer', label: 'Bearer Token', hint: 'Authorization: Bearer <token>' },\n { value: 'basic', label: 'Basic Auth', hint: 'Username/password' },\n ],\n });\n\n if (p.isCancel(authType)) {\n return authType;\n }\n\n if (authType === 'none') {\n return { authType: 'none' };\n }\n\n if (authType === 'bearer') {\n const token = await p.text({\n message: 'Bearer token',\n placeholder: 'your-token-here',\n initialValue: defaults?.token || '',\n validate: (v) => (!v ? 'Token required' : undefined),\n });\n\n if (p.isCancel(token)) {\n return token;\n }\n return { authType: 'bearer', token };\n }\n\n // Basic auth\n const creds = await p.group({\n username: () =>\n p.text({\n message: 'Username',\n initialValue: defaults?.username || '',\n validate: (v) => (!v ? 'Username required' : undefined),\n }),\n password: () =>\n p.password({\n message: 'Password',\n validate: (v) => (!v ? 'Password required' : undefined),\n }),\n });\n\n if (p.isCancel(creds.username) || p.isCancel(creds.password)) {\n return Symbol('cancel');\n }\n\n return { authType: 'basic', username: creds.username, password: creds.password };\n}\n\n/**\n * Prompts for advanced options.\n */\nexport async function promptAdvanced(\n defaults?: Partial<WizardAnswers>,\n): Promise<Partial<WizardAnswers> | symbol> {\n const configure = await p.confirm({\n message: 'Configure advanced options?',\n initialValue: false,\n });\n\n if (p.isCancel(configure) || !configure) {\n return p.isCancel(configure) ? configure : {};\n }\n\n const options = await p.group({\n timeout: () =>\n p.text({\n message: 'Timeout (ms)',\n placeholder: '30000',\n initialValue: defaults?.timeout?.toString() || '',\n validate: (v) => {\n if (!v) {\n return undefined;\n }\n const num = Number(v);\n if (Number.isNaN(num) || num < 0) {\n return 'Must be a positive number';\n }\n },\n }),\n followRedirects: () =>\n p.confirm({\n message: 'Follow redirects?',\n initialValue: defaults?.followRedirects ?? true,\n }),\n insecure: () =>\n p.confirm({\n message: 'Skip SSL verification? (insecure)',\n initialValue: defaults?.insecure ?? false,\n }),\n http2: () =>\n p.confirm({\n message: 'Use HTTP/2?',\n initialValue: defaults?.http2 ?? false,\n }),\n });\n\n const result: Partial<WizardAnswers> = {};\n\n if (options.timeout) {\n result.timeout = Number(options.timeout);\n }\n if (options.followRedirects === false) {\n result.followRedirects = false;\n }\n if (options.insecure) {\n result.insecure = true;\n }\n if (options.http2) {\n result.http2 = true;\n }\n\n return result;\n}\n\n/**\n * Prompts for retry configuration.\n */\nexport async function promptRetry(\n defaults?: Partial<WizardAnswers>,\n): Promise<Partial<WizardAnswers> | symbol> {\n const configure = await p.confirm({\n message: 'Configure retry strategy?',\n initialValue: defaults?.retryEnabled ?? false,\n });\n\n if (p.isCancel(configure) || !configure) {\n return p.isCancel(configure) ? configure : {};\n }\n\n const retry = await p.group({\n count: () =>\n p.text({\n message: 'Max retry attempts',\n placeholder: '3',\n initialValue: defaults?.retryCount?.toString() || '3',\n validate: (v) => {\n const num = Number(v);\n if (Number.isNaN(num) || num < 1) {\n return 'Must be at least 1';\n }\n },\n }),\n delay: () =>\n p.text({\n message: 'Retry delay (ms)',\n placeholder: '1000',\n initialValue: defaults?.retryDelay?.toString() || '1000',\n validate: (v) => {\n if (!v) {\n return undefined;\n }\n const num = Number(v);\n if (Number.isNaN(num) || num < 0) {\n return 'Must be a positive number';\n }\n },\n }),\n backoff: () =>\n p.text({\n message: 'Backoff multiplier',\n placeholder: '2 (exponential)',\n initialValue: defaults?.retryBackoff?.toString() || '',\n validate: (v) => {\n if (!v) {\n return undefined;\n }\n const num = Number(v);\n if (Number.isNaN(num) || num < 1) {\n return 'Must be at least 1';\n }\n },\n }),\n });\n\n return {\n retryEnabled: true,\n retryCount: Number(retry.count),\n retryDelay: retry.delay ? Number(retry.delay) : undefined,\n retryBackoff: retry.backoff ? Number(retry.backoff) : undefined,\n };\n}\n\n/**\n * Prompts for validation/expect configuration.\n */\nexport async function promptValidation(\n defaults?: Partial<WizardAnswers>,\n): Promise<Partial<WizardAnswers> | symbol> {\n const configure = await p.confirm({\n message: 'Add response validation?',\n initialValue: !!(defaults?.expectStatus || defaults?.expectResponseTime),\n });\n\n if (p.isCancel(configure) || !configure) {\n return p.isCancel(configure) ? configure : {};\n }\n\n const validation = await p.group({\n status: () =>\n p.text({\n message: 'Expected status code(s)',\n placeholder: '200 or 200,201',\n initialValue: defaults?.expectStatus\n ? Array.isArray(defaults.expectStatus)\n ? defaults.expectStatus.join(',')\n : String(defaults.expectStatus)\n : '',\n }),\n responseTime: () =>\n p.text({\n message: 'Response time constraint',\n placeholder: '< 2000 (ms)',\n initialValue: defaults?.expectResponseTime || '',\n }),\n });\n\n const result: Partial<WizardAnswers> = {};\n\n if (validation.status) {\n const codes = validation.status.split(',').map((s) => Number(s.trim()));\n result.expectStatus = codes.length === 1 ? codes[0] : codes;\n }\n if (validation.responseTime) {\n result.expectResponseTime = validation.responseTime;\n }\n\n return result;\n}\n\n/**\n * Prompts for output configuration.\n */\nexport async function promptOutput(\n defaults?: Partial<WizardAnswers>,\n): Promise<{ outputPath: string; runAfter: boolean } | symbol> {\n const result = await p.group({\n outputPath: () =>\n p.text({\n message: 'Save to file',\n placeholder: 'api-request.yaml',\n initialValue: defaults?.outputFile || 'request.yaml',\n validate: (v) => {\n if (!v) {\n return 'File path required';\n }\n if (!v.endsWith('.yaml') && !v.endsWith('.yml')) {\n return 'File must end with .yaml or .yml';\n }\n },\n }),\n runAfter: () =>\n p.confirm({\n message: 'Run request after creating?',\n initialValue: true,\n }),\n });\n\n return result as { outputPath: string; runAfter: boolean };\n}\n",
|
|
59
|
+
"/**\n * Builds YAML configuration from wizard answers.\n */\n\nimport type { JsonValue, RequestConfig } from '../types/config';\nimport type { WizardAnswers } from './types';\n\nexport interface YamlOutput {\n request: RequestConfig;\n}\n\n/**\n * Converts wizard answers to a RequestConfig object.\n */\nexport function buildRequestConfig(answers: WizardAnswers): RequestConfig {\n const config: RequestConfig = {\n url: answers.url,\n };\n\n // Name\n if (answers.name) {\n config.name = answers.name;\n }\n\n // Method (only include if not GET)\n if (answers.method && answers.method !== 'GET') {\n config.method = answers.method;\n }\n\n // Headers\n if (answers.headers && Object.keys(answers.headers).length > 0) {\n config.headers = answers.headers;\n }\n\n // Query params\n if (answers.params && Object.keys(answers.params).length > 0) {\n config.params = answers.params;\n }\n\n // Body\n if (answers.bodyType === 'json' && answers.body) {\n config.body = answers.body as JsonValue;\n } else if (answers.bodyType === 'form' && answers.formData) {\n config.formData = answers.formData;\n } else if (answers.bodyType === 'raw' && answers.body) {\n config.body = answers.body as string;\n }\n\n // Auth\n if (answers.authType === 'basic' && answers.username) {\n config.auth = {\n type: 'basic',\n username: answers.username,\n password: answers.password || '',\n };\n } else if (answers.authType === 'bearer' && answers.token) {\n config.auth = {\n type: 'bearer',\n token: answers.token,\n };\n }\n\n // Timeout\n if (answers.timeout) {\n config.timeout = answers.timeout;\n }\n\n // Redirects\n if (answers.followRedirects === false) {\n config.followRedirects = false;\n }\n if (answers.maxRedirects) {\n config.maxRedirects = answers.maxRedirects;\n }\n\n // SSL\n if (answers.insecure) {\n config.insecure = true;\n }\n\n // HTTP/2\n if (answers.http2) {\n config.http2 = true;\n }\n\n // Retry\n if (answers.retryEnabled && answers.retryCount) {\n config.retry = {\n count: answers.retryCount,\n };\n if (answers.retryDelay) {\n config.retry.delay = answers.retryDelay;\n }\n if (answers.retryBackoff) {\n config.retry.backoff = answers.retryBackoff;\n }\n }\n\n // Validation (expect)\n if (answers.expectStatus || answers.expectResponseTime) {\n config.expect = {};\n if (answers.expectStatus) {\n config.expect.status = answers.expectStatus;\n }\n if (answers.expectResponseTime) {\n config.expect.responseTime = answers.expectResponseTime;\n }\n }\n\n // Output file\n if (answers.outputFile) {\n config.output = answers.outputFile;\n }\n\n return config;\n}\n\n/**\n * Converts wizard answers to full YAML structure.\n */\nexport function buildYamlConfig(answers: WizardAnswers): YamlOutput {\n return {\n request: buildRequestConfig(answers),\n };\n}\n\n/**\n * Serializes config to YAML string.\n */\nexport function toYamlString(config: YamlOutput): string {\n return serializeToYaml(config);\n}\n\n/**\n * Custom YAML serializer for clean output.\n * Uses Bun's YAML stringify but with formatting.\n */\nfunction serializeToYaml(obj: unknown, indent = 0): string {\n const spaces = ' '.repeat(indent);\n\n if (obj === null || obj === undefined) {\n return 'null';\n }\n\n if (typeof obj === 'string') {\n // Check if string needs quoting\n if (\n obj.includes(':') ||\n obj.includes('#') ||\n obj.includes('\\n') ||\n obj.startsWith(' ') ||\n obj.endsWith(' ') ||\n /^[0-9]/.test(obj) ||\n ['true', 'false', 'null', 'yes', 'no'].includes(obj.toLowerCase())\n ) {\n return JSON.stringify(obj);\n }\n return obj;\n }\n\n if (typeof obj === 'number' || typeof obj === 'boolean') {\n return String(obj);\n }\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) {\n return '[]';\n }\n\n // Check if simple array (all primitives)\n if (obj.every((item) => typeof item !== 'object' || item === null)) {\n return `[${obj.map((item) => serializeToYaml(item, 0)).join(', ')}]`;\n }\n\n return obj\n .map((item) => `${spaces}- ${serializeToYaml(item, indent + 1).trimStart()}`)\n .join('\\n');\n }\n\n if (typeof obj === 'object') {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) {\n return '{}';\n }\n\n const lines: string[] = [];\n for (const [key, value] of entries) {\n if (value === undefined) {\n continue;\n }\n\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n lines.push(`${spaces}${key}:`);\n const nested = serializeToYaml(value, indent + 1);\n lines.push(nested);\n } else {\n const serialized = serializeToYaml(value, indent + 1);\n if (serialized.includes('\\n')) {\n lines.push(`${spaces}${key}:`);\n lines.push(serialized);\n } else {\n lines.push(`${spaces}${key}: ${serialized}`);\n }\n }\n }\n\n return lines.join('\\n');\n }\n\n return String(obj);\n}\n",
|
|
60
|
+
"/**\n * YAML Wizard - Interactive CLI for creating curl-runner YAML files.\n */\n\nimport * as p from '@clack/prompts';\nimport { getVersion } from '../version';\nimport { fileExists, loadYamlFile } from './parser';\nimport {\n promptAdvanced,\n promptAuth,\n promptBasics,\n promptBody,\n promptHeaders,\n promptOutput,\n promptRetry,\n promptTemplate,\n promptValidation,\n} from './prompts';\nimport { getTemplate } from './templates';\nimport type { WizardAnswers, WizardOptions, WizardTemplate } from './types';\nimport { buildYamlConfig, toYamlString } from './yaml-builder';\n\nexport type { WizardAnswers, WizardOptions } from './types';\n\n/**\n * Main wizard entry point.\n */\nexport async function runWizard(options: WizardOptions = {}): Promise<void> {\n p.intro(`curl-runner wizard v${getVersion()}`);\n\n let answers: WizardAnswers;\n\n // Edit mode - load existing file\n if (options.editFile) {\n if (!(await fileExists(options.editFile))) {\n p.cancel(`File not found: ${options.editFile}`);\n process.exit(1);\n }\n\n p.log.info(`Editing: ${options.editFile}`);\n const existing = await loadYamlFile(options.editFile);\n answers = await runPromptFlow(existing);\n options.outputPath = options.outputPath || options.editFile;\n } else {\n // New file - start from template or blank\n const template = await promptTemplate();\n\n if (p.isCancel(template)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n\n const defaults =\n template === 'blank' ? undefined : getTemplate(template as WizardTemplate).defaults;\n\n answers = await runPromptFlow(defaults as Partial<WizardAnswers> | undefined);\n }\n\n // Output options\n const output = await promptOutput({\n outputFile: options.outputPath,\n });\n\n if (p.isCancel(output)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n\n // Build YAML\n const config = buildYamlConfig(answers);\n const yaml = toYamlString(config);\n\n // Preview\n p.log.step('Preview:');\n console.log();\n console.log(yaml);\n console.log();\n\n // Confirm save\n const confirm = await p.confirm({\n message: `Save to ${output.outputPath}?`,\n initialValue: true,\n });\n\n if (p.isCancel(confirm) || !confirm) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n\n // Write file\n await Bun.write(output.outputPath, yaml);\n p.log.success(`Saved to ${output.outputPath}`);\n\n // Run after create\n if (output.runAfter) {\n p.log.step('Running request...');\n console.log();\n\n const proc = Bun.spawn(['bun', 'run', process.argv[1], output.outputPath], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n\n await proc.exited;\n }\n\n p.outro('Done!');\n}\n\n/**\n * Runs the full prompt flow.\n */\nasync function runPromptFlow(defaults?: Partial<WizardAnswers>): Promise<WizardAnswers> {\n // Step 1: Basics (URL, method, name)\n const basics = await promptBasics(defaults);\n if (p.isCancel(basics)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n\n let answers: WizardAnswers = {\n ...defaults,\n ...basics,\n } as WizardAnswers;\n\n // Step 2: Headers\n const headers = await promptHeaders(defaults?.headers);\n if (p.isCancel(headers)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n if (headers) {\n answers.headers = headers;\n }\n\n // Step 3: Body (skip for GET/HEAD/OPTIONS)\n if (!['GET', 'HEAD', 'OPTIONS'].includes(answers.method)) {\n const body = await promptBody(defaults);\n if (p.isCancel(body)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n answers = { ...answers, ...body };\n }\n\n // Step 4: Auth\n const auth = await promptAuth(defaults);\n if (p.isCancel(auth)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n answers = { ...answers, ...auth };\n\n // Step 5: Advanced options\n const advanced = await promptAdvanced(defaults);\n if (p.isCancel(advanced)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n answers = { ...answers, ...advanced };\n\n // Step 6: Retry\n const retry = await promptRetry(defaults);\n if (p.isCancel(retry)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n answers = { ...answers, ...retry };\n\n // Step 7: Validation\n const validation = await promptValidation(defaults);\n if (p.isCancel(validation)) {\n p.cancel('Wizard cancelled');\n process.exit(0);\n }\n answers = { ...answers, ...validation };\n\n return answers;\n}\n\n/**\n * Quick init - creates a simple request without full wizard.\n */\nexport async function quickInit(url?: string): Promise<void> {\n p.intro('curl-runner quick init');\n\n const urlInput =\n url ||\n (await p.text({\n message: 'Request URL',\n placeholder: 'https://api.example.com/endpoint',\n validate: (value) => {\n if (!value) {\n return 'URL is required';\n }\n try {\n new URL(value);\n } catch {\n return 'Invalid URL format';\n }\n },\n }));\n\n if (p.isCancel(urlInput)) {\n p.cancel('Cancelled');\n process.exit(0);\n }\n\n const method = await p.select({\n message: 'HTTP method',\n initialValue: 'GET' as const,\n options: [\n { value: 'GET' as const, label: 'GET' },\n { value: 'POST' as const, label: 'POST' },\n { value: 'PUT' as const, label: 'PUT' },\n { value: 'DELETE' as const, label: 'DELETE' },\n ],\n });\n\n if (p.isCancel(method)) {\n p.cancel('Cancelled');\n process.exit(0);\n }\n\n const filename = await p.text({\n message: 'Save to',\n placeholder: 'request.yaml',\n initialValue: 'request.yaml',\n validate: (v) => {\n if (!v) {\n return 'Filename required';\n }\n if (!v.endsWith('.yaml') && !v.endsWith('.yml')) {\n return 'Must end with .yaml or .yml';\n }\n },\n });\n\n if (p.isCancel(filename)) {\n p.cancel('Cancelled');\n process.exit(0);\n }\n\n const config = buildYamlConfig({\n url: urlInput,\n method: method,\n });\n\n const yaml = toYamlString(config);\n\n await Bun.write(filename, yaml);\n p.log.success(`Created ${filename}`);\n\n const run = await p.confirm({\n message: 'Run now?',\n initialValue: true,\n });\n\n if (p.isCancel(run)) {\n p.outro('Done!');\n return;\n }\n\n if (run) {\n console.log();\n const proc = Bun.spawn(['bun', 'run', process.argv[1], filename], {\n stdout: 'inherit',\n stderr: 'inherit',\n });\n await proc.exited;\n }\n\n p.outro('Done!');\n}\n"
|
|
61
|
+
],
|
|
62
|
+
"mappings": "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AAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAG,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,KAAG,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,G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AAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAG,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,KAAG,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,IAAI,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,IAAI,QAAQ,IAAI,QAAQ,GAAG,Q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",
|
|
63
|
+
"debugId": "370B90C78426925364756E2164756E21",
|
|
64
|
+
"names": []
|
|
65
|
+
}
|