UNPKG

cp-app

Version:

Easily bootstrap a new permissionless app based on permissionless.js and your favourite tooling!

243 lines (225 loc) 8.36 kB
import * as p from "@clack/prompts" import { Command } from "commander" import { CREATE_PERMISSIONLESS_APP, DEFAULT_APP_NAME } from "../constants" import { type PackageManager, detectPackageManager } from "../utils/detectPackageManager" import { logger } from "../utils/logger" import { validateAppName } from "../utils/validateAppName" interface CliFlags { noGit: boolean noInstall: boolean default: boolean bundler: string paymaster: string signer: string accountSystem: string pimlicoApiKey: string privyAppId: string publicRPCUrl: string } interface CliResults { appName: string flags: CliFlags } const defaultOptions: CliResults = { appName: DEFAULT_APP_NAME, flags: { noGit: false, noInstall: false, default: false, bundler: "pimlico", paymaster: "pimlico", signer: "privy", accountSystem: "safe", pimlicoApiKey: "", privyAppId: "", publicRPCUrl: "" } } export const runCli = async (): Promise<CliResults> => { const cliResults = defaultOptions const program = new Command() .name(CREATE_PERMISSIONLESS_APP) .description("A CLI to spin up a permissionless app with Pimlico") .argument( "[dir]", "The name of the application, as well as the name of the directory to create" ) .option( "--noGit", "Explicitly tell the CLI to not initialize a new git repo in the project", false ) .option( "--noInstall", "Explicitly tell the CLI to not run the package manager's install command", false ) .option( "-y, --default", "Bypass the CLI and use all default options to bootstrap a new permissionless app", false ) /** START CI-FLAGS * As of now these CI Flags are not well structured but will be updated soon.. */ .option( "-b, --bundler", "Specify the bundler provider", defaultOptions.flags.bundler ) .option( "-p, --paymaster", "Specify the paymaster provider", defaultOptions.flags.paymaster ) .option( "-s, --signer", "Specify the signer", defaultOptions.flags.signer ) .option( "-a, --account-system", "Specify the account system", defaultOptions.flags.accountSystem ) /** END CI-FLAGS */ .parse(process.argv) const cliProvidedName = program.args[0] if (cliProvidedName) { cliResults.appName = cliProvidedName } cliResults.flags = program.opts() try { const packageManager: PackageManager = detectPackageManager() const project = await p.group( { ...(!cliProvidedName && { name: () => p.text({ message: "What will your project be called?", defaultValue: cliProvidedName, validate: validateAppName }) }), bundler: () => { return p.select({ message: "Pick your bundler provider", options: [{ value: "pimlico", label: "Pimlico" }], initialValue: cliResults.flags.bundler }) }, paymaster: () => { return p.select({ message: "Pick your paymaster provider", options: [{ value: "pimlico", label: "Pimlico" }], initialValue: cliResults.flags.paymaster }) }, ...(cliResults.flags.bundler === "pimlico" || cliResults.flags.paymaster === "pimlico" ? { pimlicoApiKey: () => { return p.text({ message: "Please provide the Pimlico API key for your project configuration", defaultValue: cliResults.flags.pimlicoApiKey }) } } : {}), accountSystem: () => { return p.select({ message: "Pick your account system", options: [{ value: "safe", label: "Safe" }], initialValue: cliResults.flags.accountSystem }) }, signer: () => { return p.select({ message: "Pick your signer", options: [{ value: "privy", label: "Privy" }], initialValue: cliResults.flags.signer }) }, ...(cliResults.flags.signer === "privy" ? { privyAppId: () => { return p.text({ message: "Please provide the Privy API ID for your project configuration", defaultValue: cliResults.flags.publicRPCUrl }) } } : {}), publicRPCUrl: () => { return p.text({ message: "Please provide the sepolia testnet rpc url for your project configuration", defaultValue: cliResults.flags.publicRPCUrl }) }, ...(!cliResults.flags.noGit && { git: () => { return p.confirm({ message: "Should we initialize a Git repository and stage the changes?", initialValue: !defaultOptions.flags.noGit }) } }), ...(!cliResults.flags.noInstall && { install: () => { return p.confirm({ message: `Should we run '${packageManager}${ packageManager === "yarn" ? `'?` : ` install' for you?` }`, initialValue: !defaultOptions.flags.noInstall }) } }) }, { onCancel() { process.exit(1) } } ) return { appName: project.name ?? cliResults.appName, flags: { ...cliResults.flags, noGit: !project.git || cliResults.flags.noGit, noInstall: !project.install || cliResults.flags.noInstall, signer: project.signer ?? cliResults.flags.signer, paymaster: project.paymaster ?? cliResults.flags.paymaster, bundler: project.bundler ?? cliResults.flags.bundler, accountSystem: project.accountSystem ?? cliResults.flags.accountSystem, privyAppId: project.privyAppId ?? cliResults.flags.privyAppId, pimlicoApiKey: project.pimlicoApiKey ?? cliResults.flags.pimlicoApiKey, publicRPCUrl: project.publicRPCUrl ?? cliResults.flags.publicRPCUrl } } } catch (err) { const shouldContinue = await p.confirm({ message: "Continue scaffolding a default Permissionless app?", initialValue: true }) if (!shouldContinue) { logger.info("Exiting...") process.exit(0) } logger.info( `Bootstrapping a default Permissionless app in ./${cliResults.appName}` ) } return cliResults }