vako 1.3.0 → 1.3.3
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 -63
- package/README.md +311 -1661
- package/bin/create-veko-app.js +5 -5
- package/bin/{veko.js → vako.js} +11 -11
- package/bin/veko-update.js +15 -15
- package/lib/adapters/nextjs-adapter.js +241 -241
- package/package.json +11 -12
- package/tsconfig.json +50 -50
- package/types/index.d.ts +238 -238
package/bin/create-veko-app.js
CHANGED
|
@@ -8,19 +8,19 @@ const QuickSetup = require('./commands/quick-setup');
|
|
|
8
8
|
const program = new Command();
|
|
9
9
|
|
|
10
10
|
program
|
|
11
|
-
.name('create-
|
|
12
|
-
.description('Create a new
|
|
13
|
-
.version('1.
|
|
11
|
+
.name('create-vako-app')
|
|
12
|
+
.description('Create a new Vako application')
|
|
13
|
+
.version('1.3.0')
|
|
14
14
|
.argument('[project-name]', 'Name of the project')
|
|
15
15
|
.option('--template <template>', 'Template to use')
|
|
16
16
|
.option('--quick', 'Quick setup with minimal questions')
|
|
17
17
|
.option('--wizard', 'Full interactive wizard')
|
|
18
18
|
.action(async (projectName, options) => {
|
|
19
|
-
console.log(chalk.blue.bold('🚀 Create
|
|
19
|
+
console.log(chalk.blue.bold('🚀 Create Vako App\n'));
|
|
20
20
|
|
|
21
21
|
if (!projectName) {
|
|
22
22
|
console.log(chalk.red('❌ Project name is required'));
|
|
23
|
-
console.log(chalk.gray('Usage: npx create-
|
|
23
|
+
console.log(chalk.gray('Usage: npx create-vako-app my-app'));
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
|
package/bin/{veko.js → vako.js}
RENAMED
|
@@ -19,9 +19,9 @@ require('module')._initPaths();
|
|
|
19
19
|
const program = new Command();
|
|
20
20
|
|
|
21
21
|
program
|
|
22
|
-
.name('
|
|
23
|
-
.description('
|
|
24
|
-
.version('1.
|
|
22
|
+
.name('vako')
|
|
23
|
+
.description('Vako Framework CLI')
|
|
24
|
+
.version('1.3.3');
|
|
25
25
|
|
|
26
26
|
// ============= DEV COMMAND =============
|
|
27
27
|
program
|
|
@@ -82,7 +82,7 @@ program
|
|
|
82
82
|
.action(async (projectNameArg, options) => {
|
|
83
83
|
if (options.quick) {
|
|
84
84
|
const quickConfig = {
|
|
85
|
-
projectName: projectNameArg || '
|
|
85
|
+
projectName: projectNameArg || 'vako-app',
|
|
86
86
|
template: options.template || 'default',
|
|
87
87
|
features: options.features ? options.features.split(',') : ['hotreload', 'layouts'],
|
|
88
88
|
database: options.db || 'sqlite',
|
|
@@ -152,11 +152,11 @@ program
|
|
|
152
152
|
// Ajout de la commande update qui servira de passerelle vers veko-update
|
|
153
153
|
program
|
|
154
154
|
.command('update')
|
|
155
|
-
.description('Gestionnaire de mise à jour
|
|
155
|
+
.description('Gestionnaire de mise à jour Vako')
|
|
156
156
|
.allowUnknownOption(true)
|
|
157
157
|
.action(() => {
|
|
158
158
|
// Exécuter veko-update avec les mêmes arguments
|
|
159
|
-
const updateBin = path.join(__dirname, 'veko-update.js');
|
|
159
|
+
const updateBin = path.join(__dirname, 'veko-update.js'); // Note: fichier garde le nom veko-update.js pour compatibilité
|
|
160
160
|
if (fs.existsSync(updateBin)) {
|
|
161
161
|
const { execSync } = require('child_process');
|
|
162
162
|
try {
|
|
@@ -176,13 +176,13 @@ program
|
|
|
176
176
|
program.parse(process.argv);
|
|
177
177
|
|
|
178
178
|
if (!process.argv.slice(2).length) {
|
|
179
|
-
console.log('\n🚀
|
|
179
|
+
console.log('\n🚀 Vako v' + version + ' - Ultra-modern Node.js framework\n');
|
|
180
180
|
console.log('Available commands:');
|
|
181
181
|
console.log(' dev Start development server with hot reload');
|
|
182
|
-
console.log(' setup Set up a new
|
|
182
|
+
console.log(' setup Set up a new Vako project');
|
|
183
183
|
console.log(' verify Verify code quality and security');
|
|
184
|
-
console.log(' update Gestionnaire de mise à jour
|
|
185
|
-
console.log('\nRun `
|
|
186
|
-
console.log('\nDocumentation: https://
|
|
184
|
+
console.log(' update Gestionnaire de mise à jour Vako');
|
|
185
|
+
console.log('\nRun `vako <command> --help` for more information on specific commands.');
|
|
186
|
+
console.log('\nDocumentation: https://github.com/sdevfr/vako');
|
|
187
187
|
process.exit(0);
|
|
188
188
|
}
|
package/bin/veko-update.js
CHANGED
|
@@ -24,27 +24,27 @@ function emergencyRepair() {
|
|
|
24
24
|
|
|
25
25
|
console.error('✅ package.json trouvé');
|
|
26
26
|
|
|
27
|
-
// Vérifier l'installation de
|
|
27
|
+
// Vérifier l'installation de vako
|
|
28
28
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
29
|
-
const
|
|
30
|
-
packageJson.devDependencies?.
|
|
31
|
-
packageJson.peerDependencies?.
|
|
32
|
-
|
|
33
|
-
if (!
|
|
34
|
-
console.error('⚠️
|
|
35
|
-
console.error('🔧 Installation de
|
|
29
|
+
const vakoVersion = packageJson.dependencies?.vako ||
|
|
30
|
+
packageJson.devDependencies?.vako ||
|
|
31
|
+
packageJson.peerDependencies?.vako;
|
|
32
|
+
|
|
33
|
+
if (!vakoVersion) {
|
|
34
|
+
console.error('⚠️ Vako non trouvé dans package.json');
|
|
35
|
+
console.error('🔧 Installation de vako...');
|
|
36
36
|
|
|
37
37
|
const { execSync } = require('child_process');
|
|
38
38
|
try {
|
|
39
|
-
execSync('npm install
|
|
40
|
-
console.error('✅
|
|
39
|
+
execSync('npm install vako@latest', { stdio: 'inherit' });
|
|
40
|
+
console.error('✅ Vako installé avec succès');
|
|
41
41
|
return true;
|
|
42
42
|
} catch (error) {
|
|
43
43
|
console.error('❌ Échec de l\'installation:', error.message);
|
|
44
44
|
return false;
|
|
45
45
|
}
|
|
46
46
|
} else {
|
|
47
|
-
console.error(`✅
|
|
47
|
+
console.error(`✅ Vako v${vakoVersion.replace(/[\^~>=<]/g, '')} détecté`);
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -135,7 +135,7 @@ async function main() {
|
|
|
135
135
|
console.error('\n🔧 DIAGNOSTIC:');
|
|
136
136
|
console.error('L\'auto-updater semble être corrompu ou incompatible.');
|
|
137
137
|
console.error('\n💡 SOLUTIONS:');
|
|
138
|
-
console.error('1. Réinstallez
|
|
138
|
+
console.error('1. Réinstallez vako: npm install vako@latest');
|
|
139
139
|
console.error('2. Nettoyez le cache npm: npm cache clean --force');
|
|
140
140
|
console.error('3. Supprimez node_modules et réinstallez: rm -rf node_modules && npm install');
|
|
141
141
|
} else if (error.message.includes('Timeout')) {
|
|
@@ -144,10 +144,10 @@ async function main() {
|
|
|
144
144
|
console.error('\n💡 SOLUTIONS:');
|
|
145
145
|
console.error('1. Vérifiez votre connexion internet');
|
|
146
146
|
console.error('2. Essayez à nouveau dans quelques minutes');
|
|
147
|
-
console.error('3. Utilisez:
|
|
147
|
+
console.error('3. Utilisez: vako update fix pour réparer');
|
|
148
148
|
} else {
|
|
149
149
|
console.error('\n💡 Pour réparer automatiquement l\'auto-updater:');
|
|
150
|
-
console.error('npm install
|
|
150
|
+
console.error('npm install vako@latest');
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
if (process.env.DEBUG) {
|
|
@@ -176,7 +176,7 @@ process.on('uncaughtException', (error) => {
|
|
|
176
176
|
|
|
177
177
|
if (error.message && error.message.includes('not a function')) {
|
|
178
178
|
console.error('\n🔧 L\'auto-updater est corrompu.');
|
|
179
|
-
console.error('Exécutez: npm install
|
|
179
|
+
console.error('Exécutez: npm install vako@latest');
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
if (process.env.DEBUG) {
|
|
@@ -1,241 +1,241 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Next.js Adapter for
|
|
3
|
-
*
|
|
4
|
-
* Permet d'intégrer
|
|
5
|
-
* - Utilisez les routes
|
|
6
|
-
* - Utilisez les plugins
|
|
7
|
-
* - Compatible avec les API routes de Next.js
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
class NextJsAdapter {
|
|
13
|
-
constructor(options = {}) {
|
|
14
|
-
this.nextApp = options.nextApp;
|
|
15
|
-
this.
|
|
16
|
-
this.
|
|
17
|
-
this.routePrefix = options.routePrefix || '/api/
|
|
18
|
-
this.
|
|
19
|
-
this.integrated = false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Intègre les routes
|
|
24
|
-
* @param {App}
|
|
25
|
-
*/
|
|
26
|
-
integrateRoutes(
|
|
27
|
-
if (!this.nextApp) {
|
|
28
|
-
throw new Error('Next.js app instance is required');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
if (!this.
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Créer un handler Next.js pour toutes les routes
|
|
38
|
-
this.nextApp.use(this.routePrefix, (req, res, next) => {
|
|
39
|
-
// Passer la requête à Express (
|
|
40
|
-
this.
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
this.integrated = true;
|
|
44
|
-
this.
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Active les plugins
|
|
49
|
-
* @param {App}
|
|
50
|
-
*/
|
|
51
|
-
usePlugins(
|
|
52
|
-
if (!this.
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
// Exposer les plugins dans le contexte Next.js
|
|
59
|
-
if (this.nextApp.getRequestHandler) {
|
|
60
|
-
const originalHandler = this.nextApp.getRequestHandler();
|
|
61
|
-
|
|
62
|
-
this.nextApp.getRequestHandler = (req, res) => {
|
|
63
|
-
// Ajouter les plugins au contexte de la requête
|
|
64
|
-
req.
|
|
65
|
-
req.
|
|
66
|
-
|
|
67
|
-
return originalHandler(req, res);
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Crée un handler API Next.js à partir d'un handler
|
|
76
|
-
* @param {Function}
|
|
77
|
-
* @returns {Function} Handler compatible Next.js API route
|
|
78
|
-
*/
|
|
79
|
-
createApiHandler(
|
|
80
|
-
return async (req, res) => {
|
|
81
|
-
try {
|
|
82
|
-
// Adapter le contexte pour être compatible avec Express
|
|
83
|
-
await new Promise((resolve, reject) => {
|
|
84
|
-
const next = (err) => {
|
|
85
|
-
if (err) reject(err);
|
|
86
|
-
else resolve();
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
// Appeler le handler
|
|
90
|
-
const result =
|
|
91
|
-
|
|
92
|
-
// Si c'est une Promise, attendre sa résolution
|
|
93
|
-
if (result && typeof result.then === 'function') {
|
|
94
|
-
result.catch(reject);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
} catch (error) {
|
|
98
|
-
if (!res.headersSent) {
|
|
99
|
-
res.status(500).json({ error: error.message });
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Middleware pour Next.js qui expose les fonctionnalités
|
|
107
|
-
* @returns {Function} Middleware Express compatible
|
|
108
|
-
*/
|
|
109
|
-
middleware() {
|
|
110
|
-
return (req, res, next) => {
|
|
111
|
-
if (!this.
|
|
112
|
-
return next();
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Ajouter l'app
|
|
116
|
-
req.
|
|
117
|
-
req.
|
|
118
|
-
req.
|
|
119
|
-
|
|
120
|
-
// Exécuter les hooks
|
|
121
|
-
if (this.
|
|
122
|
-
this.
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Hook pour la fin de la requête
|
|
126
|
-
const originalEnd = res.end;
|
|
127
|
-
res.end = function(...args) {
|
|
128
|
-
if (this.
|
|
129
|
-
this.
|
|
130
|
-
}
|
|
131
|
-
return originalEnd.apply(this, args);
|
|
132
|
-
}.bind({
|
|
133
|
-
|
|
134
|
-
next();
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Crée une route API Next.js dynamique depuis une route
|
|
140
|
-
* @param {string} method - Méthode HTTP
|
|
141
|
-
* @param {string} path - Chemin de la route
|
|
142
|
-
* @param {Function|Array} handlers - Handlers
|
|
143
|
-
*/
|
|
144
|
-
createNextApiRoute(method, path, handlers) {
|
|
145
|
-
if (!this.nextApp) {
|
|
146
|
-
throw new Error('Next.js app instance is required');
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const fullPath = path.startsWith('/') ? path : `/${path}`;
|
|
150
|
-
const apiPath = `${this.routePrefix}${fullPath}`;
|
|
151
|
-
|
|
152
|
-
// Convertir les handlers en handler Next.js
|
|
153
|
-
const handlerArray = Array.isArray(handlers) ? handlers : [handlers];
|
|
154
|
-
const nextHandler = this.createApiHandler(async (req, res) => {
|
|
155
|
-
for (const handler of handlerArray) {
|
|
156
|
-
await new Promise((resolve, reject) => {
|
|
157
|
-
const next = (err) => {
|
|
158
|
-
if (err) reject(err);
|
|
159
|
-
else resolve();
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const result = handler(req, res, next);
|
|
163
|
-
if (result && typeof result.then === 'function') {
|
|
164
|
-
result.catch(reject);
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// Enregistrer la route dans Next.js
|
|
171
|
-
// Note: Cela nécessite une configuration spéciale dans Next.js
|
|
172
|
-
// car Next.js utilise un système de routing basé sur les fichiers
|
|
173
|
-
this.
|
|
174
|
-
|
|
175
|
-
return {
|
|
176
|
-
path: apiPath,
|
|
177
|
-
method: method.toUpperCase(),
|
|
178
|
-
handler: nextHandler
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Génère les fichiers de routes API Next.js depuis les routes
|
|
184
|
-
* @param {string} outputDir - Dossier de sortie (pages/api ou app/api)
|
|
185
|
-
*/
|
|
186
|
-
generateNextApiFiles(outputDir = 'pages/api') {
|
|
187
|
-
if (!this.
|
|
188
|
-
throw new Error('
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const routes = this.
|
|
192
|
-
const fs = require('fs');
|
|
193
|
-
const path = require('path');
|
|
194
|
-
|
|
195
|
-
routes.forEach(route => {
|
|
196
|
-
const routePath = route.path.replace(this.routePrefix, '').replace(/^\//, '');
|
|
197
|
-
const filePath = path.join(outputDir, routePath.replace(/\//g, '/'));
|
|
198
|
-
const dirPath = path.dirname(filePath);
|
|
199
|
-
|
|
200
|
-
// Créer le dossier si nécessaire
|
|
201
|
-
if (!fs.existsSync(dirPath)) {
|
|
202
|
-
fs.mkdirSync(dirPath, { recursive: true });
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Générer le fichier API Next.js
|
|
206
|
-
const content = this.generateNextApiFileContent(route);
|
|
207
|
-
fs.writeFileSync(`${filePath}.js`, content);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
this.
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Génère le contenu d'un fichier API Next.js
|
|
215
|
-
* @private
|
|
216
|
-
*/
|
|
217
|
-
generateNextApiFileContent(route) {
|
|
218
|
-
return `// Auto-generated by
|
|
219
|
-
// Route: ${route.method} ${route.path}
|
|
220
|
-
|
|
221
|
-
export default async function handler(req, res) {
|
|
222
|
-
// Cette route est gérée par
|
|
223
|
-
// Pour personnaliser, modifiez ce fichier
|
|
224
|
-
|
|
225
|
-
if (req.method !== '${route.method}') {
|
|
226
|
-
return res.status(405).json({ error: 'Method not allowed' });
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Rediriger vers le handler
|
|
230
|
-
// Note: Vous devez configurer le proxy ou utiliser le middleware
|
|
231
|
-
return res.status(200).json({
|
|
232
|
-
message: 'Route handled by
|
|
233
|
-
route: '${route.path}',
|
|
234
|
-
method: '${route.method}'
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
`;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
module.exports = NextJsAdapter;
|
|
1
|
+
/**
|
|
2
|
+
* Next.js Adapter for Vako
|
|
3
|
+
*
|
|
4
|
+
* Permet d'intégrer Vako avec Next.js pour bénéficier des deux frameworks
|
|
5
|
+
* - Utilisez les routes Vako dans Next.js
|
|
6
|
+
* - Utilisez les plugins Vako dans Next.js
|
|
7
|
+
* - Compatible avec les API routes de Next.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
class NextJsAdapter {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.nextApp = options.nextApp;
|
|
15
|
+
this.enableVakoRoutes = options.enableVakoRoutes !== false;
|
|
16
|
+
this.enableVakoPlugins = options.enableVakoPlugins !== false;
|
|
17
|
+
this.routePrefix = options.routePrefix || '/api/vako';
|
|
18
|
+
this.vakoApp = null;
|
|
19
|
+
this.integrated = false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Intègre les routes Vako avec Next.js
|
|
24
|
+
* @param {App} vakoApp - Instance de l'application Vako
|
|
25
|
+
*/
|
|
26
|
+
integrateRoutes(vakoApp) {
|
|
27
|
+
if (!this.nextApp) {
|
|
28
|
+
throw new Error('Next.js app instance is required');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.vakoApp = vakoApp;
|
|
32
|
+
|
|
33
|
+
if (!this.enableVakoRoutes) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Créer un handler Next.js pour toutes les routes Vako
|
|
38
|
+
this.nextApp.use(this.routePrefix, (req, res, next) => {
|
|
39
|
+
// Passer la requête à Express (Vako utilise Express)
|
|
40
|
+
this.vakoApp.express(req, res, next);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this.integrated = true;
|
|
44
|
+
this.vakoApp.log('success', 'Next.js adapter intégré', `Routes disponibles sous ${this.routePrefix}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Active les plugins Vako dans Next.js
|
|
49
|
+
* @param {App} vakoApp - Instance de l'application Vako
|
|
50
|
+
*/
|
|
51
|
+
usePlugins(vakoApp) {
|
|
52
|
+
if (!this.enableVakoPlugins) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.vakoApp = vakoApp;
|
|
57
|
+
|
|
58
|
+
// Exposer les plugins dans le contexte Next.js
|
|
59
|
+
if (this.nextApp.getRequestHandler) {
|
|
60
|
+
const originalHandler = this.nextApp.getRequestHandler();
|
|
61
|
+
|
|
62
|
+
this.nextApp.getRequestHandler = (req, res) => {
|
|
63
|
+
// Ajouter les plugins au contexte de la requête
|
|
64
|
+
req.vakoPlugins = vakoApp.pluginManager?.plugins || new Map();
|
|
65
|
+
req.vakoApp = vakoApp;
|
|
66
|
+
|
|
67
|
+
return originalHandler(req, res);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
vakoApp.log('info', 'Plugins Vako disponibles dans Next.js');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Crée un handler API Next.js à partir d'un handler Vako
|
|
76
|
+
* @param {Function} vakoHandler - Handler Vako
|
|
77
|
+
* @returns {Function} Handler compatible Next.js API route
|
|
78
|
+
*/
|
|
79
|
+
createApiHandler(vakoHandler) {
|
|
80
|
+
return async (req, res) => {
|
|
81
|
+
try {
|
|
82
|
+
// Adapter le contexte pour être compatible avec Express
|
|
83
|
+
await new Promise((resolve, reject) => {
|
|
84
|
+
const next = (err) => {
|
|
85
|
+
if (err) reject(err);
|
|
86
|
+
else resolve();
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Appeler le handler Vako avec le contexte Express
|
|
90
|
+
const result = vakoHandler(req, res, next);
|
|
91
|
+
|
|
92
|
+
// Si c'est une Promise, attendre sa résolution
|
|
93
|
+
if (result && typeof result.then === 'function') {
|
|
94
|
+
result.catch(reject);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (!res.headersSent) {
|
|
99
|
+
res.status(500).json({ error: error.message });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Middleware pour Next.js qui expose les fonctionnalités Vako
|
|
107
|
+
* @returns {Function} Middleware Express compatible
|
|
108
|
+
*/
|
|
109
|
+
middleware() {
|
|
110
|
+
return (req, res, next) => {
|
|
111
|
+
if (!this.vakoApp) {
|
|
112
|
+
return next();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Ajouter l'app Vako au contexte de la requête
|
|
116
|
+
req.vakoApp = this.vakoApp;
|
|
117
|
+
req.vakoPlugins = this.vakoApp.pluginManager?.plugins || new Map();
|
|
118
|
+
req.vakoLogger = this.vakoApp.logger;
|
|
119
|
+
|
|
120
|
+
// Exécuter les hooks Vako
|
|
121
|
+
if (this.vakoApp.pluginManager) {
|
|
122
|
+
this.vakoApp.pluginManager.executeHook('request:start', req, res);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Hook pour la fin de la requête
|
|
126
|
+
const originalEnd = res.end;
|
|
127
|
+
res.end = function(...args) {
|
|
128
|
+
if (this.vakoApp?.pluginManager) {
|
|
129
|
+
this.vakoApp.pluginManager.executeHook('request:end', req, res);
|
|
130
|
+
}
|
|
131
|
+
return originalEnd.apply(this, args);
|
|
132
|
+
}.bind({ vakoApp: this.vakoApp });
|
|
133
|
+
|
|
134
|
+
next();
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Crée une route API Next.js dynamique depuis une route Vako
|
|
140
|
+
* @param {string} method - Méthode HTTP
|
|
141
|
+
* @param {string} path - Chemin de la route
|
|
142
|
+
* @param {Function|Array} handlers - Handlers Vako
|
|
143
|
+
*/
|
|
144
|
+
createNextApiRoute(method, path, handlers) {
|
|
145
|
+
if (!this.nextApp) {
|
|
146
|
+
throw new Error('Next.js app instance is required');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const fullPath = path.startsWith('/') ? path : `/${path}`;
|
|
150
|
+
const apiPath = `${this.routePrefix}${fullPath}`;
|
|
151
|
+
|
|
152
|
+
// Convertir les handlers en handler Next.js
|
|
153
|
+
const handlerArray = Array.isArray(handlers) ? handlers : [handlers];
|
|
154
|
+
const nextHandler = this.createApiHandler(async (req, res) => {
|
|
155
|
+
for (const handler of handlerArray) {
|
|
156
|
+
await new Promise((resolve, reject) => {
|
|
157
|
+
const next = (err) => {
|
|
158
|
+
if (err) reject(err);
|
|
159
|
+
else resolve();
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const result = handler(req, res, next);
|
|
163
|
+
if (result && typeof result.then === 'function') {
|
|
164
|
+
result.catch(reject);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Enregistrer la route dans Next.js
|
|
171
|
+
// Note: Cela nécessite une configuration spéciale dans Next.js
|
|
172
|
+
// car Next.js utilise un système de routing basé sur les fichiers
|
|
173
|
+
this.vakoApp?.log('info', `Route Next.js créée: ${method.toUpperCase()} ${apiPath}`);
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
path: apiPath,
|
|
177
|
+
method: method.toUpperCase(),
|
|
178
|
+
handler: nextHandler
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Génère les fichiers de routes API Next.js depuis les routes Vako
|
|
184
|
+
* @param {string} outputDir - Dossier de sortie (pages/api ou app/api)
|
|
185
|
+
*/
|
|
186
|
+
generateNextApiFiles(outputDir = 'pages/api') {
|
|
187
|
+
if (!this.vakoApp) {
|
|
188
|
+
throw new Error('Vako app must be integrated first');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const routes = this.vakoApp.listRoutes();
|
|
192
|
+
const fs = require('fs');
|
|
193
|
+
const path = require('path');
|
|
194
|
+
|
|
195
|
+
routes.forEach(route => {
|
|
196
|
+
const routePath = route.path.replace(this.routePrefix, '').replace(/^\//, '');
|
|
197
|
+
const filePath = path.join(outputDir, routePath.replace(/\//g, '/'));
|
|
198
|
+
const dirPath = path.dirname(filePath);
|
|
199
|
+
|
|
200
|
+
// Créer le dossier si nécessaire
|
|
201
|
+
if (!fs.existsSync(dirPath)) {
|
|
202
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Générer le fichier API Next.js
|
|
206
|
+
const content = this.generateNextApiFileContent(route);
|
|
207
|
+
fs.writeFileSync(`${filePath}.js`, content);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
this.vakoApp.log('success', 'Fichiers API Next.js générés', `Dans ${outputDir}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Génère le contenu d'un fichier API Next.js
|
|
215
|
+
* @private
|
|
216
|
+
*/
|
|
217
|
+
generateNextApiFileContent(route) {
|
|
218
|
+
return `// Auto-generated by Vako Next.js Adapter
|
|
219
|
+
// Route: ${route.method} ${route.path}
|
|
220
|
+
|
|
221
|
+
export default async function handler(req, res) {
|
|
222
|
+
// Cette route est gérée par Vako
|
|
223
|
+
// Pour personnaliser, modifiez ce fichier
|
|
224
|
+
|
|
225
|
+
if (req.method !== '${route.method}') {
|
|
226
|
+
return res.status(405).json({ error: 'Method not allowed' });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Rediriger vers le handler Vako
|
|
230
|
+
// Note: Vous devez configurer le proxy ou utiliser le middleware
|
|
231
|
+
return res.status(200).json({
|
|
232
|
+
message: 'Route handled by Vako',
|
|
233
|
+
route: '${route.path}',
|
|
234
|
+
method: '${route.method}'
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
`;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
module.exports = NextJsAdapter;
|