create-fluxstack 1.5.2 → 1.5.4
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/.env.example +8 -1
- package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +475 -0
- package/CRYPTO-AUTH-MIDDLEWARES.md +473 -0
- package/CRYPTO-AUTH-USAGE.md +491 -0
- package/EXEMPLO-ROTA-PROTEGIDA.md +347 -0
- package/QUICK-START-CRYPTO-AUTH.md +221 -0
- package/app/client/src/App.tsx +4 -1
- package/app/client/src/pages/CryptoAuthPage.tsx +394 -0
- package/app/server/index.ts +4 -0
- package/app/server/live/FluxStackConfig.ts +1 -1
- package/app/server/routes/crypto-auth-demo.routes.ts +167 -0
- package/app/server/routes/example-with-crypto-auth.routes.ts +235 -0
- package/app/server/routes/exemplo-posts.routes.ts +161 -0
- package/app/server/routes/index.ts +5 -1
- package/config/index.ts +9 -1
- package/core/cli/generators/plugin.ts +324 -34
- package/core/cli/generators/template-engine.ts +5 -0
- package/core/cli/plugin-discovery.ts +33 -12
- package/core/framework/server.ts +10 -0
- package/core/plugins/dependency-manager.ts +89 -22
- package/core/plugins/index.ts +4 -0
- package/core/plugins/manager.ts +3 -2
- package/core/plugins/module-resolver.ts +216 -0
- package/core/plugins/registry.ts +28 -1
- package/core/templates/create-project.ts +7 -0
- package/core/utils/logger/index.ts +4 -0
- package/core/utils/version.ts +1 -1
- package/fluxstack.config.ts +253 -114
- package/package.json +3 -3
- package/plugins/crypto-auth/README.md +788 -0
- package/plugins/crypto-auth/ai-context.md +1282 -0
- package/plugins/crypto-auth/cli/make-protected-route.command.ts +383 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -0
- package/plugins/crypto-auth/client/components/AuthProvider.tsx +131 -0
- package/plugins/crypto-auth/client/components/LoginButton.tsx +138 -0
- package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +89 -0
- package/plugins/crypto-auth/client/components/index.ts +12 -0
- package/plugins/crypto-auth/client/index.ts +12 -0
- package/plugins/crypto-auth/config/index.ts +34 -0
- package/plugins/crypto-auth/index.ts +162 -0
- package/plugins/crypto-auth/package.json +66 -0
- package/plugins/crypto-auth/server/AuthMiddleware.ts +181 -0
- package/plugins/crypto-auth/server/CryptoAuthService.ts +186 -0
- package/plugins/crypto-auth/server/index.ts +22 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +65 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +26 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +76 -0
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +45 -0
- package/plugins/crypto-auth/server/middlewares/helpers.ts +140 -0
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -0
- package/plugins/crypto-auth/server/middlewares.ts +19 -0
- package/test-crypto-auth.ts +101 -0
|
@@ -33,11 +33,12 @@ export class PluginGenerator implements Generator {
|
|
|
33
33
|
|
|
34
34
|
console.log(`\n✅ Generated plugin '${options.name}' with ${files.length} files`)
|
|
35
35
|
console.log(`\n📦 Next steps:`)
|
|
36
|
-
console.log(` 1.
|
|
37
|
-
console.log(` 2.
|
|
38
|
-
console.log(` 3.
|
|
39
|
-
console.log(` 4. Add
|
|
40
|
-
console.log(` 5.
|
|
36
|
+
console.log(` 1. Configure plugin in plugins/${options.name}/config/index.ts`)
|
|
37
|
+
console.log(` 2. Set environment variables (optional): ${options.name.toUpperCase().replace(/-/g, '_')}_*`)
|
|
38
|
+
console.log(` 3. Implement your plugin logic in plugins/${options.name}/index.ts`)
|
|
39
|
+
console.log(` 4. Add server-side code in plugins/${options.name}/server/ (optional)`)
|
|
40
|
+
console.log(` 5. Add client-side code in plugins/${options.name}/client/ (optional)`)
|
|
41
|
+
console.log(` 6. Run: bun run dev`)
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
private getTemplate(templateName?: string): Template {
|
|
@@ -59,31 +60,80 @@ export class PluginGenerator implements Generator {
|
|
|
59
60
|
description: 'Basic plugin template with essential files',
|
|
60
61
|
files: [
|
|
61
62
|
{
|
|
62
|
-
path: 'plugins/{{name}}/
|
|
63
|
+
path: 'plugins/{{name}}/package.json',
|
|
63
64
|
content: `{
|
|
64
|
-
"name": "{{name}}",
|
|
65
|
+
"name": "@fluxstack/{{name}}-plugin",
|
|
65
66
|
"version": "1.0.0",
|
|
66
67
|
"description": "{{description}}",
|
|
67
|
-
"author": "Your Name",
|
|
68
|
-
"type": "fluxstack-plugin",
|
|
69
68
|
"main": "index.ts",
|
|
69
|
+
"types": "index.ts",
|
|
70
|
+
"exports": {
|
|
71
|
+
".": {
|
|
72
|
+
"import": "./index.ts",
|
|
73
|
+
"types": "./index.ts"
|
|
74
|
+
},
|
|
75
|
+
"./config": {
|
|
76
|
+
"import": "./config/index.ts",
|
|
77
|
+
"types": "./config/index.ts"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"keywords": [
|
|
81
|
+
"fluxstack",
|
|
82
|
+
"plugin",
|
|
83
|
+
"{{name}}",
|
|
84
|
+
"typescript"
|
|
85
|
+
],
|
|
86
|
+
"author": "FluxStack Developer",
|
|
87
|
+
"license": "MIT",
|
|
88
|
+
"peerDependencies": {},
|
|
70
89
|
"dependencies": {},
|
|
71
|
-
"
|
|
72
|
-
"
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"typescript": "^5.0.0"
|
|
73
92
|
},
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
"fluxstack": {
|
|
94
|
+
"plugin": true,
|
|
95
|
+
"version": "^1.0.0",
|
|
96
|
+
"hooks": [
|
|
97
|
+
"setup",
|
|
98
|
+
"onServerStart"
|
|
99
|
+
],
|
|
100
|
+
"category": "utility",
|
|
101
|
+
"tags": ["{{name}}"]
|
|
80
102
|
}
|
|
81
103
|
}
|
|
104
|
+
`
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
path: 'plugins/{{name}}/config/index.ts',
|
|
108
|
+
content: `/**
|
|
109
|
+
* {{pascalName}} Plugin Configuration
|
|
110
|
+
* Declarative config using FluxStack config system
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
import { defineConfig, config } from '@/core/utils/config-schema'
|
|
114
|
+
|
|
115
|
+
const {{camelName}}ConfigSchema = {
|
|
116
|
+
// Enable/disable plugin
|
|
117
|
+
enabled: config.boolean('{{constantName}}_ENABLED', true),
|
|
118
|
+
|
|
119
|
+
// Add your configuration options here
|
|
120
|
+
// Example:
|
|
121
|
+
// apiKey: config.string('{{constantName}}_API_KEY', ''),
|
|
122
|
+
// timeout: config.number('{{constantName}}_TIMEOUT', 5000),
|
|
123
|
+
// debug: config.boolean('{{constantName}}_DEBUG', false),
|
|
124
|
+
} as const
|
|
125
|
+
|
|
126
|
+
export const {{camelName}}Config = defineConfig({{camelName}}ConfigSchema)
|
|
127
|
+
|
|
128
|
+
export type {{pascalName}}Config = typeof {{camelName}}Config
|
|
129
|
+
export default {{camelName}}Config
|
|
82
130
|
`
|
|
83
131
|
},
|
|
84
132
|
{
|
|
85
133
|
path: 'plugins/{{name}}/index.ts',
|
|
86
134
|
content: `import type { FluxStackPlugin, PluginContext } from '@/core/types/plugin'
|
|
135
|
+
// ✅ Plugin imports its own configuration
|
|
136
|
+
import { {{camelName}}Config } from './config'
|
|
87
137
|
|
|
88
138
|
/**
|
|
89
139
|
* {{pascalName}} Plugin
|
|
@@ -97,6 +147,12 @@ export class {{pascalName}}Plugin implements FluxStackPlugin {
|
|
|
97
147
|
* Setup hook - called when plugin is loaded
|
|
98
148
|
*/
|
|
99
149
|
async setup(context: PluginContext): Promise<void> {
|
|
150
|
+
// Check if plugin is enabled
|
|
151
|
+
if (!{{camelName}}Config.enabled) {
|
|
152
|
+
context.logger.info(\`[{{name}}] Plugin disabled by configuration\`)
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
|
|
100
156
|
console.log(\`[{{name}}] Plugin initialized\`)
|
|
101
157
|
|
|
102
158
|
// Add your initialization logic here
|
|
@@ -107,6 +163,8 @@ export class {{pascalName}}Plugin implements FluxStackPlugin {
|
|
|
107
163
|
* Server start hook - called when server starts
|
|
108
164
|
*/
|
|
109
165
|
async onServerStart?(context: PluginContext): Promise<void> {
|
|
166
|
+
if (!{{camelName}}Config.enabled) return
|
|
167
|
+
|
|
110
168
|
console.log(\`[{{name}}] Server started\`)
|
|
111
169
|
|
|
112
170
|
// Add logic to run when server starts
|
|
@@ -116,6 +174,8 @@ export class {{pascalName}}Plugin implements FluxStackPlugin {
|
|
|
116
174
|
* Request hook - called on each request
|
|
117
175
|
*/
|
|
118
176
|
async onRequest?(context: PluginContext, request: Request): Promise<void> {
|
|
177
|
+
if (!{{camelName}}Config.enabled) return
|
|
178
|
+
|
|
119
179
|
// Add request processing logic
|
|
120
180
|
}
|
|
121
181
|
|
|
@@ -123,6 +183,8 @@ export class {{pascalName}}Plugin implements FluxStackPlugin {
|
|
|
123
183
|
* Response hook - called on each response
|
|
124
184
|
*/
|
|
125
185
|
async onResponse?(context: PluginContext, response: Response): Promise<void> {
|
|
186
|
+
if (!{{camelName}}Config.enabled) return
|
|
187
|
+
|
|
126
188
|
// Add response processing logic
|
|
127
189
|
}
|
|
128
190
|
|
|
@@ -156,17 +218,29 @@ This plugin is already in your FluxStack project. To use it:
|
|
|
156
218
|
bun run cli plugin:deps install
|
|
157
219
|
\`\`\`
|
|
158
220
|
|
|
221
|
+
## Configuration
|
|
222
|
+
|
|
223
|
+
This plugin uses FluxStack's declarative configuration system. Configure it by editing \`config/index.ts\` or by setting environment variables:
|
|
224
|
+
|
|
225
|
+
\`\`\`bash
|
|
226
|
+
# Enable/disable plugin
|
|
227
|
+
{{constantName}}_ENABLED=true
|
|
228
|
+
|
|
229
|
+
# Add your environment variables here
|
|
230
|
+
# Example:
|
|
231
|
+
# {{constantName}}_API_KEY=your-api-key
|
|
232
|
+
# {{constantName}}_TIMEOUT=5000
|
|
233
|
+
\`\`\`
|
|
234
|
+
|
|
235
|
+
The plugin's configuration is located in \`plugins/{{name}}/config/index.ts\` and is self-contained, making the plugin fully portable.
|
|
236
|
+
|
|
159
237
|
## Usage
|
|
160
238
|
|
|
161
239
|
\`\`\`typescript
|
|
162
240
|
// The plugin is automatically loaded by FluxStack
|
|
163
|
-
//
|
|
241
|
+
// It imports its own configuration from ./config
|
|
164
242
|
\`\`\`
|
|
165
243
|
|
|
166
|
-
## Configuration
|
|
167
|
-
|
|
168
|
-
Add configuration options here.
|
|
169
|
-
|
|
170
244
|
## API
|
|
171
245
|
|
|
172
246
|
Document your plugin's API here.
|
|
@@ -184,8 +258,8 @@ This plugin uses the following hooks:
|
|
|
184
258
|
|
|
185
259
|
To modify this plugin:
|
|
186
260
|
|
|
187
|
-
1. Edit \`index.ts\`
|
|
188
|
-
2.
|
|
261
|
+
1. Edit \`config/index.ts\` to add configuration options
|
|
262
|
+
2. Edit \`index.ts\` with your logic
|
|
189
263
|
3. Test with: \`bun run dev\`
|
|
190
264
|
|
|
191
265
|
## License
|
|
@@ -204,7 +278,60 @@ MIT
|
|
|
204
278
|
name: 'server-plugin',
|
|
205
279
|
description: 'Plugin with server-side code',
|
|
206
280
|
files: [
|
|
207
|
-
|
|
281
|
+
{
|
|
282
|
+
path: 'plugins/{{name}}/package.json',
|
|
283
|
+
content: `{
|
|
284
|
+
"name": "@fluxstack/{{name}}-plugin",
|
|
285
|
+
"version": "1.0.0",
|
|
286
|
+
"description": "{{description}}",
|
|
287
|
+
"main": "index.ts",
|
|
288
|
+
"types": "index.ts",
|
|
289
|
+
"exports": {
|
|
290
|
+
".": {
|
|
291
|
+
"import": "./index.ts",
|
|
292
|
+
"types": "./index.ts"
|
|
293
|
+
},
|
|
294
|
+
"./config": {
|
|
295
|
+
"import": "./config/index.ts",
|
|
296
|
+
"types": "./config/index.ts"
|
|
297
|
+
},
|
|
298
|
+
"./server": {
|
|
299
|
+
"import": "./server/index.ts",
|
|
300
|
+
"types": "./server/index.ts"
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
"keywords": [
|
|
304
|
+
"fluxstack",
|
|
305
|
+
"plugin",
|
|
306
|
+
"{{name}}",
|
|
307
|
+
"server",
|
|
308
|
+
"typescript"
|
|
309
|
+
],
|
|
310
|
+
"author": "FluxStack Developer",
|
|
311
|
+
"license": "MIT",
|
|
312
|
+
"peerDependencies": {
|
|
313
|
+
"elysia": "^1.0.0"
|
|
314
|
+
},
|
|
315
|
+
"dependencies": {},
|
|
316
|
+
"devDependencies": {
|
|
317
|
+
"typescript": "^5.0.0"
|
|
318
|
+
},
|
|
319
|
+
"fluxstack": {
|
|
320
|
+
"plugin": true,
|
|
321
|
+
"version": "^1.0.0",
|
|
322
|
+
"hooks": [
|
|
323
|
+
"setup",
|
|
324
|
+
"onServerStart",
|
|
325
|
+
"onRequest",
|
|
326
|
+
"onResponse"
|
|
327
|
+
],
|
|
328
|
+
"category": "utility",
|
|
329
|
+
"tags": ["{{name}}", "server"]
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
`
|
|
333
|
+
},
|
|
334
|
+
...basic.files.slice(1), // Skip package.json from basic
|
|
208
335
|
{
|
|
209
336
|
path: 'plugins/{{name}}/server/index.ts',
|
|
210
337
|
content: `/**
|
|
@@ -233,7 +360,65 @@ export const {{camelName}}Service = new {{pascalName}}Service()
|
|
|
233
360
|
name: 'client-plugin',
|
|
234
361
|
description: 'Plugin with client-side code',
|
|
235
362
|
files: [
|
|
236
|
-
|
|
363
|
+
{
|
|
364
|
+
path: 'plugins/{{name}}/package.json',
|
|
365
|
+
content: `{
|
|
366
|
+
"name": "@fluxstack/{{name}}-plugin",
|
|
367
|
+
"version": "1.0.0",
|
|
368
|
+
"description": "{{description}}",
|
|
369
|
+
"main": "index.ts",
|
|
370
|
+
"types": "index.ts",
|
|
371
|
+
"exports": {
|
|
372
|
+
".": {
|
|
373
|
+
"import": "./index.ts",
|
|
374
|
+
"types": "./index.ts"
|
|
375
|
+
},
|
|
376
|
+
"./config": {
|
|
377
|
+
"import": "./config/index.ts",
|
|
378
|
+
"types": "./config/index.ts"
|
|
379
|
+
},
|
|
380
|
+
"./client": {
|
|
381
|
+
"import": "./client/index.ts",
|
|
382
|
+
"types": "./client/index.ts"
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"keywords": [
|
|
386
|
+
"fluxstack",
|
|
387
|
+
"plugin",
|
|
388
|
+
"{{name}}",
|
|
389
|
+
"react",
|
|
390
|
+
"client",
|
|
391
|
+
"typescript"
|
|
392
|
+
],
|
|
393
|
+
"author": "FluxStack Developer",
|
|
394
|
+
"license": "MIT",
|
|
395
|
+
"peerDependencies": {
|
|
396
|
+
"react": ">=16.8.0"
|
|
397
|
+
},
|
|
398
|
+
"peerDependenciesMeta": {
|
|
399
|
+
"react": {
|
|
400
|
+
"optional": true
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
"dependencies": {},
|
|
404
|
+
"devDependencies": {
|
|
405
|
+
"@types/react": "^18.0.0",
|
|
406
|
+
"typescript": "^5.0.0"
|
|
407
|
+
},
|
|
408
|
+
"fluxstack": {
|
|
409
|
+
"plugin": true,
|
|
410
|
+
"version": "^1.0.0",
|
|
411
|
+
"hooks": [
|
|
412
|
+
"setup",
|
|
413
|
+
"onServerStart"
|
|
414
|
+
],
|
|
415
|
+
"category": "utility",
|
|
416
|
+
"tags": ["{{name}}", "client", "react"]
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
`
|
|
420
|
+
},
|
|
421
|
+
...basic.files.slice(1), // Skip package.json from basic
|
|
237
422
|
{
|
|
238
423
|
path: 'plugins/{{name}}/client/index.ts',
|
|
239
424
|
content: `/**
|
|
@@ -265,22 +450,127 @@ export const {{camelName}}Client = new {{pascalName}}Client()
|
|
|
265
450
|
name: 'full-plugin',
|
|
266
451
|
description: 'Complete plugin with server and client code',
|
|
267
452
|
files: [
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
453
|
+
{
|
|
454
|
+
path: 'plugins/{{name}}/package.json',
|
|
455
|
+
content: `{
|
|
456
|
+
"name": "@fluxstack/{{name}}-plugin",
|
|
457
|
+
"version": "1.0.0",
|
|
458
|
+
"description": "{{description}}",
|
|
459
|
+
"main": "index.ts",
|
|
460
|
+
"types": "index.ts",
|
|
461
|
+
"exports": {
|
|
462
|
+
".": {
|
|
463
|
+
"import": "./index.ts",
|
|
464
|
+
"types": "./index.ts"
|
|
465
|
+
},
|
|
466
|
+
"./config": {
|
|
467
|
+
"import": "./config/index.ts",
|
|
468
|
+
"types": "./config/index.ts"
|
|
469
|
+
},
|
|
470
|
+
"./server": {
|
|
471
|
+
"import": "./server/index.ts",
|
|
472
|
+
"types": "./server/index.ts"
|
|
473
|
+
},
|
|
474
|
+
"./client": {
|
|
475
|
+
"import": "./client/index.ts",
|
|
476
|
+
"types": "./client/index.ts"
|
|
477
|
+
},
|
|
478
|
+
"./types": {
|
|
479
|
+
"import": "./types.ts",
|
|
480
|
+
"types": "./types.ts"
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
"keywords": [
|
|
484
|
+
"fluxstack",
|
|
485
|
+
"plugin",
|
|
486
|
+
"{{name}}",
|
|
487
|
+
"react",
|
|
488
|
+
"server",
|
|
489
|
+
"client",
|
|
490
|
+
"typescript"
|
|
491
|
+
],
|
|
492
|
+
"author": "FluxStack Developer",
|
|
493
|
+
"license": "MIT",
|
|
494
|
+
"peerDependencies": {
|
|
495
|
+
"react": ">=16.8.0",
|
|
496
|
+
"elysia": "^1.0.0"
|
|
497
|
+
},
|
|
498
|
+
"peerDependenciesMeta": {
|
|
499
|
+
"react": {
|
|
500
|
+
"optional": true
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
"dependencies": {},
|
|
504
|
+
"devDependencies": {
|
|
505
|
+
"@types/react": "^18.0.0",
|
|
506
|
+
"typescript": "^5.0.0"
|
|
507
|
+
},
|
|
508
|
+
"fluxstack": {
|
|
509
|
+
"plugin": true,
|
|
510
|
+
"version": "^1.0.0",
|
|
511
|
+
"hooks": [
|
|
512
|
+
"setup",
|
|
513
|
+
"onServerStart",
|
|
514
|
+
"onRequest",
|
|
515
|
+
"onResponse",
|
|
516
|
+
"onError"
|
|
517
|
+
],
|
|
518
|
+
"category": "utility",
|
|
519
|
+
"tags": ["{{name}}", "server", "client", "react"]
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
`
|
|
523
|
+
},
|
|
524
|
+
...basic.files.slice(1), // Skip package.json from basic
|
|
525
|
+
{
|
|
526
|
+
path: 'plugins/{{name}}/server/index.ts',
|
|
527
|
+
content: `/**
|
|
528
|
+
* Server-side logic for {{pascalName}} plugin
|
|
529
|
+
*/
|
|
530
|
+
|
|
531
|
+
export class {{pascalName}}Service {
|
|
532
|
+
async initialize() {
|
|
533
|
+
console.log(\`[{{name}}] Server service initialized\`)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Add your server-side methods here
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export const {{camelName}}Service = new {{pascalName}}Service()
|
|
540
|
+
`
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
path: 'plugins/{{name}}/client/index.ts',
|
|
544
|
+
content: `/**
|
|
545
|
+
* Client-side logic for {{pascalName}} plugin
|
|
546
|
+
*/
|
|
547
|
+
|
|
548
|
+
export class {{pascalName}}Client {
|
|
549
|
+
initialize() {
|
|
550
|
+
console.log(\`[{{name}}] Client initialized\`)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Add your client-side methods here
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export const {{camelName}}Client = new {{pascalName}}Client()
|
|
557
|
+
`
|
|
558
|
+
},
|
|
271
559
|
{
|
|
272
560
|
path: 'plugins/{{name}}/types.ts',
|
|
273
561
|
content: `/**
|
|
274
562
|
* Type definitions for {{pascalName}} plugin
|
|
275
563
|
*/
|
|
276
564
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
enabled: boolean
|
|
280
|
-
}
|
|
565
|
+
// Config types are exported from ./config/index.ts
|
|
566
|
+
// Import them like: import type { {{pascalName}}Config } from './config'
|
|
281
567
|
|
|
282
568
|
export interface {{pascalName}}Options {
|
|
283
|
-
// Add your options types here
|
|
569
|
+
// Add your runtime options types here
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export interface {{pascalName}}Event {
|
|
573
|
+
// Add your event types here
|
|
284
574
|
}
|
|
285
575
|
`
|
|
286
576
|
}
|
|
@@ -85,6 +85,7 @@ export class TemplateEngine {
|
|
|
85
85
|
camelName: this.toCamelCase(options.name),
|
|
86
86
|
pascalName: this.toPascalCase(options.name),
|
|
87
87
|
snakeName: this.toSnakeCase(options.name),
|
|
88
|
+
constantName: this.toConstantCase(options.name), // SCREAMING_SNAKE_CASE
|
|
88
89
|
timestamp: new Date().toISOString(),
|
|
89
90
|
date: new Date().toLocaleDateString(),
|
|
90
91
|
year: new Date().getFullYear(),
|
|
@@ -149,6 +150,10 @@ export class TemplateEngine {
|
|
|
149
150
|
.replace(/[\s-]+/g, '_')
|
|
150
151
|
.toLowerCase()
|
|
151
152
|
}
|
|
153
|
+
|
|
154
|
+
private toConstantCase(str: string): string {
|
|
155
|
+
return this.toSnakeCase(str).toUpperCase()
|
|
156
|
+
}
|
|
152
157
|
}
|
|
153
158
|
|
|
154
159
|
export const templateEngine = new TemplateEngine()
|
|
@@ -10,14 +10,14 @@ export class CliPluginDiscovery {
|
|
|
10
10
|
async discoverAndRegisterCommands(): Promise<void> {
|
|
11
11
|
// 1. Load built-in plugins with CLI commands
|
|
12
12
|
await this.loadBuiltInPlugins()
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
// 2. Load local plugins from project
|
|
15
15
|
await this.loadLocalPlugins()
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
private async loadBuiltInPlugins(): Promise<void> {
|
|
19
19
|
const builtInPluginsDir = join(__dirname, '../plugins/built-in')
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
if (!existsSync(builtInPluginsDir)) {
|
|
22
22
|
return
|
|
23
23
|
}
|
|
@@ -33,7 +33,7 @@ export class CliPluginDiscovery {
|
|
|
33
33
|
const pluginPath = join(builtInPluginsDir, pluginName, 'index.ts')
|
|
34
34
|
if (existsSync(pluginPath)) {
|
|
35
35
|
const pluginModule = await import(pluginPath)
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
if (pluginModule.commands) {
|
|
38
38
|
for (const command of pluginModule.commands) {
|
|
39
39
|
cliRegistry.register(command)
|
|
@@ -57,7 +57,7 @@ export class CliPluginDiscovery {
|
|
|
57
57
|
|
|
58
58
|
private async loadLocalPlugins(): Promise<void> {
|
|
59
59
|
const localPluginsDir = join(process.cwd(), 'plugins')
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
if (!existsSync(localPluginsDir)) {
|
|
62
62
|
return
|
|
63
63
|
}
|
|
@@ -65,17 +65,18 @@ export class CliPluginDiscovery {
|
|
|
65
65
|
try {
|
|
66
66
|
const fs = await import('fs')
|
|
67
67
|
const entries = fs.readdirSync(localPluginsDir, { withFileTypes: true })
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
for (const entry of entries) {
|
|
70
|
+
// Buscar arquivos .ts/.js diretamente
|
|
70
71
|
if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.js'))) {
|
|
71
72
|
const pluginPath = join(localPluginsDir, entry.name)
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
try {
|
|
74
75
|
const pluginModule = await import(pluginPath)
|
|
75
76
|
const plugin = pluginModule.default || Object.values(pluginModule).find(
|
|
76
77
|
(exp: any) => exp && typeof exp === 'object' && exp.name && exp.commands
|
|
77
78
|
) as Plugin
|
|
78
|
-
|
|
79
|
+
|
|
79
80
|
if (plugin && plugin.commands) {
|
|
80
81
|
this.registerPluginCommands(plugin)
|
|
81
82
|
}
|
|
@@ -83,6 +84,26 @@ export class CliPluginDiscovery {
|
|
|
83
84
|
logger.debug(`Failed to load local plugin ${entry.name}:`, error)
|
|
84
85
|
}
|
|
85
86
|
}
|
|
87
|
+
|
|
88
|
+
// ✅ Buscar em subdiretórios (plugins/nome-plugin/index.ts)
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
const pluginIndexPath = join(localPluginsDir, entry.name, 'index.ts')
|
|
91
|
+
|
|
92
|
+
if (existsSync(pluginIndexPath)) {
|
|
93
|
+
try {
|
|
94
|
+
const pluginModule = await import(pluginIndexPath)
|
|
95
|
+
const plugin = pluginModule.default || Object.values(pluginModule).find(
|
|
96
|
+
(exp: any) => exp && typeof exp === 'object' && exp.name && exp.commands
|
|
97
|
+
) as Plugin
|
|
98
|
+
|
|
99
|
+
if (plugin && plugin.commands) {
|
|
100
|
+
this.registerPluginCommands(plugin)
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
logger.debug(`Failed to load local plugin ${entry.name}:`, error)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
86
107
|
}
|
|
87
108
|
} catch (error) {
|
|
88
109
|
logger.debug('Failed to scan local plugins:', error)
|
|
@@ -103,9 +124,9 @@ export class CliPluginDiscovery {
|
|
|
103
124
|
category: command.category || `Plugin: ${plugin.name}`,
|
|
104
125
|
aliases: command.aliases?.map(alias => `${plugin.name}:${alias}`)
|
|
105
126
|
}
|
|
106
|
-
|
|
127
|
+
|
|
107
128
|
cliRegistry.register(prefixedCommand)
|
|
108
|
-
|
|
129
|
+
|
|
109
130
|
// Also register without prefix if no conflict exists
|
|
110
131
|
if (!cliRegistry.has(command.name)) {
|
|
111
132
|
cliRegistry.register({
|
|
@@ -114,10 +135,10 @@ export class CliPluginDiscovery {
|
|
|
114
135
|
})
|
|
115
136
|
}
|
|
116
137
|
}
|
|
117
|
-
|
|
138
|
+
|
|
118
139
|
this.loadedPlugins.add(plugin.name)
|
|
119
140
|
logger.debug(`Registered ${plugin.commands.length} CLI commands from plugin: ${plugin.name}`)
|
|
120
|
-
|
|
141
|
+
|
|
121
142
|
} catch (error) {
|
|
122
143
|
logger.error(`Failed to register CLI commands for plugin ${plugin.name}:`, error)
|
|
123
144
|
}
|
|
@@ -128,4 +149,4 @@ export class CliPluginDiscovery {
|
|
|
128
149
|
}
|
|
129
150
|
}
|
|
130
151
|
|
|
131
|
-
export const pluginDiscovery = new CliPluginDiscovery()
|
|
152
|
+
export const pluginDiscovery = new CliPluginDiscovery()
|
package/core/framework/server.ts
CHANGED
|
@@ -469,6 +469,16 @@ export class FluxStackFramework {
|
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
// Mount plugin routes if they have a plugin property
|
|
473
|
+
for (const pluginName of loadOrder) {
|
|
474
|
+
const plugin = this.pluginRegistry.get(pluginName)!
|
|
475
|
+
|
|
476
|
+
if ((plugin as any).plugin) {
|
|
477
|
+
this.app.use((plugin as any).plugin)
|
|
478
|
+
logger.debug(`Plugin '${pluginName}' routes mounted`)
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
472
482
|
// Call onServerStart hooks
|
|
473
483
|
for (const pluginName of loadOrder) {
|
|
474
484
|
const plugin = this.pluginRegistry.get(pluginName)!
|