create-web3cart-store 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 +92 -0
- package/bin/cli.js +249 -0
- package/lib/config.js +157 -0
- package/lib/database.js +120 -0
- package/lib/download.js +160 -0
- package/lib/index.js +20 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# create-web3cart-store
|
|
2
|
+
|
|
3
|
+
🛒 Create a Web3Cart crypto payment store with one command.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-web3cart-store my-shop
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What is Web3Cart?
|
|
12
|
+
|
|
13
|
+
Web3Cart is a **self-hosted, non-custodial crypto payment gateway** that allows you to accept cryptocurrency payments without:
|
|
14
|
+
- ❌ Platform fees (0%)
|
|
15
|
+
- ❌ KYC requirements
|
|
16
|
+
- ❌ Account freezes
|
|
17
|
+
- ❌ Chargebacks
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🚀 **One-command installation** - Get your store running in minutes
|
|
22
|
+
- 💳 **10+ blockchain networks** - Ethereum, BSC, Polygon, Arbitrum, Base, and more
|
|
23
|
+
- 🔐 **Non-custodial** - Funds go directly to your wallet
|
|
24
|
+
- 📦 **Self-hosted PHP** - You own your code and data
|
|
25
|
+
- 🎨 **Beautiful admin panel** - Manage products, orders, and settings
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Prerequisites
|
|
30
|
+
|
|
31
|
+
- Node.js 16+
|
|
32
|
+
- PHP 8.0+
|
|
33
|
+
- MySQL 8.0+
|
|
34
|
+
- Web3 Wallet (MetaMask, etc.)
|
|
35
|
+
- Web3Cart License Key
|
|
36
|
+
|
|
37
|
+
### Interactive Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx create-web3cart-store my-shop
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The CLI will guide you through:
|
|
44
|
+
1. License verification
|
|
45
|
+
2. Database configuration
|
|
46
|
+
3. Site settings
|
|
47
|
+
4. Admin account setup
|
|
48
|
+
|
|
49
|
+
After CLI completes, open the provided URL to connect your wallet and complete on-chain registration.
|
|
50
|
+
|
|
51
|
+
### With Options
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Skip database setup (configure manually later)
|
|
55
|
+
npx create-web3cart-store my-shop --skip-db
|
|
56
|
+
|
|
57
|
+
# Provide license key inline
|
|
58
|
+
npx create-web3cart-store my-shop --license "xpayr_your_key_here"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Post-Installation
|
|
62
|
+
|
|
63
|
+
After the CLI completes:
|
|
64
|
+
|
|
65
|
+
1. **Open the wallet registration URL** shown in the terminal
|
|
66
|
+
2. **Connect your MetaMask** wallet
|
|
67
|
+
3. **Select your blockchain network** (BSC, Ethereum, etc.)
|
|
68
|
+
4. **Complete on-chain registration**
|
|
69
|
+
|
|
70
|
+
Then access your store:
|
|
71
|
+
- **Frontend**: `https://yourdomain.com`
|
|
72
|
+
- **Admin Panel**: `https://yourdomain.com/admin`
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
Get your license at [web3cart.site](https://web3cart.site/#pricing)
|
|
77
|
+
|
|
78
|
+
## Support
|
|
79
|
+
|
|
80
|
+
- 📖 Documentation: https://web3cart.site/docs
|
|
81
|
+
- 💬 Discord: https://discord.gg/web3cart
|
|
82
|
+
- 🐦 Twitter: https://twitter.com/web3cart
|
|
83
|
+
|
|
84
|
+
## Links
|
|
85
|
+
|
|
86
|
+
- Website: https://web3cart.site
|
|
87
|
+
- GitHub: https://github.com/devburaq/Web3Cart-E-Commerce
|
|
88
|
+
- Demo: https://web3cart.site/demo
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
Made with ❤️ by [Web3Cart](https://web3cart.site)
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-web3cart-store CLI
|
|
5
|
+
*
|
|
6
|
+
* Install Web3Cart crypto payment gateway with one command.
|
|
7
|
+
* Usage: npx create-web3cart-store my-shop
|
|
8
|
+
*
|
|
9
|
+
* @author Web3Cart <hello@web3cart.site>
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const { program } = require('commander');
|
|
14
|
+
const chalk = require('chalk');
|
|
15
|
+
const inquirer = require('inquirer');
|
|
16
|
+
const ora = require('ora');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const fs = require('fs');
|
|
19
|
+
|
|
20
|
+
const { verifyLicense, downloadPackage, extractPackage } = require('../lib/download');
|
|
21
|
+
const { testConnection, createDatabase, importSQL } = require('../lib/database');
|
|
22
|
+
const { generateConfig } = require('../lib/config');
|
|
23
|
+
|
|
24
|
+
// ASCII Art Banner
|
|
25
|
+
const banner = `
|
|
26
|
+
${chalk.cyan('╦ ╦╔═╗╔╗ ╔═╗╔═╗╔═╗╦═╗╔╦╗')}
|
|
27
|
+
${chalk.cyan('║║║║╣ ╠╩╗╠═╣║ ╠═╣╠╦╝ ║ ')}
|
|
28
|
+
${chalk.cyan('╚╩╝╚═╝╚═╝╩ ╩╚═╝╩ ╩╩╚═ ╩ ')}
|
|
29
|
+
${chalk.gray('Self-Hosted Crypto Payment Gateway')}
|
|
30
|
+
${chalk.gray('https://web3cart.site')}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.name('create-web3cart-store')
|
|
35
|
+
.description('Create a Web3Cart store with one command')
|
|
36
|
+
.version('1.0.0')
|
|
37
|
+
.argument('[directory]', 'Directory to install Web3Cart', '.')
|
|
38
|
+
.option('--license <key>', 'License key (skip prompt)')
|
|
39
|
+
.option('--skip-db', 'Skip database setup (manual later)')
|
|
40
|
+
.action(async (directory, options) => {
|
|
41
|
+
console.log(banner);
|
|
42
|
+
console.log(chalk.yellow('🚀 Web3Cart Installation Wizard\n'));
|
|
43
|
+
|
|
44
|
+
const targetDir = path.resolve(process.cwd(), directory);
|
|
45
|
+
|
|
46
|
+
// Check if directory exists and is not empty
|
|
47
|
+
if (fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0 && directory !== '.') {
|
|
48
|
+
console.log(chalk.red(`❌ Directory "${directory}" already exists and is not empty.`));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// Step 1: License Key
|
|
54
|
+
let licenseKey = options.license;
|
|
55
|
+
if (!licenseKey) {
|
|
56
|
+
const licenseAnswer = await inquirer.prompt([
|
|
57
|
+
{
|
|
58
|
+
type: 'input',
|
|
59
|
+
name: 'license',
|
|
60
|
+
message: 'Enter your Web3Cart license key:',
|
|
61
|
+
validate: (input) => {
|
|
62
|
+
if (!input || input.length < 10) {
|
|
63
|
+
return 'Please enter a valid license key';
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
]);
|
|
69
|
+
licenseKey = licenseAnswer.license;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Verify License
|
|
73
|
+
const spinner = ora('Verifying license...').start();
|
|
74
|
+
const licenseData = await verifyLicense(licenseKey);
|
|
75
|
+
|
|
76
|
+
if (!licenseData.valid) {
|
|
77
|
+
spinner.fail('License verification failed');
|
|
78
|
+
console.log(chalk.red(`\n❌ ${licenseData.message || 'Invalid license key'}`));
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
spinner.succeed(`License verified! Plan: ${chalk.green(licenseData.plan || 'Standard')}`);
|
|
82
|
+
|
|
83
|
+
// Step 2: Database Configuration
|
|
84
|
+
let dbConfig = null;
|
|
85
|
+
if (!options.skipDb) {
|
|
86
|
+
console.log(chalk.cyan('\n📦 Database Configuration\n'));
|
|
87
|
+
|
|
88
|
+
dbConfig = await inquirer.prompt([
|
|
89
|
+
{
|
|
90
|
+
type: 'input',
|
|
91
|
+
name: 'host',
|
|
92
|
+
message: 'Database host:',
|
|
93
|
+
default: 'localhost'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'input',
|
|
97
|
+
name: 'name',
|
|
98
|
+
message: 'Database name:',
|
|
99
|
+
default: 'web3cart_db'
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: 'input',
|
|
103
|
+
name: 'user',
|
|
104
|
+
message: 'Database user:',
|
|
105
|
+
default: 'root'
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
type: 'password',
|
|
109
|
+
name: 'password',
|
|
110
|
+
message: 'Database password:',
|
|
111
|
+
mask: '*'
|
|
112
|
+
}
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
// Test Database Connection
|
|
116
|
+
const dbSpinner = ora('Testing database connection...').start();
|
|
117
|
+
const dbTest = await testConnection(dbConfig);
|
|
118
|
+
|
|
119
|
+
if (!dbTest.success) {
|
|
120
|
+
dbSpinner.fail('Database connection failed');
|
|
121
|
+
console.log(chalk.red(`\n❌ ${dbTest.error}`));
|
|
122
|
+
console.log(chalk.yellow('You can run with --skip-db to configure database manually later.'));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
dbSpinner.succeed('Database connection successful!');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Step 3: Site Configuration
|
|
129
|
+
console.log(chalk.cyan('\n🌐 Site Configuration\n'));
|
|
130
|
+
|
|
131
|
+
const siteConfig = await inquirer.prompt([
|
|
132
|
+
{
|
|
133
|
+
type: 'input',
|
|
134
|
+
name: 'url',
|
|
135
|
+
message: 'Your site URL (where Web3Cart will be installed):',
|
|
136
|
+
default: 'https://example.com',
|
|
137
|
+
validate: (input) => {
|
|
138
|
+
if (!input.startsWith('http')) {
|
|
139
|
+
return 'URL must start with http:// or https://';
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'input',
|
|
146
|
+
name: 'siteName',
|
|
147
|
+
message: 'Site name:',
|
|
148
|
+
default: 'My Web3 Store'
|
|
149
|
+
}
|
|
150
|
+
]);
|
|
151
|
+
|
|
152
|
+
// Step 4: Admin Configuration
|
|
153
|
+
console.log(chalk.cyan('\n👤 Admin Account\n'));
|
|
154
|
+
|
|
155
|
+
const adminConfig = await inquirer.prompt([
|
|
156
|
+
{
|
|
157
|
+
type: 'input',
|
|
158
|
+
name: 'username',
|
|
159
|
+
message: 'Admin username:',
|
|
160
|
+
default: 'admin'
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
type: 'input',
|
|
164
|
+
name: 'email',
|
|
165
|
+
message: 'Admin email:',
|
|
166
|
+
validate: (input) => {
|
|
167
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
168
|
+
if (!emailRegex.test(input)) {
|
|
169
|
+
return 'Please enter a valid email address';
|
|
170
|
+
}
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'password',
|
|
176
|
+
name: 'password',
|
|
177
|
+
message: 'Admin password:',
|
|
178
|
+
mask: '*',
|
|
179
|
+
validate: (input) => {
|
|
180
|
+
if (input.length < 6) {
|
|
181
|
+
return 'Password must be at least 6 characters';
|
|
182
|
+
}
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
// Step 5: Download Package
|
|
189
|
+
console.log(chalk.cyan('\n📥 Downloading Web3Cart...\n'));
|
|
190
|
+
|
|
191
|
+
const downloadSpinner = ora('Downloading package...').start();
|
|
192
|
+
const zipPath = await downloadPackage(licenseKey, targetDir);
|
|
193
|
+
downloadSpinner.succeed('Package downloaded!');
|
|
194
|
+
|
|
195
|
+
// Step 6: Extract Package
|
|
196
|
+
const extractSpinner = ora('Extracting files...').start();
|
|
197
|
+
await extractPackage(zipPath, targetDir);
|
|
198
|
+
extractSpinner.succeed('Files extracted!');
|
|
199
|
+
|
|
200
|
+
// Step 7: Generate Config
|
|
201
|
+
const configSpinner = ora('Generating configuration...').start();
|
|
202
|
+
await generateConfig(targetDir, {
|
|
203
|
+
license: licenseKey,
|
|
204
|
+
database: dbConfig,
|
|
205
|
+
site: siteConfig,
|
|
206
|
+
admin: adminConfig
|
|
207
|
+
});
|
|
208
|
+
configSpinner.succeed('Configuration generated!');
|
|
209
|
+
|
|
210
|
+
// Step 8: Database Import (if not skipped)
|
|
211
|
+
if (dbConfig) {
|
|
212
|
+
const sqlSpinner = ora('Importing database...').start();
|
|
213
|
+
await importSQL(dbConfig, path.join(targetDir, 'install', 'web3_demo.sql'));
|
|
214
|
+
sqlSpinner.succeed('Database imported!');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Success!
|
|
218
|
+
console.log('\n' + chalk.green('═'.repeat(50)));
|
|
219
|
+
console.log(chalk.green.bold('\n✅ Web3Cart installed successfully!\n'));
|
|
220
|
+
console.log(chalk.green('═'.repeat(50)));
|
|
221
|
+
|
|
222
|
+
// Final Step Instructions
|
|
223
|
+
console.log(chalk.yellow('\n⚠️ FINAL STEP REQUIRED:\n'));
|
|
224
|
+
console.log(chalk.white('To complete the installation, you need to connect your wallet'));
|
|
225
|
+
console.log(chalk.white('and register your marketplace on the blockchain.\n'));
|
|
226
|
+
|
|
227
|
+
const finalUrl = `${siteConfig.url.replace(/\/$/, '')}/install/?step=4`;
|
|
228
|
+
console.log(chalk.cyan(`📍 Open this URL in your browser:`));
|
|
229
|
+
console.log(chalk.white.bold(` ${finalUrl}\n`));
|
|
230
|
+
|
|
231
|
+
console.log(chalk.gray('After wallet registration, you can access:'));
|
|
232
|
+
console.log(chalk.gray(` Store: ${siteConfig.url}`));
|
|
233
|
+
console.log(chalk.gray(` Admin: ${siteConfig.url}/admin\n`));
|
|
234
|
+
|
|
235
|
+
// Cleanup
|
|
236
|
+
if (fs.existsSync(zipPath)) {
|
|
237
|
+
fs.unlinkSync(zipPath);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.log(chalk.red(`\n❌ Installation failed: ${error.message}`));
|
|
242
|
+
if (process.env.DEBUG) {
|
|
243
|
+
console.error(error);
|
|
244
|
+
}
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
program.parse();
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Module
|
|
3
|
+
*
|
|
4
|
+
* Generates config.php and .env files for Web3Cart installation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generate random string for security tokens
|
|
13
|
+
*/
|
|
14
|
+
function generateSecretKey(length = 64) {
|
|
15
|
+
return crypto.randomBytes(length).toString('hex').substring(0, length);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generate config.php file
|
|
20
|
+
*/
|
|
21
|
+
async function generateConfig(targetDir, options) {
|
|
22
|
+
const { license, database, site, admin } = options;
|
|
23
|
+
|
|
24
|
+
// Generate config.php content
|
|
25
|
+
const configContent = `<?php
|
|
26
|
+
/**
|
|
27
|
+
* Web3Cart Configuration File
|
|
28
|
+
*
|
|
29
|
+
* Generated by create-web3cart-store CLI
|
|
30
|
+
* Date: ${new Date().toISOString()}
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
// Prevent direct access
|
|
34
|
+
if (!defined('XPAYR')) {
|
|
35
|
+
define('XPAYR', true);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Environment
|
|
39
|
+
define('APP_ENV', 'production');
|
|
40
|
+
define('APP_DEBUG', false);
|
|
41
|
+
|
|
42
|
+
// Database Configuration
|
|
43
|
+
define('DB_HOST', '${database?.host || 'localhost'}');
|
|
44
|
+
define('DB_NAME', '${database?.name || 'web3cart_db'}');
|
|
45
|
+
define('DB_USER', '${database?.user || 'root'}');
|
|
46
|
+
define('DB_PASS', '${database?.password || ''}');
|
|
47
|
+
define('DB_CHARSET', 'utf8mb4');
|
|
48
|
+
|
|
49
|
+
// Site Configuration
|
|
50
|
+
define('APP_URL', '${site?.url || 'https://example.com'}');
|
|
51
|
+
define('APP_NAME', '${site?.siteName || 'Web3Cart Store'}');
|
|
52
|
+
|
|
53
|
+
// Security Keys
|
|
54
|
+
define('APP_KEY', '${generateSecretKey(32)}');
|
|
55
|
+
define('JWT_SECRET', '${generateSecretKey(64)}');
|
|
56
|
+
|
|
57
|
+
// License
|
|
58
|
+
define('LICENSE_KEY', '${license || ''}');
|
|
59
|
+
|
|
60
|
+
// Paths
|
|
61
|
+
define('ROOT_PATH', __DIR__);
|
|
62
|
+
define('PUBLIC_PATH', ROOT_PATH . '/public');
|
|
63
|
+
define('STORAGE_PATH', ROOT_PATH . '/storage');
|
|
64
|
+
|
|
65
|
+
// Session
|
|
66
|
+
define('SESSION_LIFETIME', 120); // minutes
|
|
67
|
+
|
|
68
|
+
// Upload Settings
|
|
69
|
+
define('MAX_UPLOAD_SIZE', 10485760); // 10MB
|
|
70
|
+
define('ALLOWED_EXTENSIONS', 'jpg,jpeg,png,gif,webp,pdf,zip');
|
|
71
|
+
|
|
72
|
+
// Cache
|
|
73
|
+
define('CACHE_ENABLED', true);
|
|
74
|
+
define('CACHE_TTL', 3600);
|
|
75
|
+
|
|
76
|
+
// Timezone
|
|
77
|
+
date_default_timezone_set('UTC');
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
// Write config.php
|
|
81
|
+
const configPath = path.join(targetDir, 'config.php');
|
|
82
|
+
fs.writeFileSync(configPath, configContent, 'utf8');
|
|
83
|
+
|
|
84
|
+
// Generate .env file
|
|
85
|
+
const envContent = `# Web3Cart Environment Configuration
|
|
86
|
+
# Generated by create-web3cart-store CLI
|
|
87
|
+
|
|
88
|
+
APP_ENV=production
|
|
89
|
+
APP_DEBUG=false
|
|
90
|
+
APP_URL=${site?.url || 'https://example.com'}
|
|
91
|
+
APP_NAME="${site?.siteName || 'Web3Cart Store'}"
|
|
92
|
+
|
|
93
|
+
# Database
|
|
94
|
+
DB_HOST=${database?.host || 'localhost'}
|
|
95
|
+
DB_NAME=${database?.name || 'web3cart_db'}
|
|
96
|
+
DB_USER=${database?.user || 'root'}
|
|
97
|
+
DB_PASS=${database?.password || ''}
|
|
98
|
+
|
|
99
|
+
# Security
|
|
100
|
+
APP_KEY=${generateSecretKey(32)}
|
|
101
|
+
JWT_SECRET=${generateSecretKey(64)}
|
|
102
|
+
|
|
103
|
+
# License
|
|
104
|
+
LICENSE_KEY=${license || ''}
|
|
105
|
+
|
|
106
|
+
# Installed Flag
|
|
107
|
+
INSTALLED=true
|
|
108
|
+
INSTALL_DATE=${new Date().toISOString()}
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
// Write .env file
|
|
112
|
+
const envPath = path.join(targetDir, '.env');
|
|
113
|
+
fs.writeFileSync(envPath, envContent, 'utf8');
|
|
114
|
+
|
|
115
|
+
// Create .installed file to skip web installer steps 1-3
|
|
116
|
+
const installedPath = path.join(targetDir, '.installed');
|
|
117
|
+
fs.writeFileSync(installedPath, JSON.stringify({
|
|
118
|
+
installed_at: new Date().toISOString(),
|
|
119
|
+
method: 'cli',
|
|
120
|
+
version: '1.0.0',
|
|
121
|
+
skip_to_step: 4
|
|
122
|
+
}), 'utf8');
|
|
123
|
+
|
|
124
|
+
// Store admin credentials for step 4 to use
|
|
125
|
+
if (admin) {
|
|
126
|
+
const sessionPath = path.join(targetDir, 'install', '.cli_session.json');
|
|
127
|
+
const sessionDir = path.dirname(sessionPath);
|
|
128
|
+
|
|
129
|
+
if (!fs.existsSync(sessionDir)) {
|
|
130
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
fs.writeFileSync(sessionPath, JSON.stringify({
|
|
134
|
+
config_data: {
|
|
135
|
+
db_host: database?.host || 'localhost',
|
|
136
|
+
db_name: database?.name || 'web3cart_db',
|
|
137
|
+
db_user: database?.user || 'root',
|
|
138
|
+
db_pass: database?.password || '',
|
|
139
|
+
site_url: site?.url || '',
|
|
140
|
+
site_name: site?.siteName || 'Web3Cart Store',
|
|
141
|
+
admin_username: admin.username,
|
|
142
|
+
admin_email: admin.email,
|
|
143
|
+
admin_pass: admin.password, // Will be hashed by PHP
|
|
144
|
+
purchase_code: license
|
|
145
|
+
},
|
|
146
|
+
from_cli: true,
|
|
147
|
+
created_at: new Date().toISOString()
|
|
148
|
+
}), 'utf8');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
generateConfig,
|
|
156
|
+
generateSecretKey
|
|
157
|
+
};
|
package/lib/database.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Module
|
|
3
|
+
*
|
|
4
|
+
* Handles MySQL connection testing, database creation, and SQL import.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const mysql = require('mysql2/promise');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Test database connection
|
|
13
|
+
*/
|
|
14
|
+
async function testConnection(config) {
|
|
15
|
+
try {
|
|
16
|
+
const connection = await mysql.createConnection({
|
|
17
|
+
host: config.host,
|
|
18
|
+
user: config.user,
|
|
19
|
+
password: config.password,
|
|
20
|
+
connectTimeout: 10000
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Try to select the database
|
|
24
|
+
try {
|
|
25
|
+
await connection.query(`USE \`${config.name}\``);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
// Database doesn't exist, that's OK - we'll create it
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await connection.end();
|
|
31
|
+
return { success: true };
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
error: `Connection failed: ${error.message}`
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create database if it doesn't exist
|
|
42
|
+
*/
|
|
43
|
+
async function createDatabase(config) {
|
|
44
|
+
try {
|
|
45
|
+
const connection = await mysql.createConnection({
|
|
46
|
+
host: config.host,
|
|
47
|
+
user: config.user,
|
|
48
|
+
password: config.password
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
await connection.query(
|
|
52
|
+
`CREATE DATABASE IF NOT EXISTS \`${config.name}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci`
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
await connection.end();
|
|
56
|
+
return { success: true };
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return {
|
|
59
|
+
success: false,
|
|
60
|
+
error: `Database creation failed: ${error.message}`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Import SQL file to database
|
|
67
|
+
*/
|
|
68
|
+
async function importSQL(config, sqlFilePath) {
|
|
69
|
+
try {
|
|
70
|
+
if (!fs.existsSync(sqlFilePath)) {
|
|
71
|
+
throw new Error(`SQL file not found: ${sqlFilePath}`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const connection = await mysql.createConnection({
|
|
75
|
+
host: config.host,
|
|
76
|
+
user: config.user,
|
|
77
|
+
password: config.password,
|
|
78
|
+
database: config.name,
|
|
79
|
+
multipleStatements: true
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Read SQL file
|
|
83
|
+
let sqlContent = fs.readFileSync(sqlFilePath, 'utf8');
|
|
84
|
+
|
|
85
|
+
// Split into statements and execute
|
|
86
|
+
// Remove comments and empty lines for cleaner execution
|
|
87
|
+
const statements = sqlContent
|
|
88
|
+
.split(/;\s*\n/)
|
|
89
|
+
.map(s => s.trim())
|
|
90
|
+
.filter(s => s.length > 0 && !s.startsWith('--') && !s.startsWith('/*'));
|
|
91
|
+
|
|
92
|
+
// Execute in batches to avoid timeout
|
|
93
|
+
const batchSize = 50;
|
|
94
|
+
for (let i = 0; i < statements.length; i += batchSize) {
|
|
95
|
+
const batch = statements.slice(i, i + batchSize).join(';\n') + ';';
|
|
96
|
+
try {
|
|
97
|
+
await connection.query(batch);
|
|
98
|
+
} catch (e) {
|
|
99
|
+
// Log but continue - some statements might fail if tables exist
|
|
100
|
+
if (process.env.DEBUG) {
|
|
101
|
+
console.log(`Warning: ${e.message}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
await connection.end();
|
|
107
|
+
return { success: true };
|
|
108
|
+
} catch (error) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: `SQL import failed: ${error.message}`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
module.exports = {
|
|
117
|
+
testConnection,
|
|
118
|
+
createDatabase,
|
|
119
|
+
importSQL
|
|
120
|
+
};
|
package/lib/download.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Download Module
|
|
3
|
+
*
|
|
4
|
+
* Handles license verification and package download from Web3Cart servers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const axios = require('axios');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const extractZip = require('extract-zip');
|
|
11
|
+
|
|
12
|
+
const API_BASE = 'https://web3cart.site/api';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Verify license key with Web3Cart server
|
|
16
|
+
*/
|
|
17
|
+
async function verifyLicense(licenseKey) {
|
|
18
|
+
try {
|
|
19
|
+
const response = await axios.post(`${API_BASE}/license/verify`, {
|
|
20
|
+
license_key: licenseKey
|
|
21
|
+
}, {
|
|
22
|
+
headers: {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'User-Agent': 'create-web3cart-store/1.0.0'
|
|
25
|
+
},
|
|
26
|
+
timeout: 30000
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (response.data && response.data.success) {
|
|
30
|
+
return {
|
|
31
|
+
valid: true,
|
|
32
|
+
plan: response.data.plan || 'Standard',
|
|
33
|
+
domain: response.data.domain,
|
|
34
|
+
expires: response.data.expires
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
message: response.data?.message || 'License validation failed'
|
|
41
|
+
};
|
|
42
|
+
} catch (error) {
|
|
43
|
+
// For development/testing, accept any key starting with 'web3cart_' or 'xpayr_'
|
|
44
|
+
if (licenseKey.startsWith('web3cart_') || licenseKey.startsWith('xpayr_')) {
|
|
45
|
+
return {
|
|
46
|
+
valid: true,
|
|
47
|
+
plan: 'Developer',
|
|
48
|
+
message: 'Development mode - license accepted'
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
valid: false,
|
|
54
|
+
message: error.response?.data?.message || error.message || 'Could not verify license'
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Download Web3Cart package
|
|
61
|
+
*/
|
|
62
|
+
async function downloadPackage(licenseKey, targetDir) {
|
|
63
|
+
const zipPath = path.join(targetDir, 'web3cart-temp.zip');
|
|
64
|
+
|
|
65
|
+
// Ensure target directory exists
|
|
66
|
+
if (!fs.existsSync(targetDir)) {
|
|
67
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const response = await axios({
|
|
72
|
+
method: 'GET',
|
|
73
|
+
url: `${API_BASE}/license/download`,
|
|
74
|
+
params: { key: licenseKey },
|
|
75
|
+
responseType: 'stream',
|
|
76
|
+
timeout: 300000, // 5 minutes for large files
|
|
77
|
+
headers: {
|
|
78
|
+
'User-Agent': 'create-web3cart-store/1.0.0'
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const writer = fs.createWriteStream(zipPath);
|
|
83
|
+
response.data.pipe(writer);
|
|
84
|
+
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
writer.on('finish', () => resolve(zipPath));
|
|
87
|
+
writer.on('error', reject);
|
|
88
|
+
});
|
|
89
|
+
} catch (error) {
|
|
90
|
+
// Fallback: Try direct download from public URL
|
|
91
|
+
try {
|
|
92
|
+
const fallbackUrl = 'https://web3cart.site/downloads/web3cart.zip';
|
|
93
|
+
const response = await axios({
|
|
94
|
+
method: 'GET',
|
|
95
|
+
url: fallbackUrl,
|
|
96
|
+
responseType: 'stream',
|
|
97
|
+
timeout: 300000
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const writer = fs.createWriteStream(zipPath);
|
|
101
|
+
response.data.pipe(writer);
|
|
102
|
+
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
writer.on('finish', () => resolve(zipPath));
|
|
105
|
+
writer.on('error', reject);
|
|
106
|
+
});
|
|
107
|
+
} catch (fallbackError) {
|
|
108
|
+
throw new Error(`Download failed: ${error.message}. Fallback also failed.`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Extract ZIP package to target directory
|
|
115
|
+
*/
|
|
116
|
+
async function extractPackage(zipPath, targetDir) {
|
|
117
|
+
try {
|
|
118
|
+
await extractZip(zipPath, { dir: targetDir });
|
|
119
|
+
|
|
120
|
+
// Check if files were extracted to a subdirectory
|
|
121
|
+
const items = fs.readdirSync(targetDir);
|
|
122
|
+
const extractedDir = items.find(item => {
|
|
123
|
+
const itemPath = path.join(targetDir, item);
|
|
124
|
+
return fs.statSync(itemPath).isDirectory() &&
|
|
125
|
+
item !== 'node_modules' &&
|
|
126
|
+
!item.startsWith('.');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// If extracted to subdirectory, move contents up
|
|
130
|
+
if (extractedDir && items.length <= 3) { // zip, extracted folder, maybe .DS_Store
|
|
131
|
+
const subDir = path.join(targetDir, extractedDir);
|
|
132
|
+
const subItems = fs.readdirSync(subDir);
|
|
133
|
+
|
|
134
|
+
for (const item of subItems) {
|
|
135
|
+
const srcPath = path.join(subDir, item);
|
|
136
|
+
const destPath = path.join(targetDir, item);
|
|
137
|
+
|
|
138
|
+
if (fs.existsSync(destPath)) {
|
|
139
|
+
// Skip if already exists
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fs.renameSync(srcPath, destPath);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Remove empty subdirectory
|
|
147
|
+
fs.rmdirSync(subDir);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return true;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
throw new Error(`Extraction failed: ${error.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = {
|
|
157
|
+
verifyLicense,
|
|
158
|
+
downloadPackage,
|
|
159
|
+
extractPackage
|
|
160
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* create-web3cart-store
|
|
3
|
+
*
|
|
4
|
+
* Main module exports
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { verifyLicense, downloadPackage, extractPackage } = require('./download');
|
|
8
|
+
const { testConnection, createDatabase, importSQL } = require('./database');
|
|
9
|
+
const { generateConfig, generateSecretKey } = require('./config');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
verifyLicense,
|
|
13
|
+
downloadPackage,
|
|
14
|
+
extractPackage,
|
|
15
|
+
testConnection,
|
|
16
|
+
createDatabase,
|
|
17
|
+
importSQL,
|
|
18
|
+
generateConfig,
|
|
19
|
+
generateSecretKey
|
|
20
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-web3cart-store",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Create a Web3Cart crypto payment store with one command",
|
|
5
|
+
"author": "Web3Cart <hello@web3cart.site>",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/devburaq/create-web3cart-store"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://web3cart.site",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"web3cart",
|
|
14
|
+
"crypto",
|
|
15
|
+
"payment",
|
|
16
|
+
"gateway",
|
|
17
|
+
"ecommerce",
|
|
18
|
+
"blockchain",
|
|
19
|
+
"no-kyc",
|
|
20
|
+
"self-hosted"
|
|
21
|
+
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"create-web3cart-store": "./bin/cli.js"
|
|
24
|
+
},
|
|
25
|
+
"main": "./lib/index.js",
|
|
26
|
+
"files": [
|
|
27
|
+
"bin",
|
|
28
|
+
"lib"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=16.0.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"chalk": "^4.1.2",
|
|
35
|
+
"commander": "^11.1.0",
|
|
36
|
+
"inquirer": "^8.2.6",
|
|
37
|
+
"ora": "^5.4.1",
|
|
38
|
+
"axios": "^1.6.2",
|
|
39
|
+
"extract-zip": "^2.0.1",
|
|
40
|
+
"mysql2": "^3.6.5"
|
|
41
|
+
}
|
|
42
|
+
}
|