@secondlayer/cli 0.1.0 → 0.1.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils/config.ts","../src/core/plugin-manager.ts"],"sourcesContent":["/**\n * @stacks/codegen\n * CLI tool for generating type-safe Stacks contract interfaces\n */\n\nexport { defineConfig } from \"./utils/config.js\";\nexport type {\n StacksConfig,\n ContractSource,\n NetworkName,\n} from \"./types/config.js\";\n\nexport type {\n ClarityContract,\n ClarityFunction,\n ClarityType,\n ContractCallParams,\n ReadOnlyCallParams,\n} from \"@secondlayer/clarity-types\";\n\n// Plugin system exports\nexport type {\n StacksCodegenPlugin,\n PluginFactory,\n PluginOptions,\n UserConfig,\n ResolvedConfig,\n GenerateContext,\n PluginContext,\n Logger,\n PluginUtils,\n GeneratedOutput,\n ProcessedContract,\n ContractConfig,\n OutputType,\n} from \"./types/plugin.js\";\n\nexport { PluginManager } from \"./core/plugin-manager.js\";\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 @stacks/codegen 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 @stacks/codegen as if it were a normal package\n const require = createRequire(import.meta.url);\n const packagePath = require.resolve(\"@stacks/codegen\");\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 @stacks/codegen\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"],"mappings":"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","names":["path","fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils/config.ts","../src/core/plugin-manager.ts"],"sourcesContent":["/**\n * @secondlayer/cli\n * CLI tool for generating type-safe Stacks contract interfaces\n */\n\nexport { defineConfig } from \"./utils/config.js\";\nexport type {\n StacksConfig,\n ContractSource,\n NetworkName,\n} from \"./types/config.js\";\n\nexport type {\n ClarityContract,\n ClarityFunction,\n ClarityType,\n ContractCallParams,\n ReadOnlyCallParams,\n} from \"@secondlayer/clarity-types\";\n\n// Plugin system exports\nexport type {\n StacksCodegenPlugin,\n PluginFactory,\n PluginOptions,\n UserConfig,\n ResolvedConfig,\n GenerateContext,\n PluginContext,\n Logger,\n PluginUtils,\n GeneratedOutput,\n ProcessedContract,\n ContractConfig,\n OutputType,\n} from \"./types/plugin.js\";\n\nexport { PluginManager } from \"./core/plugin-manager.js\";\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIA,qBAA8B;;;ACC9B,sBAAuB;AACvB,gBAA+B;AAC/B,kBAAiB;AACjB,0BAAsC;AAkB/B,IAAM,gBAAN,MAAoB;AAAA,EAMzB,cAAc;AALd,SAAQ,UAAiC,CAAC;AAMxC,SAAK,SAAS,KAAK,aAAa;AAChC,SAAK,QAAQ,KAAK,YAAY;AAC9B,SAAK,mBAAmB;AAAA,MACtB,OAAO;AAAA,MACP,WAAW,KAAK,IAAI;AAAA,MACpB,SAAS,oBAAI,IAAI;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAAmC;AAE1C,QAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,SAAS;AACnC,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAGA,UAAM,WAAW,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI;AAChE,QAAI,UAAU;AACZ,YAAM,IAAI;AAAA,QACR,WAAW,OAAO,IAAI,oCAAoC,SAAS,OAAO;AAAA,MAC5E;AAAA,IACF;AAEA,SAAK,QAAQ,KAAK,MAAM;AACxB,SAAK,OAAO,MAAM,sBAAsB,OAAO,IAAI,IAAI,OAAO,OAAO,EAAE;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,aAAoC;AAClC,WAAO,CAAC,GAAG,KAAK,OAAO;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAgB,QAA6C;AACjE,SAAK,iBAAiB,QAAQ;AAC9B,QAAI,oBAAoB,EAAE,GAAG,OAAO;AAEpC,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,OAAO,iBAAiB;AAC1B,aAAK,iBAAiB,gBAAgB;AACtC,YAAI;AACF,gBAAM,SAAS,MAAM,OAAO,gBAAgB,iBAAiB;AAC7D,8BAAoB;AACpB,eAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,YACpD,SAAS;AAAA,UACX,CAAC;AAAA,QACH,SAAS,OAAO;AACd,gBAAM,MAAM;AACZ,eAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,YACpD,SAAS;AAAA,YACT,OAAO;AAAA,UACT,CAAC;AACD,gBAAM,IAAI;AAAA,YACR,WAAW,OAAO,IAAI,0CAA0C,IAAI,OAAO;AAAA,UAC7E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,iBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,SAAS,KAAK;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBACJ,WACA,SAC8B;AAC9B,UAAM,qBAA0C,CAAC;AAEjD,aAAS,YAAY,WAAW;AAE9B,UAAK,SAAiB,mBAAmB,SAAS,KAAK;AAErD,cAAM,UACJ,OAAO,SAAS,YAAY,WAAW,SAAS,UAAU;AAC5D,cAAM,CAAC,iBAAiB,YAAY,IAAI,QAAQ,MAAM,GAAG;AACzD,cAAM,YAA+B;AAAA,UACnC,MAAM,SAAS,QAAQ;AAAA,UACvB,SAAS;AAAA,UACT;AAAA,UACA,KAAK,SAAS;AAAA,UACd,QAAQ;AAAA,UACR,UAAU,EAAE,QAAQ,WAAW;AAAA,QACjC;AACA,2BAAmB,KAAK,SAAS;AACjC;AAAA,MACF;AAGA,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,OAAO,mBAAmB;AAC5B,eAAK,iBAAiB,gBAAgB;AACtC,cAAI;AACF,uBAAW,MAAM,OAAO,kBAAkB,QAAQ;AAClD,iBAAK,iBAAiB,OAAO,MAAM,qBAAqB;AAAA,cACtD,SAAS;AAAA,YACX,CAAC;AAAA,UACH,SAAS,OAAO;AACd,kBAAM,MAAM;AACZ,iBAAK,iBAAiB,OAAO,MAAM,qBAAqB;AAAA,cACtD,SAAS;AAAA,cACT,OAAO;AAAA,YACT,CAAC;AACD,iBAAK,OAAO;AAAA,cACV,WAAW,OAAO,IAAI,mCAAmC,IAAI,OAAO;AAAA,YACtE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,SAAS,KAAK;AAChB,cAAM,YAA+B;AAAA,UACnC,MAAM,SAAS,QAAQ;AAAA,UACvB,SACE,OAAO,SAAS,YAAY,WACxB,SAAS,QAAQ,MAAM,GAAG,EAAE,CAAC,IAC7B;AAAA,UACN,cAAc,SAAS,QAAQ;AAAA,UAC/B,KAAK,SAAS;AAAA,UACd,QAAQ;AAAA;AAAA,UACR,UAAU,SAAS;AAAA,QACrB;AACA,2BAAmB,KAAK,SAAS;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,UACA,SACe;AACf,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,OAAO,OAAO,QAAQ;AAC5B,UAAI,OAAO,SAAS,YAAY;AAC9B,aAAK,iBAAiB,gBAAgB;AACtC,YAAI;AACF,gBAAO,KAAa,KAAK,QAAQ,OAAO;AACxC,eAAK,iBAAiB,OAAO,MAAM,UAAoB;AAAA,YACrD,SAAS;AAAA,UACX,CAAC;AAAA,QACH,SAAS,OAAO;AACd,gBAAM,MAAM;AACZ,eAAK,iBAAiB,OAAO,MAAM,UAAoB;AAAA,YACrD,SAAS;AAAA,YACT,OAAO;AAAA,UACT,CAAC;AACD,eAAK,OAAO;AAAA,YACV,WAAW,OAAO,IAAI,mBAAmB,QAAkB,KAAK,IAAI,OAAO;AAAA,UAC7E;AAAA,QAEF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBACJ,WACA,QACuC;AACvC,SAAK,iBAAiB,QAAQ;AAC9B,UAAM,UAAU,oBAAI,IAA6B;AAGjD,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA,SAAS,CAAC,WAAmB,cAAsB,YAAiB;AAClE,aAAK,cAAc,SAAS,WAAW,cAAc,OAAO;AAAA,MAC9D;AAAA,MACA,WAAW,CAAC,KAAa,WAA4B;AACnD,gBAAQ,IAAI,KAAK,MAAM;AAAA,MACzB;AAAA,IACF;AAGA,UAAM,KAAK,YAAY,kBAAkB,OAAO;AAGhD,UAAM,KAAK,YAAY,YAAY,OAAO;AAG1C,UAAM,KAAK,YAAY,iBAAiB,OAAO;AAE/C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBACJ,SACuC;AACvC,SAAK,iBAAiB,QAAQ;AAC9B,UAAM,qBAAqB,oBAAI,IAA6B;AAE5D,eAAW,CAAC,KAAK,MAAM,KAAK,SAAS;AACnC,UAAI,qBAAqB,OAAO;AAEhC,iBAAW,UAAU,KAAK,SAAS;AACjC,YAAI,OAAO,iBAAiB;AAC1B,eAAK,iBAAiB,gBAAgB;AACtC,cAAI;AACF,iCAAqB,MAAM,OAAO;AAAA,cAChC;AAAA,cACA,OAAO,QAAQ;AAAA,YACjB;AACA,iBAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,cACpD,SAAS;AAAA,YACX,CAAC;AAAA,UACH,SAAS,OAAO;AACd,kBAAM,MAAM;AACZ,iBAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,cACpD,SAAS;AAAA,cACT,OAAO;AAAA,YACT,CAAC;AACD,iBAAK,OAAO;AAAA,cACV,WAAW,OAAO,IAAI,iCAAiC,IAAI,OAAO;AAAA,YACpE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,yBAAmB,IAAI,KAAK;AAAA,QAC1B,GAAG;AAAA,QACH,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAAsD;AACvE,eAAW,CAAC,EAAE,MAAM,KAAK,SAAS;AAChC,UAAI;AACF,cAAM,eAAe,YAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,OAAO,IAAI;AAC5D,cAAM,KAAK,MAAM,UAAU,YAAAA,QAAK,QAAQ,YAAY,CAAC;AACrD,cAAM,KAAK,MAAM,UAAU,cAAc,OAAO,OAAO;AAAA,MAEzD,SAAS,OAAO;AACd,cAAM,MAAM;AACZ,aAAK,OAAO,MAAM,mBAAmB,OAAO,IAAI,KAAK,IAAI,OAAO,EAAE;AAClE,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAiD;AAC/C,WAAO,IAAI,IAAI,KAAK,iBAAiB,OAAO;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKQ,cACN,SACA,WACA,cACA,SACM;AACN,UAAM,WAAW,QAAQ,IAAI,SAAS;AACtC,QAAI,CAAC,UAAU;AACb,WAAK,OAAO,KAAK,uCAAuC,SAAS,EAAE;AACnE;AAAA,IACF;AAIA,UAAM,mBAAmB,GAAG,SAAS,OAAO;AAAA;AAAA,6BAAkC,YAAY;AAAA,EAAK,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAE/H,YAAQ,IAAI,WAAW;AAAA,MACrB,GAAG;AAAA,MACH,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,iBACN,YACA,UACA,QACM;AACN,UAAM,MAAM,GAAG,UAAU,IAAI,QAAQ;AACrC,UAAM,WAAW,KAAK,iBAAiB,QAAQ,IAAI,GAAG,KAAK,CAAC;AAC5D,aAAS,KAAK,EAAE,GAAG,QAAQ,QAAQ,WAAW,CAAC;AAC/C,SAAK,iBAAiB,QAAQ,IAAI,KAAK,QAAQ;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAuB;AAC7B,WAAO;AAAA,MACL,MAAM,CAAC,YAAoB,QAAQ,IAAI,iBAAO,OAAO,EAAE;AAAA,MACvD,MAAM,CAAC,YAAoB,QAAQ,KAAK,iBAAO,OAAO,EAAE;AAAA,MACxD,OAAO,CAAC,YAAoB,QAAQ,MAAM,UAAK,OAAO,EAAE;AAAA,MACxD,OAAO,CAAC,YAAoB;AAC1B,YAAI,QAAQ,IAAI,OAAO;AACrB,kBAAQ,IAAI,aAAM,OAAO,EAAE;AAAA,QAC7B;AAAA,MACF;AAAA,MACA,SAAS,CAAC,YAAoB,QAAQ,IAAI,UAAK,OAAO,EAAE;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAA2B;AACjC,WAAO;AAAA,MACL,aAAa,CAAC,QAAgB;AAC5B,eAAO,IAAI,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC;AAAA,MACrE;AAAA,MAEA,aAAa,CAAC,QAAgB;AAC5B,eAAO,IAAI,QAAQ,UAAU,CAAC,WAAW,IAAI,OAAO,YAAY,CAAC,EAAE;AAAA,MACrE;AAAA,MAEA,iBAAiB,CAAC,YAAoB;AACpC,mBAAO,2CAAsB,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,MACpD;AAAA,MAEA,iBAAiB,CAAC,eAAuB;AACvC,cAAM,CAAC,SAAS,YAAY,IAAI,WAAW,MAAM,GAAG;AACpD,eAAO,EAAE,SAAS,aAAa;AAAA,MACjC;AAAA,MAEA,YAAY,OAAO,SAAiB;AAClC,mBAAO,wBAAO,MAAM;AAAA,UAClB,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,MAEA,aAAa,CAAC,iBAAyB;AACrC,eAAO,YAAAA,QAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY;AAAA,MACjD;AAAA,MAEA,YAAY,OAAO,aAAqB;AACtC,YAAI;AACF,gBAAM,UAAAC,SAAG,OAAO,QAAQ;AACxB,iBAAO;AAAA,QACT,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MAEA,UAAU,OAAO,aAAqB;AACpC,eAAO,UAAAA,SAAG,SAAS,UAAU,OAAO;AAAA,MACtC;AAAA,MAEA,WAAW,OAAO,UAAkB,YAAoB;AACtD,cAAM,UAAAA,SAAG,UAAU,UAAU,SAAS,OAAO;AAAA,MAC/C;AAAA,MAEA,WAAW,OAAO,YAAoB;AACpC,cAAM,UAAAA,SAAG,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AACF;;;ADpRO,SAAS,aAAa,iBAA+C;AAC1E,SAAO;AACT;","names":["path","fs"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as StacksConfig, C as ConfigDefiner } from './plugin-manager-DBXFfyFZ.cjs';
2
- export { h as ContractConfig, a as ContractSource, G as GenerateContext, f as GeneratedOutput, L as Logger, N as NetworkName, O as OutputType, d as PluginContext, P as PluginFactory, i as PluginManager, c as PluginOptions, e as PluginUtils, g as ProcessedContract, R as ResolvedConfig, b as StacksCodegenPlugin, U as UserConfig } from './plugin-manager-DBXFfyFZ.cjs';
1
+ import { S as StacksConfig, C as ConfigDefiner } from './plugin-manager-Cc1rHnQS.cjs';
2
+ export { h as ContractConfig, a as ContractSource, G as GenerateContext, f as GeneratedOutput, L as Logger, N as NetworkName, O as OutputType, d as PluginContext, P as PluginFactory, i as PluginManager, c as PluginOptions, e as PluginUtils, g as ProcessedContract, R as ResolvedConfig, b as StacksCodegenPlugin, U as UserConfig } from './plugin-manager-Cc1rHnQS.cjs';
3
3
  export { ClarityContract, ClarityFunction, ClarityType, ContractCallParams, ReadOnlyCallParams } from '@secondlayer/clarity-types';
4
4
 
5
5
  declare function defineConfig(config: StacksConfig): StacksConfig;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as StacksConfig, C as ConfigDefiner } from './plugin-manager-DBXFfyFZ.js';
