UNPKG

create-nft-gallery

Version:

CLI tool to scaffold NFT gallery applications for Arweave Name System (ArNS) domains

174 lines (152 loc) • 5.98 kB
#!/usr/bin/env node import { Command } from 'commander'; import inquirer from 'inquirer'; import fs from 'fs-extra'; import path from 'path'; import { fileURLToPath } from 'url'; import { execSync } from 'child_process'; import ejs from 'ejs'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const program = new Command(); program .name('create-nft-gallery') .description('Create a new NFT gallery application for Arweave Name System (ArNS) domains') .argument('[project-name]', 'Name of the project') .option('--domain <ar-domain>', 'Specify ArNS domain') .option('--variant <variant>', 'Specify the variant to use (e.g., manifold)') .action(async (projectName, options) => { try { // Get project name and variant const answers = await inquirer.prompt([ { type: 'input', name: 'projectName', message: 'What is your project named?', default: projectName || 'nft-gallery', when: !projectName }, { type: 'list', name: 'variant', message: 'Which variant would you like to use?', choices: ['manifold', 'metaplex'], // Added metaplex as an option default: options.variant || 'manifold' } ]); const finalProjectName = projectName || answers.projectName; const variant = answers.variant; // Get ArNS domain const domainAnswer = await inquirer.prompt([ { type: 'input', name: 'domain', message: 'What is your ArNS domain?', default: options.domain || 'mygallery' } ]); const finalDomain = domainAnswer.domain; // Create project directory const projectPath = path.join(process.cwd(), finalProjectName); await fs.ensureDir(projectPath); // Copy base template files const baseTemplatePath = path.join(__dirname, '..', 'templates', 'base'); await fs.copy(baseTemplatePath, projectPath); // Overlay variant files const variantTemplatePath = path.join(__dirname, '..', 'templates', 'variants', variant); await fs.copy(variantTemplatePath, projectPath, { overwrite: true }); // Merge package.json files const basePackageJson = JSON.parse(await fs.readFile(path.join(projectPath, 'package.json.ejs'), 'utf-8')); // Check if variant has a package.json let variantPackageJson = { dependencies: {}, devDependencies: {}, scripts: {} }; const variantPackageJsonPath = path.join(variantTemplatePath, 'package.json.ejs'); if (await fs.pathExists(variantPackageJsonPath)) { variantPackageJson = JSON.parse(await fs.readFile(variantPackageJsonPath, 'utf-8')); } // Merge dependencies while preserving scripts and other fields const mergedPackageJson = { name: basePackageJson.name, version: basePackageJson.version, private: basePackageJson.private, type: basePackageJson.type, scripts: { ...basePackageJson.scripts, ...variantPackageJson.scripts }, dependencies: { ...basePackageJson.dependencies, ...variantPackageJson.dependencies }, devDependencies: { ...basePackageJson.devDependencies, ...variantPackageJson.devDependencies } }; // Write merged package.json await fs.writeFile( path.join(projectPath, 'package.json.ejs'), JSON.stringify(mergedPackageJson, null, 2) ); // Get environment variables const envAnswers = await inquirer.prompt([ { type: 'input', name: 'NFT_CONTRACT_ADDRESS', message: 'Enter your NFT contract address (optional):', default: '' }, { type: 'input', name: 'RPC_ENDPOINT', message: 'Enter your RPC endpoint URL (optional):', default: '' } ]); // Create .env file const envContent = `# Environment variables for ${finalProjectName} ARNS_NAME=${finalDomain} NFT_CONTRACT_ADDRESS=${envAnswers.NFT_CONTRACT_ADDRESS} RPC_ENDPOINT=${envAnswers.RPC_ENDPOINT} DEPLOY_KEY="a base64 of your arweave wallet key" `; await fs.writeFile(path.join(projectPath, '.env'), envContent); // Process template files const templateFiles = await fs.readdir(projectPath, { recursive: true }); for (const file of templateFiles) { if (file.endsWith('.ejs')) { const filePath = path.join(projectPath, file); const content = await fs.readFile(filePath, 'utf-8'); const rendered = ejs.render(content, { name: finalProjectName, domain: finalDomain, includeManifold: variant === 'manifold', ARNS_NAME: finalDomain, ...envAnswers }); // Preserve the original file extension when removing .ejs const newFilePath = filePath.replace(/\.ejs$/, ''); await fs.writeFile(newFilePath, rendered); await fs.remove(filePath); } } // Install dependencies console.log('\nInstalling dependencies...'); execSync('npm install', { cwd: projectPath, stdio: 'inherit' }); // Initialize git repository try { execSync('git init', { cwd: projectPath }); execSync('git add .', { cwd: projectPath }); execSync('git commit -m "Initial commit"', { cwd: projectPath }); } catch (error) { console.log('Git initialization skipped'); } console.log(`\nšŸŽ‰ Created ${finalProjectName} as an NFT gallery on ${finalDomain} using the ${variant} variant`); console.log('\nNext steps:'); console.log(` cd ${finalProjectName}`); console.log(' npm run dev'); } catch (error) { console.error('Error:', error.message); process.exit(1); } }); program.parse();