@secondlayer/cli 3.3.1 → 3.4.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.
@@ -1,5 +1,35 @@
1
1
  import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
12
+ var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
20
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
21
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
+ for (let key of __getOwnPropNames(mod))
23
+ if (!__hasOwnProp.call(to, key))
24
+ __defProp(to, key, {
25
+ get: __accessProp.bind(mod, key),
26
+ enumerable: true
27
+ });
28
+ if (canCache)
29
+ cache.set(mod, to);
30
+ return to;
31
+ };
32
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
33
  var __returnValue = (v) => v;
4
34
  function __exportSetter(name, newValue) {
5
35
  this[name] = __returnValue.bind(null, newValue);
@@ -14,6 +44,27 @@ var __export = (target, all) => {
14
44
  });
15
45
  };
16
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
+
49
+ // src/types/plugin.ts
50
+ function isClarinetContract(c) {
51
+ return "_clarinetSource" in c && c._clarinetSource === true;
52
+ }
53
+ function isDirectFileContract(c) {
54
+ return "_directFile" in c && c._directFile === true;
55
+ }
56
+
57
+ // src/utils/contract-id.ts
58
+ function parseContractId(contractId) {
59
+ const dotIndex = contractId.indexOf(".");
60
+ if (dotIndex === -1) {
61
+ throw new Error(`Invalid contract ID: "${contractId}" (expected "address.contractName")`);
62
+ }
63
+ return {
64
+ address: contractId.slice(0, dotIndex),
65
+ contractName: contractId.slice(dotIndex + 1)
66
+ };
67
+ }
17
68
 
18
69
  // src/utils/format.ts
19
70
  var exports_format = {};
@@ -73,29 +124,6 @@ import { isValidAddress as _validateStacksAddress } from "@secondlayer/stacks";
73
124
  import { getErrorMessage } from "@secondlayer/shared";
74
125
  import { toCamelCase } from "@secondlayer/stacks/clarity";
75
126
 
