create-fluxstack 1.7.5 → 1.8.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/.dockerignore +82 -0
- package/.env.example +19 -0
- package/Dockerfile +70 -0
- package/README.md +6 -3
- package/app/client/SIMPLIFICATION.md +140 -0
- package/app/client/frontend-only.ts +1 -1
- package/app/client/src/App.tsx +148 -283
- package/app/client/src/index.css +5 -20
- package/app/client/src/lib/eden-api.ts +53 -220
- package/app/client/src/main.tsx +2 -3
- package/app/server/app.ts +20 -5
- package/app/server/backend-only.ts +15 -12
- package/app/server/controllers/users.controller.ts +57 -31
- package/app/server/index.ts +86 -96
- package/app/server/live/register-components.ts +18 -7
- package/app/server/routes/env-test.ts +110 -0
- package/app/server/routes/index.ts +1 -8
- package/app/server/routes/users.routes.ts +192 -91
- package/config/app.config.ts +2 -54
- package/config/client.config.ts +95 -0
- package/config/fluxstack.config.ts +2 -2
- package/config/index.ts +57 -22
- package/config/monitoring.config.ts +114 -0
- package/config/plugins.config.ts +80 -0
- package/config/runtime.config.ts +0 -17
- package/config/server.config.ts +50 -30
- package/core/build/bundler.ts +17 -16
- package/core/build/flux-plugins-generator.ts +34 -23
- package/core/build/index.ts +32 -31
- package/core/build/live-components-generator.ts +44 -30
- package/core/build/optimizer.ts +37 -17
- package/core/cli/command-registry.ts +4 -14
- package/core/cli/commands/plugin-deps.ts +8 -8
- package/core/cli/generators/component.ts +3 -3
- package/core/cli/generators/controller.ts +4 -4
- package/core/cli/generators/index.ts +8 -8
- package/core/cli/generators/interactive.ts +4 -4
- package/core/cli/generators/plugin.ts +3 -3
- package/core/cli/generators/prompts.ts +1 -1
- package/core/cli/generators/route.ts +27 -11
- package/core/cli/generators/service.ts +5 -5
- package/core/cli/generators/template-engine.ts +1 -1
- package/core/cli/generators/types.ts +1 -1
- package/core/cli/index.ts +158 -189
- package/core/cli/plugin-discovery.ts +3 -3
- package/core/client/hooks/index.ts +2 -2
- package/core/client/hooks/state-validator.ts +1 -1
- package/core/client/hooks/useAuth.ts +1 -1
- package/core/client/hooks/useChunkedUpload.ts +1 -1
- package/core/client/hooks/useHybridLiveComponent.ts +1 -1
- package/core/client/hooks/useWebSocket.ts +1 -1
- package/core/config/env.ts +5 -1
- package/core/config/runtime-config.ts +12 -10
- package/core/config/schema.ts +33 -2
- package/core/framework/server.ts +30 -14
- package/core/framework/types.ts +2 -2
- package/core/index.ts +31 -23
- package/core/live/ComponentRegistry.ts +1 -1
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1 -1
- package/core/plugins/built-in/live-components/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +65 -161
- package/core/plugins/built-in/static/index.ts +75 -277
- package/core/plugins/built-in/swagger/index.ts +301 -231
- package/core/plugins/built-in/vite/index.ts +342 -377
- package/core/plugins/config.ts +2 -2
- package/core/plugins/dependency-manager.ts +2 -2
- package/core/plugins/discovery.ts +1 -1
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/manager.ts +19 -4
- package/core/plugins/module-resolver.ts +1 -1
- package/core/plugins/registry.ts +25 -21
- package/core/plugins/types.ts +147 -5
- package/core/server/backend-entry.ts +51 -0
- package/core/server/framework.ts +2 -2
- package/core/server/live/ComponentRegistry.ts +9 -26
- package/core/server/live/FileUploadManager.ts +1 -1
- package/core/server/live/auto-generated-components.ts +26 -0
- package/core/server/live/websocket-plugin.ts +211 -19
- package/core/server/middleware/errorHandling.ts +1 -1
- package/core/server/middleware/index.ts +4 -4
- package/core/server/plugins/database.ts +1 -2
- package/core/server/plugins/static-files-plugin.ts +259 -231
- package/core/server/plugins/swagger.ts +1 -1
- package/core/server/services/BaseService.ts +1 -1
- package/core/server/services/ServiceContainer.ts +1 -1
- package/core/server/services/index.ts +4 -4
- package/core/server/standalone.ts +16 -1
- package/core/testing/index.ts +1 -1
- package/core/testing/setup.ts +1 -1
- package/core/types/plugin.ts +6 -0
- package/core/utils/build-logger.ts +324 -0
- package/core/utils/config-schema.ts +2 -6
- package/core/utils/helpers.ts +14 -9
- package/core/utils/logger/startup-banner.ts +7 -33
- package/core/utils/regenerate-files.ts +69 -0
- package/core/utils/version.ts +6 -6
- package/create-fluxstack.ts +68 -25
- package/fluxstack.config.ts +138 -252
- package/package.json +3 -18
- package/plugins/crypto-auth/index.ts +52 -47
- package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
- package/plugins/crypto-auth/server/middlewares/helpers.ts +16 -1
- package/vitest.config.ts +17 -26
- package/app/client/src/App.css +0 -883
- package/app/client/src/components/ErrorBoundary.tsx +0 -107
- package/app/client/src/components/ErrorDisplay.css +0 -365
- package/app/client/src/components/ErrorDisplay.tsx +0 -258
- package/app/client/src/components/FluxStackConfig.tsx +0 -1321
- package/app/client/src/components/HybridLiveCounter.tsx +0 -140
- package/app/client/src/components/LiveClock.tsx +0 -286
- package/app/client/src/components/MainLayout.tsx +0 -388
- package/app/client/src/components/SidebarNavigation.tsx +0 -391
- package/app/client/src/components/StateDemo.tsx +0 -178
- package/app/client/src/components/SystemMonitor.tsx +0 -1044
- package/app/client/src/components/UserProfile.tsx +0 -809
- package/app/client/src/hooks/useAuth.ts +0 -39
- package/app/client/src/hooks/useNotifications.ts +0 -56
- package/app/client/src/lib/errors.ts +0 -340
- package/app/client/src/lib/hooks/useErrorHandler.ts +0 -258
- package/app/client/src/lib/index.ts +0 -45
- package/app/client/src/pages/ApiDocs.tsx +0 -182
- package/app/client/src/pages/CryptoAuthPage.tsx +0 -394
- package/app/client/src/pages/Demo.tsx +0 -174
- package/app/client/src/pages/HybridLive.tsx +0 -263
- package/app/client/src/pages/Overview.tsx +0 -155
- package/app/client/src/store/README.md +0 -43
- package/app/client/src/store/index.ts +0 -16
- package/app/client/src/store/slices/uiSlice.ts +0 -151
- package/app/client/src/store/slices/userSlice.ts +0 -161
- package/app/client/src/test/README.md +0 -257
- package/app/client/src/test/setup.ts +0 -70
- package/app/client/src/test/types.ts +0 -12
- package/app/server/live/CounterComponent.ts +0 -191
- package/app/server/live/FluxStackConfig.ts +0 -534
- package/app/server/live/SidebarNavigation.ts +0 -157
- package/app/server/live/SystemMonitor.ts +0 -595
- package/app/server/live/SystemMonitorIntegration.ts +0 -151
- package/app/server/live/UserProfileComponent.ts +0 -141
- package/app/server/middleware/auth.ts +0 -136
- package/app/server/middleware/errorHandling.ts +0 -252
- package/app/server/middleware/index.ts +0 -10
- package/app/server/middleware/rateLimit.ts +0 -193
- package/app/server/middleware/requestLogging.ts +0 -215
- package/app/server/middleware/validation.ts +0 -270
- package/app/server/routes/config.ts +0 -145
- package/app/server/routes/crypto-auth-demo.routes.ts +0 -167
- package/app/server/routes/example-with-crypto-auth.routes.ts +0 -235
- package/app/server/routes/exemplo-posts.routes.ts +0 -161
- package/app/server/routes/upload.ts +0 -92
- package/app/server/services/NotificationService.ts +0 -302
- package/app/server/services/UserService.ts +0 -222
- package/app/server/services/index.ts +0 -46
- package/app/server/types/index.ts +0 -1
- package/config/build.config.ts +0 -24
package/app/server/index.ts
CHANGED
|
@@ -1,125 +1,115 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* 🚀 FluxStack Application Server Entry Point
|
|
3
|
+
* Main server configuration and initialization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ===== Core Framework =====
|
|
7
|
+
import { FluxStackFramework } from "@/core/server"
|
|
3
8
|
import { isDevelopment } from "@/core/utils/helpers"
|
|
4
9
|
import { DEBUG } from "@/core/utils/logger"
|
|
5
|
-
import { apiRoutes } from "./routes"
|
|
6
10
|
import { helpers } from "@/core/utils/env"
|
|
7
|
-
|
|
11
|
+
|
|
12
|
+
// ===== Configuration =====
|
|
8
13
|
import { appConfig } from "@/config/app.config"
|
|
9
|
-
import {
|
|
14
|
+
import { serverConfig } from "@/config/server.config"
|
|
15
|
+
|
|
16
|
+
// ===== Plugins =====
|
|
17
|
+
import {
|
|
18
|
+
vitePlugin,
|
|
19
|
+
swaggerPlugin,
|
|
20
|
+
staticPlugin,
|
|
21
|
+
liveComponentsPlugin,
|
|
22
|
+
staticFilesPlugin
|
|
23
|
+
} from "@/core/server"
|
|
10
24
|
import cryptoAuthPlugin from "@/plugins/crypto-auth"
|
|
11
|
-
import "./live/register-components"
|
|
12
25
|
|
|
13
|
-
//
|
|
26
|
+
// ===== Application Routes =====
|
|
27
|
+
import { appInstance } from "./app"
|
|
28
|
+
|
|
29
|
+
// ===== Live Components Registration =====
|
|
30
|
+
// Import auto-generated component registrations from core/ (for production build)
|
|
31
|
+
// The generator creates this file in core/ to prevent accidental user modifications
|
|
32
|
+
// This ensures components are registered before the plugin tries to use them
|
|
33
|
+
import "@/core/server/live/auto-generated-components"
|
|
34
|
+
|
|
35
|
+
// ===== Startup Logging =====
|
|
14
36
|
DEBUG('🔧 Loading declarative configuration...')
|
|
15
37
|
DEBUG(`📊 Environment: ${appConfig.env}`)
|
|
16
|
-
DEBUG(`🚀 Port: ${serverConfig.port}`)
|
|
17
|
-
DEBUG(`🌐 Host: ${serverConfig.host}`)
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
DEBUG(`🚀 Port: ${serverConfig.server.port}`)
|
|
39
|
+
DEBUG(`🌐 Host: ${serverConfig.server.host}`)
|
|
40
|
+
|
|
41
|
+
// ===== Framework Configuration Helper =====
|
|
42
|
+
/**
|
|
43
|
+
* Creates FluxStack framework configuration from declarative configs
|
|
44
|
+
*/
|
|
45
|
+
function createFrameworkConfig() {
|
|
46
|
+
return {
|
|
47
|
+
server: {
|
|
48
|
+
port: serverConfig.server.port,
|
|
49
|
+
host: serverConfig.server.host,
|
|
50
|
+
apiPrefix: serverConfig.server.apiPrefix,
|
|
51
|
+
cors: {
|
|
52
|
+
origins: serverConfig.cors.origins,
|
|
53
|
+
methods: serverConfig.cors.methods,
|
|
54
|
+
headers: serverConfig.cors.headers,
|
|
55
|
+
credentials: serverConfig.cors.credentials
|
|
56
|
+
},
|
|
57
|
+
middleware: []
|
|
30
58
|
},
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
name: serverConfig.appName,
|
|
35
|
-
version: serverConfig.appVersion
|
|
36
|
-
},
|
|
37
|
-
client: {
|
|
38
|
-
port: serverConfig.clientPort,
|
|
39
|
-
proxy: {
|
|
40
|
-
target: helpers.getServerUrl()
|
|
59
|
+
app: {
|
|
60
|
+
name: appConfig.name,
|
|
61
|
+
version: appConfig.version
|
|
41
62
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
client: {
|
|
64
|
+
port: serverConfig.server.backendPort,
|
|
65
|
+
proxy: {
|
|
66
|
+
target: helpers.getServerUrl()
|
|
67
|
+
},
|
|
68
|
+
build: {
|
|
69
|
+
sourceMaps: false,
|
|
70
|
+
minify: false,
|
|
71
|
+
target: 'es2020' as any,
|
|
72
|
+
outDir: 'dist'
|
|
73
|
+
}
|
|
47
74
|
}
|
|
48
75
|
}
|
|
49
|
-
}
|
|
76
|
+
}
|
|
50
77
|
|
|
78
|
+
// ===== Initialize Application =====
|
|
79
|
+
const app = new FluxStackFramework(createFrameworkConfig())
|
|
51
80
|
|
|
52
|
-
//
|
|
81
|
+
// ===== Register Plugins =====
|
|
82
|
+
// Note: Logger is part of core, not a plugin
|
|
53
83
|
|
|
54
|
-
//
|
|
84
|
+
// 1. Authentication plugin (must be registered first)
|
|
55
85
|
app.use(cryptoAuthPlugin)
|
|
56
86
|
|
|
57
|
-
//
|
|
87
|
+
// 2. Development/Production plugins (conditional)
|
|
58
88
|
if (isDevelopment()) {
|
|
59
|
-
app.use(vitePlugin)
|
|
89
|
+
app.use(vitePlugin) // Development: Vite dev server
|
|
60
90
|
} else {
|
|
61
|
-
app.use(staticPlugin)
|
|
91
|
+
app.use(staticPlugin) // Production: Static file serving
|
|
62
92
|
}
|
|
63
93
|
|
|
64
|
-
//
|
|
65
|
-
app.use(staticFilesPlugin)
|
|
66
|
-
app.use(liveComponentsPlugin) // Add Live Components support
|
|
67
|
-
|
|
94
|
+
// 3. Static files (after Vite, before Live Components to avoid conflicts)
|
|
95
|
+
app.use(staticFilesPlugin)
|
|
68
96
|
|
|
69
|
-
//
|
|
70
|
-
app.
|
|
71
|
-
return {
|
|
72
|
-
message: '⚡ Declarative Config System!',
|
|
73
|
-
timestamp: new Date().toISOString(),
|
|
74
|
-
serverConfig: {
|
|
75
|
-
port: serverConfig.port,
|
|
76
|
-
host: serverConfig.host,
|
|
77
|
-
apiPrefix: serverConfig.apiPrefix,
|
|
78
|
-
appName: serverConfig.appName,
|
|
79
|
-
appVersion: serverConfig.appVersion,
|
|
80
|
-
cors: {
|
|
81
|
-
origins: serverConfig.corsOrigins,
|
|
82
|
-
methods: serverConfig.corsMethods,
|
|
83
|
-
credentials: serverConfig.corsCredentials
|
|
84
|
-
},
|
|
85
|
-
client: {
|
|
86
|
-
port: serverConfig.clientPort,
|
|
87
|
-
target: serverConfig.clientTarget,
|
|
88
|
-
sourceMaps: serverConfig.clientSourceMaps
|
|
89
|
-
},
|
|
90
|
-
features: {
|
|
91
|
-
enableSwagger: serverConfig.enableSwagger,
|
|
92
|
-
enableMetrics: serverConfig.enableMetrics,
|
|
93
|
-
enableMonitoring: serverConfig.enableMonitoring
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
environment: {
|
|
97
|
-
NODE_ENV: appConfig.env,
|
|
98
|
-
DEBUG: appConfig.debug,
|
|
99
|
-
LOG_LEVEL: loggerConfig.level
|
|
100
|
-
},
|
|
101
|
-
urls: {
|
|
102
|
-
server: helpers.getServerUrl(),
|
|
103
|
-
client: helpers.getClientUrl(),
|
|
104
|
-
swagger: `${helpers.getServerUrl()}/swagger`
|
|
105
|
-
},
|
|
106
|
-
system: {
|
|
107
|
-
version: 'declarative-config',
|
|
108
|
-
features: ['type-safe', 'validated', 'declarative', 'runtime-reload']
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
})
|
|
97
|
+
// 4. Live Components (WebSocket support)
|
|
98
|
+
app.use(liveComponentsPlugin)
|
|
112
99
|
|
|
113
|
-
//
|
|
114
|
-
app.
|
|
100
|
+
// ===== Register Routes =====
|
|
101
|
+
// Note: Routes are now registered in app.ts (including envTestRoute)
|
|
102
|
+
app.routes(appInstance)
|
|
115
103
|
|
|
116
|
-
//
|
|
104
|
+
// ===== Final Setup =====
|
|
105
|
+
|
|
106
|
+
// Swagger documentation (must be last to discover all routes)
|
|
117
107
|
app.use(swaggerPlugin)
|
|
118
108
|
|
|
119
|
-
//
|
|
109
|
+
// ===== Start Server =====
|
|
110
|
+
// Banner will be displayed automatically by the framework
|
|
120
111
|
app.listen()
|
|
121
112
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// Exportar tipo da aplicação para Eden Treaty (método correto)
|
|
113
|
+
// ===== Eden Treaty Type Export =====
|
|
114
|
+
// Export application type for type-safe client communication
|
|
125
115
|
export type App = typeof app
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
//
|
|
2
|
-
// This file
|
|
3
|
-
//
|
|
1
|
+
// ⚠️ DEPRECATION NOTICE
|
|
2
|
+
// This file has been moved to: core/server/live/auto-generated-components.ts
|
|
3
|
+
//
|
|
4
|
+
// The auto-generated component registration is now located in the core/ directory
|
|
5
|
+
// to prevent accidental user modifications and keep framework code separate from
|
|
6
|
+
// application code.
|
|
7
|
+
//
|
|
8
|
+
// If you're looking for component registration logic:
|
|
9
|
+
// - Generated file: core/server/live/auto-generated-components.ts (auto-generated during build)
|
|
10
|
+
// - Generator: core/build/live-components-generator.ts
|
|
11
|
+
// - Import location: app/server/index.ts
|
|
12
|
+
//
|
|
13
|
+
// To add new Live Components:
|
|
14
|
+
// 1. Create your component class in this directory (app/server/live/)
|
|
15
|
+
// 2. Extend LiveComponent class
|
|
16
|
+
// 3. Run 'bun run build' to regenerate the registration file
|
|
4
17
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// Removed startup log to keep output clean - auto-generation handles everything
|
|
18
|
+
// This file intentionally left empty - do not import
|
|
19
|
+
export {}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔧 Environment Test Route
|
|
3
|
+
* Displays current configuration for debugging purposes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Elysia, t } from 'elysia'
|
|
7
|
+
import { appConfig } from '@/config/app.config'
|
|
8
|
+
import { serverConfig } from '@/config/server.config'
|
|
9
|
+
import { loggerConfig } from '@/config/logger.config'
|
|
10
|
+
import { appRuntimeConfig } from '@/config/runtime.config'
|
|
11
|
+
import { helpers } from '@/core/utils/env'
|
|
12
|
+
|
|
13
|
+
// Response schema for environment test
|
|
14
|
+
const EnvTestResponseSchema = t.Object({
|
|
15
|
+
message: t.String(),
|
|
16
|
+
timestamp: t.String(),
|
|
17
|
+
serverConfig: t.Object({
|
|
18
|
+
port: t.Number(),
|
|
19
|
+
host: t.String(),
|
|
20
|
+
apiPrefix: t.String(),
|
|
21
|
+
appName: t.String(),
|
|
22
|
+
appVersion: t.String(),
|
|
23
|
+
cors: t.Object({
|
|
24
|
+
origins: t.Array(t.String()),
|
|
25
|
+
methods: t.Array(t.String()),
|
|
26
|
+
credentials: t.Boolean()
|
|
27
|
+
}),
|
|
28
|
+
client: t.Object({
|
|
29
|
+
port: t.Number(),
|
|
30
|
+
target: t.String(),
|
|
31
|
+
sourceMaps: t.Boolean()
|
|
32
|
+
}),
|
|
33
|
+
features: t.Object({
|
|
34
|
+
enableSwagger: t.Boolean(),
|
|
35
|
+
enableMetrics: t.Boolean(),
|
|
36
|
+
enableMonitoring: t.Boolean()
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
environment: t.Object({
|
|
40
|
+
NODE_ENV: t.String(),
|
|
41
|
+
DEBUG: t.Boolean(),
|
|
42
|
+
LOG_LEVEL: t.String()
|
|
43
|
+
}),
|
|
44
|
+
urls: t.Object({
|
|
45
|
+
server: t.String(),
|
|
46
|
+
client: t.String(),
|
|
47
|
+
swagger: t.String()
|
|
48
|
+
}),
|
|
49
|
+
system: t.Object({
|
|
50
|
+
version: t.String(),
|
|
51
|
+
features: t.Array(t.String())
|
|
52
|
+
})
|
|
53
|
+
}, {
|
|
54
|
+
description: 'Environment and configuration information for debugging'
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Environment test endpoint
|
|
59
|
+
* Shows declarative config system information
|
|
60
|
+
*/
|
|
61
|
+
export const envTestRoute = new Elysia({ prefix: '/api', tags: ['Development'] })
|
|
62
|
+
.get('/env-test', () => {
|
|
63
|
+
return {
|
|
64
|
+
message: '⚡ Declarative Config System!',
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
serverConfig: {
|
|
67
|
+
port: serverConfig.server.port,
|
|
68
|
+
host: serverConfig.server.host,
|
|
69
|
+
apiPrefix: serverConfig.server.apiPrefix,
|
|
70
|
+
appName: appConfig.name,
|
|
71
|
+
appVersion: appConfig.version,
|
|
72
|
+
cors: {
|
|
73
|
+
origins: serverConfig.cors.origins,
|
|
74
|
+
methods: serverConfig.cors.methods,
|
|
75
|
+
credentials: serverConfig.cors.credentials
|
|
76
|
+
},
|
|
77
|
+
client: {
|
|
78
|
+
port: serverConfig.server.backendPort,
|
|
79
|
+
target: 'es2020',
|
|
80
|
+
sourceMaps: false
|
|
81
|
+
},
|
|
82
|
+
features: {
|
|
83
|
+
enableSwagger: appRuntimeConfig.values.enableSwagger,
|
|
84
|
+
enableMetrics: appRuntimeConfig.values.enableMetrics,
|
|
85
|
+
enableMonitoring: appRuntimeConfig.values.enableMonitoring
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
environment: {
|
|
89
|
+
NODE_ENV: appConfig.env,
|
|
90
|
+
DEBUG: appRuntimeConfig.values.enableDebugMode,
|
|
91
|
+
LOG_LEVEL: loggerConfig.level
|
|
92
|
+
},
|
|
93
|
+
urls: {
|
|
94
|
+
server: helpers.getServerUrl(),
|
|
95
|
+
client: helpers.getClientUrl(),
|
|
96
|
+
swagger: `${helpers.getServerUrl()}/swagger`
|
|
97
|
+
},
|
|
98
|
+
system: {
|
|
99
|
+
version: 'declarative-config',
|
|
100
|
+
features: ['type-safe', 'validated', 'declarative', 'runtime-reload']
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}, {
|
|
104
|
+
detail: {
|
|
105
|
+
summary: 'Environment Configuration Test',
|
|
106
|
+
description: 'Returns current environment configuration, server settings, and runtime features for debugging and validation',
|
|
107
|
+
tags: ['Development', 'Configuration', 'Debug']
|
|
108
|
+
},
|
|
109
|
+
response: EnvTestResponseSchema
|
|
110
|
+
})
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { Elysia, t } from "elysia"
|
|
2
2
|
import { usersRoutes } from "./users.routes"
|
|
3
|
-
import { uploadRoutes } from "./upload"
|
|
4
|
-
import { configRoutes } from "./config"
|
|
5
|
-
import { cryptoAuthDemoRoutes } from "./crypto-auth-demo.routes"
|
|
6
|
-
import { exemploPostsRoutes } from "./exemplo-posts.routes"
|
|
7
3
|
|
|
8
4
|
export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
9
5
|
.get("/", () => ({ message: "🔥 Hot Reload funcionando! FluxStack API v1.4.0 ⚡" }), {
|
|
@@ -36,8 +32,5 @@ export const apiRoutes = new Elysia({ prefix: "/api" })
|
|
|
36
32
|
description: 'Returns the current health status of the API server'
|
|
37
33
|
}
|
|
38
34
|
})
|
|
35
|
+
// Register users routes
|
|
39
36
|
.use(usersRoutes)
|
|
40
|
-
.use(uploadRoutes)
|
|
41
|
-
.use(configRoutes)
|
|
42
|
-
.use(cryptoAuthDemoRoutes)
|
|
43
|
-
.use(exemploPostsRoutes) // ✅ Exemplo de rotas com crypto-auth
|
|
@@ -1,114 +1,215 @@
|
|
|
1
|
-
import { Elysia, t } from
|
|
2
|
-
import { UsersController } from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { Elysia, t } from 'elysia'
|
|
2
|
+
import { UsersController } from '@/app/server/controllers/users.controller'
|
|
3
|
+
|
|
4
|
+
// ===== Request/Response Schemas =====
|
|
5
|
+
|
|
6
|
+
const UserSchema = t.Object({
|
|
7
|
+
id: t.Number(),
|
|
8
|
+
name: t.String(),
|
|
9
|
+
email: t.String()
|
|
10
|
+
}, {
|
|
11
|
+
description: 'User object'
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const CreateUserRequestSchema = t.Object({
|
|
15
|
+
name: t.String({ minLength: 2, description: 'User name (minimum 2 characters)' }),
|
|
16
|
+
email: t.String({ format: 'email', description: 'Valid email address' })
|
|
17
|
+
}, {
|
|
18
|
+
description: 'Request body for creating a new user'
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const CreateUserResponseSchema = t.Union([
|
|
22
|
+
t.Object({
|
|
23
|
+
success: t.Literal(true),
|
|
24
|
+
user: UserSchema,
|
|
25
|
+
message: t.Optional(t.String())
|
|
26
|
+
}),
|
|
27
|
+
t.Object({
|
|
28
|
+
success: t.Literal(false),
|
|
29
|
+
error: t.String()
|
|
30
|
+
})
|
|
31
|
+
], {
|
|
32
|
+
description: 'Response after attempting to create a user'
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const GetUsersResponseSchema = t.Object({
|
|
36
|
+
success: t.Boolean(),
|
|
37
|
+
users: t.Array(UserSchema),
|
|
38
|
+
count: t.Number()
|
|
39
|
+
}, {
|
|
40
|
+
description: 'List of all users'
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const GetUserResponseSchema = t.Union([
|
|
44
|
+
t.Object({
|
|
45
|
+
success: t.Literal(true),
|
|
46
|
+
user: UserSchema
|
|
47
|
+
}),
|
|
48
|
+
t.Object({
|
|
49
|
+
success: t.Literal(false),
|
|
50
|
+
error: t.String()
|
|
51
|
+
})
|
|
52
|
+
], {
|
|
53
|
+
description: 'Single user or error'
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const DeleteUserResponseSchema = t.Union([
|
|
57
|
+
t.Object({
|
|
58
|
+
success: t.Literal(true),
|
|
59
|
+
message: t.String()
|
|
60
|
+
}),
|
|
61
|
+
t.Object({
|
|
62
|
+
success: t.Literal(false),
|
|
63
|
+
message: t.String()
|
|
64
|
+
})
|
|
65
|
+
], {
|
|
66
|
+
description: 'Result of delete operation'
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const ErrorResponseSchema = t.Object({
|
|
70
|
+
error: t.String()
|
|
71
|
+
}, {
|
|
72
|
+
description: 'Error response'
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Users API Routes
|
|
77
|
+
*/
|
|
78
|
+
export const usersRoutes = new Elysia({ prefix: '/users', tags: ['Users'] })
|
|
79
|
+
// GET /users - Get all users
|
|
80
|
+
.get('/', async () => {
|
|
81
|
+
return await UsersController.getUsers()
|
|
82
|
+
}, {
|
|
14
83
|
detail: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
84
|
+
summary: 'Get All Users',
|
|
85
|
+
description: 'Retrieves a list of all registered users',
|
|
86
|
+
tags: ['Users', 'CRUD']
|
|
87
|
+
},
|
|
88
|
+
response: GetUsersResponseSchema
|
|
19
89
|
})
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
90
|
+
|
|
91
|
+
// GET /users/:id - Get user by ID
|
|
92
|
+
.get('/:id', async ({ params, set }) => {
|
|
93
|
+
const id = parseInt(params.id)
|
|
94
|
+
|
|
95
|
+
// Handle invalid ID
|
|
96
|
+
if (isNaN(id)) {
|
|
97
|
+
set.status = 400
|
|
98
|
+
return { error: 'ID inválido' }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const result = await UsersController.getUserById(id)
|
|
102
|
+
|
|
25
103
|
if (!result) {
|
|
26
104
|
set.status = 404
|
|
27
|
-
return { error:
|
|
105
|
+
return { error: 'Usuário não encontrado' }
|
|
28
106
|
}
|
|
29
|
-
|
|
107
|
+
|
|
30
108
|
return result
|
|
31
109
|
}, {
|
|
32
|
-
params: t.Object({
|
|
33
|
-
id: t.String()
|
|
34
|
-
}),
|
|
35
110
|
detail: {
|
|
36
|
-
tags: ['Users'],
|
|
37
111
|
summary: 'Get User by ID',
|
|
38
|
-
description: '
|
|
112
|
+
description: 'Retrieves a single user by their unique identifier',
|
|
113
|
+
tags: ['Users', 'CRUD']
|
|
114
|
+
},
|
|
115
|
+
params: t.Object({
|
|
116
|
+
id: t.String({ description: 'User ID' })
|
|
117
|
+
}),
|
|
118
|
+
response: {
|
|
119
|
+
200: GetUserResponseSchema,
|
|
120
|
+
400: ErrorResponseSchema,
|
|
121
|
+
404: ErrorResponseSchema
|
|
39
122
|
}
|
|
40
123
|
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
124
|
+
|
|
125
|
+
// POST /users - Create new user
|
|
126
|
+
.post('/', async ({ body, set }) => {
|
|
127
|
+
// Validate required fields
|
|
128
|
+
if (!body.name || !body.email) {
|
|
129
|
+
set.status = 400
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: 'Nome e email são obrigatórios'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Validate name length
|
|
137
|
+
if (body.name.length < 2) {
|
|
138
|
+
set.status = 400
|
|
139
|
+
return {
|
|
140
|
+
success: false,
|
|
141
|
+
error: 'Nome deve ter pelo menos 2 caracteres'
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Validate email format
|
|
146
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
147
|
+
if (!emailRegex.test(body.email)) {
|
|
46
148
|
set.status = 400
|
|
47
|
-
return {
|
|
48
|
-
success: false,
|
|
49
|
-
error:
|
|
50
|
-
details: error instanceof Error ? error.message : 'Unknown error'
|
|
149
|
+
return {
|
|
150
|
+
success: false,
|
|
151
|
+
error: 'Email inválido'
|
|
51
152
|
}
|
|
52
153
|
}
|
|
154
|
+
|
|
155
|
+
const result = await UsersController.createUser(body)
|
|
156
|
+
|
|
157
|
+
// If email is duplicate, still return 200 but with success: false
|
|
158
|
+
if (!result.success) {
|
|
159
|
+
return result
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return result
|
|
53
163
|
}, {
|
|
54
|
-
body: t.Object({
|
|
55
|
-
name: t.String({ minLength: 2 }),
|
|
56
|
-
email: t.String({ format: "email" })
|
|
57
|
-
}),
|
|
58
|
-
response: t.Object({
|
|
59
|
-
success: t.Boolean(),
|
|
60
|
-
user: t.Optional(t.Object({
|
|
61
|
-
id: t.Number(),
|
|
62
|
-
name: t.String(),
|
|
63
|
-
email: t.String(),
|
|
64
|
-
createdAt: t.Date()
|
|
65
|
-
})),
|
|
66
|
-
message: t.Optional(t.String())
|
|
67
|
-
}),
|
|
68
164
|
detail: {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
165
|
+
summary: 'Create New User',
|
|
166
|
+
description: 'Creates a new user with name and email. Email must be unique.',
|
|
167
|
+
tags: ['Users', 'CRUD']
|
|
72
168
|
},
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
details: error.message
|
|
81
|
-
}
|
|
82
|
-
default:
|
|
83
|
-
set.status = 500
|
|
84
|
-
return {
|
|
85
|
-
success: false,
|
|
86
|
-
error: "Erro interno do servidor"
|
|
87
|
-
}
|
|
88
|
-
}
|
|
169
|
+
body: CreateUserRequestSchema,
|
|
170
|
+
response: {
|
|
171
|
+
200: CreateUserResponseSchema,
|
|
172
|
+
400: t.Object({
|
|
173
|
+
success: t.Literal(false),
|
|
174
|
+
error: t.String()
|
|
175
|
+
})
|
|
89
176
|
}
|
|
90
177
|
})
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
178
|
+
|
|
179
|
+
// DELETE /users/:id - Delete user
|
|
180
|
+
.delete('/:id', async ({ params, set }) => {
|
|
181
|
+
const id = parseInt(params.id)
|
|
182
|
+
|
|
183
|
+
if (isNaN(id)) {
|
|
184
|
+
set.status = 400
|
|
185
|
+
return {
|
|
186
|
+
success: false,
|
|
187
|
+
message: 'ID inválido'
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const result = await UsersController.deleteUser(id)
|
|
192
|
+
|
|
193
|
+
if (!result.success) {
|
|
194
|
+
// Don't set 404 status, just return success: false
|
|
195
|
+
return result
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return result
|
|
95
199
|
}, {
|
|
96
|
-
params: t.Object({
|
|
97
|
-
id: t.String()
|
|
98
|
-
}),
|
|
99
|
-
response: t.Object({
|
|
100
|
-
success: t.Boolean(),
|
|
101
|
-
user: t.Optional(t.Object({
|
|
102
|
-
id: t.Number(),
|
|
103
|
-
name: t.String(),
|
|
104
|
-
email: t.String(),
|
|
105
|
-
createdAt: t.Date()
|
|
106
|
-
})),
|
|
107
|
-
message: t.Optional(t.String())
|
|
108
|
-
}),
|
|
109
200
|
detail: {
|
|
110
|
-
tags: ['Users'],
|
|
111
201
|
summary: 'Delete User',
|
|
112
|
-
description: '
|
|
202
|
+
description: 'Deletes a user by their ID',
|
|
203
|
+
tags: ['Users', 'CRUD']
|
|
204
|
+
},
|
|
205
|
+
params: t.Object({
|
|
206
|
+
id: t.String({ description: 'User ID to delete' })
|
|
207
|
+
}),
|
|
208
|
+
response: {
|
|
209
|
+
200: DeleteUserResponseSchema,
|
|
210
|
+
400: t.Object({
|
|
211
|
+
success: t.Literal(false),
|
|
212
|
+
message: t.String()
|
|
213
|
+
})
|
|
113
214
|
}
|
|
114
|
-
})
|
|
215
|
+
})
|