UNPKG

create-accessnode

Version:

CLI for setting up AccessNode projects. Clones AccessNode repo, prompts for chains & contracts, creates node.config.ts.

134 lines (129 loc) 4.25 kB
#!/usr/bin/env node // bin/cli.ts import fs from "fs"; import path from "path"; import prompts from "prompts"; import pico from "picocolors"; import prettier from "prettier"; import { execa } from "execa"; // src/chain.ts var CHAINS = [ { id: "base", name: "Base", config: { chainId: 8453, transport: "http(process.env.ACCESSNODE_RPC_URL_8453)", maxRequestsPerSecond: 15 } }, { id: "base-sepolia", name: "Base Sepolia", config: { chainId: 84532, transport: "http(process.env.ACCESSNODE_RPC_URL_84532)", maxRequestsPerSecond: 15 } } ]; // bin/cli.ts var REPO_URL = "https://github.com/accesstimeio/accessnode"; async function main() { const args = process.argv.slice(2); const cliProjectName = args.find((arg) => arg.startsWith("--project-name=")); let projectName = cliProjectName?.split("=")[1]; if (!projectName) { const res = await prompts({ type: "text", name: "name", message: "Enter your project name:", initial: "accessnode-app" }); projectName = res.name.trim(); } const projectPath = path.resolve(process.cwd(), projectName); console.log(pico.blue("\u23F3 Cloning repository...")); await execa("git", ["clone", REPO_URL, projectName]); const { selectedChains } = await prompts({ type: "multiselect", name: "selectedChains", message: "Select chains to support:", choices: CHAINS.map((c) => ({ title: c.name, value: c.id })), min: 1 }); const contractNetworkConfig = {}; for (const chainId of selectedChains) { const { addresses } = await prompts({ type: "text", name: "addresses", message: `Enter contract addresses for ${chainId} (comma-separated):` }); const addressList = addresses.split(",").map((a) => a.trim().toLowerCase()).filter(Boolean); const { startBlock } = await prompts({ type: "number", name: "startBlock", message: `Enter start block for ${chainId}:` }); contractNetworkConfig[chainId] = { address: addressList, startBlock }; } const selectedNetworkConfigs = Object.fromEntries( selectedChains.map((id) => { const chain = CHAINS.find((c) => c.id === id); return [id, chain.config]; }) ); const rawConfig = ` import { createNodeConfig } from "./src/types"; import { http } from "viem"; export default createNodeConfig({ networks: ${JSON.stringify(selectedNetworkConfigs, null, 2).replaceAll( /"http\((.*?)\)"/g, (_, env) => `http(${env})` )}, contracts: { AccessTime: { network: ${JSON.stringify(contractNetworkConfig, null, 2)} } } }); `; const formattedConfig = await prettier.format(rawConfig, { parser: "typescript" }); fs.writeFileSync(path.join(projectPath, "node.config.ts"), formattedConfig); console.log(); console.log(pico.green("\u2705 Project created at:"), pico.bold(projectPath)); console.log(pico.green("\u2705 Configuration written to node.config.ts")); console.log(); console.log(pico.blue("\u{1F527} Resetting git history...")); fs.rmSync(path.join(projectPath, ".git"), { recursive: true, force: true }); await execa("git", ["init"], { cwd: projectPath }); await execa("git", ["add", "."], { cwd: projectPath }); await execa("git", ["commit", "-m", "chore: update config"], { cwd: projectPath }); console.log(pico.green("\u2705 Git repository initialized.")); console.log(pico.blue("\u{1F50D} Checking pnpm...")); let pnpmInstalled = true; try { await execa("pnpm", ["--version"]); } catch { pnpmInstalled = false; } if (!pnpmInstalled) { console.log(pico.yellow("\u{1F4E6} pnpm not found. Installing...")); await execa("npm", ["install", "-g", "pnpm"]); console.log(pico.green("\u2705 pnpm installed globally.")); } console.log(pico.blue("\u{1F4E6} Installing dependencies with pnpm...")); await execa("pnpm", ["install"], { cwd: projectPath }); console.log(pico.green("\u2705 Dependencies installed.")); console.log(); console.log(pico.green("\u{1F680} Setup complete! Happy hacking!")); } main().catch((err) => { console.error(pico.red("\u274C Error:"), err.message); process.exit(1); });