create-fluxstack 1.0.13 โ 1.0.15
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 +29 -29
- package/app/client/README.md +69 -69
- package/app/client/index.html +14 -13
- package/app/client/src/App.tsx +157 -524
- package/app/client/src/components/ErrorBoundary.tsx +107 -0
- package/app/client/src/components/ErrorDisplay.css +365 -0
- package/app/client/src/components/ErrorDisplay.tsx +258 -0
- package/app/client/src/components/FluxStackConfig.tsx +1321 -0
- package/app/client/src/components/HybridLiveCounter.tsx +140 -0
- package/app/client/src/components/LiveClock.tsx +286 -0
- package/app/client/src/components/MainLayout.tsx +390 -0
- package/app/client/src/components/SidebarNavigation.tsx +391 -0
- package/app/client/src/components/StateDemo.tsx +178 -0
- package/app/client/src/components/SystemMonitor.tsx +1038 -0
- package/app/client/src/components/Teste.tsx +104 -0
- package/app/client/src/components/UserProfile.tsx +809 -0
- package/app/client/src/hooks/useAuth.ts +39 -0
- package/app/client/src/hooks/useNotifications.ts +56 -0
- package/app/client/src/lib/eden-api.ts +189 -53
- package/app/client/src/lib/errors.ts +340 -0
- package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
- package/app/client/src/lib/index.ts +45 -0
- package/app/client/src/main.tsx +3 -2
- package/app/client/src/pages/ApiDocs.tsx +182 -0
- package/app/client/src/pages/Demo.tsx +174 -0
- package/app/client/src/pages/HybridLive.tsx +263 -0
- package/app/client/src/pages/Overview.tsx +155 -0
- package/app/client/src/store/README.md +43 -0
- package/app/client/src/store/index.ts +16 -0
- package/app/client/src/store/slices/uiSlice.ts +151 -0
- package/app/client/src/store/slices/userSlice.ts +161 -0
- package/app/client/src/test/README.md +257 -0
- package/app/client/src/test/setup.ts +70 -0
- package/app/client/src/test/types.ts +12 -0
- package/app/client/src/vite-env.d.ts +1 -1
- package/app/client/tsconfig.app.json +44 -43
- package/app/client/tsconfig.json +7 -7
- package/app/client/tsconfig.node.json +25 -25
- package/app/client/zustand-setup.md +65 -0
- package/app/server/controllers/users.controller.ts +68 -68
- package/app/server/index.ts +9 -1
- package/app/server/live/CounterComponent.ts +191 -0
- package/app/server/live/FluxStackConfig.ts +529 -0
- package/app/server/live/LiveClockComponent.ts +214 -0
- package/app/server/live/SidebarNavigation.ts +156 -0
- package/app/server/live/SystemMonitor.ts +594 -0
- package/app/server/live/SystemMonitorIntegration.ts +151 -0
- package/app/server/live/TesteComponent.ts +87 -0
- package/app/server/live/UserProfileComponent.ts +135 -0
- package/app/server/live/register-components.ts +28 -0
- package/app/server/middleware/auth.ts +136 -0
- package/app/server/middleware/errorHandling.ts +250 -0
- package/app/server/middleware/index.ts +10 -0
- package/app/server/middleware/rateLimit.ts +193 -0
- package/app/server/middleware/requestLogging.ts +215 -0
- package/app/server/middleware/validation.ts +270 -0
- package/app/server/routes/index.ts +14 -2
- package/app/server/routes/upload.ts +92 -0
- package/app/server/routes/users.routes.ts +2 -9
- package/app/server/services/NotificationService.ts +302 -0
- package/app/server/services/UserService.ts +222 -0
- package/app/server/services/index.ts +46 -0
- package/core/cli/commands/plugin-deps.ts +263 -0
- package/core/cli/generators/README.md +339 -0
- package/core/cli/generators/component.ts +770 -0
- package/core/cli/generators/controller.ts +299 -0
- package/core/cli/generators/index.ts +144 -0
- package/core/cli/generators/interactive.ts +228 -0
- package/core/cli/generators/prompts.ts +83 -0
- package/core/cli/generators/route.ts +513 -0
- package/core/cli/generators/service.ts +465 -0
- package/core/cli/generators/template-engine.ts +154 -0
- package/core/cli/generators/types.ts +71 -0
- package/core/cli/generators/utils.ts +192 -0
- package/core/cli/index.ts +69 -0
- package/core/cli/plugin-discovery.ts +16 -85
- package/core/client/fluxstack.ts +17 -0
- package/core/client/hooks/index.ts +7 -0
- package/core/client/hooks/state-validator.ts +130 -0
- package/core/client/hooks/useAuth.ts +49 -0
- package/core/client/hooks/useChunkedUpload.ts +258 -0
- package/core/client/hooks/useHybridLiveComponent.ts +967 -0
- package/core/client/hooks/useWebSocket.ts +373 -0
- package/core/client/index.ts +47 -0
- package/core/client/state/createStore.ts +193 -0
- package/core/client/state/index.ts +15 -0
- package/core/config/env-dynamic.ts +1 -1
- package/core/config/env.ts +2 -1
- package/core/config/runtime-config.ts +3 -3
- package/core/config/schema.ts +84 -49
- package/core/framework/server.ts +30 -0
- package/core/index.ts +25 -0
- package/core/live/ComponentRegistry.ts +399 -0
- package/core/live/types.ts +164 -0
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
- package/core/plugins/built-in/live-components/index.ts +27 -0
- package/core/plugins/built-in/logger/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +1 -1
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +1 -1
- package/core/plugins/built-in/vite/index.ts +1 -1
- package/core/plugins/dependency-manager.ts +384 -0
- package/core/plugins/index.ts +5 -1
- package/core/plugins/manager.ts +7 -3
- package/core/plugins/registry.ts +88 -10
- package/core/plugins/types.ts +11 -11
- package/core/server/framework.ts +43 -0
- package/core/server/index.ts +11 -1
- package/core/server/live/ComponentRegistry.ts +1017 -0
- package/core/server/live/FileUploadManager.ts +272 -0
- package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
- package/core/server/live/SingleConnectionManager.ts +0 -0
- package/core/server/live/StateSignature.ts +644 -0
- package/core/server/live/WebSocketConnectionManager.ts +688 -0
- package/core/server/live/websocket-plugin.ts +435 -0
- package/core/server/middleware/errorHandling.ts +141 -0
- package/core/server/middleware/index.ts +16 -0
- package/core/server/plugins/static-files-plugin.ts +232 -0
- package/core/server/services/BaseService.ts +95 -0
- package/core/server/services/ServiceContainer.ts +144 -0
- package/core/server/services/index.ts +9 -0
- package/core/templates/create-project.ts +196 -33
- package/core/testing/index.ts +10 -0
- package/core/testing/setup.ts +74 -0
- package/core/types/build.ts +38 -14
- package/core/types/types.ts +319 -0
- package/core/utils/env-runtime.ts +7 -0
- package/core/utils/errors/handlers.ts +264 -39
- package/core/utils/errors/index.ts +528 -18
- package/core/utils/errors/middleware.ts +114 -0
- package/core/utils/logger/formatters.ts +222 -0
- package/core/utils/logger/index.ts +167 -48
- package/core/utils/logger/middleware.ts +253 -0
- package/core/utils/logger/performance.ts +384 -0
- package/core/utils/logger/transports.ts +365 -0
- package/create-fluxstack.ts +296 -296
- package/fluxstack.config.ts +17 -1
- package/package-template.json +66 -66
- package/package.json +31 -6
- package/public/README.md +16 -0
- package/vite.config.ts +29 -14
- package/.claude/settings.local.json +0 -74
- package/.github/workflows/ci-build-tests.yml +0 -480
- package/.github/workflows/dependency-management.yml +0 -324
- package/.github/workflows/release-validation.yml +0 -355
- package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
- package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
- package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
- package/CLAUDE.md +0 -200
- package/Dockerfile +0 -58
- package/Dockerfile.backend +0 -52
- package/Dockerfile.frontend +0 -54
- package/README-Docker.md +0 -85
- package/ai-context/00-QUICK-START.md +0 -86
- package/ai-context/README.md +0 -88
- package/ai-context/development/eden-treaty-guide.md +0 -362
- package/ai-context/development/patterns.md +0 -382
- package/ai-context/development/plugins-guide.md +0 -572
- package/ai-context/examples/crud-complete.md +0 -626
- package/ai-context/project/architecture.md +0 -399
- package/ai-context/project/overview.md +0 -213
- package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
- package/ai-context/recent-changes/type-inference-fix.md +0 -223
- package/ai-context/reference/environment-vars.md +0 -384
- package/ai-context/reference/troubleshooting.md +0 -407
- package/app/client/src/components/TestPage.tsx +0 -453
- package/bun.lock +0 -1063
- package/bunfig.toml +0 -16
- package/core/__tests__/integration.test.ts +0 -227
- package/core/build/index.ts +0 -186
- package/core/config/__tests__/config-loader.test.ts +0 -554
- package/core/config/__tests__/config-merger.test.ts +0 -657
- package/core/config/__tests__/env-converter.test.ts +0 -372
- package/core/config/__tests__/env-processor.test.ts +0 -431
- package/core/config/__tests__/env.test.ts +0 -452
- package/core/config/__tests__/integration.test.ts +0 -418
- package/core/config/__tests__/loader.test.ts +0 -331
- package/core/config/__tests__/schema.test.ts +0 -129
- package/core/config/__tests__/validator.test.ts +0 -318
- package/core/framework/__tests__/server.test.ts +0 -233
- package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
- package/core/plugins/__tests__/manager.test.ts +0 -398
- package/core/plugins/__tests__/monitoring.test.ts +0 -401
- package/core/plugins/__tests__/registry.test.ts +0 -335
- package/core/utils/__tests__/errors.test.ts +0 -139
- package/core/utils/__tests__/helpers.test.ts +0 -297
- package/core/utils/__tests__/logger.test.ts +0 -141
- package/create-test-app.ts +0 -156
- package/docker-compose.microservices.yml +0 -75
- package/docker-compose.simple.yml +0 -57
- package/docker-compose.yml +0 -71
- package/eslint.config.js +0 -23
- package/flux-cli.ts +0 -214
- package/nginx-lb.conf +0 -37
- package/publish.sh +0 -63
- package/run-clean.ts +0 -26
- package/run-env-tests.ts +0 -313
- package/tailwind.config.js +0 -34
- package/tests/__mocks__/api.ts +0 -56
- package/tests/fixtures/users.ts +0 -69
- package/tests/integration/api/users.routes.test.ts +0 -221
- package/tests/setup.ts +0 -29
- package/tests/unit/app/client/App-simple.test.tsx +0 -56
- package/tests/unit/app/client/App.test.tsx.skip +0 -237
- package/tests/unit/app/client/eden-api.test.ts +0 -186
- package/tests/unit/app/client/simple.test.tsx +0 -23
- package/tests/unit/app/controllers/users.controller.test.ts +0 -150
- package/tests/unit/core/create-project.test.ts.skip +0 -95
- package/tests/unit/core/framework.test.ts +0 -144
- package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
- package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
- package/tests/utils/test-helpers.ts +0 -61
- package/vitest.config.ts +0 -50
- package/workspace.json +0 -6
|
@@ -1,572 +0,0 @@
|
|
|
1
|
-
# ๐ FluxStack Plugins Guide
|
|
2
|
-
|
|
3
|
-
> Complete guide for adding and creating plugins in FluxStack applications
|
|
4
|
-
|
|
5
|
-
## ๐ฏ Overview
|
|
6
|
-
|
|
7
|
-
FluxStack provides a powerful plugin system that allows developers to extend their applications with custom functionality. Plugins can hook into various parts of the application lifecycle and provide reusable features.
|
|
8
|
-
|
|
9
|
-
## ๐ฆ Built-in Plugins
|
|
10
|
-
|
|
11
|
-
FluxStack comes with several built-in plugins:
|
|
12
|
-
|
|
13
|
-
- **๐ชต Logger Plugin**: Structured logging with customizable levels
|
|
14
|
-
- **๐ Swagger Plugin**: Auto-generated API documentation
|
|
15
|
-
- **๐ Static Plugin**: Serves static files in production
|
|
16
|
-
- **โก Vite Plugin**: Dev server integration with hot reload
|
|
17
|
-
- **๐ Monitoring Plugin**: Performance metrics and health checks
|
|
18
|
-
|
|
19
|
-
## ๐ Using Built-in Plugins
|
|
20
|
-
|
|
21
|
-
### Basic Plugin Usage
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
// app/server/index.ts
|
|
25
|
-
import {
|
|
26
|
-
FluxStackFramework,
|
|
27
|
-
loggerPlugin,
|
|
28
|
-
swaggerPlugin,
|
|
29
|
-
staticPlugin,
|
|
30
|
-
vitePlugin
|
|
31
|
-
} from "@/core/server"
|
|
32
|
-
|
|
33
|
-
const app = new FluxStackFramework({ /* config */ })
|
|
34
|
-
|
|
35
|
-
// Add built-in plugins
|
|
36
|
-
app.use(loggerPlugin)
|
|
37
|
-
app.use(swaggerPlugin)
|
|
38
|
-
|
|
39
|
-
// Conditional plugin loading
|
|
40
|
-
if (isDevelopment()) {
|
|
41
|
-
app.use(vitePlugin)
|
|
42
|
-
} else {
|
|
43
|
-
app.use(staticPlugin)
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### Plugin Configuration
|
|
48
|
-
|
|
49
|
-
```typescript
|
|
50
|
-
// Configure plugins with options
|
|
51
|
-
app.use(loggerPlugin, {
|
|
52
|
-
level: 'debug',
|
|
53
|
-
format: 'pretty',
|
|
54
|
-
timestamp: true
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
app.use(swaggerPlugin, {
|
|
58
|
-
title: 'My API',
|
|
59
|
-
version: '2.0.0',
|
|
60
|
-
description: 'Custom API documentation'
|
|
61
|
-
})
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## ๐ ๏ธ Creating Custom Plugins
|
|
65
|
-
|
|
66
|
-
### 1. Simple Plugin Structure
|
|
67
|
-
|
|
68
|
-
Create plugins in your application directory:
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// app/server/plugins/auth.ts
|
|
72
|
-
import { Elysia } from 'elysia'
|
|
73
|
-
|
|
74
|
-
export const authPlugin = new Elysia({ name: 'auth' })
|
|
75
|
-
.derive(({ headers }) => ({
|
|
76
|
-
user: getUserFromToken(headers.authorization)
|
|
77
|
-
}))
|
|
78
|
-
.guard({
|
|
79
|
-
beforeHandle({ user, set }) {
|
|
80
|
-
if (!user) {
|
|
81
|
-
set.status = 401
|
|
82
|
-
return { error: 'Unauthorized' }
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
// Usage in app/server/index.ts
|
|
88
|
-
import { authPlugin } from './plugins/auth'
|
|
89
|
-
app.use(authPlugin)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 2. Advanced Plugin with Lifecycle Hooks
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
// app/server/plugins/monitoring.ts
|
|
96
|
-
import { Elysia } from 'elysia'
|
|
97
|
-
import type { PluginContext, FluxStackPlugin } from '@/core/plugins/types'
|
|
98
|
-
|
|
99
|
-
export interface MonitoringConfig {
|
|
100
|
-
metricsEndpoint?: string
|
|
101
|
-
enableHealthCheck?: boolean
|
|
102
|
-
collectMetrics?: boolean
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export const createMonitoringPlugin = (config: MonitoringConfig): FluxStackPlugin => ({
|
|
106
|
-
name: 'monitoring',
|
|
107
|
-
version: '1.0.0',
|
|
108
|
-
dependencies: [],
|
|
109
|
-
|
|
110
|
-
setup: async (context: PluginContext) => {
|
|
111
|
-
context.logger.info('Setting up monitoring plugin')
|
|
112
|
-
|
|
113
|
-
// Initialize metrics collection
|
|
114
|
-
const metrics = {
|
|
115
|
-
requests: 0,
|
|
116
|
-
errors: 0,
|
|
117
|
-
startTime: Date.now()
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return { metrics }
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
onServerStart: async (context: PluginContext) => {
|
|
124
|
-
context.logger.info('Monitoring plugin started')
|
|
125
|
-
// Start periodic health checks, metrics collection
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
onRequest: async (context: PluginContext) => {
|
|
129
|
-
context.metrics.requests++
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
plugin: new Elysia({ name: 'monitoring' })
|
|
133
|
-
.get('/metrics', () => ({
|
|
134
|
-
requests: context.metrics.requests,
|
|
135
|
-
errors: context.metrics.errors,
|
|
136
|
-
uptime: Date.now() - context.metrics.startTime
|
|
137
|
-
}))
|
|
138
|
-
.get('/health', () => ({
|
|
139
|
-
status: 'healthy',
|
|
140
|
-
timestamp: new Date().toISOString()
|
|
141
|
-
}))
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
// Usage
|
|
145
|
-
import { createMonitoringPlugin } from './plugins/monitoring'
|
|
146
|
-
|
|
147
|
-
const monitoringPlugin = createMonitoringPlugin({
|
|
148
|
-
metricsEndpoint: '/metrics',
|
|
149
|
-
enableHealthCheck: true,
|
|
150
|
-
collectMetrics: true
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
app.use(monitoringPlugin)
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### 3. Plugin with Configuration Schema
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
// app/server/plugins/cache.ts
|
|
160
|
-
import { Elysia } from 'elysia'
|
|
161
|
-
import type { FluxStackPlugin } from '@/core/plugins/types'
|
|
162
|
-
|
|
163
|
-
export interface CacheConfig {
|
|
164
|
-
provider: 'redis' | 'memory'
|
|
165
|
-
ttl: number
|
|
166
|
-
maxSize?: number
|
|
167
|
-
redis?: {
|
|
168
|
-
host: string
|
|
169
|
-
port: number
|
|
170
|
-
password?: string
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export const createCachePlugin = (config: CacheConfig): FluxStackPlugin => {
|
|
175
|
-
const cache = config.provider === 'redis'
|
|
176
|
-
? new RedisCache(config.redis!)
|
|
177
|
-
: new MemoryCache({ maxSize: config.maxSize })
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
name: 'cache',
|
|
181
|
-
version: '1.0.0',
|
|
182
|
-
|
|
183
|
-
setup: async (context) => {
|
|
184
|
-
await cache.connect()
|
|
185
|
-
context.logger.info('Cache plugin initialized', { provider: config.provider })
|
|
186
|
-
|
|
187
|
-
return { cache }
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
plugin: new Elysia({ name: 'cache' })
|
|
191
|
-
.derive(() => ({
|
|
192
|
-
cache: {
|
|
193
|
-
get: (key: string) => cache.get(key),
|
|
194
|
-
set: (key: string, value: any, ttl = config.ttl) =>
|
|
195
|
-
cache.set(key, value, ttl),
|
|
196
|
-
del: (key: string) => cache.del(key),
|
|
197
|
-
flush: () => cache.flush()
|
|
198
|
-
}
|
|
199
|
-
}))
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Usage in routes
|
|
204
|
-
// app/server/routes/posts.routes.ts
|
|
205
|
-
export const postsRoutes = new Elysia({ prefix: '/posts' })
|
|
206
|
-
.get('/', async ({ cache }) => {
|
|
207
|
-
const cached = await cache.get('posts:all')
|
|
208
|
-
if (cached) return cached
|
|
209
|
-
|
|
210
|
-
const posts = await getAllPosts()
|
|
211
|
-
await cache.set('posts:all', posts, 300) // 5 minutes
|
|
212
|
-
return posts
|
|
213
|
-
})
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
## ๐จ Plugin Patterns
|
|
217
|
-
|
|
218
|
-
### 1. Middleware Plugin
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
// app/server/plugins/cors.ts
|
|
222
|
-
import { Elysia } from 'elysia'
|
|
223
|
-
|
|
224
|
-
export interface CorsConfig {
|
|
225
|
-
origins: string[]
|
|
226
|
-
methods: string[]
|
|
227
|
-
headers: string[]
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export const createCorsPlugin = (config: CorsConfig) =>
|
|
231
|
-
new Elysia({ name: 'cors' })
|
|
232
|
-
.onBeforeHandle(({ set, request }) => {
|
|
233
|
-
const origin = request.headers.get('origin')
|
|
234
|
-
|
|
235
|
-
if (config.origins.includes(origin || '')) {
|
|
236
|
-
set.headers['Access-Control-Allow-Origin'] = origin
|
|
237
|
-
set.headers['Access-Control-Allow-Methods'] = config.methods.join(', ')
|
|
238
|
-
set.headers['Access-Control-Allow-Headers'] = config.headers.join(', ')
|
|
239
|
-
}
|
|
240
|
-
})
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
### 2. Validation Plugin
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
// app/server/plugins/validation.ts
|
|
247
|
-
import { Elysia } from 'elysia'
|
|
248
|
-
import { z } from 'zod'
|
|
249
|
-
|
|
250
|
-
export const validationPlugin = new Elysia({ name: 'validation' })
|
|
251
|
-
.macro(({ onBeforeHandle }) => ({
|
|
252
|
-
validate: (schema: z.ZodSchema) => onBeforeHandle(({ body, set }) => {
|
|
253
|
-
try {
|
|
254
|
-
return schema.parse(body)
|
|
255
|
-
} catch (error) {
|
|
256
|
-
set.status = 400
|
|
257
|
-
return { error: 'Validation failed', details: error.errors }
|
|
258
|
-
}
|
|
259
|
-
})
|
|
260
|
-
}))
|
|
261
|
-
|
|
262
|
-
// Usage
|
|
263
|
-
const userSchema = z.object({
|
|
264
|
-
name: z.string().min(2),
|
|
265
|
-
email: z.string().email()
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
export const usersRoutes = new Elysia({ prefix: '/users' })
|
|
269
|
-
.use(validationPlugin)
|
|
270
|
-
.post('/', ({ body }) => {
|
|
271
|
-
// body is now validated and typed
|
|
272
|
-
return createUser(body)
|
|
273
|
-
}, {
|
|
274
|
-
validate: userSchema
|
|
275
|
-
})
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
### 3. Rate Limiting Plugin
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
// app/server/plugins/rate-limit.ts
|
|
282
|
-
import { Elysia } from 'elysia'
|
|
283
|
-
|
|
284
|
-
interface RateLimitConfig {
|
|
285
|
-
max: number
|
|
286
|
-
window: number // milliseconds
|
|
287
|
-
keyGenerator?: (request: Request) => string
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
export const createRateLimitPlugin = (config: RateLimitConfig) => {
|
|
291
|
-
const requests = new Map<string, { count: number; resetTime: number }>()
|
|
292
|
-
|
|
293
|
-
return new Elysia({ name: 'rate-limit' })
|
|
294
|
-
.onBeforeHandle(({ request, set }) => {
|
|
295
|
-
const key = config.keyGenerator?.(request) ??
|
|
296
|
-
request.headers.get('x-forwarded-for') ?? 'default'
|
|
297
|
-
|
|
298
|
-
const now = Date.now()
|
|
299
|
-
const record = requests.get(key)
|
|
300
|
-
|
|
301
|
-
if (!record || now > record.resetTime) {
|
|
302
|
-
requests.set(key, { count: 1, resetTime: now + config.window })
|
|
303
|
-
return
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (record.count >= config.max) {
|
|
307
|
-
set.status = 429
|
|
308
|
-
return { error: 'Rate limit exceeded' }
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
record.count++
|
|
312
|
-
})
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Usage
|
|
316
|
-
const rateLimitPlugin = createRateLimitPlugin({
|
|
317
|
-
max: 100,
|
|
318
|
-
window: 60 * 1000, // 1 minute
|
|
319
|
-
keyGenerator: (req) => req.headers.get('x-api-key') ?? 'anonymous'
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
app.use(rateLimitPlugin)
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
## ๐ Plugin Organization
|
|
326
|
-
|
|
327
|
-
### Recommended Structure
|
|
328
|
-
|
|
329
|
-
```
|
|
330
|
-
app/server/plugins/
|
|
331
|
-
โโโ auth/
|
|
332
|
-
โ โโโ index.ts # Main auth plugin
|
|
333
|
-
โ โโโ strategies/ # Different auth strategies
|
|
334
|
-
โ โ โโโ jwt.ts
|
|
335
|
-
โ โ โโโ oauth.ts
|
|
336
|
-
โ โโโ middleware/ # Auth-related middleware
|
|
337
|
-
โโโ cache/
|
|
338
|
-
โ โโโ index.ts # Cache plugin
|
|
339
|
-
โ โโโ providers/ # Different cache providers
|
|
340
|
-
โ โ โโโ redis.ts
|
|
341
|
-
โ โ โโโ memory.ts
|
|
342
|
-
โโโ monitoring/
|
|
343
|
-
โ โโโ index.ts # Monitoring plugin
|
|
344
|
-
โ โโโ metrics.ts # Custom metrics
|
|
345
|
-
โ โโโ health.ts # Health checks
|
|
346
|
-
โโโ validation/
|
|
347
|
-
โโโ index.ts # Validation plugin
|
|
348
|
-
โโโ schemas/ # Validation schemas
|
|
349
|
-
โโโ middleware/ # Validation middleware
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
### Plugin Registration
|
|
353
|
-
|
|
354
|
-
```typescript
|
|
355
|
-
// app/server/plugins/index.ts
|
|
356
|
-
export { authPlugin } from './auth'
|
|
357
|
-
export { createCachePlugin } from './cache'
|
|
358
|
-
export { createMonitoringPlugin } from './monitoring'
|
|
359
|
-
export { validationPlugin } from './validation'
|
|
360
|
-
|
|
361
|
-
// app/server/index.ts
|
|
362
|
-
import {
|
|
363
|
-
authPlugin,
|
|
364
|
-
createCachePlugin,
|
|
365
|
-
createMonitoringPlugin,
|
|
366
|
-
validationPlugin
|
|
367
|
-
} from './plugins'
|
|
368
|
-
|
|
369
|
-
// Register plugins in order of dependency
|
|
370
|
-
app.use(validationPlugin)
|
|
371
|
-
app.use(createCachePlugin({ provider: 'memory', ttl: 300 }))
|
|
372
|
-
app.use(authPlugin)
|
|
373
|
-
app.use(createMonitoringPlugin({ enableHealthCheck: true }))
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
## ๐ง Plugin Configuration
|
|
377
|
-
|
|
378
|
-
### Environment-based Plugin Loading
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
// app/server/index.ts
|
|
382
|
-
import { env } from '@/core/utils/env-runtime-v2'
|
|
383
|
-
|
|
384
|
-
// Conditional plugin loading based on environment
|
|
385
|
-
if (env.ENABLE_AUTH) {
|
|
386
|
-
app.use(authPlugin)
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (env.ENABLE_CACHE) {
|
|
390
|
-
app.use(createCachePlugin({
|
|
391
|
-
provider: env.CACHE_PROVIDER,
|
|
392
|
-
ttl: env.CACHE_TTL
|
|
393
|
-
}))
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (env.ENABLE_MONITORING) {
|
|
397
|
-
app.use(monitoringPlugin)
|
|
398
|
-
}
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### Plugin Configuration File
|
|
402
|
-
|
|
403
|
-
```typescript
|
|
404
|
-
// app/server/config/plugins.ts
|
|
405
|
-
import type { PluginConfig } from '@/core/plugins/types'
|
|
406
|
-
|
|
407
|
-
export const pluginConfig: PluginConfig = {
|
|
408
|
-
auth: {
|
|
409
|
-
enabled: true,
|
|
410
|
-
strategy: 'jwt',
|
|
411
|
-
secret: process.env.JWT_SECRET,
|
|
412
|
-
expiresIn: '24h'
|
|
413
|
-
},
|
|
414
|
-
cache: {
|
|
415
|
-
enabled: true,
|
|
416
|
-
provider: 'redis',
|
|
417
|
-
redis: {
|
|
418
|
-
host: process.env.REDIS_HOST,
|
|
419
|
-
port: parseInt(process.env.REDIS_PORT || '6379'),
|
|
420
|
-
password: process.env.REDIS_PASSWORD
|
|
421
|
-
},
|
|
422
|
-
ttl: 300
|
|
423
|
-
},
|
|
424
|
-
monitoring: {
|
|
425
|
-
enabled: process.env.NODE_ENV === 'production',
|
|
426
|
-
metrics: true,
|
|
427
|
-
healthChecks: true,
|
|
428
|
-
profiling: false
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## ๐งช Testing Plugins
|
|
434
|
-
|
|
435
|
-
### Plugin Unit Tests
|
|
436
|
-
|
|
437
|
-
```typescript
|
|
438
|
-
// app/server/plugins/__tests__/auth.test.ts
|
|
439
|
-
import { describe, it, expect } from 'bun:test'
|
|
440
|
-
import { Elysia } from 'elysia'
|
|
441
|
-
import { authPlugin } from '../auth'
|
|
442
|
-
|
|
443
|
-
describe('Auth Plugin', () => {
|
|
444
|
-
const app = new Elysia().use(authPlugin)
|
|
445
|
-
|
|
446
|
-
it('should authenticate valid token', async () => {
|
|
447
|
-
const response = await app.handle(
|
|
448
|
-
new Request('http://localhost/protected', {
|
|
449
|
-
headers: { Authorization: 'Bearer valid-token' }
|
|
450
|
-
})
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
expect(response.status).toBe(200)
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('should reject invalid token', async () => {
|
|
457
|
-
const response = await app.handle(
|
|
458
|
-
new Request('http://localhost/protected', {
|
|
459
|
-
headers: { Authorization: 'Bearer invalid-token' }
|
|
460
|
-
})
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
expect(response.status).toBe(401)
|
|
464
|
-
})
|
|
465
|
-
})
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
### Integration Testing
|
|
469
|
-
|
|
470
|
-
```typescript
|
|
471
|
-
// tests/integration/plugins.test.ts
|
|
472
|
-
import { describe, it, expect } from 'bun:test'
|
|
473
|
-
import { FluxStackFramework } from '@/core/server'
|
|
474
|
-
import { authPlugin, createCachePlugin } from '@/app/server/plugins'
|
|
475
|
-
|
|
476
|
-
describe('Plugin Integration', () => {
|
|
477
|
-
const app = new FluxStackFramework()
|
|
478
|
-
.use(authPlugin)
|
|
479
|
-
.use(createCachePlugin({ provider: 'memory', ttl: 100 }))
|
|
480
|
-
|
|
481
|
-
it('should work with multiple plugins', async () => {
|
|
482
|
-
// Test plugin interactions
|
|
483
|
-
})
|
|
484
|
-
})
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
## ๐ Best Practices
|
|
488
|
-
|
|
489
|
-
### 1. Plugin Design Principles
|
|
490
|
-
|
|
491
|
-
- **Single Responsibility**: Each plugin should have a clear, focused purpose
|
|
492
|
-
- **Minimal Dependencies**: Avoid heavy dependencies when possible
|
|
493
|
-
- **Configuration**: Make plugins configurable rather than hardcoded
|
|
494
|
-
- **Error Handling**: Graceful error handling and fallbacks
|
|
495
|
-
- **Logging**: Proper logging for debugging and monitoring
|
|
496
|
-
|
|
497
|
-
### 2. Performance Considerations
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
// Good: Lazy loading of heavy dependencies
|
|
501
|
-
export const createDatabasePlugin = (config: DatabaseConfig) => {
|
|
502
|
-
let db: Database | null = null
|
|
503
|
-
|
|
504
|
-
return {
|
|
505
|
-
name: 'database',
|
|
506
|
-
setup: async () => {
|
|
507
|
-
if (!db) {
|
|
508
|
-
db = await import('./database').then(m => m.connect(config))
|
|
509
|
-
}
|
|
510
|
-
return { db }
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
// Good: Efficient middleware
|
|
516
|
-
export const createAuthPlugin = () => new Elysia()
|
|
517
|
-
.derive(({ headers }) => {
|
|
518
|
-
// Only parse token if Authorization header exists
|
|
519
|
-
const auth = headers.authorization
|
|
520
|
-
return auth ? { user: parseToken(auth) } : { user: null }
|
|
521
|
-
})
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
### 3. Type Safety
|
|
525
|
-
|
|
526
|
-
```typescript
|
|
527
|
-
// Define strong types for plugin configuration
|
|
528
|
-
export interface DatabasePluginConfig {
|
|
529
|
-
readonly url: string
|
|
530
|
-
readonly poolSize?: number
|
|
531
|
-
readonly ssl?: boolean
|
|
532
|
-
readonly timeout?: number
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// Use branded types for better type safety
|
|
536
|
-
type UserId = string & { readonly brand: unique symbol }
|
|
537
|
-
type DatabaseConnection = object & { readonly brand: unique symbol }
|
|
538
|
-
|
|
539
|
-
export const createDatabasePlugin = (
|
|
540
|
-
config: DatabasePluginConfig
|
|
541
|
-
): FluxStackPlugin<{ db: DatabaseConnection }> => {
|
|
542
|
-
// Implementation with strong typing
|
|
543
|
-
}
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
## ๐ Plugin Examples
|
|
547
|
-
|
|
548
|
-
### Real-world Plugin Examples
|
|
549
|
-
|
|
550
|
-
See the built-in plugins for reference:
|
|
551
|
-
- **Logger Plugin**: `core/plugins/built-in/logger/index.ts`
|
|
552
|
-
- **Swagger Plugin**: `core/plugins/built-in/swagger/index.ts`
|
|
553
|
-
- **Static Plugin**: `core/plugins/built-in/static/index.ts`
|
|
554
|
-
- **Vite Plugin**: `core/plugins/built-in/vite/index.ts`
|
|
555
|
-
- **Monitoring Plugin**: `core/plugins/built-in/monitoring/index.ts`
|
|
556
|
-
|
|
557
|
-
## ๐ฏ Summary
|
|
558
|
-
|
|
559
|
-
FluxStack's plugin system provides:
|
|
560
|
-
|
|
561
|
-
1. **๐ Easy Integration**: Simple API for adding functionality
|
|
562
|
-
2. **๐จ Flexible Architecture**: Support for various plugin patterns
|
|
563
|
-
3. **โก Performance**: Efficient plugin loading and execution
|
|
564
|
-
4. **๐ Type Safety**: Full TypeScript support
|
|
565
|
-
5. **๐งช Testability**: Easy unit and integration testing
|
|
566
|
-
6. **๐ฆ Built-in Plugins**: Ready-to-use common functionality
|
|
567
|
-
|
|
568
|
-
Start with built-in plugins, then create custom ones as your application grows!
|
|
569
|
-
|
|
570
|
-
---
|
|
571
|
-
|
|
572
|
-
**Need help with plugins? Check the troubleshooting guide or FluxStack documentation.**
|