2
- export { h as ContractConfig, a as ContractSource, G as GenerateContext, f as GeneratedOutput, L as Logger, N as NetworkName, O as OutputType, d as PluginContext, P as PluginFactory, i as PluginManager, c as PluginOptions, e as PluginUtils, g as ProcessedContract, R as ResolvedConfig, b as StacksCodegenPlugin, U as UserConfig } from './plugin-manager-DBXFfyFZ.js';
1
+ import { S as StacksConfig, C as ConfigDefiner } from './plugin-manager-Cc1rHnQS.js';
2
+ export { h as ContractConfig, a as ContractSource, G as GenerateContext, f as GeneratedOutput, L as Logger, N as NetworkName, O as OutputType, d as PluginContext, P as PluginFactory, i as PluginManager, c as PluginOptions, e as PluginUtils, g as ProcessedContract, R as ResolvedConfig, b as StacksCodegenPlugin, U as UserConfig } from './plugin-manager-Cc1rHnQS.js';
3
3
  export { ClarityContract, ClarityFunction, ClarityType, ContractCallParams, ReadOnlyCallParams } from '@secondlayer/clarity-types';
4
4
 
5
5
  declare function defineConfig(config: StacksConfig): StacksConfig;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/config.ts","../src/core/plugin-manager.ts"],"sourcesContent":["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 @stacks/codegen 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 @stacks/codegen as if it were a normal package\n const require = createRequire(import.meta.url);\n const packagePath = require.resolve(\"@stacks/codegen\");\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 @stacks/codegen\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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/utils/config.ts","../src/core/plugin-manager.ts"],"sourcesContent":["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"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Configuration types for @stacks/codegen
2
+ * Configuration types for @secondlayer/cli
3
3
  */
4
4
  type NetworkName = "mainnet" | "testnet" | "devnet";
5
5
  interface ContractSource {
@@ -52,7 +52,7 @@ interface ResolvedContract {
52
52
  type ConfigDefiner = (config: StacksConfig) => StacksConfig;
53
53
 
54
54
  /**
55
- * Plugin system types for @stacks/codegen
55
+ * Plugin system types for @secondlayer/cli
56
56
  */
57
57
 
58
58
  /**
@@ -215,7 +215,7 @@ interface HookResult<T = any> {
215
215
  }
216
216
 
217
217
  /**
218
- * Plugin Manager for @stacks/codegen
218
+ * Plugin Manager for @secondlayer/cli
219
219
  * Handles plugin registration, lifecycle execution, and output management
220
220
  */
221
221
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Configuration types for @stacks/codegen
2
+ * Configuration types for @secondlayer/cli
3
3
  */
4
4
  type NetworkName = "mainnet" | "testnet" | "devnet";
5
5
  interface ContractSource {
@@ -52,7 +52,7 @@ interface ResolvedContract {
52
52
  type ConfigDefiner = (config: StacksConfig) => StacksConfig;
53
53
 
54
54
  /**
55
- * Plugin system types for @stacks/codegen
55
+ * Plugin system types for @secondlayer/cli
56
56
  */
57
57
 
58
58
  /**
@@ -215,7 +215,7 @@ interface HookResult<T = any> {
215
215
  }
216
216
 
217
217
  /**
218
- * Plugin Manager for @stacks/codegen
218
+ * Plugin Manager for @secondlayer/cli
219
219
  * Handles plugin registration, lifecycle execution, and output management
220
220
  */
221
221
 
@@ -379,7 +379,7 @@ var import_prettier2 = require("prettier");
379
379
  async function generateContractInterface(contracts) {
380
380
  const imports = `import { Cl, validateStacksAddress } from '@stacks/transactions'`;
381
381
  const header = `/**
382
- * Generated by @stacks/codegen
382
+ * Generated by @secondlayer/cli
383
383
  * DO NOT EDIT MANUALLY
384
384
  */`;
385
385
  const contractsCode = contracts.map((contract) => generateContract(contract)).join("\n\n");
@@ -674,7 +674,7 @@ var clarinet = (options = {}) => {
674
674
  const manifestPath = options.path || "./Clarinet.toml";
675
675
  let simnet;
676
676
  return {
677
- name: "@stacks/codegen/plugin-clarinet",
677
+ name: "@secondlayer/cli/plugin-clarinet",
678
678
  version: "1.0.0",
679
679
  async transformConfig(config) {
680
680
  try {
@@ -1024,7 +1024,7 @@ async function generateActionHelpers(contract, options) {
1024
1024
  // src/plugins/actions/index.ts
1025
1025
  var actions = (options = {}) => {
1026
1026
  return {
1027
- name: "@stacks/codegen/plugin-actions",
1027
+ name: "@secondlayer/cli/plugin-actions",
1028
1028
  version: "1.0.0",
1029
1029
  async generate(context) {
1030
1030
  const { contracts } = context;
@@ -2262,7 +2262,7 @@ function generateWriteHook(func, contractName) {
2262
2262
  var react = (options = {}) => {
2263
2263
  const excludeList = options.exclude || [];
2264
2264
  return {
2265
- name: "@stacks/codegen/plugin-react",
2265
+ name: "@secondlayer/cli/plugin-react",
2266
2266
  version: "1.0.0",
2267
2267
  async generate(context) {
2268
2268
  if (options.debug) {
@@ -2493,7 +2493,7 @@ var hiro = (options) => {
2493
2493
  );
2494
2494
  }
2495
2495
  return {
2496
- name: "@stacks/codegen/plugin-hiro",
2496
+ name: "@secondlayer/cli/plugin-hiro",
2497
2497
  version: "1.0.0",
2498
2498
  async transformConfig(config) {
2499
2499
  if (options.debug) {