76
- // src/types/plugin.ts
77
- function isClarinetContract(c) {
78
- return "_clarinetSource" in c && c._clarinetSource === true;
79
- }
80
- function isDirectFileContract(c) {
81
- return "_directFile" in c && c._directFile === true;
82
- }
83
-
84
- // src/utils/contract-id.ts
85
- function parseContractId(contractId) {
86
- const dotIndex = contractId.indexOf(".");
87
- if (dotIndex === -1) {
88
- throw new Error(`Invalid contract ID: "${contractId}" (expected "address.contractName")`);
89
- }
90
- return {
91
- address: contractId.slice(0, dotIndex),
92
- contractName: contractId.slice(dotIndex + 1)
93
- };
94
- }
95
-
96
- // src/core/plugin-manager.ts
97
- var validateStacksAddress = _validateStacksAddress;
98
-
99
127
  class PluginManager {
100
128
  plugins = [];
101
129
  logger;
@@ -355,9 +383,15 @@ ${JSON.stringify(content, null, 2)}`;
355
383
  };
356
384
  }
357
385
  }
386
+ var validateStacksAddress;
387
+ var init_plugin_manager = __esm(() => {
388
+ validateStacksAddress = _validateStacksAddress;
389
+ });
390
+ init_plugin_manager();
391
+
358
392
  export {
359
393
  PluginManager
360
394
  };
361
395
 
362
- //# debugId=85ECC6D6BBFA69D064756E2164756E21
396
+ //# debugId=5FBC88459146F53D64756E2164756E21
363
397
  //# sourceMappingURL=plugin-manager.js.map
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/utils/format.ts", "../src/core/plugin-manager.ts", "../src/types/plugin.ts", "../src/utils/contract-id.ts"],
3
+ "sources": ["../src/types/plugin.ts", "../src/utils/contract-id.ts", "../src/utils/format.ts", "../src/core/plugin-manager.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * Shared code formatting utilities using Biome\n */\n\nimport { Biome, Distribution } from \"@biomejs/js-api\";\n\nlet biome: Biome | null = null;\n\n/**\n * Lazily initialize Biome singleton\n */\nasync function getBiome(): Promise<Biome> {\n\tif (!biome) {\n\t\tbiome = await Biome.create({\n\t\t\tdistribution: Distribution.NODE,\n\t\t});\n\n\t\tbiome.applyConfiguration({\n\t\t\tformatter: {\n\t\t\t\tenabled: true,\n\t\t\t\tindentStyle: \"tab\",\n\t\t\t\tlineWidth: 80,\n\t\t\t},\n\t\t\tjavascript: {\n\t\t\t\tformatter: {\n\t\t\t\t\tsemicolons: \"always\",\n\t\t\t\t\tquoteStyle: \"single\",\n\t\t\t\t},\n\t\t\t},\n\t\t\torganizeImports: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t\tlinter: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t\tassists: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t});\n\n\t\tbiome.registerProjectFolder();\n\t}\n\n\treturn biome;\n}\n\n/**\n * Format TypeScript code using Biome\n */\nexport async function formatCode(code: string): Promise<string> {\n\tconst b = await getBiome();\n\n\t// Use lintContent with SafeFixes to organize imports\n\tconst linted = b.lintContent(code, {\n\t\tfilePath: \"generated.ts\",\n\t\tfixFileMode: \"SafeFixes\",\n\t});\n\n\t// Then format\n\tconst formatted = b.formatContent(linted.content, {\n\t\tfilePath: \"generated.ts\",\n\t});\n\n\treturn formatted.content;\n}\n",
6
- "/**\n * Plugin Manager for @secondlayer/cli\n * Handles plugin registration, lifecycle execution, and output management\n */\n\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { isValidAddress as _validateStacksAddress } from \"@secondlayer/stacks\";\nconst validateStacksAddress = _validateStacksAddress as (\n\taddress: string,\n) => boolean;\nimport { getErrorMessage } from \"@secondlayer/shared\";\nimport { toCamelCase } from \"@secondlayer/stacks/clarity\";\nimport type {\n\tContractConfig,\n\tGenerateContext,\n\tGeneratedOutput,\n\tHookResult,\n\tLogger,\n\tPluginExecutionContext,\n\tPluginUtils,\n\tProcessedContract,\n\tResolvedConfig,\n\tSecondLayerPlugin,\n\tUserConfig,\n} from \"../types/plugin\";\nimport { isClarinetContract, isDirectFileContract } from \"../types/plugin\";\nimport { parseContractId } from \"../utils/contract-id\";\n\n/**\n * Core plugin manager that orchestrates plugin execution\n */\nexport class PluginManager {\n\tprivate plugins: SecondLayerPlugin[] = [];\n\tprivate logger: Logger;\n\tprivate utils: PluginUtils;\n\tprivate executionContext: PluginExecutionContext;\n\n\tconstructor() {\n\t\tthis.logger = this.createLogger();\n\t\tthis.utils = this.createUtils();\n\t\tthis.executionContext = {\n\t\t\tphase: \"config\",\n\t\t\tstartTime: Date.now(),\n\t\t\tresults: new Map(),\n\t\t};\n\t}\n\n\t/**\n\t * Register a plugin\n\t */\n\tregister(plugin: SecondLayerPlugin): void {\n\t\t// Validate plugin\n\t\tif (!plugin.name || !plugin.version) {\n\t\t\tthrow new Error(\"Plugin must have a name and version\");\n\t\t}\n\n\t\t// Check for duplicate plugin names\n\t\tconst existing = this.plugins.find((p) => p.name === plugin.name);\n\t\tif (existing) {\n\t\t\tthrow new Error(\n\t\t\t\t`Plugin \"${plugin.name}\" is already registered (version ${existing.version})`,\n\t\t\t);\n\t\t}\n\n\t\tthis.plugins.push(plugin);\n\t\tthis.logger.debug(`Registered plugin: ${plugin.name}@${plugin.version}`);\n\t}\n\n\t/**\n\t * Get all registered plugins\n\t */\n\tgetPlugins(): SecondLayerPlugin[] {\n\t\treturn [...this.plugins];\n\t}\n\n\t/**\n\t * Transform user config through all plugins\n\t */\n\tasync transformConfig(config: UserConfig): Promise<ResolvedConfig> {\n\t\tthis.executionContext.phase = \"config\";\n\t\tlet transformedConfig = { ...config };\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tif (plugin.transformConfig) {\n\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await plugin.transformConfig(transformedConfig);\n\t\t\t\t\ttransformedConfig = result;\n\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformConfig\", {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformConfig\", {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed during config transformation: ${getErrorMessage(error)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add plugins array to resolved config\n\t\tconst resolvedConfig: ResolvedConfig = {\n\t\t\t...transformedConfig,\n\t\t\tplugins: this.plugins,\n\t\t};\n\n\t\treturn resolvedConfig;\n\t}\n\n\t/**\n\t * Transform contracts through all plugins\n\t */\n\tasync transformContracts(\n\t\tcontracts: ContractConfig[],\n\t\t_config: ResolvedConfig,\n\t): Promise<ProcessedContract[]> {\n\t\tconst processedContracts: ProcessedContract[] = [];\n\n\t\tfor (let contract of contracts) {\n\t\t\tif (isClarinetContract(contract) && contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"clarinet\"));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectFileContract(contract) && contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"direct\"));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Transform through each plugin\n\t\t\tfor (const plugin of this.plugins) {\n\t\t\t\tif (plugin.transformContract) {\n\t\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcontract = await plugin.transformContract(contract);\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformContract\", {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformContract\", {\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.logger.warn(\n\t\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed to transform contract: ${getErrorMessage(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"api\"));\n\t\t\t}\n\t\t}\n\n\t\treturn processedContracts;\n\t}\n\n\t/**\n\t * Execute lifecycle hooks\n\t */\n\tasync executeHook(\n\t\thookName: keyof SecondLayerPlugin,\n\t\tcontext: any,\n\t): Promise<void> {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst hook = plugin[hookName];\n\t\t\tif (typeof hook === \"function\") {\n\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\ttry {\n\t\t\t\t\tawait (hook as any).call(plugin, context);\n\t\t\t\t\tthis.recordHookResult(plugin.name, hookName as string, {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordHookResult(plugin.name, hookName as string, {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t});\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed during ${hookName as string}: ${getErrorMessage(error)}`,\n\t\t\t\t\t);\n\t\t\t\t\t// Don't throw - allow other plugins to continue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Execute generation phase with full context\n\t */\n\tasync executeGeneration(\n\t\tcontracts: ProcessedContract[],\n\t\tconfig: ResolvedConfig,\n\t): Promise<Map<string, GeneratedOutput>> {\n\t\tthis.executionContext.phase = \"generate\";\n\t\tconst outputs = new Map<string, GeneratedOutput>();\n\n\t\t// Create generation context\n\t\tconst context: GenerateContext = {\n\t\t\tconfig,\n\t\t\tlogger: this.logger,\n\t\t\tutils: this.utils,\n\t\t\tcontracts,\n\t\t\toutputs,\n\t\t\taugment: (outputKey: string, contractName: string, content: any) => {\n\t\t\t\tthis.augmentOutput(outputs, outputKey, contractName, content);\n\t\t\t},\n\t\t\taddOutput: (key: string, output: GeneratedOutput) => {\n\t\t\t\toutputs.set(key, output);\n\t\t\t},\n\t\t};\n\n\t\t// Execute beforeGenerate hooks\n\t\tawait this.executeHook(\"beforeGenerate\", context);\n\n\t\t// Execute generate hooks\n\t\tawait this.executeHook(\"generate\", context);\n\n\t\t// Execute afterGenerate hooks\n\t\tawait this.executeHook(\"afterGenerate\", context);\n\n\t\treturn outputs;\n\t}\n\n\t/**\n\t * Transform outputs through plugins\n\t */\n\tasync transformOutputs(\n\t\toutputs: Map<string, GeneratedOutput>,\n\t): Promise<Map<string, GeneratedOutput>> {\n\t\tthis.executionContext.phase = \"output\";\n\t\tconst transformedOutputs = new Map<string, GeneratedOutput>();\n\n\t\tfor (const [key, output] of outputs) {\n\t\t\tlet transformedContent = output.content;\n\n\t\t\tfor (const plugin of this.plugins) {\n\t\t\t\tif (plugin.transformOutput) {\n\t\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttransformedContent = await plugin.transformOutput(\n\t\t\t\t\t\t\ttransformedContent,\n\t\t\t\t\t\t\toutput.type || \"other\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformOutput\", {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformOutput\", {\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.logger.warn(\n\t\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed to transform output: ${getErrorMessage(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttransformedOutputs.set(key, {\n\t\t\t\t...output,\n\t\t\t\tcontent: transformedContent,\n\t\t\t});\n\t\t}\n\n\t\treturn transformedOutputs;\n\t}\n\n\t/**\n\t * Write outputs to disk\n\t */\n\tasync writeOutputs(outputs: Map<string, GeneratedOutput>): Promise<void> {\n\t\tfor (const [, output] of outputs) {\n\t\t\ttry {\n\t\t\t\tconst resolvedPath = path.resolve(process.cwd(), output.path);\n\t\t\t\tawait this.utils.ensureDir(path.dirname(resolvedPath));\n\t\t\t\tawait this.utils.writeFile(resolvedPath, output.content);\n\t\t\t\t// Don't log here - let the main command handle success messaging\n\t\t\t} catch (error) {\n\t\t\t\tthis.logger.error(\n\t\t\t\t\t`Failed to write ${output.path}: ${getErrorMessage(error)}`,\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get execution results for debugging\n\t */\n\tgetExecutionResults(): Map<string, HookResult[]> {\n\t\treturn new Map(this.executionContext.results);\n\t}\n\n\t/**\n\t * Convert a contract config with an ABI into a ProcessedContract\n\t */\n\tprivate contractToProcessed(\n\t\tcontract: ContractConfig,\n\t\tsource: string,\n\t): ProcessedContract {\n\t\tconst address =\n\t\t\ttypeof contract.address === \"string\" ? contract.address : \"\";\n\t\tconst parsed = parseContractId(address);\n\t\treturn {\n\t\t\tname: contract.name || parsed.contractName || \"unknown\",\n\t\t\taddress: parsed.address || \"unknown\",\n\t\t\tcontractName: parsed.contractName || contract.name || \"unknown\",\n\t\t\tabi: contract.abi!,\n\t\t\tsource: source === \"api\" ? (\"api\" as const) : (\"local\" as const),\n\t\t\tmetadata: contract.metadata ?? { source },\n\t\t};\n\t}\n\n\t/**\n\t * Augment existing output with additional content\n\t */\n\tprivate augmentOutput(\n\t\toutputs: Map<string, GeneratedOutput>,\n\t\toutputKey: string,\n\t\tcontractName: string,\n\t\tcontent: any,\n\t): void {\n\t\tconst existing = outputs.get(outputKey);\n\t\tif (!existing) {\n\t\t\tthis.logger.warn(`Cannot augment non-existent output: ${outputKey}`);\n\t\t\treturn;\n\t\t}\n\n\t\t// Simple augmentation - append content\n\t\t// In a real implementation, this would be more sophisticated\n\t\tconst augmentedContent = `${existing.content}\\n\\n// Augmented by plugin for ${contractName}\\n${JSON.stringify(content, null, 2)}`;\n\n\t\toutputs.set(outputKey, {\n\t\t\t...existing,\n\t\t\tcontent: augmentedContent,\n\t\t});\n\t}\n\n\t/**\n\t * Record hook execution result\n\t */\n\tprivate recordHookResult(\n\t\tpluginName: string,\n\t\thookName: string,\n\t\tresult: Omit<HookResult, \"plugin\">,\n\t): void {\n\t\tconst key = `${pluginName}:${hookName}`;\n\t\tconst existing = this.executionContext.results.get(key) || [];\n\t\texisting.push({ ...result, plugin: pluginName });\n\t\tthis.executionContext.results.set(key, existing);\n\t}\n\n\t/**\n\t * Create logger instance\n\t */\n\tprivate createLogger(): Logger {\n\t\treturn {\n\t\t\tinfo: (message: string) => console.log(`ℹ️ ${message}`),\n\t\t\twarn: (message: string) => console.warn(`⚠️ ${message}`),\n\t\t\terror: (message: string) => console.error(`❌ ${message}`),\n\t\t\tdebug: (message: string) => {\n\t\t\t\tif (process.env.DEBUG) {\n\t\t\t\t\tconsole.log(`🐛 ${message}`);\n\t\t\t\t}\n\t\t\t},\n\t\t\tsuccess: (message: string) => console.log(`✅ ${message}`),\n\t\t};\n\t}\n\n\t/**\n\t * Create utils instance\n\t */\n\tprivate createUtils(): PluginUtils {\n\t\treturn {\n\t\t\ttoCamelCase,\n\n\t\t\ttoKebabCase: (str: string) => {\n\t\t\t\treturn str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\t\t\t},\n\n\t\t\tvalidateAddress: (address: string) => {\n\t\t\t\treturn validateStacksAddress(parseContractId(address).address);\n\t\t\t},\n\n\t\t\tparseContractId: (contractId: string) => {\n\t\t\t\treturn parseContractId(contractId);\n\t\t\t},\n\n\t\t\tformatCode: async (code: string) => {\n\t\t\t\tconst { formatCode } = await import(\"../utils/format\");\n\t\t\t\treturn formatCode(code);\n\t\t\t},\n\n\t\t\tresolvePath: (relativePath: string) => {\n\t\t\t\treturn path.resolve(process.cwd(), relativePath);\n\t\t\t},\n\n\t\t\tfileExists: async (filePath: string) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.access(filePath);\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\treadFile: async (filePath: string) => {\n\t\t\t\treturn fs.readFile(filePath, \"utf-8\");\n\t\t\t},\n\n\t\t\twriteFile: async (filePath: string, content: string) => {\n\t\t\t\tawait fs.writeFile(filePath, content, \"utf-8\");\n\t\t\t},\n\n\t\t\tensureDir: async (dirPath: string) => {\n\t\t\t\tawait fs.mkdir(dirPath, { recursive: true });\n\t\t\t},\n\t\t};\n\t}\n}\n",
7
5
  "/**\n * Plugin system types for @secondlayer/cli\n */\n\nimport type { AbiContract } from \"@secondlayer/stacks/clarity\";\nimport type {\n\tNetworkName,\n\tResolvedContract,\n\tSecondLayerConfig,\n} from \"./config\";\n\n/**\n * Core plugin interface that all plugins must implement\n */\nexport interface SecondLayerPlugin {\n\t/** Plugin name (should be unique) */\n\tname: string;\n\n\t/** Plugin version */\n\tversion: string;\n\n\t// Lifecycle hooks\n\t/** Called after config is resolved but before generation starts */\n\tconfigResolved?: (config: ResolvedConfig) => void | Promise<void>;\n\n\t/** Called before generation starts */\n\tbeforeGenerate?: (context: GenerateContext) => void | Promise<void>;\n\n\t/** Called during generation phase - plugins can add their own outputs */\n\tgenerate?: (context: GenerateContext) => void | Promise<void>;\n\n\t/** Called after all generation is complete */\n\tafterGenerate?: (context: GenerateContext) => void | Promise<void>;\n\n\t// Transform hooks\n\t/** Transform user config before resolution */\n\ttransformConfig?: (config: UserConfig) => UserConfig | Promise<UserConfig>;\n\n\t/** Transform individual contracts during processing */\n\ttransformContract?: (\n\t\tcontract: ContractConfig,\n\t) => ContractConfig | Promise<ContractConfig>;\n\n\t/** Transform generated output before writing to disk */\n\ttransformOutput?: (\n\t\toutput: string,\n\t\ttype: OutputType,\n\t) => string | Promise<string>;\n}\n\n/**\n * User configuration (before plugin transformations)\n */\nexport type UserConfig = SecondLayerConfig;\n\n/**\n * Resolved configuration (after plugin transformations)\n */\nexport interface ResolvedConfig extends SecondLayerConfig {\n\t/** Resolved plugins array */\n\tplugins: SecondLayerPlugin[];\n}\n\n/**\n * Contract configuration that can be transformed by plugins\n */\nexport interface ContractConfig {\n\tname?: string;\n\taddress?: string | Partial<Record<NetworkName, string>>;\n\tsource?: string;\n\tabi?: AbiContract;\n\tmetadata?: Record<string, any>;\n}\n\n/**\n * Contract config from Clarinet plugin\n */\nexport interface ClarinetContractConfig extends ContractConfig {\n\t_clarinetSource: true;\n}\n\n/**\n * Contract config from direct file input\n */\nexport interface DirectFileContractConfig extends ContractConfig {\n\t_directFile: true;\n}\n\n/**\n * Union of all contract config types\n */\nexport type PluginContractConfig =\n\t| ContractConfig\n\t| ClarinetContractConfig\n\t| DirectFileContractConfig;\n\n/**\n * Type guard for Clarinet contracts\n */\nexport function isClarinetContract(\n\tc: ContractConfig,\n): c is ClarinetContractConfig {\n\treturn \"_clarinetSource\" in c && c._clarinetSource === true;\n}\n\n/**\n * Type guard for direct file contracts\n */\nexport function isDirectFileContract(\n\tc: ContractConfig,\n): c is DirectFileContractConfig {\n\treturn \"_directFile\" in c && c._directFile === true;\n}\n\n/**\n * Processed contract with resolved ABI and metadata\n */\nexport interface ProcessedContract extends ResolvedContract {\n\t/** Additional metadata added by plugins */\n\tmetadata?: Record<string, any>;\n}\n\n/**\n * Generated output from plugins\n */\nexport interface GeneratedOutput {\n\t/** File path where output should be written */\n\tpath: string;\n\n\t/** Generated content */\n\tcontent: string;\n\n\t/** Output type for transformation hooks */\n\ttype?: OutputType;\n\n\t/** Whether this output should overwrite existing files */\n\toverwrite?: boolean;\n}\n\n/**\n * Types of outputs that can be generated\n */\nexport type OutputType =\n\t| \"contracts\"\n\t| \"hooks\"\n\t| \"actions\"\n\t| \"types\"\n\t| \"utils\"\n\t| \"config\"\n\t| \"other\";\n\n/**\n * Base context available to all plugin hooks\n */\nexport interface PluginContext {\n\t/** Resolved configuration */\n\tconfig: ResolvedConfig;\n\n\t/** Logger for plugin output */\n\tlogger: Logger;\n\n\t/** Utility functions for plugins */\n\tutils: PluginUtils;\n}\n\n/**\n * Context available during generation phase\n */\nexport interface GenerateContext extends PluginContext {\n\t/** Processed contracts ready for generation */\n\tcontracts: ProcessedContract[];\n\n\t/** Map of output keys to generated content */\n\toutputs: Map<string, GeneratedOutput>;\n\n\t/** Function to augment existing outputs */\n\taugment: (outputKey: string, contractName: string, content: any) => void;\n\n\t/** Function to add new outputs */\n\taddOutput: (key: string, output: GeneratedOutput) => void;\n}\n\n/**\n * Logger interface for plugin output\n */\nexport interface Logger {\n\tinfo: (message: string) => void;\n\twarn: (message: string) => void;\n\terror: (message: string) => void;\n\tdebug: (message: string) => void;\n\tsuccess: (message: string) => void;\n}\n\n/**\n * Utility functions available to plugins\n */\nexport interface PluginUtils {\n\t/** Convert kebab-case to camelCase */\n\ttoCamelCase: (str: string) => string;\n\n\t/** Convert camelCase to kebab-case */\n\ttoKebabCase: (str: string) => string;\n\n\t/** Validate Stacks address format */\n\tvalidateAddress: (address: string) => boolean;\n\n\t/** Parse contract identifier (address.contract-name) */\n\tparseContractId: (contractId: string) => {\n\t\taddress: string;\n\t\tcontractName: string;\n\t};\n\n\t/** Format TypeScript code using prettier */\n\tformatCode: (code: string) => Promise<string>;\n\n\t/** Resolve file path relative to project root */\n\tresolvePath: (relativePath: string) => string;\n\n\t/** Check if file exists */\n\tfileExists: (path: string) => Promise<boolean>;\n\n\t/** Read file content */\n\treadFile: (path: string) => Promise<string>;\n\n\t/** Write file content */\n\twriteFile: (path: string, content: string) => Promise<void>;\n\n\t/** Create directory recursively */\n\tensureDir: (path: string) => Promise<void>;\n}\n\n/**\n * Plugin factory function type for creating plugins with options\n */\nexport type PluginFactory<TOptions = any> = (\n\toptions?: TOptions,\n) => SecondLayerPlugin;\n\n/**\n * Plugin options base interface\n */\nexport interface PluginOptions {\n\t/** Include only specific contracts/functions */\n\tinclude?: string[];\n\n\t/** Exclude specific contracts/functions */\n\texclude?: string[];\n\n\t/** Enable debug output */\n\tdebug?: boolean;\n}\n\n/**\n * Hook execution result\n */\nexport interface HookResult<T = any> {\n\t/** Whether the hook was successful */\n\tsuccess: boolean;\n\n\t/** Result data from the hook */\n\tdata?: T;\n\n\t/** Error if hook failed */\n\terror?: Error;\n\n\t/** Plugin that executed the hook */\n\tplugin: string;\n}\n\n/**\n * Plugin execution context for internal use\n */\nexport interface PluginExecutionContext {\n\t/** Current plugin being executed */\n\tcurrentPlugin?: SecondLayerPlugin;\n\n\t/** Execution phase */\n\tphase: \"config\" | \"generate\" | \"output\";\n\n\t/** Start time for performance tracking */\n\tstartTime: number;\n\n\t/** Plugin execution results */\n\tresults: Map<string, HookResult[]>;\n}\n",
8
- "/**\n * Parse a fully-qualified contract ID (\"address.contractName\") into its parts.\n * Throws if the input doesn't contain a dot separator.\n */\nexport function parseContractId(contractId: string): {\n\taddress: string;\n\tcontractName: string;\n} {\n\tconst dotIndex = contractId.indexOf(\".\");\n\tif (dotIndex === -1) {\n\t\tthrow new Error(\n\t\t\t`Invalid contract ID: \"${contractId}\" (expected \"address.contractName\")`,\n\t\t);\n\t}\n\treturn {\n\t\taddress: contractId.slice(0, dotIndex),\n\t\tcontractName: contractId.slice(dotIndex + 1),\n\t};\n}\n"
6
+ "/**\n * Parse a fully-qualified contract ID (\"address.contractName\") into its parts.\n * Throws if the input doesn't contain a dot separator.\n */\nexport function parseContractId(contractId: string): {\n\taddress: string;\n\tcontractName: string;\n} {\n\tconst dotIndex = contractId.indexOf(\".\");\n\tif (dotIndex === -1) {\n\t\tthrow new Error(\n\t\t\t`Invalid contract ID: \"${contractId}\" (expected \"address.contractName\")`,\n\t\t);\n\t}\n\treturn {\n\t\taddress: contractId.slice(0, dotIndex),\n\t\tcontractName: contractId.slice(dotIndex + 1),\n\t};\n}\n",
7
+ "/**\n * Shared code formatting utilities using Biome\n */\n\nimport { Biome, Distribution } from \"@biomejs/js-api\";\n\nlet biome: Biome | null = null;\n\n/**\n * Lazily initialize Biome singleton\n */\nasync function getBiome(): Promise<Biome> {\n\tif (!biome) {\n\t\tbiome = await Biome.create({\n\t\t\tdistribution: Distribution.NODE,\n\t\t});\n\n\t\tbiome.applyConfiguration({\n\t\t\tformatter: {\n\t\t\t\tenabled: true,\n\t\t\t\tindentStyle: \"tab\",\n\t\t\t\tlineWidth: 80,\n\t\t\t},\n\t\t\tjavascript: {\n\t\t\t\tformatter: {\n\t\t\t\t\tsemicolons: \"always\",\n\t\t\t\t\tquoteStyle: \"single\",\n\t\t\t\t},\n\t\t\t},\n\t\t\torganizeImports: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t\tlinter: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t\tassists: {\n\t\t\t\tenabled: true,\n\t\t\t},\n\t\t});\n\n\t\tbiome.registerProjectFolder();\n\t}\n\n\treturn biome;\n}\n\n/**\n * Format TypeScript code using Biome\n */\nexport async function formatCode(code: string): Promise<string> {\n\tconst b = await getBiome();\n\n\t// Use lintContent with SafeFixes to organize imports\n\tconst linted = b.lintContent(code, {\n\t\tfilePath: \"generated.ts\",\n\t\tfixFileMode: \"SafeFixes\",\n\t});\n\n\t// Then format\n\tconst formatted = b.formatContent(linted.content, {\n\t\tfilePath: \"generated.ts\",\n\t});\n\n\treturn formatted.content;\n}\n",
8
+ "/**\n * Plugin Manager for @secondlayer/cli\n * Handles plugin registration, lifecycle execution, and output management\n */\n\nimport { promises as fs } from \"fs\";\nimport path from \"path\";\nimport { isValidAddress as _validateStacksAddress } from \"@secondlayer/stacks\";\nconst validateStacksAddress = _validateStacksAddress as (\n\taddress: string,\n) => boolean;\nimport { getErrorMessage } from \"@secondlayer/shared\";\nimport { toCamelCase } from \"@secondlayer/stacks/clarity\";\nimport type {\n\tContractConfig,\n\tGenerateContext,\n\tGeneratedOutput,\n\tHookResult,\n\tLogger,\n\tPluginExecutionContext,\n\tPluginUtils,\n\tProcessedContract,\n\tResolvedConfig,\n\tSecondLayerPlugin,\n\tUserConfig,\n} from \"../types/plugin\";\nimport { isClarinetContract, isDirectFileContract } from \"../types/plugin\";\nimport { parseContractId } from \"../utils/contract-id\";\n\n/**\n * Core plugin manager that orchestrates plugin execution\n */\nexport class PluginManager {\n\tprivate plugins: SecondLayerPlugin[] = [];\n\tprivate logger: Logger;\n\tprivate utils: PluginUtils;\n\tprivate executionContext: PluginExecutionContext;\n\n\tconstructor() {\n\t\tthis.logger = this.createLogger();\n\t\tthis.utils = this.createUtils();\n\t\tthis.executionContext = {\n\t\t\tphase: \"config\",\n\t\t\tstartTime: Date.now(),\n\t\t\tresults: new Map(),\n\t\t};\n\t}\n\n\t/**\n\t * Register a plugin\n\t */\n\tregister(plugin: SecondLayerPlugin): void {\n\t\t// Validate plugin\n\t\tif (!plugin.name || !plugin.version) {\n\t\t\tthrow new Error(\"Plugin must have a name and version\");\n\t\t}\n\n\t\t// Check for duplicate plugin names\n\t\tconst existing = this.plugins.find((p) => p.name === plugin.name);\n\t\tif (existing) {\n\t\t\tthrow new Error(\n\t\t\t\t`Plugin \"${plugin.name}\" is already registered (version ${existing.version})`,\n\t\t\t);\n\t\t}\n\n\t\tthis.plugins.push(plugin);\n\t\tthis.logger.debug(`Registered plugin: ${plugin.name}@${plugin.version}`);\n\t}\n\n\t/**\n\t * Get all registered plugins\n\t */\n\tgetPlugins(): SecondLayerPlugin[] {\n\t\treturn [...this.plugins];\n\t}\n\n\t/**\n\t * Transform user config through all plugins\n\t */\n\tasync transformConfig(config: UserConfig): Promise<ResolvedConfig> {\n\t\tthis.executionContext.phase = \"config\";\n\t\tlet transformedConfig = { ...config };\n\n\t\tfor (const plugin of this.plugins) {\n\t\t\tif (plugin.transformConfig) {\n\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await plugin.transformConfig(transformedConfig);\n\t\t\t\t\ttransformedConfig = result;\n\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformConfig\", {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformConfig\", {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t});\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed during config transformation: ${getErrorMessage(error)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add plugins array to resolved config\n\t\tconst resolvedConfig: ResolvedConfig = {\n\t\t\t...transformedConfig,\n\t\t\tplugins: this.plugins,\n\t\t};\n\n\t\treturn resolvedConfig;\n\t}\n\n\t/**\n\t * Transform contracts through all plugins\n\t */\n\tasync transformContracts(\n\t\tcontracts: ContractConfig[],\n\t\t_config: ResolvedConfig,\n\t): Promise<ProcessedContract[]> {\n\t\tconst processedContracts: ProcessedContract[] = [];\n\n\t\tfor (let contract of contracts) {\n\t\t\tif (isClarinetContract(contract) && contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"clarinet\"));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isDirectFileContract(contract) && contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"direct\"));\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Transform through each plugin\n\t\t\tfor (const plugin of this.plugins) {\n\t\t\t\tif (plugin.transformContract) {\n\t\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tcontract = await plugin.transformContract(contract);\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformContract\", {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformContract\", {\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.logger.warn(\n\t\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed to transform contract: ${getErrorMessage(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (contract.abi) {\n\t\t\t\tprocessedContracts.push(this.contractToProcessed(contract, \"api\"));\n\t\t\t}\n\t\t}\n\n\t\treturn processedContracts;\n\t}\n\n\t/**\n\t * Execute lifecycle hooks\n\t */\n\tasync executeHook(\n\t\thookName: keyof SecondLayerPlugin,\n\t\tcontext: any,\n\t): Promise<void> {\n\t\tfor (const plugin of this.plugins) {\n\t\t\tconst hook = plugin[hookName];\n\t\t\tif (typeof hook === \"function\") {\n\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\ttry {\n\t\t\t\t\tawait (hook as any).call(plugin, context);\n\t\t\t\t\tthis.recordHookResult(plugin.name, hookName as string, {\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordHookResult(plugin.name, hookName as string, {\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\terror:\n\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t});\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed during ${hookName as string}: ${getErrorMessage(error)}`,\n\t\t\t\t\t);\n\t\t\t\t\t// Don't throw - allow other plugins to continue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Execute generation phase with full context\n\t */\n\tasync executeGeneration(\n\t\tcontracts: ProcessedContract[],\n\t\tconfig: ResolvedConfig,\n\t): Promise<Map<string, GeneratedOutput>> {\n\t\tthis.executionContext.phase = \"generate\";\n\t\tconst outputs = new Map<string, GeneratedOutput>();\n\n\t\t// Create generation context\n\t\tconst context: GenerateContext = {\n\t\t\tconfig,\n\t\t\tlogger: this.logger,\n\t\t\tutils: this.utils,\n\t\t\tcontracts,\n\t\t\toutputs,\n\t\t\taugment: (outputKey: string, contractName: string, content: any) => {\n\t\t\t\tthis.augmentOutput(outputs, outputKey, contractName, content);\n\t\t\t},\n\t\t\taddOutput: (key: string, output: GeneratedOutput) => {\n\t\t\t\toutputs.set(key, output);\n\t\t\t},\n\t\t};\n\n\t\t// Execute beforeGenerate hooks\n\t\tawait this.executeHook(\"beforeGenerate\", context);\n\n\t\t// Execute generate hooks\n\t\tawait this.executeHook(\"generate\", context);\n\n\t\t// Execute afterGenerate hooks\n\t\tawait this.executeHook(\"afterGenerate\", context);\n\n\t\treturn outputs;\n\t}\n\n\t/**\n\t * Transform outputs through plugins\n\t */\n\tasync transformOutputs(\n\t\toutputs: Map<string, GeneratedOutput>,\n\t): Promise<Map<string, GeneratedOutput>> {\n\t\tthis.executionContext.phase = \"output\";\n\t\tconst transformedOutputs = new Map<string, GeneratedOutput>();\n\n\t\tfor (const [key, output] of outputs) {\n\t\t\tlet transformedContent = output.content;\n\n\t\t\tfor (const plugin of this.plugins) {\n\t\t\t\tif (plugin.transformOutput) {\n\t\t\t\t\tthis.executionContext.currentPlugin = plugin;\n\t\t\t\t\ttry {\n\t\t\t\t\t\ttransformedContent = await plugin.transformOutput(\n\t\t\t\t\t\t\ttransformedContent,\n\t\t\t\t\t\t\toutput.type || \"other\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformOutput\", {\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.recordHookResult(plugin.name, \"transformOutput\", {\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\terror:\n\t\t\t\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: new Error(getErrorMessage(error)),\n\t\t\t\t\t\t});\n\t\t\t\t\t\tthis.logger.warn(\n\t\t\t\t\t\t\t`Plugin \"${plugin.name}\" failed to transform output: ${getErrorMessage(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttransformedOutputs.set(key, {\n\t\t\t\t...output,\n\t\t\t\tcontent: transformedContent,\n\t\t\t});\n\t\t}\n\n\t\treturn transformedOutputs;\n\t}\n\n\t/**\n\t * Write outputs to disk\n\t */\n\tasync writeOutputs(outputs: Map<string, GeneratedOutput>): Promise<void> {\n\t\tfor (const [, output] of outputs) {\n\t\t\ttry {\n\t\t\t\tconst resolvedPath = path.resolve(process.cwd(), output.path);\n\t\t\t\tawait this.utils.ensureDir(path.dirname(resolvedPath));\n\t\t\t\tawait this.utils.writeFile(resolvedPath, output.content);\n\t\t\t\t// Don't log here - let the main command handle success messaging\n\t\t\t} catch (error) {\n\t\t\t\tthis.logger.error(\n\t\t\t\t\t`Failed to write ${output.path}: ${getErrorMessage(error)}`,\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get execution results for debugging\n\t */\n\tgetExecutionResults(): Map<string, HookResult[]> {\n\t\treturn new Map(this.executionContext.results);\n\t}\n\n\t/**\n\t * Convert a contract config with an ABI into a ProcessedContract\n\t */\n\tprivate contractToProcessed(\n\t\tcontract: ContractConfig,\n\t\tsource: string,\n\t): ProcessedContract {\n\t\tconst address =\n\t\t\ttypeof contract.address === \"string\" ? contract.address : \"\";\n\t\tconst parsed = parseContractId(address);\n\t\treturn {\n\t\t\tname: contract.name || parsed.contractName || \"unknown\",\n\t\t\taddress: parsed.address || \"unknown\",\n\t\t\tcontractName: parsed.contractName || contract.name || \"unknown\",\n\t\t\tabi: contract.abi!,\n\t\t\tsource: source === \"api\" ? (\"api\" as const) : (\"local\" as const),\n\t\t\tmetadata: contract.metadata ?? { source },\n\t\t};\n\t}\n\n\t/**\n\t * Augment existing output with additional content\n\t */\n\tprivate augmentOutput(\n\t\toutputs: Map<string, GeneratedOutput>,\n\t\toutputKey: string,\n\t\tcontractName: string,\n\t\tcontent: any,\n\t): void {\n\t\tconst existing = outputs.get(outputKey);\n\t\tif (!existing) {\n\t\t\tthis.logger.warn(`Cannot augment non-existent output: ${outputKey}`);\n\t\t\treturn;\n\t\t}\n\n\t\t// Simple augmentation - append content\n\t\t// In a real implementation, this would be more sophisticated\n\t\tconst augmentedContent = `${existing.content}\\n\\n// Augmented by plugin for ${contractName}\\n${JSON.stringify(content, null, 2)}`;\n\n\t\toutputs.set(outputKey, {\n\t\t\t...existing,\n\t\t\tcontent: augmentedContent,\n\t\t});\n\t}\n\n\t/**\n\t * Record hook execution result\n\t */\n\tprivate recordHookResult(\n\t\tpluginName: string,\n\t\thookName: string,\n\t\tresult: Omit<HookResult, \"plugin\">,\n\t): void {\n\t\tconst key = `${pluginName}:${hookName}`;\n\t\tconst existing = this.executionContext.results.get(key) || [];\n\t\texisting.push({ ...result, plugin: pluginName });\n\t\tthis.executionContext.results.set(key, existing);\n\t}\n\n\t/**\n\t * Create logger instance\n\t */\n\tprivate createLogger(): Logger {\n\t\treturn {\n\t\t\tinfo: (message: string) => console.log(`ℹ️ ${message}`),\n\t\t\twarn: (message: string) => console.warn(`⚠️ ${message}`),\n\t\t\terror: (message: string) => console.error(`❌ ${message}`),\n\t\t\tdebug: (message: string) => {\n\t\t\t\tif (process.env.DEBUG) {\n\t\t\t\t\tconsole.log(`🐛 ${message}`);\n\t\t\t\t}\n\t\t\t},\n\t\t\tsuccess: (message: string) => console.log(`✅ ${message}`),\n\t\t};\n\t}\n\n\t/**\n\t * Create utils instance\n\t */\n\tprivate createUtils(): PluginUtils {\n\t\treturn {\n\t\t\ttoCamelCase,\n\n\t\t\ttoKebabCase: (str: string) => {\n\t\t\t\treturn str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\t\t\t},\n\n\t\t\tvalidateAddress: (address: string) => {\n\t\t\t\treturn validateStacksAddress(parseContractId(address).address);\n\t\t\t},\n\n\t\t\tparseContractId: (contractId: string) => {\n\t\t\t\treturn parseContractId(contractId);\n\t\t\t},\n\n\t\t\tformatCode: async (code: string) => {\n\t\t\t\tconst { formatCode } = await import(\"../utils/format\");\n\t\t\t\treturn formatCode(code);\n\t\t\t},\n\n\t\t\tresolvePath: (relativePath: string) => {\n\t\t\t\treturn path.resolve(process.cwd(), relativePath);\n\t\t\t},\n\n\t\t\tfileExists: async (filePath: string) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait fs.access(filePath);\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\treadFile: async (filePath: string) => {\n\t\t\t\treturn fs.readFile(filePath, \"utf-8\");\n\t\t\t},\n\n\t\t\twriteFile: async (filePath: string, content: string) => {\n\t\t\t\tawait fs.writeFile(filePath, content, \"utf-8\");\n\t\t\t},\n\n\t\t\tensureDir: async (dirPath: string) => {\n\t\t\t\tawait fs.mkdir(dirPath, { recursive: true });\n\t\t\t},\n\t\t};\n\t}\n}\n"
9
9
  ],
