create-fluxstack 1.0.13 → 1.0.14
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 +46 -2
- 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
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// 🔥 System Monitor Integration - Auto-capture metrics from Live Components
|
|
2
|
+
|
|
3
|
+
import { componentRegistry } from '../../../core/server/live/ComponentRegistry'
|
|
4
|
+
|
|
5
|
+
export class SystemMonitorIntegration {
|
|
6
|
+
private static instance: SystemMonitorIntegration | null = null
|
|
7
|
+
private systemMonitorId: string | null = null
|
|
8
|
+
|
|
9
|
+
private constructor() {
|
|
10
|
+
this.setupHooks()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public static getInstance(): SystemMonitorIntegration {
|
|
14
|
+
if (!SystemMonitorIntegration.instance) {
|
|
15
|
+
SystemMonitorIntegration.instance = new SystemMonitorIntegration()
|
|
16
|
+
}
|
|
17
|
+
return SystemMonitorIntegration.instance
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Set the system monitor component ID
|
|
21
|
+
public setSystemMonitorId(componentId: string) {
|
|
22
|
+
this.systemMonitorId = componentId
|
|
23
|
+
console.log(`📊 SystemMonitor integration activated: ${componentId}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Get system monitor component
|
|
27
|
+
private getSystemMonitor() {
|
|
28
|
+
if (!this.systemMonitorId) return null
|
|
29
|
+
return componentRegistry.getComponent(this.systemMonitorId)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Setup hooks to capture Live Component events
|
|
33
|
+
private setupHooks() {
|
|
34
|
+
// Override the original mountComponent method
|
|
35
|
+
const originalMountComponent = componentRegistry.mountComponent.bind(componentRegistry)
|
|
36
|
+
componentRegistry.mountComponent = async (...args) => {
|
|
37
|
+
const result = await originalMountComponent(...args)
|
|
38
|
+
|
|
39
|
+
// Record connection event
|
|
40
|
+
this.recordConnection(args[1], 'connected')
|
|
41
|
+
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Override the original unmountComponent method
|
|
46
|
+
const originalUnmountComponent = componentRegistry.unmountComponent.bind(componentRegistry)
|
|
47
|
+
componentRegistry.unmountComponent = async (componentId) => {
|
|
48
|
+
const component = componentRegistry.getComponent(componentId)
|
|
49
|
+
const componentType = component?.constructor.name || 'Unknown'
|
|
50
|
+
|
|
51
|
+
await originalUnmountComponent(componentId)
|
|
52
|
+
|
|
53
|
+
// Record disconnection event
|
|
54
|
+
this.recordConnection(componentType, 'disconnected')
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Override the original rehydrateComponent method
|
|
58
|
+
const originalRehydrateComponent = componentRegistry.rehydrateComponent.bind(componentRegistry)
|
|
59
|
+
componentRegistry.rehydrateComponent = async (...args) => {
|
|
60
|
+
const result = await originalRehydrateComponent(...args)
|
|
61
|
+
|
|
62
|
+
if (result.success) {
|
|
63
|
+
// Record rehydration event
|
|
64
|
+
this.recordConnection(args[1], 'rehydrated')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return result
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Override the original executeAction method
|
|
71
|
+
const originalExecuteAction = componentRegistry.executeAction.bind(componentRegistry)
|
|
72
|
+
componentRegistry.executeAction = async (componentId, action, payload) => {
|
|
73
|
+
const startTime = Date.now()
|
|
74
|
+
let success = false
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const result = await originalExecuteAction(componentId, action, payload)
|
|
78
|
+
success = true
|
|
79
|
+
return result
|
|
80
|
+
} catch (error) {
|
|
81
|
+
success = false
|
|
82
|
+
throw error
|
|
83
|
+
} finally {
|
|
84
|
+
const responseTime = Date.now() - startTime
|
|
85
|
+
|
|
86
|
+
// Record message event
|
|
87
|
+
this.recordMessage(action, componentId, success, responseTime)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log('🔗 SystemMonitor integration hooks setup completed')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Record a connection event
|
|
95
|
+
private recordConnection(componentType: string, status: 'connected' | 'disconnected' | 'rehydrated') {
|
|
96
|
+
const monitor = this.getSystemMonitor()
|
|
97
|
+
if (!monitor) return
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
monitor.executeAction('recordConnection', {
|
|
101
|
+
componentType,
|
|
102
|
+
status
|
|
103
|
+
}).catch(error => {
|
|
104
|
+
console.warn('⚠️ Failed to record connection event:', error.message)
|
|
105
|
+
})
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.warn('⚠️ Error recording connection event:', error)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Record a message event
|
|
112
|
+
private recordMessage(type: string, componentId: string, success: boolean, responseTime?: number) {
|
|
113
|
+
const monitor = this.getSystemMonitor()
|
|
114
|
+
if (!monitor) return
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
monitor.executeAction('recordMessage', {
|
|
118
|
+
type,
|
|
119
|
+
componentId,
|
|
120
|
+
success,
|
|
121
|
+
responseTime
|
|
122
|
+
}).catch(error => {
|
|
123
|
+
console.warn('⚠️ Failed to record message event:', error.message)
|
|
124
|
+
})
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.warn('⚠️ Error recording message event:', error)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Manually trigger metrics collection for all monitors
|
|
131
|
+
public triggerMetricsCollection() {
|
|
132
|
+
const monitor = this.getSystemMonitor()
|
|
133
|
+
if (!monitor) return
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
monitor.executeAction('collectMetrics', {}).catch(error => {
|
|
137
|
+
console.warn('⚠️ Failed to trigger metrics collection:', error.message)
|
|
138
|
+
})
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.warn('⚠️ Error triggering metrics collection:', error)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Get current system stats
|
|
145
|
+
public getSystemStats() {
|
|
146
|
+
return componentRegistry.getStats()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Export singleton instance
|
|
151
|
+
export const systemMonitorIntegration = SystemMonitorIntegration.getInstance()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// 🔥 Teste - Live Component
|
|
2
|
+
import { LiveComponent } from "@/core/types/types";
|
|
3
|
+
|
|
4
|
+
interface TesteState {
|
|
5
|
+
message: string;
|
|
6
|
+
count: number;
|
|
7
|
+
lastUpdated: Date;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class TesteComponent extends LiveComponent<TesteState> {
|
|
11
|
+
constructor(initialState: TesteState, ws: any, options?: { room?: string; userId?: string }) {
|
|
12
|
+
super({
|
|
13
|
+
message: "Hello from Teste!",
|
|
14
|
+
count: 0,
|
|
15
|
+
lastUpdated: new Date(),
|
|
16
|
+
...initialState
|
|
17
|
+
}, ws, options);
|
|
18
|
+
// Default room: testeroom
|
|
19
|
+
this.room = 'testeroom';
|
|
20
|
+
|
|
21
|
+
console.log(`🔥 ${this.constructor.name} component created: ${this.id}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async updateMessage(payload: { message: string }) {
|
|
25
|
+
const { message } = payload;
|
|
26
|
+
|
|
27
|
+
if (!message || message.trim().length === 0) {
|
|
28
|
+
throw new Error('Message cannot be empty');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.setState({
|
|
32
|
+
message: message.trim(),
|
|
33
|
+
lastUpdated: new Date()
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Broadcast to room if in multi-user mode
|
|
37
|
+
if (this.room) {
|
|
38
|
+
this.broadcast('MESSAGE_UPDATED', {
|
|
39
|
+
message: message.trim(),
|
|
40
|
+
userId: this.userId
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`📝 Message updated: "${message}"`);
|
|
45
|
+
return { success: true, message: message.trim() };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async incrementCounter() {
|
|
49
|
+
const newCount = this.state.count + 1;
|
|
50
|
+
|
|
51
|
+
this.setState({
|
|
52
|
+
count: newCount,
|
|
53
|
+
lastUpdated: new Date()
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (this.room) {
|
|
57
|
+
this.broadcast('COUNTER_INCREMENTED', {
|
|
58
|
+
count: newCount,
|
|
59
|
+
userId: this.userId
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { success: true, count: newCount };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async resetData() {
|
|
67
|
+
this.setState({
|
|
68
|
+
message: "Hello from Teste!",
|
|
69
|
+
count: 0,
|
|
70
|
+
lastUpdated: new Date()
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return { success: true };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async getData() {
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
data: {
|
|
80
|
+
...this.state,
|
|
81
|
+
componentId: this.id,
|
|
82
|
+
room: this.room,
|
|
83
|
+
userId: this.userId
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { LiveComponent } from "@/core/types/types";
|
|
2
|
+
|
|
3
|
+
interface UserProfileState {
|
|
4
|
+
name: string;
|
|
5
|
+
email: string;
|
|
6
|
+
avatar: string;
|
|
7
|
+
status: 'online' | 'away' | 'busy' | 'offline';
|
|
8
|
+
bio: string;
|
|
9
|
+
location: string;
|
|
10
|
+
joinedDate: string;
|
|
11
|
+
followers: number;
|
|
12
|
+
following: number;
|
|
13
|
+
posts: number;
|
|
14
|
+
isEditing: boolean;
|
|
15
|
+
lastActivity: string;
|
|
16
|
+
theme: 'light' | 'dark';
|
|
17
|
+
notifications: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class UserProfileComponent extends LiveComponent<UserProfileState> {
|
|
21
|
+
constructor(initialState: UserProfileState, ws: any, options?: { room?: string; userId?: string }) {
|
|
22
|
+
const defaultState: UserProfileState = {
|
|
23
|
+
name: "João Silva",
|
|
24
|
+
email: "joao.silva@example.com",
|
|
25
|
+
avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face",
|
|
26
|
+
status: "online",
|
|
27
|
+
bio: "Desenvolvedor Full-Stack apaixonado por tecnologia e inovação. Sempre em busca de novos desafios!",
|
|
28
|
+
location: "São Paulo, Brasil",
|
|
29
|
+
joinedDate: "Janeiro 2023",
|
|
30
|
+
followers: 1234,
|
|
31
|
+
following: 567,
|
|
32
|
+
posts: 89,
|
|
33
|
+
isEditing: false,
|
|
34
|
+
lastActivity: new Date().toISOString(),
|
|
35
|
+
theme: "light",
|
|
36
|
+
notifications: 5,
|
|
37
|
+
...initialState
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
super(defaultState, ws, options);
|
|
41
|
+
console.log('👤 UserProfile component created:', this.id, { initialState: defaultState });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async updateProfile(payload: { name?: string; bio?: string; location?: string }) {
|
|
45
|
+
const updates: Partial<UserProfileState> = {
|
|
46
|
+
lastActivity: new Date().toISOString()
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (payload.name) updates.name = payload.name;
|
|
50
|
+
if (payload.bio) updates.bio = payload.bio;
|
|
51
|
+
if (payload.location) updates.location = payload.location;
|
|
52
|
+
|
|
53
|
+
this.setState(updates);
|
|
54
|
+
console.log('👤 Profile updated:', this.id, updates);
|
|
55
|
+
return { success: true, updated: Object.keys(updates) };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async toggleStatus() {
|
|
59
|
+
const statuses: UserProfileState['status'][] = ['online', 'away', 'busy', 'offline'];
|
|
60
|
+
const currentIndex = statuses.indexOf(this.state.status);
|
|
61
|
+
const nextStatus = statuses[(currentIndex + 1) % statuses.length];
|
|
62
|
+
|
|
63
|
+
this.setState({
|
|
64
|
+
status: nextStatus,
|
|
65
|
+
lastActivity: new Date().toISOString()
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
console.log('👤 Status changed:', this.id, { from: this.state.status, to: nextStatus });
|
|
69
|
+
return { success: true, newStatus: nextStatus };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async toggleTheme() {
|
|
73
|
+
const newTheme = this.state.theme === 'light' ? 'dark' : 'light';
|
|
74
|
+
this.setState({
|
|
75
|
+
theme: newTheme,
|
|
76
|
+
lastActivity: new Date().toISOString()
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
console.log('👤 Theme changed:', this.id, { to: newTheme });
|
|
80
|
+
return { success: true, theme: newTheme };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async followUser() {
|
|
84
|
+
this.setState({
|
|
85
|
+
followers: this.state.followers + 1,
|
|
86
|
+
lastActivity: new Date().toISOString()
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log('👤 New follower:', this.id, { followers: this.state.followers + 1 });
|
|
90
|
+
return { success: true, followers: this.state.followers };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async toggleEdit() {
|
|
94
|
+
this.setState({
|
|
95
|
+
isEditing: !this.state.isEditing,
|
|
96
|
+
lastActivity: new Date().toISOString()
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log('👤 Edit mode toggled:', this.id, { isEditing: !this.state.isEditing });
|
|
100
|
+
return { success: true, isEditing: this.state.isEditing };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async clearNotifications() {
|
|
104
|
+
this.setState({
|
|
105
|
+
notifications: 0,
|
|
106
|
+
lastActivity: new Date().toISOString()
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
console.log('👤 Notifications cleared:', this.id);
|
|
110
|
+
return { success: true };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async updateAvatar(payload: { imageUrl: string }) {
|
|
114
|
+
if (!payload.imageUrl) {
|
|
115
|
+
throw new Error('Invalid image URL');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Update avatar URL - in a real app, you might want to validate the URL format
|
|
119
|
+
this.setState({
|
|
120
|
+
avatar: payload.imageUrl,
|
|
121
|
+
lastActivity: new Date().toISOString()
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log('👤 Avatar updated:', this.id, {
|
|
125
|
+
newAvatar: payload.imageUrl,
|
|
126
|
+
previousAvatar: this.state.avatar
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
avatar: payload.imageUrl,
|
|
132
|
+
message: 'Avatar updated successfully!'
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// 🔥 Register all live components
|
|
2
|
+
// NOTE: Components are now auto-discovered from this directory!
|
|
3
|
+
// Manual registration is optional for custom initial states
|
|
4
|
+
|
|
5
|
+
import { CounterComponent } from "./CounterComponent"
|
|
6
|
+
|
|
7
|
+
// Manual registration is now optional - components are auto-discovered
|
|
8
|
+
// Uncomment below for custom initial states:
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
import { componentRegistry } from "@/core/server/live/ComponentRegistry"
|
|
12
|
+
|
|
13
|
+
componentRegistry.registerComponent({
|
|
14
|
+
name: 'CounterComponent',
|
|
15
|
+
component: CounterComponent,
|
|
16
|
+
initialState: {
|
|
17
|
+
count: 0,
|
|
18
|
+
title: 'Live Counter',
|
|
19
|
+
step: 1,
|
|
20
|
+
history: [0],
|
|
21
|
+
lastUpdated: new Date()
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
console.log('📝 Live components registered successfully!')
|
|
27
|
+
|
|
28
|
+
export { CounterComponent }
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Middleware
|
|
3
|
+
* Handles user authentication and authorization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { Context } from 'elysia'
|
|
7
|
+
|
|
8
|
+
export interface AuthUser {
|
|
9
|
+
id: number
|
|
10
|
+
email: string
|
|
11
|
+
name: string
|
|
12
|
+
role: 'admin' | 'user'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AuthContext extends Context {
|
|
16
|
+
user?: AuthUser
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Authentication middleware
|
|
21
|
+
* Validates JWT tokens and sets user context
|
|
22
|
+
*/
|
|
23
|
+
export const authMiddleware = {
|
|
24
|
+
name: 'auth',
|
|
25
|
+
|
|
26
|
+
beforeHandle: async (context: AuthContext) => {
|
|
27
|
+
const authHeader = context.headers.authorization
|
|
28
|
+
|
|
29
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
30
|
+
return new Response(
|
|
31
|
+
JSON.stringify({ error: 'Missing or invalid authorization header' }),
|
|
32
|
+
{ status: 401, headers: { 'Content-Type': 'application/json' } }
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const token = authHeader.substring(7) // Remove 'Bearer ' prefix
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
// In a real application, you would validate the JWT token here
|
|
40
|
+
// For demo purposes, we'll simulate token validation
|
|
41
|
+
const user = await validateToken(token)
|
|
42
|
+
|
|
43
|
+
if (!user) {
|
|
44
|
+
return new Response(
|
|
45
|
+
JSON.stringify({ error: 'Invalid or expired token' }),
|
|
46
|
+
{ status: 401, headers: { 'Content-Type': 'application/json' } }
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Set user in context
|
|
51
|
+
context.user = user
|
|
52
|
+
} catch (error) {
|
|
53
|
+
return new Response(
|
|
54
|
+
JSON.stringify({ error: 'Token validation failed' }),
|
|
55
|
+
{ status: 401, headers: { 'Content-Type': 'application/json' } }
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Optional authentication middleware
|
|
63
|
+
* Sets user context if token is present, but doesn't require it
|
|
64
|
+
*/
|
|
65
|
+
export const optionalAuthMiddleware = {
|
|
66
|
+
name: 'optional-auth',
|
|
67
|
+
|
|
68
|
+
beforeHandle: async (context: AuthContext) => {
|
|
69
|
+
const authHeader = context.headers.authorization
|
|
70
|
+
|
|
71
|
+
if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
72
|
+
const token = authHeader.substring(7)
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const user = await validateToken(token)
|
|
76
|
+
if (user) {
|
|
77
|
+
context.user = user
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// Ignore errors for optional auth
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Role-based authorization middleware
|
|
88
|
+
*/
|
|
89
|
+
export const requireRole = (requiredRole: 'admin' | 'user') => ({
|
|
90
|
+
name: `require-${requiredRole}`,
|
|
91
|
+
|
|
92
|
+
beforeHandle: async (context: AuthContext) => {
|
|
93
|
+
if (!context.user) {
|
|
94
|
+
return new Response(
|
|
95
|
+
JSON.stringify({ error: 'Authentication required' }),
|
|
96
|
+
{ status: 401, headers: { 'Content-Type': 'application/json' } }
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (requiredRole === 'admin' && context.user.role !== 'admin') {
|
|
101
|
+
return new Response(
|
|
102
|
+
JSON.stringify({ error: 'Admin access required' }),
|
|
103
|
+
{ status: 403, headers: { 'Content-Type': 'application/json' } }
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Validate JWT token (mock implementation)
|
|
111
|
+
* In a real application, this would use a proper JWT library
|
|
112
|
+
*/
|
|
113
|
+
async function validateToken(token: string): Promise<AuthUser | null> {
|
|
114
|
+
// Mock token validation
|
|
115
|
+
// In reality, you would decode and verify the JWT
|
|
116
|
+
|
|
117
|
+
if (token === 'valid-admin-token') {
|
|
118
|
+
return {
|
|
119
|
+
id: 1,
|
|
120
|
+
email: 'admin@example.com',
|
|
121
|
+
name: 'Admin User',
|
|
122
|
+
role: 'admin'
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (token === 'valid-user-token') {
|
|
127
|
+
return {
|
|
128
|
+
id: 2,
|
|
129
|
+
email: 'user@example.com',
|
|
130
|
+
name: 'Regular User',
|
|
131
|
+
role: 'user'
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return null
|
|
136
|
+
}
|