Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More ā†’
Socket
Sign inDemoInstall
Socket

create-dynamic-app

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

create-dynamic-app - npm Package Compare versions

Comparing version 2.0.0 to 2.0.1

58

create-dynamic-app.js

@@ -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",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with āš”ļø by Socket Inc