10
- "mappings": "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",
11
- "debugId": "85ECC6D6BBFA69D064756E2164756E21",
10
+ "mappings": "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",
11
+ "debugId": "5FBC88459146F53D64756E2164756E21",
12
12
  "names": []
13
13
  }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
1
2
  import { AbiContract } from "@secondlayer/stacks/clarity";
2
3
  /** Supported Stacks network identifiers for contract resolution. */
3
4
  type NetworkName = "mainnet" | "testnet" | "devnet";
@@ -56,7 +57,6 @@ interface ResolvedContract {
56
57
  source: "api" | "local";
57
58
  }
58
59
  type ConfigDefiner = (config: SecondLayerConfig) => SecondLayerConfig;
59
- import { AbiContract as AbiContract2 } from "@secondlayer/stacks/clarity";
60
60
  /**
61
61
  * Core plugin interface that all plugins must implement
62
62
  */
@@ -216,23 +216,6 @@ interface HookResult<T = any> {
216
216
  plugin: string;
217
217
  }
218
218
  /**
219
- * Type-safe helper for creating a `secondlayer.config.ts` configuration.
220
- * Accepts either a config object or a factory function that receives a base config and returns a modified one.
221
- *
222
- * @example
223
- * ```ts
224
- * import { defineConfig } from "@secondlayer/cli";
225
- *
226
- * defineConfig({
227
- * contracts: [{ address: "SP000000000000000000002Q6VF78.bns" }],
228
- * out: "./src/generated.ts",
229
- * });
230
- * ```
231
- */
232
- declare function defineConfig(config: SecondLayerConfig): SecondLayerConfig;
233
- declare function defineConfig(definer: ConfigDefiner): ConfigDefiner;
234
- import { AbiContract as AbiContract3, AbiFunction, AbiType } from "@secondlayer/stacks/clarity";
235
- /**
236
219
  * Core plugin manager that orchestrates plugin execution
237
220
  */
