@codama/cli
Version:
A CLI for setting up and managing Codama IDLs
1 lines • 60.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/cli/index.ts","../src/program.ts","../src/commands/init.ts","../src/utils/childCommands.ts","../src/utils/errors.ts","../src/utils/fs.ts","../src/utils/import.ts","../src/utils/logs.ts","../src/utils/packageInstall.ts","../src/utils/packageJson.ts","../src/utils/packageManager.ts","../src/utils/prompts.ts","../src/utils/nodes.ts","../src/utils/promises.ts","../src/utils/visitors.ts","../src/commands/run.ts","../src/config.ts","../src/parsedConfig.ts","../src/programOptions.ts"],"sourcesContent":["import { createProgram, runProgram } from '../program';\n\nconst program = createProgram();\n\nexport async function run(argv: readonly string[]) {\n await runProgram(program, argv);\n}\n","import { Command, createCommand, ParseOptions } from 'commander';\nimport pico from 'picocolors';\n\nimport { setInitCommand, setRunCommand } from './commands';\nimport { setProgramOptions } from './programOptions';\nimport { logDebug, logError } from './utils';\n\nexport async function codama(args: string[], opts?: { suppressOutput?: boolean }): Promise<void> {\n const program = createProgram({\n exitOverride: true,\n suppressOutput: opts?.suppressOutput,\n });\n await runProgram(program, args, { from: 'user' });\n}\n\nexport async function runProgram(program: Command, argv: readonly string[], parseOptions?: ParseOptions) {\n try {\n await program.parseAsync(argv, parseOptions);\n } catch (err) {\n const error = err as { message: string; stack?: string; items?: string[] };\n if (program.opts().debug) {\n logDebug(`${error.stack}`);\n }\n logError(pico.bold(error.message), error.items ?? []);\n process.exitCode = 1;\n }\n}\n\nexport function createProgram(internalOptions?: { exitOverride?: boolean; suppressOutput?: boolean }): Command {\n const program = createCommand()\n .version(__VERSION__)\n .allowExcessArguments(false)\n .configureHelp({ showGlobalOptions: true, sortOptions: true, sortSubcommands: true });\n\n // Set program options and commands.\n setProgramOptions(program);\n setInitCommand(program);\n setRunCommand(program);\n\n // Internal options.\n if (internalOptions?.exitOverride) {\n program.exitOverride();\n }\n if (internalOptions?.suppressOutput) {\n program.configureOutput({\n writeErr: () => {},\n writeOut: () => {},\n });\n }\n\n return program;\n}\n","import { Command } from 'commander';\nimport pico from 'picocolors';\nimport prompts, { PromptType } from 'prompts';\n\nimport { Config, ScriptConfig, ScriptName } from '../config';\nimport {\n canRead,\n CliError,\n importModuleItem,\n installMissingDependencies,\n isRootNode,\n logBanner,\n logSuccess,\n PROMPT_OPTIONS,\n resolveRelativePath,\n writeFile,\n} from '../utils';\n\nexport function setInitCommand(program: Command): void {\n program\n .command('init')\n .argument('[output]', 'Optional path used to output the configuration file')\n .option('-d, --default', 'Bypass prompts and select all defaults options')\n .option('--force', 'Overwrite existing configuration file, if any')\n .option('--js', 'Forces the output to be a JavaScript file')\n .option('--gill', 'Forces the output to be a gill based JavaScript file')\n .action(doInit);\n}\n\ntype InitOptions = {\n default?: boolean;\n force?: boolean;\n gill?: boolean;\n js?: boolean;\n};\n\nasync function doInit(explicitOutput: string | undefined, options: InitOptions) {\n const output = getOutputPath(explicitOutput, options);\n const configFileType = getConfigFileType(output, options);\n\n if (!options.force && (await canRead(output))) {\n throw new CliError(`Configuration file already exists.`, [`${pico.bold('Path')}: ${output}`]);\n }\n\n // Start prompts.\n logBanner();\n const result = await getPromptResult(options, configFileType);\n\n // Check dependencies.\n const isAnchor = await isAnchorIdl(result.idlPath);\n await installMissingDependencies(`Your configuration requires additional dependencies.`, [\n ...(isAnchor ? ['@codama/nodes-from-anchor'] : []),\n ...(result.scripts.includes('js') ? ['@codama/renderers-js'] : []),\n ...(result.scripts.includes('rust') ? ['@codama/renderers-rust'] : []),\n ]);\n\n // Write configuration file.\n const content = getContentFromPromptResult(result, configFileType);\n await writeFile(output, content);\n console.log();\n logSuccess(pico.bold('Configuration file created.'), [`${pico.bold('Path')}: ${output}`]);\n}\n\nfunction getOutputPath(explicitOutput: string | undefined, options: Pick<InitOptions, 'gill' | 'js'>): string {\n if (explicitOutput) {\n return resolveRelativePath(explicitOutput);\n }\n return resolveRelativePath(options.js || options.gill ? 'codama.js' : 'codama.json');\n}\n\ntype PromptResult = {\n idlPath: string;\n jsPath?: string;\n rustCrate?: string;\n rustPath?: string;\n scripts: string[];\n};\n\nasync function getPromptResult(\n options: Pick<InitOptions, 'default'>,\n configFileType: ConfigFileType,\n): Promise<PromptResult> {\n const defaults = getDefaultPromptResult();\n if (options.default) {\n return defaults;\n }\n\n const hasScript =\n (script: string, type: PromptType = 'text') =>\n (_: unknown, values: { scripts: string[] }) =>\n values.scripts.includes(script) ? type : null;\n return await prompts(\n [\n {\n initial: defaults.idlPath,\n message: 'Where is your IDL located? (Supports Codama and Anchor IDLs).',\n name: 'idlPath',\n type: 'text',\n },\n {\n choices: [\n { selected: true, title: 'Generate JavaScript client', value: 'js' },\n { selected: true, title: 'Generate Rust client', value: 'rust' },\n ],\n instructions: '[space] to toggle / [a] to toggle all / [enter] to submit',\n message: 'Which script preset would you like to use?',\n name: 'scripts',\n type: 'multiselect',\n onRender() {\n if (configFileType === 'gill') {\n const value = (this as unknown as { value: prompts.Choice[] }).value;\n const jsChoice = value.find(choice => choice.value === 'js')!;\n jsChoice.description = pico.yellow('Required with --gill option.');\n jsChoice.selected = true;\n }\n },\n },\n {\n initial: defaults.jsPath,\n message: '[js] Where should the JavaScript code be generated?',\n name: 'jsPath',\n type: hasScript('js'),\n },\n {\n initial: defaults.rustCrate,\n message: '[rust] Where is the Rust client crate located?',\n name: 'rustCrate',\n type: hasScript('rust'),\n },\n {\n initial: (prev: string) => `${prev}/src/generated`,\n message: '[rust] Where should the Rust code be generated?',\n name: 'rustPath',\n type: hasScript('rust'),\n },\n ],\n PROMPT_OPTIONS,\n );\n}\n\nfunction getDefaultPromptResult(): PromptResult {\n return {\n idlPath: 'program/idl.json',\n jsPath: 'clients/js/src/generated',\n rustCrate: 'clients/rust',\n rustPath: 'clients/rust/src/generated',\n scripts: ['js', 'rust'],\n };\n}\n\ntype ConfigFileType = 'gill' | 'js' | 'json';\nfunction getConfigFileType(output: string, options: Pick<InitOptions, 'gill' | 'js'>): ConfigFileType {\n if (options.gill) return 'gill';\n else if (options.js) return 'js';\n return output.endsWith('.js') ? 'js' : 'json';\n}\n\nfunction getContentFromPromptResult(result: PromptResult, configFileType: ConfigFileType): string {\n switch (configFileType) {\n case 'gill':\n return getContentForGill(result);\n case 'js':\n return (\n `export default ` +\n JSON.stringify(getConfigFromPromptResult(result), null, 4)\n // Remove quotes around property names\n .replace(/\"([^\"]+)\":/g, '$1:')\n // Convert double-quoted strings to single quotes\n .replace(/\"([^\"]*)\"/g, \"'$1'\")\n );\n case 'json':\n default:\n return JSON.stringify(getConfigFromPromptResult(result), null, 4);\n }\n}\n\nfunction getConfigFromPromptResult(result: PromptResult): Config {\n const scripts: Record<ScriptName, ScriptConfig> = {};\n if (result.scripts.includes('js')) {\n scripts.js = {\n from: '@codama/renderers-js',\n args: [result.jsPath],\n };\n }\n if (result.scripts.includes('rust')) {\n scripts.rust = {\n from: '@codama/renderers-rust',\n args: [result.rustPath, { crateFolder: result.rustCrate, formatCode: true }],\n };\n }\n return { idl: result.idlPath, before: [], scripts };\n}\n\nfunction getContentForGill(result: PromptResult): string {\n const attributes: string[] = [\n `idl: \"${result.idlPath}\"`,\n `clientJs: \"${result.jsPath}\"`,\n ...(result.scripts.includes('rust') ? [`clientRust: \"${result.rustPath}\"`] : []),\n ];\n const attributesString = attributes.map(attr => ` ${attr},\\n`).join('');\n\n return (\n `import { createCodamaConfig } from \"gill\";\\n\\n` +\n `export default createCodamaConfig({\\n${attributesString}});\\n`\n );\n}\n\nasync function isAnchorIdl(idlPath: string): Promise<boolean> {\n const resolvedIdlPath = resolveRelativePath(idlPath);\n if (!(await canRead(resolvedIdlPath))) return false;\n try {\n const idlContent = await importModuleItem({ identifier: 'IDL', from: resolvedIdlPath });\n return !isRootNode(idlContent);\n } catch {\n return false;\n }\n}\n","import { ChildProcess, spawn, SpawnOptions } from 'child_process';\n\nexport type ChildCommand = {\n command: string;\n args: string[];\n};\n\nexport function createChildCommand(command: string, args: string[] = []): ChildCommand {\n return { command, args };\n}\n\nexport function formatChildCommand(childCommand: ChildCommand): string {\n const { command, args } = childCommand;\n return [command, ...args].join(' ');\n}\n\nexport type ChildProcessResult = ChildProcess & {\n stdoutString: string;\n stderrString: string;\n};\n\nexport type ChildProcessError = Error & {\n childProcess: ChildProcessResult;\n};\n\nexport async function spawnChildCommand(\n childCommand: ChildCommand,\n options: SpawnOptions & { quiet: boolean } = { quiet: false },\n): Promise<ChildProcess & { stdoutString: string; stderrString: string }> {\n const { command, args } = childCommand;\n const childProcess = spawn(command, args, options) as ChildProcessResult;\n childProcess.stdoutString = '';\n childProcess.stderrString = '';\n\n childProcess.stdout?.on('data', (chunk: Uint8Array) => {\n childProcess.stdoutString += chunk.toString();\n if (!options.quiet) {\n process.stdout.write(chunk);\n }\n });\n childProcess.stderr?.on('data', (chunk: Uint8Array) => {\n childProcess.stderrString += chunk.toString();\n if (!options.quiet) {\n process.stderr.write(chunk);\n }\n });\n\n const exitCode: number = await new Promise((resolve, reject) => {\n childProcess.on('error', () => reject(createChildProcessResultError(childCommand, childProcess)));\n childProcess.on('close', resolve);\n });\n if (exitCode) {\n throw createChildProcessResultError(childCommand, childProcess);\n }\n\n return childProcess;\n}\n\nfunction createChildProcessResultError(\n childCommand: ChildCommand,\n childProcess: ChildProcessResult,\n): ChildProcessError {\n const error = new Error(`Command [${formatChildCommand(childCommand)}] failed`) as ChildProcessError;\n error.childProcess = childProcess;\n return error;\n}\n","export class CliError extends Error {\n constructor(\n message: string,\n public items: string[] = [],\n options?: ErrorOptions,\n ) {\n super(message, options);\n this.name = 'CliError';\n }\n}\n","import { R_OK, W_OK } from 'node:constants';\nimport fs, { PathLike } from 'node:fs';\nimport path from 'node:path';\n\nexport function resolveRelativePath(childPath: string, relativeDirectory: string | null = null) {\n return path.resolve(relativeDirectory ?? process.cwd(), childPath);\n}\n\nexport function resolveConfigPath(childPath: string, configPath: string | null) {\n const configDir = configPath ? path.dirname(configPath) : null;\n return resolveRelativePath(childPath, configDir);\n}\n\nexport function isLocalModulePath(modulePath: string) {\n return modulePath.startsWith('.') || modulePath.startsWith('/');\n}\n\nexport async function readJson<T>(filePath: string): Promise<T> {\n return JSON.parse(await readFile(filePath)) as T;\n}\n\nexport async function readFile(filePath: string): Promise<string> {\n return await fs.promises.readFile(filePath, 'utf8');\n}\n\nexport async function writeFile(filePath: string, content: string) {\n const directory = path.dirname(filePath);\n if (!(await canWrite(directory))) {\n await fs.promises.mkdir(directory, { recursive: true });\n }\n await fs.promises.writeFile(filePath, content);\n}\n\nexport async function canRead(p: PathLike) {\n try {\n await fs.promises.access(p, R_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function canWrite(p: PathLike) {\n try {\n await fs.promises.access(p, W_OK);\n return true;\n } catch {\n return false;\n }\n}\n","import { createRequire } from 'node:module';\n\nimport pico from 'picocolors';\n\nimport { CliError } from './errors';\nimport { canRead, isLocalModulePath, resolveRelativePath } from './fs';\n\ntype ImportModuleItemOptions = {\n from: string;\n identifier?: string;\n item?: string;\n};\n\nexport async function importModuleItem<T = unknown>(options: ImportModuleItemOptions): Promise<T> {\n const module = await importModule(options);\n const moduleItem = pickModuleItem(module, options.item) as T | undefined;\n if (moduleItem === undefined) {\n const items = getErrorItems(options);\n throw new CliError(`Failed to load ${options.identifier ?? 'module'}.`, items);\n }\n return moduleItem;\n}\n\ntype ModuleDefinition = Partial<Record<string, unknown>> & {\n __esModule?: boolean;\n default?: Partial<Record<string, unknown>> & { default?: Partial<Record<string, unknown>> };\n};\n\nfunction pickModuleItem(module: ModuleDefinition, item: string = 'default'): unknown {\n if (item === 'default') {\n return module.default?.default ?? module.default ?? module;\n }\n return module[item] ?? module.default?.[item] ?? module.default?.default?.[item];\n}\n\nasync function importModule<T extends object>(options: ImportModuleItemOptions): Promise<T> {\n if (isLocalModulePath(options.from)) {\n return await importLocalModule(options);\n }\n\n try {\n return await importExternalUserModule(options);\n } catch {\n return await importExternalModule(options);\n }\n}\n\nasync function importLocalModule<T extends object>(options: ImportModuleItemOptions): Promise<T> {\n const { from, identifier } = options;\n if (!(await canRead(from))) {\n const items = getErrorItems(options);\n throw new CliError(`Cannot access ${identifier ?? 'module'}.`, items);\n }\n\n const dotIndex = from.lastIndexOf('.');\n const extension = dotIndex === -1 ? undefined : from.slice(dotIndex);\n const modulePromise = extension === '.json' ? import(from, { with: { type: 'json' } }) : import(from);\n return await handleImportPromise(modulePromise, options);\n}\n\nasync function importExternalModule<T extends object>(options: ImportModuleItemOptions): Promise<T> {\n return await handleImportPromise(import(options.from), options);\n}\n\nasync function importExternalUserModule<T extends object>(options: ImportModuleItemOptions): Promise<T> {\n const userPackageJsonPath = resolveRelativePath('package.json');\n const userRequire = createRequire(userPackageJsonPath);\n const userFrom = userRequire.resolve(options.from);\n return await importExternalModule<T>({ ...options, from: userFrom });\n}\n\nasync function handleImportPromise<T extends object>(\n importPromise: Promise<unknown>,\n options: ImportModuleItemOptions,\n): Promise<T> {\n try {\n return (await importPromise) as T;\n } catch (cause) {\n const items = getErrorItems(options, cause);\n throw new CliError(`Failed to load ${options.identifier ?? 'module'}.`, items, { cause });\n }\n}\n\nfunction getErrorItems(options: ImportModuleItemOptions, cause?: unknown): string[] {\n const { from, item } = options;\n const items = [`${pico.bold('Module')}: ${from}`];\n if (item) {\n items.push(`${pico.bold('Item')}: ${item}`);\n }\n\n const hasCause = !!cause && typeof cause === 'object' && 'message' in cause && typeof cause.message === 'string';\n if (hasCause) {\n items.push(`${pico.bold('Caused by')}: ${(cause as { message: string }).message}`);\n }\n\n return items;\n}\n","import pico from 'picocolors';\n\ntype LogLevel = 'debug' | 'error' | 'info' | 'success' | 'warning';\n\ntype LogOptions = {\n level: LogLevel;\n message: string;\n items?: string[];\n};\n\nfunction getLogLevelInfo(logLevel: LogLevel) {\n const identity = (text: string) => text;\n const infos: Record<LogLevel, [string, (text: string) => string, (text: string) => string]> = {\n success: ['✔', pico.green, pico.green],\n info: ['→', pico.blueBright, identity],\n warning: ['▲', pico.yellow, pico.yellow],\n error: ['✖', pico.red, pico.red],\n debug: ['✱', pico.magenta, pico.magenta],\n };\n\n return {\n icon: infos[logLevel][0],\n color: infos[logLevel][1],\n messageColor: infos[logLevel][2],\n };\n}\n\nconst logWrapper = (level: LogLevel) => (message: string, items?: string[]) => log({ level, message, items });\nexport const logSuccess = logWrapper('success');\nexport const logError = logWrapper('error');\nexport const logInfo = logWrapper('info');\nexport const logWarning = logWrapper('warning');\nexport const logDebug = logWrapper('debug');\n\nfunction log({ level, message, items }: LogOptions): void {\n const { icon, color, messageColor } = getLogLevelInfo(level);\n console.log(color(icon), messageColor(message));\n if (items) {\n logItems(items, color);\n }\n}\n\nfunction logItems(items: string[], color?: (text: string) => string): void {\n const colorFn = color ?? (text => text);\n items.forEach((item, index) => {\n const prefix = index === items.length - 1 ? '└─' : '├─';\n console.log(' ' + colorFn(prefix), item);\n });\n}\n\nexport function logBanner(): void {\n console.log(getBanner());\n}\n\nfunction getBanner(): string {\n const textBanner = 'Welcome to Codama!';\n const gradientBanner = pico.bold(`\\x1b[38;2;231;171;97m${textBanner}\\x1b[0m`);\n return process.stdout.isTTY && process.stdout.getColorDepth() > 8 ? gradientBanner : textBanner;\n}\n","import pico from 'picocolors';\nimport prompts from 'prompts';\n\nimport { ChildCommand, createChildCommand, formatChildCommand, spawnChildCommand } from './childCommands';\nimport { logError, logInfo, logSuccess, logWarning } from './logs';\nimport { getPackageJsonDependencies } from './packageJson';\nimport { getPackageManager } from './packageManager';\nimport { PROMPT_OPTIONS } from './prompts';\n\nexport async function getPackageManagerInstallCommand(\n packages: string[],\n options: string[] = [],\n): Promise<ChildCommand> {\n const packageManager = await getPackageManager();\n const args = [packageManager === 'yarn' ? 'add' : 'install', ...packages, ...options];\n return createChildCommand(packageManager, args);\n}\n\nexport async function installMissingDependencies(message: string, requiredDependencies: string[]): Promise<boolean> {\n if (requiredDependencies.length === 0) return true;\n\n const installedDependencies = await getPackageJsonDependencies({ includeDev: true });\n const missingDependencies = requiredDependencies.filter(dep => !installedDependencies.includes(dep));\n if (missingDependencies.length === 0) return true;\n\n return await installDependencies(message, missingDependencies);\n}\n\nexport async function installDependencies(message: string, dependencies: string[]): Promise<boolean> {\n if (dependencies.length === 0) return true;\n const installCommand = await getPackageManagerInstallCommand(dependencies);\n const formattedInstallCommand = pico.yellow(formatChildCommand(installCommand));\n\n if (process.env.CI) {\n logWarning(message);\n logWarning(`Skipping installation in CI environment. Please install manually:`);\n logWarning(formattedInstallCommand);\n return false;\n }\n\n logWarning(message);\n logWarning(`Install command: ${formattedInstallCommand}`);\n\n const dependencyResult: { installDependencies: boolean } = await prompts(\n { initial: true, message: 'Install dependencies?', name: 'installDependencies', type: 'confirm' },\n PROMPT_OPTIONS,\n );\n if (!dependencyResult.installDependencies) {\n logWarning('Skipping installation.');\n return false;\n }\n\n try {\n logInfo(`Installing`, dependencies);\n await spawnChildCommand(installCommand, { quiet: true });\n logSuccess(`Dependencies installed successfully.`);\n return true;\n } catch {\n logError(`Failed to install dependencies. Please try manually:`);\n logError(formattedInstallCommand);\n return false;\n }\n}\n","import pico from 'picocolors';\n\nimport { CliError } from './errors';\nimport { canRead, readJson, resolveRelativePath } from './fs';\n\ntype PackageJson = {\n name: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n packageManager?: string;\n [key: string]: unknown;\n};\n\nlet packageJson: PackageJson | undefined;\nexport async function getPackageJson(): Promise<PackageJson> {\n if (!packageJson) {\n const packageJsonPath = resolveRelativePath('package.json');\n if (!(await canRead(packageJsonPath))) {\n throw new CliError('Cannot read package.json.', [`${pico.bold('Path')}: ${packageJsonPath}`]);\n }\n packageJson = await readJson<PackageJson>(packageJsonPath);\n }\n return packageJson;\n}\n\nexport async function getPackageJsonDependencies(options: { includeDev?: boolean } = {}): Promise<string[]> {\n const packageJson = await getPackageJson();\n return [\n ...(packageJson.dependencies ? Object.keys(packageJson.dependencies) : []),\n ...(options.includeDev && packageJson.devDependencies ? Object.keys(packageJson.devDependencies) : []),\n ];\n}\n","import { createChildCommand, spawnChildCommand } from './childCommands';\nimport { canRead, resolveRelativePath } from './fs';\nimport { getPackageJson } from './packageJson';\n\ntype PackageManager = 'bun' | 'npm' | 'pnpm' | 'yarn';\n\nconst FALLBACK_PACKAGE_MANAGER: PackageManager = 'npm';\n\nlet packageManager: PackageManager | undefined;\nexport async function getPackageManager(): Promise<PackageManager> {\n if (!packageManager) {\n packageManager = await detectPackageManager();\n }\n return packageManager;\n}\n\nasync function detectPackageManager(): Promise<PackageManager> {\n const fromPackageJson = await detectPackageManagerFromPackageJson();\n if (fromPackageJson) return fromPackageJson;\n\n const fromLockfile = await detectPackageManagerFromLockfile();\n if (fromLockfile) return fromLockfile;\n\n const fromInstalledCli = await detectPackageManagerFromInstalledCli();\n if (fromInstalledCli) return fromInstalledCli;\n\n return FALLBACK_PACKAGE_MANAGER;\n}\n\nasync function detectPackageManagerFromPackageJson(): Promise<PackageManager | undefined> {\n const packageJson = await getPackageJson();\n if (!packageJson.packageManager) return undefined;\n if (packageJson.packageManager.startsWith('npm@')) return 'npm';\n if (packageJson.packageManager.startsWith('pnpm@')) return 'pnpm';\n if (packageJson.packageManager.startsWith('yarn@')) return 'yarn';\n if (packageJson.packageManager.startsWith('bun@')) return 'bun';\n return undefined;\n}\n\nasync function detectPackageManagerFromLockfile(): Promise<PackageManager | undefined> {\n const [isYarn, isPnpm, isBun, isNpm] = await Promise.all([\n canRead(resolveRelativePath('yarn.lock')),\n canRead(resolveRelativePath('pnpm-lock.yaml')),\n canRead(resolveRelativePath('bun.lockb')),\n canRead(resolveRelativePath('package-lock.json')),\n ]);\n\n if (isYarn) return 'yarn';\n if (isPnpm) return 'pnpm';\n if (isBun) return 'bun';\n if (isNpm) return 'npm';\n return undefined;\n}\n\nasync function detectPackageManagerFromInstalledCli(): Promise<PackageManager | undefined> {\n const [isPnpm, isYarn, isBun] = await Promise.all([\n hasPackageManagerCli('pnpm'),\n hasPackageManagerCli('yarn'),\n hasPackageManagerCli('bun'),\n ]);\n\n if (isPnpm) return 'pnpm';\n if (isYarn) return 'yarn';\n if (isBun) return 'bun';\n return undefined;\n}\n\nasync function hasPackageManagerCli(packageManager: PackageManager): Promise<boolean> {\n return await spawnChildCommand(createChildCommand(packageManager, ['--version']), { quiet: true })\n .then(() => true)\n .catch(() => false);\n}\n","import prompts from 'prompts';\n\nimport { CliError } from './errors';\n\nexport const PROMPT_OPTIONS: prompts.Options = {\n onCancel: () => {\n throw new CliError('Operation cancelled.');\n },\n};\n","import type { RootNode } from '@codama/nodes';\n\nimport { CliError } from './errors';\nimport { importModuleItem } from './import';\nimport { installMissingDependencies } from './packageInstall';\n\nexport async function getRootNodeFromIdl(idl: unknown): Promise<RootNode> {\n if (typeof idl !== 'object' || idl === null) {\n throw new CliError('Unexpected IDL content. Expected an object, got ' + typeof idl);\n }\n if (isRootNode(idl)) {\n return idl;\n }\n\n const hasNodesFromAnchor = await installMissingDependencies(\n 'Anchor IDL detected. Additional dependencies are required to process Anchor IDLs.',\n ['@codama/nodes-from-anchor'],\n );\n if (!hasNodesFromAnchor) {\n throw new CliError('Cannot proceed without Anchor IDL support.');\n }\n\n const rootNodeFromAnchor = await importModuleItem<(idl: unknown) => RootNode>({\n from: '@codama/nodes-from-anchor',\n item: 'rootNodeFromAnchor',\n });\n return rootNodeFromAnchor(idl);\n}\n\nexport function isRootNode(value: unknown): value is RootNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { standard?: string }).standard === 'codama' &&\n (value as { kind?: string }).kind === 'rootNode'\n );\n}\n","export function promisify<T>(value: Promise<T> | T): Promise<T> {\n return Promise.resolve(value);\n}\n","import type { RootNode } from '@codama/nodes';\nimport { rootNodeVisitor, visit, type Visitor } from '@codama/visitors-core';\nimport pico from 'picocolors';\n\nimport { ParsedVisitorConfig } from '../parsedConfig';\nimport { CliError } from './errors';\nimport { importModuleItem } from './import';\nimport { isRootNode } from './nodes';\nimport { promisify } from './promises';\n\nexport async function getRootNodeVisitors(\n visitors: readonly ParsedVisitorConfig[],\n): Promise<Visitor<RootNode, 'rootNode'>[]> {\n return await Promise.all(visitors.map(getRootNodeVisitor));\n}\n\nasync function getRootNodeVisitor(visitorConfig: ParsedVisitorConfig): Promise<Visitor<RootNode, 'rootNode'>> {\n const { item, path } = visitorConfig;\n const identifier = getVisitorIdentifier(visitorConfig);\n const moduleItem = await importModuleItem({ identifier, from: path, item });\n const visitor = await getVisitorFromModuleItem(identifier, moduleItem, visitorConfig);\n return rootNodeVisitor(root => {\n const result = visit(root, visitor);\n return isRootNode(result) ? result : root;\n });\n}\n\ntype UnknownFunction = (...args: readonly unknown[]) => unknown;\nasync function getVisitorFromModuleItem(\n identifier: string,\n moduleItem: unknown,\n visitorConfig: ParsedVisitorConfig,\n): Promise<Visitor<unknown, 'rootNode'>> {\n const { args, item, path } = visitorConfig;\n if (isRootNodeVisitor(moduleItem)) {\n return moduleItem;\n }\n if (typeof moduleItem === 'function') {\n const result = await promisify((moduleItem as UnknownFunction)(...args));\n if (isRootNodeVisitor(result)) {\n return result;\n }\n }\n throw new CliError(`Invalid visitor. Expected a visitor or a function returning a visitor.`, [\n `${pico.bold('Visitor')}: ${identifier}`,\n `${pico.bold('Path')}: ${path}`,\n ...(item ? [`${pico.bold('Item')}: ${item}`] : []),\n ]);\n}\n\nfunction isRootNodeVisitor(value: unknown): value is Visitor<unknown, 'rootNode'> {\n return !!value && typeof value === 'object' && 'visitRoot' in value;\n}\n\nfunction getVisitorIdentifier(visitorConfig: ParsedVisitorConfig): string {\n const { index, script } = visitorConfig;\n let identifier = `visitor #${index}`;\n identifier += script ? ` in script \"${script}\"` : '';\n return identifier;\n}\n","import type { RootNode } from '@codama/nodes';\nimport { visit, type Visitor } from '@codama/visitors-core';\nimport { Command } from 'commander';\nimport pico from 'picocolors';\n\nimport { ScriptName } from '../config';\nimport { getParsedConfigFromCommand, ParsedConfig } from '../parsedConfig';\nimport {\n CliError,\n getRootNodeVisitors,\n installMissingDependencies,\n isLocalModulePath,\n logInfo,\n logSuccess,\n logWarning,\n} from '../utils';\n\nexport function setRunCommand(program: Command): void {\n program\n .command('run')\n .argument('[scripts...]', 'The scripts to execute')\n .option('-a, --all', 'Run all scripts in the configuration file')\n .action(doRun);\n}\n\ntype RunOptions = {\n all?: boolean;\n};\n\nasync function doRun(explicitScripts: string[], { all }: RunOptions, cmd: Command) {\n if (all && explicitScripts.length > 0) {\n logWarning(`CLI arguments \"${explicitScripts.join(' ')}\" are ignored because the \"--all\" option is set.`);\n }\n const parsedConfig = await getParsedConfigFromCommand(cmd);\n const scripts = all ? Object.keys(parsedConfig.scripts) : explicitScripts;\n const plans = await getPlans(parsedConfig, scripts);\n runPlans(plans, parsedConfig.rootNode);\n}\n\ntype RunPlan = {\n script: ScriptName | null;\n visitors: Visitor<RootNode, 'rootNode'>[];\n};\n\nasync function getPlans(\n parsedConfig: Pick<ParsedConfig, 'before' | 'configPath' | 'scripts'>,\n scripts: ScriptName[],\n): Promise<RunPlan[]> {\n const plans: RunPlan[] = [];\n if (scripts.length === 0 && parsedConfig.before.length === 0) {\n throw new CliError('There are no scripts or before visitors to run.');\n }\n\n checkMissingScripts(parsedConfig, scripts);\n await checkMissingDependencies(parsedConfig, scripts);\n\n if (parsedConfig.before.length > 0) {\n plans.push({ script: null, visitors: await getRootNodeVisitors(parsedConfig.before) });\n }\n\n for (const script of scripts) {\n plans.push({ script, visitors: await getRootNodeVisitors(parsedConfig.scripts[script]) });\n }\n\n return plans;\n}\n\nfunction runPlans(plans: RunPlan[], rootNode: RootNode): void {\n for (const plan of plans) {\n const result = runPlan(plan, rootNode);\n if (!plan.script) {\n rootNode = result;\n }\n }\n}\n\nfunction runPlan(plan: RunPlan, rootNode: RootNode): RootNode {\n const visitorLength = plan.visitors.length;\n const visitorPluralized = visitorLength === 1 ? 'visitor' : 'visitors';\n const identifier = plan.script\n ? `script \"${plan.script}\" with ${visitorLength} ${visitorPluralized}`\n : `${visitorLength} before ${visitorPluralized}`;\n logInfo(`Running ${identifier}...`);\n const newRoot = plan.visitors.reduce(visit, rootNode);\n logSuccess(`Executed ${identifier}!`);\n return newRoot;\n}\n\nfunction checkMissingScripts(parsedConfig: Pick<ParsedConfig, 'configPath' | 'scripts'>, scripts: ScriptName[]) {\n const missingScripts = scripts.filter(script => !parsedConfig.scripts[script]);\n if (missingScripts.length === 0) return;\n\n const scriptPluralized = missingScripts.length === 1 ? 'Script' : 'Scripts';\n const message = parsedConfig.configPath\n ? `${scriptPluralized} not found in configuration file.`\n : `${scriptPluralized} not found because no configuration file was found.`;\n const items = [\n `${pico.bold(scriptPluralized)}: ${missingScripts.join(', ')}`,\n ...(parsedConfig.configPath ? [`${pico.bold('Path')}: ${parsedConfig.configPath}`] : []),\n ];\n throw new CliError(message, items);\n}\n\nasync function checkMissingDependencies(\n parsedConfig: Pick<ParsedConfig, 'before' | 'configPath' | 'scripts'>,\n scripts: ScriptName[],\n) {\n const dependencies = new Set<string>([\n ...parsedConfig.before.map(v => v.path),\n ...scripts.flatMap(script => parsedConfig.scripts[script]?.map(v => v.path) ?? []),\n ]);\n const externalDependencies = [...dependencies].filter(dep => !isLocalModulePath(dep));\n const scriptsRequirePluralized = scripts.length === 1 ? 'script requires' : 'scripts require';\n const installed = await installMissingDependencies(\n `Your ${scriptsRequirePluralized} additional dependencies.`,\n externalDependencies,\n );\n if (!installed) {\n throw new CliError('Cannot proceed without missing dependencies.');\n }\n}\n","import path from 'node:path';\n\nimport pico from 'picocolors';\n\nimport { ProgramOptions } from './programOptions';\nimport { canRead, CliError, importModuleItem, logWarning } from './utils';\n\nexport type Config = Readonly<{\n idl?: string;\n scripts?: ScriptsConfig;\n before?: readonly VisitorConfig[];\n}>;\n\nexport type ScriptName = string;\nexport type ScriptConfig = VisitorConfig | readonly VisitorConfig[];\nexport type ScriptsConfig = Readonly<Record<ScriptName, ScriptConfig>>;\n\nexport type VisitorPath = string;\nexport type VisitorConfig<T extends readonly unknown[] = readonly unknown[]> = VisitorConfigObject<T> | VisitorPath;\nexport type VisitorConfigObject<T extends readonly unknown[] = readonly unknown[]> = Readonly<{\n args?: T;\n from: VisitorPath;\n}>;\n\nexport async function getConfig(options: Pick<ProgramOptions, 'config'>): Promise<[Config, string | null]> {\n const configPath = options.config != null ? path.resolve(options.config) : await getDefaultConfigPath();\n\n if (!configPath) {\n logWarning('No configuration file found. Using empty configs. Make sure you provide the `--idl` option.');\n return [{}, configPath];\n }\n\n const configFile = await importModuleItem({ identifier: 'configuration file', from: configPath });\n if (!configFile || typeof configFile !== 'object') {\n throw new CliError(`Invalid configuration file.`, [`${pico.bold('Path')}: ${configPath}`]);\n }\n\n return [configFile, configPath];\n}\n\nasync function getDefaultConfigPath(): Promise<string | null> {\n const candidatePaths = ['codama.js', 'codama.mjs', 'codama.cjs', 'codama.json'];\n for (const candidatePath of candidatePaths) {\n const resolvedPath = path.resolve(process.cwd(), candidatePath);\n if (await canRead(resolvedPath)) {\n return resolvedPath;\n }\n }\n return null;\n}\n","import type { RootNode } from '@codama/nodes';\nimport { Command } from 'commander';\n\nimport { Config, getConfig, ScriptName, ScriptsConfig, VisitorConfig, VisitorPath } from './config';\nimport { ProgramOptions } from './programOptions';\nimport {\n CliError,\n getRootNodeFromIdl,\n importModuleItem,\n isLocalModulePath,\n resolveConfigPath,\n resolveRelativePath,\n} from './utils';\n\nexport type ParsedConfig = Readonly<{\n configPath: string | null;\n idlContent: unknown;\n idlPath: string;\n rootNode: RootNode;\n scripts: ParsedScriptsConfig;\n before: readonly ParsedVisitorConfig[];\n}>;\n\nexport type ParsedScriptsConfig = Readonly<Record<ScriptName, readonly ParsedVisitorConfig[]>>;\nexport type ParsedVisitorConfig<T extends readonly unknown[] = readonly unknown[]> = Readonly<{\n args: T;\n index: number;\n item: string | undefined;\n path: VisitorPath;\n script: ScriptName | null;\n}>;\n\nexport async function getParsedConfigFromCommand(cmd: Command): Promise<ParsedConfig> {\n return await getParsedConfig(cmd.optsWithGlobals());\n}\n\nexport async function getParsedConfig(options: Pick<ProgramOptions, 'config' | 'idl'>): Promise<ParsedConfig> {\n const [config, configPath] = await getConfig(options);\n return await parseConfig(config, configPath, options);\n}\n\nasync function parseConfig(\n config: Config,\n configPath: string | null,\n options: Pick<ProgramOptions, 'idl'>,\n): Promise<ParsedConfig> {\n const idlPath = parseIdlPath(config, configPath, options);\n const idlContent = await importModuleItem({ identifier: 'IDL', from: idlPath });\n const rootNode = await getRootNodeFromIdl(idlContent);\n const scripts = parseScripts(config.scripts ?? {}, configPath);\n const visitors = (config.before ?? []).map((v, i) => parseVisitorConfig(v, configPath, i, null));\n\n return { configPath, idlContent, idlPath, rootNode, scripts, before: visitors };\n}\n\nfunction parseIdlPath(\n config: Pick<Config, 'idl'>,\n configPath: string | null,\n options: Pick<ProgramOptions, 'idl'>,\n): string {\n if (options.idl) {\n return resolveRelativePath(options.idl);\n }\n if (config.idl) {\n return resolveConfigPath(config.idl, configPath);\n }\n throw new CliError('No IDL identified. Please provide the `--idl` option or set it in the configuration file.');\n}\n\nfunction parseScripts(scripts: ScriptsConfig, configPath: string | null): ParsedScriptsConfig {\n const entryPromises = Object.entries(scripts).map(([name, scriptConfig]) => {\n const visitors: readonly VisitorConfig[] = Array.isArray(scriptConfig) ? scriptConfig : [scriptConfig];\n return [name, visitors.map((v, i) => parseVisitorConfig(v, configPath, i, name))] as const;\n });\n return Object.fromEntries(entryPromises);\n}\n\nfunction parseVisitorConfig<T extends readonly unknown[]>(\n visitorConfig: VisitorConfig<T>,\n configPath: string | null,\n index: number,\n script: ScriptName | null,\n): ParsedVisitorConfig<T> {\n const emptyArgs = [] as readonly unknown[] as T;\n const visitorPath = typeof visitorConfig === 'string' ? visitorConfig : visitorConfig.from;\n const visitorArgs = typeof visitorConfig === 'string' ? emptyArgs : (visitorConfig.args ?? emptyArgs);\n const [path, item] = resolveVisitorPath(visitorPath, configPath);\n return { args: visitorArgs, index, item, path, script };\n}\n\nfunction resolveVisitorPath(visitorPath: string, configPath: string | null): readonly [string, string | undefined] {\n const [modulePath, itemName] = visitorPath.split('#') as [string, string | undefined];\n const resolveModulePath = isLocalModulePath(modulePath) ? resolveConfigPath(modulePath, configPath) : modulePath;\n return [resolveModulePath, itemName];\n}\n","import { Command } from 'commander';\n\nexport type ProgramOptions = Readonly<{\n config?: string;\n debug?: boolean;\n idl?: string;\n}>;\n\nexport function setProgramOptions(program: Command): void {\n program\n .option('--debug', 'include debugging information, such as stack dump')\n .option('-i, --idl <path>', 'The path to the IDL to use.')\n .option('-c, --config <path>', 'The path to the Codama configuration file. Defaults to `codama.(js|json)`.');\n}\n"],"mappings":"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