create-dynamic-app
Advanced tools
Comparing version 2.0.0 to 2.0.1
@@ -33,12 +33,8 @@ #!/usr/bin/env node | ||
async function askAdditionalQuestions(answers) { | ||
if (answers.framework === 'react-native' || answers.framework === 'scaffold-eth') { | ||
return answers; | ||
} | ||
const additionalQuestions = [ | ||
async function askLibraryQuestion() { | ||
const libraryQuestion = [ | ||
{ | ||
type: 'list', | ||
name: 'library', | ||
message: 'Are you happy with Viem, or do you need Ethers?', | ||
message: 'For Ethereum interactions, are you happy with Viem, or do you need Ethers?', | ||
choices: [ | ||
@@ -48,7 +44,13 @@ { name: 'Happy with Viem', value: 'viem' }, | ||
] | ||
}, | ||
} | ||
]; | ||
return inquirer.prompt(libraryQuestion); | ||
} | ||
async function askWagmiQuestion() { | ||
const wagmiQuestion = [ | ||
{ | ||
type: 'list', | ||
name: 'wagmi', | ||
message: 'Do you want to use Wagmi on top of Dynamic?', | ||
message: 'Do you want to use Wagmi on top of Viem?', | ||
choices: [ | ||
@@ -60,5 +62,3 @@ { name: 'Yes', value: 'wagmi' }, | ||
]; | ||
const additionalAnswers = await inquirer.prompt(additionalQuestions); | ||
return { ...answers, ...additionalAnswers }; | ||
return inquirer.prompt(wagmiQuestion); | ||
} | ||
@@ -75,5 +75,6 @@ | ||
async function generateApp(repoUrl, directoryName, answers) { | ||
async function generateApp(repoUrl, directoryName, answers, selectedChains) { | ||
console.log(answers); | ||
if (answers.framework === 'nextjs' || answers.framework === 'react') { | ||
const selectedChains = await promptForChains(); | ||
console.log('answers',answers) | ||
const useViem = answers.library === 'viem'; | ||
@@ -129,5 +130,5 @@ const useWagmi = answers.wagmi === 'wagmi'; | ||
if (directoryExists) { | ||
await askForNewDirectory(newDir, repoUrl); | ||
return await askForNewDirectory(newDir, repoUrl); | ||
} else { | ||
await generateApp(repoUrl, newDir); | ||
return newDir; | ||
} | ||
@@ -145,3 +146,17 @@ } | ||
const initialAnswers = await askFrameworkQuestion(); | ||
const answers = await askAdditionalQuestions(initialAnswers); | ||
const selectedChains = await promptForChains(); | ||
const hasEthereum = selectedChains.some(chain => chain.name === 'Ethereum'); | ||
let answers = { ...initialAnswers, library: '', wagmi: '' }; | ||
if (hasEthereum) { | ||
const libraryAnswer = await askLibraryQuestion(); | ||
answers.library = libraryAnswer.library; | ||
if (answers.library === 'viem') { | ||
const wagmiAnswer = await askWagmiQuestion(); | ||
answers.wagmi = wagmiAnswer.wagmi; | ||
} | ||
} | ||
const repoUrl = generateRepoUrl(answers); | ||
@@ -159,7 +174,8 @@ let directoryName; | ||
if (directoryExists) { | ||
await askForNewDirectory(directoryName, repoUrl); | ||
} else { | ||
await generateApp(repoUrl, directoryName, answers); | ||
} | ||
directoryName = await askForNewDirectory(directoryName, repoUrl); | ||
} | ||
await generateApp(repoUrl, directoryName, answers, selectedChains); | ||
if (answers.framework === 'scaffold-eth') { | ||
@@ -166,0 +182,0 @@ const url = "https://github.com/dynamic-labs/hackathon-starter-kit"; |
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
import { execSync } from 'child_process'; | ||
import figlet from 'figlet'; | ||
import { generateLayoutJsContent, pageJs, PageCss, generateProvidersContent, generateDynamicLibContent, wagmiContent } from './next-templates/index.js'; | ||
@@ -22,3 +23,3 @@ import { addSolanaDependencies, createConfigOverrides } from './next-templates/solana-config.js'; | ||
"@dynamic-labs/sdk-react-core": "^3.0.0-alpha", | ||
...(useViem ? { viem: "*" } : { "@dynamic-labs/ethers-v6": "^3.0.0-alpha" }), | ||
...(useViem && selectedChains.some(chain => chain.name === 'Ethereum') ? { viem: "*" } : !useViem && selectedChains.some(chain => chain.name === 'Ethereum') ?{ "@dynamic-labs/ethers-v6": "^3.0.0-alpha" } : {}), | ||
...(useWagmi && { | ||
@@ -66,2 +67,5 @@ "@dynamic-labs/wagmi-connector": "^3.0.0-alpha", | ||
try { | ||
// Ensure the public directory exists | ||
await fs.mkdir(publicDir, { recursive: true }); | ||
const files = await fs.readdir(assetsDir); | ||
@@ -79,18 +83,41 @@ await Promise.all(files.map(file => | ||
const nextDir = customDir ? process.cwd() : path.join(process.cwd(), 'next'); | ||
const appConfigs = [ | ||
{ name: customDir || 'next-viem', useViem: true, useWagmi: false }, | ||
...(customDir ? [] : [ | ||
{ name: 'next-viem-wagmi', useViem: true, useWagmi: true }, | ||
{ name: 'next-ethers', useViem: false, useWagmi: false }, | ||
{ name: 'next-ethers-wagmi', useViem: false, useWagmi: true } | ||
]) | ||
]; | ||
if (!customDir) { | ||
await fs.mkdir(nextDir, { recursive: true }); | ||
await checkExistingDirectories(appConfigs.map(config => config.name), nextDir); | ||
} | ||
console.log(chalk.cyan(figlet.textSync('Next.js Apps', { horizontalLayout: 'full' }))); | ||
// Ask for chains first | ||
const selectedChains = await promptForChains(); | ||
const hasEthereum = selectedChains.some(chain => chain.name === 'Ethereum'); | ||
let appConfigs; | ||
if (hasEthereum) { | ||
appConfigs = [ | ||
{ name: 'next-app-viem', useViem: true, useWagmi: false }, | ||
{ name: 'next-app-viem-wagmi', useViem: true, useWagmi: true }, | ||
{ name: 'next-app-ethers', useViem: false, useWagmi: false }, | ||
]; | ||
} else { | ||
appConfigs = [ | ||
{ name: 'next-app-vanilla', useViem: false, useWagmi: false }, | ||
]; | ||
} | ||
if (!customDir) { | ||
await checkExistingDirectories(appConfigs.map(config => config.name), nextDir); | ||
} | ||
console.log(chalk.yellow(`\nš About to generate ${appConfigs.length} example app${appConfigs.length > 1 ? 's' : ''}:\n`)); | ||
appConfigs.forEach(config => { | ||
const nextIcon = 'ā² '; // Next.js icon (triangle) | ||
const viemIcon = config.useViem ? 'š· ' : 'š '; // Viem icon (blue diamond) or Ethers icon (blue book) | ||
const wagmiIcon = config.useWagmi ? 'š ' : ''; // Wagmi icon (chain link) | ||
console.log(chalk.green(`${nextIcon}${viemIcon}${config.name} ${wagmiIcon}`)); | ||
}); | ||
console.log(chalk.yellow('\nGenerating apps... š ļø\n')); | ||
await Promise.all(appConfigs.map(config => | ||
@@ -97,0 +124,0 @@ generateNextApp(nextDir, config.name, config.useViem, config.useWagmi, selectedChains) |
import fs from 'fs/promises'; | ||
import path from 'path'; | ||
import { execSync } from 'child_process'; | ||
import figlet from 'figlet'; | ||
import mainCss from './react-templates/mainCss.js'; | ||
import mainJs from './react-templates/main.js'; | ||
import generateAppJsContent from './react-templates/app.js'; | ||
import { addSolanaDependencies, createConfigOverrides } from './react-templates/solana-config.js'; | ||
import { addSolanaDependencies, createConfigOverrides, updatePackageJsonScripts } from './react-templates/solana-config.js'; | ||
import { promptForChains, checkExistingDirectories } from './utils.js'; | ||
@@ -26,3 +27,3 @@ import chalk from 'chalk'; | ||
"react-scripts": "5.0.1", | ||
...(useViem ? { viem: "*" } : { "@dynamic-labs/ethers-v6": "^3.0.0-alpha" }), | ||
...(useViem && selectedChains.some(chain => chain.name === 'Ethereum') ? { viem: "*" } : !useViem && selectedChains.some(chain => chain.name === 'Ethereum') ?{ "@dynamic-labs/ethers-v6": "^3.0.0-alpha" } : {}), | ||
...(useWagmi && { | ||
@@ -78,2 +79,5 @@ "@dynamic-labs/wagmi-connector": "^3.0.0-alpha", | ||
try { | ||
// Ensure the public directory exists | ||
await fs.mkdir(publicDir, { recursive: true }); | ||
const files = await fs.readdir(assetsDir); | ||
@@ -84,6 +88,6 @@ await Promise.all(files.map(file => | ||
} catch (error) { | ||
if (error.code === 'ENOENT') { | ||
if (error.code === 'ENOENT' && error.path === assetsDir) { | ||
console.log(chalk.yellow('Assets folder not found. Skipping asset copy.')); | ||
} else { | ||
throw error; | ||
console.error(chalk.red(`Error copying assets: ${error.message}`)); | ||
} | ||
@@ -96,22 +100,42 @@ } | ||
const reactDir = customDir ? process.cwd() : path.join(process.cwd(), 'react'); | ||
const appNames = ['react-viem', 'react-viem-wagmi', 'react-ethers', 'react-ethers-wagmi']; | ||
if (!customDir) { | ||
await fs.mkdir(reactDir, { recursive: true }); | ||
await checkExistingDirectories(appNames, reactDir); | ||
} | ||
console.log(chalk.cyan(figlet.textSync('React Apps', { horizontalLayout: 'full' }))); | ||
const selectedChains = await promptForChains(); | ||
const hasEthereum = selectedChains.some(chain => chain.name === 'Ethereum'); | ||
const apps = [ | ||
{ name: customDir || 'react-viem', useViem: true, useWagmi: false }, | ||
...(customDir ? [] : [ | ||
{ name: 'react-viem-wagmi', useViem: true, useWagmi: true }, | ||
{ name: 'react-ethers', useViem: false, useWagmi: false }, | ||
{ name: 'react-ethers-wagmi', useViem: false, useWagmi: true } | ||
]) | ||
]; | ||
let appConfigs; | ||
if (hasEthereum) { | ||
appConfigs = [ | ||
{ name: 'react-app-viem', useViem: true, useWagmi: false }, | ||
{ name: 'react-app-viem-wagmi', useViem: true, useWagmi: true }, | ||
{ name: 'react-app-ethers', useViem: false, useWagmi: false }, | ||
]; | ||
} else { | ||
appConfigs = [ | ||
{ name: 'react-app-vanilla', useViem: false, useWagmi: false }, | ||
]; | ||
} | ||
await Promise.all(apps.map(app => | ||
generateReactApp(reactDir, app.name, app.useViem, app.useWagmi, selectedChains) | ||
if (!customDir) { | ||
await checkExistingDirectories(appConfigs.map(config => config.name), reactDir); | ||
} | ||
console.log(chalk.yellow(`\nš About to generate ${appConfigs.length} example app${appConfigs.length > 1 ? 's' : ''}:\n`)); | ||
appConfigs.forEach(config => { | ||
const reactIcon = 'āļø '; // React icon | ||
const viemIcon = config.useViem ? 'š· ' : (hasEthereum && !config.useViem ? 'š ' : ''); // Viem icon (blue diamond) or Ethers icon (blue book) if Ethereum | ||
const wagmiIcon = config.useWagmi ? 'š ' : ''; // Wagmi icon (chain link) | ||
console.log(chalk.green(`${reactIcon}${viemIcon}${config.name} ${wagmiIcon}`)); | ||
}); | ||
console.log(chalk.yellow('\nGenerating app(s)... š ļø\n')); | ||
await Promise.all(appConfigs.map(config => | ||
generateReactApp(reactDir, config.name, config.useViem, config.useWagmi, selectedChains) | ||
)); | ||
@@ -122,10 +146,10 @@ | ||
} else { | ||
const createdApps = (await Promise.all(apps.map(async app => | ||
(await fs.stat(path.join(reactDir, app.name)).catch(() => null)) ? app.name : null | ||
const createdApps = (await Promise.all(appConfigs.map(async config => | ||
(await fs.stat(path.join(reactDir, config.name)).catch(() => null)) ? config.name : null | ||
))).filter(Boolean); | ||
if (createdApps.length === apps.length) { | ||
if (createdApps.length === appConfigs.length) { | ||
console.log(chalk.green('All example apps were created successfully in the "react" directory.')); | ||
} else { | ||
const missingApps = apps.map(app => app.name).filter(name => !createdApps.includes(name)); | ||
const missingApps = appConfigs.map(config => config.name).filter(name => !createdApps.includes(name)); | ||
console.error(chalk.red(`Error: The following apps were not created: ${missingApps.join(', ')}`)); | ||
@@ -132,0 +156,0 @@ } |
@@ -1,10 +0,5 @@ | ||
const generateDynamicLibContent = (useViem, useWagmi) => { | ||
const generateDynamicLibContent = (useViem, useWagmi, selectedChains) => { | ||
let imports = `export * from "@dynamic-labs/sdk-react-core";\n`; | ||
imports += `export * from "@dynamic-labs/ethereum";\n`; | ||
if (useWagmi) { | ||
imports += `export * from "@dynamic-labs/wagmi-connector";\n`; | ||
} | ||
if (!useViem) { | ||
if (!useViem && selectedChains.some(chain => chain.name === 'Ethereum')) { | ||
imports += `export * from "@dynamic-labs/ethers-v6";\n`; | ||
@@ -11,0 +6,0 @@ } |
@@ -1,17 +0,7 @@ | ||
const generateLayoutContent = (useViem, useWagmi, selectedChains) => { | ||
const generateLayoutContent = () => { | ||
let imports = `import "./globals.css";\n`; | ||
imports += `import type { Metadata } from "next";\n`; | ||
imports += `import { Inter } from "next/font/google";\n`; | ||
if (useWagmi) { | ||
imports += `import Providers from "@/lib/providers";\n`; | ||
} else { | ||
imports += `import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";\n`; | ||
selectedChains.forEach(chain => { | ||
imports += `import { ${chain.connector} } from "${chain.package}";\n`; | ||
}); | ||
} | ||
const walletConnectors = selectedChains.map(chain => chain.connector).join(', '); | ||
imports += `import Providers from "@/lib/providers";\n`; | ||
let content = ` | ||
@@ -32,14 +22,3 @@ const inter = Inter({ subsets: ["latin"] }); | ||
<html lang="en"> | ||
${useWagmi | ||
? '<Providers><body className={inter.className}>{children}</body></Providers>' | ||
: `<DynamicContextProvider | ||
theme="auto" | ||
settings={{ | ||
environmentId: "2762a57b-faa4-41ce-9f16-abff9300e2c9", | ||
walletConnectors: [${walletConnectors}], | ||
}} | ||
> | ||
<body className={inter.className}>{children}</body> | ||
</DynamicContextProvider>` | ||
} | ||
<Providers><body className={inter.className}>{children}</body></Providers> | ||
</html> | ||
@@ -46,0 +25,0 @@ ); |
const page = ` | ||
'use client'; | ||
import { DynamicWidget } from "@dynamic-labs/sdk-react-core"; | ||
import { DynamicWidget } from "@/lib/dynamic"; | ||
import { useState, useEffect } from 'react'; | ||
@@ -6,0 +6,0 @@ import './page.css'; |
@@ -1,5 +0,8 @@ | ||
const generateProvidersContent = (useWagmi) => { | ||
const generateProvidersContent = (useWagmi, selectedChains) => { | ||
let imports = `'use client';\n\n`; | ||
imports += `import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core";\n`; | ||
imports += `import { EthereumWalletConnectors } from "@dynamic-labs/ethereum";\n`; | ||
selectedChains.forEach(chain => { | ||
imports += `import { ${chain.connector} } from "${chain.package}";\n`; | ||
}); | ||
@@ -13,2 +16,4 @@ if (useWagmi) { | ||
const walletConnectors = selectedChains.map(chain => chain.connector).join(', '); | ||
let content = ` | ||
@@ -20,9 +25,11 @@ export default function Providers({ | ||
}) { | ||
const queryClient = new QueryClient(); | ||
${useWagmi ? `const queryClient = new QueryClient();` : ''} | ||
return ( | ||
<DynamicContextProvider | ||
theme="auto" | ||
settings={{ | ||
environmentId: "2762a57b-faa4-41ce-9f16-abff9300e2c9", | ||
walletConnectors: [EthereumWalletConnectors] | ||
walletConnectors: [${walletConnectors}], | ||
}} | ||
@@ -29,0 +36,0 @@ > |
{ | ||
"name": "create-dynamic-app", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"scripts": { | ||
@@ -5,0 +5,0 @@ "generate-react": "node generate-react.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
405800
982
2