238
221
  declare class PluginManager {
@@ -298,4 +281,21 @@ declare class PluginManager {
298
281
  */
299
282
  private createUtils;
300
283
  }
284
+ /**
285
+ * Type-safe helper for creating a `secondlayer.config.ts` configuration.
286
+ * Accepts either a config object or a factory function that receives a base config and returns a modified one.
287
+ *
288
+ * @example
289
+ * ```ts
290
+ * import { defineConfig } from "@secondlayer/cli";
291
+ *
292
+ * defineConfig({
293
+ * contracts: [{ address: "SP000000000000000000002Q6VF78.bns" }],
294
+ * out: "./src/generated.ts",
295
+ * });
296
+ * ```
297
+ */
298
+ declare function defineConfig(config: SecondLayerConfig): SecondLayerConfig;
299
+ declare function defineConfig(definer: ConfigDefiner): ConfigDefiner;
300
+ import { AbiContract as AbiContract3, AbiFunction, AbiType } from "@secondlayer/stacks/clarity";
301
301
  export { defineConfig, UserConfig, SecondLayerPlugin, SecondLayerConfig, ResolvedConfig, ProcessedContract, PluginUtils, PluginOptions, PluginManager, PluginFactory, PluginContext, OutputType, NetworkName, Logger, GeneratedOutput, GenerateContext, ContractSource, ContractConfig, AbiType, AbiFunction, AbiContract3 as AbiContract };
package/dist/index.js CHANGED
@@ -1,5 +1,35 @@
1
1
  import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
12
+ var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
20
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
21
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
+ for (let key of __getOwnPropNames(mod))
23
+ if (!__hasOwnProp.call(to, key))
24
+ __defProp(to, key, {
25
+ get: __accessProp.bind(mod, key),
26
+ enumerable: true
27
+ });
28
+ if (canCache)
29
+ cache.set(mod, to);
30
+ return to;
31
+ };
32
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
33
  var __returnValue = (v) => v;
