import path from 'path'; import prompts from 'prompts'; import pc from 'picocolors'; import ora from 'ora'; import fs from 'fs'; import { isValidPackageName, toValidPackageName, createClickableLink, copyDir, } from './utils.js'; import { fileURLToPath } from 'url'; import { analyticsPrompt } from './analytics.js'; export async function createOnchainKitTemplate() { console.log( `${pc.greenBright(` ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // :::::::: :::: ::: :::::::: ::: ::: ::: ::::::::::: :::: ::: ::: ::: ::::::::::: ::::::::::: // // :+: :+: :+:+: :+: :+: :+: :+: :+: :+: :+: :+: :+:+: :+: :+: :+: :+: :+: // // +:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ +:+ // // +#+ +:+ +#+ +:+ +#+ +#+ +#++:++#++ +#++:++#++: +#+ +#+ +:+ +#+ +#++:++ +#+ +#+ // // +#+ +#+ +#+ +#+#+# +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+# +#+ +#+ +#+ +#+ // // #+# #+# #+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+# #+#+# #+# #+# #+# #+# // // ######## ### #### ######## ### ### ### ### ########### ### #### ### ### ########### ### // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`)}\n\n`, ); const defaultProjectName = 'my-onchainkit-app'; let result: prompts.Answers<'projectName' | 'packageName' | 'clientKey'>; try { result = await prompts( [ { type: 'text', name: 'projectName', message: pc.reset('Project name:'), initial: defaultProjectName, onState: (state) => { state.value = state.value.trim(); }, validate: (value) => { const targetDir = path.join(process.cwd(), value); if ( fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0 ) { return 'Directory already exists and is not empty. Please choose a different name.'; } return true; }, }, { type: (_, { projectName }: { projectName: string }) => isValidPackageName(projectName) ? null : 'text', name: 'packageName', message: pc.reset('Package name:'), initial: (_, { projectName }: { projectName: string }) => toValidPackageName(projectName), validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name', }, { type: 'password', name: 'clientKey', message: pc.reset( `Enter your ${createClickableLink( 'Coinbase Developer Platform Client API Key:', 'https://portal.cdp.coinbase.com/products/onchainkit', )} (optional)`, ), }, ], { onCancel: () => { console.log('\nProject creation cancelled.'); process.exit(0); }, }, ); } catch (cancelled: any) { console.log(cancelled.message); process.exit(1); } const { projectName, packageName, clientKey } = result; const root = path.join(process.cwd(), projectName); await analyticsPrompt('onchainkit-nextjs'); const spinner = ora(`Creating ${projectName}...`).start(); const sourceDir = path.resolve( fileURLToPath(import.meta.url), '../../../templates/onchainkit-nextjs', ); await copyDir(sourceDir, root); const pkgPath = path.join(root, 'package.json'); const pkg = JSON.parse(await fs.promises.readFile(pkgPath, 'utf-8')); pkg.name = packageName || toValidPackageName(projectName); await fs.promises.writeFile(pkgPath, JSON.stringify(pkg, null, 2)); // Customize .env file from template const envPath = path.join(root, '.env'); const templateEnvContent = await fs.promises .readFile(envPath, 'utf-8') .catch(() => ''); const customEnvContent = templateEnvContent .replace( 'NEXT_PUBLIC_PROJECT_NAME="template-next-basic"', `NEXT_PUBLIC_PROJECT_NAME="${projectName}"`, ) .replace( 'NEXT_PUBLIC_ONCHAINKIT_API_KEY=""', `NEXT_PUBLIC_ONCHAINKIT_API_KEY="${clientKey}"`, ); await fs.promises.writeFile(envPath, customEnvContent); spinner.succeed(); console.log(`\n${pc.magenta(`Created new OnchainKit project in ${root}`)}`); console.log(`\nIntegrations:`); console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`Base`)}`); if (clientKey) { console.log( `${pc.greenBright('\u2713')} ${pc.blueBright( `Coinbase Developer Platform`, )}`, ); console.log(`${pc.greenBright('\u2713')} ${pc.blueBright(`Paymaster`)}`); } console.log(`\nFrameworks:`); console.log(`${pc.cyan('- Wagmi')}`); console.log(`${pc.cyan('- React')}`); console.log(`${pc.cyan('- Next.js')}`); console.log(`${pc.cyan('- ESLint')}`); console.log( `\nTo get started with ${pc.green( projectName, )}, run the following commands:\n`, ); if (root !== process.cwd()) { console.log(` - cd ${path.relative(process.cwd(), root)}`); } console.log(' - npm install'); console.log(' - npm run dev'); }