create-universal-dapp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/commands/create.d.ts +2 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +52 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/nextjs.d.ts +3 -0
- package/dist/templates/nextjs.d.ts.map +1 -0
- package/dist/templates/nextjs.js +406 -0
- package/dist/templates/nextjs.js.map +1 -0
- package/dist/templates/vite.d.ts +3 -0
- package/dist/templates/vite.d.ts.map +1 -0
- package/dist/templates/vite.js +784 -0
- package/dist/templates/vite.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/package-manager.d.ts +4 -0
- package/dist/utils/package-manager.d.ts.map +1 -0
- package/dist/utils/package-manager.js +67 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/prompts.d.ts +3 -0
- package/dist/utils/prompts.d.ts.map +1 -0
- package/dist/utils/prompts.js +55 -0
- package/dist/utils/prompts.js.map +1 -0
- package/package.json +66 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# create-universal-dapp
|
|
2
|
+
|
|
3
|
+
A CLI tool to scaffold Push Chain applications with your choice of framework and tooling.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g create-universal-dapp
|
|
9
|
+
create-universal-dapp my-app
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or use npx:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx create-universal-dapp my-app
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- ⚡ **Multiple Frameworks**: Choose between Next.js or Vite (React)
|
|
21
|
+
- 🔧 **ESLint**: Optional code linting setup
|
|
22
|
+
- 📦 **Push Chain Integration**: Pre-configured with @pushchain/core and @pushchain/ui-kit
|
|
23
|
+
- 🚀 **TypeScript**: Full TypeScript support out of the box
|
|
24
|
+
- 🎨 **Styling**: Tailwind CSS set up by default
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Interactive Mode
|
|
29
|
+
|
|
30
|
+
Run the CLI without arguments to enter interactive mode:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
create-universal-dapp
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You'll be prompted to:
|
|
37
|
+
1. Choose your project name
|
|
38
|
+
2. Select a framework (Next.js or Vite)
|
|
39
|
+
3. Enable/disable ESLint
|
|
40
|
+
|
|
41
|
+
### Command Line Options
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
create-universal-dapp my-app --framework nextjs --eslint
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Available options:
|
|
48
|
+
- `-f, --framework <framework>`: Choose 'nextjs' or 'vite'
|
|
49
|
+
- `--eslint / --no-eslint`: Include/exclude ESLint configuration
|
|
50
|
+
|
|
51
|
+
## Generated Project Structure
|
|
52
|
+
|
|
53
|
+
### Next.js Project
|
|
54
|
+
```
|
|
55
|
+
my-app/
|
|
56
|
+
├── src/
|
|
57
|
+
│ ├── app/
|
|
58
|
+
│ │ ├── globals.css
|
|
59
|
+
│ │ ├── layout.tsx
|
|
60
|
+
│ │ └── page.tsx
|
|
61
|
+
│ ├── components/
|
|
62
|
+
│ └── lib/
|
|
63
|
+
│ ├── pushchain.tsx # Push Chain provider
|
|
64
|
+
│ └── utils.ts # Utility functions
|
|
65
|
+
├── package.json
|
|
66
|
+
├── next.config.js
|
|
67
|
+
├── tsconfig.json
|
|
68
|
+
└── tailwind.config.js
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Vite Project
|
|
72
|
+
```
|
|
73
|
+
my-app/
|
|
74
|
+
├── src/
|
|
75
|
+
│ ├── components/
|
|
76
|
+
│ ├── lib/
|
|
77
|
+
│ │ ├── pushchain.tsx # Push Chain provider
|
|
78
|
+
│ │ └── utils.ts # Utility functions
|
|
79
|
+
│ ├── App.tsx
|
|
80
|
+
│ ├── main.tsx
|
|
81
|
+
│ └── index.css
|
|
82
|
+
├── index.html
|
|
83
|
+
├── package.json
|
|
84
|
+
├── vite.config.ts
|
|
85
|
+
├── tsconfig.json
|
|
86
|
+
└── tailwind.config.js
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Push Chain Integration
|
|
90
|
+
|
|
91
|
+
The generated project includes:
|
|
92
|
+
|
|
93
|
+
### 1. PushChain Provider
|
|
94
|
+
A React context provider that manages the Push Chain connection:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import { usePushChain } from '@/lib/pushchain'
|
|
98
|
+
|
|
99
|
+
function MyComponent() {
|
|
100
|
+
const { pushChain, isConnected, connect, disconnect, error } = usePushChain()
|
|
101
|
+
|
|
102
|
+
// Use Push Chain methods here
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 2. Demo Component
|
|
107
|
+
A working example showing how to:
|
|
108
|
+
- Connect to Push Chain
|
|
109
|
+
- Send messages
|
|
110
|
+
- Handle errors
|
|
111
|
+
- Display connection status
|
|
112
|
+
|
|
113
|
+
### 3. Environment Variables
|
|
114
|
+
Configure your Push Chain settings:
|
|
115
|
+
|
|
116
|
+
```env
|
|
117
|
+
# Next.js
|
|
118
|
+
NEXT_PUBLIC_PUSHCHAIN_API_KEY=your_api_key_here
|
|
119
|
+
NEXT_PUBLIC_PUSHCHAIN_NETWORK=testnet
|
|
120
|
+
|
|
121
|
+
# Vite
|
|
122
|
+
VITE_PUSHCHAIN_API_KEY=your_api_key_here
|
|
123
|
+
VITE_PUSHCHAIN_NETWORK=testnet
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Development
|
|
127
|
+
|
|
128
|
+
To work on this CLI tool:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git clone https://github.com/pushchainxyz/create-universal-dapp
|
|
132
|
+
cd create-universal-dapp
|
|
133
|
+
npm install
|
|
134
|
+
npm run build
|
|
135
|
+
npm link
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Then you can test it:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
create-universal-dapp test-app
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Scripts
|
|
145
|
+
|
|
146
|
+
- `npm run build` - Build the CLI
|
|
147
|
+
- `npm run dev` - Run in development mode
|
|
148
|
+
- `npm start` - Run the built CLI
|
|
149
|
+
|
|
150
|
+
## Next Steps
|
|
151
|
+
|
|
152
|
+
After creating your project:
|
|
153
|
+
|
|
154
|
+
1. **Configure Environment Variables**: Set up your Push Chain API keys
|
|
155
|
+
2. **Customize the Integration**: Replace example code with your specific Push Chain functionality
|
|
156
|
+
3. **Add Features**: Build upon the generated structure
|
|
157
|
+
4. **Explore Push Chain**: Check out the @pushchain/ui-kit for additional components
|
|
158
|
+
|
|
159
|
+
## Contributing
|
|
160
|
+
|
|
161
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAUA,wBAAsB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,iBAmDtE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import { getProjectOptions } from '../utils/prompts.js';
|
|
5
|
+
import { createNextjsApp } from '../templates/nextjs.js';
|
|
6
|
+
import { createViteApp } from '../templates/vite.js';
|
|
7
|
+
export async function createPushApp(projectName, options) {
|
|
8
|
+
try {
|
|
9
|
+
// Get project configuration from user
|
|
10
|
+
const projectOptions = await getProjectOptions(projectName, options);
|
|
11
|
+
console.log(chalk.blue('\n📋 Project Configuration:'));
|
|
12
|
+
console.log(chalk.gray(` Project Name: ${projectOptions.projectName}`));
|
|
13
|
+
console.log(chalk.gray(` Framework: ${projectOptions.framework}`));
|
|
14
|
+
console.log(chalk.gray(` ESLint: ${projectOptions.eslint ? 'Yes' : 'No'}`));
|
|
15
|
+
console.log(chalk.gray(` Target Directory: ${projectOptions.targetDir}\n`));
|
|
16
|
+
// Check if directory already exists
|
|
17
|
+
if (await fs.pathExists(projectOptions.targetDir)) {
|
|
18
|
+
console.log(chalk.red(`❌ Directory ${projectOptions.projectName} already exists!`));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
// Create project directory
|
|
22
|
+
const spinner = ora('Creating project directory...').start();
|
|
23
|
+
await fs.ensureDir(projectOptions.targetDir);
|
|
24
|
+
spinner.succeed('Project directory created');
|
|
25
|
+
// Generate project based on framework choice
|
|
26
|
+
if (projectOptions.framework === 'nextjs') {
|
|
27
|
+
await createNextjsApp(projectOptions);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
await createViteApp(projectOptions);
|
|
31
|
+
}
|
|
32
|
+
// Skipping auto-install to save time; user will install manually
|
|
33
|
+
console.log(chalk.green(`
|
|
34
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
35
|
+
`));
|
|
36
|
+
console.log(chalk.green.bold(` 🎉 SUCCESS! Project Created! 🎉 `));
|
|
37
|
+
console.log(chalk.cyan(` Your Push Chain Universal App is ready to go! `));
|
|
38
|
+
console.log(chalk.green(`
|
|
39
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
40
|
+
`));
|
|
41
|
+
console.log(chalk.blue.bold('\n🚀 Next Steps:'));
|
|
42
|
+
console.log(chalk.white(` cd ${projectOptions.projectName}`));
|
|
43
|
+
console.log(chalk.white(` npm install`));
|
|
44
|
+
console.log(chalk.white(` npm run dev`));
|
|
45
|
+
console.log(chalk.green('\n Happy Building! 🚀✨\n'));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error(chalk.red('❌ Error creating project:'), error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAoB,EAAE,OAAa;IACrE,IAAI,CAAC;QACH,sCAAsC;QACtC,MAAM,cAAc,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAErE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC9E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wBAAwB,cAAc,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;QAE9E,oCAAoC;QACpC,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,cAAc,CAAC,WAAW,kBAAkB,CAAC,CAAC,CAAC;YACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,2BAA2B;QAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,+BAA+B,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAE7C,6CAA6C;QAC7C,IAAI,cAAc,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,eAAe,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,MAAM,aAAa,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;QAED,iEAAiE;QAEjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;;KAEvB,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,gGAAgG,CAAC,CAAC,CAAC;QAChI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gGAAgG,CAAC,CAAC,CAAC;QAC1H,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;;KAEvB,CAAC,CAAC,CAAC;QAEJ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC;QAE3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;IAEzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,2BAA2B,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { createPushApp } from './commands/create.js';
|
|
5
|
+
console.log(chalk.cyan.bold(`
|
|
6
|
+
$$$$$$\\ $$\\ $$$$$$\\ $$\\ $$\\
|
|
7
|
+
$$ __$$\\ $$ | $$ __$$\\ $$ | $$\\
|
|
8
|
+
$$ / $$ |$$\\ $$\\ $$$$$$$\\ $$$$$$$\\ $$ / \\__|$$$$$$$\\ $$$$$$\\ $$ |$$$$$$$\\
|
|
9
|
+
$$$$$$$ |$$ | $$ |$$ _____| $$ __$$\\ $$ | $$ __$$\\ \\____$$\\ $$ |$$ __$$\\
|
|
10
|
+
$$ ____/ $$ | $$ |\\$$$$$$\\ $$ | $$ | $$ | $$ | $$ | $$$$$$$ |$$ |$$ | $$ |
|
|
11
|
+
$$ | $$ | $$ | \\____$$\\ $$ | $$ | $$ | $$\\ $$ | $$ |$$ __$$ |$$ |$$ | $$ |
|
|
12
|
+
$$ | \\$$$$$$ |$$$$$$$ | $$ | $$ | \\$$$$$$ |$$ | $$ |\\$$$$$$$ |$$ |$$ | $$ |
|
|
13
|
+
\\__| \\______/ \\_______/ \\__| \\__| \\______/ \\__| \\__| \\_______|\\__|\\__| \\__|
|
|
14
|
+
`));
|
|
15
|
+
program
|
|
16
|
+
.name('create-universal-dapp')
|
|
17
|
+
.description('CLI tool to scaffold Push Chain universal applications')
|
|
18
|
+
.version('1.0.0');
|
|
19
|
+
program
|
|
20
|
+
.argument('[project-name]', 'name of the project')
|
|
21
|
+
.option('-f, --framework <framework>', 'framework to use (nextjs or vite)')
|
|
22
|
+
.option('--eslint', 'include ESLint configuration')
|
|
23
|
+
.option('--no-eslint', 'skip ESLint configuration')
|
|
24
|
+
.action(createPushApp);
|
|
25
|
+
program.parse();
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;;;;;;;;;CAS3B,CAAC,CAAC,CAAC;AAEJ,OAAO;KACJ,IAAI,CAAC,uBAAuB,CAAC;KAC7B,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;KACjD,MAAM,CAAC,6BAA6B,EAAE,mCAAmC,CAAC;KAC1E,MAAM,CAAC,UAAU,EAAE,8BAA8B,CAAC;KAClD,MAAM,CAAC,aAAa,EAAE,2BAA2B,CAAC;KAClD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../src/templates/nextjs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,wBAAsB,eAAe,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6B5E"}
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
export async function createNextjsApp(options) {
|
|
5
|
+
const spinner = ora('Setting up Next.js project...').start();
|
|
6
|
+
try {
|
|
7
|
+
// Create package.json
|
|
8
|
+
await createNextjsPackageJson(options);
|
|
9
|
+
// Create Next.js configuration files
|
|
10
|
+
await createNextjsConfig(options);
|
|
11
|
+
// Create source structure
|
|
12
|
+
await createNextjsSourceFiles(options);
|
|
13
|
+
// Create Push Chain integration files
|
|
14
|
+
await createPushChainIntegration(options);
|
|
15
|
+
// Create ESLint config if requested
|
|
16
|
+
if (options.eslint) {
|
|
17
|
+
await createESLintConfig(options);
|
|
18
|
+
}
|
|
19
|
+
// Create Tailwind config (Tailwind-only setup)
|
|
20
|
+
await createTailwindConfig(options);
|
|
21
|
+
spinner.succeed('Next.js project structure created');
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
spinner.fail('Failed to create Next.js project');
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function createNextjsPackageJson(options) {
|
|
29
|
+
const packageJson = {
|
|
30
|
+
name: options.projectName,
|
|
31
|
+
version: "0.1.0",
|
|
32
|
+
private: true,
|
|
33
|
+
scripts: {
|
|
34
|
+
dev: "next dev",
|
|
35
|
+
build: "next build",
|
|
36
|
+
start: "next start",
|
|
37
|
+
lint: options.eslint ? "next lint" : undefined
|
|
38
|
+
},
|
|
39
|
+
dependencies: {
|
|
40
|
+
react: "^18.3.1",
|
|
41
|
+
"react-dom": "^18.3.1",
|
|
42
|
+
next: "^14.0.0",
|
|
43
|
+
"@pushchain/ui-kit": "^1.1.33"
|
|
44
|
+
},
|
|
45
|
+
devDependencies: {
|
|
46
|
+
typescript: "^5.2.2",
|
|
47
|
+
"@types/node": "^20.8.0",
|
|
48
|
+
"@types/react": "^18.2.33",
|
|
49
|
+
"@types/react-dom": "^18.2.14",
|
|
50
|
+
tailwindcss: "^3.3.0",
|
|
51
|
+
autoprefixer: "^10.4.16",
|
|
52
|
+
postcss: "^8.4.31"
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
// Remove undefined values
|
|
56
|
+
Object.keys(packageJson.scripts).forEach(key => {
|
|
57
|
+
const scripts = packageJson.scripts;
|
|
58
|
+
if (scripts[key] === undefined) {
|
|
59
|
+
delete scripts[key];
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
await fs.writeJSON(path.join(options.targetDir, 'package.json'), packageJson, { spaces: 2 });
|
|
63
|
+
}
|
|
64
|
+
async function createNextjsConfig(options) {
|
|
65
|
+
// Next.js config
|
|
66
|
+
const nextConfig = `/** @type {import('next').NextConfig} */
|
|
67
|
+
const nextConfig = {
|
|
68
|
+
// Add any Next.js config options here
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = nextConfig`;
|
|
72
|
+
await fs.writeFile(path.join(options.targetDir, 'next.config.js'), nextConfig);
|
|
73
|
+
// TypeScript config
|
|
74
|
+
const tsConfig = {
|
|
75
|
+
compilerOptions: {
|
|
76
|
+
target: "es5",
|
|
77
|
+
lib: ["dom", "dom.iterable", "es6"],
|
|
78
|
+
allowJs: true,
|
|
79
|
+
skipLibCheck: true,
|
|
80
|
+
strict: true,
|
|
81
|
+
forceConsistentCasingInFileNames: true,
|
|
82
|
+
noEmit: true,
|
|
83
|
+
esModuleInterop: true,
|
|
84
|
+
module: "esnext",
|
|
85
|
+
moduleResolution: "bundler",
|
|
86
|
+
resolveJsonModule: true,
|
|
87
|
+
isolatedModules: true,
|
|
88
|
+
jsx: "preserve",
|
|
89
|
+
incremental: true,
|
|
90
|
+
plugins: [
|
|
91
|
+
{
|
|
92
|
+
name: "next"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
baseUrl: ".",
|
|
96
|
+
paths: {
|
|
97
|
+
"@/*": ["./src/*"]
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
101
|
+
exclude: ["node_modules"]
|
|
102
|
+
};
|
|
103
|
+
await fs.writeJSON(path.join(options.targetDir, 'tsconfig.json'), tsConfig, { spaces: 2 });
|
|
104
|
+
}
|
|
105
|
+
async function createNextjsSourceFiles(options) {
|
|
106
|
+
// Create src directory structure
|
|
107
|
+
const srcDir = path.join(options.targetDir, 'src');
|
|
108
|
+
const appDir = path.join(srcDir, 'app');
|
|
109
|
+
await fs.ensureDir(appDir);
|
|
110
|
+
// Create app layout
|
|
111
|
+
const layout = `import './globals.css'
|
|
112
|
+
import { Inter } from 'next/font/google'
|
|
113
|
+
import { PushChainProviders } from '@/providers/PushChainProviders'
|
|
114
|
+
import type { Metadata } from 'next'
|
|
115
|
+
|
|
116
|
+
const inter = Inter({ subsets: ['latin'] })
|
|
117
|
+
|
|
118
|
+
export const metadata: Metadata = {
|
|
119
|
+
title: '${options.projectName}',
|
|
120
|
+
description: 'A Push Chain application built with Next.js - enabling universal blockchain access and shared state management.',
|
|
121
|
+
keywords: ['Push Chain', 'blockchain', 'Web3', 'universal wallet', 'Next.js'],
|
|
122
|
+
authors: [{ name: '${options.projectName} Team' }],
|
|
123
|
+
creator: '${options.projectName}',
|
|
124
|
+
publisher: '${options.projectName}',
|
|
125
|
+
formatDetection: {
|
|
126
|
+
email: false,
|
|
127
|
+
address: false,
|
|
128
|
+
telephone: false,
|
|
129
|
+
},
|
|
130
|
+
metadataBase: new URL('https://your-domain.com'), // Replace with your actual domain
|
|
131
|
+
openGraph: {
|
|
132
|
+
title: '${options.projectName}',
|
|
133
|
+
description: 'A Push Chain application built with Next.js',
|
|
134
|
+
url: 'https://your-domain.com', // Replace with your actual URL
|
|
135
|
+
siteName: '${options.projectName}',
|
|
136
|
+
locale: 'en_US',
|
|
137
|
+
type: 'website',
|
|
138
|
+
},
|
|
139
|
+
twitter: {
|
|
140
|
+
card: 'summary_large_image',
|
|
141
|
+
title: '${options.projectName}',
|
|
142
|
+
description: 'A Push Chain application built with Next.js',
|
|
143
|
+
creator: '@your_twitter_handle', // Replace with your Twitter handle
|
|
144
|
+
},
|
|
145
|
+
robots: {
|
|
146
|
+
index: true,
|
|
147
|
+
follow: true,
|
|
148
|
+
googleBot: {
|
|
149
|
+
index: true,
|
|
150
|
+
follow: true,
|
|
151
|
+
'max-video-preview': -1,
|
|
152
|
+
'max-image-preview': 'large',
|
|
153
|
+
'max-snippet': -1,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export default function RootLayout({
|
|
159
|
+
children,
|
|
160
|
+
}: {
|
|
161
|
+
children: React.ReactNode
|
|
162
|
+
}) {
|
|
163
|
+
return (
|
|
164
|
+
<html lang="en">
|
|
165
|
+
<body className={inter.className}>
|
|
166
|
+
<PushChainProviders>
|
|
167
|
+
{children}
|
|
168
|
+
</PushChainProviders>
|
|
169
|
+
</body>
|
|
170
|
+
</html>
|
|
171
|
+
)
|
|
172
|
+
}`;
|
|
173
|
+
await fs.writeFile(path.join(appDir, 'layout.tsx'), layout);
|
|
174
|
+
// Create main page
|
|
175
|
+
const page = `'use client'
|
|
176
|
+
|
|
177
|
+
import { PushUniversalAccountButton, usePushWalletContext } from '@pushchain/ui-kit'
|
|
178
|
+
|
|
179
|
+
export default function Home() {
|
|
180
|
+
const { universalAccount } = usePushWalletContext();
|
|
181
|
+
|
|
182
|
+
console.log("universalAccount", universalAccount);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<main className="min-h-screen bg-white text-gray-900 p-8">
|
|
186
|
+
<div className="container mx-auto max-w-4xl">
|
|
187
|
+
<div className="text-center mb-8">
|
|
188
|
+
<h1 className="text-4xl font-bold mb-4">
|
|
189
|
+
Welcome to ${options.projectName}
|
|
190
|
+
</h1>
|
|
191
|
+
<p className="text-lg text-gray-600 mb-8">
|
|
192
|
+
Your Push Chain application is ready to go!
|
|
193
|
+
</p>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<div className="max-w-2xl mx-auto border rounded-lg shadow-sm p-6">
|
|
197
|
+
<div className="flex items-center justify-between mb-4">
|
|
198
|
+
<h2 className="text-2xl font-semibold">Push Chain Integration</h2>
|
|
199
|
+
<span className={"inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold text-white " + (universalAccount ? 'bg-green-500' : 'bg-gray-500')}>
|
|
200
|
+
{universalAccount ? 'Connected' : 'Not Connected'}
|
|
201
|
+
</span>
|
|
202
|
+
</div>
|
|
203
|
+
|
|
204
|
+
<div className="flex justify-center mb-6">
|
|
205
|
+
<PushUniversalAccountButton />
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{universalAccount && (
|
|
209
|
+
<div className="mt-6 p-4 bg-gray-100 rounded-lg">
|
|
210
|
+
<h3 className="font-semibold mb-2">Account Details:</h3>
|
|
211
|
+
<pre className="text-sm overflow-auto">
|
|
212
|
+
{JSON.stringify(universalAccount, null, 2)}
|
|
213
|
+
</pre>
|
|
214
|
+
</div>
|
|
215
|
+
)}
|
|
216
|
+
|
|
217
|
+
<div className="text-sm text-gray-600 mt-6">
|
|
218
|
+
<p className="font-medium">Next steps:</p>
|
|
219
|
+
<ul className="list-disc list-inside space-y-1 mt-2">
|
|
220
|
+
<li>Configure your Push Chain settings in providers/PushChainProviders.tsx</li>
|
|
221
|
+
<li>Customize the app metadata in app/layout.tsx</li>
|
|
222
|
+
<li>Add your chain configuration and RPC URLs</li>
|
|
223
|
+
<li>Explore the @pushchain/ui-kit for more components</li>
|
|
224
|
+
</ul>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
</main>
|
|
229
|
+
)
|
|
230
|
+
}`;
|
|
231
|
+
await fs.writeFile(path.join(appDir, 'page.tsx'), page);
|
|
232
|
+
// Create global CSS (Tailwind directives only)
|
|
233
|
+
const globalCss = `@tailwind base;
|
|
234
|
+
@tailwind components;
|
|
235
|
+
@tailwind utilities;`;
|
|
236
|
+
await fs.writeFile(path.join(appDir, 'globals.css'), globalCss);
|
|
237
|
+
}
|
|
238
|
+
async function createPushChainIntegration(options) {
|
|
239
|
+
// Create providers directory
|
|
240
|
+
const providersDir = path.join(options.targetDir, 'src', 'providers');
|
|
241
|
+
await fs.ensureDir(providersDir);
|
|
242
|
+
// Create PushChainProviders.tsx following your pattern but with Next.js specific comments
|
|
243
|
+
const pushchainProviders = `'use client'
|
|
244
|
+
|
|
245
|
+
import {
|
|
246
|
+
PushUI,
|
|
247
|
+
PushUniversalWalletProvider,
|
|
248
|
+
type AppMetadata,
|
|
249
|
+
type ProviderConfigProps,
|
|
250
|
+
} from "@pushchain/ui-kit";
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* PushChainProviders Component for Next.js
|
|
254
|
+
*
|
|
255
|
+
* This component wraps your entire Next.js application with Push Chain's Universal Wallet Provider.
|
|
256
|
+
* It configures the wallet connection options, network settings, and app metadata.
|
|
257
|
+
*
|
|
258
|
+
* Configuration Guide:
|
|
259
|
+
* - network: Choose between MAINNET, TESTNET, or DEV
|
|
260
|
+
* - login: Configure authentication methods (email, google, wallet)
|
|
261
|
+
* - modal: Customize the UI appearance and behavior
|
|
262
|
+
* - chainConfig: Add your custom RPC endpoints
|
|
263
|
+
* - appMetadata: Brand your app with logo, title, and description
|
|
264
|
+
*
|
|
265
|
+
* Next.js Specific Notes:
|
|
266
|
+
* - This component uses 'use client' directive for client-side functionality
|
|
267
|
+
* - Environment variables should be prefixed with NEXT_PUBLIC_ for client access
|
|
268
|
+
* - Metadata is also configured in app/layout.tsx for SEO
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
const PushChainProviders = ({ children }: { children: React.ReactNode }) => {
|
|
272
|
+
// Wallet configuration - customize these settings for your app
|
|
273
|
+
const walletConfig: ProviderConfigProps = {
|
|
274
|
+
// Network selection: MAINNET for production, TESTNET for development
|
|
275
|
+
network: PushUI.CONSTANTS.PUSH_NETWORK.TESTNET,
|
|
276
|
+
|
|
277
|
+
// Login options - enable/disable authentication methods
|
|
278
|
+
login: {
|
|
279
|
+
email: true, // Allow email authentication
|
|
280
|
+
google: true, // Allow Google OAuth
|
|
281
|
+
wallet: {
|
|
282
|
+
enabled: true, // Allow wallet connection (MetaMask, etc.)
|
|
283
|
+
},
|
|
284
|
+
appPreview: true, // Show app preview in login modal
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
// Modal UI customization
|
|
288
|
+
modal: {
|
|
289
|
+
// Layout: SPLIT (side-by-side) or STACKED (vertical)
|
|
290
|
+
loginLayout: PushUI.CONSTANTS.LOGIN.LAYOUT.SPLIT,
|
|
291
|
+
|
|
292
|
+
// Connected wallet display: HOVER (on hover) or FULL (always visible)
|
|
293
|
+
connectedLayout: PushUI.CONSTANTS.CONNECTED.LAYOUT.HOVER,
|
|
294
|
+
|
|
295
|
+
// Show app preview in modals
|
|
296
|
+
appPreview: true,
|
|
297
|
+
|
|
298
|
+
// Background interaction when modal is open: BLUR or NONE
|
|
299
|
+
connectedInteraction: PushUI.CONSTANTS.CONNECTED.INTERACTION.BLUR,
|
|
300
|
+
},
|
|
301
|
+
|
|
302
|
+
// Chain configuration - add your custom RPC endpoints here
|
|
303
|
+
chainConfig: {
|
|
304
|
+
rpcUrls: {
|
|
305
|
+
// Ethereum Sepolia testnet (for testing)
|
|
306
|
+
"eip155:11155111": ["https://sepolia.gateway.tenderly.co/"],
|
|
307
|
+
|
|
308
|
+
// Add more chains as needed:
|
|
309
|
+
// "eip155:1": ["https://mainnet.infura.io/v3/YOUR_PROJECT_ID"], // Ethereum Mainnet
|
|
310
|
+
// "eip155:137": ["https://polygon-rpc.com/"], // Polygon
|
|
311
|
+
// "eip155:42161": ["https://arb1.arbitrum.io/rpc"], // Arbitrum
|
|
312
|
+
// "eip155:10": ["https://mainnet.optimism.io"], // Optimism
|
|
313
|
+
// "eip155:8453": ["https://mainnet.base.org"], // Base
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// App metadata - customize with your app's branding
|
|
319
|
+
const appMetadata: AppMetadata = {
|
|
320
|
+
// Your app's logo URL (can be a URL or base64 data URI)
|
|
321
|
+
logoUrl: "https://avatars.githubusercontent.com/u/64157541?v=4",
|
|
322
|
+
|
|
323
|
+
// Your app's display name
|
|
324
|
+
title: "${options.projectName}",
|
|
325
|
+
|
|
326
|
+
// Brief description of your app (shown in wallet connection prompts)
|
|
327
|
+
description:
|
|
328
|
+
"Push Chain is a shared state L1 blockchain that allows all chains to unify, enabling apps of any chain to be accessed by users of any chain.",
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
return (
|
|
332
|
+
<PushUniversalWalletProvider config={walletConfig} app={appMetadata}>
|
|
333
|
+
{children}
|
|
334
|
+
</PushUniversalWalletProvider>
|
|
335
|
+
);
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
export { PushChainProviders };`;
|
|
339
|
+
await fs.writeFile(path.join(providersDir, 'PushChainProviders.tsx'), pushchainProviders);
|
|
340
|
+
// Create .env.local file for Next.js with configuration notes
|
|
341
|
+
const envFile = `# Push Chain Configuration for Next.js
|
|
342
|
+
#
|
|
343
|
+
# This file contains environment variables for your Push Chain application.
|
|
344
|
+
# In Next.js, client-side variables must be prefixed with NEXT_PUBLIC_
|
|
345
|
+
#
|
|
346
|
+
# IMPORTANT: Never commit sensitive API keys to version control!
|
|
347
|
+
# This file (.env.local) is automatically ignored by Git.
|
|
348
|
+
|
|
349
|
+
# Push Chain Network Configuration
|
|
350
|
+
# Options: mainnet, testnet, dev
|
|
351
|
+
NEXT_PUBLIC_PUSHCHAIN_NETWORK=testnet
|
|
352
|
+
|
|
353
|
+
# Optional: Custom API endpoints (if you have specific requirements)
|
|
354
|
+
# NEXT_PUBLIC_PUSHCHAIN_API_ENDPOINT=https://your-custom-endpoint.com
|
|
355
|
+
|
|
356
|
+
# Optional: App-specific configuration
|
|
357
|
+
# NEXT_PUBLIC_APP_NAME=${options.projectName}
|
|
358
|
+
# NEXT_PUBLIC_APP_VERSION=1.0.0
|
|
359
|
+
|
|
360
|
+
# Server-side only variables (without NEXT_PUBLIC_ prefix)
|
|
361
|
+
# These are only available in API routes and server components
|
|
362
|
+
# PRIVATE_API_KEY=your_private_key_here`;
|
|
363
|
+
await fs.writeFile(path.join(options.targetDir, '.env.local'), envFile);
|
|
364
|
+
}
|
|
365
|
+
async function createESLintConfig(options) {
|
|
366
|
+
const eslintConfig = {
|
|
367
|
+
extends: [
|
|
368
|
+
"next/core-web-vitals",
|
|
369
|
+
"@typescript-eslint/recommended"
|
|
370
|
+
],
|
|
371
|
+
parser: "@typescript-eslint/parser",
|
|
372
|
+
plugins: ["@typescript-eslint"],
|
|
373
|
+
rules: {
|
|
374
|
+
"@typescript-eslint/no-unused-vars": "warn",
|
|
375
|
+
"@typescript-eslint/no-explicit-any": "warn"
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
await fs.writeJSON(path.join(options.targetDir, '.eslintrc.json'), eslintConfig, { spaces: 2 });
|
|
379
|
+
}
|
|
380
|
+
async function createTailwindConfig(options) {
|
|
381
|
+
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
382
|
+
module.exports = {
|
|
383
|
+
darkMode: ["class"],
|
|
384
|
+
content: [
|
|
385
|
+
'./pages/**/*.{ts,tsx}',
|
|
386
|
+
'./components/**/*.{ts,tsx}',
|
|
387
|
+
'./app/**/*.{ts,tsx}',
|
|
388
|
+
'./src/**/*.{ts,tsx}',
|
|
389
|
+
],
|
|
390
|
+
theme: {
|
|
391
|
+
extend: {},
|
|
392
|
+
},
|
|
393
|
+
plugins: [],
|
|
394
|
+
}`;
|
|
395
|
+
await fs.writeFile(path.join(options.targetDir, 'tailwind.config.js'), tailwindConfig);
|
|
396
|
+
// PostCSS config
|
|
397
|
+
const postcssConfig = `module.exports = {
|
|
398
|
+
plugins: {
|
|
399
|
+
tailwindcss: {},
|
|
400
|
+
autoprefixer: {},
|
|
401
|
+
},
|
|
402
|
+
}`;
|
|
403
|
+
await fs.writeFile(path.join(options.targetDir, 'postcss.config.js'), postcssConfig);
|
|
404
|
+
}
|
|
405
|
+
// Removed shadcn config and components for Tailwind-only setup
|
|
406
|
+
//# sourceMappingURL=nextjs.js.map
|