4
34
  function __exportSetter(name, newValue) {
5
35
  this[name] = __returnValue.bind(null, newValue);
@@ -14,6 +44,27 @@ var __export = (target, all) => {
14
44
  });
15
45
  };
16
46
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
+
49
+ // src/types/plugin.ts
50
+ function isClarinetContract(c) {
51
+ return "_clarinetSource" in c && c._clarinetSource === true;
52
+ }
53
+ function isDirectFileContract(c) {
54
+ return "_directFile" in c && c._directFile === true;
55
+ }
56
+
57
+ // src/utils/contract-id.ts
58
+ function parseContractId(contractId) {
59
+ const dotIndex = contractId.indexOf(".");
60
+ if (dotIndex === -1) {
61
+ throw new Error(`Invalid contract ID: "${contractId}" (expected "address.contractName")`);
62
+ }
63
+ return {
64
+ address: contractId.slice(0, dotIndex),
65
+ contractName: contractId.slice(dotIndex + 1)
66
+ };
67
+ }
17
68
 
18
69
  // src/utils/format.ts
19
70
  var exports_format = {};
@@ -66,14 +117,6 @@ async function formatCode(code) {
66
117
  var biome = null;
67
118
  var init_format = () => {};
68
119
 
69
- // src/utils/config.ts
70
- import { randomBytes } from "crypto";
71
- import { promises as fs2 } from "fs";
72
- import { createRequire as createRequire2 } from "module";
73
- import { tmpdir } from "os";
74
- import path2 from "path";
75
- import { pathToFileURL } from "url";
76
-
77
120
  // src/core/plugin-manager.ts
78
121
  import { promises as fs } from "fs";
79
122
  import path from "path";
@@ -81,29 +124,6 @@ import { isValidAddress as _validateStacksAddress } from "@secondlayer/stacks";
81
124
  import { getErrorMessage } from "@secondlayer/shared";
82
125
  import { toCamelCase } from "@secondlayer/stacks/clarity";
83
126
 
84
- // src/types/plugin.ts
85
- function isClarinetContract(c) {
86
- return "_clarinetSource" in c && c._clarinetSource === true;
87
- }
88
- function isDirectFileContract(c) {
89
- return "_directFile" in c && c._directFile === true;
90
- }
91
-
92
- // src/utils/contract-id.ts
93
- function parseContractId(contractId) {
94
- const dotIndex = contractId.indexOf(".");
95
- if (dotIndex === -1) {
96
- throw new Error(`Invalid contract ID: "${contractId}" (expected "address.contractName")`);
97
- }
98
- return {
99
- address: contractId.slice(0, dotIndex),
100
- contractName: contractId.slice(dotIndex + 1)
101
- };
102
- }
103
-
104
- // src/core/plugin-manager.ts
105
- var validateStacksAddress = _validateStacksAddress;
106
-
107
127
  class PluginManager {
108
128
  plugins = [];
109
129
  logger;
@@ -363,15 +383,126 @@ ${JSON.stringify(content, null, 2)}`;
363
383
  };
364
384
  }
365
385
  }
386
+ var validateStacksAddress;
387
+ var init_plugin_manager = __esm(() => {
388
+ validateStacksAddress = _validateStacksAddress;
389
+ });
366
390
 
367
391
  // src/utils/config.ts
392
+ import { randomBytes } from "crypto";
393
+ import { promises as fs2 } from "fs";
394
+ import { createRequire as createRequire2 } from "module";
395
+ import { tmpdir } from "os";
396
+ import path2 from "path";
397
+ import { pathToFileURL } from "url";
398
+ async function findConfigFile(cwd) {
399
+ for (const fileName of CONFIG_FILE_NAMES) {
400
+ const filePath = path2.join(cwd, fileName);
401
+ try {
402
+ await fs2.access(filePath);
403
+ return filePath;
404
+ } catch {}
405
+ }
406
+ return null;
407
+ }
408
+ async function loadConfig(configPath) {
409
+ const cwd = process.cwd();
410
+ const resolvedPath = configPath ? path2.resolve(cwd, configPath) : await findConfigFile(cwd);
411
+ if (!resolvedPath) {
412
+ throw new Error("No config file found. Create a secondlayer.config.ts file or specify a path with --config");
413
+ }
414
+ let config;
415
+ if (resolvedPath.endsWith(".ts")) {
416
+ const code = await fs2.readFile(resolvedPath, "utf-8");
417
+ let replacementPath;
418
+ try {
419
+ const require2 = createRequire2(import.meta.url);
420
+ const packagePath = require2.resolve("@secondlayer/cli");
421
+ replacementPath = pathToFileURL(packagePath).href;
422
+ } catch {
423
+ const currentModuleDir = path2.dirname(new URL(import.meta.url).pathname);
424
+ const indexPath = path2.resolve(currentModuleDir, "../index");
425
+ replacementPath = pathToFileURL(indexPath).href;
426
+ }
427
+ const transformedCode = code.replace(/from\s+["']@secondlayer\/cli["']/g, `from '${replacementPath}'`);
428
+ const { transformSync } = await import("esbuild");
429
+ const result = transformSync(transformedCode, {
430
+ format: "esm",
431
+ target: "node18",
432
+ loader: "ts"
433
+ });
434
+ const tempPath = path2.join(tmpdir(), `secondlayer-config-${randomBytes(4).toString("hex")}.mjs`);
435
+ await fs2.writeFile(tempPath, result.code);
436
+ try {
437
+ const fileUrl = pathToFileURL(tempPath).href;
438
+ const module = await import(fileUrl);
439
+ config = module.default;
440
+ } finally {
441
+ await fs2.unlink(tempPath).catch(() => {});
442
+ }
443
+ } else {
444
+ const fileUrl = pathToFileURL(resolvedPath).href;
445
+ const module = await import(fileUrl);
446
+ config = module.default;
447
+ }
448
+ if (!config) {
449
+ throw new Error("Config file must export a default configuration");
450
+ }
451
+ if (typeof config === "function") {
452
+ config = config({});
453
+ }
454
+ validateConfig(config);
455
+ const pluginManager = new PluginManager;
456
+ if (config.plugins && Array.isArray(config.plugins)) {
457
+ for (const plugin of config.plugins) {
458
+ pluginManager.register(plugin);
459
+ }
460
+ }
461
+ const resolvedConfig = await pluginManager.transformConfig(config);
462
+ return resolvedConfig;
463
+ }
464
+ function validateConfig(config) {
465
+ if (!config || typeof config !== "object") {
466
+ throw new Error("Config must be an object");
467
+ }
468
+ const c = config;
469
+ if (c.contracts && !Array.isArray(c.contracts)) {
470
+ throw new Error("Config contracts must be an array");
471
+ }
472
+ if (!c.out || typeof c.out !== "string") {
473
+ throw new Error("Config out must be a string path");
474
+ }
475
+ if (c.contracts) {
476
+ for (const contract of c.contracts) {
477
+ if (!contract.address && !contract.source) {
478
+ throw new Error("Each contract must have either an address or source");
479
+ }
480
+ }
481
+ }
482
+ if (c.plugins && !Array.isArray(c.plugins)) {
483
+ throw new Error("Config plugins must be an array");
484
+ }
485
+ }
368
486
  function defineConfig(configOrDefiner) {
369
487
  return configOrDefiner;
370
488
  }
489
+ var CONFIG_FILE_NAMES;
490
+ var init_config = __esm(() => {
491
+ init_plugin_manager();
492
+ CONFIG_FILE_NAMES = [
493
+ "secondlayer.config.ts",
494
+ "secondlayer.config",
495
+ "secondlayer.config.mjs"
496
+ ];
497
+ });
498
+
499
+ // src/index.ts
500
+ init_config();
501
+ init_plugin_manager();
371
502
  export {
372
503
  defineConfig,
373
504
  PluginManager
374
505
  };
375
506
 
376
- //# debugId=6FDA39721A22F05264756E2164756E21
507
+ //# debugId=AF644CA8AC7B439C64756E2164756E21
377
508
  //# sourceMappingURL=index.js.map