@secondlayer/cli 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +427 -174
- package/dist/cli.js.map +17 -1
- package/dist/index.d.ts +351 -8
- package/dist/index.js +2386 -73
- package/dist/index.js.map +22 -1
- package/dist/plugin-manager.d.ts +257 -0
- package/dist/{core/plugin-manager.js → plugin-manager.js} +35 -67
- package/dist/plugin-manager.js.map +10 -0
- package/package.json +9 -15
- package/LICENSE +0 -21
- package/README.md +0 -222
- package/dist/cli.cjs +0 -897
- package/dist/cli.cjs.map +0 -1
- package/dist/core/plugin-manager.cjs +0 -368
- package/dist/core/plugin-manager.cjs.map +0 -1
- package/dist/core/plugin-manager.d.cts +0 -1
- package/dist/core/plugin-manager.d.ts +0 -1
- package/dist/core/plugin-manager.js.map +0 -1
- package/dist/index.cjs +0 -380
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -8
- package/dist/plugin-manager-Cc1rHnQS.d.cts +0 -285
- package/dist/plugin-manager-Cc1rHnQS.d.ts +0 -285
- package/dist/plugins/index.cjs +0 -2622
- package/dist/plugins/index.cjs.map +0 -1
- package/dist/plugins/index.d.cts +0 -136
- package/dist/plugins/index.d.ts +0 -136
- package/dist/plugins/index.js +0 -2578
- package/dist/plugins/index.js.map +0 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/commands/init.ts","../src/cli.ts","../src/commands/generate.ts","../src/utils/config.ts","../src/core/plugin-manager.ts","../src/utils/api.ts","../src/parsers/clarity.ts","../src/generators/contract.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { promises as fs } from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\n\n/**\n * Init command - creates a default config file\n */\n\nexport async function init() {\n const spinner = ora(\"Initializing\").start();\n const configPath = path.join(process.cwd(), \"stacks.config.ts\");\n\n // Check if config already exists\n try {\n await fs.access(configPath);\n spinner.warn(\"stacks.config.ts already exists\");\n return;\n } catch {\n // File doesn't exist, continue\n }\n\n // Check for Clarinet project\n const hasClarinetProject = await fileExists(\"./Clarinet.toml\");\n\n let config: string;\n\n if (hasClarinetProject) {\n // Generate plugin-based config for Clarinet projects\n config = `import { defineConfig } from '@secondlayer/cli';\nimport { clarinet } from '@secondlayer/cli/plugins';\n\nexport default defineConfig({\n out: './src/generated/contracts.ts',\n plugins: [\n clarinet() // Found Clarinet.toml in current directory\n ]\n});`;\n } else {\n // Generate basic config for non-Clarinet projects\n config = `import { defineConfig } from '@secondlayer/cli';\n\nexport default defineConfig({\n out: './src/generated/contracts.ts',\n plugins: [],\n});`;\n }\n\n // Write config file\n await fs.writeFile(configPath, config);\n\n spinner.succeed(\"Created `stacks.config.ts`\");\n\n console.log(\n \"\\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!\"\n );\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","#!/usr/bin/env node\nimport { program } from \"commander\";\nimport { generate } from \"./commands/generate.js\";\n\n/**\n * CLI entry point\n */\n\nprogram\n .name(\"stacks\")\n .description(\"CLI tool for generating type-safe Stacks contract interfaces\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"generate\")\n .alias(\"gen\")\n .description(\"Generate TypeScript interfaces from Clarity contracts\")\n .option(\"-c, --config <path>\", \"Path to config file\")\n .option(\"-w, --watch\", \"Watch for changes\")\n .action(generate);\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new stacks.config.ts file\")\n .action(async () => {\n const { init } = await import(\"./commands/init.js\");\n await init();\n });\n\nprogram.parse();\n","import { promises as fs } from \"fs\";\nimport path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { StacksApiClient } from \"../utils/api.js\";\nimport { parseClarityFile, parseApiResponse } from \"../parsers/clarity.js\";\nimport { generateContractInterface } from \"../generators/contract.js\";\nimport { PluginManager } from \"../core/plugin-manager.js\";\nimport type {\n ResolvedContract,\n NetworkName,\n ContractSource,\n} from \"../types/config.js\";\nimport type {\n ResolvedConfig,\n ProcessedContract,\n ContractConfig,\n} from \"../types/plugin.js\";\n\n/**\n * Generate command implementation\n */\n\nexport interface GenerateOptions {\n config?: string;\n watch?: boolean;\n}\n\nexport async function generate(options: GenerateOptions) {\n const spinner = ora(\"Processing contracts\").start();\n\n try {\n const config = await loadConfig(options.config);\n\n // Get plugin manager from config loading\n const pluginManager = new PluginManager();\n\n // Register plugins from config\n if (config.plugins) {\n for (const plugin of config.plugins) {\n pluginManager.register(plugin);\n }\n }\n\n // Execute configResolved hooks\n await pluginManager.executeHook(\"configResolved\", config);\n\n // Convert existing contracts to ContractConfig format (if any)\n // Use the resolved config which includes contracts added by plugins\n const contractConfigs: ContractConfig[] = (config.contracts || []).map(\n (contract) => ({\n name: contract.name,\n address: contract.address,\n source: contract.source,\n abi: (contract as any).abi, // Include ABI if it exists (from plugins)\n _clarinetSource: (contract as any)._clarinetSource, // Include plugin flags\n })\n );\n\n // Transform contracts through plugins (plugins can add more contracts)\n const processedContracts = await pluginManager.transformContracts(\n contractConfigs,\n config\n );\n\n if (processedContracts.length === 0) {\n spinner.warn(\"No contracts found to generate\");\n console.log(\"\\nTo get started:\");\n console.log(\" • Add contracts to your config file, or\");\n console.log(\" • Use plugins like clarinet() for local contracts\");\n return;\n }\n\n // Execute generation through plugin system\n const outputs = await pluginManager.executeGeneration(\n processedContracts,\n config\n );\n\n // If no plugins generated the main contracts output, generate it using the existing generator\n if (!outputs.has(\"contracts\") && processedContracts.length > 0) {\n const contractsCode = await generateContractInterface(processedContracts);\n outputs.set(\"contracts\", {\n path: config.out,\n content: contractsCode,\n type: \"contracts\",\n });\n }\n\n // Transform outputs through plugins\n const transformedOutputs = await pluginManager.transformOutputs(outputs);\n\n // Write all outputs to disk\n await pluginManager.writeOutputs(transformedOutputs);\n\n const contractCount = processedContracts.length;\n const contractWord = contractCount === 1 ? \"contract\" : \"contracts\";\n spinner.succeed(`Generation complete for ${contractCount} ${contractWord}`);\n\n console.log(`\\n📄 ${config.out}`);\n console.log(`\\n💡 Import your contracts:`);\n\n // Show import examples based on actual contract names\n if (processedContracts.length > 0) {\n const exampleContract = processedContracts[0];\n console.log(\n chalk.gray(\n ` import { ${exampleContract.name} } from '${config.out.replace(/\\.ts$/, \"\")}'`\n )\n );\n\n if (processedContracts.length > 1) {\n console.log(\n chalk.gray(\n ` // Also available: ${processedContracts\n .slice(1)\n .map((c) => c.name)\n .join(\", \")}`\n )\n );\n }\n }\n } catch (error: any) {\n spinner.fail(\"Generation failed\");\n console.error(chalk.red(`\\n${error.message}`));\n if (process.env.DEBUG) {\n console.error(error.stack);\n }\n process.exit(1);\n }\n}\n\n// Keep existing contract resolution functions for backward compatibility and plugin use\nexport async function resolveContract(\n source: ContractSource,\n network: NetworkName,\n apiKey?: string,\n apiUrl?: string\n): Promise<ResolvedContract> {\n // Handle local source files\n if (source.source) {\n const filePath = path.resolve(process.cwd(), source.source);\n const abi = await parseClarityFile(filePath);\n\n const name =\n source.name ||\n path\n .basename(source.source, \".clar\")\n .replace(/-/g, \"_\")\n .replace(/^\\d/, \"_$&\");\n\n // For local files, we need to construct the address\n const address =\n typeof source.address === \"string\"\n ? source.address\n : source.address?.[network] ||\n \"ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM\";\n\n const [contractAddress, contractName] = address.includes(\".\")\n ? address.split(\".\")\n : [address, name];\n\n return {\n name,\n address: contractAddress,\n contractName: contractName || name,\n abi,\n source: \"local\",\n };\n }\n\n // Handle deployed contracts\n if (source.address) {\n const contractId =\n typeof source.address === \"string\"\n ? source.address\n : source.address[network];\n\n if (!contractId) {\n throw new Error(`No contract address for network ${network}`);\n }\n\n const contractInfo = await new StacksApiClient(\n network,\n apiKey,\n apiUrl\n ).getContractInfo(contractId);\n const abi = parseApiResponse(contractInfo);\n\n const [contractAddress, contractName] = contractId.split(\".\");\n const name =\n source.name || contractName.replace(/-/g, \"_\").replace(/^\\d/, \"_$&\");\n\n return {\n name,\n address: contractAddress,\n contractName,\n abi,\n source: \"api\",\n };\n }\n\n throw new Error(\"Contract must have either address or source\");\n}\n\nexport async function resolveContracts(\n source: ContractSource,\n defaultNetwork: NetworkName | undefined,\n apiKey?: string,\n apiUrl?: string\n): Promise<ResolvedContract[]> {\n // Handle single network contracts (existing behavior)\n if (typeof source.address === \"string\" || source.source) {\n const resolved = await resolveContract(\n source,\n defaultNetwork || \"testnet\", // Use testnet as fallback for single contracts\n apiKey,\n apiUrl\n );\n return [resolved];\n }\n\n // Handle multi-network contracts\n if (source.address && typeof source.address === \"object\") {\n const resolvedContracts: ResolvedContract[] = [];\n\n // If defaultNetwork is specified, only generate that network\n // If no network specified, generate all networks defined in the address object\n const networksToGenerate = defaultNetwork\n ? [defaultNetwork].filter(\n (net) => (source.address as Partial<Record<NetworkName, string>>)[net]\n ) // Only if address exists for that network\n : (Object.keys(source.address) as NetworkName[]);\n\n for (const network of networksToGenerate) {\n const contractId = source.address[network];\n if (!contractId) continue;\n\n try {\n const networkApiClient = new StacksApiClient(network, apiKey, apiUrl);\n\n const contractInfo = await networkApiClient.getContractInfo(contractId);\n const abi = parseApiResponse(contractInfo);\n\n const [contractAddress, contractName] = contractId.split(\".\");\n const baseName =\n source.name || contractName.replace(/-/g, \"_\").replace(/^\\d/, \"_$&\");\n\n // Generate network-specific names\n const name =\n network === \"mainnet\"\n ? baseName\n : `${network}${baseName.charAt(0).toUpperCase() + baseName.slice(1)}`;\n\n resolvedContracts.push({\n name,\n address: contractAddress,\n contractName,\n abi,\n source: \"api\",\n });\n } catch (error: any) {\n console.warn(\n `Warning: Failed to resolve contract for ${network}: ${error.message}`\n );\n }\n }\n\n return resolvedContracts;\n }\n\n throw new Error(\"Contract must have either address or source\");\n}\n","import { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { createRequire } from \"module\";\nimport { transformSync } from \"esbuild\";\nimport type { StacksConfig, ConfigDefiner } from \"../types/config.js\";\nimport type { ResolvedConfig } from \"../types/plugin.js\";\nimport { PluginManager } from \"../core/plugin-manager.js\";\n\n/**\n * Config file utilities\n */\n\nconst CONFIG_FILE_NAMES = [\n \"stacks.config.ts\",\n \"stacks.config.js\",\n \"stacks.config.mjs\",\n];\n\nexport async function findConfigFile(cwd: string): Promise<string | null> {\n for (const fileName of CONFIG_FILE_NAMES) {\n const filePath = path.join(cwd, fileName);\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, continue\n }\n }\n return null;\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const cwd = process.cwd();\n\n const resolvedPath = configPath\n ? path.resolve(cwd, configPath)\n : await findConfigFile(cwd);\n\n if (!resolvedPath) {\n throw new Error(\n \"No config file found. Create a stacks.config.ts file or specify a path with --config\"\n );\n }\n\n let config: any;\n\n if (resolvedPath.endsWith(\".ts\")) {\n const code = await fs.readFile(resolvedPath, \"utf-8\");\n\n // Transform TypeScript to JavaScript, replacing the @secondlayer/cli import\n // For development/linked packages, we need to resolve to the actual package location\n // This will work both for published packages and local development\n let replacementPath: string;\n\n try {\n // Try to resolve @secondlayer/cli as if it were a normal package\n const require = createRequire(import.meta.url);\n const packagePath = require.resolve(\"@secondlayer/cli\");\n replacementPath = pathToFileURL(packagePath).href;\n } catch {\n // Fallback: resolve relative to current module (for development)\n const currentModuleDir = path.dirname(new URL(import.meta.url).pathname);\n const indexPath = path.resolve(currentModuleDir, \"../index.js\");\n replacementPath = pathToFileURL(indexPath).href;\n }\n\n const transformedCode = code.replace(\n /from\\s+[\"']@stacks\\/cli[\"']/g,\n `from '${replacementPath}'`\n );\n\n const result = transformSync(transformedCode, {\n format: \"esm\",\n target: \"node18\",\n loader: \"ts\",\n });\n\n const tempPath = resolvedPath.replace(/\\.ts$/, \".mjs\");\n await fs.writeFile(tempPath, result.code);\n\n try {\n const fileUrl = pathToFileURL(tempPath).href;\n const module = await import(fileUrl);\n config = module.default;\n } finally {\n await fs.unlink(tempPath).catch(() => {});\n }\n } else {\n const fileUrl = pathToFileURL(resolvedPath).href;\n const module = await import(fileUrl);\n config = module.default;\n }\n\n if (!config) {\n throw new Error(\"Config file must export a default configuration\");\n }\n\n if (typeof config === \"function\") {\n config = config({} as StacksConfig);\n }\n\n validateConfig(config);\n\n // Process plugins if they exist\n const pluginManager = new PluginManager();\n\n if (config.plugins && Array.isArray(config.plugins)) {\n for (const plugin of config.plugins) {\n pluginManager.register(plugin);\n }\n }\n\n // Transform config through plugins\n const resolvedConfig = await pluginManager.transformConfig(config);\n\n return resolvedConfig;\n}\n\nexport function validateConfig(\n config: unknown\n): asserts config is StacksConfig {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"Config must be an object\");\n }\n\n const c = config as any;\n\n // Contracts are optional now since plugins can provide them\n if (c.contracts && !Array.isArray(c.contracts)) {\n throw new Error(\"Config contracts must be an array\");\n }\n\n if (!c.out || typeof c.out !== \"string\") {\n throw new Error(\"Config out must be a string path\");\n }\n\n // Validate contracts if they exist\n if (c.contracts) {\n for (const contract of c.contracts) {\n if (!contract.address && !contract.source) {\n throw new Error(\"Each contract must have either an address or source\");\n }\n }\n }\n\n // Validate plugins if they exist\n if (c.plugins && !Array.isArray(c.plugins)) {\n throw new Error(\"Config plugins must be an array\");\n }\n}\n\nexport function defineConfig(config: StacksConfig): StacksConfig;\nexport function defineConfig(definer: ConfigDefiner): ConfigDefiner;\nexport function defineConfig(configOrDefiner: StacksConfig | ConfigDefiner) {\n return configOrDefiner;\n}\n","/**\n * Plugin Manager for @secondlayer/cli\n * Handles plugin registration, lifecycle execution, and output management\n */\n\nimport { format } from \"prettier\";\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { validateStacksAddress } from \"@stacks/transactions\";\nimport type {\n StacksCodegenPlugin,\n UserConfig,\n ResolvedConfig,\n GenerateContext,\n Logger,\n PluginUtils,\n GeneratedOutput,\n ProcessedContract,\n ContractConfig,\n HookResult,\n PluginExecutionContext,\n} from \"../types/plugin.js\";\n\n/**\n * Core plugin manager that orchestrates plugin execution\n */\nexport class PluginManager {\n private plugins: StacksCodegenPlugin[] = [];\n private logger: Logger;\n private utils: PluginUtils;\n private executionContext: PluginExecutionContext;\n\n constructor() {\n this.logger = this.createLogger();\n this.utils = this.createUtils();\n this.executionContext = {\n phase: \"config\",\n startTime: Date.now(),\n results: new Map(),\n };\n }\n\n /**\n * Register a plugin\n */\n register(plugin: StacksCodegenPlugin): void {\n // Validate plugin\n if (!plugin.name || !plugin.version) {\n throw new Error(\"Plugin must have a name and version\");\n }\n\n // Check for duplicate plugin names\n const existing = this.plugins.find((p) => p.name === plugin.name);\n if (existing) {\n throw new Error(\n `Plugin \"${plugin.name}\" is already registered (version ${existing.version})`\n );\n }\n\n this.plugins.push(plugin);\n this.logger.debug(`Registered plugin: ${plugin.name}@${plugin.version}`);\n }\n\n /**\n * Get all registered plugins\n */\n getPlugins(): StacksCodegenPlugin[] {\n return [...this.plugins];\n }\n\n /**\n * Transform user config through all plugins\n */\n async transformConfig(config: UserConfig): Promise<ResolvedConfig> {\n this.executionContext.phase = \"config\";\n let transformedConfig = { ...config };\n\n for (const plugin of this.plugins) {\n if (plugin.transformConfig) {\n this.executionContext.currentPlugin = plugin;\n try {\n const result = await plugin.transformConfig(transformedConfig);\n transformedConfig = result;\n this.recordHookResult(plugin.name, \"transformConfig\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformConfig\", {\n success: false,\n error: err,\n });\n throw new Error(\n `Plugin \"${plugin.name}\" failed during config transformation: ${err.message}`\n );\n }\n }\n }\n\n // Add plugins array to resolved config\n const resolvedConfig: ResolvedConfig = {\n ...transformedConfig,\n plugins: this.plugins,\n };\n\n return resolvedConfig;\n }\n\n /**\n * Transform contracts through all plugins\n */\n async transformContracts(\n contracts: ContractConfig[],\n _config: ResolvedConfig\n ): Promise<ProcessedContract[]> {\n const processedContracts: ProcessedContract[] = [];\n\n for (let contract of contracts) {\n // Handle special case for Clarinet plugin contracts\n if ((contract as any)._clarinetSource && contract.abi) {\n // Convert Clarinet contracts directly to ProcessedContract format\n const address =\n typeof contract.address === \"string\" ? contract.address : \"\";\n const [contractAddress, contractName] = address.split(\".\");\n const processed: ProcessedContract = {\n name: contract.name || contractName,\n address: contractAddress,\n contractName: contractName,\n abi: contract.abi,\n source: \"local\" as const,\n metadata: { source: \"clarinet\" },\n };\n processedContracts.push(processed);\n continue;\n }\n\n // Transform through each plugin\n for (const plugin of this.plugins) {\n if (plugin.transformContract) {\n this.executionContext.currentPlugin = plugin;\n try {\n contract = await plugin.transformContract(contract);\n this.recordHookResult(plugin.name, \"transformContract\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformContract\", {\n success: false,\n error: err,\n });\n this.logger.warn(\n `Plugin \"${plugin.name}\" failed to transform contract: ${err.message}`\n );\n }\n }\n }\n\n // Convert to ProcessedContract\n if (contract.abi) {\n const processed: ProcessedContract = {\n name: contract.name || \"unknown\",\n address:\n typeof contract.address === \"string\"\n ? contract.address.split(\".\")[0]\n : \"unknown\",\n contractName: contract.name || \"unknown\",\n abi: contract.abi,\n source: \"api\" as const, // Use \"api\" as default for plugin-processed contracts\n metadata: contract.metadata,\n };\n processedContracts.push(processed);\n }\n }\n\n return processedContracts;\n }\n\n /**\n * Execute lifecycle hooks\n */\n async executeHook(\n hookName: keyof StacksCodegenPlugin,\n context: any\n ): Promise<void> {\n for (const plugin of this.plugins) {\n const hook = plugin[hookName];\n if (typeof hook === \"function\") {\n this.executionContext.currentPlugin = plugin;\n try {\n await (hook as any).call(plugin, context);\n this.recordHookResult(plugin.name, hookName as string, {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, hookName as string, {\n success: false,\n error: err,\n });\n this.logger.error(\n `Plugin \"${plugin.name}\" failed during ${hookName as string}: ${err.message}`\n );\n // Don't throw - allow other plugins to continue\n }\n }\n }\n }\n\n /**\n * Execute generation phase with full context\n */\n async executeGeneration(\n contracts: ProcessedContract[],\n config: ResolvedConfig\n ): Promise<Map<string, GeneratedOutput>> {\n this.executionContext.phase = \"generate\";\n const outputs = new Map<string, GeneratedOutput>();\n\n // Create generation context\n const context: GenerateContext = {\n config,\n logger: this.logger,\n utils: this.utils,\n contracts,\n outputs,\n augment: (outputKey: string, contractName: string, content: any) => {\n this.augmentOutput(outputs, outputKey, contractName, content);\n },\n addOutput: (key: string, output: GeneratedOutput) => {\n outputs.set(key, output);\n },\n };\n\n // Execute beforeGenerate hooks\n await this.executeHook(\"beforeGenerate\", context);\n\n // Execute generate hooks\n await this.executeHook(\"generate\", context);\n\n // Execute afterGenerate hooks\n await this.executeHook(\"afterGenerate\", context);\n\n return outputs;\n }\n\n /**\n * Transform outputs through plugins\n */\n async transformOutputs(\n outputs: Map<string, GeneratedOutput>\n ): Promise<Map<string, GeneratedOutput>> {\n this.executionContext.phase = \"output\";\n const transformedOutputs = new Map<string, GeneratedOutput>();\n\n for (const [key, output] of outputs) {\n let transformedContent = output.content;\n\n for (const plugin of this.plugins) {\n if (plugin.transformOutput) {\n this.executionContext.currentPlugin = plugin;\n try {\n transformedContent = await plugin.transformOutput(\n transformedContent,\n output.type || \"other\"\n );\n this.recordHookResult(plugin.name, \"transformOutput\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformOutput\", {\n success: false,\n error: err,\n });\n this.logger.warn(\n `Plugin \"${plugin.name}\" failed to transform output: ${err.message}`\n );\n }\n }\n }\n\n transformedOutputs.set(key, {\n ...output,\n content: transformedContent,\n });\n }\n\n return transformedOutputs;\n }\n\n /**\n * Write outputs to disk\n */\n async writeOutputs(outputs: Map<string, GeneratedOutput>): Promise<void> {\n for (const [, output] of outputs) {\n try {\n const resolvedPath = path.resolve(process.cwd(), output.path);\n await this.utils.ensureDir(path.dirname(resolvedPath));\n await this.utils.writeFile(resolvedPath, output.content);\n // Don't log here - let the main command handle success messaging\n } catch (error) {\n const err = error as Error;\n this.logger.error(`Failed to write ${output.path}: ${err.message}`);\n throw err;\n }\n }\n }\n\n /**\n * Get execution results for debugging\n */\n getExecutionResults(): Map<string, HookResult[]> {\n return new Map(this.executionContext.results);\n }\n\n /**\n * Augment existing output with additional content\n */\n private augmentOutput(\n outputs: Map<string, GeneratedOutput>,\n outputKey: string,\n contractName: string,\n content: any\n ): void {\n const existing = outputs.get(outputKey);\n if (!existing) {\n this.logger.warn(`Cannot augment non-existent output: ${outputKey}`);\n return;\n }\n\n // Simple augmentation - append content\n // In a real implementation, this would be more sophisticated\n const augmentedContent = `${existing.content}\\n\\n// Augmented by plugin for ${contractName}\\n${JSON.stringify(content, null, 2)}`;\n\n outputs.set(outputKey, {\n ...existing,\n content: augmentedContent,\n });\n }\n\n /**\n * Record hook execution result\n */\n private recordHookResult(\n pluginName: string,\n hookName: string,\n result: Omit<HookResult, \"plugin\">\n ): void {\n const key = `${pluginName}:${hookName}`;\n const existing = this.executionContext.results.get(key) || [];\n existing.push({ ...result, plugin: pluginName });\n this.executionContext.results.set(key, existing);\n }\n\n /**\n * Create logger instance\n */\n private createLogger(): Logger {\n return {\n info: (message: string) => console.log(`ℹ️ ${message}`),\n warn: (message: string) => console.warn(`⚠️ ${message}`),\n error: (message: string) => console.error(`❌ ${message}`),\n debug: (message: string) => {\n if (process.env.DEBUG) {\n console.log(`🐛 ${message}`);\n }\n },\n success: (message: string) => console.log(`✅ ${message}`),\n };\n }\n\n /**\n * Create utils instance\n */\n private createUtils(): PluginUtils {\n return {\n toCamelCase: (str: string) => {\n return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n },\n\n toKebabCase: (str: string) => {\n return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n },\n\n validateAddress: (address: string) => {\n return validateStacksAddress(address.split(\".\")[0]);\n },\n\n parseContractId: (contractId: string) => {\n const [address, contractName] = contractId.split(\".\");\n return { address, contractName };\n },\n\n formatCode: async (code: string) => {\n return format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: true,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n },\n\n resolvePath: (relativePath: string) => {\n return path.resolve(process.cwd(), relativePath);\n },\n\n fileExists: async (filePath: string) => {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n },\n\n readFile: async (filePath: string) => {\n return fs.readFile(filePath, \"utf-8\");\n },\n\n writeFile: async (filePath: string, content: string) => {\n await fs.writeFile(filePath, content, \"utf-8\");\n },\n\n ensureDir: async (dirPath: string) => {\n await fs.mkdir(dirPath, { recursive: true });\n },\n };\n }\n}\n","import got from \"got\";\nimport type { NetworkName } from \"../types/config.js\";\n\n/**\n * Stacks API client for fetching contract information\n */\n\nconst API_URLS: Record<NetworkName, string> = {\n mainnet: \"https://api.hiro.so\",\n testnet: \"https://api.testnet.hiro.so\",\n devnet: \"http://localhost:3999\",\n};\n\nexport interface ContractInfo {\n functions: any[];\n variables?: any[];\n maps?: any[];\n fungible_tokens?: any[];\n non_fungible_tokens?: any[];\n epoch?: string;\n clarity_version?: string;\n}\n\nexport class StacksApiClient {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(\n network: NetworkName = \"mainnet\",\n apiKey?: string,\n apiUrl?: string\n ) {\n this.baseUrl = apiUrl || API_URLS[network];\n this.headers = apiKey ? { \"x-api-key\": apiKey } : {};\n }\n\n async getContractInfo(contractId: string): Promise<ContractInfo> {\n const [address, contractName] = contractId.split(\".\");\n\n if (!address || !contractName) {\n throw new Error(\n `Invalid contract ID format: ${contractId}. Expected format: ADDRESS.CONTRACT_NAME`\n );\n }\n\n const url = `${this.baseUrl}/v2/contracts/interface/${address}/${contractName}`;\n\n try {\n const response = await got(url, {\n headers: this.headers,\n responseType: \"json\",\n });\n\n return response.body as ContractInfo;\n } catch (error: any) {\n if (error.response?.statusCode === 404) {\n throw new Error(`Contract not found: ${contractId}`);\n }\n if (error.response?.statusCode === 429) {\n throw new Error(\n \"Rate limited. Please provide an API key in your config.\"\n );\n }\n throw new Error(`Failed to fetch contract: ${error.message}`);\n }\n }\n\n async getContractSource(contractId: string): Promise<string> {\n const [address, contractName] = contractId.split(\".\");\n\n if (!address || !contractName) {\n throw new Error(\n `Invalid contract ID format: ${contractId}. Expected format: ADDRESS.CONTRACT_NAME`\n );\n }\n\n const url = `${this.baseUrl}/v2/contracts/source/${address}/${contractName}`;\n\n try {\n const response = await got(url, {\n headers: this.headers,\n responseType: \"json\",\n });\n\n const data = response.body as { source: string };\n return data.source;\n } catch (error: any) {\n return \"\";\n }\n }\n}\n","import { promises as fs } from \"fs\";\nimport type {\n ClarityContract,\n ClarityFunction,\n ClarityType,\n} from \"@secondlayer/clarity-types\";\n\n/**\n * Basic Clarity contract parser\n * This is a simplified parser - a full implementation would be more robust\n */\n\nexport async function parseClarityFile(\n filePath: string\n): Promise<ClarityContract> {\n const content = await fs.readFile(filePath, \"utf-8\");\n return parseClarityContent(content);\n}\n\nexport function parseClarityContent(content: string): ClarityContract {\n const functions: ClarityFunction[] = [];\n\n const functionRegex =\n /\\(define-(public|read-only|private)\\s+\\(([^)]+)\\)([\\s\\S]*?)\\)\\s*$/gm;\n\n let match;\n while ((match = functionRegex.exec(content)) !== null) {\n const [, access, signature, body] = match;\n const func = parseFunctionSignature(signature, access as any, body);\n if (func) {\n functions.push(func);\n }\n }\n\n return { functions };\n}\n\nfunction parseFunctionSignature(\n signature: string,\n access: \"public\" | \"read-only\" | \"private\",\n body: string\n): ClarityFunction | null {\n // Parse function name and arguments\n const parts = signature.trim().split(/\\s+/);\n const name = parts[0];\n\n const args: Array<{ name: string; type: ClarityType }> = [];\n\n // Parse arguments (simplified)\n for (let i = 1; i < parts.length; i += 2) {\n if (parts[i] && parts[i + 1]) {\n const argName = parts[i].replace(/[()]/g, \"\");\n const argType = parseType(parts[i + 1]);\n if (argType) {\n args.push({ name: argName, type: argType });\n }\n }\n }\n\n // Infer return type from body (simplified)\n const outputs = inferReturnType(body);\n\n return {\n name,\n access,\n args,\n outputs,\n };\n}\n\nfunction parseType(typeStr: string): ClarityType | null {\n typeStr = typeStr.replace(/[()]/g, \"\").trim();\n\n // Basic type mappings\n switch (typeStr) {\n case \"uint\":\n case \"uint128\":\n return \"uint128\";\n case \"int\":\n case \"int128\":\n return \"int128\";\n case \"bool\":\n return \"bool\";\n case \"principal\":\n return \"principal\";\n case \"trait_reference\":\n return \"principal\";\n default:\n // Handle complex types (simplified)\n if (typeStr.startsWith(\"string-ascii\")) {\n return { \"string-ascii\": { length: 256 } };\n }\n if (typeStr.startsWith(\"string-utf8\")) {\n return { \"string-utf8\": { length: 256 } };\n }\n if (typeStr.startsWith(\"buff\")) {\n return { buff: { length: 32 } };\n }\n // Default to uint128 for unknown types\n return \"uint128\";\n }\n}\n\nfunction inferReturnType(body: string): ClarityType {\n // Simplified return type inference\n if (body.includes(\"(ok\")) {\n if (body.includes(\"(err\")) {\n return {\n response: {\n ok: \"bool\",\n error: \"uint128\",\n },\n };\n }\n }\n\n if (body.includes(\"true\") || body.includes(\"false\")) {\n return \"bool\";\n }\n\n return \"bool\";\n}\n\n/**\n * Parse ABI from API response\n */\nexport function parseApiResponse(apiResponse: any): ClarityContract {\n try {\n const functions: ClarityFunction[] = [];\n\n if (apiResponse.functions) {\n for (const func of apiResponse.functions) {\n const access = func.access === \"read_only\" ? \"read-only\" : func.access;\n\n functions.push({\n name: func.name,\n access: access,\n args: func.args.map((arg: any) => ({\n name: arg.name,\n type: convertApiType(arg.type),\n })),\n outputs: convertApiType(func.outputs.type),\n });\n }\n }\n\n return { functions };\n } catch (error) {\n throw new Error(`Failed to parse API response: ${error}`);\n }\n}\n\nfunction convertApiType(apiType: any): ClarityType {\n if (typeof apiType === \"string\") {\n if (apiType === \"trait_reference\") {\n return \"trait_reference\";\n }\n return parseType(apiType) || \"uint128\";\n }\n\n // Handle complex types from API\n if (apiType.response) {\n return {\n response: {\n ok: convertApiType(apiType.response.ok),\n error: convertApiType(apiType.response.error),\n },\n };\n }\n\n if (apiType.optional) {\n return {\n optional: convertApiType(apiType.optional),\n };\n }\n\n if (apiType.list) {\n return {\n list: {\n type: convertApiType(apiType.list.type),\n length: apiType.list.length || 100,\n },\n };\n }\n\n if (apiType.tuple) {\n return {\n tuple: apiType.tuple.map((field: any) => ({\n name: field.name,\n type: convertApiType(field.type),\n })),\n };\n }\n\n if (apiType.buffer) {\n return {\n buff: {\n length: apiType.buffer.length || 32,\n },\n };\n }\n\n if (apiType[\"string-ascii\"]) {\n return {\n \"string-ascii\": {\n length: apiType[\"string-ascii\"].length || 256,\n },\n };\n }\n\n if (apiType[\"string-utf8\"]) {\n return {\n \"string-utf8\": {\n length: apiType[\"string-utf8\"].length || 256,\n },\n };\n }\n\n // Handle none type\n if (apiType === \"none\") {\n return \"uint128\"; // TODO: We'll need to handle this better in the future\n }\n\n // Default\n return \"uint128\";\n}\n","import { format } from \"prettier\";\nimport type { ResolvedContract } from \"../types/config.js\";\nimport type { ClarityFunction } from \"@secondlayer/clarity-types\";\n\n/**\n * Code generator for contract interfaces\n */\n\nexport async function generateContractInterface(\n contracts: ResolvedContract[]\n): Promise<string> {\n const imports = `import { Cl, validateStacksAddress } from '@stacks/transactions'`;\n\n const header = `/**\n * Generated by @secondlayer/cli\n * DO NOT EDIT MANUALLY\n */`;\n\n const contractsCode = contracts\n .map((contract) => generateContract(contract))\n .join(\"\\n\\n\");\n\n const code = `${imports}\\n\\n${header}\\n\\n${contractsCode}`;\n\n const formatted = await format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: true,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n\n return formatted;\n}\n\nfunction generateContract(contract: ResolvedContract): string {\n const { name, address, contractName, abi } = contract;\n\n const abiCode = generateAbiConstant(name, abi);\n\n const methods = abi.functions\n .filter((func: ClarityFunction) => func.access !== \"private\")\n .map((func: ClarityFunction) => generateMethod(func, address, contractName))\n .join(\",\\n\\n \");\n\n const contractCode = `export const ${name} = {\n address: '${address}',\n contractAddress: '${address}',\n contractName: '${contractName}',\n \n ${methods}\n} as const`;\n\n return `${abiCode}\\n\\n${contractCode}`;\n}\n\nfunction generateAbiConstant(name: string, abi: any): string {\n const abiJson = JSON.stringify(abi, null, 2)\n .replace(/\"([a-zA-Z_$][a-zA-Z0-9_$]*)\":/g, \"$1:\") // Only remove quotes from valid JS identifiers\n .replace(/\"/g, \"'\"); // Use single quotes\n\n return `export const ${name}Abi = ${abiJson} as const`;\n}\n\nfunction generateMethod(\n func: ClarityFunction,\n address: string,\n contractName: string\n): string {\n const methodName = toCamelCase(func.name);\n\n if (func.args.length === 0) {\n return `${methodName}() {\n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: []\n }\n }`;\n }\n\n if (func.args.length === 1) {\n const originalArgName = func.args[0].name;\n const argName = toCamelCase(originalArgName);\n const argType = getTypeForArg(func.args[0]);\n const clarityConversion = generateClarityConversion(argName, func.args[0]);\n\n return `${methodName}(...args: [{ ${argName}: ${argType} }] | [${argType}]) {\n const ${argName} = args.length === 1 && typeof args[0] === 'object' && args[0] !== null && '${argName}' in args[0]\n ? args[0].${argName}\n : args[0] as ${argType}\n \n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: [${clarityConversion}]\n }\n }`;\n }\n\n const argsList = func.args.map((arg) => toCamelCase(arg.name)).join(\", \");\n const argsTypes = func.args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `${camelName}: ${getTypeForArg(arg)}`;\n })\n .join(\"; \");\n const argsArray = func.args\n .map((arg) => {\n const argName = toCamelCase(arg.name);\n return generateClarityConversion(argName, arg);\n })\n .join(\", \");\n const objectAccess = func.args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `args[0].${camelName}`;\n })\n .join(\", \");\n const positionTypes = func.args.map((arg) => getTypeForArg(arg)).join(\", \");\n\n return `${methodName}(...args: [{ ${argsTypes} }] | [${positionTypes}]) {\n const [${argsList}] = args.length === 1 && typeof args[0] === 'object' && args[0] !== null\n ? [${objectAccess}]\n : args as [${positionTypes}]\n \n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: [${argsArray}]\n }\n }`;\n}\n\nfunction getTypeForArg(arg: any): string {\n const type = arg.type;\n\n if (typeof type === \"string\") {\n switch (type) {\n case \"uint128\":\n case \"int128\":\n return \"bigint\";\n case \"bool\":\n return \"boolean\";\n case \"principal\":\n case \"trait_reference\":\n return \"string\";\n default:\n return \"any\";\n }\n }\n\n if (type[\"string-ascii\"] || type[\"string-utf8\"]) {\n return \"string\";\n }\n\n if (type.buff) {\n // Support flexible buffer input types\n return \"Uint8Array | string | { type: 'ascii' | 'utf8' | 'hex'; value: string }\";\n }\n\n if (type.optional) {\n const innerType = getTypeForArg({ type: type.optional });\n return `${innerType} | null`;\n }\n\n if (type.list) {\n const innerType = getTypeForArg({ type: type.list.type });\n return `${innerType}[]`;\n }\n\n if (type.tuple) {\n const fields = type.tuple\n .map(\n (field: any) =>\n `${toCamelCase(field.name)}: ${getTypeForArg({ type: field.type })}`\n )\n .join(\"; \");\n return `{ ${fields} }`;\n }\n\n if (type.response) {\n const okType = getTypeForArg({ type: type.response.ok });\n const errType = getTypeForArg({ type: type.response.error });\n return `{ ok: ${okType} } | { err: ${errType} }`;\n }\n\n return \"any\";\n}\n\nfunction toCamelCase(str: string): string {\n return str\n .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) // Convert -a to A\n .replace(/-([A-Z])/g, (_, letter) => letter) // Convert -A to A\n .replace(/-(\\d)/g, (_, digit) => digit) // Convert -1 to 1\n .replace(/-/g, \"\"); // Remove any remaining hyphens\n}\n\n/**\n * Convert TypeScript value to ClarityValue based on the argument type\n */\nfunction generateClarityConversion(argName: string, argType: any): string {\n const type = argType.type;\n\n if (typeof type === \"string\") {\n switch (type) {\n case \"uint128\":\n return `Cl.uint(${argName})`;\n case \"int128\":\n return `Cl.int(${argName})`;\n case \"bool\":\n return `Cl.bool(${argName})`;\n case \"principal\":\n case \"trait_reference\":\n return `(() => {\n const [address, contractName] = ${argName}.split(\".\") as [string, string];\n if (!validateStacksAddress(address)) {\n throw new Error(\"Invalid Stacks address format\");\n }\n if (${argName}.includes(\".\")) {\n return Cl.contractPrincipal(address, contractName);\n } else {\n return Cl.standardPrincipal(${argName});\n }\n })()`;\n default:\n return `${argName}`; // fallback for unknown types\n }\n }\n\n if (type[\"string-ascii\"]) {\n return `Cl.stringAscii(${argName})`;\n }\n\n if (type[\"string-utf8\"]) {\n return `Cl.stringUtf8(${argName})`;\n }\n\n if (type.buff) {\n // Generate flexible buffer conversion code that matches the hooks implementation\n return `(() => {\n const value = ${argName};\n // Direct Uint8Array\n if (value instanceof Uint8Array) {\n return Cl.buffer(value);\n }\n // Object notation with explicit type\n if (typeof value === 'object' && value !== null && value.type && value.value) {\n switch (value.type) {\n case 'ascii':\n return Cl.bufferFromAscii(value.value);\n case 'utf8':\n return Cl.bufferFromUtf8(value.value);\n case 'hex':\n return Cl.bufferFromHex(value.value);\n default:\n throw new Error(\\`Unsupported buffer type: \\${value.type}\\`);\n }\n }\n // Auto-detect string type\n if (typeof value === 'string') {\n // Check for hex (0x prefix or pure hex pattern)\n if (value.startsWith('0x') || /^[0-9a-fA-F]+$/.test(value)) {\n return Cl.bufferFromHex(value);\n }\n // Check for non-ASCII characters (UTF-8)\n if (!/^[\\\\x00-\\\\x7F]*$/.test(value)) {\n return Cl.bufferFromUtf8(value);\n }\n // Default to ASCII for simple ASCII strings\n return Cl.bufferFromAscii(value);\n }\n throw new Error(\\`Invalid buffer value: \\${value}\\`);\n })()`;\n }\n\n if (type.optional) {\n const innerConversion = generateClarityConversion(argName, {\n type: type.optional,\n });\n return `${argName} !== null ? Cl.some(${innerConversion.replace(argName, `${argName}`)}) : Cl.none()`;\n }\n\n if (type.list) {\n const innerConversion = generateClarityConversion(\"item\", {\n type: type.list.type,\n });\n return `Cl.list(${argName}.map(item => ${innerConversion}))`;\n }\n\n if (type.tuple) {\n const fields = type.tuple\n .map((field: any) => {\n const camelFieldName = toCamelCase(field.name);\n const fieldConversion = generateClarityConversion(\n `${argName}.${camelFieldName}`,\n { type: field.type }\n );\n return `\"${field.name}\": ${fieldConversion}`;\n })\n .join(\", \");\n return `Cl.tuple({ ${fields} })`;\n }\n\n if (type.response) {\n // For response types, we expect the user to pass { ok: value } or { err: value }\n const okConversion = generateClarityConversion(`${argName}.ok`, {\n type: type.response.ok,\n });\n const errConversion = generateClarityConversion(`${argName}.err`, {\n type: type.response.error,\n });\n return `'ok' in ${argName} ? Cl.ok(${okConversion.replace(`${argName}.ok`, `${argName}.ok`)}) : Cl.error(${errConversion.replace(`${argName}.err`, `${argName}.err`)})`;\n }\n\n // Default fallback\n return `${argName}`;\n}\n"],"mappings":"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","names":["fs","path","ora","fs","path","path","path","fs","require","format","init"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/init.ts", "../src/cli.ts", "../src/commands/generate.ts", "../src/utils/config.ts", "../src/core/plugin-manager.ts", "../src/utils/api.ts", "../src/parsers/clarity.ts", "../src/generators/contract.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { promises as fs } from \"fs\";\nimport path from \"path\";\nimport ora from \"ora\";\n\n/**\n * Init command - creates a default config file\n */\n\nexport async function init() {\n const spinner = ora(\"Initializing\").start();\n const configPath = path.join(process.cwd(), \"stacks.config.ts\");\n\n // Check if config already exists\n try {\n await fs.access(configPath);\n spinner.warn(\"stacks.config.ts already exists\");\n return;\n } catch {\n // File doesn't exist, continue\n }\n\n // Check for Clarinet project\n const hasClarinetProject = await fileExists(\"./Clarinet.toml\");\n\n let config: string;\n\n if (hasClarinetProject) {\n // Generate plugin-based config for Clarinet projects\n config = `import { defineConfig } from '@secondlayer/cli';\nimport { clarinet } from '@secondlayer/cli/plugins';\n\nexport default defineConfig({\n out: './src/generated/contracts.ts',\n plugins: [\n clarinet() // Found Clarinet.toml in current directory\n ]\n});`;\n } else {\n // Generate basic config for non-Clarinet projects\n config = `import { defineConfig } from '@secondlayer/cli';\n\nexport default defineConfig({\n out: './src/generated/contracts.ts',\n plugins: [],\n});`;\n }\n\n // Write config file\n await fs.writeFile(configPath, config);\n\n spinner.succeed(\"Created `stacks.config.ts`\");\n\n console.log(\n \"\\nRun `secondlayer generate` to generate type-safe interfaces, functions, and hooks!\"\n );\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n",
|
|
6
|
+
"#!/usr/bin/env node\nimport { program } from \"commander\";\nimport { generate } from \"./commands/generate\";\n\n/**\n * CLI entry point\n */\n\nprogram\n .name(\"stacks\")\n .description(\"CLI tool for generating type-safe Stacks contract interfaces\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"generate [files...]\")\n .alias(\"gen\")\n .description(\"Generate TypeScript interfaces from Clarity contracts\")\n .option(\"-c, --config <path>\", \"Path to config file\")\n .option(\"-o, --out <path>\", \"Output file path (required when using direct files)\")\n .option(\"-k, --api-key <key>\", \"Hiro API key (or set HIRO_API_KEY env var)\")\n .option(\"-w, --watch\", \"Watch for changes\")\n .action(generate);\n\nprogram\n .command(\"init\")\n .description(\"Initialize a new stacks.config.ts file\")\n .action(async () => {\n const { init } = await import(\"./commands/init\");\n await init();\n });\n\nprogram.parse();\n",
|
|
7
|
+
"import path from \"path\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { Glob } from \"bun\";\nimport { loadConfig } from \"../utils/config\";\nimport { StacksApiClient } from \"../utils/api\";\nimport { parseClarityFile, parseApiResponse } from \"../parsers/clarity\";\nimport { generateContractInterface } from \"../generators/contract\";\nimport { PluginManager } from \"../core/plugin-manager\";\nimport type {\n ResolvedContract,\n NetworkName,\n ContractSource,\n StacksConfig,\n} from \"../types/config\";\nimport type { ContractConfig, ResolvedConfig } from \"../types/plugin\";\n\n/**\n * Generate command implementation\n */\n\nexport interface GenerateOptions {\n config?: string;\n out?: string;\n apiKey?: string;\n watch?: boolean;\n}\n\n/**\n * Check if a string looks like a deployed contract address (ADDRESS.contract-name)\n */\nfunction isContractAddress(input: string): boolean {\n // Contract addresses are in format: SP/ST/SM/SN...ADDRESS.contract-name\n // SP = mainnet standard, ST = testnet standard\n // SM = mainnet multisig, SN = testnet multisig\n const contractIdPattern = /^(SP|ST|SM|SN)[A-Z0-9]{38,}\\.[a-zA-Z][a-zA-Z0-9-]*$/;\n return contractIdPattern.test(input);\n}\n\n/**\n * Infer network from contract address prefix\n */\nfunction inferNetwork(address: string): NetworkName {\n // SP = mainnet standard, SM = mainnet multisig\n if (address.startsWith(\"SP\") || address.startsWith(\"SM\")) {\n return \"mainnet\";\n }\n // ST = testnet standard, SN = testnet multisig\n return \"testnet\";\n}\n\n/**\n * Parse inputs and separate into local files and deployed contract addresses\n */\ninterface ParsedInputs {\n files: string[];\n contractIds: string[];\n}\n\nasync function parseInputs(inputs: string[]): Promise<ParsedInputs> {\n const files: string[] = [];\n const contractIds: string[] = [];\n\n for (const input of inputs) {\n // Check if it's a deployed contract address\n if (isContractAddress(input)) {\n contractIds.push(input);\n continue;\n }\n\n // Check if it's a glob pattern\n if (input.includes(\"*\") || input.includes(\"?\")) {\n const glob = new Glob(input);\n for await (const file of glob.scan({ cwd: process.cwd(), absolute: true })) {\n if (file.endsWith(\".clar\")) {\n files.push(file);\n }\n }\n continue;\n }\n\n // Direct file path\n if (input.endsWith(\".clar\")) {\n const absolutePath = path.resolve(process.cwd(), input);\n files.push(absolutePath);\n }\n }\n\n return {\n files: [...new Set(files)],\n contractIds: [...new Set(contractIds)],\n };\n}\n\n/**\n * Convert filename to camelCase contract name\n */\nfunction deriveContractName(filePath: string): string {\n const basename = path.basename(filePath, \".clar\");\n // Convert kebab-case or snake_case to camelCase\n return basename\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (_, char) => char.toLowerCase())\n .replace(/^\\d/, \"_$&\"); // Prefix with underscore if starts with digit\n}\n\n/**\n * Convert contract name from kebab-case to camelCase\n */\nfunction toCamelCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (_, char) => char.toLowerCase())\n .replace(/^\\d/, \"_$&\");\n}\n\n/**\n * Build config from direct inputs (local files and/or deployed contract addresses)\n */\nasync function buildConfigFromInputs(\n parsedInputs: ParsedInputs,\n outPath: string,\n apiKey: string | undefined,\n spinner: ReturnType<typeof ora>\n): Promise<StacksConfig> {\n const contracts = [];\n\n // Process local .clar files\n for (const file of parsedInputs.files) {\n const abi = await parseClarityFile(file);\n const name = deriveContractName(file);\n\n contracts.push({\n name,\n address: `ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.${name}`,\n abi,\n _directFile: true,\n });\n }\n\n // Process deployed contract addresses (fetch from API)\n for (const contractId of parsedInputs.contractIds) {\n const [address, contractName] = contractId.split(\".\");\n const network = inferNetwork(address);\n\n spinner.text = `Fetching ${contractName} from ${network}...`;\n\n try {\n const apiClient = new StacksApiClient(network, apiKey);\n const contractInfo = await apiClient.getContractInfo(contractId);\n const abi = parseApiResponse(contractInfo);\n const name = toCamelCase(contractName);\n\n contracts.push({\n name,\n address: contractId,\n abi,\n _directFile: true,\n });\n } catch (error: any) {\n throw new Error(`Failed to fetch contract ${contractId}: ${error.message}`);\n }\n }\n\n return {\n out: outPath,\n contracts,\n plugins: [],\n };\n}\n\nexport async function generate(files: string[], options: GenerateOptions) {\n const spinner = ora(\"Processing contracts\").start();\n\n try {\n let config: StacksConfig;\n\n // Check if direct inputs were provided (files or contract addresses)\n if (files && files.length > 0) {\n // Require -o/--out when using direct inputs\n if (!options.out) {\n spinner.fail(\"Output path required\");\n console.error(\n chalk.red(\"\\nWhen using direct inputs, you must specify an output path with -o/--out\")\n );\n console.log(chalk.gray(\"\\nExamples:\"));\n console.log(chalk.gray(\" secondlayer generate ./contracts/*.clar -o ./src/generated.ts\"));\n console.log(chalk.gray(\" secondlayer generate SP2C2YFP12AJZB1M6DY7SF9A3PRHWKGYGVWQKW3.my-token -o ./src/generated.ts\"));\n process.exit(1);\n }\n\n // Parse inputs to separate files from contract addresses\n const parsedInputs = await parseInputs(files);\n const totalInputs = parsedInputs.files.length + parsedInputs.contractIds.length;\n\n if (totalInputs === 0) {\n spinner.fail(\"No valid inputs found\");\n console.error(chalk.red(\"\\nNo .clar files or contract addresses matched the provided inputs\"));\n process.exit(1);\n }\n\n spinner.text = `Processing ${totalInputs} contract(s)...`;\n\n // Get API key from option or environment variable\n const apiKey = options.apiKey || process.env.HIRO_API_KEY;\n\n config = await buildConfigFromInputs(parsedInputs, options.out, apiKey, spinner);\n } else {\n // Use config file (existing behavior)\n config = await loadConfig(options.config);\n }\n\n // Get plugin manager from config loading\n const pluginManager = new PluginManager();\n\n // Register plugins from config\n if (config.plugins) {\n for (const plugin of config.plugins) {\n pluginManager.register(plugin);\n }\n }\n\n // Create resolved config with typed plugins\n const resolvedConfig: ResolvedConfig = {\n ...config,\n plugins: pluginManager.getPlugins(),\n };\n\n // Execute configResolved hooks\n await pluginManager.executeHook(\"configResolved\", resolvedConfig);\n\n // Convert existing contracts to ContractConfig format (if any)\n // Use the resolved config which includes contracts added by plugins\n const contractConfigs: ContractConfig[] = (config.contracts || []).map(\n (contract) => ({\n name: contract.name,\n address: contract.address,\n source: contract.source,\n abi: (contract as any).abi, // Include ABI if it exists (from plugins)\n _clarinetSource: (contract as any)._clarinetSource, // Include plugin flags\n })\n );\n\n // Transform contracts through plugins (plugins can add more contracts)\n const processedContracts = await pluginManager.transformContracts(\n contractConfigs,\n resolvedConfig\n );\n\n if (processedContracts.length === 0) {\n spinner.warn(\"No contracts found to generate\");\n console.log(\"\\nTo get started:\");\n console.log(\" • Add contracts to your config file, or\");\n console.log(\" • Use plugins like clarinet() for local contracts\");\n return;\n }\n\n // Execute generation through plugin system\n const outputs = await pluginManager.executeGeneration(\n processedContracts,\n resolvedConfig\n );\n\n // If no plugins generated the main contracts output, generate it using the existing generator\n if (!outputs.has(\"contracts\") && processedContracts.length > 0) {\n const contractsCode = await generateContractInterface(processedContracts);\n outputs.set(\"contracts\", {\n path: config.out,\n content: contractsCode,\n type: \"contracts\",\n });\n }\n\n // Transform outputs through plugins\n const transformedOutputs = await pluginManager.transformOutputs(outputs);\n\n // Write all outputs to disk\n await pluginManager.writeOutputs(transformedOutputs);\n\n const contractCount = processedContracts.length;\n const contractWord = contractCount === 1 ? \"contract\" : \"contracts\";\n spinner.succeed(`Generation complete for ${contractCount} ${contractWord}`);\n\n console.log(`\\n📄 ${config.out}`);\n console.log(`\\n💡 Import your contracts:`);\n\n // Show import examples based on actual contract names\n if (processedContracts.length > 0) {\n const exampleContract = processedContracts[0];\n console.log(\n chalk.gray(\n ` import { ${exampleContract.name} } from '${config.out.replace(/\\.ts$/, \"\")}'`\n )\n );\n\n if (processedContracts.length > 1) {\n console.log(\n chalk.gray(\n ` // Also available: ${processedContracts\n .slice(1)\n .map((c) => c.name)\n .join(\", \")}`\n )\n );\n }\n }\n } catch (error: any) {\n spinner.fail(\"Generation failed\");\n console.error(chalk.red(`\\n${error.message}`));\n if (process.env.DEBUG) {\n console.error(error.stack);\n }\n process.exit(1);\n }\n}\n\n// Keep existing contract resolution functions for backward compatibility and plugin use\nexport async function resolveContract(\n source: ContractSource,\n network: NetworkName,\n apiKey?: string,\n apiUrl?: string\n): Promise<ResolvedContract> {\n // Handle local source files\n if (source.source) {\n const filePath = path.resolve(process.cwd(), source.source);\n const abi = await parseClarityFile(filePath);\n\n const name =\n source.name ||\n path\n .basename(source.source, \".clar\")\n .replace(/-/g, \"_\")\n .replace(/^\\d/, \"_$&\");\n\n // For local files, we need to construct the address\n const address =\n typeof source.address === \"string\"\n ? source.address\n : source.address?.[network] ||\n \"ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM\";\n\n const [contractAddress, contractName] = address.includes(\".\")\n ? address.split(\".\")\n : [address, name];\n\n return {\n name,\n address: contractAddress,\n contractName: contractName || name,\n abi,\n source: \"local\",\n };\n }\n\n // Handle deployed contracts\n if (source.address) {\n const contractId =\n typeof source.address === \"string\"\n ? source.address\n : source.address[network];\n\n if (!contractId) {\n throw new Error(`No contract address for network ${network}`);\n }\n\n const contractInfo = await new StacksApiClient(\n network,\n apiKey,\n apiUrl\n ).getContractInfo(contractId);\n const abi = parseApiResponse(contractInfo);\n\n const [contractAddress, contractName] = contractId.split(\".\");\n const name =\n source.name || contractName.replace(/-/g, \"_\").replace(/^\\d/, \"_$&\");\n\n return {\n name,\n address: contractAddress,\n contractName,\n abi,\n source: \"api\",\n };\n }\n\n throw new Error(\"Contract must have either address or source\");\n}\n\nexport async function resolveContracts(\n source: ContractSource,\n defaultNetwork: NetworkName | undefined,\n apiKey?: string,\n apiUrl?: string\n): Promise<ResolvedContract[]> {\n // Handle single network contracts (existing behavior)\n if (typeof source.address === \"string\" || source.source) {\n const resolved = await resolveContract(\n source,\n defaultNetwork || \"testnet\", // Use testnet as fallback for single contracts\n apiKey,\n apiUrl\n );\n return [resolved];\n }\n\n // Handle multi-network contracts\n if (source.address && typeof source.address === \"object\") {\n const resolvedContracts: ResolvedContract[] = [];\n\n // If defaultNetwork is specified, only generate that network\n // If no network specified, generate all networks defined in the address object\n const networksToGenerate = defaultNetwork\n ? [defaultNetwork].filter(\n (net) => (source.address as Partial<Record<NetworkName, string>>)[net]\n ) // Only if address exists for that network\n : (Object.keys(source.address) as NetworkName[]);\n\n for (const network of networksToGenerate) {\n const contractId = source.address[network];\n if (!contractId) continue;\n\n try {\n const networkApiClient = new StacksApiClient(network, apiKey, apiUrl);\n\n const contractInfo = await networkApiClient.getContractInfo(contractId);\n const abi = parseApiResponse(contractInfo);\n\n const [contractAddress, contractName] = contractId.split(\".\");\n const baseName =\n source.name || contractName.replace(/-/g, \"_\").replace(/^\\d/, \"_$&\");\n\n // Generate network-specific names\n const name =\n network === \"mainnet\"\n ? baseName\n : `${network}${baseName.charAt(0).toUpperCase() + baseName.slice(1)}`;\n\n resolvedContracts.push({\n name,\n address: contractAddress,\n contractName,\n abi,\n source: \"api\",\n });\n } catch (error: any) {\n console.warn(\n `Warning: Failed to resolve contract for ${network}: ${error.message}`\n );\n }\n }\n\n return resolvedContracts;\n }\n\n throw new Error(\"Contract must have either address or source\");\n}\n",
|
|
8
|
+
"import { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { pathToFileURL } from \"url\";\nimport { createRequire } from \"module\";\nimport { transformSync } from \"esbuild\";\nimport type { StacksConfig, ConfigDefiner } from \"../types/config\";\nimport type { ResolvedConfig } from \"../types/plugin\";\nimport { PluginManager } from \"../core/plugin-manager\";\n\n/**\n * Config file utilities\n */\n\nconst CONFIG_FILE_NAMES = [\n \"stacks.config.ts\",\n \"stacks.config\",\n \"stacks.config.mjs\",\n];\n\nexport async function findConfigFile(cwd: string): Promise<string | null> {\n for (const fileName of CONFIG_FILE_NAMES) {\n const filePath = path.join(cwd, fileName);\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, continue\n }\n }\n return null;\n}\n\nexport async function loadConfig(configPath?: string): Promise<ResolvedConfig> {\n const cwd = process.cwd();\n\n const resolvedPath = configPath\n ? path.resolve(cwd, configPath)\n : await findConfigFile(cwd);\n\n if (!resolvedPath) {\n throw new Error(\n \"No config file found. Create a stacks.config.ts file or specify a path with --config\"\n );\n }\n\n let config: any;\n\n if (resolvedPath.endsWith(\".ts\")) {\n const code = await fs.readFile(resolvedPath, \"utf-8\");\n\n // Transform TypeScript to JavaScript, replacing the @secondlayer/cli import\n // For development/linked packages, we need to resolve to the actual package location\n // This will work both for published packages and local development\n let replacementPath: string;\n\n try {\n // Try to resolve @secondlayer/cli as if it were a normal package\n const require = createRequire(import.meta.url);\n const packagePath = require.resolve(\"@secondlayer/cli\");\n replacementPath = pathToFileURL(packagePath).href;\n } catch {\n // Fallback: resolve relative to current module (for development)\n const currentModuleDir = path.dirname(new URL(import.meta.url).pathname);\n const indexPath = path.resolve(currentModuleDir, \"../index\");\n replacementPath = pathToFileURL(indexPath).href;\n }\n\n const transformedCode = code.replace(\n /from\\s+[\"']@stacks\\/cli[\"']/g,\n `from '${replacementPath}'`\n );\n\n const result = transformSync(transformedCode, {\n format: \"esm\",\n target: \"node18\",\n loader: \"ts\",\n });\n\n const tempPath = resolvedPath.replace(/\\.ts$/, \".mjs\");\n await fs.writeFile(tempPath, result.code);\n\n try {\n const fileUrl = pathToFileURL(tempPath).href;\n const module = await import(fileUrl);\n config = module.default;\n } finally {\n await fs.unlink(tempPath).catch(() => {});\n }\n } else {\n const fileUrl = pathToFileURL(resolvedPath).href;\n const module = await import(fileUrl);\n config = module.default;\n }\n\n if (!config) {\n throw new Error(\"Config file must export a default configuration\");\n }\n\n if (typeof config === \"function\") {\n config = config({} as StacksConfig);\n }\n\n validateConfig(config);\n\n // Process plugins if they exist\n const pluginManager = new PluginManager();\n\n if (config.plugins && Array.isArray(config.plugins)) {\n for (const plugin of config.plugins) {\n pluginManager.register(plugin);\n }\n }\n\n // Transform config through plugins\n const resolvedConfig = await pluginManager.transformConfig(config);\n\n return resolvedConfig;\n}\n\nexport function validateConfig(\n config: unknown\n): asserts config is StacksConfig {\n if (!config || typeof config !== \"object\") {\n throw new Error(\"Config must be an object\");\n }\n\n const c = config as any;\n\n // Contracts are optional now since plugins can provide them\n if (c.contracts && !Array.isArray(c.contracts)) {\n throw new Error(\"Config contracts must be an array\");\n }\n\n if (!c.out || typeof c.out !== \"string\") {\n throw new Error(\"Config out must be a string path\");\n }\n\n // Validate contracts if they exist\n if (c.contracts) {\n for (const contract of c.contracts) {\n if (!contract.address && !contract.source) {\n throw new Error(\"Each contract must have either an address or source\");\n }\n }\n }\n\n // Validate plugins if they exist\n if (c.plugins && !Array.isArray(c.plugins)) {\n throw new Error(\"Config plugins must be an array\");\n }\n}\n\nexport function defineConfig(config: StacksConfig): StacksConfig;\nexport function defineConfig(definer: ConfigDefiner): ConfigDefiner;\nexport function defineConfig(configOrDefiner: StacksConfig | ConfigDefiner) {\n return configOrDefiner;\n}\n",
|
|
9
|
+
"/**\n * Plugin Manager for @secondlayer/cli\n * Handles plugin registration, lifecycle execution, and output management\n */\n\nimport { format } from \"prettier\";\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { validateStacksAddress } from \"@stacks/transactions\";\nimport type {\n StacksCodegenPlugin,\n UserConfig,\n ResolvedConfig,\n GenerateContext,\n Logger,\n PluginUtils,\n GeneratedOutput,\n ProcessedContract,\n ContractConfig,\n HookResult,\n PluginExecutionContext,\n} from \"../types/plugin\";\n\n/**\n * Core plugin manager that orchestrates plugin execution\n */\nexport class PluginManager {\n private plugins: StacksCodegenPlugin[] = [];\n private logger: Logger;\n private utils: PluginUtils;\n private executionContext: PluginExecutionContext;\n\n constructor() {\n this.logger = this.createLogger();\n this.utils = this.createUtils();\n this.executionContext = {\n phase: \"config\",\n startTime: Date.now(),\n results: new Map(),\n };\n }\n\n /**\n * Register a plugin\n */\n register(plugin: StacksCodegenPlugin): void {\n // Validate plugin\n if (!plugin.name || !plugin.version) {\n throw new Error(\"Plugin must have a name and version\");\n }\n\n // Check for duplicate plugin names\n const existing = this.plugins.find((p) => p.name === plugin.name);\n if (existing) {\n throw new Error(\n `Plugin \"${plugin.name}\" is already registered (version ${existing.version})`\n );\n }\n\n this.plugins.push(plugin);\n this.logger.debug(`Registered plugin: ${plugin.name}@${plugin.version}`);\n }\n\n /**\n * Get all registered plugins\n */\n getPlugins(): StacksCodegenPlugin[] {\n return [...this.plugins];\n }\n\n /**\n * Transform user config through all plugins\n */\n async transformConfig(config: UserConfig): Promise<ResolvedConfig> {\n this.executionContext.phase = \"config\";\n let transformedConfig = { ...config };\n\n for (const plugin of this.plugins) {\n if (plugin.transformConfig) {\n this.executionContext.currentPlugin = plugin;\n try {\n const result = await plugin.transformConfig(transformedConfig);\n transformedConfig = result;\n this.recordHookResult(plugin.name, \"transformConfig\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformConfig\", {\n success: false,\n error: err,\n });\n throw new Error(\n `Plugin \"${plugin.name}\" failed during config transformation: ${err.message}`\n );\n }\n }\n }\n\n // Add plugins array to resolved config\n const resolvedConfig: ResolvedConfig = {\n ...transformedConfig,\n plugins: this.plugins,\n };\n\n return resolvedConfig;\n }\n\n /**\n * Transform contracts through all plugins\n */\n async transformContracts(\n contracts: ContractConfig[],\n _config: ResolvedConfig\n ): Promise<ProcessedContract[]> {\n const processedContracts: ProcessedContract[] = [];\n\n for (let contract of contracts) {\n // Handle special case for Clarinet plugin contracts\n if ((contract as any)._clarinetSource && contract.abi) {\n // Convert Clarinet contracts directly to ProcessedContract format\n const address =\n typeof contract.address === \"string\" ? contract.address : \"\";\n const [contractAddress, contractName] = address.split(\".\");\n const processed: ProcessedContract = {\n name: contract.name || contractName,\n address: contractAddress,\n contractName: contractName,\n abi: contract.abi,\n source: \"local\" as const,\n metadata: { source: \"clarinet\" },\n };\n processedContracts.push(processed);\n continue;\n }\n\n // Handle direct file mode contracts (already have ABIs parsed)\n if ((contract as any)._directFile && contract.abi) {\n const address =\n typeof contract.address === \"string\" ? contract.address : \"\";\n const [contractAddress, contractName] = address.split(\".\");\n const processed: ProcessedContract = {\n name: contract.name || contractName,\n address: contractAddress,\n contractName: contractName,\n abi: contract.abi,\n source: \"local\" as const,\n metadata: { source: \"direct\" },\n };\n processedContracts.push(processed);\n continue;\n }\n\n // Transform through each plugin\n for (const plugin of this.plugins) {\n if (plugin.transformContract) {\n this.executionContext.currentPlugin = plugin;\n try {\n contract = await plugin.transformContract(contract);\n this.recordHookResult(plugin.name, \"transformContract\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformContract\", {\n success: false,\n error: err,\n });\n this.logger.warn(\n `Plugin \"${plugin.name}\" failed to transform contract: ${err.message}`\n );\n }\n }\n }\n\n // Convert to ProcessedContract\n if (contract.abi) {\n const processed: ProcessedContract = {\n name: contract.name || \"unknown\",\n address:\n typeof contract.address === \"string\"\n ? contract.address.split(\".\")[0]\n : \"unknown\",\n contractName: contract.name || \"unknown\",\n abi: contract.abi,\n source: \"api\" as const, // Use \"api\" as default for plugin-processed contracts\n metadata: contract.metadata,\n };\n processedContracts.push(processed);\n }\n }\n\n return processedContracts;\n }\n\n /**\n * Execute lifecycle hooks\n */\n async executeHook(\n hookName: keyof StacksCodegenPlugin,\n context: any\n ): Promise<void> {\n for (const plugin of this.plugins) {\n const hook = plugin[hookName];\n if (typeof hook === \"function\") {\n this.executionContext.currentPlugin = plugin;\n try {\n await (hook as any).call(plugin, context);\n this.recordHookResult(plugin.name, hookName as string, {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, hookName as string, {\n success: false,\n error: err,\n });\n this.logger.error(\n `Plugin \"${plugin.name}\" failed during ${hookName as string}: ${err.message}`\n );\n // Don't throw - allow other plugins to continue\n }\n }\n }\n }\n\n /**\n * Execute generation phase with full context\n */\n async executeGeneration(\n contracts: ProcessedContract[],\n config: ResolvedConfig\n ): Promise<Map<string, GeneratedOutput>> {\n this.executionContext.phase = \"generate\";\n const outputs = new Map<string, GeneratedOutput>();\n\n // Create generation context\n const context: GenerateContext = {\n config,\n logger: this.logger,\n utils: this.utils,\n contracts,\n outputs,\n augment: (outputKey: string, contractName: string, content: any) => {\n this.augmentOutput(outputs, outputKey, contractName, content);\n },\n addOutput: (key: string, output: GeneratedOutput) => {\n outputs.set(key, output);\n },\n };\n\n // Execute beforeGenerate hooks\n await this.executeHook(\"beforeGenerate\", context);\n\n // Execute generate hooks\n await this.executeHook(\"generate\", context);\n\n // Execute afterGenerate hooks\n await this.executeHook(\"afterGenerate\", context);\n\n return outputs;\n }\n\n /**\n * Transform outputs through plugins\n */\n async transformOutputs(\n outputs: Map<string, GeneratedOutput>\n ): Promise<Map<string, GeneratedOutput>> {\n this.executionContext.phase = \"output\";\n const transformedOutputs = new Map<string, GeneratedOutput>();\n\n for (const [key, output] of outputs) {\n let transformedContent = output.content;\n\n for (const plugin of this.plugins) {\n if (plugin.transformOutput) {\n this.executionContext.currentPlugin = plugin;\n try {\n transformedContent = await plugin.transformOutput(\n transformedContent,\n output.type || \"other\"\n );\n this.recordHookResult(plugin.name, \"transformOutput\", {\n success: true,\n });\n } catch (error) {\n const err = error as Error;\n this.recordHookResult(plugin.name, \"transformOutput\", {\n success: false,\n error: err,\n });\n this.logger.warn(\n `Plugin \"${plugin.name}\" failed to transform output: ${err.message}`\n );\n }\n }\n }\n\n transformedOutputs.set(key, {\n ...output,\n content: transformedContent,\n });\n }\n\n return transformedOutputs;\n }\n\n /**\n * Write outputs to disk\n */\n async writeOutputs(outputs: Map<string, GeneratedOutput>): Promise<void> {\n for (const [, output] of outputs) {\n try {\n const resolvedPath = path.resolve(process.cwd(), output.path);\n await this.utils.ensureDir(path.dirname(resolvedPath));\n await this.utils.writeFile(resolvedPath, output.content);\n // Don't log here - let the main command handle success messaging\n } catch (error) {\n const err = error as Error;\n this.logger.error(`Failed to write ${output.path}: ${err.message}`);\n throw err;\n }\n }\n }\n\n /**\n * Get execution results for debugging\n */\n getExecutionResults(): Map<string, HookResult[]> {\n return new Map(this.executionContext.results);\n }\n\n /**\n * Augment existing output with additional content\n */\n private augmentOutput(\n outputs: Map<string, GeneratedOutput>,\n outputKey: string,\n contractName: string,\n content: any\n ): void {\n const existing = outputs.get(outputKey);\n if (!existing) {\n this.logger.warn(`Cannot augment non-existent output: ${outputKey}`);\n return;\n }\n\n // Simple augmentation - append content\n // In a real implementation, this would be more sophisticated\n const augmentedContent = `${existing.content}\\n\\n// Augmented by plugin for ${contractName}\\n${JSON.stringify(content, null, 2)}`;\n\n outputs.set(outputKey, {\n ...existing,\n content: augmentedContent,\n });\n }\n\n /**\n * Record hook execution result\n */\n private recordHookResult(\n pluginName: string,\n hookName: string,\n result: Omit<HookResult, \"plugin\">\n ): void {\n const key = `${pluginName}:${hookName}`;\n const existing = this.executionContext.results.get(key) || [];\n existing.push({ ...result, plugin: pluginName });\n this.executionContext.results.set(key, existing);\n }\n\n /**\n * Create logger instance\n */\n private createLogger(): Logger {\n return {\n info: (message: string) => console.log(`ℹ️ ${message}`),\n warn: (message: string) => console.warn(`⚠️ ${message}`),\n error: (message: string) => console.error(`❌ ${message}`),\n debug: (message: string) => {\n if (process.env.DEBUG) {\n console.log(`🐛 ${message}`);\n }\n },\n success: (message: string) => console.log(`✅ ${message}`),\n };\n }\n\n /**\n * Create utils instance\n */\n private createUtils(): PluginUtils {\n return {\n toCamelCase: (str: string) => {\n return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n },\n\n toKebabCase: (str: string) => {\n return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n },\n\n validateAddress: (address: string) => {\n return validateStacksAddress(address.split(\".\")[0]);\n },\n\n parseContractId: (contractId: string) => {\n const [address, contractName] = contractId.split(\".\");\n return { address, contractName };\n },\n\n formatCode: async (code: string) => {\n return format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: true,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n },\n\n resolvePath: (relativePath: string) => {\n return path.resolve(process.cwd(), relativePath);\n },\n\n fileExists: async (filePath: string) => {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n },\n\n readFile: async (filePath: string) => {\n return fs.readFile(filePath, \"utf-8\");\n },\n\n writeFile: async (filePath: string, content: string) => {\n await fs.writeFile(filePath, content, \"utf-8\");\n },\n\n ensureDir: async (dirPath: string) => {\n await fs.mkdir(dirPath, { recursive: true });\n },\n };\n }\n}\n",
|
|
10
|
+
"import got from \"got\";\nimport type { NetworkName } from \"../types/config\";\n\n/**\n * Stacks API client for fetching contract information\n */\n\nconst API_URLS: Record<NetworkName, string> = {\n mainnet: \"https://api.hiro.so\",\n testnet: \"https://api.testnet.hiro.so\",\n devnet: \"http://localhost:3999\",\n};\n\nexport interface ContractInfo {\n functions: any[];\n variables?: any[];\n maps?: any[];\n fungible_tokens?: any[];\n non_fungible_tokens?: any[];\n epoch?: string;\n clarity_version?: string;\n}\n\nexport class StacksApiClient {\n private baseUrl: string;\n private headers: Record<string, string>;\n\n constructor(\n network: NetworkName = \"mainnet\",\n apiKey?: string,\n apiUrl?: string\n ) {\n this.baseUrl = apiUrl || API_URLS[network];\n this.headers = apiKey ? { \"x-api-key\": apiKey } : {};\n }\n\n async getContractInfo(contractId: string): Promise<ContractInfo> {\n const [address, contractName] = contractId.split(\".\");\n\n if (!address || !contractName) {\n throw new Error(\n `Invalid contract ID format: ${contractId}. Expected format: ADDRESS.CONTRACT_NAME`\n );\n }\n\n const url = `${this.baseUrl}/v2/contracts/interface/${address}/${contractName}`;\n\n try {\n const response = await got(url, {\n headers: this.headers,\n responseType: \"json\",\n });\n\n return response.body as ContractInfo;\n } catch (error: any) {\n if (error.response?.statusCode === 404) {\n throw new Error(`Contract not found: ${contractId}`);\n }\n if (error.response?.statusCode === 429) {\n throw new Error(\n \"Rate limited. Please provide an API key in your config.\"\n );\n }\n throw new Error(`Failed to fetch contract: ${error.message}`);\n }\n }\n\n async getContractSource(contractId: string): Promise<string> {\n const [address, contractName] = contractId.split(\".\");\n\n if (!address || !contractName) {\n throw new Error(\n `Invalid contract ID format: ${contractId}. Expected format: ADDRESS.CONTRACT_NAME`\n );\n }\n\n const url = `${this.baseUrl}/v2/contracts/source/${address}/${contractName}`;\n\n try {\n const response = await got(url, {\n headers: this.headers,\n responseType: \"json\",\n });\n\n const data = response.body as { source: string };\n return data.source;\n } catch (error: any) {\n return \"\";\n }\n }\n}\n",
|
|
11
|
+
"import { promises as fs } from \"fs\";\nimport type {\n ClarityContract,\n ClarityFunction,\n ClarityType,\n} from \"@secondlayer/clarity-types\";\n\n/**\n * Basic Clarity contract parser\n * This is a simplified parser - a full implementation would be more robust\n */\n\nexport async function parseClarityFile(\n filePath: string\n): Promise<ClarityContract> {\n const content = await fs.readFile(filePath, \"utf-8\");\n return parseClarityContent(content);\n}\n\nexport function parseClarityContent(content: string): ClarityContract {\n const functions: ClarityFunction[] = [];\n\n const functionRegex =\n /\\(define-(public|read-only|private)\\s+\\(([^)]+)\\)([\\s\\S]*?)\\)\\s*$/gm;\n\n let match;\n while ((match = functionRegex.exec(content)) !== null) {\n const [, access, signature, body] = match;\n const func = parseFunctionSignature(signature, access as any, body);\n if (func) {\n functions.push(func);\n }\n }\n\n return { functions };\n}\n\nfunction parseFunctionSignature(\n signature: string,\n access: \"public\" | \"read-only\" | \"private\",\n body: string\n): ClarityFunction | null {\n // Parse function name and arguments\n const parts = signature.trim().split(/\\s+/);\n const name = parts[0];\n\n const args: Array<{ name: string; type: ClarityType }> = [];\n\n // Parse arguments (simplified)\n for (let i = 1; i < parts.length; i += 2) {\n if (parts[i] && parts[i + 1]) {\n const argName = parts[i].replace(/[()]/g, \"\");\n const argType = parseType(parts[i + 1]);\n if (argType) {\n args.push({ name: argName, type: argType });\n }\n }\n }\n\n // Infer return type from body (simplified)\n const outputs = inferReturnType(body);\n\n return {\n name,\n access,\n args,\n outputs,\n };\n}\n\nfunction parseType(typeStr: string): ClarityType | null {\n typeStr = typeStr.replace(/[()]/g, \"\").trim();\n\n // Basic type mappings\n switch (typeStr) {\n case \"uint\":\n case \"uint128\":\n return \"uint128\";\n case \"int\":\n case \"int128\":\n return \"int128\";\n case \"bool\":\n return \"bool\";\n case \"principal\":\n return \"principal\";\n case \"trait_reference\":\n return \"principal\";\n default:\n // Handle complex types (simplified)\n if (typeStr.startsWith(\"string-ascii\")) {\n return { \"string-ascii\": { length: 256 } };\n }\n if (typeStr.startsWith(\"string-utf8\")) {\n return { \"string-utf8\": { length: 256 } };\n }\n if (typeStr.startsWith(\"buff\")) {\n return { buff: { length: 32 } };\n }\n // Default to uint128 for unknown types\n return \"uint128\";\n }\n}\n\nfunction inferReturnType(body: string): ClarityType {\n // Simplified return type inference\n if (body.includes(\"(ok\")) {\n if (body.includes(\"(err\")) {\n return {\n response: {\n ok: \"bool\",\n error: \"uint128\",\n },\n };\n }\n }\n\n if (body.includes(\"true\") || body.includes(\"false\")) {\n return \"bool\";\n }\n\n return \"bool\";\n}\n\n/**\n * Parse ABI from API response\n */\nexport function parseApiResponse(apiResponse: any): ClarityContract {\n try {\n const functions: ClarityFunction[] = [];\n\n if (apiResponse.functions) {\n for (const func of apiResponse.functions) {\n const access = func.access === \"read_only\" ? \"read-only\" : func.access;\n\n functions.push({\n name: func.name,\n access: access,\n args: func.args.map((arg: any) => ({\n name: arg.name,\n type: convertApiType(arg.type),\n })),\n outputs: convertApiType(func.outputs.type),\n });\n }\n }\n\n return { functions };\n } catch (error) {\n throw new Error(`Failed to parse API response: ${error}`);\n }\n}\n\nfunction convertApiType(apiType: any): ClarityType {\n if (typeof apiType === \"string\") {\n if (apiType === \"trait_reference\") {\n return \"trait_reference\";\n }\n return parseType(apiType) || \"uint128\";\n }\n\n // Handle complex types from API\n if (apiType.response) {\n return {\n response: {\n ok: convertApiType(apiType.response.ok),\n error: convertApiType(apiType.response.error),\n },\n };\n }\n\n if (apiType.optional) {\n return {\n optional: convertApiType(apiType.optional),\n };\n }\n\n if (apiType.list) {\n return {\n list: {\n type: convertApiType(apiType.list.type),\n length: apiType.list.length || 100,\n },\n };\n }\n\n if (apiType.tuple) {\n return {\n tuple: apiType.tuple.map((field: any) => ({\n name: field.name,\n type: convertApiType(field.type),\n })),\n };\n }\n\n if (apiType.buffer) {\n return {\n buff: {\n length: apiType.buffer.length || 32,\n },\n };\n }\n\n if (apiType[\"string-ascii\"]) {\n return {\n \"string-ascii\": {\n length: apiType[\"string-ascii\"].length || 256,\n },\n };\n }\n\n if (apiType[\"string-utf8\"]) {\n return {\n \"string-utf8\": {\n length: apiType[\"string-utf8\"].length || 256,\n },\n };\n }\n\n // Handle none type\n if (apiType === \"none\") {\n return \"uint128\"; // TODO: We'll need to handle this better in the future\n }\n\n // Default\n return \"uint128\";\n}\n",
|
|
12
|
+
"import { format } from \"prettier\";\nimport type { ResolvedContract } from \"../types/config\";\nimport type { ClarityFunction } from \"@secondlayer/clarity-types\";\n\n/**\n * Code generator for contract interfaces\n */\n\nexport async function generateContractInterface(\n contracts: ResolvedContract[]\n): Promise<string> {\n const imports = `import { Cl, validateStacksAddress } from '@stacks/transactions'`;\n\n const header = `/**\n * Generated by @secondlayer/cli\n * DO NOT EDIT MANUALLY\n */`;\n\n const contractsCode = contracts\n .map((contract) => generateContract(contract))\n .join(\"\\n\\n\");\n\n const code = `${imports}\\n\\n${header}\\n\\n${contractsCode}`;\n\n const formatted = await format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: true,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n\n return formatted;\n}\n\nfunction generateContract(contract: ResolvedContract): string {\n const { name, address, contractName, abi } = contract;\n\n const abiCode = generateAbiConstant(name, abi);\n\n const methods = abi.functions\n .filter((func: ClarityFunction) => func.access !== \"private\")\n .map((func: ClarityFunction) => generateMethod(func, address, contractName))\n .join(\",\\n\\n \");\n\n const contractCode = `export const ${name} = {\n address: '${address}',\n contractAddress: '${address}',\n contractName: '${contractName}',\n \n ${methods}\n} as const`;\n\n return `${abiCode}\\n\\n${contractCode}`;\n}\n\nfunction generateAbiConstant(name: string, abi: any): string {\n const abiJson = JSON.stringify(abi, null, 2)\n .replace(/\"([a-zA-Z_$][a-zA-Z0-9_$]*)\":/g, \"$1:\") // Only remove quotes from valid JS identifiers\n .replace(/\"/g, \"'\"); // Use single quotes\n\n return `export const ${name}Abi = ${abiJson} as const`;\n}\n\nfunction generateMethod(\n func: ClarityFunction,\n address: string,\n contractName: string\n): string {\n const methodName = toCamelCase(func.name);\n\n if (func.args.length === 0) {\n return `${methodName}() {\n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: []\n }\n }`;\n }\n\n if (func.args.length === 1) {\n const originalArgName = func.args[0].name;\n const argName = toCamelCase(originalArgName);\n const argType = getTypeForArg(func.args[0]);\n const clarityConversion = generateClarityConversion(argName, func.args[0]);\n\n return `${methodName}(...args: [{ ${argName}: ${argType} }] | [${argType}]) {\n const ${argName} = args.length === 1 && typeof args[0] === 'object' && args[0] !== null && '${argName}' in args[0]\n ? args[0].${argName}\n : args[0] as ${argType}\n \n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: [${clarityConversion}]\n }\n }`;\n }\n\n const argsList = func.args.map((arg) => toCamelCase(arg.name)).join(\", \");\n const argsTypes = func.args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `${camelName}: ${getTypeForArg(arg)}`;\n })\n .join(\"; \");\n const argsArray = func.args\n .map((arg) => {\n const argName = toCamelCase(arg.name);\n return generateClarityConversion(argName, arg);\n })\n .join(\", \");\n const objectAccess = func.args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `args[0].${camelName}`;\n })\n .join(\", \");\n const positionTypes = func.args.map((arg) => getTypeForArg(arg)).join(\", \");\n\n return `${methodName}(...args: [{ ${argsTypes} }] | [${positionTypes}]) {\n const [${argsList}] = args.length === 1 && typeof args[0] === 'object' && args[0] !== null\n ? [${objectAccess}]\n : args as [${positionTypes}]\n \n return {\n contractAddress: '${address}',\n contractName: '${contractName}',\n functionName: '${func.name}',\n functionArgs: [${argsArray}]\n }\n }`;\n}\n\nfunction getTypeForArg(arg: any): string {\n const type = arg.type;\n\n if (typeof type === \"string\") {\n switch (type) {\n case \"uint128\":\n case \"int128\":\n return \"bigint\";\n case \"bool\":\n return \"boolean\";\n case \"principal\":\n case \"trait_reference\":\n return \"string\";\n default:\n return \"any\";\n }\n }\n\n if (type[\"string-ascii\"] || type[\"string-utf8\"]) {\n return \"string\";\n }\n\n if (type.buff) {\n // Support flexible buffer input types\n return \"Uint8Array | string | { type: 'ascii' | 'utf8' | 'hex'; value: string }\";\n }\n\n if (type.optional) {\n const innerType = getTypeForArg({ type: type.optional });\n return `${innerType} | null`;\n }\n\n if (type.list) {\n const innerType = getTypeForArg({ type: type.list.type });\n return `${innerType}[]`;\n }\n\n if (type.tuple) {\n const fields = type.tuple\n .map(\n (field: any) =>\n `${toCamelCase(field.name)}: ${getTypeForArg({ type: field.type })}`\n )\n .join(\"; \");\n return `{ ${fields} }`;\n }\n\n if (type.response) {\n const okType = getTypeForArg({ type: type.response.ok });\n const errType = getTypeForArg({ type: type.response.error });\n return `{ ok: ${okType} } | { err: ${errType} }`;\n }\n\n return \"any\";\n}\n\nfunction toCamelCase(str: string): string {\n return str\n .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()) // Convert -a to A\n .replace(/-([A-Z])/g, (_, letter) => letter) // Convert -A to A\n .replace(/-(\\d)/g, (_, digit) => digit) // Convert -1 to 1\n .replace(/-/g, \"\"); // Remove any remaining hyphens\n}\n\n/**\n * Convert TypeScript value to ClarityValue based on the argument type\n */\nfunction generateClarityConversion(argName: string, argType: any): string {\n const type = argType.type;\n\n if (typeof type === \"string\") {\n switch (type) {\n case \"uint128\":\n return `Cl.uint(${argName})`;\n case \"int128\":\n return `Cl.int(${argName})`;\n case \"bool\":\n return `Cl.bool(${argName})`;\n case \"principal\":\n case \"trait_reference\":\n return `(() => {\n const [address, contractName] = ${argName}.split(\".\") as [string, string];\n if (!validateStacksAddress(address)) {\n throw new Error(\"Invalid Stacks address format\");\n }\n if (${argName}.includes(\".\")) {\n return Cl.contractPrincipal(address, contractName);\n } else {\n return Cl.standardPrincipal(${argName});\n }\n })()`;\n default:\n return `${argName}`; // fallback for unknown types\n }\n }\n\n if (type[\"string-ascii\"]) {\n return `Cl.stringAscii(${argName})`;\n }\n\n if (type[\"string-utf8\"]) {\n return `Cl.stringUtf8(${argName})`;\n }\n\n if (type.buff) {\n // Generate flexible buffer conversion code that matches the hooks implementation\n return `(() => {\n const value = ${argName};\n // Direct Uint8Array\n if (value instanceof Uint8Array) {\n return Cl.buffer(value);\n }\n // Object notation with explicit type\n if (typeof value === 'object' && value !== null && value.type && value.value) {\n switch (value.type) {\n case 'ascii':\n return Cl.bufferFromAscii(value.value);\n case 'utf8':\n return Cl.bufferFromUtf8(value.value);\n case 'hex':\n return Cl.bufferFromHex(value.value);\n default:\n throw new Error(\\`Unsupported buffer type: \\${value.type}\\`);\n }\n }\n // Auto-detect string type\n if (typeof value === 'string') {\n // Check for hex (0x prefix or pure hex pattern)\n if (value.startsWith('0x') || /^[0-9a-fA-F]+$/.test(value)) {\n return Cl.bufferFromHex(value);\n }\n // Check for non-ASCII characters (UTF-8)\n if (!/^[\\\\x00-\\\\x7F]*$/.test(value)) {\n return Cl.bufferFromUtf8(value);\n }\n // Default to ASCII for simple ASCII strings\n return Cl.bufferFromAscii(value);\n }\n throw new Error(\\`Invalid buffer value: \\${value}\\`);\n })()`;\n }\n\n if (type.optional) {\n const innerConversion = generateClarityConversion(argName, {\n type: type.optional,\n });\n return `${argName} !== null ? Cl.some(${innerConversion.replace(argName, `${argName}`)}) : Cl.none()`;\n }\n\n if (type.list) {\n const innerConversion = generateClarityConversion(\"item\", {\n type: type.list.type,\n });\n return `Cl.list(${argName}.map(item => ${innerConversion}))`;\n }\n\n if (type.tuple) {\n const fields = type.tuple\n .map((field: any) => {\n const camelFieldName = toCamelCase(field.name);\n const fieldConversion = generateClarityConversion(\n `${argName}.${camelFieldName}`,\n { type: field.type }\n );\n return `\"${field.name}\": ${fieldConversion}`;\n })\n .join(\", \");\n return `Cl.tuple({ ${fields} })`;\n }\n\n if (type.response) {\n // For response types, we expect the user to pass { ok: value } or { err: value }\n const okConversion = generateClarityConversion(`${argName}.ok`, {\n type: type.response.ok,\n });\n const errConversion = generateClarityConversion(`${argName}.err`, {\n type: type.response.error,\n });\n return `'ok' in ${argName} ? Cl.ok(${okConversion.replace(`${argName}.ok`, `${argName}.ok`)}) : Cl.error(${errConversion.replace(`${argName}.err`, `${argName}.err`)})`;\n }\n\n // Default fallback\n return `${argName}`;\n}\n"
|
|
13
|
+
],
|
|
14
|
+
"mappings": "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",
|
|
15
|
+
"debugId": "5EBBA30969CCC98F64756E2164756E21",
|
|
16
|
+
"names": []
|
|
17
|
+
}
|