create-fluxstack 1.5.1 → 1.5.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.
Files changed (51) hide show
  1. package/.env.example +8 -1
  2. package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +475 -0
  3. package/CRYPTO-AUTH-MIDDLEWARES.md +473 -0
  4. package/CRYPTO-AUTH-USAGE.md +491 -0
  5. package/EXEMPLO-ROTA-PROTEGIDA.md +347 -0
  6. package/QUICK-START-CRYPTO-AUTH.md +221 -0
  7. package/app/client/src/App.tsx +4 -1
  8. package/app/client/src/pages/CryptoAuthPage.tsx +394 -0
  9. package/app/server/index.ts +4 -0
  10. package/app/server/live/FluxStackConfig.ts +1 -1
  11. package/app/server/routes/crypto-auth-demo.routes.ts +167 -0
  12. package/app/server/routes/example-with-crypto-auth.routes.ts +235 -0
  13. package/app/server/routes/exemplo-posts.routes.ts +161 -0
  14. package/app/server/routes/index.ts +5 -1
  15. package/config/index.ts +9 -1
  16. package/core/cli/generators/plugin.ts +324 -34
  17. package/core/cli/generators/template-engine.ts +5 -0
  18. package/core/cli/plugin-discovery.ts +33 -12
  19. package/core/framework/server.ts +10 -0
  20. package/core/plugins/dependency-manager.ts +89 -22
  21. package/core/plugins/index.ts +4 -0
  22. package/core/plugins/manager.ts +3 -2
  23. package/core/plugins/module-resolver.ts +216 -0
  24. package/core/plugins/registry.ts +28 -1
  25. package/core/utils/logger/index.ts +4 -0
  26. package/core/utils/version.ts +1 -1
  27. package/fluxstack.config.ts +253 -114
  28. package/package.json +3 -3
  29. package/plugins/crypto-auth/README.md +788 -0
  30. package/plugins/crypto-auth/ai-context.md +1282 -0
  31. package/plugins/crypto-auth/cli/make-protected-route.command.ts +383 -0
  32. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -0
  33. package/plugins/crypto-auth/client/components/AuthProvider.tsx +131 -0
  34. package/plugins/crypto-auth/client/components/LoginButton.tsx +138 -0
  35. package/plugins/crypto-auth/client/components/ProtectedRoute.tsx +89 -0
  36. package/plugins/crypto-auth/client/components/index.ts +12 -0
  37. package/plugins/crypto-auth/client/index.ts +12 -0
  38. package/plugins/crypto-auth/config/index.ts +34 -0
  39. package/plugins/crypto-auth/index.ts +162 -0
  40. package/plugins/crypto-auth/package.json +66 -0
  41. package/plugins/crypto-auth/server/AuthMiddleware.ts +181 -0
  42. package/plugins/crypto-auth/server/CryptoAuthService.ts +186 -0
  43. package/plugins/crypto-auth/server/index.ts +22 -0
  44. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +65 -0
  45. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +26 -0
  46. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +76 -0
  47. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +45 -0
  48. package/plugins/crypto-auth/server/middlewares/helpers.ts +140 -0
  49. package/plugins/crypto-auth/server/middlewares/index.ts +22 -0
  50. package/plugins/crypto-auth/server/middlewares.ts +19 -0
  51. package/test-crypto-auth.ts +101 -0
