vako 1.3.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/CHANGELOG.md +63 -0
- package/README.md +1944 -0
- package/bin/commands/quick-setup.js +111 -0
- package/bin/commands/setup-executor.js +203 -0
- package/bin/commands/setup.js +737 -0
- package/bin/create-veko-app.js +75 -0
- package/bin/veko-update.js +205 -0
- package/bin/veko.js +188 -0
- package/error/error.ejs +382 -0
- package/index.js +36 -0
- package/lib/adapters/nextjs-adapter.js +241 -0
- package/lib/app.js +749 -0
- package/lib/core/auth-manager.js +1353 -0
- package/lib/core/auto-updater.js +1118 -0
- package/lib/core/logger.js +97 -0
- package/lib/core/module-installer.js +86 -0
- package/lib/dev/dev-server.js +292 -0
- package/lib/layout/layout-manager.js +834 -0
- package/lib/plugin-manager.js +1795 -0
- package/lib/routing/route-manager.js +1000 -0
- package/package.json +231 -0
- package/templates/public/css/style.css +2 -0
- package/templates/public/js/main.js +1 -0
- package/tsconfig.json +50 -0
- package/types/index.d.ts +238 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const { createSpinner } = require('nanospinner');
|
|
4
|
+
|
|
5
|
+
class QuickSetup {
|
|
6
|
+
constructor(projectName, options = {}) {
|
|
7
|
+
this.projectName = projectName;
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.config = {
|
|
10
|
+
projectName,
|
|
11
|
+
template: options.template || 'default',
|
|
12
|
+
features: ['hotreload', 'layouts'],
|
|
13
|
+
database: 'sqlite',
|
|
14
|
+
auth: { enabled: false },
|
|
15
|
+
plugins: ['logger', 'security'],
|
|
16
|
+
styling: 'bootstrap',
|
|
17
|
+
git: true,
|
|
18
|
+
install: true
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async start() {
|
|
23
|
+
console.log(chalk.blue.bold(`\nš Quick Setup for "${this.projectName}"\n`));
|
|
24
|
+
|
|
25
|
+
if (!this.options.template) {
|
|
26
|
+
await this.selectTemplate();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
await this.askEssentialQuestions();
|
|
30
|
+
await this.execute();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async selectTemplate() {
|
|
34
|
+
const { template } = await inquirer.prompt([{
|
|
35
|
+
type: 'list',
|
|
36
|
+
name: 'template',
|
|
37
|
+
message: 'šÆ Choose a template:',
|
|
38
|
+
choices: [
|
|
39
|
+
{ name: 'š Default - Full web app', value: 'default' },
|
|
40
|
+
{ name: 'š API - REST API only', value: 'api' },
|
|
41
|
+
{ name: 'š Blog - Content management', value: 'blog' },
|
|
42
|
+
{ name: 'š Admin - Dashboard', value: 'admin' },
|
|
43
|
+
{ name: 'š Portfolio - Showcase', value: 'portfolio' }
|
|
44
|
+
]
|
|
45
|
+
}]);
|
|
46
|
+
|
|
47
|
+
this.config.template = template;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async askEssentialQuestions() {
|
|
51
|
+
const questions = [
|
|
52
|
+
{
|
|
53
|
+
type: 'confirm',
|
|
54
|
+
name: 'auth',
|
|
55
|
+
message: 'š Include authentication?',
|
|
56
|
+
default: ['admin', 'blog'].includes(this.config.template),
|
|
57
|
+
when: () => this.config.template !== 'api'
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: 'list',
|
|
61
|
+
name: 'database',
|
|
62
|
+
message: 'šļø Database type:',
|
|
63
|
+
choices: [
|
|
64
|
+
{ name: 'š SQLite (easy)', value: 'sqlite' },
|
|
65
|
+
{ name: 'š PostgreSQL', value: 'postgresql' },
|
|
66
|
+
{ name: 'š MongoDB', value: 'mongodb' },
|
|
67
|
+
{ name: 'š« None', value: 'none' }
|
|
68
|
+
],
|
|
69
|
+
when: () => ['api', 'blog', 'admin'].includes(this.config.template)
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: 'list',
|
|
73
|
+
name: 'styling',
|
|
74
|
+
message: 'šØ CSS framework:',
|
|
75
|
+
choices: [
|
|
76
|
+
{ name: 'š
±ļø Bootstrap', value: 'bootstrap' },
|
|
77
|
+
{ name: 'šÆ Tailwind', value: 'tailwind' },
|
|
78
|
+
{ name: 'š Custom', value: 'custom' }
|
|
79
|
+
],
|
|
80
|
+
when: () => this.config.template !== 'api'
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
const answers = await inquirer.prompt(questions);
|
|
85
|
+
|
|
86
|
+
if (answers.auth) {
|
|
87
|
+
this.config.auth.enabled = true;
|
|
88
|
+
}
|
|
89
|
+
if (answers.database) {
|
|
90
|
+
this.config.database = answers.database;
|
|
91
|
+
}
|
|
92
|
+
if (answers.styling) {
|
|
93
|
+
this.config.styling = answers.styling;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async execute() {
|
|
98
|
+
const SetupExecutor = require('./setup-executor');
|
|
99
|
+
const executor = new SetupExecutor(this.config);
|
|
100
|
+
|
|
101
|
+
console.log(chalk.green('\nšÆ Creating your project...\n'));
|
|
102
|
+
await executor.execute();
|
|
103
|
+
|
|
104
|
+
console.log(chalk.green.bold('\n⨠Quick setup complete!\n'));
|
|
105
|
+
console.log(chalk.cyan('Next steps:'));
|
|
106
|
+
console.log(chalk.white(` cd ${this.projectName}`));
|
|
107
|
+
console.log(chalk.white(' npm run dev'));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = QuickSetup;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const { createSpinner } = require('nanospinner');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
class SetupExecutor {
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.projectPath = path.resolve(process.cwd(), config.projectName);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async execute() {
|
|
14
|
+
const totalSteps = 8;
|
|
15
|
+
let currentStep = 0;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
// Step 1: Create directory
|
|
19
|
+
currentStep++;
|
|
20
|
+
const spinner1 = createSpinner(`[${currentStep}/${totalSteps}] š Creating project directory...`).start();
|
|
21
|
+
await this.sleep(800);
|
|
22
|
+
await this.createDirectory();
|
|
23
|
+
spinner1.success({ text: `š Project directory created` });
|
|
24
|
+
|
|
25
|
+
// Step 2: Generate project structure
|
|
26
|
+
currentStep++;
|
|
27
|
+
const spinner2 = createSpinner(`[${currentStep}/${totalSteps}] šļø Generating project structure...`).start();
|
|
28
|
+
await this.sleep(1200);
|
|
29
|
+
await this.createProjectStructure();
|
|
30
|
+
spinner2.success({ text: `šļø Project structure created` });
|
|
31
|
+
|
|
32
|
+
// Step 3: Generate templates and files
|
|
33
|
+
currentStep++;
|
|
34
|
+
const spinner3 = createSpinner(`[${currentStep}/${totalSteps}] š Generating template files...`).start();
|
|
35
|
+
await this.sleep(1500);
|
|
36
|
+
await this.generateTemplateFiles();
|
|
37
|
+
spinner3.success({ text: `š Template files generated` });
|
|
38
|
+
|
|
39
|
+
// Step 4: Configure features and plugins
|
|
40
|
+
currentStep++;
|
|
41
|
+
const spinner4 = createSpinner(`[${currentStep}/${totalSteps}] ā” Configuring features and plugins...`).start();
|
|
42
|
+
await this.sleep(1000);
|
|
43
|
+
await this.configureFeatures();
|
|
44
|
+
spinner4.success({ text: `ā” Features and plugins configured` });
|
|
45
|
+
|
|
46
|
+
// Step 5: Setup authentication
|
|
47
|
+
if (this.config.auth.enabled) {
|
|
48
|
+
currentStep++;
|
|
49
|
+
const spinner5 = createSpinner(`[${currentStep}/${totalSteps}] š Setting up authentication...`).start();
|
|
50
|
+
await this.sleep(1300);
|
|
51
|
+
await this.setupAuthentication();
|
|
52
|
+
spinner5.success({ text: `š Authentication system configured` });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Step 6: Setup database
|
|
56
|
+
if (this.config.database !== 'none') {
|
|
57
|
+
currentStep++;
|
|
58
|
+
const spinner6 = createSpinner(`[${currentStep}/${totalSteps}] šļø Configuring database...`).start();
|
|
59
|
+
await this.sleep(900);
|
|
60
|
+
await this.setupDatabase();
|
|
61
|
+
spinner6.success({ text: `šļø Database configured` });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Step 7: Initialize Git
|
|
65
|
+
if (this.config.git) {
|
|
66
|
+
currentStep++;
|
|
67
|
+
const spinner7 = createSpinner(`[${currentStep}/${totalSteps}] š¦ Initializing Git repository...`).start();
|
|
68
|
+
await this.sleep(600);
|
|
69
|
+
await this.initializeGit();
|
|
70
|
+
spinner7.success({ text: `š¦ Git repository initialized` });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Step 8: Install dependencies
|
|
74
|
+
if (this.config.install) {
|
|
75
|
+
currentStep++;
|
|
76
|
+
const spinner8 = createSpinner(`[${currentStep}/${totalSteps}] š„ Installing dependencies...`).start();
|
|
77
|
+
await this.installDependencies();
|
|
78
|
+
spinner8.success({ text: `š„ Dependencies installed successfully` });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error(chalk.red('\nā Setup failed:'), error.message);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async createDirectory() {
|
|
88
|
+
if (fs.existsSync(this.projectPath)) {
|
|
89
|
+
throw new Error(`Directory ${this.config.projectName} already exists`);
|
|
90
|
+
}
|
|
91
|
+
fs.mkdirSync(this.projectPath, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async createProjectStructure() {
|
|
95
|
+
const directories = this.getDirectoriesForTemplate();
|
|
96
|
+
|
|
97
|
+
for (const dir of directories) {
|
|
98
|
+
const fullPath = path.join(this.projectPath, dir);
|
|
99
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getDirectoriesForTemplate() {
|
|
104
|
+
const baseDirectories = [
|
|
105
|
+
'views',
|
|
106
|
+
'views/layouts',
|
|
107
|
+
'views/partials',
|
|
108
|
+
'views/components',
|
|
109
|
+
'routes',
|
|
110
|
+
'routes/api',
|
|
111
|
+
'public',
|
|
112
|
+
'public/css',
|
|
113
|
+
'public/js',
|
|
114
|
+
'public/images',
|
|
115
|
+
'config',
|
|
116
|
+
'middleware',
|
|
117
|
+
'plugins',
|
|
118
|
+
'data',
|
|
119
|
+
'utils'
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const templateDirectories = {
|
|
123
|
+
blog: ['content', 'content/posts', 'admin', 'uploads'],
|
|
124
|
+
admin: ['admin', 'admin/views', 'dashboard'],
|
|
125
|
+
ecommerce: ['shop', 'products', 'orders', 'cart'],
|
|
126
|
+
portfolio: ['portfolio', 'projects', 'gallery'],
|
|
127
|
+
pwa: ['pwa', 'sw', 'manifest', 'offline']
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return [
|
|
131
|
+
...baseDirectories,
|
|
132
|
+
...(templateDirectories[this.config.template] || [])
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async generateTemplateFiles() {
|
|
137
|
+
const TemplateGenerator = require('./template-generator');
|
|
138
|
+
const generator = new TemplateGenerator(this.config);
|
|
139
|
+
const files = generator.generateFiles();
|
|
140
|
+
|
|
141
|
+
for (const [filePath, content] of Object.entries(files)) {
|
|
142
|
+
const fullPath = path.join(this.projectPath, filePath);
|
|
143
|
+
const dir = path.dirname(fullPath);
|
|
144
|
+
|
|
145
|
+
if (!fs.existsSync(dir)) {
|
|
146
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
fs.writeFileSync(fullPath, content, 'utf8');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async configureFeatures() {
|
|
154
|
+
const FeatureConfigurer = require('./feature-configurer');
|
|
155
|
+
const configurer = new FeatureConfigurer(this.config, this.projectPath);
|
|
156
|
+
await configurer.configure();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async setupAuthentication() {
|
|
160
|
+
if (this.config.auth.enabled) {
|
|
161
|
+
const AuthSetup = require('./auth-setup');
|
|
162
|
+
const authSetup = new AuthSetup(this.config, this.projectPath);
|
|
163
|
+
await authSetup.configure();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async setupDatabase() {
|
|
168
|
+
const DatabaseSetup = require('./database-setup');
|
|
169
|
+
const dbSetup = new DatabaseSetup(this.config, this.projectPath);
|
|
170
|
+
await dbSetup.configure();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async initializeGit() {
|
|
174
|
+
try {
|
|
175
|
+
execSync('git init', { cwd: this.projectPath, stdio: 'pipe' });
|
|
176
|
+
execSync('git add .', { cwd: this.projectPath, stdio: 'pipe' });
|
|
177
|
+
execSync('git commit -m "š Initial commit - Created with Veko.js"', {
|
|
178
|
+
cwd: this.projectPath,
|
|
179
|
+
stdio: 'pipe'
|
|
180
|
+
});
|
|
181
|
+
} catch (error) {
|
|
182
|
+
// Git initialization is optional
|
|
183
|
+
console.log(chalk.yellow(' ā Git initialization failed (optional)'));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async installDependencies() {
|
|
188
|
+
try {
|
|
189
|
+
execSync('npm install', {
|
|
190
|
+
cwd: this.projectPath,
|
|
191
|
+
stdio: 'pipe'
|
|
192
|
+
});
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw new Error('Failed to install dependencies. Run "npm install" manually.');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
sleep(ms) {
|
|
199
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
module.exports = SetupExecutor;
|