@secondlayer/cli 0.1.0 → 0.2.0
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 +432 -179
- 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 +10 -17
- package/LICENSE +0 -21
- package/README.md +0 -233
- 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-DBXFfyFZ.d.cts +0 -285
- package/dist/plugin-manager-DBXFfyFZ.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/index.js.map
CHANGED
|
@@ -1 +1,22 @@
|
|
|
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
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/plugin-manager.ts", "../src/plugins/clarinet/index.ts", "../src/generators/contract.ts", "../src/plugins/actions/generators.ts", "../src/plugins/actions/index.ts", "../src/plugins/react/provider/index.ts", "../src/plugins/react/generators/generic.ts", "../src/plugins/react/generators/contract.ts", "../src/plugins/react/generators/utils.ts", "../src/plugins/react/index.ts", "../src/plugins/testing/generators.ts", "../src/plugins/testing/index.ts", "../src/plugins/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\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",
|
|
6
|
+
"/**\n * Clarinet Plugin for @secondlayer/cli\n * Generates type-safe contract interfaces from local Clarity contracts using Clarinet SDK\n */\n\nimport { initSimnet } from \"@hirosystems/clarinet-sdk\";\nimport { generateContractInterface } from \"../../generators/contract\";\nimport type {\n PluginFactory,\n // StacksCodegenPlugin,\n UserConfig,\n GenerateContext,\n // ProcessedContract,\n} from \"../../types/plugin\";\n\nexport interface ClarinetPluginOptions {\n /** Path to Clarinet.toml file */\n path?: string;\n\n /** Include only specific contracts */\n include?: string[];\n\n /** Exclude specific contracts */\n exclude?: string[];\n\n /** Enable debug output */\n debug?: boolean;\n}\n\n/**\n * Convert contract name to camelCase for JavaScript export\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 .replace(/^\\d/, \"_$&\"); // Prefix with underscore if starts with digit\n}\n\n/**\n * Sanitize contract name to be a valid JavaScript identifier using camelCase\n */\nfunction sanitizeContractName(name: string): string {\n return toCamelCase(name);\n}\n\n/**\n * Check if a contract is a user-defined contract (not a system contract)\n */\nasync function isUserDefinedContract(\n contractId: string,\n manifestPath: string\n): Promise<boolean> {\n const [address, contractName] = contractId.split(\".\");\n\n try {\n // Read Clarinet.toml to get user-defined contracts\n const { promises: fs } = await import(\"fs\");\n const tomlContent = await fs.readFile(manifestPath, \"utf-8\");\n\n // Simple TOML parsing to find [contracts.CONTRACT_NAME] sections\n const contractSectionRegex = /^\\[contracts\\.([^\\]]+)\\]/gm;\n const userContracts = new Set<string>();\n\n let match;\n while ((match = contractSectionRegex.exec(tomlContent)) !== null) {\n userContracts.add(match[1]);\n }\n\n // If the contract is explicitly defined in Clarinet.toml, it's user-defined\n if (userContracts.has(contractName)) {\n return true;\n }\n } catch (error) {\n // If we can't read the TOML file, fall back to pattern matching\n }\n\n // Fallback: System contracts typically have specific addresses or are in the boot contracts\n // Common system contract patterns:\n const systemContractPatterns = [\n /^pox-\\d+$/, // pox-2, pox-3, etc.\n /^bns$/, // Blockchain Name System\n /^costs-\\d+$/, // costs-2, costs-3, etc.\n /^lockup$/, // lockup contract\n ];\n\n // Check if it matches any system contract pattern\n if (systemContractPatterns.some((pattern) => pattern.test(contractName))) {\n return false;\n }\n\n // System contracts often use specific addresses\n const systemAddresses = [\n \"SP000000000000000000002Q6VF78\", // Boot contracts address\n \"ST000000000000000000002AMW42H\", // Boot contracts address (testnet)\n ];\n\n if (systemAddresses.includes(address)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Clarinet plugin factory\n */\nexport const clarinet: PluginFactory<ClarinetPluginOptions> = (\n options = {}\n) => {\n const manifestPath = options.path || \"./Clarinet.toml\";\n let simnet: any;\n\n return {\n name: \"@secondlayer/cli/plugin-clarinet\",\n version: \"1.0.0\",\n\n async transformConfig(config: UserConfig): Promise<UserConfig> {\n try {\n // Initialize simnet to extract contract ABIs\n simnet = await initSimnet(manifestPath);\n\n // Get contract interfaces from Clarinet\n const contractInterfaces = simnet.getContractsInterfaces();\n const contracts = [];\n\n for (const [contractId, abi] of contractInterfaces) {\n const [_, contractName] = contractId.split(\".\");\n\n // Skip system contracts\n if (!(await isUserDefinedContract(contractId, manifestPath))) {\n if (options.debug) {\n console.log(`🚫 Skipping system contract: ${contractId}`);\n }\n continue;\n }\n\n // Apply user filters\n if (options.include && !options.include.includes(contractName)) {\n continue;\n }\n if (options.exclude && options.exclude.includes(contractName)) {\n continue;\n }\n\n // Sanitize the contract name for JavaScript export\n const sanitizedName = sanitizeContractName(contractName);\n\n // Don't set source field to avoid conflict with file resolution\n // Instead, we'll track this in metadata during processing\n contracts.push({\n name: sanitizedName,\n address: contractId,\n abi: abi,\n // Remove source field - this was causing the path resolution issue\n _clarinetSource: true, // Internal flag for our plugin\n });\n }\n\n if (options.debug) {\n console.log(\n `🔍 Clarinet plugin found ${contracts.length} user-defined contracts`\n );\n }\n\n return {\n ...config,\n contracts: [...(config.contracts || []), ...contracts],\n };\n } catch (error) {\n const err = error as Error;\n if (options.debug) {\n console.warn(\n `⚠️ Clarinet plugin failed to load contracts: ${err.message}`\n );\n }\n // If Clarinet.toml doesn't exist or fails, just return config unchanged\n return config;\n }\n },\n\n async generate(context: GenerateContext): Promise<void> {\n // Filter contracts that came from Clarinet\n const clarinetContracts = context.contracts.filter(\n (contract) => contract.metadata?.source === \"clarinet\"\n );\n\n if (clarinetContracts.length === 0) {\n return;\n }\n\n if (options.debug) {\n context.logger.debug(\n `Generating interfaces for ${clarinetContracts.length} Clarinet contracts`\n );\n }\n\n // Generate the main contracts file using existing generator\n const contractsCode = await generateContractInterface(clarinetContracts);\n\n context.addOutput(\"contracts\", {\n path: context.config.out,\n content: contractsCode,\n type: \"contracts\",\n });\n\n // Don't log success here - let the main command handle it\n },\n };\n};\n\n/**\n * Utility function to check if a Clarinet project exists\n */\nexport async function hasClarinetProject(\n path = \"./Clarinet.toml\"\n): Promise<boolean> {\n try {\n const { promises: fs } = await import(\"fs\");\n await fs.access(path);\n return true;\n } catch {\n return false;\n }\n}\n",
|
|
7
|
+
"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",
|
|
8
|
+
"/**\n * Action generators for read and write helper functions\n */\n\nimport type { ProcessedContract } from \"../../types/plugin\";\nimport type { ClarityFunction } from \"@secondlayer/clarity-types\";\nimport type { ActionsPluginOptions } from \"./index\";\n\n/**\n * Convert string to camelCase (enhanced version from old generator)\n */\nfunction toCamelCase(str: string): string {\n return str\n .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())\n .replace(/-([A-Z])/g, (_, letter) => letter)\n .replace(/-(\\d)/g, (_, digit) => digit)\n .replace(/-/g, \"\")\n .replace(/^\\d/, \"_$&\");\n}\n\n/**\n * Generate TypeScript type for Clarity argument (from old generator)\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 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\n/**\n * Generate arguments signature for helper functions\n */\nfunction generateArgsSignature(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n\n const argsTypes = args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `${camelName}: ${getTypeForArg(arg)}`;\n })\n .join(\"; \");\n\n return `args: { ${argsTypes} }, `;\n}\n\n/**\n * Generate Clarity arguments for function calls\n */\nfunction generateClarityArgs(\n args: readonly any[],\n _contractName: string\n): string {\n if (args.length === 0) return \"\";\n\n return args\n .map((arg) => {\n const argName = `args.${toCamelCase(arg.name)}`;\n return generateClarityConversion(argName, arg);\n })\n .join(\", \");\n}\n\n/**\n * Convert TypeScript value to ClarityValue based on the argument type (from old generator)\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}`;\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 return `(() => {\n const value = ${argName};\n if (value instanceof Uint8Array) {\n return Cl.buffer(value);\n }\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 if (typeof value === 'string') {\n if (value.startsWith('0x') || /^[0-9a-fA-F]+$/.test(value)) {\n return Cl.bufferFromHex(value);\n }\n if (!/^[\\\\x00-\\\\x7F]*$/.test(value)) {\n return Cl.bufferFromUtf8(value);\n }\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 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 return `${argName}`;\n}\n\n/**\n * Generate read helper functions for a contract (fixed version)\n */\nfunction generateReadHelpers(\n contract: ProcessedContract,\n options: ActionsPluginOptions\n): string {\n const { abi, name } = contract;\n const functions = abi.functions || [];\n\n const readOnlyFunctions = functions.filter(\n (f: ClarityFunction) =>\n (f.access as any) === \"read_only\" || f.access === \"read-only\"\n );\n\n if (readOnlyFunctions.length === 0) {\n return \"\";\n }\n\n // Apply function filters\n const filteredFunctions = readOnlyFunctions.filter(\n (func: ClarityFunction) => {\n if (\n options.includeFunctions &&\n !options.includeFunctions.includes(func.name)\n ) {\n return false;\n }\n if (\n options.excludeFunctions &&\n options.excludeFunctions.includes(func.name)\n ) {\n return false;\n }\n return true;\n }\n );\n\n if (filteredFunctions.length === 0) {\n return \"\";\n }\n\n const helpers = filteredFunctions.map((func: ClarityFunction) => {\n const methodName = toCamelCase(func.name);\n const argsSignature = generateArgsSignature(func.args);\n const clarityArgs = generateClarityArgs(func.args, name);\n\n return `async ${methodName}(${argsSignature}options?: { \n network?: 'mainnet' | 'testnet' | 'devnet';\n senderAddress?: string;\n }) {\n return await fetchCallReadOnlyFunction({\n contractAddress: '${contract.address}',\n contractName: '${contract.contractName}',\n functionName: '${func.name}',\n functionArgs: [${clarityArgs}],\n network: options?.network || 'mainnet',\n senderAddress: options?.senderAddress || 'SP000000000000000000002Q6VF78'\n });\n }`;\n });\n\n return `read: {\n ${helpers.join(\",\\n\\n \")}\n }`;\n}\n\n/**\n * Generate write helper functions for a contract (fixed version)\n */\nfunction generateWriteHelpers(\n contract: ProcessedContract,\n options: ActionsPluginOptions\n): string {\n const { abi, name } = contract;\n const functions = abi.functions || [];\n\n const publicFunctions = functions.filter(\n (f: ClarityFunction) => f.access === \"public\"\n );\n\n if (publicFunctions.length === 0) {\n return \"\";\n }\n\n // Apply function filters\n const filteredFunctions = publicFunctions.filter((func: ClarityFunction) => {\n if (\n options.includeFunctions &&\n !options.includeFunctions.includes(func.name)\n ) {\n return false;\n }\n if (\n options.excludeFunctions &&\n options.excludeFunctions.includes(func.name)\n ) {\n return false;\n }\n return true;\n });\n\n if (filteredFunctions.length === 0) {\n return \"\";\n }\n\n const helpers = filteredFunctions.map((func: ClarityFunction) => {\n const methodName = toCamelCase(func.name);\n const argsSignature = generateArgsSignature(func.args);\n const clarityArgs = generateClarityArgs(func.args, name);\n\n return `async ${methodName}(${argsSignature}options: {\n senderKey: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n fee?: string | number | undefined;\n nonce?: bigint;\n anchorMode?: 1 | 2 | 3; // AnchorMode: OnChainOnly = 1, OffChainOnly = 2, Any = 3\n postConditions?: any[]; // TODO: Add proper PostCondition types\n validateWithAbi?: boolean;\n }) {\n const { senderKey, network = 'mainnet', ...txOptions } = options;\n \n return await makeContractCall({\n contractAddress: '${contract.address}',\n contractName: '${contract.contractName}',\n functionName: '${func.name}',\n functionArgs: [${clarityArgs}],\n senderKey,\n network,\n validateWithAbi: true,\n ...txOptions\n });\n }`;\n });\n\n return `write: {\n ${helpers.join(\",\\n\\n \")}\n }`;\n}\n\n/**\n * Generate action helpers (read and write functions) for a contract\n */\nexport async function generateActionHelpers(\n contract: ProcessedContract,\n options: ActionsPluginOptions\n): Promise<string> {\n const readHelpers = generateReadHelpers(contract, options);\n const writeHelpers = generateWriteHelpers(contract, options);\n\n if (!readHelpers && !writeHelpers) {\n return \"\";\n }\n\n const helpers = [readHelpers, writeHelpers].filter(Boolean);\n return helpers.join(\",\\n\\n\");\n}\n",
|
|
9
|
+
"/**\n * Actions Plugin for @secondlayer/cli\n * Generates read and write helper functions for direct blockchain interaction\n */\n\nimport { generateActionHelpers } from \"./generators\";\nimport type {\n PluginFactory,\n // UserConfig,\n GenerateContext,\n} from \"../../types/plugin\";\n\nexport interface ActionsPluginOptions {\n /** Include only specific contracts */\n include?: string[];\n\n /** Exclude specific contracts */\n exclude?: string[];\n\n /** Include only specific functions */\n includeFunctions?: string[];\n\n /** Exclude specific functions */\n excludeFunctions?: string[];\n\n /** Enable debug output */\n debug?: boolean;\n}\n\n/**\n * Actions plugin factory\n */\nexport const actions: PluginFactory<ActionsPluginOptions> = (options = {}) => {\n return {\n name: \"@secondlayer/cli/plugin-actions\",\n version: \"1.0.0\",\n\n async generate(context: GenerateContext): Promise<void> {\n const { contracts } = context;\n\n // Filter contracts based on options\n const filteredContracts = contracts.filter((contract) => {\n if (options.include && !options.include.includes(contract.name)) {\n return false;\n }\n if (options.exclude && options.exclude.includes(contract.name)) {\n return false;\n }\n return true;\n });\n\n if (filteredContracts.length === 0) {\n if (options.debug) {\n context.logger.debug(\"Actions plugin: No contracts to process\");\n }\n return;\n }\n\n if (options.debug) {\n context.logger.debug(\n `Actions plugin: Generating read/write helpers for ${filteredContracts.length} contracts`\n );\n }\n\n // Collect all helpers for all contracts\n const contractHelpers = new Map<string, string>();\n\n for (const contract of filteredContracts) {\n const actionsCode = await generateActionHelpers(contract, options);\n if (actionsCode) {\n contractHelpers.set(contract.name, actionsCode);\n }\n }\n\n // Inject all helpers into the output\n if (contractHelpers.size > 0) {\n const existingOutput = context.outputs.get(\"contracts\");\n if (existingOutput) {\n let modifiedContent = addRequiredImports(existingOutput.content);\n\n // Inject helpers for each contract\n for (const [contractName, helpersCode] of contractHelpers) {\n modifiedContent = injectHelpersIntoContract(\n modifiedContent,\n contractName,\n helpersCode\n );\n }\n\n context.outputs.set(\"contracts\", {\n ...existingOutput,\n content: modifiedContent,\n });\n }\n }\n },\n };\n};\n\n/**\n * Add required imports for fetchCallReadOnlyFunction and makeContractCall\n */\nfunction addRequiredImports(content: string): string {\n // Check if imports already exist\n if (\n content.includes(\"fetchCallReadOnlyFunction\") &&\n content.includes(\"makeContractCall\")\n ) {\n return content;\n }\n\n // Find the existing @stacks/transactions import line\n const transactionsImportRegex =\n /import\\s+\\{([^}]+)\\}\\s+from\\s+['\"]@stacks\\/transactions['\"];/;\n const match = content.match(transactionsImportRegex);\n\n if (match) {\n // Add the new imports to the existing import\n const existingImports = match[1].trim();\n const newImports = [\"fetchCallReadOnlyFunction\", \"makeContractCall\"]\n .filter((imp) => !existingImports.includes(imp))\n .join(\", \");\n\n if (newImports) {\n const updatedImport = `import { ${existingImports}, ${newImports} } from '@stacks/transactions';`;\n return content.replace(transactionsImportRegex, updatedImport);\n }\n }\n\n return content;\n}\n\n/**\n * Inject read/write helpers into a specific contract object in the output\n */\nfunction injectHelpersIntoContract(\n content: string,\n contractName: string,\n helpersCode: string\n): string {\n // Use a more precise regex to find the entire contract object\n const contractPattern = new RegExp(\n `(export const ${contractName} = \\\\{[\\\\s\\\\S]*?)\\\\n\\\\} as const;`,\n \"g\"\n );\n\n return content.replace(contractPattern, (_, contractBody) => {\n // Remove any trailing comma and whitespace from the contract body\n const cleanBody = contractBody.replace(/,\\s*$/, \"\");\n\n // Add proper indentation to lines that start top-level properties\n const indentedHelpersCode = helpersCode\n .split(\"\\n\")\n .map((line) => {\n // Only add indentation to lines that start with a property name (like \"write:\")\n if (line.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*:/)) {\n return ` ${line}`;\n }\n return line;\n })\n .join(\"\\n\");\n\n // Add the helpers with proper formatting\n return `${cleanBody},\n\n${indentedHelpersCode}\n} as const;`;\n });\n}\n",
|
|
10
|
+
"/**\n * Provider generator for React plugin\n */\n\nimport { format } from \"prettier\";\n\n/**\n * Generate the provider file content for user projects\n */\nexport async function generateProvider(): Promise<string> {\n const code = `/**\n * Generated Stacks React Provider\n * DO NOT EDIT MANUALLY\n */\n\nimport React, { createContext, useContext } from 'react'\n\n/**\n * Stacks configuration interface\n */\nexport interface StacksReactConfig {\n /**\n * Network to use for API calls\n */\n network: 'mainnet' | 'testnet' | 'devnet'\n\n /**\n * API key for Stacks API (optional)\n */\n apiKey?: string\n\n /**\n * Base URL for Stacks API (optional override)\n */\n apiUrl?: string\n\n /**\n * Default sender address for read-only calls\n */\n senderAddress?: string\n}\n\n/**\n * Provider component props\n */\nexport interface StacksProviderProps {\n children: React.ReactNode\n config: StacksReactConfig\n}\n\n/**\n * React context for Stacks configuration\n */\nconst StacksContext = createContext<StacksReactConfig | undefined>(undefined)\nStacksContext.displayName = 'StacksContext'\n\n/**\n * Create a Stacks React configuration with defaults\n */\nexport function createStacksConfig(config: StacksReactConfig): StacksReactConfig {\n return {\n network: config.network,\n apiKey: config.apiKey,\n apiUrl: config.apiUrl,\n senderAddress: config.senderAddress || 'SP000000000000000000002Q6VF78'\n }\n}\n\n/**\n * Provider component that makes Stacks configuration available to hooks\n */\nexport function StacksProvider({ children, config }: StacksProviderProps) {\n const resolvedConfig = createStacksConfig(config)\n\n return (\n <StacksContext.Provider value={resolvedConfig}>\n {children}\n </StacksContext.Provider>\n )\n}\n\n/**\n * Hook to access the Stacks configuration\n */\nexport function useStacksConfig(): StacksReactConfig {\n const context = useContext(StacksContext)\n \n if (context === undefined) {\n throw new Error(\n 'useStacksConfig must be used within a StacksProvider. ' +\n 'Make sure to wrap your app with <StacksProvider config={{...}}>'\n )\n }\n \n return context\n}`;\n\n const formatted = await format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: false,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n\n return formatted;\n}\n",
|
|
11
|
+
"/**\n * Generic Stacks hooks generator for React plugin\n */\n\nimport { format } from \"prettier\";\n\nconst GENERIC_HOOKS = [\n \"useAccount\",\n \"useConnect\",\n \"useDisconnect\",\n \"useNetwork\",\n \"useContract\",\n \"useOpenSTXTransfer\",\n \"useSignMessage\",\n \"useDeployContract\",\n \"useReadContract\",\n \"useTransaction\",\n \"useBlock\",\n \"useAccountTransactions\",\n \"useWaitForTransaction\",\n] as const;\n\nexport async function generateGenericHooks(\n excludeList: string[] = []\n): Promise<string> {\n // Filter out excluded hooks\n const hooksToGenerate = GENERIC_HOOKS.filter(\n (hookName) => !excludeList.includes(hookName)\n );\n\n const imports = `import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useState, useCallback } from 'react'\nimport { useStacksConfig } from './provider'\nimport { connect, disconnect, isConnected, request, openContractCall as stacksOpenContractCall } from '@stacks/connect'\nimport { Cl, validateStacksAddress } from '@stacks/transactions'\nimport type { ExtractFunctionArgs, ExtractFunctionNames, ClarityContract } from '@secondlayer/clarity-types'`;\n\n const header = `/**\n * Generated generic Stacks React hooks\n * DO NOT EDIT MANUALLY\n */`;\n\n const hooksCode = hooksToGenerate\n .map((hookName) => generateGenericHook(hookName))\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n const code = `${imports}\\n\\n${header}\\n\\n${hooksCode}`;\n\n const formatted = await format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: false,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n\n return formatted;\n}\n\nfunction generateGenericHook(hookName: string): string {\n switch (hookName) {\n case \"useAccount\":\n return `export function useAccount() {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['stacks-account', config.network],\n queryFn: async () => {\n try {\n // Check if already connected using @stacks/connect v8\n const connected = isConnected()\n \n if (!connected) {\n return {\n address: undefined,\n addresses: undefined,\n isConnected: false,\n isConnecting: false,\n isDisconnected: true,\n status: 'disconnected' as const\n }\n }\n\n // Get addresses using @stacks/connect v8 request method (SIP-030)\n const result = await request('stx_getAddresses')\n \n if (!result || !result.addresses || result.addresses.length === 0) {\n return {\n address: undefined,\n addresses: undefined,\n isConnected: false,\n isConnecting: false,\n isDisconnected: true,\n status: 'disconnected' as const\n }\n }\n\n // Extract STX addresses from the response\n const stxAddresses = result.addresses\n .filter((addr: any) => addr.address.startsWith('SP') || addr.address.startsWith('ST'))\n .map((addr: any) => addr.address)\n\n return {\n address: stxAddresses[0] || undefined,\n addresses: stxAddresses,\n isConnected: true,\n isConnecting: false,\n isDisconnected: false,\n status: 'connected' as const\n }\n } catch (error) {\n // Handle case where wallet is not available or user rejected\n return {\n address: undefined,\n addresses: undefined,\n isConnected: false,\n isConnecting: false,\n isDisconnected: true,\n status: 'disconnected' as const\n }\n }\n },\n refetchOnWindowFocus: false,\n retry: false,\n staleTime: 1000 * 60 * 5, // 5 minutes\n refetchInterval: 1000 * 30, // Refetch every 30 seconds to detect wallet changes\n })\n}`;\n\n case \"useConnect\":\n return `export function useConnect() {\n const queryClient = useQueryClient()\n \n const mutation = useMutation({\n mutationFn: async (options: { forceWalletSelect?: boolean } = {}) => {\n // Use @stacks/connect v8 connect method\n return await connect(options)\n },\n onSuccess: () => {\n // Invalidate account queries to refetch connection state\n queryClient.invalidateQueries({ queryKey: ['stacks-account'] })\n },\n onError: (error) => {\n console.error('Connection failed:', error)\n }\n })\n\n return {\n // Custom connect function that works without arguments\n connect: (options?: { forceWalletSelect?: boolean }) => {\n return mutation.mutate(options || {})\n },\n connectAsync: async (options?: { forceWalletSelect?: boolean }) => {\n return mutation.mutateAsync(options || {})\n },\n // Expose all the mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset,\n // Keep the original mutate/mutateAsync for advanced users\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync\n }\n}`;\n\n case \"useDisconnect\":\n return `export function useDisconnect() {\n const queryClient = useQueryClient()\n \n const mutation = useMutation({\n mutationFn: async () => {\n // Use @stacks/connect v8 disconnect method\n return await disconnect()\n },\n onSuccess: () => {\n // Clear all cached data on disconnect\n queryClient.clear()\n },\n onError: (error) => {\n console.error('Disconnect failed:', error)\n }\n })\n\n return {\n // Custom disconnect function\n disconnect: () => {\n return mutation.mutate()\n },\n disconnectAsync: async () => {\n return mutation.mutateAsync()\n },\n // Expose all the mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset,\n // Keep the original mutate/mutateAsync for advanced users\n mutate: mutation.mutate,\n mutateAsync: mutation.mutateAsync\n }\n}`;\n\n case \"useNetwork\":\n return `export function useNetwork() {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['stacks-network', config.network],\n queryFn: async () => {\n // Currently read-only from config\n // Future: Use request('stx_getNetworks') when wallet support improves\n const network = config.network\n \n return {\n network,\n isMainnet: network === 'mainnet',\n isTestnet: network === 'testnet', \n isDevnet: network === 'devnet',\n // Future: Add switchNetwork when wallets support stx_networkChange\n // switchNetwork: async (newNetwork: string) => {\n // return await request('wallet_changeNetwork', { network: newNetwork })\n // }\n }\n },\n staleTime: Infinity, // Network config rarely changes\n refetchOnWindowFocus: false,\n retry: false\n })\n}`;\n\n case \"useContract\":\n return `export function useContract() {\n const config = useStacksConfig()\n const queryClient = useQueryClient()\n const [isRequestPending, setIsRequestPending] = useState(false)\n \n // Helper function to convert JS values to Clarity values based on ABI\n const convertArgsWithAbi = (args: any, abiArgs: any[]): any[] => {\n if (!abiArgs || abiArgs.length === 0) return []\n \n return abiArgs.map((abiArg, index) => {\n const argValue = Array.isArray(args) \n ? args[index] \n : args[abiArg.name] || args[abiArg.name.replace(/-/g, '').replace(/_/g, '')]\n return convertJSValueToClarityValue(argValue, abiArg.type)\n })\n }\n\n // Helper function to convert buffer values with auto-detection\n const convertBufferValue = (value: any): any => {\n // Direct Uint8Array\n if (value instanceof Uint8Array) {\n return Cl.buffer(value)\n }\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 \n // Auto-detect string type\n if (typeof value === 'string') {\n // 1. 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 \n // 2. Check for non-ASCII characters (UTF-8)\n if (!/^[\\\\x00-\\\\x7F]*$/.test(value)) {\n return Cl.bufferFromUtf8(value)\n }\n \n // 3. Default to ASCII for simple ASCII strings\n return Cl.bufferFromAscii(value)\n }\n \n throw new Error(\\`Invalid buffer value: \\${value}\\`)\n }\n\n // Helper function to convert a single JS value to ClarityValue\n const convertJSValueToClarityValue = (value: any, type: any): any => {\n if (typeof type === 'string') {\n switch (type) {\n case 'uint128':\n return Cl.uint(value)\n case 'int128':\n return Cl.int(value)\n case 'bool':\n return Cl.bool(value)\n case 'principal':\n if (!validateStacksAddress(value.split('.')[0])) {\n throw new Error('Invalid Stacks address format')\n }\n if (value.includes('.')) {\n const [address, contractName] = value.split('.')\n return Cl.contractPrincipal(address, contractName)\n } else {\n return Cl.standardPrincipal(value)\n }\n default:\n return value\n }\n }\n\n if (type['string-ascii']) {\n return Cl.stringAscii(value)\n }\n\n if (type['string-utf8']) {\n return Cl.stringUtf8(value)\n }\n\n if (type.buff) {\n return convertBufferValue(value)\n }\n\n if (type.optional) {\n return value !== null ? Cl.some(convertJSValueToClarityValue(value, type.optional)) : Cl.none()\n }\n\n if (type.list) {\n return Cl.list(value.map((item: any) => convertJSValueToClarityValue(item, type.list.type)))\n }\n\n if (type.tuple) {\n const tupleData = type.tuple.reduce((acc: any, field: any) => {\n acc[field.name] = convertJSValueToClarityValue(value[field.name], field.type)\n return acc\n }, {})\n return Cl.tuple(tupleData)\n }\n\n if (type.response) {\n return 'ok' in value \n ? Cl.ok(convertJSValueToClarityValue(value.ok, type.response.ok))\n : Cl.error(convertJSValueToClarityValue(value.err, type.response.error))\n }\n\n return value\n }\n\n // Helper function to find a function in an ABI by name\n const findFunctionInAbi = (abi: any, functionName: string): any => {\n if (!abi || !abi.functions) return null\n return abi.functions.find((func: any) => func.name === functionName)\n }\n \n // Legacy function - unchanged, backward compatible\n const legacyOpenContractCall = useCallback(async (params: {\n contractAddress: string;\n contractName: string;\n functionName: string;\n functionArgs: any[]; // Pre-converted Clarity values\n network?: string;\n postConditions?: any[];\n attachment?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n setIsRequestPending(true)\n \n try {\n const { contractAddress, contractName, functionName, functionArgs, onFinish, onCancel, ...options } = params\n const network = params.network || config.network || 'mainnet'\n const contract = \\`\\${contractAddress}.\\${contractName}\\`\n \n // Try @stacks/connect v8 stx_callContract first (SIP-030)\n try {\n const result = await request('stx_callContract', {\n contract,\n functionName,\n functionArgs,\n network,\n ...options\n })\n \n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ \n queryKey: ['stacks-account'] \n })\n \n onFinish?.(result)\n return result\n } catch (connectError) {\n // Fallback to openContractCall for broader wallet compatibility\n console.warn('stx_callContract not supported, falling back to openContractCall:', connectError)\n \n return new Promise((resolve, reject) => {\n stacksOpenContractCall({\n contractAddress,\n contractName,\n functionName,\n functionArgs,\n network,\n ...options,\n onFinish: (data: any) => {\n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ \n queryKey: ['stacks-account'] \n })\n \n onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n onCancel?.()\n reject(new Error('User cancelled transaction'))\n }\n })\n })\n }\n } catch (error) {\n console.error('Contract call failed:', error)\n throw error instanceof Error ? error : new Error('Contract call failed')\n } finally {\n setIsRequestPending(false)\n }\n }, [config.network, queryClient])\n\n // Enhanced function - requires ABI, auto-converts JS values\n const openContractCall = useCallback(async <\n T extends ClarityContract,\n FN extends ExtractFunctionNames<T>\n >(params: {\n contractAddress: string;\n contractName: string;\n functionName: FN;\n abi: T;\n functionArgs: ExtractFunctionArgs<T, FN>;\n network?: string;\n postConditions?: any[];\n attachment?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n setIsRequestPending(true)\n \n try {\n const { contractAddress, contractName, functionName, functionArgs, abi, onFinish, onCancel, ...options } = params\n const network = params.network || config.network || 'mainnet'\n const contract = \\`\\${contractAddress}.\\${contractName}\\`\n \n // Find the function in the ABI and convert args\n const abiFunction = findFunctionInAbi(abi, functionName)\n if (!abiFunction) {\n throw new Error(\\`Function '\\${functionName}' not found in ABI\\`)\n }\n \n const processedArgs = convertArgsWithAbi(functionArgs, abiFunction.args || [])\n \n // Try @stacks/connect v8 stx_callContract first (SIP-030)\n try {\n const result = await request('stx_callContract', {\n contract,\n functionName,\n functionArgs: processedArgs,\n network,\n ...options\n })\n \n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ \n queryKey: ['stacks-account'] \n })\n \n onFinish?.(result)\n return result\n } catch (connectError) {\n // Fallback to openContractCall for broader wallet compatibility\n console.warn('stx_callContract not supported, falling back to openContractCall:', connectError)\n \n return new Promise((resolve, reject) => {\n stacksOpenContractCall({\n contractAddress,\n contractName,\n functionName,\n functionArgs: processedArgs,\n network,\n ...options,\n onFinish: (data: any) => {\n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ \n queryKey: ['stacks-account'] \n })\n \n onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n onCancel?.()\n reject(new Error('User cancelled transaction'))\n }\n })\n })\n }\n } catch (error) {\n console.error('Contract call failed:', error)\n throw error instanceof Error ? error : new Error('Contract call failed')\n } finally {\n setIsRequestPending(false)\n }\n }, [config.network, queryClient])\n\n return {\n legacyOpenContractCall,\n openContractCall,\n isRequestPending\n }\n}`;\n\n case \"useReadContract\":\n return `export function useReadContract<TArgs = any, TResult = any>(params: {\n contractAddress: string;\n contractName: string;\n functionName: string;\n args?: TArgs;\n network?: 'mainnet' | 'testnet' | 'devnet';\n enabled?: boolean;\n}) {\n const config = useStacksConfig()\n \n return useQuery<TResult>({\n queryKey: ['read-contract', params.contractAddress, params.contractName, params.functionName, params.args, params.network || config.network],\n queryFn: async () => {\n const { fetchCallReadOnlyFunction } = await import('@stacks/transactions')\n \n // For now, we'll need to handle the args conversion here\n // In the future, we could integrate with the contract interface for automatic conversion\n let functionArgs: any[] = []\n \n if (params.args) {\n // This is a simplified conversion - in practice, we'd need the ABI to do proper conversion\n // For now, we'll assume the args are already in the correct format or simple types\n if (Array.isArray(params.args)) {\n functionArgs = params.args\n } else if (typeof params.args === 'object') {\n // Convert object args to array (this is a basic implementation)\n functionArgs = Object.values(params.args)\n } else {\n functionArgs = [params.args]\n }\n }\n \n return await fetchCallReadOnlyFunction({\n contractAddress: params.contractAddress,\n contractName: params.contractName,\n functionName: params.functionName,\n functionArgs,\n network: params.network || config.network || 'mainnet',\n senderAddress: config.senderAddress || 'SP000000000000000000002Q6VF78'\n }) as TResult\n },\n enabled: params.enabled ?? true\n })\n}`;\n\n case \"useTransaction\":\n return `export function useTransaction(txId?: string) {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['transaction', txId, config.network],\n queryFn: () => fetchTransaction({\n txId: txId!,\n network: config.network,\n apiUrl: config.apiUrl\n }),\n enabled: !!txId\n })\n}`;\n\n case \"useBlock\":\n return `export function useBlock(height?: number) {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['block', height, config.network],\n queryFn: () => fetchBlock({\n height: height!,\n network: config.network,\n apiUrl: config.apiUrl\n }),\n enabled: typeof height === 'number'\n })\n}`;\n\n case \"useAccountTransactions\":\n return `export function useAccountTransactions(address?: string) {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['account-transactions', address, config.network],\n queryFn: () => fetchAccountTransactions({\n address: address!,\n network: config.network,\n apiUrl: config.apiUrl\n }),\n enabled: !!address\n })\n}`;\n\n case \"useWaitForTransaction\":\n return `export function useWaitForTransaction(txId?: string) {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['wait-for-transaction', txId, config.network],\n queryFn: () => fetchTransaction({\n txId: txId!,\n network: config.network,\n apiUrl: config.apiUrl\n }),\n enabled: !!txId,\n refetchInterval: (data) => {\n // Stop polling when transaction is complete\n if (data?.tx_status === 'success' || \n data?.tx_status === 'abort_by_response' || \n data?.tx_status === 'abort_by_post_condition') {\n return false\n }\n return 2000 // Poll every 2 seconds\n },\n staleTime: 0 // Always refetch\n })\n}`;\n\n case \"useOpenSTXTransfer\":\n return `export function useOpenSTXTransfer() {\n const config = useStacksConfig()\n const queryClient = useQueryClient()\n \n const mutation = useMutation({\n mutationFn: async (params: {\n recipient: string;\n amount: string | number;\n memo?: string;\n network?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n const { recipient, amount, memo, onFinish, onCancel, ...options } = params\n const network = params.network || config.network || 'mainnet'\n \n return new Promise((resolve, reject) => {\n openSTXTransfer({\n recipient,\n amount: amount.toString(),\n memo,\n network,\n ...options,\n onFinish: (data: any) => {\n onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n onCancel?.()\n reject(new Error('User cancelled transaction'))\n }\n })\n })\n },\n onSuccess: () => {\n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ queryKey: ['stacks-account'] })\n },\n onError: (error) => {\n console.error('STX transfer failed:', error)\n }\n })\n\n const openSTXTransfer = useCallback(async (params: {\n recipient: string;\n amount: string | number;\n memo?: string;\n network?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n return mutation.mutateAsync(params)\n }, [mutation])\n\n return {\n openSTXTransfer,\n // Expose mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset\n }\n}`;\n\n case \"useSignMessage\":\n return `export function useSignMessage() {\n const config = useStacksConfig()\n \n const mutation = useMutation({\n mutationFn: async (params: {\n message: string;\n network?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n const { message, onFinish, onCancel, ...options } = params\n const network = params.network || config.network || 'mainnet'\n \n return new Promise((resolve, reject) => {\n openSignatureRequestPopup({\n message,\n network,\n ...options,\n onFinish: (data: any) => {\n onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n onCancel?.()\n reject(new Error('User cancelled message signing'))\n }\n })\n })\n },\n onError: (error) => {\n console.error('Message signing failed:', error)\n }\n })\n\n const signMessage = useCallback(async (params: {\n message: string;\n network?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n return mutation.mutateAsync(params)\n }, [mutation])\n\n return {\n signMessage,\n // Expose mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset\n }\n}`;\n\n case \"useDeployContract\":\n return `export function useDeployContract() {\n const config = useStacksConfig()\n const queryClient = useQueryClient()\n \n const mutation = useMutation({\n mutationFn: async (params: {\n contractName: string;\n codeBody: string;\n network?: string;\n postConditions?: any[];\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n const { contractName, codeBody, onFinish, onCancel, ...options } = params\n const network = params.network || config.network || 'mainnet'\n \n return new Promise((resolve, reject) => {\n openContractDeploy({\n contractName,\n codeBody,\n network,\n ...options,\n onFinish: (data: any) => {\n onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n onCancel?.()\n reject(new Error('User cancelled contract deployment'))\n }\n })\n })\n },\n onSuccess: () => {\n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ queryKey: ['stacks-account'] })\n },\n onError: (error) => {\n console.error('Contract deployment failed:', error)\n }\n })\n\n const deployContract = useCallback(async (params: {\n contractName: string;\n codeBody: string;\n network?: string;\n postConditions?: any[];\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }) => {\n return mutation.mutateAsync(params)\n }, [mutation])\n\n return {\n deployContract,\n // Expose mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset\n }\n}`;\n\n default:\n return \"\";\n }\n}\n",
|
|
12
|
+
"/**\n * Contract-specific hooks generator for React plugin\n */\n\nimport { format } from \"prettier\";\nimport type { ProcessedContract } from \"../../../types/plugin\";\nimport type { ClarityFunction } from \"@secondlayer/clarity-types\";\nimport {\n toCamelCase,\n capitalize,\n generateHookArgsSignature,\n generateArgsType,\n generateQueryKeyArgs,\n generateFunctionCallArgs,\n generateEnabledCondition,\n generateObjectArgs,\n} from \"./utils\";\n\nexport async function generateContractHooks(\n contracts: ProcessedContract[],\n excludeList: string[] = []\n): Promise<string> {\n const imports = `import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'\nimport { useCallback } from 'react'\nimport { useStacksConfig } from './provider'\nimport { request, openContractCall as stacksOpenContractCall } from '@stacks/connect'\nimport { ${contracts.map((c) => c.name).join(\", \")} } from './contracts'`;\n\n const header = `/**\n * Generated contract-specific React hooks\n * DO NOT EDIT MANUALLY\n */`;\n\n const hooksCode = contracts\n .map((contract) => generateContractHookMethods(contract, excludeList))\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n const code = `${imports}\\n\\n${header}\\n\\n${hooksCode}`;\n\n const formatted = await format(code, {\n parser: \"typescript\",\n singleQuote: true,\n semi: false,\n printWidth: 100,\n trailingComma: \"es5\",\n });\n\n return formatted;\n}\n\nfunction generateContractHookMethods(\n contract: ProcessedContract,\n excludeList: string[]\n): string {\n const { abi, name } = contract;\n const functions = abi.functions || [];\n\n const readOnlyFunctions = functions.filter(\n (f: ClarityFunction) =>\n (f.access as any) === \"read_only\" || f.access === \"read-only\"\n );\n const publicFunctions = functions.filter(\n (f: ClarityFunction) => f.access === \"public\"\n );\n\n const readHooks = readOnlyFunctions\n .map((func: ClarityFunction) => {\n const hookName = `use${capitalize(name)}${capitalize(toCamelCase(func.name))}`;\n // Check if this specific hook is excluded\n if (excludeList.includes(hookName)) {\n return null;\n }\n return generateReadHook(func, name);\n })\n .filter(Boolean);\n\n const writeHooks = publicFunctions\n .map((func: ClarityFunction) => {\n const hookName = `use${capitalize(name)}${capitalize(toCamelCase(func.name))}`;\n // Check if this specific hook is excluded\n if (excludeList.includes(hookName)) {\n return null;\n }\n return generateWriteHook(func, name);\n })\n .filter(Boolean);\n\n const allHooks = [...readHooks, ...writeHooks];\n\n // If all hooks for this contract are excluded, return empty string\n if (allHooks.length === 0) {\n return \"\";\n }\n\n return allHooks.join(\"\\n\\n\");\n}\n\nfunction generateReadHook(func: ClarityFunction, contractName: string): string {\n const hookName = `use${capitalize(contractName)}${capitalize(toCamelCase(func.name))}`;\n const argsSignature = generateHookArgsSignature(func.args);\n const enabledParam =\n func.args.length > 0\n ? \", options?: { enabled?: boolean }\"\n : \"options?: { enabled?: boolean }\";\n\n return `export function ${hookName}(${argsSignature}${enabledParam}) {\n const config = useStacksConfig()\n \n return useQuery({\n queryKey: ['${func.name}', ${contractName}.address, ${generateQueryKeyArgs(func.args)}],\n queryFn: () => ${contractName}.read.${toCamelCase(func.name)}(${generateFunctionCallArgs(func.args) ? `{ ${generateObjectArgs(func.args)} }, ` : \"\"}{ \n network: config.network,\n senderAddress: config.senderAddress || 'SP000000000000000000002Q6VF78'\n }),\n ${func.args.length > 0 ? `enabled: ${generateEnabledCondition(func.args)} && (options?.enabled ?? true),` : \"\"}\n ...options\n })\n}`;\n}\n\nfunction generateWriteHook(\n func: ClarityFunction,\n contractName: string\n): string {\n const hookName = `use${capitalize(contractName)}${capitalize(toCamelCase(func.name))}`;\n const argsType = generateArgsType(func.args);\n\n return `export function ${hookName}() {\n const config = useStacksConfig()\n const queryClient = useQueryClient()\n \n const mutation = useMutation({\n mutationFn: async (params: {\n args: ${argsType};\n options?: {\n postConditions?: any[];\n attachment?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n };\n }) => {\n const { args, options = {} } = params\n const contractCallData = ${contractName}.${toCamelCase(func.name)}(args)\n const { contractAddress, contractName: name, functionName, functionArgs } = contractCallData\n const network = config.network || 'mainnet'\n const contract = \\`\\${contractAddress}.\\${name}\\`\n \n // Try @stacks/connect v8 stx_callContract first (SIP-030)\n try {\n const result = await request('stx_callContract', {\n contract,\n functionName,\n functionArgs,\n network,\n ...options\n })\n \n options.onFinish?.(result)\n return result\n } catch (connectError) {\n // Fallback to openContractCall for broader wallet compatibility\n console.warn('stx_callContract not supported, falling back to openContractCall:', connectError)\n \n return new Promise((resolve, reject) => {\n stacksOpenContractCall({\n contractAddress,\n contractName: name,\n functionName,\n functionArgs,\n network,\n ...options,\n onFinish: (data: any) => {\n options.onFinish?.(data)\n resolve(data)\n },\n onCancel: () => {\n options.onCancel?.()\n reject(new Error('User cancelled transaction'))\n }\n })\n })\n }\n },\n onSuccess: () => {\n // Invalidate relevant queries on success\n queryClient.invalidateQueries({ queryKey: ['stacks-account'] })\n },\n onError: (error) => {\n console.error('Contract call failed:', error)\n }\n })\n\n const ${toCamelCase(func.name)} = useCallback(async (\n args: ${argsType}, \n options?: {\n postConditions?: any[];\n attachment?: string;\n onFinish?: (data: any) => void;\n onCancel?: () => void;\n }\n ) => {\n return mutation.mutateAsync({ args, options })\n }, [mutation])\n\n return {\n ${toCamelCase(func.name)},\n // Expose mutation state\n isPending: mutation.isPending,\n isError: mutation.isError,\n isSuccess: mutation.isSuccess,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset\n }\n}`;\n}\n",
|
|
13
|
+
"/**\n * Utility functions for React hook generation\n */\n\n// Helper functions\nexport function toCamelCase(str: string): string {\n return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\n}\n\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n\nexport function generateHookArgsSignature(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n\n const argsList = args\n .map((arg) => `${toCamelCase(arg.name)}: ${mapClarityTypeToTS(arg.type)}`)\n .join(\", \");\n return `${argsList}`;\n}\n\nexport function generateArgsType(args: readonly any[]): string {\n if (args.length === 0) return \"void\";\n\n const argsList = args\n .map((arg) => `${toCamelCase(arg.name)}: ${mapClarityTypeToTS(arg.type)}`)\n .join(\"; \");\n return `{ ${argsList} }`;\n}\n\nexport function generateQueryKeyArgs(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n return args.map((arg) => toCamelCase(arg.name)).join(\", \");\n}\n\nexport function generateFunctionCallArgs(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n return args.map((arg) => toCamelCase(arg.name)).join(\", \");\n}\n\nexport function generateEnabledCondition(args: readonly any[]): string {\n return args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n const type = mapClarityTypeToTS(arg.type);\n if (type === \"string\") return `!!${camelName}`;\n if (type === \"bigint\") return `${camelName} !== undefined`;\n return `${camelName} !== undefined`;\n })\n .join(\" && \");\n}\n\nexport function mapClarityTypeToTS(clarityType: any): string {\n // Handle non-string types\n if (typeof clarityType !== \"string\") {\n if (clarityType?.uint || clarityType?.int) return \"bigint\";\n if (clarityType?.principal) return \"string\";\n if (clarityType?.bool) return \"boolean\";\n if (clarityType?.string || clarityType?.ascii) return \"string\";\n if (clarityType?.buff) return \"Uint8Array\";\n if (clarityType?.optional) {\n const innerType = mapClarityTypeToTS(clarityType.optional);\n return `${innerType} | null`;\n }\n if (clarityType?.response) return \"any\";\n if (clarityType?.tuple) return \"any\";\n if (clarityType?.list) return \"any[]\";\n return \"any\";\n }\n\n // Handle string types\n if (clarityType.includes(\"uint\") || clarityType.includes(\"int\"))\n return \"bigint\";\n if (clarityType.includes(\"principal\")) return \"string\";\n if (clarityType.includes(\"bool\")) return \"boolean\";\n if (clarityType.includes(\"string\") || clarityType.includes(\"ascii\"))\n return \"string\";\n if (clarityType.includes(\"buff\")) return \"Uint8Array\";\n if (clarityType.includes(\"optional\")) {\n const innerType = clarityType.replace(/optional\\s*/, \"\").trim();\n return `${mapClarityTypeToTS(innerType)} | null`;\n }\n if (clarityType.includes(\"response\")) return \"any\"; // TODO: Better response type handling\n if (clarityType.includes(\"tuple\")) return \"any\"; // TODO: Better tuple type handling\n if (clarityType.includes(\"list\")) return \"any[]\"; // TODO: Better list type handling\n\n return \"any\";\n}\n\nexport function generateObjectArgs(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n return args.map((arg) => `${arg.name}: ${toCamelCase(arg.name)}`).join(\", \");\n}\n",
|
|
14
|
+
"/**\n * React Plugin for @secondlayer/cli\n * Generates React hooks for contract interfaces and generic Stacks functionality\n */\n\nimport type { PluginFactory, GenerateContext } from \"../../types/plugin\";\nimport type { ReactPluginOptions } from \"./types\";\nimport { generateProvider } from \"./provider/index\";\nimport { generateGenericHooks } from \"./generators/generic\";\nimport { generateContractHooks } from \"./generators/contract\";\n\n/**\n * React plugin factory\n */\nexport const react: PluginFactory<ReactPluginOptions> = (options = {}) => {\n const excludeList = options.exclude || [];\n\n return {\n name: \"@secondlayer/cli/plugin-react\",\n version: \"1.0.0\",\n\n async generate(context: GenerateContext): Promise<void> {\n if (options.debug) {\n context.logger.debug(\n `React plugin generating hooks (excluding: ${excludeList.join(\", \") || \"none\"})`\n );\n }\n\n // Generate provider (always generated)\n const provider = await generateProvider();\n context.addOutput(\"provider\", {\n path: \"./src/generated/provider.tsx\",\n content: provider,\n type: \"config\",\n });\n\n // Generate generic hooks (all by default, minus excludes)\n const genericHooks = await generateGenericHooks(excludeList);\n context.addOutput(\"generic-hooks\", {\n path: \"./src/generated/hooks.ts\",\n content: genericHooks,\n type: \"hooks\",\n });\n\n // Generate contract hooks (all contracts, minus excludes)\n if (context.contracts.length > 0) {\n const contractHooks = await generateContractHooks(\n context.contracts,\n excludeList\n );\n\n // Only add output if there are hooks to generate\n if (contractHooks.trim()) {\n context.addOutput(\"contract-hooks\", {\n path: \"./src/generated/contract-hooks.ts\",\n content: contractHooks,\n type: \"hooks\",\n });\n }\n }\n\n if (options.debug) {\n context.logger.success(\n `React plugin generated ${context.contracts.length} contract hook sets`\n );\n }\n },\n };\n};\n\n// Re-export types for convenience\nexport type { ReactPluginOptions } from \"./types\";\n",
|
|
15
|
+
"/**\n * Code generators for the testing plugin\n * Generates type-safe helpers for Clarinet SDK unit tests\n */\n\nimport type { ProcessedContract } from \"../../types/plugin\";\nimport type { ClarityFunction } from \"@secondlayer/clarity-types\";\nimport type { TestingPluginOptions } from \"./index\";\n\n/**\n * Clarity data variable definition from ABI\n */\ninterface ClarityVariable {\n name: string;\n type: any;\n access: \"constant\" | \"variable\";\n}\n\n/**\n * Clarity map definition from ABI\n */\ninterface ClarityMap {\n name: string;\n key: any;\n value: any;\n}\n\n/**\n * Convert string to camelCase\n */\nfunction toCamelCase(str: string): string {\n return str\n .replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())\n .replace(/-([A-Z])/g, (_, letter) => letter)\n .replace(/-(\\d)/g, (_, digit) => digit)\n .replace(/-/g, \"\")\n .replace(/^\\d/, \"_$&\");\n}\n\n/**\n * Convert string to PascalCase\n */\nfunction toPascalCase(str: string): string {\n const camel = toCamelCase(str);\n return camel.charAt(0).toUpperCase() + camel.slice(1);\n}\n\n/**\n * Generate TypeScript type for Clarity argument\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 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\n/**\n * Generate arguments signature for helper functions\n */\nfunction generateArgsSignature(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n\n const argsTypes = args\n .map((arg) => {\n const camelName = toCamelCase(arg.name);\n return `${camelName}: ${getTypeForArg(arg)}`;\n })\n .join(\"; \");\n\n return `args: { ${argsTypes} }, `;\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 principal = ${argName};\n if (principal.includes(\".\")) {\n const [address, contractName] = principal.split(\".\") as [string, string];\n return Cl.contractPrincipal(address, contractName);\n } else {\n return Cl.standardPrincipal(principal);\n }\n })()`;\n default:\n return `${argName}`;\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 return `(() => {\n const value = ${argName};\n if (value instanceof Uint8Array) {\n return Cl.buffer(value);\n }\n if (typeof value === 'object' && value !== null && 'type' in value && 'value' in 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 if (typeof value === 'string') {\n if (value.startsWith('0x') || /^[0-9a-fA-F]+$/.test(value)) {\n return Cl.bufferFromHex(value);\n }\n if (!/^[\\\\x00-\\\\x7F]*$/.test(value)) {\n return Cl.bufferFromUtf8(value);\n }\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(\"inner\", {\n type: type.optional,\n });\n return `${argName} !== null ? Cl.some((() => { const inner = ${argName}; return ${innerConversion}; })()) : 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 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}) : Cl.error(${errConversion})`;\n }\n\n return `${argName}`;\n}\n\n/**\n * Generate Clarity arguments for function calls\n */\nfunction generateClarityArgs(args: readonly any[]): string {\n if (args.length === 0) return \"\";\n\n return args\n .map((arg) => {\n const argName = `args.${toCamelCase(arg.name)}`;\n return generateClarityConversion(argName, arg);\n })\n .join(\", \");\n}\n\n/**\n * Generate a public function helper\n */\nfunction generatePublicFunction(\n func: ClarityFunction,\n contractId: string\n): string {\n const methodName = toCamelCase(func.name);\n const argsSignature = generateArgsSignature(func.args);\n const clarityArgs = generateClarityArgs(func.args);\n\n return `${methodName}: (${argsSignature}caller: string) => {\n const callerAddr = accounts.get(caller) ?? caller;\n return simnet.callPublicFn(\n '${contractId}',\n '${func.name}',\n [${clarityArgs}],\n callerAddr\n );\n }`;\n}\n\n/**\n * Generate a read-only function helper\n */\nfunction generateReadOnlyFunction(\n func: ClarityFunction,\n contractId: string\n): string {\n const methodName = toCamelCase(func.name);\n const argsSignature = generateArgsSignature(func.args);\n const clarityArgs = generateClarityArgs(func.args);\n\n // Read-only functions don't need a caller, use deployer as default\n const hasArgs = func.args.length > 0;\n const argsParam = hasArgs ? argsSignature : \"\";\n\n return `${methodName}: (${argsParam}) => {\n return simnet.callReadOnlyFn(\n '${contractId}',\n '${func.name}',\n [${clarityArgs}],\n accounts.get('deployer')!\n );\n }`;\n}\n\n/**\n * Generate a private function helper (for testing only)\n */\nfunction generatePrivateFunction(\n func: ClarityFunction,\n contractId: string\n): string {\n const methodName = toCamelCase(func.name);\n const argsSignature = generateArgsSignature(func.args);\n const clarityArgs = generateClarityArgs(func.args);\n\n return `${methodName}: (${argsSignature}caller: string) => {\n const callerAddr = accounts.get(caller) ?? caller;\n return simnet.callPrivateFn(\n '${contractId}',\n '${func.name}',\n [${clarityArgs}],\n callerAddr\n );\n }`;\n}\n\n/**\n * Generate a data variable accessor helper\n */\nfunction generateDataVarHelper(\n variable: ClarityVariable,\n contractId: string\n): string {\n const methodName = toCamelCase(variable.name);\n\n return `${methodName}: () => {\n return simnet.getDataVar('${contractId}', '${variable.name}');\n }`;\n}\n\n/**\n * Generate TypeScript type for map key based on its structure\n */\nfunction getMapKeyType(keyType: any): string {\n // Map keys are typically tuples\n if (keyType.tuple) {\n const fields = keyType.tuple\n .map(\n (field: any) =>\n `${toCamelCase(field.name)}: ${getTypeForArg({ type: field.type })}`\n )\n .join(\"; \");\n return `{ ${fields} }`;\n }\n\n // Single-value keys (less common but possible)\n return getTypeForArg({ type: keyType });\n}\n\n/**\n * Generate Clarity conversion for map key\n */\nfunction generateMapKeyConversion(keyType: any): string {\n // Map keys are typically tuples\n if (keyType.tuple) {\n const fields = keyType.tuple\n .map((field: any) => {\n const camelFieldName = toCamelCase(field.name);\n const fieldConversion = generateClarityConversion(\n `key.${camelFieldName}`,\n { type: field.type }\n );\n return `\"${field.name}\": ${fieldConversion}`;\n })\n .join(\", \");\n return `Cl.tuple({ ${fields} })`;\n }\n\n // Single-value keys\n return generateClarityConversion(\"key\", { type: keyType });\n}\n\n/**\n * Generate a map entry accessor helper\n */\nfunction generateMapEntryHelper(map: ClarityMap, contractId: string): string {\n const methodName = toCamelCase(map.name);\n const keyType = getMapKeyType(map.key);\n const keyConversion = generateMapKeyConversion(map.key);\n\n return `${methodName}: (key: ${keyType}) => {\n return simnet.getMapEntry(\n '${contractId}',\n '${map.name}',\n ${keyConversion}\n );\n }`;\n}\n\n/**\n * Generate the vars object containing all data variable accessors\n */\nfunction generateVarsObject(\n variables: ClarityVariable[],\n contractId: string\n): string {\n // Filter to only include mutable variables (not constants)\n const dataVars = variables.filter((v) => v.access === \"variable\");\n\n if (dataVars.length === 0) {\n return \"\";\n }\n\n const varHelpers = dataVars.map((v) => generateDataVarHelper(v, contractId));\n\n return `vars: {\n ${varHelpers.join(\",\\n\\n \")}\n }`;\n}\n\n/**\n * Generate the maps object containing all map entry accessors\n */\nfunction generateMapsObject(maps: ClarityMap[], contractId: string): string {\n if (maps.length === 0) {\n return \"\";\n }\n\n const mapHelpers = maps.map((m) => generateMapEntryHelper(m, contractId));\n\n return `maps: {\n ${mapHelpers.join(\",\\n\\n \")}\n }`;\n}\n\n/**\n * Generate a contract helper factory function\n */\nfunction generateContractHelper(\n contract: ProcessedContract,\n options: TestingPluginOptions\n): string {\n const { abi, name, address } = contract;\n const functions = abi.functions || [];\n const variables: ClarityVariable[] = abi.variables || [];\n const maps: ClarityMap[] = abi.maps || [];\n const pascalName = toPascalCase(name);\n\n // Filter functions by access type\n const publicFns = functions.filter(\n (f: ClarityFunction) => f.access === \"public\"\n );\n const readOnlyFns = functions.filter(\n (f: ClarityFunction) =>\n (f.access as any) === \"read_only\" || f.access === \"read-only\"\n );\n const privateFns = options.includePrivate\n ? functions.filter((f: ClarityFunction) => f.access === \"private\")\n : [];\n\n // Generate function helpers\n const publicHelpers = publicFns.map((f: ClarityFunction) =>\n generatePublicFunction(f, address)\n );\n const readOnlyHelpers = readOnlyFns.map((f: ClarityFunction) =>\n generateReadOnlyFunction(f, address)\n );\n const privateHelpers = privateFns.map((f: ClarityFunction) =>\n generatePrivateFunction(f, address)\n );\n\n // Generate data variable and map accessors\n const varsObject = generateVarsObject(variables, address);\n const mapsObject = generateMapsObject(maps, address);\n\n const allHelpers = [...publicHelpers, ...readOnlyHelpers, ...privateHelpers];\n\n // Include vars and maps objects if they have content\n if (varsObject) {\n allHelpers.push(varsObject);\n }\n if (mapsObject) {\n allHelpers.push(mapsObject);\n }\n\n if (allHelpers.length === 0) {\n return \"\";\n }\n\n return `export function get${pascalName}(simnet: Simnet) {\n const accounts = simnet.getAccounts();\n\n return {\n ${allHelpers.join(\",\\n\\n \")}\n };\n}`;\n}\n\n/**\n * Generate the getContracts convenience wrapper\n */\nfunction generateGetContracts(contracts: ProcessedContract[]): string {\n const contractEntries = contracts\n .map((contract) => {\n const camelName = toCamelCase(contract.name);\n const pascalName = toPascalCase(contract.name);\n return `${camelName}: get${pascalName}(simnet)`;\n })\n .join(\",\\n \");\n\n return `export function getContracts(simnet: Simnet) {\n const accounts = simnet.getAccounts();\n\n return {\n accounts,\n ${contractEntries}\n };\n}`;\n}\n\n/**\n * Generate type exports for consumer convenience\n */\nfunction generateTypeExports(contracts: ProcessedContract[]): string {\n const typeExports = contracts\n .map((contract) => {\n const pascalName = toPascalCase(contract.name);\n return `export type ${pascalName}Helpers = ReturnType<typeof get${pascalName}>;`;\n })\n .join(\"\\n\");\n\n return `${typeExports}\nexport type Contracts = ReturnType<typeof getContracts>;`;\n}\n\n/**\n * Main entry point - generates the full testing helpers file\n */\nexport async function generateTestingHelpers(\n contracts: ProcessedContract[],\n options: TestingPluginOptions\n): Promise<string> {\n const contractHelpers = contracts\n .map((contract) => generateContractHelper(contract, options))\n .filter(Boolean);\n\n if (contractHelpers.length === 0) {\n return `// No contracts with functions to generate helpers for\nexport {};`;\n }\n\n const getContractsCode = generateGetContracts(contracts);\n const typeExports = generateTypeExports(contracts);\n\n return `/**\n * Generated by @secondlayer/cli testing plugin\n * Type-safe helpers for Clarinet SDK unit tests\n */\n\nimport { type Simnet, Cl } from '@hirosystems/clarinet-sdk';\n\n// ============================================\n// Per-contract factory functions\n// ============================================\n\n${contractHelpers.join(\"\\n\\n\")}\n\n// ============================================\n// Convenience: all contracts at once\n// ============================================\n\n${getContractsCode}\n\n// ============================================\n// Type exports\n// ============================================\n\n${typeExports}\n`;\n}\n",
|
|
16
|
+
"/**\n * Testing plugin for @secondlayer/cli\n * Generates type-safe helpers for Clarinet SDK unit tests\n */\n\nimport type { PluginFactory, GenerateContext } from \"../../types/plugin\";\nimport { generateTestingHelpers } from \"./generators\";\n\nexport interface TestingPluginOptions {\n /** Include only specific contracts */\n include?: string[];\n\n /** Exclude specific contracts */\n exclude?: string[];\n\n /** Output path for generated testing helpers (default: ./src/generated/testing.ts) */\n out?: string;\n\n /** Include private function helpers (default: false) */\n includePrivate?: boolean;\n\n /** Enable debug output */\n debug?: boolean;\n}\n\nexport const testing: PluginFactory<TestingPluginOptions> = (options = {}) => {\n return {\n name: \"@secondlayer/cli/plugin-testing\",\n version: \"1.0.0\",\n\n async generate(context: GenerateContext): Promise<void> {\n const { contracts } = context;\n\n // Filter contracts based on options\n const filteredContracts = contracts.filter((contract) => {\n if (options.include && !options.include.includes(contract.name)) {\n return false;\n }\n if (options.exclude && options.exclude.includes(contract.name)) {\n return false;\n }\n return true;\n });\n\n if (filteredContracts.length === 0) {\n if (options.debug) {\n context.logger.debug(\"Testing plugin: No contracts to process\");\n }\n return;\n }\n\n if (options.debug) {\n context.logger.debug(\n `Testing plugin: Generating helpers for ${filteredContracts.length} contracts`\n );\n }\n\n // Generate testing helpers\n const testingCode = await generateTestingHelpers(\n filteredContracts,\n options\n );\n\n const outputPath = options.out || \"./src/generated/testing.ts\";\n\n context.addOutput(\"testing\", {\n path: outputPath,\n content: testingCode,\n type: \"utils\",\n });\n\n if (options.debug) {\n context.logger.debug(\n `Testing plugin: Generated helpers for ${filteredContracts.length} contracts`\n );\n }\n },\n };\n};\n",
|
|
17
|
+
"/**\n * Plugin exports for @secondlayer/cli\n * This will be expanded as plugins are implemented\n */\n\nimport type { StacksCodegenPlugin } from \"../types/plugin\";\n\n// Re-export plugin types for convenience\nexport type {\n StacksCodegenPlugin,\n PluginFactory,\n PluginOptions,\n GenerateContext,\n PluginContext,\n Logger,\n PluginUtils,\n} from \"../types/plugin\";\n\n// Plugin utilities\nexport { PluginManager } from \"../core/plugin-manager\";\n\n// Base plugin options interface\nexport interface BasePluginOptions {\n /** Include only specific contracts/functions */\n include?: string[];\n\n /** Exclude specific contracts/functions */\n exclude?: string[];\n\n /** Enable debug output */\n debug?: boolean;\n}\n\n/**\n * Utility function to filter contracts/functions based on include/exclude options\n */\nexport function filterByOptions<T extends { name: string }>(\n items: T[],\n options: BasePluginOptions = {}\n): T[] {\n let filtered = items;\n\n if (options.include && options.include.length > 0) {\n filtered = filtered.filter((item) =>\n options.include!.some(\n (pattern) =>\n item.name.includes(pattern) || item.name.match(new RegExp(pattern))\n )\n );\n }\n\n if (options.exclude && options.exclude.length > 0) {\n filtered = filtered.filter(\n (item) =>\n !options.exclude!.some(\n (pattern) =>\n item.name.includes(pattern) || item.name.match(new RegExp(pattern))\n )\n );\n }\n\n return filtered;\n}\n\n/**\n * Utility function to create a simple plugin\n */\nexport function createPlugin(\n name: string,\n version: string,\n implementation: Partial<StacksCodegenPlugin>\n): StacksCodegenPlugin {\n return {\n name,\n version,\n ...implementation,\n };\n}\n\n// Plugin exports\nexport { clarinet, hasClarinetProject } from \"./clarinet/index\";\nexport type { ClarinetPluginOptions } from \"./clarinet/index\";\n\nexport { actions } from \"./actions/index\";\nexport type { ActionsPluginOptions } from \"./actions/index\";\n\nexport { react } from \"./react/index\";\nexport type { ReactPluginOptions } from \"./react/index\";\n\nexport { testing } from \"./testing/index\";\nexport type { TestingPluginOptions } from \"./testing/index\";\n\n"
|
|
18
|
+
],
|
|
19
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAKA;AACA,qBAAS;AACT;AACA;AAAA;AAkBO,MAAM,cAAc;AAAA,EACjB,UAAiC,CAAC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EAER,WAAW,GAAG;AAAA,IACZ,KAAK,SAAS,KAAK,aAAa;AAAA,IAChC,KAAK,QAAQ,KAAK,YAAY;AAAA,IAC9B,KAAK,mBAAmB;AAAA,MACtB,OAAO;AAAA,MACP,WAAW,KAAK,IAAI;AAAA,MACpB,SAAS,IAAI;AAAA,IACf;AAAA;AAAA,EAMF,QAAQ,CAAC,QAAmC;AAAA,IAE1C,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,SAAS;AAAA,MACnC,MAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAAA,IAGA,MAAM,WAAW,KAAK,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI;AAAA,IAChE,IAAI,UAAU;AAAA,MACZ,MAAM,IAAI,MACR,WAAW,OAAO,wCAAwC,SAAS,UACrE;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ,KAAK,MAAM;AAAA,IACxB,KAAK,OAAO,MAAM,sBAAsB,OAAO,QAAQ,OAAO,SAAS;AAAA;AAAA,EAMzE,UAAU,GAA0B;AAAA,IAClC,OAAO,CAAC,GAAG,KAAK,OAAO;AAAA;AAAA,OAMnB,gBAAe,CAAC,QAA6C;AAAA,IACjE,KAAK,iBAAiB,QAAQ;AAAA,IAC9B,IAAI,oBAAoB,KAAK,OAAO;AAAA,IAEpC,WAAW,UAAU,KAAK,SAAS;AAAA,MACjC,IAAI,OAAO,iBAAiB;AAAA,QAC1B,KAAK,iBAAiB,gBAAgB;AAAA,QACtC,IAAI;AAAA,UACF,MAAM,SAAS,MAAM,OAAO,gBAAgB,iBAAiB;AAAA,UAC7D,oBAAoB;AAAA,UACpB,KAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,YACpD,SAAS;AAAA,UACX,CAAC;AAAA,UACD,OAAO,OAAO;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,KAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,YACpD,SAAS;AAAA,YACT,OAAO;AAAA,UACT,CAAC;AAAA,UACD,MAAM,IAAI,MACR,WAAW,OAAO,8CAA8C,IAAI,SACtE;AAAA;AAAA,MAEJ;AAAA,IACF;AAAA,IAGA,MAAM,iBAAiC;AAAA,SAClC;AAAA,MACH,SAAS,KAAK;AAAA,IAChB;AAAA,IAEA,OAAO;AAAA;AAAA,OAMH,mBAAkB,CACtB,WACA,SAC8B;AAAA,IAC9B,MAAM,qBAA0C,CAAC;AAAA,IAEjD,SAAS,YAAY,WAAW;AAAA,MAE9B,IAAK,SAAiB,mBAAmB,SAAS,KAAK;AAAA,QAErD,MAAM,UACJ,OAAO,SAAS,YAAY,WAAW,SAAS,UAAU;AAAA,QAC5D,OAAO,iBAAiB,gBAAgB,QAAQ,MAAM,GAAG;AAAA,QACzD,MAAM,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;AAAA,QACA,mBAAmB,KAAK,SAAS;AAAA,QACjC;AAAA,MACF;AAAA,MAGA,IAAK,SAAiB,eAAe,SAAS,KAAK;AAAA,QACjD,MAAM,UACJ,OAAO,SAAS,YAAY,WAAW,SAAS,UAAU;AAAA,QAC5D,OAAO,iBAAiB,gBAAgB,QAAQ,MAAM,GAAG;AAAA,QACzD,MAAM,YAA+B;AAAA,UACnC,MAAM,SAAS,QAAQ;AAAA,UACvB,SAAS;AAAA,UACT;AAAA,UACA,KAAK,SAAS;AAAA,UACd,QAAQ;AAAA,UACR,UAAU,EAAE,QAAQ,SAAS;AAAA,QAC/B;AAAA,QACA,mBAAmB,KAAK,SAAS;AAAA,QACjC;AAAA,MACF;AAAA,MAGA,WAAW,UAAU,KAAK,SAAS;AAAA,QACjC,IAAI,OAAO,mBAAmB;AAAA,UAC5B,KAAK,iBAAiB,gBAAgB;AAAA,UACtC,IAAI;AAAA,YACF,WAAW,MAAM,OAAO,kBAAkB,QAAQ;AAAA,YAClD,KAAK,iBAAiB,OAAO,MAAM,qBAAqB;AAAA,cACtD,SAAS;AAAA,YACX,CAAC;AAAA,YACD,OAAO,OAAO;AAAA,YACd,MAAM,MAAM;AAAA,YACZ,KAAK,iBAAiB,OAAO,MAAM,qBAAqB;AAAA,cACtD,SAAS;AAAA,cACT,OAAO;AAAA,YACT,CAAC;AAAA,YACD,KAAK,OAAO,KACV,WAAW,OAAO,uCAAuC,IAAI,SAC/D;AAAA;AAAA,QAEJ;AAAA,MACF;AAAA,MAGA,IAAI,SAAS,KAAK;AAAA,QAChB,MAAM,YAA+B;AAAA,UACnC,MAAM,SAAS,QAAQ;AAAA,UACvB,SACE,OAAO,SAAS,YAAY,WACxB,SAAS,QAAQ,MAAM,GAAG,EAAE,KAC5B;AAAA,UACN,cAAc,SAAS,QAAQ;AAAA,UAC/B,KAAK,SAAS;AAAA,UACd,QAAQ;AAAA,UACR,UAAU,SAAS;AAAA,QACrB;AAAA,QACA,mBAAmB,KAAK,SAAS;AAAA,MACnC;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,OAMH,YAAW,CACf,UACA,SACe;AAAA,IACf,WAAW,UAAU,KAAK,SAAS;AAAA,MACjC,MAAM,OAAO,OAAO;AAAA,MACpB,IAAI,OAAO,SAAS,YAAY;AAAA,QAC9B,KAAK,iBAAiB,gBAAgB;AAAA,QACtC,IAAI;AAAA,UACF,MAAO,KAAa,KAAK,QAAQ,OAAO;AAAA,UACxC,KAAK,iBAAiB,OAAO,MAAM,UAAoB;AAAA,YACrD,SAAS;AAAA,UACX,CAAC;AAAA,UACD,OAAO,OAAO;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,KAAK,iBAAiB,OAAO,MAAM,UAAoB;AAAA,YACrD,SAAS;AAAA,YACT,OAAO;AAAA,UACT,CAAC;AAAA,UACD,KAAK,OAAO,MACV,WAAW,OAAO,uBAAuB,aAAuB,IAAI,SACtE;AAAA;AAAA,MAGJ;AAAA,IACF;AAAA;AAAA,OAMI,kBAAiB,CACrB,WACA,QACuC;AAAA,IACvC,KAAK,iBAAiB,QAAQ;AAAA,IAC9B,MAAM,UAAU,IAAI;AAAA,IAGpB,MAAM,UAA2B;AAAA,MAC/B;AAAA,MACA,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA,SAAS,CAAC,WAAmB,cAAsB,YAAiB;AAAA,QAClE,KAAK,cAAc,SAAS,WAAW,cAAc,OAAO;AAAA;AAAA,MAE9D,WAAW,CAAC,KAAa,WAA4B;AAAA,QACnD,QAAQ,IAAI,KAAK,MAAM;AAAA;AAAA,IAE3B;AAAA,IAGA,MAAM,KAAK,YAAY,kBAAkB,OAAO;AAAA,IAGhD,MAAM,KAAK,YAAY,YAAY,OAAO;AAAA,IAG1C,MAAM,KAAK,YAAY,iBAAiB,OAAO;AAAA,IAE/C,OAAO;AAAA;AAAA,OAMH,iBAAgB,CACpB,SACuC;AAAA,IACvC,KAAK,iBAAiB,QAAQ;AAAA,IAC9B,MAAM,qBAAqB,IAAI;AAAA,IAE/B,YAAY,KAAK,WAAW,SAAS;AAAA,MACnC,IAAI,qBAAqB,OAAO;AAAA,MAEhC,WAAW,UAAU,KAAK,SAAS;AAAA,QACjC,IAAI,OAAO,iBAAiB;AAAA,UAC1B,KAAK,iBAAiB,gBAAgB;AAAA,UACtC,IAAI;AAAA,YACF,qBAAqB,MAAM,OAAO,gBAChC,oBACA,OAAO,QAAQ,OACjB;AAAA,YACA,KAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,cACpD,SAAS;AAAA,YACX,CAAC;AAAA,YACD,OAAO,OAAO;AAAA,YACd,MAAM,MAAM;AAAA,YACZ,KAAK,iBAAiB,OAAO,MAAM,mBAAmB;AAAA,cACpD,SAAS;AAAA,cACT,OAAO;AAAA,YACT,CAAC;AAAA,YACD,KAAK,OAAO,KACV,WAAW,OAAO,qCAAqC,IAAI,SAC7D;AAAA;AAAA,QAEJ;AAAA,MACF;AAAA,MAEA,mBAAmB,IAAI,KAAK;AAAA,WACvB;AAAA,QACH,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,IAEA,OAAO;AAAA;AAAA,OAMH,aAAY,CAAC,SAAsD;AAAA,IACvE,cAAc,WAAW,SAAS;AAAA,MAChC,IAAI;AAAA,QACF,MAAM,eAAe,KAAK,QAAQ,QAAQ,IAAI,GAAG,OAAO,IAAI;AAAA,QAC5D,MAAM,KAAK,MAAM,UAAU,KAAK,QAAQ,YAAY,CAAC;AAAA,QACrD,MAAM,KAAK,MAAM,UAAU,cAAc,OAAO,OAAO;AAAA,QAEvD,OAAO,OAAO;AAAA,QACd,MAAM,MAAM;AAAA,QACZ,KAAK,OAAO,MAAM,mBAAmB,OAAO,SAAS,IAAI,SAAS;AAAA,QAClE,MAAM;AAAA;AAAA,IAEV;AAAA;AAAA,EAMF,mBAAmB,GAA8B;AAAA,IAC/C,OAAO,IAAI,IAAI,KAAK,iBAAiB,OAAO;AAAA;AAAA,EAMtC,aAAa,CACnB,SACA,WACA,cACA,SACM;AAAA,IACN,MAAM,WAAW,QAAQ,IAAI,SAAS;AAAA,IACtC,IAAI,CAAC,UAAU;AAAA,MACb,KAAK,OAAO,KAAK,uCAAuC,WAAW;AAAA,MACnE;AAAA,IACF;AAAA,IAIA,MAAM,mBAAmB,GAAG,SAAS;AAAA;AAAA,6BAAyC;AAAA,EAAiB,KAAK,UAAU,SAAS,MAAM,CAAC;AAAA,IAE9H,QAAQ,IAAI,WAAW;AAAA,SAClB;AAAA,MACH,SAAS;AAAA,IACX,CAAC;AAAA;AAAA,EAMK,gBAAgB,CACtB,YACA,UACA,QACM;AAAA,IACN,MAAM,MAAM,GAAG,cAAc;AAAA,IAC7B,MAAM,WAAW,KAAK,iBAAiB,QAAQ,IAAI,GAAG,KAAK,CAAC;AAAA,IAC5D,SAAS,KAAK,KAAK,QAAQ,QAAQ,WAAW,CAAC;AAAA,IAC/C,KAAK,iBAAiB,QAAQ,IAAI,KAAK,QAAQ;AAAA;AAAA,EAMzC,YAAY,GAAW;AAAA,IAC7B,OAAO;AAAA,MACL,MAAM,CAAC,YAAoB,QAAQ,IAAI,iBAAM,SAAS;AAAA,MACtD,MAAM,CAAC,YAAoB,QAAQ,KAAK,iBAAM,SAAS;AAAA,MACvD,OAAO,CAAC,YAAoB,QAAQ,MAAM,UAAI,SAAS;AAAA,MACvD,OAAO,CAAC,YAAoB;AAAA,QAC1B,IAAI,QAAQ,IAAI,OAAO;AAAA,UACrB,QAAQ,IAAI,gBAAK,SAAS;AAAA,QAC5B;AAAA;AAAA,MAEF,SAAS,CAAC,YAAoB,QAAQ,IAAI,UAAI,SAAS;AAAA,IACzD;AAAA;AAAA,EAMM,WAAW,GAAgB;AAAA,IACjC,OAAO;AAAA,MACL,aAAa,CAAC,QAAgB;AAAA,QAC5B,OAAO,IAAI,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC;AAAA;AAAA,MAGrE,aAAa,CAAC,QAAgB;AAAA,QAC5B,OAAO,IAAI,QAAQ,UAAU,CAAC,WAAW,IAAI,OAAO,YAAY,GAAG;AAAA;AAAA,MAGrE,iBAAiB,CAAC,YAAoB;AAAA,QACpC,OAAO,sBAAsB,QAAQ,MAAM,GAAG,EAAE,EAAE;AAAA;AAAA,MAGpD,iBAAiB,CAAC,eAAuB;AAAA,QACvC,OAAO,SAAS,gBAAgB,WAAW,MAAM,GAAG;AAAA,QACpD,OAAO,EAAE,SAAS,aAAa;AAAA;AAAA,MAGjC,YAAY,OAAO,SAAiB;AAAA,QAClC,OAAO,OAAO,MAAM;AAAA,UAClB,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,eAAe;AAAA,QACjB,CAAC;AAAA;AAAA,MAGH,aAAa,CAAC,iBAAyB;AAAA,QACrC,OAAO,KAAK,QAAQ,QAAQ,IAAI,GAAG,YAAY;AAAA;AAAA,MAGjD,YAAY,OAAO,aAAqB;AAAA,QACtC,IAAI;AAAA,UACF,MAAM,GAAG,OAAO,QAAQ;AAAA,UACxB,OAAO;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA;AAAA;AAAA,MAIX,UAAU,OAAO,aAAqB;AAAA,QACpC,OAAO,GAAG,SAAS,UAAU,OAAO;AAAA;AAAA,MAGtC,WAAW,OAAO,UAAkB,YAAoB;AAAA,QACtD,MAAM,GAAG,UAAU,UAAU,SAAS,OAAO;AAAA;AAAA,MAG/C,WAAW,OAAO,YAAoB;AAAA,QACpC,MAAM,GAAG,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA;AAAA,IAE/C;AAAA;AAEJ;;AC1bA;;;ACLA,mBAAS;AAQT,eAAsB,yBAAyB,CAC7C,WACiB;AAAA,EACjB,MAAM,UAAU;AAAA,EAEhB,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAKf,MAAM,gBAAgB,UACnB,IAAI,CAAC,aAAa,iBAAiB,QAAQ,CAAC,EAC5C,KAAK;AAAA;AAAA,CAAM;AAAA,EAEd,MAAM,OAAO,GAAG;AAAA;AAAA,EAAc;AAAA;AAAA,EAAa;AAAA,EAE3C,MAAM,YAAY,MAAM,QAAO,MAAM;AAAA,IACnC,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAAA,EAED,OAAO;AAAA;AAGT,SAAS,gBAAgB,CAAC,UAAoC;AAAA,EAC5D,QAAQ,MAAM,SAAS,cAAc,QAAQ;AAAA,EAE7C,MAAM,UAAU,oBAAoB,MAAM,GAAG;AAAA,EAE7C,MAAM,UAAU,IAAI,UACjB,OAAO,CAAC,SAA0B,KAAK,WAAW,SAAS,EAC3D,IAAI,CAAC,SAA0B,eAAe,MAAM,SAAS,YAAY,CAAC,EAC1E,KAAK;AAAA;AAAA,GAAS;AAAA,EAEjB,MAAM,eAAe,gBAAgB;AAAA,cACzB;AAAA,sBACQ;AAAA,mBACH;AAAA;AAAA,IAEf;AAAA;AAAA,EAGF,OAAO,GAAG;AAAA;AAAA,EAAc;AAAA;AAG1B,SAAS,mBAAmB,CAAC,MAAc,KAAkB;AAAA,EAC3D,MAAM,UAAU,KAAK,UAAU,KAAK,MAAM,CAAC,EACxC,QAAQ,kCAAkC,KAAK,EAC/C,QAAQ,MAAM,GAAG;AAAA,EAEpB,OAAO,gBAAgB,aAAa;AAAA;AAGtC,SAAS,cAAc,CACrB,MACA,SACA,cACQ;AAAA,EACR,MAAM,aAAa,YAAY,KAAK,IAAI;AAAA,EAExC,IAAI,KAAK,KAAK,WAAW,GAAG;AAAA,IAC1B,OAAO,GAAG;AAAA;AAAA,0BAEY;AAAA,uBACH;AAAA,uBACA,KAAK;AAAA;AAAA;AAAA;AAAA,EAI1B;AAAA,EAEA,IAAI,KAAK,KAAK,WAAW,GAAG;AAAA,IAC1B,MAAM,kBAAkB,KAAK,KAAK,GAAG;AAAA,IACrC,MAAM,UAAU,YAAY,eAAe;AAAA,IAC3C,MAAM,UAAU,cAAc,KAAK,KAAK,EAAE;AAAA,IAC1C,MAAM,oBAAoB,0BAA0B,SAAS,KAAK,KAAK,EAAE;AAAA,IAEzE,OAAO,GAAG,0BAA0B,YAAY,iBAAiB;AAAA,YACzD,sFAAsF;AAAA,kBAChF;AAAA,qBACG;AAAA;AAAA;AAAA,0BAGK;AAAA,uBACH;AAAA,uBACA,KAAK;AAAA,uBACL;AAAA;AAAA;AAAA,EAGrB;AAAA,EAEA,MAAM,WAAW,KAAK,KAAK,IAAI,CAAC,QAAQ,YAAY,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;AAAA,EACxE,MAAM,YAAY,KAAK,KACpB,IAAI,CAAC,QAAQ;AAAA,IACZ,MAAM,YAAY,YAAY,IAAI,IAAI;AAAA,IACtC,OAAO,GAAG,cAAc,cAAc,GAAG;AAAA,GAC1C,EACA,KAAK,IAAI;AAAA,EACZ,MAAM,YAAY,KAAK,KACpB,IAAI,CAAC,QAAQ;AAAA,IACZ,MAAM,UAAU,YAAY,IAAI,IAAI;AAAA,IACpC,OAAO,0BAA0B,SAAS,GAAG;AAAA,GAC9C,EACA,KAAK,IAAI;AAAA,EACZ,MAAM,eAAe,KAAK,KACvB,IAAI,CAAC,QAAQ;AAAA,IACZ,MAAM,YAAY,YAAY,IAAI,IAAI;AAAA,IACtC,OAAO,WAAW;AAAA,GACnB,EACA,KAAK,IAAI;AAAA,EACZ,MAAM,gBAAgB,KAAK,KAAK,IAAI,CAAC,QAAQ,cAAc,GAAG,CAAC,EAAE,KAAK,IAAI;AAAA,EAE1E,OAAO,GAAG,0BAA0B,mBAAmB;AAAA,aAC5C;AAAA,WACF;AAAA,mBACQ;AAAA;AAAA;AAAA,0BAGO;AAAA,uBACH;AAAA,uBACA,KAAK;AAAA,uBACL;AAAA;AAAA;AAAA;AAKvB,SAAS,aAAa,CAAC,KAAkB;AAAA,EACvC,MAAM,OAAO,IAAI;AAAA,EAEjB,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,QAAQ;AAAA,WACD;AAAA,WACA;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,WACA;AAAA,QACH,OAAO;AAAA;AAAA,QAEP,OAAO;AAAA;AAAA,EAEb;AAAA,EAEA,IAAI,KAAK,mBAAmB,KAAK,gBAAgB;AAAA,IAC/C,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IAEb,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,YAAY,cAAc,EAAE,MAAM,KAAK,SAAS,CAAC;AAAA,IACvD,OAAO,GAAG;AAAA,EACZ;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,MAAM,YAAY,cAAc,EAAE,MAAM,KAAK,KAAK,KAAK,CAAC;AAAA,IACxD,OAAO,GAAG;AAAA,EACZ;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,MAAM,SAAS,KAAK,MACjB,IACC,CAAC,UACC,GAAG,YAAY,MAAM,IAAI,MAAM,cAAc,EAAE,MAAM,MAAM,KAAK,CAAC,GACrE,EACC,KAAK,IAAI;AAAA,IACZ,OAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,SAAS,cAAc,EAAE,MAAM,KAAK,SAAS,GAAG,CAAC;AAAA,IACvD,MAAM,UAAU,cAAc,EAAE,MAAM,KAAK,SAAS,MAAM,CAAC;AAAA,IAC3D,OAAO,SAAS,qBAAqB;AAAA,EACvC;AAAA,EAEA,OAAO;AAAA;AAGT,SAAS,WAAW,CAAC,KAAqB;AAAA,EACxC,OAAO,IACJ,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC,EACxD,QAAQ,aAAa,CAAC,GAAG,WAAW,MAAM,EAC1C,QAAQ,UAAU,CAAC,GAAG,UAAU,KAAK,EACrC,QAAQ,MAAM,EAAE;AAAA;AAMrB,SAAS,yBAAyB,CAAC,SAAiB,SAAsB;AAAA,EACxE,MAAM,OAAO,QAAQ;AAAA,EAErB,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,QAAQ;AAAA,WACD;AAAA,QACH,OAAO,WAAW;AAAA,WACf;AAAA,QACH,OAAO,UAAU;AAAA,WACd;AAAA,QACH,OAAO,WAAW;AAAA,WACf;AAAA,WACA;AAAA,QACH,OAAO;AAAA,4CAC6B;AAAA;AAAA;AAAA;AAAA,gBAI5B;AAAA;AAAA;AAAA,0CAG0B;AAAA;AAAA;AAAA;AAAA,QAIlC,OAAO,GAAG;AAAA;AAAA,EAEhB;AAAA,EAEA,IAAI,KAAK,iBAAiB;AAAA,IACxB,OAAO,kBAAkB;AAAA,EAC3B;AAAA,EAEA,IAAI,KAAK,gBAAgB;AAAA,IACvB,OAAO,iBAAiB;AAAA,EAC1B;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IAEb,OAAO;AAAA,sBACW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiCpB;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,kBAAkB,0BAA0B,SAAS;AAAA,MACzD,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,IACD,OAAO,GAAG,8BAA8B,gBAAgB,QAAQ,SAAS,GAAG,SAAS;AAAA,EACvF;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,MAAM,kBAAkB,0BAA0B,QAAQ;AAAA,MACxD,MAAM,KAAK,KAAK;AAAA,IAClB,CAAC;AAAA,IACD,OAAO,WAAW,uBAAuB;AAAA,EAC3C;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,MAAM,SAAS,KAAK,MACjB,IAAI,CAAC,UAAe;AAAA,MACnB,MAAM,iBAAiB,YAAY,MAAM,IAAI;AAAA,MAC7C,MAAM,kBAAkB,0BACtB,GAAG,WAAW,kBACd,EAAE,MAAM,MAAM,KAAK,CACrB;AAAA,MACA,OAAO,IAAI,MAAM,UAAU;AAAA,KAC5B,EACA,KAAK,IAAI;AAAA,IACZ,OAAO,cAAc;AAAA,EACvB;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IAEjB,MAAM,eAAe,0BAA0B,GAAG,cAAc;AAAA,MAC9D,MAAM,KAAK,SAAS;AAAA,IACtB,CAAC;AAAA,IACD,MAAM,gBAAgB,0BAA0B,GAAG,eAAe;AAAA,MAChE,MAAM,KAAK,SAAS;AAAA,IACtB,CAAC;AAAA,IACD,OAAO,WAAW,mBAAmB,aAAa,QAAQ,GAAG,cAAc,GAAG,YAAY,iBAAiB,cAAc,QAAQ,GAAG,eAAe,GAAG,aAAa;AAAA,EACrK;AAAA,EAGA,OAAO,GAAG;AAAA;;;AD/RZ,SAAS,YAAW,CAAC,KAAqB;AAAA,EACxC,OAAO,IACJ,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC,EACxD,QAAQ,aAAa,CAAC,GAAG,WAAW,MAAM,EAC1C,QAAQ,UAAU,CAAC,GAAG,UAAU,KAAK,EACrC,QAAQ,MAAM,EAAE,EAChB,QAAQ,OAAO,KAAK;AAAA;AAMzB,SAAS,oBAAoB,CAAC,MAAsB;AAAA,EAClD,OAAO,aAAY,IAAI;AAAA;AAMzB,eAAe,qBAAqB,CAClC,YACA,cACkB;AAAA,EAClB,OAAO,SAAS,gBAAgB,WAAW,MAAM,GAAG;AAAA,EAEpD,IAAI;AAAA,IAEF,QAAQ,UAAU,QAAO,MAAa;AAAA,IACtC,MAAM,cAAc,MAAM,IAAG,SAAS,cAAc,OAAO;AAAA,IAG3D,MAAM,uBAAuB;AAAA,IAC7B,MAAM,gBAAgB,IAAI;AAAA,IAE1B,IAAI;AAAA,IACJ,QAAQ,QAAQ,qBAAqB,KAAK,WAAW,OAAO,MAAM;AAAA,MAChE,cAAc,IAAI,MAAM,EAAE;AAAA,IAC5B;AAAA,IAGA,IAAI,cAAc,IAAI,YAAY,GAAG;AAAA,MACnC,OAAO;AAAA,IACT;AAAA,IACA,OAAO,OAAO;AAAA,EAMhB,MAAM,yBAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAGA,IAAI,uBAAuB,KAAK,CAAC,YAAY,QAAQ,KAAK,YAAY,CAAC,GAAG;AAAA,IACxE,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,IAAI,gBAAgB,SAAS,OAAO,GAAG;AAAA,IACrC,OAAO;AAAA,EACT;AAAA,EAEA,OAAO;AAAA;AAMF,IAAM,WAAiD,CAC5D,UAAU,CAAC,MACR;AAAA,EACH,MAAM,eAAe,QAAQ,QAAQ;AAAA,EACrC,IAAI;AAAA,EAEJ,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,SAEH,gBAAe,CAAC,QAAyC;AAAA,MAC7D,IAAI;AAAA,QAEF,SAAS,MAAM,WAAW,YAAY;AAAA,QAGtC,MAAM,qBAAqB,OAAO,uBAAuB;AAAA,QACzD,MAAM,YAAY,CAAC;AAAA,QAEnB,YAAY,YAAY,QAAQ,oBAAoB;AAAA,UAClD,OAAO,GAAG,gBAAgB,WAAW,MAAM,GAAG;AAAA,UAG9C,IAAI,CAAE,MAAM,sBAAsB,YAAY,YAAY,GAAI;AAAA,YAC5D,IAAI,QAAQ,OAAO;AAAA,cACjB,QAAQ,IAAI,0CAA+B,YAAY;AAAA,YACzD;AAAA,YACA;AAAA,UACF;AAAA,UAGA,IAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,SAAS,YAAY,GAAG;AAAA,YAC9D;AAAA,UACF;AAAA,UACA,IAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,YAAY,GAAG;AAAA,YAC7D;AAAA,UACF;AAAA,UAGA,MAAM,gBAAgB,qBAAqB,YAAY;AAAA,UAIvD,UAAU,KAAK;AAAA,YACb,MAAM;AAAA,YACN,SAAS;AAAA,YACT;AAAA,YAEA,iBAAiB;AAAA,UACnB,CAAC;AAAA,QACH;AAAA,QAEA,IAAI,QAAQ,OAAO;AAAA,UACjB,QAAQ,IACN,sCAA2B,UAAU,+BACvC;AAAA,QACF;AAAA,QAEA,OAAO;AAAA,aACF;AAAA,UACH,WAAW,CAAC,GAAI,OAAO,aAAa,CAAC,GAAI,GAAG,SAAS;AAAA,QACvD;AAAA,QACA,OAAO,OAAO;AAAA,QACd,MAAM,MAAM;AAAA,QACZ,IAAI,QAAQ,OAAO;AAAA,UACjB,QAAQ,KACN,2DAAgD,IAAI,SACtD;AAAA,QACF;AAAA,QAEA,OAAO;AAAA;AAAA;AAAA,SAIL,SAAQ,CAAC,SAAyC;AAAA,MAEtD,MAAM,oBAAoB,QAAQ,UAAU,OAC1C,CAAC,aAAa,SAAS,UAAU,WAAW,UAC9C;AAAA,MAEA,IAAI,kBAAkB,WAAW,GAAG;AAAA,QAClC;AAAA,MACF;AAAA,MAEA,IAAI,QAAQ,OAAO;AAAA,QACjB,QAAQ,OAAO,MACb,6BAA6B,kBAAkB,2BACjD;AAAA,MACF;AAAA,MAGA,MAAM,gBAAgB,MAAM,0BAA0B,iBAAiB;AAAA,MAEvE,QAAQ,UAAU,aAAa;AAAA,QAC7B,MAAM,QAAQ,OAAO;AAAA,QACrB,SAAS;AAAA,QACT,MAAM;AAAA,MACR,CAAC;AAAA;AAAA,EAIL;AAAA;AAMF,eAAsB,kBAAkB,CACtC,QAAO,mBACW;AAAA,EAClB,IAAI;AAAA,IACF,QAAQ,UAAU,QAAO,MAAa;AAAA,IACtC,MAAM,IAAG,OAAO,KAAI;AAAA,IACpB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;;AErNX,SAAS,YAAW,CAAC,KAAqB;AAAA,EACxC,OAAO,IACJ,QAAQ,aAAa,CAAC,GAAG,WAAW,OAAO,YAAY,CAAC,EACxD,QAAQ,aAAa,CAAC,GAAG,WAAW,MAAM,EAC1C,QAAQ,UAAU,CAAC,GAAG,UAAU,KAAK,EACrC,QAAQ,MAAM,EAAE,EAChB,QAAQ,OAAO,KAAK;AAAA;AAMzB,SAAS,cAAa,CAAC,KAAkB;AAAA,EACvC,MAAM,OAAO,IAAI;AAAA,EAEjB,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,QAAQ;AAAA,WACD;AAAA,WACA;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,WACA;AAAA,QACH,OAAO;AAAA;AAAA,QAEP,OAAO;AAAA;AAAA,EAEb;AAAA,EAEA,IAAI,KAAK,mBAAmB,KAAK,gBAAgB;AAAA,IAC/C,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,YAAY,eAAc,EAAE,MAAM,KAAK,SAAS,CAAC;AAAA,IACvD,OAAO,GAAG;AAAA,EACZ;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,MAAM,YAAY,eAAc,EAAE,MAAM,KAAK,KAAK,KAAK,CAAC;AAAA,IACxD,OAAO,GAAG;AAAA,EACZ;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,MAAM,SAAS,KAAK,MACjB,IACC,CAAC,UACC,GAAG,aAAY,MAAM,IAAI,MAAM,eAAc,EAAE,MAAM,MAAM,KAAK,CAAC,GACrE,EACC,KAAK,IAAI;AAAA,IACZ,OAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,SAAS,eAAc,EAAE,MAAM,KAAK,SAAS,GAAG,CAAC;AAAA,IACvD,MAAM,UAAU,eAAc,EAAE,MAAM,KAAK,SAAS,MAAM,CAAC;AAAA,IAC3D,OAAO,SAAS,qBAAqB;AAAA,EACvC;AAAA,EAEA,OAAO;AAAA;AAMT,SAAS,qBAAqB,CAAC,MAA8B;AAAA,EAC3D,IAAI,KAAK,WAAW;AAAA,IAAG,OAAO;AAAA,EAE9B,MAAM,YAAY,KACf,IAAI,CAAC,QAAQ;AAAA,IACZ,MAAM,YAAY,aAAY,IAAI,IAAI;AAAA,IACtC,OAAO,GAAG,cAAc,eAAc,GAAG;AAAA,GAC1C,EACA,KAAK,IAAI;AAAA,EAEZ,OAAO,WAAW;AAAA;AAMpB,SAAS,mBAAmB,CAC1B,MACA,eACQ;AAAA,EACR,IAAI,KAAK,WAAW;AAAA,IAAG,OAAO;AAAA,EAE9B,OAAO,KACJ,IAAI,CAAC,QAAQ;AAAA,IACZ,MAAM,UAAU,QAAQ,aAAY,IAAI,IAAI;AAAA,IAC5C,OAAO,2BAA0B,SAAS,GAAG;AAAA,GAC9C,EACA,KAAK,IAAI;AAAA;AAMd,SAAS,0BAAyB,CAAC,SAAiB,SAAsB;AAAA,EACxE,MAAM,OAAO,QAAQ;AAAA,EAErB,IAAI,OAAO,SAAS,UAAU;AAAA,IAC5B,QAAQ;AAAA,WACD;AAAA,QACH,OAAO,WAAW;AAAA,WACf;AAAA,QACH,OAAO,UAAU;AAAA,WACd;AAAA,QACH,OAAO,WAAW;AAAA,WACf;AAAA,WACA;AAAA,QACH,OAAO;AAAA,4CAC6B;AAAA;AAAA;AAAA;AAAA,gBAI5B;AAAA;AAAA;AAAA,0CAG0B;AAAA;AAAA;AAAA;AAAA,QAIlC,OAAO,GAAG;AAAA;AAAA,EAEhB;AAAA,EAEA,IAAI,KAAK,iBAAiB;AAAA,IACxB,OAAO,kBAAkB;AAAA,EAC3B;AAAA,EAEA,IAAI,KAAK,gBAAgB;AAAA,IACvB,OAAO,iBAAiB;AAAA,EAC1B;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,OAAO;AAAA,sBACW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BpB;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,kBAAkB,2BAA0B,SAAS;AAAA,MACzD,MAAM,KAAK;AAAA,IACb,CAAC;AAAA,IACD,OAAO,GAAG,8BAA8B,gBAAgB,QAAQ,SAAS,GAAG,SAAS;AAAA,EACvF;AAAA,EAEA,IAAI,KAAK,MAAM;AAAA,IACb,MAAM,kBAAkB,2BAA0B,QAAQ;AAAA,MACxD,MAAM,KAAK,KAAK;AAAA,IAClB,CAAC;AAAA,IACD,OAAO,WAAW,uBAAuB;AAAA,EAC3C;AAAA,EAEA,IAAI,KAAK,OAAO;AAAA,IACd,MAAM,SAAS,KAAK,MACjB,IAAI,CAAC,UAAe;AAAA,MACnB,MAAM,iBAAiB,aAAY,MAAM,IAAI;AAAA,MAC7C,MAAM,kBAAkB,2BACtB,GAAG,WAAW,kBACd,EAAE,MAAM,MAAM,KAAK,CACrB;AAAA,MACA,OAAO,IAAI,MAAM,UAAU;AAAA,KAC5B,EACA,KAAK,IAAI;AAAA,IACZ,OAAO,cAAc;AAAA,EACvB;AAAA,EAEA,IAAI,KAAK,UAAU;AAAA,IACjB,MAAM,eAAe,2BAA0B,GAAG,cAAc;AAAA,MAC9D,MAAM,KAAK,SAAS;AAAA,IACtB,CAAC;AAAA,IACD,MAAM,gBAAgB,2BAA0B,GAAG,eAAe;AAAA,MAChE,MAAM,KAAK,SAAS;AAAA,IACtB,CAAC;AAAA,IACD,OAAO,WAAW,mBAAmB,aAAa,QAAQ,GAAG,cAAc,GAAG,YAAY,iBAAiB,cAAc,QAAQ,GAAG,eAAe,GAAG,aAAa;AAAA,EACrK;AAAA,EAEA,OAAO,GAAG;AAAA;AAMZ,SAAS,mBAAmB,CAC1B,UACA,SACQ;AAAA,EACR,QAAQ,KAAK,SAAS;AAAA,EACtB,MAAM,YAAY,IAAI,aAAa,CAAC;AAAA,EAEpC,MAAM,oBAAoB,UAAU,OAClC,CAAC,MACE,EAAE,WAAmB,eAAe,EAAE,WAAW,WACtD;AAAA,EAEA,IAAI,kBAAkB,WAAW,GAAG;AAAA,IAClC,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,oBAAoB,kBAAkB,OAC1C,CAAC,SAA0B;AAAA,IACzB,IACE,QAAQ,oBACR,CAAC,QAAQ,iBAAiB,SAAS,KAAK,IAAI,GAC5C;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA,IACE,QAAQ,oBACR,QAAQ,iBAAiB,SAAS,KAAK,IAAI,GAC3C;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,GAEX;AAAA,EAEA,IAAI,kBAAkB,WAAW,GAAG;AAAA,IAClC,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,kBAAkB,IAAI,CAAC,SAA0B;AAAA,IAC/D,MAAM,aAAa,aAAY,KAAK,IAAI;AAAA,IACxC,MAAM,gBAAgB,sBAAsB,KAAK,IAAI;AAAA,IACrD,MAAM,cAAc,oBAAoB,KAAK,MAAM,IAAI;AAAA,IAEvD,OAAO,SAAS,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,4BAKN,SAAS;AAAA,yBACZ,SAAS;AAAA,yBACT,KAAK;AAAA,yBACL;AAAA;AAAA;AAAA;AAAA;AAAA,GAKtB;AAAA,EAED,OAAO;AAAA,MACH,QAAQ,KAAK;AAAA;AAAA,KAAW;AAAA;AAAA;AAO9B,SAAS,oBAAoB,CAC3B,UACA,SACQ;AAAA,EACR,QAAQ,KAAK,SAAS;AAAA,EACtB,MAAM,YAAY,IAAI,aAAa,CAAC;AAAA,EAEpC,MAAM,kBAAkB,UAAU,OAChC,CAAC,MAAuB,EAAE,WAAW,QACvC;AAAA,EAEA,IAAI,gBAAgB,WAAW,GAAG;AAAA,IAChC,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,oBAAoB,gBAAgB,OAAO,CAAC,SAA0B;AAAA,IAC1E,IACE,QAAQ,oBACR,CAAC,QAAQ,iBAAiB,SAAS,KAAK,IAAI,GAC5C;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA,IACE,QAAQ,oBACR,QAAQ,iBAAiB,SAAS,KAAK,IAAI,GAC3C;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA,OAAO;AAAA,GACR;AAAA,EAED,IAAI,kBAAkB,WAAW,GAAG;AAAA,IAClC,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,kBAAkB,IAAI,CAAC,SAA0B;AAAA,IAC/D,MAAM,aAAa,aAAY,KAAK,IAAI;AAAA,IACxC,MAAM,gBAAgB,sBAAsB,KAAK,IAAI;AAAA,IACrD,MAAM,cAAc,oBAAoB,KAAK,MAAM,IAAI;AAAA,IAEvD,OAAO,SAAS,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAYN,SAAS;AAAA,yBACZ,SAAS;AAAA,yBACT,KAAK;AAAA,yBACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAOtB;AAAA,EAED,OAAO;AAAA,MACH,QAAQ,KAAK;AAAA;AAAA,KAAW;AAAA;AAAA;AAO9B,eAAsB,qBAAqB,CACzC,UACA,SACiB;AAAA,EACjB,MAAM,cAAc,oBAAoB,UAAU,OAAO;AAAA,EACzD,MAAM,eAAe,qBAAqB,UAAU,OAAO;AAAA,EAE3D,IAAI,CAAC,eAAe,CAAC,cAAc;AAAA,IACjC,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,UAAU,CAAC,aAAa,YAAY,EAAE,OAAO,OAAO;AAAA,EAC1D,OAAO,QAAQ,KAAK;AAAA;AAAA,CAAO;AAAA;;;AC1VtB,IAAM,UAA+C,CAAC,UAAU,CAAC,MAAM;AAAA,EAC5E,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,SAEH,SAAQ,CAAC,SAAyC;AAAA,MACtD,QAAQ,cAAc;AAAA,MAGtB,MAAM,oBAAoB,UAAU,OAAO,CAAC,aAAa;AAAA,QACvD,IAAI,QAAQ,WAAW,CAAC,QAAQ,QAAQ,SAAS,SAAS,IAAI,GAAG;AAAA,UAC/D,OAAO;AAAA,QACT;AAAA,QACA,IAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,SAAS,IAAI,GAAG;AAAA,UAC9D,OAAO;AAAA,QACT;AAAA,QACA,OAAO;AAAA,OACR;AAAA,MAED,IAAI,kBAAkB,WAAW,GAAG;AAAA,QAClC,IAAI,QAAQ,OAAO;AAAA,UACjB,QAAQ,OAAO,MAAM,yCAAyC;AAAA,QAChE;AAAA,QACA;AAAA,MACF;AAAA,MAEA,IAAI,QAAQ,OAAO;AAAA,QACjB,QAAQ,OAAO,MACb,qDAAqD,kBAAkB,kBACzE;AAAA,MACF;AAAA,MAGA,MAAM,kBAAkB,IAAI;AAAA,MAE5B,WAAW,YAAY,mBAAmB;AAAA,QACxC,MAAM,cAAc,MAAM,sBAAsB,UAAU,OAAO;AAAA,QACjE,IAAI,aAAa;AAAA,UACf,gBAAgB,IAAI,SAAS,MAAM,WAAW;AAAA,QAChD;AAAA,MACF;AAAA,MAGA,IAAI,gBAAgB,OAAO,GAAG;AAAA,QAC5B,MAAM,iBAAiB,QAAQ,QAAQ,IAAI,WAAW;AAAA,QACtD,IAAI,gBAAgB;AAAA,UAClB,IAAI,kBAAkB,mBAAmB,eAAe,OAAO;AAAA,UAG/D,YAAY,cAAc,gBAAgB,iBAAiB;AAAA,YACzD,kBAAkB,0BAChB,iBACA,cACA,WACF;AAAA,UACF;AAAA,UAEA,QAAQ,QAAQ,IAAI,aAAa;AAAA,eAC5B;AAAA,YACH,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA;AAAA,EAEJ;AAAA;AAMF,SAAS,kBAAkB,CAAC,SAAyB;AAAA,EAEnD,IACE,QAAQ,SAAS,2BAA2B,KAC5C,QAAQ,SAAS,kBAAkB,GACnC;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAGA,MAAM,0BACJ;AAAA,EACF,MAAM,QAAQ,QAAQ,MAAM,uBAAuB;AAAA,EAEnD,IAAI,OAAO;AAAA,IAET,MAAM,kBAAkB,MAAM,GAAG,KAAK;AAAA,IACtC,MAAM,aAAa,CAAC,6BAA6B,kBAAkB,EAChE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,SAAS,GAAG,CAAC,EAC9C,KAAK,IAAI;AAAA,IAEZ,IAAI,YAAY;AAAA,MACd,MAAM,gBAAgB,YAAY,oBAAoB;AAAA,MACtD,OAAO,QAAQ,QAAQ,yBAAyB,aAAa;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAMT,SAAS,yBAAyB,CAChC,SACA,cACA,aACQ;AAAA,EAER,MAAM,kBAAkB,IAAI,OAC1B,iBAAiB,iDACjB,GACF;AAAA,EAEA,OAAO,QAAQ,QAAQ,iBAAiB,CAAC,GAAG,iBAAiB;AAAA,IAE3D,MAAM,YAAY,aAAa,QAAQ,SAAS,EAAE;AAAA,IAGlD,MAAM,sBAAsB,YACzB,MAAM;AAAA,CAAI,EACV,IAAI,CAAC,SAAS;AAAA,MAEb,IAAI,KAAK,MAAM,+BAA+B,GAAG;AAAA,QAC/C,OAAO,KAAK;AAAA,MACd;AAAA,MACA,OAAO;AAAA,KACR,EACA,KAAK;AAAA,CAAI;AAAA,IAGZ,OAAO,GAAG;AAAA;AAAA,EAEZ;AAAA;AAAA,GAEC;AAAA;;ACnKH,mBAAS;AAKT,eAAsB,gBAAgB,GAAoB;AAAA,EACxD,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuFb,MAAM,YAAY,MAAM,QAAO,MAAM;AAAA,IACnC,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAAA,EAED,OAAO;AAAA;;;ACrGT,mBAAS;AAET,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB,CACxC,cAAwB,CAAC,GACR;AAAA,EAEjB,MAAM,kBAAkB,cAAc,OACpC,CAAC,aAAa,CAAC,YAAY,SAAS,QAAQ,CAC9C;AAAA,EAEA,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhB,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA,EAKf,MAAM,YAAY,gBACf,IAAI,CAAC,aAAa,oBAAoB,QAAQ,CAAC,EAC/C,OAAO,OAAO,EACd,KAAK;AAAA;AAAA,CAAM;AAAA,EAEd,MAAM,OAAO,GAAG;AAAA;AAAA,EAAc;AAAA;AAAA,EAAa;AAAA,EAE3C,MAAM,YAAY,MAAM,QAAO,MAAM;AAAA,IACnC,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,eAAe;AAAA,EACjB,CAAC;AAAA,EAED,OAAO;AAAA;AAGT,SAAS,mBAAmB,CAAC,UAA0B;AAAA,EACrD,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAmEJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAsCJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAsCJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SA2BJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAgSJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SA6CJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAcJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAcJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAcJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAwBJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAkEJ;AAAA,MACH,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAuDJ;AAAA,MACH,OAAO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",
|
|
20
|
+
"debugId": "944FF0A218B7401F64756E2164756E21",
|
|
21
|
+
"names": []
|
|
22
|
+
}
|