@@ -0,0 +1,473 @@
1
+ # 🔐 Crypto Auth - Middlewares Elysia
2
+
3
+ ## 🚀 Guia Rápido
4
+
5
+ ### Uso Básico
6
+
7
+ ```typescript
8
+ import { Elysia } from 'elysia'
9
+ import { cryptoAuthRequired, cryptoAuthAdmin } from '@/plugins/crypto-auth/server'
10
+
11
+ export const myRoutes = new Elysia()
12
+ // ✅ Aplica autenticação a todas as rotas
13
+ .use(cryptoAuthRequired())
14
+
15
+ .get('/users', ({ request }) => {
16
+ const user = (request as any).user
17
+ return { users: [], requestedBy: user.publicKey }
18
+ })
19
+
20
+ .post('/users', ({ request, body }) => {
21
+ const user = (request as any).user
22
+ return { created: body, by: user.publicKey }
23
+ })
24
+ ```
25
+
26
+ ---
27
+
28
+ ## 📚 Middlewares Disponíveis
29
+
30
+ ### 1️⃣ `cryptoAuthRequired()` - Requer Autenticação
31
+
32
+ Valida assinatura e bloqueia acesso se não autenticado.
33
+
34
+ ```typescript
35
+ import { cryptoAuthRequired, getCryptoAuthUser } from '@/plugins/crypto-auth/server'
36
+
37
+ export const protectedRoutes = new Elysia()
38
+ .use(cryptoAuthRequired()) // ✅ Todas as rotas protegidas
39
+
40
+ .get('/profile', ({ request }) => {
41
+ const user = getCryptoAuthUser(request)!
42
+ return {
43
+ publicKey: user.publicKey,
44
+ isAdmin: user.isAdmin,
45
+ permissions: user.permissions
46
+ }
47
+ })
48
+ ```
49
+
50
+ **Retorno se não autenticado**:
51
+ ```json
52
+ {
53
+ "error": {
54
+ "message": "Authentication required",
55
+ "code": "CRYPTO_AUTH_REQUIRED",
56
+ "statusCode": 401
57
+ }
58
+ }
59
+ ```
60
+
61
+ ---
62
+
63
+ ### 2️⃣ `cryptoAuthAdmin()` - Requer Admin
64
+
65
+ Valida autenticação E verifica se usuário é admin.
66
+
67
+ ```typescript
68
+ import { cryptoAuthAdmin } from '@/plugins/crypto-auth/server'
69
+
70
+ export const adminRoutes = new Elysia()
71
+ .use(cryptoAuthAdmin()) // ✅ Apenas admins
72
+
73
+ .get('/admin/stats', () => ({
74
+ totalUsers: 100,
75
+ systemHealth: 'optimal'
76
+ }))
77
+
78
+ .delete('/admin/users/:id', ({ params, request }) => {
79
+ const user = (request as any).user
80
+ return {
81
+ deleted: params.id,
82
+ by: user.publicKey
83
+ }
84
+ })
85
+ ```
86
+
87
+ **Retorno se não for admin**:
88
+ ```json
89
+ {
90
+ "error": {
91
+ "message": "Admin privileges required",
92
+ "code": "ADMIN_REQUIRED",
93
+ "statusCode": 403,
94
+ "yourPermissions": ["read"]
95
+ }
96
+ }
97
+ ```
98
+
99
+ ---
100
+
101
+ ### 3️⃣ `cryptoAuthPermissions(permissions)` - Requer Permissões
102
+
103
+ Valida autenticação E verifica permissões específicas.
104
+
105
+ ```typescript
106
+ import { cryptoAuthPermissions } from '@/plugins/crypto-auth/server'
107
+
108
+ export const writeRoutes = new Elysia()
109
+ .use(cryptoAuthPermissions(['write'])) // ✅ Requer permissão 'write'
110
+
111
+ .put('/posts/:id', ({ params, body }) => ({
112
+ updated: params.id,
113
+ data: body
114
+ }))
115
+
116
+ .patch('/posts/:id/publish', ({ params }) => ({
117
+ published: params.id
118
+ }))
119
+ ```
120
+
121
+ **Múltiplas permissões**:
122
+ ```typescript
123
+ .use(cryptoAuthPermissions(['write', 'publish']))
124
+ ```
125
+
126
+ **Retorno se sem permissão**:
127
+ ```json
128
+ {
129
+ "error": {
130
+ "message": "Insufficient permissions",
131
+ "code": "PERMISSION_DENIED",
132
+ "statusCode": 403,
133
+ "required": ["write"],
134
+ "yours": ["read"]
135
+ }
136
+ }
137
+ ```
138
+
139
+ ---
140
+
141
+ ### 4️⃣ `cryptoAuthOptional()` - Autenticação Opcional
142
+
143
+ Adiciona `user` se autenticado, mas NÃO bloqueia se não autenticado.
144
+
145
+ ```typescript
146
+ import { cryptoAuthOptional, getCryptoAuthUser } from '@/plugins/crypto-auth/server'
147
+
148
+ export const mixedRoutes = new Elysia()
149
+ .use(cryptoAuthOptional()) // ✅ Opcional
150
+
151
+ // Comportamento diferente se autenticado
152
+ .get('/posts/:id', ({ request, params }) => {
153
+ const user = getCryptoAuthUser(request)
154
+
155
+ return {
156
+ post: {
157
+ id: params.id,
158
+ title: 'Post Title',
159
+ // Conteúdo completo apenas se autenticado
160
+ content: user ? 'Full content...' : 'Preview...'
161
+ },
162
+ viewer: user ? {
163
+ publicKey: user.publicKey,
164
+ canEdit: user.isAdmin
165
+ } : null
166
+ }
167
+ })
168
+ ```
169
+
170
+ ---
171
+
172
+ ## 🛠️ Helper Functions
173
+
174
+ ### `getCryptoAuthUser(request)` - Obter Usuário
175
+
176
+ ```typescript
177
+ import { getCryptoAuthUser } from '@/plugins/crypto-auth/server'
178
+
179
+ .get('/me', ({ request }) => {
180
+ const user = getCryptoAuthUser(request)
181
+
182
+ if (!user) {
183
+ return { error: 'Not authenticated' }
184
+ }
185
+
186
+ return { user }
187
+ })
188
+ ```
189
+
190
+ ---
191
+
192
+ ### `isCryptoAuthAuthenticated(request)` - Verificar se Autenticado
193
+
194
+ ```typescript
195
+ import { isCryptoAuthAuthenticated } from '@/plugins/crypto-auth/server'
196
+
197
+ .get('/posts/:id', ({ request, params }) => {
198
+ const isAuth = isCryptoAuthAuthenticated(request)
199
+
200
+ return {
201
+ post: { id: params.id },
202
+ canComment: isAuth
203
+ }
204
+ })
205
+ ```
206
+
207
+ ---
208
+
209
+ ### `isCryptoAuthAdmin(request)` - Verificar se é Admin
210
+
211
+ ```typescript
212
+ import { isCryptoAuthAdmin } from '@/plugins/crypto-auth/server'
213
+
214
+ .get('/posts/:id', ({ request, params, set }) => {
215
+ if (!isCryptoAuthAdmin(request)) {
216
+ set.status = 403
217
+ return { error: 'Admin only' }
218
+ }
219
+
220
+ return { post: params.id }
221
+ })
222
+ ```
223
+
224
+ ---
225
+
226
+ ### `hasCryptoAuthPermission(request, permission)` - Verificar Permissão
227
+
228
+ ```typescript
229
+ import { hasCryptoAuthPermission } from '@/plugins/crypto-auth/server'
230
+
231
+ .put('/posts/:id', ({ request, params, set }) => {
232
+ if (!hasCryptoAuthPermission(request, 'write')) {
233
+ set.status = 403
234
+ return { error: 'Write permission required' }
235
+ }
236
+
237
+ return { updated: params.id }
238
+ })
239
+ ```
240
+
241
+ ---
242
+
243
+ ## 🎯 Padrões de Uso
244
+
245
+ ### Padrão 1: Grupo de Rotas Protegidas
246
+
247
+ ```typescript
248
+ export const apiRoutes = new Elysia()
249
+ // Rotas públicas
250
+ .get('/health', () => ({ status: 'ok' }))
251
+ .get('/posts', () => ({ posts: [] }))
252
+
253
+ // Grupo protegido
254
+ .group('/users', (app) => app
255
+ .use(cryptoAuthRequired())
256
+ .get('/', () => ({ users: [] }))
257
+ .post('/', ({ body }) => ({ created: body }))
258
+ .delete('/:id', ({ params }) => ({ deleted: params.id }))
259
+ )
260
+
261
+ // Grupo admin
262
+ .group('/admin', (app) => app
263
+ .use(cryptoAuthAdmin())
264
+ .get('/stats', () => ({ stats: {} }))
265
+ )
266
+ ```
267
+
268
+ ---
269
+
270
+ ### Padrão 2: Middleware Cascata
271
+
272
+ ```typescript
273
+ export const routes = new Elysia()
274
+ // Aplica a todas as rotas
275
+ .use(cryptoAuthRequired())
276
+
277
+ .get('/profile', () => ({ profile: {} }))
278
+
279
+ // Sub-grupo com restrição adicional
280
+ .group('/admin', (app) => app
281
+ .use(cryptoAuthAdmin()) // Admin adicional ao required
282
+ .get('/users', () => ({ users: [] }))
283
+ )
284
+ ```
285
+
286
+ ---
287
+
288
+ ### Padrão 3: Verificação Manual Combinada
289
+
290
+ ```typescript
291
+ export const routes = new Elysia()
292
+ .use(cryptoAuthRequired())
293
+
294
+ .delete('/posts/:id', ({ request, params, set }) => {
295
+ const user = getCryptoAuthUser(request)!
296
+
297
+ // Buscar post do DB
298
+ const post = { id: params.id, authorKey: 'abc...' }
299
+
300
+ // Apenas autor ou admin pode deletar
301
+ const canDelete = user.isAdmin ||
302
+ user.publicKey === post.authorKey
303
+
304
+ if (!canDelete) {
305
+ set.status = 403
306
+ return {
307
+ error: 'Apenas o autor ou admin podem deletar'
308
+ }
309
+ }
310
+
311
+ return { deleted: params.id }
312
+ })
313
+ ```
314
+
315
+ ---
316
+
317
+ ### Padrão 4: Rotas Condicionais
318
+
319
+ ```typescript
320
+ export const routes = new Elysia()
321
+ .use(cryptoAuthOptional())
322
+
323
+ .get('/posts/:id/download', ({ request, params, set }) => {
324
+ const user = getCryptoAuthUser(request)
325
+
326
+ // Usuários autenticados: download ilimitado
327
+ // Não autenticados: limite de 3 por dia
328
+ if (!user) {
329
+ const dailyLimit = checkRateLimit(request.headers.get('x-forwarded-for'))
330
+ if (dailyLimit > 3) {
331
+ set.status = 429
332
+ return { error: 'Rate limit exceeded. Authenticate for unlimited access.' }
333
+ }
334
+ }
335
+
336
+ return { download: `post-${params.id}.pdf` }
337
+ })
338
+ ```
339
+
340
+ ---
341
+
342
+ ## 🔍 Debugging
343
+
344
+ ### Log de Autenticação
345
+
346
+ ```typescript
347
+ import { cryptoAuthRequired } from '@/plugins/crypto-auth/server'
348
+
349
+ export const routes = new Elysia()
350
+ .use(cryptoAuthRequired({
351
+ logger: yourLogger // ✅ Passar logger para debug
352
+ }))
353
+
354
+ .get('/users', ({ request }) => {
355
+ const user = (request as any).user
356
+ console.log('User:', user)
357
+ return { users: [] }
358
+ })
359
+ ```
360
+
361
+ ---
362
+
363
+ ### Rota de Debug
364
+
365
+ ```typescript
366
+ export const debugRoutes = new Elysia()
367
+ .use(cryptoAuthOptional())
368
+
369
+ .get('/debug/auth', ({ request }) => {
370
+ const user = getCryptoAuthUser(request)
371
+
372
+ return {
373
+ authenticated: !!user,
374
+ user: user || null,
375
+ headers: {
376
+ publicKey: request.headers.get('x-public-key'),
377
+ timestamp: request.headers.get('x-timestamp'),
378
+ nonce: request.headers.get('x-nonce'),
379
+ signature: request.headers.get('x-signature')?.substring(0, 16) + '...'
380
+ }
381
+ }
382
+ })
383
+ ```
384
+
385
+ ---
386
+
387
+ ## ⚠️ Importante
388
+
389
+ 1. **Ordem importa**: Aplique middlewares antes de definir rotas
390
+ ```typescript
391
+ .use(cryptoAuthRequired()) // ✅ Primeiro
392
+ .get('/users', ...) // ✅ Depois
393
+ ```
394
+
395
+ 2. **Grupos herdam middlewares**:
396
+ ```typescript
397
+ .use(cryptoAuthRequired())
398
+ .group('/api', ...) // ✅ Herda cryptoAuthRequired
399
+ ```
400
+
401
+ 3. **User object sempre disponível**: Em rotas com `cryptoAuthRequired`, `cryptoAuthAdmin` ou `cryptoAuthPermissions`
402
+
403
+ 4. **Null check necessário**: Em rotas com `cryptoAuthOptional`:
404
+ ```typescript
405
+ const user = getCryptoAuthUser(request)
406
+ if (user) { // ✅ Verificar antes de usar
407
+ ...
408
+ }
409
+ ```
410
+
411
+ ---
412
+
413
+ ## 📦 TypeScript Types
414
+
415
+ ```typescript
416
+ interface CryptoAuthUser {
417
+ publicKey: string // Chave pública (ID único)
418
+ isAdmin: boolean // Se é administrador
419
+ permissions: string[] // ["read"] ou ["admin", "read", "write", "delete"]
420
+ }
421
+ ```
422
+
423
+ ---
424
+
425
+ ## 🆚 Comparação com Config
426
+
427
+ ### ❌ Antes (Config Global)
428
+ ```typescript
429
+ // config/app.config.ts
430
+ plugins: {
431
+ config: {
432
+ 'crypto-auth': {
433
+ protectedRoutes: ["/api/users/*"]
434
+ }
435
+ }
436
+ }
437
+
438
+ // routes/users.routes.ts
439
+ .get('/users', ({ request }) => {
440
+ // Protegido automaticamente
441
+ })
442
+ ```
443
+
444
+ ### ✅ Agora (Middlewares)
445
+ ```typescript
446
+ // routes/users.routes.ts
447
+ import { cryptoAuthRequired } from '@/plugins/crypto-auth/server'
448
+
449
+ export const routes = new Elysia()
450
+ .use(cryptoAuthRequired()) // ✅ Explícito
451
+ .get('/users', ({ request }) => {
452
+ // Protegido
453
+ })
454
+ ```
455
+
456
+ **Vantagens**:
457
+ - ✅ Explícito e visível
458
+ - ✅ Type-safe
459
+ - ✅ Mais flexível
460
+ - ✅ Melhor autocomplete
461
+ - ✅ Não depende de config global
462
+
463
+ ---
464
+
465
+ ## 📚 Ver Mais
466
+
467
+ - **Exemplo completo**: `app/server/routes/example-with-crypto-auth.routes.ts`
468
+ - **Documentação AI**: `plugins/crypto-auth/ai-context.md`
469
+ - **Demo rotas**: `app/server/routes/crypto-auth-demo.routes.ts`
470
+
471
+ ---
472
+
473
+ **Última atualização**: Janeiro 2025