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
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Zustand Setup for FluxStack
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
Add Zustand to your project:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Using npm
|
|
9
|
+
npm install zustand
|
|
10
|
+
|
|
11
|
+
# Using yarn
|
|
12
|
+
yarn add zustand
|
|
13
|
+
|
|
14
|
+
# Using pnpm
|
|
15
|
+
pnpm add zustand
|
|
16
|
+
|
|
17
|
+
# Using bun
|
|
18
|
+
bun add zustand
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Package.json Dependencies
|
|
22
|
+
|
|
23
|
+
Add to your `package.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"zustand": "^4.4.7"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## TypeScript Support
|
|
34
|
+
|
|
35
|
+
Zustand has built-in TypeScript support, no additional packages needed.
|
|
36
|
+
|
|
37
|
+
## Optional: DevTools Integration
|
|
38
|
+
|
|
39
|
+
For Redux DevTools integration (already included in our stores):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# No additional packages needed - works out of the box
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Middleware
|
|
46
|
+
|
|
47
|
+
Our stores already use the `persist` middleware. Other useful middleware:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# For more advanced middleware (optional)
|
|
51
|
+
npm install immer # For immutable updates
|
|
52
|
+
npm install zustand-middleware-yjs # For collaborative editing
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Ready to Use
|
|
56
|
+
|
|
57
|
+
The FluxStack template already includes:
|
|
58
|
+
- ✅ User authentication store
|
|
59
|
+
- ✅ UI state store
|
|
60
|
+
- ✅ Persistence middleware
|
|
61
|
+
- ✅ DevTools integration
|
|
62
|
+
- ✅ Utility hooks
|
|
63
|
+
- ✅ TypeScript support
|
|
64
|
+
|
|
65
|
+
Just start using the stores in your components!
|
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import type { User, CreateUserRequest, UserResponse } from '../types'
|
|
2
|
-
|
|
3
|
-
let users: User[] = [
|
|
4
|
-
{ id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
|
|
5
|
-
{ id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
|
|
6
|
-
]
|
|
7
|
-
|
|
8
|
-
export class UsersController {
|
|
9
|
-
static async getUsers() {
|
|
10
|
-
return { users }
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static resetForTesting() {
|
|
14
|
-
users.splice(0, users.length)
|
|
15
|
-
users.push(
|
|
16
|
-
{ id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
|
|
17
|
-
{ id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
|
|
18
|
-
)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static async createUser(userData: CreateUserRequest): Promise<UserResponse> {
|
|
22
|
-
const existingUser = users.find(u => u.email === userData.email)
|
|
23
|
-
|
|
24
|
-
if (existingUser) {
|
|
25
|
-
return {
|
|
26
|
-
success: false,
|
|
27
|
-
message: "Email já está em uso"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const newUser: User = {
|
|
32
|
-
id: Date.now(),
|
|
33
|
-
name: userData.name,
|
|
34
|
-
email: userData.email,
|
|
35
|
-
createdAt: new Date()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
users.push(newUser)
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
success: true,
|
|
42
|
-
user: newUser
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
static async getUserById(id: number) {
|
|
47
|
-
const user = users.find(u => u.id === id)
|
|
48
|
-
return user ? { user } : null
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
static async deleteUser(id: number): Promise<UserResponse> {
|
|
52
|
-
const userIndex = users.findIndex(u => u.id === id)
|
|
53
|
-
|
|
54
|
-
if (userIndex === -1) {
|
|
55
|
-
return {
|
|
56
|
-
success: false,
|
|
57
|
-
message: "Usuário não encontrado"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const deletedUser = users.splice(userIndex, 1)[0]
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
success: true,
|
|
65
|
-
user: deletedUser,
|
|
66
|
-
message: "Usuário deletado com sucesso"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
import type { User, CreateUserRequest, UserResponse } from '../types'
|
|
2
|
+
|
|
3
|
+
let users: User[] = [
|
|
4
|
+
{ id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
|
|
5
|
+
{ id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
export class UsersController {
|
|
9
|
+
static async getUsers() {
|
|
10
|
+
return { users }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static resetForTesting() {
|
|
14
|
+
users.splice(0, users.length)
|
|
15
|
+
users.push(
|
|
16
|
+
{ id: 1, name: "João", email: "joao@example.com", createdAt: new Date() },
|
|
17
|
+
{ id: 2, name: "Maria", email: "maria@example.com", createdAt: new Date() }
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static async createUser(userData: CreateUserRequest): Promise<UserResponse> {
|
|
22
|
+
const existingUser = users.find(u => u.email === userData.email)
|
|
23
|
+
|
|
24
|
+
if (existingUser) {
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
message: "Email já está em uso"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const newUser: User = {
|
|
32
|
+
id: Date.now(),
|
|
33
|
+
name: userData.name,
|
|
34
|
+
email: userData.email,
|
|
35
|
+
createdAt: new Date()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
users.push(newUser)
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
user: newUser
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static async getUserById(id: number) {
|
|
47
|
+
const user = users.find(u => u.id === id)
|
|
48
|
+
return user ? { user } : null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static async deleteUser(id: number): Promise<UserResponse> {
|
|
52
|
+
const userIndex = users.findIndex(u => u.id === id)
|
|
53
|
+
|
|
54
|
+
if (userIndex === -1) {
|
|
55
|
+
return {
|
|
56
|
+
success: false,
|
|
57
|
+
message: "Usuário não encontrado"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const deletedUser = users.splice(userIndex, 1)[0]
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
success: true,
|
|
65
|
+
user: deletedUser,
|
|
66
|
+
message: "Usuário deletado com sucesso"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
69
|
}
|
package/app/server/index.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// User application entry point
|
|
2
|
-
import { FluxStackFramework, loggerPlugin, vitePlugin, swaggerPlugin, staticPlugin } from "@/core/server"
|
|
2
|
+
import { FluxStackFramework, loggerPlugin, vitePlugin, swaggerPlugin, staticPlugin, liveComponentsPlugin, staticFilesPlugin } from "@/core/server"
|
|
3
3
|
import { isDevelopment } from "@/core/utils/helpers"
|
|
4
4
|
import { apiRoutes } from "./routes"
|
|
5
5
|
// Import sistema de env dinâmico simplificado
|
|
6
6
|
import { env, helpers } from "@/core/utils/env-runtime-v2"
|
|
7
|
+
// Import live components registration
|
|
8
|
+
import "./live/register-components"
|
|
7
9
|
|
|
8
10
|
console.log('🔧 Loading dynamic environment configuration...')
|
|
9
11
|
console.log(`📊 Environment: ${env.NODE_ENV}`) // Direto!
|
|
@@ -52,6 +54,10 @@ if (isDevelopment()) {
|
|
|
52
54
|
} else {
|
|
53
55
|
app.use(staticPlugin)
|
|
54
56
|
}
|
|
57
|
+
|
|
58
|
+
// Add static files AFTER Vite to avoid conflicts, but BEFORE Live Components
|
|
59
|
+
app.use(staticFilesPlugin) // Add Static Files support
|
|
60
|
+
app.use(liveComponentsPlugin) // Add Live Components support
|
|
55
61
|
|
|
56
62
|
|
|
57
63
|
// Adicionar rota de teste para mostrar env dinâmico (antes das rotas)
|
|
@@ -100,5 +106,7 @@ app.listen(() => {
|
|
|
100
106
|
console.log('💡 Mude as env vars e reinicie para ver a diferença!')
|
|
101
107
|
})
|
|
102
108
|
|
|
109
|
+
|
|
110
|
+
|
|
103
111
|
// Exportar tipo da aplicação para Eden Treaty (método correto)
|
|
104
112
|
export type App = typeof app
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// 🔥 Example Live Component - Counter
|
|
2
|
+
|
|
3
|
+
import { LiveComponent } from "../../../core/types/types"
|
|
4
|
+
|
|
5
|
+
interface CounterState {
|
|
6
|
+
count: number
|
|
7
|
+
title: string
|
|
8
|
+
step: number
|
|
9
|
+
history: number[]
|
|
10
|
+
lastUpdated: Date
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class CounterComponent extends LiveComponent<CounterState> {
|
|
14
|
+
|
|
15
|
+
constructor(initialState: CounterState, ws: any, options?: { room?: string; userId?: string }) {
|
|
16
|
+
super(initialState, ws, options)
|
|
17
|
+
|
|
18
|
+
// Ensure history is initialized
|
|
19
|
+
if (!this.state.history) {
|
|
20
|
+
this.state.history = []
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Log component creation
|
|
24
|
+
console.log(`🔢 Counter component created: ${this.id}`, {
|
|
25
|
+
initialState,
|
|
26
|
+
room: options?.room,
|
|
27
|
+
userId: options?.userId
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Action: Increment counter
|
|
32
|
+
async increment(amount: number = 1) {
|
|
33
|
+
const newCount = this.state.count + amount
|
|
34
|
+
const newHistory = [...this.state.history, newCount]
|
|
35
|
+
|
|
36
|
+
this.setState({
|
|
37
|
+
count: newCount,
|
|
38
|
+
history: newHistory.slice(-10), // Keep last 10 values
|
|
39
|
+
lastUpdated: new Date()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Broadcast to room if in multi-user mode
|
|
43
|
+
if (this.room) {
|
|
44
|
+
this.broadcast('COUNTER_INCREMENTED', {
|
|
45
|
+
count: newCount,
|
|
46
|
+
amount,
|
|
47
|
+
userId: this.userId
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log(`🔢 Counter incremented to ${newCount} (step: ${amount})`)
|
|
52
|
+
return { success: true, count: newCount }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Action: Decrement counter
|
|
56
|
+
async decrement(amount: number = 1) {
|
|
57
|
+
const newCount = Math.max(0, this.state.count - amount)
|
|
58
|
+
const newHistory = [...this.state.history, newCount]
|
|
59
|
+
|
|
60
|
+
this.setState({
|
|
61
|
+
count: newCount,
|
|
62
|
+
history: newHistory.slice(-10),
|
|
63
|
+
lastUpdated: new Date()
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
if (this.room) {
|
|
67
|
+
this.broadcast('COUNTER_DECREMENTED', {
|
|
68
|
+
count: newCount,
|
|
69
|
+
amount,
|
|
70
|
+
userId: this.userId
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
console.log(`🔢 Counter decremented to ${newCount} (step: ${amount})`)
|
|
75
|
+
return { success: true, count: newCount }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Action: Reset counter
|
|
79
|
+
async reset() {
|
|
80
|
+
this.setState({
|
|
81
|
+
count: 0,
|
|
82
|
+
history: [0],
|
|
83
|
+
lastUpdated: new Date()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
if (this.room) {
|
|
87
|
+
this.broadcast('COUNTER_RESET', {
|
|
88
|
+
userId: this.userId
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`🔢 Counter reset`)
|
|
93
|
+
return { success: true, count: 0 }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Action: Set step size
|
|
97
|
+
async setStep(step: number) {
|
|
98
|
+
this.setState({
|
|
99
|
+
step: Math.max(1, step),
|
|
100
|
+
lastUpdated: new Date()
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
console.log(`🔢 Counter step set to ${step}`)
|
|
104
|
+
return { success: true, step }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Action: Update title
|
|
108
|
+
async updateTitle(data: { title: string }) {
|
|
109
|
+
const newTitle = data.title.trim()
|
|
110
|
+
|
|
111
|
+
// Validate title
|
|
112
|
+
if (!newTitle || newTitle.length > 50) {
|
|
113
|
+
throw new Error('Title must be 1-50 characters')
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.setState({
|
|
117
|
+
title: newTitle,
|
|
118
|
+
lastUpdated: new Date()
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
console.log(`📝 Title updated to: "${newTitle}"`)
|
|
122
|
+
return { success: true, title: newTitle }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Action: Set title
|
|
126
|
+
async setTitle(title: string) {
|
|
127
|
+
this.setState({
|
|
128
|
+
title: title.substring(0, 50), // Max 50 chars
|
|
129
|
+
lastUpdated: new Date()
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
console.log(`🔢 Counter title set to "${title}"`)
|
|
133
|
+
return { success: true, title }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Action: Bulk update
|
|
137
|
+
async bulkUpdate(updates: { count?: number; title?: string; step?: number }) {
|
|
138
|
+
const newState: Partial<CounterState> = {
|
|
139
|
+
lastUpdated: new Date()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (updates.count !== undefined) {
|
|
143
|
+
newState.count = Math.max(0, updates.count)
|
|
144
|
+
newState.history = [...this.state.history, updates.count].slice(-10)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (updates.title !== undefined) {
|
|
148
|
+
newState.title = updates.title.substring(0, 50)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (updates.step !== undefined) {
|
|
152
|
+
newState.step = Math.max(1, updates.step)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
this.setState(newState)
|
|
156
|
+
|
|
157
|
+
if (this.room) {
|
|
158
|
+
this.broadcast('COUNTER_BULK_UPDATE', {
|
|
159
|
+
updates: newState,
|
|
160
|
+
userId: this.userId
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(`🔢 Counter bulk updated`, updates)
|
|
165
|
+
return { success: true, updates: newState }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Get computed properties
|
|
169
|
+
async getStats() {
|
|
170
|
+
const { count, history, step } = this.state
|
|
171
|
+
|
|
172
|
+
const stats = {
|
|
173
|
+
current: count,
|
|
174
|
+
min: Math.min(...history),
|
|
175
|
+
max: Math.max(...history),
|
|
176
|
+
average: history.reduce((a, b) => a + b, 0) / history.length,
|
|
177
|
+
step,
|
|
178
|
+
historyLength: history.length,
|
|
179
|
+
canIncrement: true,
|
|
180
|
+
canDecrement: count > 0
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return { success: true, stats }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Override destroy for cleanup
|
|
187
|
+
public destroy() {
|
|
188
|
+
console.log(`🗑️ Counter component ${this.id} destroyed`)
|
|
189
|
+
super.destroy()
|
|
190
|
+
}
|
|
191
|
+
}
|