UNPKG

@abix/zisk-dev-cli

Version:

A comprehensive CLI tool for ZisK zkVM development with full macOS support. Features project initialization, building, execution, proof generation, environment diagnostics, and project management. This is a personal tool for testing and learning - not an

279 lines (232 loc) 7.49 kB
/** * Project Discovery Module * Hardcoded logic to discover project details from Cargo.toml and file system */ const fs = require('fs-extra'); const path = require('path'); const glob = require('glob'); class ProjectDiscoverer { constructor() { this.cache = new Map(); } /** * Discover project information using hardcoded logic */ async discoverProject(projectRoot = process.cwd()) { if (this.cache.has(projectRoot)) { return this.cache.get(projectRoot); } const project = { root: projectRoot, name: await this.discoverProjectName(projectRoot), mainFile: await this.discoverMainFile(projectRoot), inputFiles: await this.discoverInputFiles(projectRoot), outputDirectory: await this.discoverOutputDirectory(projectRoot), buildTarget: await this.discoverBuildTarget(projectRoot), buildProfile: await this.discoverBuildProfile(projectRoot), features: await this.discoverFeatures(projectRoot) }; this.cache.set(projectRoot, project); return project; } /** * Discover project name from Cargo.toml */ async discoverProjectName(projectRoot) { const cargoTomlPath = path.join(projectRoot, 'Cargo.toml'); if (!await fs.pathExists(cargoTomlPath)) { // Fallback to directory name return path.basename(projectRoot); } try { const cargoContent = await fs.readFile(cargoTomlPath, 'utf8'); const nameMatch = cargoContent.match(/name\s*=\s*"([^"]+)"/); return nameMatch ? nameMatch[1] : path.basename(projectRoot); } catch (error) { return path.basename(projectRoot); } } /** * Discover main file using hardcoded logic */ async discoverMainFile(projectRoot) { const possibleMainFiles = [ 'src/main.rs', 'src/lib.rs', 'main.rs', 'lib.rs' ]; for (const mainFile of possibleMainFiles) { const fullPath = path.join(projectRoot, mainFile); if (await fs.pathExists(fullPath)) { return mainFile; } } return 'src/main.rs'; // Default fallback } /** * Discover input files using hardcoded logic */ async discoverInputFiles(projectRoot) { const inputDirectories = [ 'inputs', 'build', 'test-data', 'data', 'input' ]; const inputFiles = []; for (const dir of inputDirectories) { const dirPath = path.join(projectRoot, dir); if (await fs.pathExists(dirPath)) { const files = await fs.readdir(dirPath); const inputFilesInDir = files .filter(file => this.isInputFile(file)) .map(file => path.join(dir, file)); inputFiles.push(...inputFilesInDir); } } // If no input files found in directories, look for files in root if (inputFiles.length === 0) { const rootFiles = await fs.readdir(projectRoot); const inputFilesInRoot = rootFiles .filter(file => this.isInputFile(file)) .map(file => file); inputFiles.push(...inputFilesInRoot); } return inputFiles; } /** * Check if file is an input file */ isInputFile(filename) { const inputExtensions = ['.bin', '.json', '.yaml', '.yml', '.txt']; const inputPatterns = ['input', 'data', 'test']; const ext = path.extname(filename).toLowerCase(); const name = path.basename(filename, ext).toLowerCase(); return inputExtensions.includes(ext) || inputPatterns.some(pattern => name.includes(pattern)); } /** * Discover output directory using hardcoded logic */ async discoverOutputDirectory(projectRoot) { const possibleOutputDirs = [ 'proofs', 'proof', 'outputs', 'output', 'generated-proofs' ]; for (const dir of possibleOutputDirs) { const dirPath = path.join(projectRoot, dir); if (await fs.pathExists(dirPath)) { return dir; } } return 'proofs'; // Default fallback } /** * Discover build target from Cargo.toml or use default */ async discoverBuildTarget(projectRoot) { const cargoTomlPath = path.join(projectRoot, 'Cargo.toml'); if (!await fs.pathExists(cargoTomlPath)) { return 'riscv64ima-zisk-zkvm-elf'; } try { const cargoContent = await fs.readFile(cargoTomlPath, 'utf8'); // Look for target configuration const targetMatch = cargoContent.match(/target\s*=\s*"([^"]+)"/); if (targetMatch) { return targetMatch[1]; } // Look for zisk-specific configuration const ziskMatch = cargoContent.match(/zisk.*target\s*=\s*"([^"]+)"/); if (ziskMatch) { return ziskMatch[1]; } } catch (error) { // Ignore parsing errors } return 'riscv64ima-zisk-zkvm-elf'; // Default ZisK target } /** * Discover build profile from Cargo.toml or use default */ async discoverBuildProfile(projectRoot) { const cargoTomlPath = path.join(projectRoot, 'Cargo.toml'); if (!await fs.pathExists(cargoTomlPath)) { return 'release'; } try { const cargoContent = await fs.readFile(cargoTomlPath, 'utf8'); // Look for profile configuration const profileMatch = cargoContent.match(/profile\s*=\s*"([^"]+)"/); if (profileMatch) { return profileMatch[1]; } // Look for zisk-specific profile const ziskProfileMatch = cargoContent.match(/zisk.*profile\s*=\s*"([^"]+)"/); if (ziskProfileMatch) { return ziskProfileMatch[1]; } } catch (error) { // Ignore parsing errors } return 'release'; // Default profile } /** * Discover features from Cargo.toml */ async discoverFeatures(projectRoot) { const cargoTomlPath = path.join(projectRoot, 'Cargo.toml'); if (!await fs.pathExists(cargoTomlPath)) { return null; } try { const cargoContent = await fs.readFile(cargoTomlPath, 'utf8'); // Look for features configuration const featuresMatch = cargoContent.match(/features\s*=\s*\[(.*?)\]/s); if (featuresMatch) { const featuresStr = featuresMatch[1]; const features = featuresStr .split(',') .map(f => f.trim().replace(/['"]/g, '')) .filter(f => f.length > 0); return features.length > 0 ? features.join(',') : null; } } catch (error) { // Ignore parsing errors } return null; } /** * Get expected ELF path based on discovered project info */ async getExpectedElfPath(projectRoot, profile = null) { const project = await this.discoverProject(projectRoot); const buildProfile = profile || project.buildProfile; const targetDir = buildProfile === 'release' ? 'release' : 'debug'; return `target/${project.buildTarget}/${targetDir}/${project.name}`; } /** * Check if current directory is a ZisK project */ async isZiskProject(projectRoot = process.cwd()) { const cargoTomlPath = path.join(projectRoot, 'Cargo.toml'); if (!await fs.pathExists(cargoTomlPath)) { return false; } try { const cargoContent = await fs.readFile(cargoTomlPath, 'utf8'); // Check for ziskos dependency return cargoContent.includes('ziskos') || cargoContent.includes('zisk') || cargoContent.includes('zkvm'); } catch (error) { return false; } } } module.exports = { ProjectDiscoverer };