recon-generate 0.0.2 → 0.0.3

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.
@@ -21,6 +21,7 @@ export declare class ReconGenerator {
21
21
  private options;
22
22
  private generatedMocks;
23
23
  private allowedMockNames;
24
+ private contractKindCache;
24
25
  constructor(foundryRoot: string, options: GeneratorOptions);
25
26
  private logDebug;
26
27
  private outDir;
@@ -33,6 +34,7 @@ export declare class ReconGenerator {
33
34
  private installSetupHelpers;
34
35
  private updateRemappings;
35
36
  private updateGitignore;
37
+ private getContractKind;
36
38
  private findSourceContracts;
37
39
  private matchesSignatureOrName;
38
40
  private paramType;
package/dist/generator.js CHANGED
@@ -41,6 +41,7 @@ const child_process_1 = require("child_process");
41
41
  const fs = __importStar(require("fs/promises"));
42
42
  const path = __importStar(require("path"));
43
43
  const abi_to_mock_1 = __importDefault(require("abi-to-mock"));
44
+ const parser_1 = __importDefault(require("@solidity-parser/parser"));
44
45
  const templateManager_1 = require("./templateManager");
45
46
  const types_1 = require("./types");
46
47
  const utils_1 = require("./utils");
@@ -50,6 +51,7 @@ class ReconGenerator {
50
51
  this.options = options;
51
52
  this.generatedMocks = new Set();
52
53
  this.allowedMockNames = new Set();
54
+ this.contractKindCache = new Map();
53
55
  }
54
56
  logDebug(message, obj) {
55
57
  if (!this.options.debug)
@@ -153,6 +155,45 @@ class ReconGenerator {
153
155
  await fs.writeFile(gitignorePath, content);
154
156
  }
155
157
  }
158
+ async getContractKind(sourcePath, contractName) {
159
+ const absPath = path.isAbsolute(sourcePath) ? sourcePath : path.join(this.foundryRoot, sourcePath);
160
+ let fileCache = this.contractKindCache.get(absPath);
161
+ if (fileCache && fileCache.has(contractName)) {
162
+ return fileCache.get(contractName);
163
+ }
164
+ let content;
165
+ try {
166
+ content = await fs.readFile(absPath, 'utf8');
167
+ }
168
+ catch (e) {
169
+ this.logDebug('Failed to read source when determining contract kind', { sourcePath, error: String(e) });
170
+ return 'unknown';
171
+ }
172
+ let ast;
173
+ try {
174
+ ast = parser_1.default.parse(content, { tolerant: true });
175
+ }
176
+ catch (e) {
177
+ this.logDebug('Failed to parse source when determining contract kind', { sourcePath, error: String(e) });
178
+ return 'unknown';
179
+ }
180
+ fileCache = fileCache !== null && fileCache !== void 0 ? fileCache : new Map();
181
+ let kind = 'unknown';
182
+ const children = ast === null || ast === void 0 ? void 0 : ast.children;
183
+ if (Array.isArray(children)) {
184
+ for (const node of children) {
185
+ if ((node === null || node === void 0 ? void 0 : node.type) === 'ContractDefinition' && node.name === contractName) {
186
+ if (node.kind === 'contract' || node.kind === 'interface' || node.kind === 'library') {
187
+ kind = node.kind;
188
+ }
189
+ break;
190
+ }
191
+ }
192
+ }
193
+ fileCache.set(contractName, kind);
194
+ this.contractKindCache.set(absPath, fileCache);
195
+ return kind;
196
+ }
156
197
  async findSourceContracts() {
157
198
  var _a;
158
199
  const contracts = [];
@@ -181,18 +222,14 @@ class ReconGenerator {
181
222
  for (const [sourcePath, contractName] of Object.entries(metadata.settings.compilationTarget)) {
182
223
  const lowerPath = sourcePath.toLowerCase();
183
224
  const lowerName = String(contractName).toLowerCase();
184
- // Skip interfaces, libraries, and mocks by convention, unless explicitly allowed (generated mocks)
185
225
  const isGeneratedMock = this.generatedMocks.has(String(contractName));
186
- if (!isGeneratedMock) {
187
- if (lowerPath.includes('/interface') ||
188
- lowerPath.includes('/interfaces') ||
189
- lowerPath.includes('/lib/') ||
190
- lowerPath.includes('/libraries') ||
191
- lowerPath.includes('/library') ||
192
- lowerPath.includes('/mock') ||
193
- lowerName.includes('mock')) {
194
- continue;
195
- }
226
+ const contractKind = await this.getContractKind(sourcePath, String(contractName));
227
+ if (contractKind === 'interface' || contractKind === 'library') {
228
+ this.logDebug('Skipping non-contract artifact', { contractName, sourcePath, contractKind });
229
+ continue;
230
+ }
231
+ if (!isGeneratedMock && (lowerPath.includes('/mock') || lowerName.includes('mock'))) {
232
+ continue;
196
233
  }
197
234
  const relativeJson = path.relative(this.foundryRoot, filePath);
198
235
  let displayedPath = sourcePath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recon-generate",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "CLI to scaffold Recon fuzzing suite inside Foundry projects",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -18,9 +18,10 @@
18
18
  "package.json"
19
19
  ],
20
20
  "dependencies": {
21
+ "@solidity-parser/parser": "^0.20.2",
21
22
  "abi-to-mock": "^1.0.4",
22
23
  "case": "^1.6.3",
23
- "commander": "^12.1.0",
24
+ "commander": "^14.0.2",
24
25
  "handlebars": "^4.7.8"
25
26
  },
26
27
  "devDependencies": {