@contractkit/cli
Advanced tools
| > @contractkit/cli@0.9.0 build:ci /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > @contractkit/cli@0.9.1 build:ci /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > eslint --max-warnings=0 && pnpm run build | ||
| > @contractkit/cli@0.9.0 build /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > @contractkit/cli@0.9.1 build /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > tsup src/cli.ts --format esm --sourcemap | ||
@@ -14,4 +14,4 @@ | ||
| [34mESM[39m Build start | ||
| [32mESM[39m [1mdist/cli.js [22m[32m21.20 KB[39m | ||
| [32mESM[39m [1mdist/cli.js.map [22m[32m53.87 KB[39m | ||
| [32mESM[39m ⚡️ Build success in 41ms | ||
| [32mESM[39m [1mdist/cli.js [22m[32m21.26 KB[39m | ||
| [32mESM[39m [1mdist/cli.js.map [22m[32m54.36 KB[39m | ||
| [32mESM[39m ⚡️ Build success in 43ms |
| > @contractkit/cli@0.9.0 test:ci /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > @contractkit/cli@0.9.1 test:ci /home/runner/work/ContractKit/ContractKit/apps/cli | ||
| > vitest run --coverage | ||
@@ -9,10 +9,10 @@ | ||
| [32m✓[39m tests/config.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 10[2mms[22m[39m | ||
| [32m✓[39m tests/cache.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 17[2mms[22m[39m | ||
| [32m✓[39m tests/resolve-plugin-extensions.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 18[2mms[22m[39m | ||
| [32m✓[39m tests/config.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 12[2mms[22m[39m | ||
| [32m✓[39m tests/resolve-plugin-extensions.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 19[2mms[22m[39m | ||
| [2m Test Files [22m [1m[32m3 passed[39m[22m[90m (3)[39m | ||
| [2m Tests [22m [1m[32m36 passed[39m[22m[90m (36)[39m | ||
| [2m Start at [22m 12:37:14 | ||
| [2m Duration [22m 777ms[2m (transform 264ms, setup 0ms, import 669ms, tests 44ms, environment 1ms)[22m | ||
| [2m Start at [22m 11:09:15 | ||
| [2m Duration [22m 726ms[2m (transform 234ms, setup 0ms, import 659ms, tests 48ms, environment 1ms)[22m | ||
@@ -19,0 +19,0 @@ [34m % [39m[2mCoverage report from [22m[33mv8[39m |
+9
-0
| # @contractkit/cli | ||
| ## 0.9.1 | ||
| ### Patch Changes | ||
| - 10ca07b: Add per-output incremental caching to the Bruno, Python, and TypeScript plugins. Editing a single contract or operation no longer regenerates every output file — only the units whose transitive inputs actually changed are re-rendered, with the rest reused from a per-plugin manifest. `@contractkit/core` exposes the shared utility (`runIncrementalCodegen`, `parseIncrementalManifest`, `hashFingerprint`, `collectTransitiveModelRefs`, manifest types) for plugin authors. `PluginContext` gains a `cacheEnabled` flag so plugins can honor `--force` / `cache: false`. | ||
| - Updated dependencies [10ca07b] | ||
| - @contractkit/core@0.15.0 | ||
| - @contractkit/openapi-to-ck@0.7.5 | ||
| ## 0.9.0 | ||
@@ -4,0 +13,0 @@ |
@@ -460,3 +460,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-06T12:37:15.129Z | ||
| at 2026-05-07T11:09:16.146Z | ||
| </div> | ||
@@ -463,0 +463,0 @@ <script src="prettify.js"></script> |
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <coverage generated="1778071035135" clover="3.2.0"> | ||
| <project timestamp="1778071035135" name="All files"> | ||
| <coverage generated="1778152156152" clover="3.2.0"> | ||
| <project timestamp="1778152156152" name="All files"> | ||
| <metrics statements="106" coveredstatements="85" conditionals="61" coveredconditionals="53" methods="19" coveredmethods="17" elements="186" coveredelements="155" complexity="0" loc="106" ncloc="106" packages="1" files="3" classes="3"/> | ||
@@ -5,0 +5,0 @@ <file name="cache.ts" path="/home/runner/work/ContractKit/ContractKit/apps/cli/src/cache.ts"> |
@@ -469,3 +469,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-06T12:37:15.129Z | ||
| at 2026-05-07T11:09:16.146Z | ||
| </div> | ||
@@ -472,0 +472,0 @@ <script src="prettify.js"></script> |
@@ -134,3 +134,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-06T12:37:15.129Z | ||
| at 2026-05-07T11:09:16.146Z | ||
| </div> | ||
@@ -137,0 +137,0 @@ <script src="prettify.js"></script> |
@@ -442,3 +442,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-06T12:37:15.129Z | ||
| at 2026-05-07T11:09:16.146Z | ||
| </div> | ||
@@ -445,0 +445,0 @@ <script src="prettify.js"></script> |
+4
-3
@@ -196,6 +196,7 @@ #!/usr/bin/env node | ||
| __name(loadPlugins, "loadPlugins"); | ||
| function makePluginContext(entry, config, emitFile) { | ||
| function makePluginContext(entry, config, cacheEnabled, emitFile) { | ||
| return { | ||
| rootDir: config.rootDir, | ||
| options: entry.options ?? {}, | ||
| cacheEnabled, | ||
| emitFile: emitFile ?? (() => { | ||
@@ -485,3 +486,3 @@ throw new Error("emitFile is only available in generateTargets"); | ||
| for (const { plugin, entry } of plugins) { | ||
| const ctx = makePluginContext(entry, config); | ||
| const ctx = makePluginContext(entry, config, cacheEnabled); | ||
| if (plugin.validate) { | ||
@@ -571,3 +572,3 @@ try { | ||
| const pluginEmitted = []; | ||
| const ctx = makePluginContext(entry, config, (outPath, content) => { | ||
| const ctx = makePluginContext(entry, config, cacheEnabled, (outPath, content) => { | ||
| pluginEmitted.push({ | ||
@@ -574,0 +575,0 @@ outPath, |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/cache.ts","../src/plugin.ts","../src/resolve-plugin-extensions.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ─── Built-in command plugins ─────────────────────────────────────────────\n// Each plugin may expose a `command` hook — the CLI dispatches subcommands\n// to the first plugin whose command.name matches argv[2].\nimport { default as importOpenApiPlugin } from '@contractkit/openapi-to-ck/plugin';\n\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { resolve, join, dirname } from 'node:path';\nimport { glob } from 'glob';\nimport {\n DiagnosticCollector,\n parseCk,\n decomposeCk,\n validateOp,\n validateRefs,\n validateInheritance,\n applyOptionsDefaults,\n applyVariableSubstitution,\n computeModelsWithInput,\n computeModelsWithOutput,\n} from '@contractkit/core';\nimport type { ContractRootNode, OpRootNode, ContractKitPlugin } from '@contractkit/core';\nimport { loadConfig, mergeConfig, type PluginEntry } from './config.js';\nimport { CacheService, computeHash } from './cache.js';\nimport { loadPlugins, makePluginContext, computePluginFingerprint, pluginOutputsExist } from './plugin.js';\nimport { resolvePluginExtensions } from './resolve-plugin-extensions.js';\nimport type { FileHashMap } from './cache.js';\n\n// ─── Arg parsing ───────────────────────────────────────────────────────────\n\ninterface CliArgs {\n config?: string;\n watch: boolean;\n force: boolean;\n help: boolean;\n}\n\nconst BUILTIN_COMMAND_PLUGINS = [importOpenApiPlugin];\n\nfunction printHelp(): void {\n console.log('Usage: contractkit [command] [options]');\n console.log('');\n console.log('Commands:');\n for (const plugin of BUILTIN_COMMAND_PLUGINS) {\n if (plugin.command) {\n console.log(` ${plugin.command.name.padEnd(20)} ${plugin.command.description}`);\n }\n }\n console.log('');\n console.log('Options:');\n console.log(' -c, --config <path> Path to config file (default: contractkit.config.json)');\n console.log(' -w, --watch Watch for changes and recompile');\n console.log(' --force Skip cache and recompile all files');\n console.log(' -h, --help Show this help message');\n console.log('');\n console.log('Configure patterns, output dirs, and plugins in contractkit.config.json.');\n}\n\nfunction parseArgs(argv: string[]): CliArgs {\n const args = argv.slice(2);\n let config: string | undefined;\n let watch = false;\n let force = false;\n let help = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === '--config' || arg === '-c') {\n config = args[++i];\n } else if (arg === '--watch' || arg === '-w') {\n watch = true;\n } else if (arg === '--force') {\n force = true;\n } else if (arg === '--help' || arg === '-h') {\n help = true;\n }\n }\n\n return { config, watch, force, help };\n}\n\n// ─── Fallback keys for {{var}} substitution ────────────────────────────────\n\n/**\n * Built-in variables available inside plugin-config `keys` values. These let a\n * user write `\"{{rootDir}}/path\"` in `contractkit.config.json` and have the\n * absolute resolved root substituted in at load time.\n */\nconst FALLBACK_BUILTINS_RE = /\\\\\\{\\{(\\w+)\\}\\}|\\{\\{(\\w+)\\}\\}/g;\n\nfunction substituteBuiltins(input: string, builtins: Record<string, string>, onMissing: (name: string) => void): string {\n if (!input.includes('{{')) return input;\n return input.replace(FALLBACK_BUILTINS_RE, (_match, escapedName: string | undefined, varName: string | undefined) => {\n if (escapedName !== undefined) return `{{${escapedName}}}`;\n const value = builtins[varName!];\n if (value === undefined) {\n onMissing(varName!);\n return 'undefined';\n }\n return value;\n });\n}\n\nfunction collectFallbackKeys(entries: PluginEntry[], builtins: Record<string, string>): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const entry of entries) {\n const keys = entry.options?.['keys'];\n if (keys === undefined) continue;\n if (typeof keys !== 'object' || keys === null || Array.isArray(keys)) {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys' must be an object of string→string; ignoring.`);\n continue;\n }\n for (const [name, value] of Object.entries(keys)) {\n if (typeof value !== 'string') {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys.${name}' must be a string; ignoring.`);\n continue;\n }\n merged[name] = substituteBuiltins(value, builtins, missing => {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys.${name}' references unknown built-in '{{${missing}}}'.`);\n });\n }\n }\n return merged;\n}\n\n// ─── File resolution ───────────────────────────────────────────────────────\n\nasync function resolveFiles(patterns: string[], rootDir: string): Promise<string[]> {\n const files: string[] = [];\n for (const pattern of patterns) {\n const matches = await glob(pattern, { absolute: true, cwd: resolve(rootDir) });\n files.push(...matches);\n }\n return [...new Set(files)];\n}\n\n// ─── Prettier formatting ──────────────────────────────────────────────────\n\nasync function formatWithPrettier(results: { outPath: string; content: string }[]): Promise<void> {\n let prettier: typeof import('prettier');\n try {\n prettier = await import('prettier');\n } catch {\n console.warn(' ⚠ prettier not found — skipping format step');\n return;\n }\n for (const result of results) {\n try {\n const options = (await prettier.resolveConfig(result.outPath)) ?? {};\n result.content = await prettier.format(result.content, {\n ...options,\n filepath: result.outPath,\n });\n } catch {\n // Leave content unformatted if prettier fails (e.g. unsupported parser)\n }\n }\n}\n\n// ─── Main ─────────────────────────────────────────────────────────────────\n\nasync function main() {\n const cliArgs = parseArgs(process.argv);\n\n if (cliArgs.help) {\n printHelp();\n process.exit(0);\n }\n\n // ── Built-in subcommand dispatch ──────────────────────────────────────\n const subcommand = process.argv[2];\n if (subcommand && !subcommand.startsWith('-')) {\n const matched = BUILTIN_COMMAND_PLUGINS.find(p => p.command?.name === subcommand);\n if (matched?.command) {\n const subArgs = process.argv.slice(3);\n if (subArgs.includes('--help') || subArgs.includes('-h')) {\n console.log(matched.command.usage);\n process.exit(0);\n }\n const { config: fileConfig, configDir } = loadConfig(cliArgs.config);\n const resolved = mergeConfig(fileConfig, { watch: false, force: false }, configDir);\n await matched.command.run(subArgs, { rootDir: resolved.rootDir, configDir });\n process.exit(0);\n }\n console.error(`Unknown command: \"${subcommand}\". Run \"contractkit --help\" for usage.`);\n process.exit(1);\n }\n\n const { config: fileConfig, configDir } = loadConfig(cliArgs.config);\n const config = mergeConfig(fileConfig, cliArgs, configDir);\n const plugins = await loadPlugins(config.plugins, config.configDir);\n\n // Merge `keys` from each plugin entry's options into a single workspace-wide fallback\n // map for `{{var}}` substitution. File-local `options { keys }` always wins; this map\n // catches anything that isn't defined per-file. Built-in variables (`rootDir`,\n // `configDir`) can be referenced inside the values themselves.\n const fallbackKeys = collectFallbackKeys(config.plugins, {\n rootDir: config.rootDir,\n configDir: config.configDir,\n });\n\n if (config.patterns.length === 0) {\n printHelp();\n process.exit(1);\n }\n\n const run = async () => {\n const files = await resolveFiles(config.patterns, config.rootDir);\n\n if (files.length === 0) {\n console.warn(`No matching files found for patterns:`, config.patterns.join(', '));\n return;\n }\n\n const diag = new DiagnosticCollector();\n const resolvedBase = resolve(config.rootDir);\n const cacheEnabled = config.cache.enabled && !config.force;\n const cacheService = new CacheService(resolvedBase, { enabled: cacheEnabled, dir: config.cache.dir });\n const cache: FileHashMap = cacheService.loadBuildCache();\n const newCache: FileHashMap = {};\n\n // ── Parse all .ck files ────────────────────────────────────────\n const allContracts: ContractRootNode[] = [];\n const allOps: OpRootNode[] = [];\n\n for (const filePath of files) {\n if (!filePath.endsWith('.ck')) {\n diag.warn(filePath, 0, `Skipping unknown file extension (expected .ck)`);\n continue;\n }\n\n const source = readFileSync(filePath, 'utf-8');\n newCache[filePath] = computeHash(source);\n\n let ckAst = parseCk(source, filePath, diag);\n // Merge options-level header globals into each operation before plugins run,\n // so transform/validate hooks see the fully-resolved AST.\n applyOptionsDefaults(ckAst, diag);\n applyVariableSubstitution(ckAst, diag, fallbackKeys);\n\n // Plugin: validate + transform hooks (run before decompose and cross-file validation)\n for (const { plugin, entry } of plugins) {\n const ctx = makePluginContext(entry, config);\n if (plugin.validate) {\n try {\n await plugin.validate(ckAst, ctx);\n } catch (err) {\n diag.error(filePath, 0, `[plugin:${plugin.name}] ${(err as Error).message}`);\n }\n }\n if (plugin.transform) {\n try {\n ckAst = await plugin.transform(ckAst, ctx);\n } catch (err) {\n diag.error(filePath, 0, `[plugin:${plugin.name}] ${(err as Error).message}`);\n }\n }\n }\n\n const { contract, op } = decomposeCk(ckAst);\n if (contract.models.length > 0) allContracts.push(contract);\n if (op.routes.length > 0) allOps.push(op);\n }\n\n // ── Resolve plugin extension URL references (file:// and http(s)://) ──\n await resolvePluginExtensions(allOps, resolvedBase, diag, { httpCache: cacheService.httpCache() });\n\n // ── Per-plugin extension validation ───────────────────────────\n const validatorsByName = new Map<string, NonNullable<ContractKitPlugin['validateExtension']>>();\n for (const { plugin } of plugins) {\n if (plugin.validateExtension) validatorsByName.set(plugin.name, plugin.validateExtension);\n }\n for (const root of allOps) {\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!op.pluginExtensions) continue;\n for (const [name, value] of Object.entries(op.pluginExtensions)) {\n const validator = validatorsByName.get(name);\n if (!validator) continue;\n const result = validator(value);\n if (!result) continue;\n if (result.errors) {\n for (const msg of result.errors) {\n diag.error(root.file, op.loc.line, `plugins.${name}: ${msg}`);\n }\n }\n if (result.warnings) {\n for (const msg of result.warnings) {\n diag.warn(root.file, op.loc.line, `plugins.${name}: ${msg}`);\n }\n }\n }\n }\n }\n }\n\n // ── Compute cross-file semantics ───────────────────────────────\n // modelsWithInput: which model names need an Input variant (have readonly/writeonly\n // fields, or transitively reference models that do). Used by all code generators.\n const modelsWithInput = computeModelsWithInput(allContracts.flatMap(r => r.models));\n // modelsWithOutput: which model names need an Output variant (have format(output=...),\n // or transitively reference models that do). Used by codegen for the post-transform\n // wire shape on response bodies.\n const modelsWithOutput = computeModelsWithOutput(allContracts.flatMap(r => r.models));\n\n // ── Dependency fingerprint ─────────────────────────────────────\n const depsFingerprint = computeHash([...modelsWithInput].sort().join(',') + '|' + [...modelsWithOutput].sort().join(','));\n const depsChanged = cacheEnabled && cache['__deps__'] !== depsFingerprint;\n newCache['__deps__'] = depsFingerprint;\n\n if (diag.hasErrors()) {\n diag.report();\n console.error('\\nCompilation failed.');\n process.exitCode = 1;\n return;\n }\n\n // ── Cross-file validation ──────────────────────────────────────\n validateRefs(allContracts, allOps, diag);\n validateInheritance(allContracts, diag);\n\n for (const op of allOps) {\n validateOp(op, diag);\n }\n\n // ── Generate via plugins ───────────────────────────────────────\n const results: { outPath: string; content: string }[] = [];\n\n for (const { plugin, entry } of plugins) {\n if (!plugin.generateTargets) continue;\n\n const optionsSuffix = entry.options && Object.keys(entry.options).length > 0 ? `:${JSON.stringify(entry.options)}` : '';\n const cacheKey = plugin.cacheKey ? `${plugin.cacheKey}${optionsSuffix}` : undefined;\n if (cacheKey && !config.force && cacheEnabled && !depsChanged) {\n const fingerprint = computePluginFingerprint(newCache, cacheKey);\n if (cache[`__plugin_${cacheKey}__`] === fingerprint && pluginOutputsExist(cache, cacheKey)) {\n console.log(` - [plugin:${plugin.name}] (unchanged)`);\n newCache[`__plugin_${cacheKey}__`] = fingerprint;\n newCache[`__plugin_${cacheKey}__files__`] = cache[`__plugin_${cacheKey}__files__`] ?? '';\n continue;\n }\n }\n\n const pluginEmitted: { outPath: string; content: string }[] = [];\n const ctx = makePluginContext(entry, config, (outPath, content) => {\n pluginEmitted.push({ outPath, content });\n });\n\n try {\n await plugin.generateTargets(\n {\n contractRoots: allContracts,\n opRoots: allOps,\n modelsWithInput,\n modelsWithOutput,\n },\n ctx,\n );\n } catch (err) {\n diag.error('', 0, `[plugin:${plugin.name}] generateTargets failed: ${(err as Error).message}`);\n continue;\n }\n\n results.push(...pluginEmitted);\n\n if (cacheKey) {\n newCache[`__plugin_${cacheKey}__`] = computePluginFingerprint(newCache, cacheKey);\n newCache[`__plugin_${cacheKey}__files__`] = pluginEmitted.map(f => f.outPath).join('|');\n }\n }\n\n if (diag.hasErrors()) {\n diag.report();\n console.error('\\nCompilation failed.');\n process.exitCode = 1;\n return;\n }\n\n // ── Format with prettier (opt-in) ────────────────────────────\n if (config.prettier && results.length > 0) {\n await formatWithPrettier(results);\n }\n\n // ── Write output files ──────────────────────────────────────\n mkdirSync(resolvedBase, { recursive: true });\n\n for (const { outPath, content } of results) {\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, 'utf-8');\n console.log(` ✓ ${outPath}`);\n }\n\n // Save cache\n if (config.cache.enabled) {\n cacheService.saveBuildCache(newCache);\n }\n\n // Report all collected warnings/errors after file writes so they\n // appear at the bottom of the output and are easy to spot.\n diag.report();\n\n console.log(`\\nCompiled ${results.length} file(s).`);\n };\n\n await run();\n\n if (config.watch) {\n const { watch } = await import('node:fs');\n const watchFiles = await resolveFiles(config.patterns, config.rootDir);\n const allDirs = new Set(watchFiles.map(f => dirname(f)));\n console.log('\\nWatching for changes...');\n for (const dir of allDirs) {\n watch(dir, { recursive: false }, async (event, filename) => {\n if (!filename) return;\n const full = join(dir, filename);\n if (!full.endsWith('.ck')) return;\n console.log(`\\nChange detected: ${filename}`);\n await run();\n });\n }\n }\n}\n\nmain().catch(err => {\n console.error('Unexpected error:', err);\n process.exit(1);\n});\n","import { readFileSync } from 'node:fs';\nimport { resolve, dirname, join } from 'node:path';\nimport { DEFAULT_CACHE_DIR } from './cache.js';\nimport { homedir } from 'node:os';\n\nexport interface PluginEntry {\n /** npm package name or local path relative to contractkit.config.json */\n plugin: string;\n /**\n * Plugin-specific options passed as ctx.options.\n *\n * One reserved key: `keys?: Record<string, string>`. Entries are merged across all plugin\n * entries into a workspace-wide fallback map for `{{var}}` substitution in `.ck` files.\n * A file's `options { keys }` block still wins over this fallback when both define a name.\n */\n options?: Record<string, unknown>;\n}\n\n/** Record-keyed plugin config: each key is the plugin package name, value is options. */\nexport type PluginsConfig = Record<string, Record<string, unknown>>;\n\n/** Raw shape of `contractkit.config.json` before CLI flag merge. All fields are optional. */\nexport interface DslConfig {\n rootDir?: string;\n /**\n * Build/HTTP caching control.\n * - `true` — enable, default directory `.contractkit/cache`\n * - `false` (default) — disabled\n * - `string` — enabled, treats the value as a custom cache directory (relative to `rootDir` or absolute)\n */\n cache?: boolean | string;\n /** Glob patterns for .ck files to compile, relative to rootDir. */\n patterns?: string[];\n /** Run prettier on generated TypeScript files after compilation. Default: false. */\n prettier?: boolean;\n /** Plugins to load: each key is the plugin package name, value is its options. */\n plugins?: PluginsConfig;\n}\n\n/** Resolved cache configuration produced by {@link mergeConfig}. */\nexport interface ResolvedCacheConfig {\n /** Whether the build/HTTP caches are active. `--force` does NOT flip this — it is gated separately at the CLI. */\n enabled: boolean;\n /** Directory (relative to `rootDir` or absolute) where caches live. */\n dir: string;\n}\n\nconst CONFIG_FILENAME = 'contractkit.config.json';\n\n/**\n * Load `contractkit.config.json` from an explicit path or by walking up from `startDir`.\n *\n * Returns the parsed config plus the directory that contained it (used to resolve relative\n * paths in the config). When no config is found anywhere on the path, returns an empty\n * config rooted at `startDir`.\n *\n * @throws if `configPath` is provided but the file cannot be read or parsed.\n */\nexport function loadConfig(configPath?: string, startDir: string = process.cwd()): { config: DslConfig; configDir: string } {\n if (configPath) {\n const resolved = resolve(configPath);\n try {\n const text = readFileSync(resolved, 'utf-8');\n return { config: JSON.parse(text) as DslConfig, configDir: dirname(resolved) };\n } catch (err) {\n throw new Error(`Failed to load config from ${resolved}: ${(err as Error).message}`, { cause: err });\n }\n }\n\n let dir = resolve(startDir);\n while (true) {\n const candidate = join(dir, CONFIG_FILENAME);\n try {\n const text = readFileSync(candidate, 'utf-8');\n return { config: JSON.parse(text) as DslConfig, configDir: dir };\n } catch {\n // File not found or invalid -- walk up\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return { config: {}, configDir: resolve(startDir) };\n}\n\n/** Fully resolved configuration: file values merged with CLI flags, paths absolutized, plugins normalized. */\nexport interface ResolvedConfig {\n patterns: string[];\n rootDir: string;\n cache: ResolvedCacheConfig;\n watch: boolean;\n force: boolean;\n prettier: boolean;\n plugins: PluginEntry[];\n configDir: string;\n}\n\nfunction normalizePlugins(plugins: PluginsConfig | undefined): PluginEntry[] {\n if (!plugins) return [];\n return Object.entries(plugins).map(([name, options]) => ({ plugin: name, options }));\n}\n\n/**\n * Merge a parsed {@link DslConfig} with CLI flags into a fully resolved configuration.\n *\n * Normalizes `cache` (boolean | string), expands a leading `~` in `rootDir`, resolves\n * `rootDir` to an absolute path, and converts the record-shaped `plugins` block into\n * an ordered `PluginEntry[]`.\n */\nexport function mergeConfig(config: DslConfig, cliArgs: { watch: boolean; force: boolean }, configDir: string = process.cwd()): ResolvedConfig {\n const cache: ResolvedCacheConfig =\n typeof config.cache === 'string'\n ? { enabled: true, dir: config.cache }\n : { enabled: config.cache === true, dir: DEFAULT_CACHE_DIR };\n\n let rootDir = config.rootDir ?? '.';\n if (rootDir.startsWith('~')) {\n rootDir = homedir() + rootDir.slice(1);\n }\n\n return {\n patterns: config.patterns ?? [],\n rootDir: resolve(rootDir),\n cache,\n watch: cliArgs.watch,\n force: cliArgs.force,\n prettier: config.prettier ?? false,\n plugins: normalizePlugins(config.plugins),\n configDir,\n };\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { join, dirname, resolve } from 'node:path';\n\n/** Default directory (relative to `rootDir`) where all CLI caches live. */\nexport const DEFAULT_CACHE_DIR = '.contractkit/cache';\nconst BUILD_CACHE_FILENAME = 'build.json';\nconst HTTP_CACHE_DIRNAME = 'http';\n\n/** Map of source file path → sha256 hex of its content (or synthetic keys like `__plugin_<key>__`). */\nexport interface FileHashMap {\n [filePath: string]: string;\n}\n\n/** Compute a stable sha256 hex digest for a string of content. */\nexport function computeHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n/**\n * Minimal key-value interface for plugin extension HTTP responses. `get` returns\n * `null` on a cache miss; `set` is best-effort and silently swallows write\n * failures so a broken cache never blocks the build.\n */\nexport interface HttpCache {\n get(url: string): string | null;\n set(url: string, body: string): void;\n}\n\nexport interface CacheServiceOptions {\n /** When false, every read returns empty/null and every write is a no-op. */\n enabled: boolean;\n /** Directory (relative to `rootDir` or absolute) used as the cache root. Defaults to `.contractkit/cache`. */\n dir?: string;\n}\n\n/**\n * Unified cache service. Owns one root directory under which both the build\n * cache (file/plugin hashes, single JSON file) and the HTTP response cache\n * (one blob per URL hash) live.\n *\n * Layout:\n * <root>/build.json — FileHashMap from the previous run\n * <root>/http/<sha256(url)> — fetched HTTP response bodies\n *\n * When `enabled` is false the service is a no-op: reads return empty/null and\n * writes do nothing. Disk failures (corrupted JSON, unwritable directory) fall\n * through to the empty/null path so a broken cache never fails the build.\n */\nexport class CacheService {\n readonly enabled: boolean;\n readonly root: string;\n private readonly buildCachePath: string;\n private readonly httpCacheDir: string;\n\n constructor(rootDir: string, options: CacheServiceOptions) {\n this.enabled = options.enabled;\n this.root = resolve(rootDir, options.dir ?? DEFAULT_CACHE_DIR);\n this.buildCachePath = join(this.root, BUILD_CACHE_FILENAME);\n this.httpCacheDir = join(this.root, HTTP_CACHE_DIRNAME);\n }\n\n /** Load the previous run's `FileHashMap` from disk, or return `{}` when disabled or unreadable. */\n loadBuildCache(): FileHashMap {\n if (!this.enabled) return {};\n try {\n return JSON.parse(readFileSync(this.buildCachePath, 'utf-8'));\n } catch {\n return {};\n }\n }\n\n /** Persist a `FileHashMap` for the next run. No-op when disabled; write errors are swallowed. */\n saveBuildCache(cache: FileHashMap): void {\n if (!this.enabled) return;\n try {\n mkdirSync(dirname(this.buildCachePath), { recursive: true });\n writeFileSync(this.buildCachePath, JSON.stringify(cache, null, 2), 'utf-8');\n } catch {\n // best-effort\n }\n }\n\n /** HTTP cache view backed by this service, suitable for passing into the plugin-extension resolver. */\n httpCache(): HttpCache {\n return {\n get: (url) => this.getHttpResponse(url),\n set: (url, body) => this.setHttpResponse(url, body),\n };\n }\n\n private urlPath(url: string): string {\n return join(this.httpCacheDir, computeHash(url));\n }\n\n /** Read a previously cached HTTP body for `url`, or `null` on miss / when disabled / on read error. */\n getHttpResponse(url: string): string | null {\n if (!this.enabled) return null;\n const path = this.urlPath(url);\n if (!existsSync(path)) return null;\n try {\n return readFileSync(path, 'utf-8');\n } catch {\n return null;\n }\n }\n\n /** Persist an HTTP response body keyed by the URL's sha256. No-op when disabled; write errors are swallowed. */\n setHttpResponse(url: string, body: string): void {\n if (!this.enabled) return;\n try {\n mkdirSync(this.httpCacheDir, { recursive: true });\n writeFileSync(this.urlPath(url), body, 'utf-8');\n } catch {\n // best-effort\n }\n }\n}\n\n/**\n * Returns true when `filePath`'s `content` no longer matches the hash stored in\n * `cache`, or when `outPath` does not exist on disk. Used by plugin output\n * gating to decide whether a file needs regeneration.\n */\nexport function isFileChanged(filePath: string, content: string, outPath: string, cache: FileHashMap): boolean {\n if (!existsSync(outPath)) return true;\n const currentHash = computeHash(content);\n return cache[filePath] !== currentHash;\n}\n","import { resolve, isAbsolute } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { computeHash } from './cache.js';\nimport type { PluginEntry, ResolvedConfig } from './config.js';\nimport type { ContractKitPlugin, PluginContext } from '@contractkit/core';\nimport type { FileHashMap } from './cache.js';\n\nexport type { ContractKitPlugin };\n\nexport interface LoadedPlugin {\n plugin: ContractKitPlugin;\n entry: PluginEntry;\n}\n\nexport async function loadPlugins(entries: PluginEntry[], configDir: string): Promise<LoadedPlugin[]> {\n const loaded: LoadedPlugin[] = [];\n for (const entry of entries) {\n const { plugin: specifier } = entry;\n const modulePath =\n specifier.startsWith('.') || specifier.startsWith('/') || isAbsolute(specifier)\n ? resolve(configDir, specifier)\n : createRequire(resolve(configDir, 'package.json')).resolve(specifier);\n let mod: unknown;\n try {\n mod = await import(modulePath);\n } catch (err) {\n throw new Error(`Failed to load plugin \"${specifier}\": ${(err as Error).message}`, { cause: err });\n }\n const raw =\n (mod as { default?: ContractKitPlugin; plugin?: ContractKitPlugin }).default ?? (mod as { plugin?: ContractKitPlugin }).plugin ?? mod;\n if (!raw || typeof raw !== 'object' || typeof (raw as { name?: string }).name !== 'string') {\n throw new Error(`Plugin \"${specifier}\" must export a ContractKitPlugin object with a \"name\" field.`);\n }\n loaded.push({ plugin: raw as ContractKitPlugin, entry });\n }\n return loaded;\n}\n\nexport function makePluginContext(entry: PluginEntry, config: ResolvedConfig, emitFile?: (outPath: string, content: string) => void): PluginContext {\n return {\n rootDir: config.rootDir,\n options: entry.options ?? {},\n emitFile:\n emitFile ??\n (() => {\n throw new Error('emitFile is only available in generateTargets');\n }),\n };\n}\n\nexport function computePluginFingerprint(newCache: FileHashMap, cacheKey: string): string {\n const allHashes = Object.values(newCache).sort().join('|') + '|' + cacheKey;\n return computeHash(allHashes);\n}\n\nexport function pluginOutputsExist(cache: FileHashMap, cacheKey: string): boolean {\n const raw = cache[`__plugin_${cacheKey}__files__`];\n if (!raw) return false;\n const files = (raw as string).split('|').filter(Boolean);\n return files.length > 0 && files.every(f => existsSync(f));\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport type { OpRootNode, PluginValue } from '@contractkit/core';\nimport type { DiagnosticCollector } from '@contractkit/core';\nimport type { HttpCache } from './cache.js';\n\nconst FILE_URL_PREFIX = 'file://';\n\nexport interface ResolvePluginExtensionsOptions {\n /**\n * Persistent HTTP response cache. Successful responses are written through\n * `set` and reused via `get` on subsequent runs. Omit to disable disk\n * caching entirely (e.g. for `--force`).\n */\n httpCache?: HttpCache;\n}\n\n/**\n * Resolves URL strings inside operation `plugins` JSON values.\n *\n * For each operation that declares a `plugins` block, walks the JSON tree of\n * every entry and replaces:\n * - `file://<path>` strings with the contents of the file (path is resolved\n * relative to the operation's `.ck` source file).\n * - `http://<url>` / `https://<url>` strings with the response body of a GET\n * request to that URL.\n *\n * The transformed tree is stored as `op.pluginExtensions[name]`. Strings without\n * a recognized URL prefix and non-string leaves pass through unchanged. Missing\n * files and failed/non-2xx HTTP requests emit warnings and leave the original\n * string in place.\n *\n * Each unique HTTP URL is fetched at most once per CLI invocation; when\n * `options.httpCacheDir` is set, successful responses are persisted there and\n * reused on subsequent runs.\n */\nexport async function resolvePluginExtensions(\n roots: OpRootNode[],\n rootDir: string,\n diag: DiagnosticCollector,\n options: ResolvePluginExtensionsOptions = {},\n): Promise<void> {\n const inFlight = new Map<string, Promise<string | null>>();\n const httpCache = options.httpCache;\n\n for (const root of roots) {\n const contractDir = dirname(resolve(rootDir, root.file));\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!op.plugins) continue;\n const resolved: Record<string, PluginValue> = {};\n for (const [name, value] of Object.entries(op.plugins)) {\n resolved[name] = await resolveUrls(value, contractDir, root.file, op.loc.line, name, diag, inFlight, httpCache);\n }\n op.pluginExtensions = resolved;\n }\n }\n }\n}\n\nasync function resolveUrls(\n value: PluginValue,\n contractDir: string,\n file: string,\n line: number,\n pluginName: string,\n diag: DiagnosticCollector,\n inFlight: Map<string, Promise<string | null>>,\n httpCache: HttpCache | undefined,\n): Promise<PluginValue> {\n if (typeof value === 'string') {\n if (value.startsWith(FILE_URL_PREFIX)) {\n const relPath = value.slice(FILE_URL_PREFIX.length);\n const absPath = resolve(contractDir, relPath);\n if (!existsSync(absPath)) {\n diag.warn(file, line, `plugins.${pluginName}: file not found: ${relPath}`);\n return value;\n }\n return readFileSync(absPath, 'utf-8');\n }\n if (value.startsWith('http://') || value.startsWith('https://')) {\n let pending = inFlight.get(value);\n if (!pending) {\n pending = fetchUrl(value, httpCache);\n inFlight.set(value, pending);\n }\n const fetched = await pending;\n if (fetched === null) {\n diag.warn(file, line, `plugins.${pluginName}: failed to fetch ${value}`);\n return value;\n }\n return fetched;\n }\n return value;\n }\n if (Array.isArray(value)) {\n return Promise.all(value.map(item => resolveUrls(item, contractDir, file, line, pluginName, diag, inFlight, httpCache)));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, PluginValue> = {};\n for (const [k, v] of Object.entries(value)) {\n out[k] = await resolveUrls(v, contractDir, file, line, pluginName, diag, inFlight, httpCache);\n }\n return out;\n }\n return value;\n}\n\nasync function fetchUrl(url: string, httpCache: HttpCache | undefined): Promise<string | null> {\n if (httpCache) {\n const cached = httpCache.get(url);\n if (cached !== null) return cached;\n }\n try {\n const res = await fetch(url);\n if (!res.ok) return null;\n const body = await res.text();\n httpCache?.set(url, body);\n return body;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["default","importOpenApiPlugin","readFileSync","writeFileSync","mkdirSync","resolve","join","dirname","glob","DiagnosticCollector","parseCk","decomposeCk","validateOp","validateRefs","validateInheritance","applyOptionsDefaults","applyVariableSubstitution","computeModelsWithInput","computeModelsWithOutput","readFileSync","resolve","dirname","join","readFileSync","writeFileSync","mkdirSync","existsSync","createHash","join","dirname","resolve","DEFAULT_CACHE_DIR","BUILD_CACHE_FILENAME","HTTP_CACHE_DIRNAME","computeHash","content","createHash","update","digest","CacheService","enabled","root","buildCachePath","httpCacheDir","rootDir","options","resolve","dir","join","loadBuildCache","JSON","parse","readFileSync","saveBuildCache","cache","mkdirSync","dirname","recursive","writeFileSync","stringify","httpCache","get","url","getHttpResponse","set","body","setHttpResponse","urlPath","path","existsSync","homedir","CONFIG_FILENAME","loadConfig","configPath","startDir","process","cwd","resolved","resolve","text","readFileSync","config","JSON","parse","configDir","dirname","err","Error","message","cause","dir","candidate","join","parent","normalizePlugins","plugins","Object","entries","map","name","options","plugin","mergeConfig","cliArgs","cache","enabled","DEFAULT_CACHE_DIR","rootDir","startsWith","homedir","slice","patterns","watch","force","prettier","resolve","isAbsolute","existsSync","createRequire","loadPlugins","entries","configDir","loaded","entry","plugin","specifier","modulePath","startsWith","isAbsolute","resolve","createRequire","mod","err","Error","message","cause","raw","default","name","push","makePluginContext","config","emitFile","rootDir","options","computePluginFingerprint","newCache","cacheKey","allHashes","Object","values","sort","join","computeHash","pluginOutputsExist","cache","files","split","filter","Boolean","length","every","f","existsSync","existsSync","readFileSync","resolve","dirname","FILE_URL_PREFIX","resolvePluginExtensions","roots","rootDir","diag","options","inFlight","Map","httpCache","root","contractDir","dirname","resolve","file","route","routes","op","operations","plugins","resolved","name","value","Object","entries","resolveUrls","loc","line","pluginExtensions","pluginName","startsWith","relPath","slice","length","absPath","existsSync","warn","readFileSync","pending","get","fetchUrl","set","fetched","Array","isArray","Promise","all","map","item","out","k","v","url","cached","res","fetch","ok","body","text","BUILTIN_COMMAND_PLUGINS","importOpenApiPlugin","printHelp","console","log","plugin","command","name","padEnd","description","parseArgs","argv","args","slice","config","watch","force","help","i","length","arg","FALLBACK_BUILTINS_RE","substituteBuiltins","input","builtins","onMissing","includes","replace","_match","escapedName","varName","undefined","value","collectFallbackKeys","entries","merged","entry","keys","options","Array","isArray","warn","Object","missing","resolveFiles","patterns","rootDir","files","pattern","matches","glob","absolute","cwd","resolve","push","Set","formatWithPrettier","results","prettier","result","resolveConfig","outPath","content","format","filepath","main","cliArgs","process","exit","subcommand","startsWith","matched","find","p","subArgs","usage","fileConfig","configDir","loadConfig","resolved","mergeConfig","run","error","plugins","loadPlugins","fallbackKeys","join","diag","DiagnosticCollector","resolvedBase","cacheEnabled","cache","enabled","cacheService","CacheService","dir","loadBuildCache","newCache","allContracts","allOps","filePath","endsWith","source","readFileSync","computeHash","ckAst","parseCk","applyOptionsDefaults","applyVariableSubstitution","ctx","makePluginContext","validate","err","message","transform","contract","op","decomposeCk","models","routes","resolvePluginExtensions","httpCache","validatorsByName","Map","validateExtension","set","root","route","operations","pluginExtensions","validator","get","errors","msg","file","loc","line","warnings","modelsWithInput","computeModelsWithInput","flatMap","r","modelsWithOutput","computeModelsWithOutput","depsFingerprint","sort","depsChanged","hasErrors","report","exitCode","validateRefs","validateInheritance","validateOp","generateTargets","optionsSuffix","JSON","stringify","cacheKey","fingerprint","computePluginFingerprint","pluginOutputsExist","pluginEmitted","contractRoots","opRoots","map","f","mkdirSync","recursive","dirname","writeFileSync","saveBuildCache","watchFiles","allDirs","event","filename","full","catch"]} | ||
| {"version":3,"sources":["../src/cli.ts","../src/config.ts","../src/cache.ts","../src/plugin.ts","../src/resolve-plugin-extensions.ts"],"sourcesContent":["#!/usr/bin/env node\n\n// ─── Built-in command plugins ─────────────────────────────────────────────\n// Each plugin may expose a `command` hook — the CLI dispatches subcommands\n// to the first plugin whose command.name matches argv[2].\nimport { default as importOpenApiPlugin } from '@contractkit/openapi-to-ck/plugin';\n\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs';\nimport { resolve, join, dirname } from 'node:path';\nimport { glob } from 'glob';\nimport {\n DiagnosticCollector,\n parseCk,\n decomposeCk,\n validateOp,\n validateRefs,\n validateInheritance,\n applyOptionsDefaults,\n applyVariableSubstitution,\n computeModelsWithInput,\n computeModelsWithOutput,\n} from '@contractkit/core';\nimport type { ContractRootNode, OpRootNode, ContractKitPlugin } from '@contractkit/core';\nimport { loadConfig, mergeConfig, type PluginEntry } from './config.js';\nimport { CacheService, computeHash } from './cache.js';\nimport { loadPlugins, makePluginContext, computePluginFingerprint, pluginOutputsExist } from './plugin.js';\nimport { resolvePluginExtensions } from './resolve-plugin-extensions.js';\nimport type { FileHashMap } from './cache.js';\n\n// ─── Arg parsing ───────────────────────────────────────────────────────────\n\ninterface CliArgs {\n config?: string;\n watch: boolean;\n force: boolean;\n help: boolean;\n}\n\nconst BUILTIN_COMMAND_PLUGINS = [importOpenApiPlugin];\n\nfunction printHelp(): void {\n console.log('Usage: contractkit [command] [options]');\n console.log('');\n console.log('Commands:');\n for (const plugin of BUILTIN_COMMAND_PLUGINS) {\n if (plugin.command) {\n console.log(` ${plugin.command.name.padEnd(20)} ${plugin.command.description}`);\n }\n }\n console.log('');\n console.log('Options:');\n console.log(' -c, --config <path> Path to config file (default: contractkit.config.json)');\n console.log(' -w, --watch Watch for changes and recompile');\n console.log(' --force Skip cache and recompile all files');\n console.log(' -h, --help Show this help message');\n console.log('');\n console.log('Configure patterns, output dirs, and plugins in contractkit.config.json.');\n}\n\nfunction parseArgs(argv: string[]): CliArgs {\n const args = argv.slice(2);\n let config: string | undefined;\n let watch = false;\n let force = false;\n let help = false;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg === '--config' || arg === '-c') {\n config = args[++i];\n } else if (arg === '--watch' || arg === '-w') {\n watch = true;\n } else if (arg === '--force') {\n force = true;\n } else if (arg === '--help' || arg === '-h') {\n help = true;\n }\n }\n\n return { config, watch, force, help };\n}\n\n// ─── Fallback keys for {{var}} substitution ────────────────────────────────\n\n/**\n * Built-in variables available inside plugin-config `keys` values. These let a\n * user write `\"{{rootDir}}/path\"` in `contractkit.config.json` and have the\n * absolute resolved root substituted in at load time.\n */\nconst FALLBACK_BUILTINS_RE = /\\\\\\{\\{(\\w+)\\}\\}|\\{\\{(\\w+)\\}\\}/g;\n\nfunction substituteBuiltins(input: string, builtins: Record<string, string>, onMissing: (name: string) => void): string {\n if (!input.includes('{{')) return input;\n return input.replace(FALLBACK_BUILTINS_RE, (_match, escapedName: string | undefined, varName: string | undefined) => {\n if (escapedName !== undefined) return `{{${escapedName}}}`;\n const value = builtins[varName!];\n if (value === undefined) {\n onMissing(varName!);\n return 'undefined';\n }\n return value;\n });\n}\n\nfunction collectFallbackKeys(entries: PluginEntry[], builtins: Record<string, string>): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const entry of entries) {\n const keys = entry.options?.['keys'];\n if (keys === undefined) continue;\n if (typeof keys !== 'object' || keys === null || Array.isArray(keys)) {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys' must be an object of string→string; ignoring.`);\n continue;\n }\n for (const [name, value] of Object.entries(keys)) {\n if (typeof value !== 'string') {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys.${name}' must be a string; ignoring.`);\n continue;\n }\n merged[name] = substituteBuiltins(value, builtins, missing => {\n console.warn(` ⚠ [plugin:${entry.plugin}] 'keys.${name}' references unknown built-in '{{${missing}}}'.`);\n });\n }\n }\n return merged;\n}\n\n// ─── File resolution ───────────────────────────────────────────────────────\n\nasync function resolveFiles(patterns: string[], rootDir: string): Promise<string[]> {\n const files: string[] = [];\n for (const pattern of patterns) {\n const matches = await glob(pattern, { absolute: true, cwd: resolve(rootDir) });\n files.push(...matches);\n }\n return [...new Set(files)];\n}\n\n// ─── Prettier formatting ──────────────────────────────────────────────────\n\nasync function formatWithPrettier(results: { outPath: string; content: string }[]): Promise<void> {\n let prettier: typeof import('prettier');\n try {\n prettier = await import('prettier');\n } catch {\n console.warn(' ⚠ prettier not found — skipping format step');\n return;\n }\n for (const result of results) {\n try {\n const options = (await prettier.resolveConfig(result.outPath)) ?? {};\n result.content = await prettier.format(result.content, {\n ...options,\n filepath: result.outPath,\n });\n } catch {\n // Leave content unformatted if prettier fails (e.g. unsupported parser)\n }\n }\n}\n\n// ─── Main ─────────────────────────────────────────────────────────────────\n\nasync function main() {\n const cliArgs = parseArgs(process.argv);\n\n if (cliArgs.help) {\n printHelp();\n process.exit(0);\n }\n\n // ── Built-in subcommand dispatch ──────────────────────────────────────\n const subcommand = process.argv[2];\n if (subcommand && !subcommand.startsWith('-')) {\n const matched = BUILTIN_COMMAND_PLUGINS.find(p => p.command?.name === subcommand);\n if (matched?.command) {\n const subArgs = process.argv.slice(3);\n if (subArgs.includes('--help') || subArgs.includes('-h')) {\n console.log(matched.command.usage);\n process.exit(0);\n }\n const { config: fileConfig, configDir } = loadConfig(cliArgs.config);\n const resolved = mergeConfig(fileConfig, { watch: false, force: false }, configDir);\n await matched.command.run(subArgs, { rootDir: resolved.rootDir, configDir });\n process.exit(0);\n }\n console.error(`Unknown command: \"${subcommand}\". Run \"contractkit --help\" for usage.`);\n process.exit(1);\n }\n\n const { config: fileConfig, configDir } = loadConfig(cliArgs.config);\n const config = mergeConfig(fileConfig, cliArgs, configDir);\n const plugins = await loadPlugins(config.plugins, config.configDir);\n\n // Merge `keys` from each plugin entry's options into a single workspace-wide fallback\n // map for `{{var}}` substitution. File-local `options { keys }` always wins; this map\n // catches anything that isn't defined per-file. Built-in variables (`rootDir`,\n // `configDir`) can be referenced inside the values themselves.\n const fallbackKeys = collectFallbackKeys(config.plugins, {\n rootDir: config.rootDir,\n configDir: config.configDir,\n });\n\n if (config.patterns.length === 0) {\n printHelp();\n process.exit(1);\n }\n\n const run = async () => {\n const files = await resolveFiles(config.patterns, config.rootDir);\n\n if (files.length === 0) {\n console.warn(`No matching files found for patterns:`, config.patterns.join(', '));\n return;\n }\n\n const diag = new DiagnosticCollector();\n const resolvedBase = resolve(config.rootDir);\n const cacheEnabled = config.cache.enabled && !config.force;\n const cacheService = new CacheService(resolvedBase, { enabled: cacheEnabled, dir: config.cache.dir });\n const cache: FileHashMap = cacheService.loadBuildCache();\n const newCache: FileHashMap = {};\n\n // ── Parse all .ck files ────────────────────────────────────────\n const allContracts: ContractRootNode[] = [];\n const allOps: OpRootNode[] = [];\n\n for (const filePath of files) {\n if (!filePath.endsWith('.ck')) {\n diag.warn(filePath, 0, `Skipping unknown file extension (expected .ck)`);\n continue;\n }\n\n const source = readFileSync(filePath, 'utf-8');\n newCache[filePath] = computeHash(source);\n\n let ckAst = parseCk(source, filePath, diag);\n // Merge options-level header globals into each operation before plugins run,\n // so transform/validate hooks see the fully-resolved AST.\n applyOptionsDefaults(ckAst, diag);\n applyVariableSubstitution(ckAst, diag, fallbackKeys);\n\n // Plugin: validate + transform hooks (run before decompose and cross-file validation)\n for (const { plugin, entry } of plugins) {\n const ctx = makePluginContext(entry, config, cacheEnabled);\n if (plugin.validate) {\n try {\n await plugin.validate(ckAst, ctx);\n } catch (err) {\n diag.error(filePath, 0, `[plugin:${plugin.name}] ${(err as Error).message}`);\n }\n }\n if (plugin.transform) {\n try {\n ckAst = await plugin.transform(ckAst, ctx);\n } catch (err) {\n diag.error(filePath, 0, `[plugin:${plugin.name}] ${(err as Error).message}`);\n }\n }\n }\n\n const { contract, op } = decomposeCk(ckAst);\n if (contract.models.length > 0) allContracts.push(contract);\n if (op.routes.length > 0) allOps.push(op);\n }\n\n // ── Resolve plugin extension URL references (file:// and http(s)://) ──\n await resolvePluginExtensions(allOps, resolvedBase, diag, { httpCache: cacheService.httpCache() });\n\n // ── Per-plugin extension validation ───────────────────────────\n const validatorsByName = new Map<string, NonNullable<ContractKitPlugin['validateExtension']>>();\n for (const { plugin } of plugins) {\n if (plugin.validateExtension) validatorsByName.set(plugin.name, plugin.validateExtension);\n }\n for (const root of allOps) {\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!op.pluginExtensions) continue;\n for (const [name, value] of Object.entries(op.pluginExtensions)) {\n const validator = validatorsByName.get(name);\n if (!validator) continue;\n const result = validator(value);\n if (!result) continue;\n if (result.errors) {\n for (const msg of result.errors) {\n diag.error(root.file, op.loc.line, `plugins.${name}: ${msg}`);\n }\n }\n if (result.warnings) {\n for (const msg of result.warnings) {\n diag.warn(root.file, op.loc.line, `plugins.${name}: ${msg}`);\n }\n }\n }\n }\n }\n }\n\n // ── Compute cross-file semantics ───────────────────────────────\n // modelsWithInput: which model names need an Input variant (have readonly/writeonly\n // fields, or transitively reference models that do). Used by all code generators.\n const modelsWithInput = computeModelsWithInput(allContracts.flatMap(r => r.models));\n // modelsWithOutput: which model names need an Output variant (have format(output=...),\n // or transitively reference models that do). Used by codegen for the post-transform\n // wire shape on response bodies.\n const modelsWithOutput = computeModelsWithOutput(allContracts.flatMap(r => r.models));\n\n // ── Dependency fingerprint ─────────────────────────────────────\n const depsFingerprint = computeHash([...modelsWithInput].sort().join(',') + '|' + [...modelsWithOutput].sort().join(','));\n const depsChanged = cacheEnabled && cache['__deps__'] !== depsFingerprint;\n newCache['__deps__'] = depsFingerprint;\n\n if (diag.hasErrors()) {\n diag.report();\n console.error('\\nCompilation failed.');\n process.exitCode = 1;\n return;\n }\n\n // ── Cross-file validation ──────────────────────────────────────\n validateRefs(allContracts, allOps, diag);\n validateInheritance(allContracts, diag);\n\n for (const op of allOps) {\n validateOp(op, diag);\n }\n\n // ── Generate via plugins ───────────────────────────────────────\n const results: { outPath: string; content: string }[] = [];\n\n for (const { plugin, entry } of plugins) {\n if (!plugin.generateTargets) continue;\n\n const optionsSuffix = entry.options && Object.keys(entry.options).length > 0 ? `:${JSON.stringify(entry.options)}` : '';\n const cacheKey = plugin.cacheKey ? `${plugin.cacheKey}${optionsSuffix}` : undefined;\n if (cacheKey && !config.force && cacheEnabled && !depsChanged) {\n const fingerprint = computePluginFingerprint(newCache, cacheKey);\n if (cache[`__plugin_${cacheKey}__`] === fingerprint && pluginOutputsExist(cache, cacheKey)) {\n console.log(` - [plugin:${plugin.name}] (unchanged)`);\n newCache[`__plugin_${cacheKey}__`] = fingerprint;\n newCache[`__plugin_${cacheKey}__files__`] = cache[`__plugin_${cacheKey}__files__`] ?? '';\n continue;\n }\n }\n\n const pluginEmitted: { outPath: string; content: string }[] = [];\n const ctx = makePluginContext(entry, config, cacheEnabled, (outPath, content) => {\n pluginEmitted.push({ outPath, content });\n });\n\n try {\n await plugin.generateTargets(\n {\n contractRoots: allContracts,\n opRoots: allOps,\n modelsWithInput,\n modelsWithOutput,\n },\n ctx,\n );\n } catch (err) {\n diag.error('', 0, `[plugin:${plugin.name}] generateTargets failed: ${(err as Error).message}`);\n continue;\n }\n\n results.push(...pluginEmitted);\n\n if (cacheKey) {\n newCache[`__plugin_${cacheKey}__`] = computePluginFingerprint(newCache, cacheKey);\n newCache[`__plugin_${cacheKey}__files__`] = pluginEmitted.map(f => f.outPath).join('|');\n }\n }\n\n if (diag.hasErrors()) {\n diag.report();\n console.error('\\nCompilation failed.');\n process.exitCode = 1;\n return;\n }\n\n // ── Format with prettier (opt-in) ────────────────────────────\n if (config.prettier && results.length > 0) {\n await formatWithPrettier(results);\n }\n\n // ── Write output files ──────────────────────────────────────\n mkdirSync(resolvedBase, { recursive: true });\n\n for (const { outPath, content } of results) {\n mkdirSync(dirname(outPath), { recursive: true });\n writeFileSync(outPath, content, 'utf-8');\n console.log(` ✓ ${outPath}`);\n }\n\n // Save cache\n if (config.cache.enabled) {\n cacheService.saveBuildCache(newCache);\n }\n\n // Report all collected warnings/errors after file writes so they\n // appear at the bottom of the output and are easy to spot.\n diag.report();\n\n console.log(`\\nCompiled ${results.length} file(s).`);\n };\n\n await run();\n\n if (config.watch) {\n const { watch } = await import('node:fs');\n const watchFiles = await resolveFiles(config.patterns, config.rootDir);\n const allDirs = new Set(watchFiles.map(f => dirname(f)));\n console.log('\\nWatching for changes...');\n for (const dir of allDirs) {\n watch(dir, { recursive: false }, async (event, filename) => {\n if (!filename) return;\n const full = join(dir, filename);\n if (!full.endsWith('.ck')) return;\n console.log(`\\nChange detected: ${filename}`);\n await run();\n });\n }\n }\n}\n\nmain().catch(err => {\n console.error('Unexpected error:', err);\n process.exit(1);\n});\n","import { readFileSync } from 'node:fs';\nimport { resolve, dirname, join } from 'node:path';\nimport { DEFAULT_CACHE_DIR } from './cache.js';\nimport { homedir } from 'node:os';\n\nexport interface PluginEntry {\n /** npm package name or local path relative to contractkit.config.json */\n plugin: string;\n /**\n * Plugin-specific options passed as ctx.options.\n *\n * One reserved key: `keys?: Record<string, string>`. Entries are merged across all plugin\n * entries into a workspace-wide fallback map for `{{var}}` substitution in `.ck` files.\n * A file's `options { keys }` block still wins over this fallback when both define a name.\n */\n options?: Record<string, unknown>;\n}\n\n/** Record-keyed plugin config: each key is the plugin package name, value is options. */\nexport type PluginsConfig = Record<string, Record<string, unknown>>;\n\n/** Raw shape of `contractkit.config.json` before CLI flag merge. All fields are optional. */\nexport interface DslConfig {\n rootDir?: string;\n /**\n * Build/HTTP caching control.\n * - `true` — enable, default directory `.contractkit/cache`\n * - `false` (default) — disabled\n * - `string` — enabled, treats the value as a custom cache directory (relative to `rootDir` or absolute)\n */\n cache?: boolean | string;\n /** Glob patterns for .ck files to compile, relative to rootDir. */\n patterns?: string[];\n /** Run prettier on generated TypeScript files after compilation. Default: false. */\n prettier?: boolean;\n /** Plugins to load: each key is the plugin package name, value is its options. */\n plugins?: PluginsConfig;\n}\n\n/** Resolved cache configuration produced by {@link mergeConfig}. */\nexport interface ResolvedCacheConfig {\n /** Whether the build/HTTP caches are active. `--force` does NOT flip this — it is gated separately at the CLI. */\n enabled: boolean;\n /** Directory (relative to `rootDir` or absolute) where caches live. */\n dir: string;\n}\n\nconst CONFIG_FILENAME = 'contractkit.config.json';\n\n/**\n * Load `contractkit.config.json` from an explicit path or by walking up from `startDir`.\n *\n * Returns the parsed config plus the directory that contained it (used to resolve relative\n * paths in the config). When no config is found anywhere on the path, returns an empty\n * config rooted at `startDir`.\n *\n * @throws if `configPath` is provided but the file cannot be read or parsed.\n */\nexport function loadConfig(configPath?: string, startDir: string = process.cwd()): { config: DslConfig; configDir: string } {\n if (configPath) {\n const resolved = resolve(configPath);\n try {\n const text = readFileSync(resolved, 'utf-8');\n return { config: JSON.parse(text) as DslConfig, configDir: dirname(resolved) };\n } catch (err) {\n throw new Error(`Failed to load config from ${resolved}: ${(err as Error).message}`, { cause: err });\n }\n }\n\n let dir = resolve(startDir);\n while (true) {\n const candidate = join(dir, CONFIG_FILENAME);\n try {\n const text = readFileSync(candidate, 'utf-8');\n return { config: JSON.parse(text) as DslConfig, configDir: dir };\n } catch {\n // File not found or invalid -- walk up\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return { config: {}, configDir: resolve(startDir) };\n}\n\n/** Fully resolved configuration: file values merged with CLI flags, paths absolutized, plugins normalized. */\nexport interface ResolvedConfig {\n patterns: string[];\n rootDir: string;\n cache: ResolvedCacheConfig;\n watch: boolean;\n force: boolean;\n prettier: boolean;\n plugins: PluginEntry[];\n configDir: string;\n}\n\nfunction normalizePlugins(plugins: PluginsConfig | undefined): PluginEntry[] {\n if (!plugins) return [];\n return Object.entries(plugins).map(([name, options]) => ({ plugin: name, options }));\n}\n\n/**\n * Merge a parsed {@link DslConfig} with CLI flags into a fully resolved configuration.\n *\n * Normalizes `cache` (boolean | string), expands a leading `~` in `rootDir`, resolves\n * `rootDir` to an absolute path, and converts the record-shaped `plugins` block into\n * an ordered `PluginEntry[]`.\n */\nexport function mergeConfig(config: DslConfig, cliArgs: { watch: boolean; force: boolean }, configDir: string = process.cwd()): ResolvedConfig {\n const cache: ResolvedCacheConfig =\n typeof config.cache === 'string'\n ? { enabled: true, dir: config.cache }\n : { enabled: config.cache === true, dir: DEFAULT_CACHE_DIR };\n\n let rootDir = config.rootDir ?? '.';\n if (rootDir.startsWith('~')) {\n rootDir = homedir() + rootDir.slice(1);\n }\n\n return {\n patterns: config.patterns ?? [],\n rootDir: resolve(rootDir),\n cache,\n watch: cliArgs.watch,\n force: cliArgs.force,\n prettier: config.prettier ?? false,\n plugins: normalizePlugins(config.plugins),\n configDir,\n };\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { join, dirname, resolve } from 'node:path';\n\n/** Default directory (relative to `rootDir`) where all CLI caches live. */\nexport const DEFAULT_CACHE_DIR = '.contractkit/cache';\nconst BUILD_CACHE_FILENAME = 'build.json';\nconst HTTP_CACHE_DIRNAME = 'http';\n\n/** Map of source file path → sha256 hex of its content (or synthetic keys like `__plugin_<key>__`). */\nexport interface FileHashMap {\n [filePath: string]: string;\n}\n\n/** Compute a stable sha256 hex digest for a string of content. */\nexport function computeHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n/**\n * Minimal key-value interface for plugin extension HTTP responses. `get` returns\n * `null` on a cache miss; `set` is best-effort and silently swallows write\n * failures so a broken cache never blocks the build.\n */\nexport interface HttpCache {\n get(url: string): string | null;\n set(url: string, body: string): void;\n}\n\nexport interface CacheServiceOptions {\n /** When false, every read returns empty/null and every write is a no-op. */\n enabled: boolean;\n /** Directory (relative to `rootDir` or absolute) used as the cache root. Defaults to `.contractkit/cache`. */\n dir?: string;\n}\n\n/**\n * Unified cache service. Owns one root directory under which both the build\n * cache (file/plugin hashes, single JSON file) and the HTTP response cache\n * (one blob per URL hash) live.\n *\n * Layout:\n * <root>/build.json — FileHashMap from the previous run\n * <root>/http/<sha256(url)> — fetched HTTP response bodies\n *\n * When `enabled` is false the service is a no-op: reads return empty/null and\n * writes do nothing. Disk failures (corrupted JSON, unwritable directory) fall\n * through to the empty/null path so a broken cache never fails the build.\n */\nexport class CacheService {\n readonly enabled: boolean;\n readonly root: string;\n private readonly buildCachePath: string;\n private readonly httpCacheDir: string;\n\n constructor(rootDir: string, options: CacheServiceOptions) {\n this.enabled = options.enabled;\n this.root = resolve(rootDir, options.dir ?? DEFAULT_CACHE_DIR);\n this.buildCachePath = join(this.root, BUILD_CACHE_FILENAME);\n this.httpCacheDir = join(this.root, HTTP_CACHE_DIRNAME);\n }\n\n /** Load the previous run's `FileHashMap` from disk, or return `{}` when disabled or unreadable. */\n loadBuildCache(): FileHashMap {\n if (!this.enabled) return {};\n try {\n return JSON.parse(readFileSync(this.buildCachePath, 'utf-8'));\n } catch {\n return {};\n }\n }\n\n /** Persist a `FileHashMap` for the next run. No-op when disabled; write errors are swallowed. */\n saveBuildCache(cache: FileHashMap): void {\n if (!this.enabled) return;\n try {\n mkdirSync(dirname(this.buildCachePath), { recursive: true });\n writeFileSync(this.buildCachePath, JSON.stringify(cache, null, 2), 'utf-8');\n } catch {\n // best-effort\n }\n }\n\n /** HTTP cache view backed by this service, suitable for passing into the plugin-extension resolver. */\n httpCache(): HttpCache {\n return {\n get: (url) => this.getHttpResponse(url),\n set: (url, body) => this.setHttpResponse(url, body),\n };\n }\n\n private urlPath(url: string): string {\n return join(this.httpCacheDir, computeHash(url));\n }\n\n /** Read a previously cached HTTP body for `url`, or `null` on miss / when disabled / on read error. */\n getHttpResponse(url: string): string | null {\n if (!this.enabled) return null;\n const path = this.urlPath(url);\n if (!existsSync(path)) return null;\n try {\n return readFileSync(path, 'utf-8');\n } catch {\n return null;\n }\n }\n\n /** Persist an HTTP response body keyed by the URL's sha256. No-op when disabled; write errors are swallowed. */\n setHttpResponse(url: string, body: string): void {\n if (!this.enabled) return;\n try {\n mkdirSync(this.httpCacheDir, { recursive: true });\n writeFileSync(this.urlPath(url), body, 'utf-8');\n } catch {\n // best-effort\n }\n }\n}\n\n/**\n * Returns true when `filePath`'s `content` no longer matches the hash stored in\n * `cache`, or when `outPath` does not exist on disk. Used by plugin output\n * gating to decide whether a file needs regeneration.\n */\nexport function isFileChanged(filePath: string, content: string, outPath: string, cache: FileHashMap): boolean {\n if (!existsSync(outPath)) return true;\n const currentHash = computeHash(content);\n return cache[filePath] !== currentHash;\n}\n","import { resolve, isAbsolute } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { computeHash } from './cache.js';\nimport type { PluginEntry, ResolvedConfig } from './config.js';\nimport type { ContractKitPlugin, PluginContext } from '@contractkit/core';\nimport type { FileHashMap } from './cache.js';\n\nexport type { ContractKitPlugin };\n\nexport interface LoadedPlugin {\n plugin: ContractKitPlugin;\n entry: PluginEntry;\n}\n\nexport async function loadPlugins(entries: PluginEntry[], configDir: string): Promise<LoadedPlugin[]> {\n const loaded: LoadedPlugin[] = [];\n for (const entry of entries) {\n const { plugin: specifier } = entry;\n const modulePath =\n specifier.startsWith('.') || specifier.startsWith('/') || isAbsolute(specifier)\n ? resolve(configDir, specifier)\n : createRequire(resolve(configDir, 'package.json')).resolve(specifier);\n let mod: unknown;\n try {\n mod = await import(modulePath);\n } catch (err) {\n throw new Error(`Failed to load plugin \"${specifier}\": ${(err as Error).message}`, { cause: err });\n }\n const raw =\n (mod as { default?: ContractKitPlugin; plugin?: ContractKitPlugin }).default ?? (mod as { plugin?: ContractKitPlugin }).plugin ?? mod;\n if (!raw || typeof raw !== 'object' || typeof (raw as { name?: string }).name !== 'string') {\n throw new Error(`Plugin \"${specifier}\" must export a ContractKitPlugin object with a \"name\" field.`);\n }\n loaded.push({ plugin: raw as ContractKitPlugin, entry });\n }\n return loaded;\n}\n\n/**\n * Build the {@link PluginContext} a plugin sees inside its hooks. `emitFile` is\n * only meaningful during `generateTargets`; the default implementation throws if\n * called from `validate` / `transform`. Pass `cacheEnabled=false` (computed by the\n * CLI from `--force` / `cache: false`) so the plugin can bypass its own incremental\n * caches.\n */\nexport function makePluginContext(\n entry: PluginEntry,\n config: ResolvedConfig,\n cacheEnabled: boolean,\n emitFile?: (outPath: string, content: string) => void,\n): PluginContext {\n return {\n rootDir: config.rootDir,\n options: entry.options ?? {},\n cacheEnabled,\n emitFile:\n emitFile ??\n (() => {\n throw new Error('emitFile is only available in generateTargets');\n }),\n };\n}\n\nexport function computePluginFingerprint(newCache: FileHashMap, cacheKey: string): string {\n const allHashes = Object.values(newCache).sort().join('|') + '|' + cacheKey;\n return computeHash(allHashes);\n}\n\nexport function pluginOutputsExist(cache: FileHashMap, cacheKey: string): boolean {\n const raw = cache[`__plugin_${cacheKey}__files__`];\n if (!raw) return false;\n const files = (raw as string).split('|').filter(Boolean);\n return files.length > 0 && files.every(f => existsSync(f));\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport type { OpRootNode, PluginValue } from '@contractkit/core';\nimport type { DiagnosticCollector } from '@contractkit/core';\nimport type { HttpCache } from './cache.js';\n\nconst FILE_URL_PREFIX = 'file://';\n\nexport interface ResolvePluginExtensionsOptions {\n /**\n * Persistent HTTP response cache. Successful responses are written through\n * `set` and reused via `get` on subsequent runs. Omit to disable disk\n * caching entirely (e.g. for `--force`).\n */\n httpCache?: HttpCache;\n}\n\n/**\n * Resolves URL strings inside operation `plugins` JSON values.\n *\n * For each operation that declares a `plugins` block, walks the JSON tree of\n * every entry and replaces:\n * - `file://<path>` strings with the contents of the file (path is resolved\n * relative to the operation's `.ck` source file).\n * - `http://<url>` / `https://<url>` strings with the response body of a GET\n * request to that URL.\n *\n * The transformed tree is stored as `op.pluginExtensions[name]`. Strings without\n * a recognized URL prefix and non-string leaves pass through unchanged. Missing\n * files and failed/non-2xx HTTP requests emit warnings and leave the original\n * string in place.\n *\n * Each unique HTTP URL is fetched at most once per CLI invocation; when\n * `options.httpCacheDir` is set, successful responses are persisted there and\n * reused on subsequent runs.\n */\nexport async function resolvePluginExtensions(\n roots: OpRootNode[],\n rootDir: string,\n diag: DiagnosticCollector,\n options: ResolvePluginExtensionsOptions = {},\n): Promise<void> {\n const inFlight = new Map<string, Promise<string | null>>();\n const httpCache = options.httpCache;\n\n for (const root of roots) {\n const contractDir = dirname(resolve(rootDir, root.file));\n for (const route of root.routes) {\n for (const op of route.operations) {\n if (!op.plugins) continue;\n const resolved: Record<string, PluginValue> = {};\n for (const [name, value] of Object.entries(op.plugins)) {\n resolved[name] = await resolveUrls(value, contractDir, root.file, op.loc.line, name, diag, inFlight, httpCache);\n }\n op.pluginExtensions = resolved;\n }\n }\n }\n}\n\nasync function resolveUrls(\n value: PluginValue,\n contractDir: string,\n file: string,\n line: number,\n pluginName: string,\n diag: DiagnosticCollector,\n inFlight: Map<string, Promise<string | null>>,\n httpCache: HttpCache | undefined,\n): Promise<PluginValue> {\n if (typeof value === 'string') {\n if (value.startsWith(FILE_URL_PREFIX)) {\n const relPath = value.slice(FILE_URL_PREFIX.length);\n const absPath = resolve(contractDir, relPath);\n if (!existsSync(absPath)) {\n diag.warn(file, line, `plugins.${pluginName}: file not found: ${relPath}`);\n return value;\n }\n return readFileSync(absPath, 'utf-8');\n }\n if (value.startsWith('http://') || value.startsWith('https://')) {\n let pending = inFlight.get(value);\n if (!pending) {\n pending = fetchUrl(value, httpCache);\n inFlight.set(value, pending);\n }\n const fetched = await pending;\n if (fetched === null) {\n diag.warn(file, line, `plugins.${pluginName}: failed to fetch ${value}`);\n return value;\n }\n return fetched;\n }\n return value;\n }\n if (Array.isArray(value)) {\n return Promise.all(value.map(item => resolveUrls(item, contractDir, file, line, pluginName, diag, inFlight, httpCache)));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, PluginValue> = {};\n for (const [k, v] of Object.entries(value)) {\n out[k] = await resolveUrls(v, contractDir, file, line, pluginName, diag, inFlight, httpCache);\n }\n return out;\n }\n return value;\n}\n\nasync function fetchUrl(url: string, httpCache: HttpCache | undefined): Promise<string | null> {\n if (httpCache) {\n const cached = httpCache.get(url);\n if (cached !== null) return cached;\n }\n try {\n const res = await fetch(url);\n if (!res.ok) return null;\n const body = await res.text();\n httpCache?.set(url, body);\n return body;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["default","importOpenApiPlugin","readFileSync","writeFileSync","mkdirSync","resolve","join","dirname","glob","DiagnosticCollector","parseCk","decomposeCk","validateOp","validateRefs","validateInheritance","applyOptionsDefaults","applyVariableSubstitution","computeModelsWithInput","computeModelsWithOutput","readFileSync","resolve","dirname","join","readFileSync","writeFileSync","mkdirSync","existsSync","createHash","join","dirname","resolve","DEFAULT_CACHE_DIR","BUILD_CACHE_FILENAME","HTTP_CACHE_DIRNAME","computeHash","content","createHash","update","digest","CacheService","enabled","root","buildCachePath","httpCacheDir","rootDir","options","resolve","dir","join","loadBuildCache","JSON","parse","readFileSync","saveBuildCache","cache","mkdirSync","dirname","recursive","writeFileSync","stringify","httpCache","get","url","getHttpResponse","set","body","setHttpResponse","urlPath","path","existsSync","homedir","CONFIG_FILENAME","loadConfig","configPath","startDir","process","cwd","resolved","resolve","text","readFileSync","config","JSON","parse","configDir","dirname","err","Error","message","cause","dir","candidate","join","parent","normalizePlugins","plugins","Object","entries","map","name","options","plugin","mergeConfig","cliArgs","cache","enabled","DEFAULT_CACHE_DIR","rootDir","startsWith","homedir","slice","patterns","watch","force","prettier","resolve","isAbsolute","existsSync","createRequire","loadPlugins","entries","configDir","loaded","entry","plugin","specifier","modulePath","startsWith","isAbsolute","resolve","createRequire","mod","err","Error","message","cause","raw","default","name","push","makePluginContext","config","cacheEnabled","emitFile","rootDir","options","computePluginFingerprint","newCache","cacheKey","allHashes","Object","values","sort","join","computeHash","pluginOutputsExist","cache","files","split","filter","Boolean","length","every","f","existsSync","existsSync","readFileSync","resolve","dirname","FILE_URL_PREFIX","resolvePluginExtensions","roots","rootDir","diag","options","inFlight","Map","httpCache","root","contractDir","dirname","resolve","file","route","routes","op","operations","plugins","resolved","name","value","Object","entries","resolveUrls","loc","line","pluginExtensions","pluginName","startsWith","relPath","slice","length","absPath","existsSync","warn","readFileSync","pending","get","fetchUrl","set","fetched","Array","isArray","Promise","all","map","item","out","k","v","url","cached","res","fetch","ok","body","text","BUILTIN_COMMAND_PLUGINS","importOpenApiPlugin","printHelp","console","log","plugin","command","name","padEnd","description","parseArgs","argv","args","slice","config","watch","force","help","i","length","arg","FALLBACK_BUILTINS_RE","substituteBuiltins","input","builtins","onMissing","includes","replace","_match","escapedName","varName","undefined","value","collectFallbackKeys","entries","merged","entry","keys","options","Array","isArray","warn","Object","missing","resolveFiles","patterns","rootDir","files","pattern","matches","glob","absolute","cwd","resolve","push","Set","formatWithPrettier","results","prettier","result","resolveConfig","outPath","content","format","filepath","main","cliArgs","process","exit","subcommand","startsWith","matched","find","p","subArgs","usage","fileConfig","configDir","loadConfig","resolved","mergeConfig","run","error","plugins","loadPlugins","fallbackKeys","join","diag","DiagnosticCollector","resolvedBase","cacheEnabled","cache","enabled","cacheService","CacheService","dir","loadBuildCache","newCache","allContracts","allOps","filePath","endsWith","source","readFileSync","computeHash","ckAst","parseCk","applyOptionsDefaults","applyVariableSubstitution","ctx","makePluginContext","validate","err","message","transform","contract","op","decomposeCk","models","routes","resolvePluginExtensions","httpCache","validatorsByName","Map","validateExtension","set","root","route","operations","pluginExtensions","validator","get","errors","msg","file","loc","line","warnings","modelsWithInput","computeModelsWithInput","flatMap","r","modelsWithOutput","computeModelsWithOutput","depsFingerprint","sort","depsChanged","hasErrors","report","exitCode","validateRefs","validateInheritance","validateOp","generateTargets","optionsSuffix","JSON","stringify","cacheKey","fingerprint","computePluginFingerprint","pluginOutputsExist","pluginEmitted","contractRoots","opRoots","map","f","mkdirSync","recursive","dirname","writeFileSync","saveBuildCache","watchFiles","allDirs","event","filename","full","catch"]} |
+5
-5
| { | ||
| "name": "@contractkit/cli", | ||
| "version": "0.9.0", | ||
| "version": "0.9.1", | ||
| "description": "Compiler for .ck files", | ||
@@ -31,4 +31,4 @@ "author": { | ||
| "glob": "^13.0.6", | ||
| "@contractkit/openapi-to-ck": "0.7.4", | ||
| "@contractkit/core": "0.14.0" | ||
| "@contractkit/core": "0.15.0", | ||
| "@contractkit/openapi-to-ck": "0.7.5" | ||
| }, | ||
@@ -44,4 +44,4 @@ "peerDependencies": { | ||
| "devDependencies": { | ||
| "@repo/config-eslint": "0.3.1", | ||
| "@repo/config-typescript": "0.1.0" | ||
| "@repo/config-typescript": "0.1.0", | ||
| "@repo/config-eslint": "0.3.1" | ||
| }, | ||
@@ -48,0 +48,0 @@ "scripts": { |
+2
-2
@@ -244,3 +244,3 @@ #!/usr/bin/env node | ||
| for (const { plugin, entry } of plugins) { | ||
| const ctx = makePluginContext(entry, config); | ||
| const ctx = makePluginContext(entry, config, cacheEnabled); | ||
| if (plugin.validate) { | ||
@@ -347,3 +347,3 @@ try { | ||
| const pluginEmitted: { outPath: string; content: string }[] = []; | ||
| const ctx = makePluginContext(entry, config, (outPath, content) => { | ||
| const ctx = makePluginContext(entry, config, cacheEnabled, (outPath, content) => { | ||
| pluginEmitted.push({ outPath, content }); | ||
@@ -350,0 +350,0 @@ }); |
+14
-1
@@ -40,6 +40,19 @@ import { resolve, isAbsolute } from 'node:path'; | ||
| export function makePluginContext(entry: PluginEntry, config: ResolvedConfig, emitFile?: (outPath: string, content: string) => void): PluginContext { | ||
| /** | ||
| * Build the {@link PluginContext} a plugin sees inside its hooks. `emitFile` is | ||
| * only meaningful during `generateTargets`; the default implementation throws if | ||
| * called from `validate` / `transform`. Pass `cacheEnabled=false` (computed by the | ||
| * CLI from `--force` / `cache: false`) so the plugin can bypass its own incremental | ||
| * caches. | ||
| */ | ||
| export function makePluginContext( | ||
| entry: PluginEntry, | ||
| config: ResolvedConfig, | ||
| cacheEnabled: boolean, | ||
| emitFile?: (outPath: string, content: string) => void, | ||
| ): PluginContext { | ||
| return { | ||
| rootDir: config.rootDir, | ||
| options: entry.options ?? {}, | ||
| cacheEnabled, | ||
| emitFile: | ||
@@ -46,0 +59,0 @@ emitFile ?? |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
285881
0.6%2531
0.56%+ Added
+ Added
- Removed
- Removed
Updated