create-fluxstack 1.15.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/LLMD/INDEX.md +4 -3
  3. package/LLMD/resources/live-binary-delta.md +507 -0
  4. package/LLMD/resources/live-components.md +1 -0
  5. package/LLMD/resources/live-rooms.md +731 -333
  6. package/app/client/src/App.tsx +23 -14
  7. package/app/client/src/components/AppLayout.tsx +4 -4
  8. package/app/client/src/live/AuthDemo.tsx +4 -4
  9. package/app/client/src/live/PingPongDemo.tsx +199 -0
  10. package/app/client/src/live/RoomChatDemo.tsx +187 -22
  11. package/app/client/src/live/SharedCounterDemo.tsx +142 -0
  12. package/app/server/live/LivePingPong.ts +61 -0
  13. package/app/server/live/LiveRoomChat.ts +106 -38
  14. package/app/server/live/LiveSharedCounter.ts +73 -0
  15. package/app/server/live/rooms/ChatRoom.ts +68 -0
  16. package/app/server/live/rooms/CounterRoom.ts +51 -0
  17. package/app/server/live/rooms/DirectoryRoom.ts +42 -0
  18. package/app/server/live/rooms/PingRoom.ts +40 -0
  19. package/core/build/bundler.ts +40 -26
  20. package/core/build/flux-plugins-generator.ts +325 -325
  21. package/core/build/index.ts +92 -21
  22. package/core/cli/command-registry.ts +44 -46
  23. package/core/cli/commands/build.ts +11 -6
  24. package/core/cli/commands/create.ts +7 -5
  25. package/core/cli/commands/dev.ts +6 -5
  26. package/core/cli/commands/help.ts +3 -2
  27. package/core/cli/commands/make-plugin.ts +8 -7
  28. package/core/cli/commands/plugin-add.ts +60 -43
  29. package/core/cli/commands/plugin-deps.ts +73 -57
  30. package/core/cli/commands/plugin-list.ts +44 -41
  31. package/core/cli/commands/plugin-remove.ts +33 -22
  32. package/core/cli/generators/component.ts +770 -769
  33. package/core/cli/generators/controller.ts +9 -8
  34. package/core/cli/generators/index.ts +148 -146
  35. package/core/cli/generators/interactive.ts +228 -227
  36. package/core/cli/generators/plugin.ts +11 -10
  37. package/core/cli/generators/prompts.ts +83 -82
  38. package/core/cli/generators/route.ts +7 -6
  39. package/core/cli/generators/service.ts +10 -9
  40. package/core/cli/generators/template-engine.ts +2 -1
  41. package/core/cli/generators/types.ts +7 -7
  42. package/core/cli/generators/utils.ts +191 -191
  43. package/core/cli/index.ts +9 -8
  44. package/core/cli/plugin-discovery.ts +2 -2
  45. package/core/client/hooks/useAuth.ts +48 -48
  46. package/core/client/index.ts +0 -16
  47. package/core/client/standalone.ts +18 -17
  48. package/core/client/state/createStore.ts +192 -192
  49. package/core/client/state/index.ts +14 -14
  50. package/core/config/index.ts +1 -0
  51. package/core/framework/client.ts +131 -131
  52. package/core/framework/index.ts +7 -7
  53. package/core/framework/server.ts +72 -112
  54. package/core/framework/types.ts +2 -2
  55. package/core/plugins/built-in/live-components/commands/create-live-component.ts +6 -3
  56. package/core/plugins/built-in/monitoring/index.ts +110 -68
  57. package/core/plugins/built-in/static/index.ts +2 -2
  58. package/core/plugins/built-in/swagger/index.ts +9 -9
  59. package/core/plugins/built-in/vite/index.ts +3 -3
  60. package/core/plugins/built-in/vite/vite-dev.ts +3 -3
  61. package/core/plugins/config.ts +50 -47
  62. package/core/plugins/discovery.ts +10 -4
  63. package/core/plugins/executor.ts +2 -2
  64. package/core/plugins/index.ts +206 -203
  65. package/core/plugins/manager.ts +21 -20
  66. package/core/plugins/registry.ts +76 -12
  67. package/core/plugins/types.ts +14 -14
  68. package/core/server/framework.ts +3 -189
  69. package/core/server/live/auto-generated-components.ts +11 -35
  70. package/core/server/live/index.ts +41 -36
  71. package/core/server/live/websocket-plugin.ts +48 -3
  72. package/core/server/middleware/elysia-helpers.ts +16 -15
  73. package/core/server/middleware/errorHandling.ts +14 -14
  74. package/core/server/middleware/index.ts +31 -31
  75. package/core/server/plugins/database.ts +181 -180
  76. package/core/server/plugins/static-files-plugin.ts +4 -3
  77. package/core/server/plugins/swagger.ts +11 -8
  78. package/core/server/rooms/RoomBroadcaster.ts +11 -10
  79. package/core/server/rooms/RoomSystem.ts +14 -11
  80. package/core/server/services/BaseService.ts +7 -7
  81. package/core/server/services/ServiceContainer.ts +5 -5
  82. package/core/server/services/index.ts +8 -8
  83. package/core/templates/create-project.ts +28 -27
  84. package/core/testing/index.ts +9 -9
  85. package/core/testing/setup.ts +73 -73
  86. package/core/types/api.ts +168 -168
  87. package/core/types/config.ts +5 -5
  88. package/core/types/index.ts +1 -1
  89. package/core/types/plugin.ts +2 -2
  90. package/core/types/types.ts +3 -3
  91. package/core/utils/build-logger.ts +324 -324
  92. package/core/utils/config-schema.ts +480 -480
  93. package/core/utils/env.ts +10 -8
  94. package/core/utils/errors/codes.ts +114 -114
  95. package/core/utils/errors/handlers.ts +30 -20
  96. package/core/utils/errors/index.ts +54 -46
  97. package/core/utils/errors/middleware.ts +113 -113
  98. package/core/utils/helpers.ts +19 -16
  99. package/core/utils/logger/colors.ts +114 -114
  100. package/core/utils/logger/config.ts +2 -2
  101. package/core/utils/logger/formatter.ts +82 -82
  102. package/core/utils/logger/group-logger.ts +101 -101
  103. package/core/utils/logger/index.ts +13 -3
  104. package/core/utils/logger/startup-banner.ts +2 -2
  105. package/core/utils/logger/winston-logger.ts +152 -152
  106. package/core/utils/monitoring/index.ts +211 -211
  107. package/core/utils/sync-version.ts +67 -66
  108. package/core/utils/version.ts +1 -1
  109. package/package.json +11 -6
  110. package/playwright-report/index.html +85 -0
  111. package/playwright.config.ts +31 -0
  112. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  113. package/plugins/crypto-auth/client/components/index.ts +11 -11
  114. package/plugins/crypto-auth/client/index.ts +11 -11
  115. package/plugins/crypto-auth/package.json +65 -65
  116. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  117. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +6 -5
  118. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +6 -5
  119. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +3 -3
  120. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  121. package/plugins/crypto-auth/server/middlewares.ts +19 -19
  122. package/tsconfig.json +4 -1
  123. package/vite.config.ts +13 -0
  124. package/app/client/.live-stubs/LiveAdminPanel.js +0 -5
  125. package/app/client/.live-stubs/LiveChat.js +0 -7
  126. package/app/client/.live-stubs/LiveCounter.js +0 -9
  127. package/app/client/.live-stubs/LiveForm.js +0 -11
  128. package/app/client/.live-stubs/LiveLocalCounter.js +0 -8
  129. package/app/client/.live-stubs/LiveRoomChat.js +0 -10
  130. package/app/client/.live-stubs/LiveTodoList.js +0 -9
  131. package/app/client/.live-stubs/LiveUpload.js +0 -15
  132. package/app/client/src/live/ChatDemo.tsx +0 -107
  133. package/app/client/src/live/LiveDebuggerPanel.tsx +0 -779
  134. package/app/client/src/live/TodoListDemo.tsx +0 -158
  135. package/app/server/live/LiveChat.ts +0 -78
  136. package/app/server/live/LiveTodoList.ts +0 -110
  137. package/app/server/live/register-components.ts +0 -19
  138. package/core/build/live-components-generator.ts +0 -312
  139. package/core/client/components/LiveDebugger.tsx +0 -1324
  140. package/core/live/ComponentRegistry.ts +0 -403
  141. package/core/live/types.ts +0 -241
  142. package/workspace.json +0 -6
@@ -1,181 +1,182 @@
1
- import type { FluxStack, PluginContext, CliCommand, Plugin } from "../../plugins/types"
2
-
3
- // Database plugin with CLI commands
4
- export const databasePlugin: Plugin = {
5
- name: "database",
6
- description: "Database management plugin with CLI commands",
7
- author: "FluxStack Team",
8
- category: "data",
9
-
10
- setup: (context: PluginContext) => {
11
- context.logger.info("Database plugin initialized")
12
- },
13
-
14
- commands: [
15
- {
16
- name: "migrate",
17
- description: "Run database migrations",
18
- category: "Database",
19
- usage: "flux database:migrate [options]",
20
- examples: [
21
- "flux database:migrate # Run all pending migrations",
22
- "flux database:migrate --rollback # Rollback last migration",
23
- "flux database:migrate --to 001 # Migrate to specific version"
24
- ],
25
- options: [
26
- {
27
- name: "rollback",
28
- short: "r",
29
- description: "Rollback the last migration",
30
- type: "boolean"
31
- },
32
- {
33
- name: "to",
34
- description: "Migrate to specific version",
35
- type: "string"
36
- },
37
- {
38
- name: "dry-run",
39
- description: "Show what would be migrated without executing",
40
- type: "boolean"
41
- }
42
- ],
43
- handler: async (args, options, context) => {
44
- if (options["dry-run"]) {
45
- console.log("🔍 Dry run mode - showing planned migrations:")
46
- }
47
-
48
- if (options.rollback) {
49
- console.log("⬇️ Rolling back last migration...")
50
- // Simulate rollback
51
- await new Promise(resolve => setTimeout(resolve, 1000))
52
- console.log("✅ Rollback completed")
53
- } else if (options.to) {
54
- console.log(`📈 Migrating to version: ${options.to}`)
55
- // Simulate migration to version
56
- await new Promise(resolve => setTimeout(resolve, 1500))
57
- console.log(`✅ Migrated to version ${options.to}`)
58
- } else {
59
- console.log("📈 Running all pending migrations...")
60
- // Simulate migration
61
- await new Promise(resolve => setTimeout(resolve, 2000))
62
- console.log("✅ All migrations completed")
63
- }
64
- }
65
- },
66
- {
67
- name: "seed",
68
- description: "Seed the database with initial data",
69
- category: "Database",
70
- usage: "flux database:seed [seeder]",
71
- examples: [
72
- "flux database:seed # Run all seeders",
73
- "flux database:seed users # Run specific seeder"
74
- ],
75
- arguments: [
76
- {
77
- name: "seeder",
78
- description: "Specific seeder to run",
79
- required: false,
80
- type: "string"
81
- }
82
- ],
83
- options: [
84
- {
85
- name: "force",
86
- short: "f",
87
- description: "Force seeding even if data exists",
88
- type: "boolean"
89
- }
90
- ],
91
- handler: async (args, options, context) => {
92
- const [seeder] = args
93
-
94
- if (seeder) {
95
- console.log(`🌱 Running seeder: ${seeder}`)
96
- console.log(` Force mode: ${options.force ? 'ON' : 'OFF'}`)
97
- } else {
98
- console.log("🌱 Running all seeders...")
99
- }
100
-
101
- // Simulate seeding
102
- await new Promise(resolve => setTimeout(resolve, 1500))
103
- console.log("✅ Database seeded successfully")
104
- }
105
- },
106
- {
107
- name: "reset",
108
- description: "Reset the database (drop all tables and recreate)",
109
- category: "Database",
110
- usage: "flux database:reset [options]",
111
- examples: [
112
- "flux database:reset # Reset and migrate",
113
- "flux database:reset --seed # Reset, migrate and seed"
114
- ],
115
- options: [
116
- {
117
- name: "seed",
118
- short: "s",
119
- description: "Run seeders after reset",
120
- type: "boolean"
121
- },
122
- {
123
- name: "confirm",
124
- description: "Skip confirmation prompt",
125
- type: "boolean"
126
- }
127
- ],
128
- handler: async (args, options, context) => {
129
- if (!options.confirm) {
130
- console.log("⚠️ WARNING: This will delete all data in the database!")
131
- console.log("Use --confirm to skip this prompt.")
132
- return
133
- }
134
-
135
- console.log("🗑️ Dropping all tables...")
136
- await new Promise(resolve => setTimeout(resolve, 1000))
137
-
138
- console.log("📈 Running migrations...")
139
- await new Promise(resolve => setTimeout(resolve, 1500))
140
-
141
- if (options.seed) {
142
- console.log("🌱 Running seeders...")
143
- await new Promise(resolve => setTimeout(resolve, 1000))
144
- }
145
-
146
- console.log("✅ Database reset completed")
147
- }
148
- },
149
- {
150
- name: "status",
151
- description: "Show database migration status",
152
- category: "Database",
153
- aliases: ["info"],
154
- handler: async (args, options, context) => {
155
- console.log("📊 Database Status:")
156
- console.log("------------------")
157
- console.log("Connected: ✅ Yes")
158
- console.log("Tables: 15")
159
- console.log("Last migration: 2024_01_15_create_users_table")
160
- console.log("Pending migrations: 2")
161
- console.log("Database size: 2.3 MB")
162
- }
163
- }
164
- ]
165
- }
166
-
167
- // Utility functions that could be used by the plugin
168
- export async function runMigration(version?: string): Promise<void> {
169
- // Actual migration logic would go here
170
- console.log(`Running migration ${version || 'all'}`)
171
- }
172
-
173
- export async function rollbackMigration(): Promise<void> {
174
- // Actual rollback logic would go here
175
- console.log("Rolling back migration")
176
- }
177
-
178
- export async function seedDatabase(seeder?: string): Promise<void> {
179
- // Actual seeding logic would go here
180
- console.log(`Seeding database ${seeder || 'all'}`)
1
+ import type { FluxStack, PluginContext, CliCommand, Plugin } from "../../plugins/types"
2
+ import { logger } from "@core/utils/logger"
3
+
4
+ // Database plugin with CLI commands
5
+ export const databasePlugin: Plugin = {
6
+ name: "database",
7
+ description: "Database management plugin with CLI commands",
8
+ author: "FluxStack Team",
9
+ category: "data",
10
+
11
+ setup: (context: PluginContext) => {
12
+ context.logger.info("Database plugin initialized")
13
+ },
14
+
15
+ commands: [
16
+ {
17
+ name: "migrate",
18
+ description: "Run database migrations",
19
+ category: "Database",
20
+ usage: "flux database:migrate [options]",
21
+ examples: [
22
+ "flux database:migrate # Run all pending migrations",
23
+ "flux database:migrate --rollback # Rollback last migration",
24
+ "flux database:migrate --to 001 # Migrate to specific version"
25
+ ],
26
+ options: [
27
+ {
28
+ name: "rollback",
29
+ short: "r",
30
+ description: "Rollback the last migration",
31
+ type: "boolean"
32
+ },
33
+ {
34
+ name: "to",
35
+ description: "Migrate to specific version",
36
+ type: "string"
37
+ },
38
+ {
39
+ name: "dry-run",
40
+ description: "Show what would be migrated without executing",
41
+ type: "boolean"
42
+ }
43
+ ],
44
+ handler: async (args, options, context) => {
45
+ if (options["dry-run"]) {
46
+ logger.info("Dry run mode - showing planned migrations:")
47
+ }
48
+
49
+ if (options.rollback) {
50
+ logger.info("Rolling back last migration...")
51
+ // Simulate rollback
52
+ await new Promise(resolve => setTimeout(resolve, 1000))
53
+ logger.info("Rollback completed")
54
+ } else if (options.to) {
55
+ logger.info(`Migrating to version: ${options.to}`)
56
+ // Simulate migration to version
57
+ await new Promise(resolve => setTimeout(resolve, 1500))
58
+ logger.info(`Migrated to version ${options.to}`)
59
+ } else {
60
+ logger.info("Running all pending migrations...")
61
+ // Simulate migration
62
+ await new Promise(resolve => setTimeout(resolve, 2000))
63
+ logger.info("All migrations completed")
64
+ }
65
+ }
66
+ },
67
+ {
68
+ name: "seed",
69
+ description: "Seed the database with initial data",
70
+ category: "Database",
71
+ usage: "flux database:seed [seeder]",
72
+ examples: [
73
+ "flux database:seed # Run all seeders",
74
+ "flux database:seed users # Run specific seeder"
75
+ ],
76
+ arguments: [
77
+ {
78
+ name: "seeder",
79
+ description: "Specific seeder to run",
80
+ required: false,
81
+ type: "string"
82
+ }
83
+ ],
84
+ options: [
85
+ {
86
+ name: "force",
87
+ short: "f",
88
+ description: "Force seeding even if data exists",
89
+ type: "boolean"
90
+ }
91
+ ],
92
+ handler: async (args, options, context) => {
93
+ const [seeder] = args
94
+
95
+ if (seeder) {
96
+ logger.info(`Running seeder: ${seeder}`)
97
+ logger.info(` Force mode: ${options.force ? 'ON' : 'OFF'}`)
98
+ } else {
99
+ logger.info("Running all seeders...")
100
+ }
101
+
102
+ // Simulate seeding
103
+ await new Promise(resolve => setTimeout(resolve, 1500))
104
+ logger.info("Database seeded successfully")
105
+ }
106
+ },
107
+ {
108
+ name: "reset",
109
+ description: "Reset the database (drop all tables and recreate)",
110
+ category: "Database",
111
+ usage: "flux database:reset [options]",
112
+ examples: [
113
+ "flux database:reset # Reset and migrate",
114
+ "flux database:reset --seed # Reset, migrate and seed"
115
+ ],
116
+ options: [
117
+ {
118
+ name: "seed",
119
+ short: "s",
120
+ description: "Run seeders after reset",
121
+ type: "boolean"
122
+ },
123
+ {
124
+ name: "confirm",
125
+ description: "Skip confirmation prompt",
126
+ type: "boolean"
127
+ }
128
+ ],
129
+ handler: async (args, options, context) => {
130
+ if (!options.confirm) {
131
+ logger.warn("WARNING: This will delete all data in the database!")
132
+ logger.info("Use --confirm to skip this prompt.")
133
+ return
134
+ }
135
+
136
+ logger.info("Dropping all tables...")
137
+ await new Promise(resolve => setTimeout(resolve, 1000))
138
+
139
+ logger.info("Running migrations...")
140
+ await new Promise(resolve => setTimeout(resolve, 1500))
141
+
142
+ if (options.seed) {
143
+ logger.info("Running seeders...")
144
+ await new Promise(resolve => setTimeout(resolve, 1000))
145
+ }
146
+
147
+ logger.info("Database reset completed")
148
+ }
149
+ },
150
+ {
151
+ name: "status",
152
+ description: "Show database migration status",
153
+ category: "Database",
154
+ aliases: ["info"],
155
+ handler: async (args, options, context) => {
156
+ logger.info("Database Status:")
157
+ logger.info("------------------")
158
+ logger.info("Connected: Yes")
159
+ logger.info("Tables: 15")
160
+ logger.info("Last migration: 2024_01_15_create_users_table")
161
+ logger.info("Pending migrations: 2")
162
+ logger.info("Database size: 2.3 MB")
163
+ }
164
+ }
165
+ ]
166
+ }
167
+
168
+ // Utility functions that could be used by the plugin
169
+ export async function runMigration(version?: string): Promise<void> {
170
+ // Actual migration logic would go here
171
+ logger.info(`Running migration ${version || 'all'}`)
172
+ }
173
+
174
+ export async function rollbackMigration(): Promise<void> {
175
+ // Actual rollback logic would go here
176
+ logger.info("Rolling back migration")
177
+ }
178
+
179
+ export async function seedDatabase(seeder?: string): Promise<void> {
180
+ // Actual seeding logic would go here
181
+ logger.info(`Seeding database ${seeder || 'all'}`)
181
182
  }
@@ -76,7 +76,7 @@ export const staticFilesPlugin: Plugin = {
76
76
  const enableUploads = pluginsConfig.staticEnableUploads
77
77
 
78
78
  // Async handler — uses Bun.file() APIs instead of Node fs
79
- const serveFile = (baseDir: string, isUpload: boolean) => async ({ params, set, request }: any) => {
79
+ const serveFile = (baseDir: string, isUpload: boolean) => async ({ params, set, request }: { params: Record<string, string>; set: { status: number; headers: Record<string, string> }; request: Request }) => {
80
80
  const requestedPath: string = params['*'] || ''
81
81
 
82
82
  // Reject null bytes early — prevents filesystem confusion
@@ -155,15 +155,16 @@ export const staticFilesPlugin: Plugin = {
155
155
  }
156
156
 
157
157
  // Register routes based on config flags
158
+ const app = context.app as import('elysia').Elysia
158
159
  if (enablePublic) {
159
160
  await mkdir(publicDir, { recursive: true })
160
- context.app.get('/api/static/*', serveFile(publicDir, false))
161
+ app.get('/api/static/*', serveFile(publicDir, false) as never)
161
162
  context.logger.debug('Static public files route registered: /api/static/*')
162
163
  }
163
164
 
164
165
  if (enableUploads) {
165
166
  await mkdir(uploadsDir, { recursive: true })
166
- context.app.get('/api/uploads/*', serveFile(uploadsDir, true))
167
+ app.get('/api/uploads/*', serveFile(uploadsDir, true) as never)
167
168
  context.logger.debug('Static uploads route registered: /api/uploads/*')
168
169
  }
169
170
 
@@ -4,7 +4,10 @@ import type { Plugin, PluginContext } from '@core/plugins/types'
4
4
  export const swaggerPlugin: Plugin = {
5
5
  name: 'swagger',
6
6
  setup(context: PluginContext) {
7
- context.app.use(swagger({
7
+ const app = context.app as import('elysia').Elysia
8
+ const config = context.config as Record<string, unknown>
9
+ const server = config.server as Record<string, unknown> | undefined
10
+ app.use(swagger({
8
11
  path: '/swagger',
9
12
  documentation: {
10
13
  info: {
@@ -13,18 +16,18 @@ export const swaggerPlugin: Plugin = {
13
16
  description: 'Modern full-stack TypeScript framework with type-safe API endpoints'
14
17
  },
15
18
  tags: [
16
- {
17
- name: 'Health',
18
- description: 'Health check endpoints'
19
+ {
20
+ name: 'Health',
21
+ description: 'Health check endpoints'
19
22
  },
20
- {
21
- name: 'Users',
22
- description: 'User management endpoints'
23
+ {
24
+ name: 'Users',
25
+ description: 'User management endpoints'
23
26
  }
24
27
  ],
25
28
  servers: [
26
29
  {
27
- url: `http://localhost:${context.config.server?.port || 3000}`,
30
+ url: `http://localhost:${server?.port || 3000}`,
28
31
  description: 'Development server'
29
32
  }
30
33
  ]
@@ -2,6 +2,7 @@
2
2
 
3
3
  import type { ServerWebSocket } from 'bun'
4
4
  import type { Room, RoomSystem, SystemEvents } from './RoomSystem'
5
+ import { logger } from "@core/utils/logger"
5
6
 
6
7
  type WebSocketLike = {
7
8
  send: (data: string) => void
@@ -19,12 +20,12 @@ interface BroadcastMessage {
19
20
  type: 'room:event' | 'room:state' | 'room:system'
20
21
  roomId: string
21
22
  event: string
22
- data: any
23
+ data: unknown
23
24
  timestamp: number
24
25
  senderId?: string
25
26
  }
26
27
 
27
- export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
28
+ export class RoomBroadcaster<TState, TEvents extends Record<string, unknown>> {
28
29
  private connections = new Map<string, RoomConnection>()
29
30
  private roomConnections = new Map<string, Set<string>>() // roomId -> connectionIds
30
31
  private roomSystem: RoomSystem<TState, TEvents>
@@ -156,7 +157,7 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
156
157
  broadcast(
157
158
  roomId: string,
158
159
  event: string,
159
- data: any,
160
+ data: unknown,
160
161
  options?: { exclude?: string | string[] }
161
162
  ): number {
162
163
  const roomConns = this.roomConnections.get(roomId)
@@ -200,7 +201,7 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
200
201
  /**
201
202
  * Envia evento do sistema para todos na sala
202
203
  */
203
- broadcastSystem(roomId: string, event: string, data: any): number {
204
+ broadcastSystem(roomId: string, event: string, data: unknown): number {
204
205
  const roomConns = this.roomConnections.get(roomId)
205
206
  if (!roomConns || roomConns.size === 0) return 0
206
207
 
@@ -238,7 +239,7 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
238
239
  connection.ws.send(JSON.stringify(message))
239
240
  return true
240
241
  } catch (error) {
241
- console.error(`[RoomBroadcaster] Error sending to ${connectionId}:`, error)
242
+ logger.error(`[RoomBroadcaster] Error sending to ${connectionId}:`, error)
242
243
  return false
243
244
  }
244
245
  }
@@ -246,7 +247,7 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
246
247
  /**
247
248
  * Envia para um usuário específico (todas as conexões do usuário)
248
249
  */
249
- sendToUser(userId: string, roomId: string, event: string, data: any): number {
250
+ sendToUser(userId: string, roomId: string, event: string, data: unknown): number {
250
251
  let sent = 0
251
252
 
252
253
  for (const [connId, conn] of this.connections) {
@@ -277,15 +278,15 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
277
278
  roomId: string,
278
279
  initialState: TState,
279
280
  connectionId?: string
280
- ): Room<TState, TEvents> & { broadcastEmit: (event: keyof TEvents, data: any) => void } {
281
+ ): Room<TState, TEvents> & { broadcastEmit: <K extends keyof TEvents>(event: K, data: TEvents[K]) => void } {
281
282
  const room = this.roomSystem.getOrCreate(roomId, initialState)
282
283
 
283
284
  // Adicionar método de broadcast
284
285
  const enhanced = room as Room<TState, TEvents> & {
285
- broadcastEmit: (event: keyof TEvents, data: any) => void
286
+ broadcastEmit: <K extends keyof TEvents>(event: K, data: TEvents[K]) => void
286
287
  }
287
288
 
288
- enhanced.broadcastEmit = (event: keyof TEvents, data: any) => {
289
+ enhanced.broadcastEmit = <K extends keyof TEvents>(event: K, data: TEvents[K]) => {
289
290
  // Emitir localmente
290
291
  room.emit(event, data)
291
292
  // Broadcast via WebSocket
@@ -347,7 +348,7 @@ export class RoomBroadcaster<TState, TEvents extends Record<string, any>> {
347
348
 
348
349
  // Factory
349
350
  export function createRoomBroadcaster<
350
- TDef extends { state: any; events: Record<string, any> }
351
+ TDef extends { state: unknown; events: Record<string, unknown> }
351
352
  >(
352
353
  roomSystem: RoomSystem<TDef['state'], TDef['events']>
353
354
  ): RoomBroadcaster<TDef['state'], TDef['events']> {
@@ -1,5 +1,8 @@
1
1
  // 🔥 FluxStack Room System - Pub/Sub tipado para comunicação entre componentes
2
2
 
3
+ import { logger } from "@core/utils/logger"
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- default `any` needed for contravariant handler storage
3
6
  type EventHandler<T = any> = (data: T) => void
4
7
  type Unsubscribe = () => void
5
8
 
@@ -9,7 +12,7 @@ export type SystemEvents<TState> = {
9
12
  '$room:destroyed': { roomId: string; reason: 'manual' | 'empty' | 'ttl'; finalState: TState }
10
13
  '$sub:join': { subscriberId: string; event: string; count: number }
11
14
  '$sub:leave': { subscriberId: string; event: string; count: number }
12
- '$state:change': { path?: string; oldValue: any; newValue: any }
15
+ '$state:change': { path?: string; oldValue: unknown; newValue: unknown }
13
16
  '$state:reset': { oldState: TState; newState: TState }
14
17
  '$error': { error: Error; context: string }
15
18
  }
@@ -25,7 +28,7 @@ interface Subscription {
25
28
  }
26
29
 
27
30
  // Room instance
28
- export class Room<TState, TEvents extends Record<string, any>> {
31
+ export class Room<TState, TEvents extends Record<string, unknown>> {
29
32
  public readonly id: string
30
33
  public readonly createdAt: number
31
34
 
@@ -36,12 +39,12 @@ export class Room<TState, TEvents extends Record<string, any>> {
36
39
  private destroyed = false
37
40
 
38
41
  // Callback para notificar o sistema global
39
- private onSystemEvent?: (event: string, data: any) => void
42
+ private onSystemEvent?: (event: string, data: unknown) => void
40
43
 
41
44
  constructor(
42
45
  id: string,
43
46
  initialState: TState,
44
- onSystemEvent?: (event: string, data: any) => void
47
+ onSystemEvent?: (event: string, data: unknown) => void
45
48
  ) {
46
49
  this.id = id
47
50
  this.createdAt = Date.now()
@@ -167,7 +170,7 @@ export class Room<TState, TEvents extends Record<string, any>> {
167
170
  this.onSystemEvent?.(event as string, { roomId: this.id, ...data })
168
171
  }
169
172
 
170
- private emitInternal(event: string, data: any): number {
173
+ private emitInternal(event: string, data: unknown): number {
171
174
  const subs = this.subscriptions.get(event)
172
175
  if (!subs || subs.size === 0) return 0
173
176
 
@@ -177,7 +180,7 @@ export class Room<TState, TEvents extends Record<string, any>> {
177
180
  sub.handler(data)
178
181
  notified++
179
182
  } catch (error) {
180
- console.error(`[Room:${this.id}] Error in handler for '${event}':`, error)
183
+ logger.error(`[Room:${this.id}] Error in handler for '${event}':`, error)
181
184
  this.emitSystem('$error', {
182
185
  error: error as Error,
183
186
  context: `Handler for event '${event}'`
@@ -242,7 +245,7 @@ export interface RoomSystemOptions {
242
245
  defaultTTL?: number // TTL padrão para salas
243
246
  }
244
247
 
245
- export class RoomSystem<TState, TEvents extends Record<string, any>> {
248
+ export class RoomSystem<TState, TEvents extends Record<string, unknown>> {
246
249
  public readonly name: string
247
250
  private rooms = new Map<string, Room<TState, TEvents>>()
248
251
  private globalSubscriptions = new Map<string, Set<EventHandler>>()
@@ -383,11 +386,11 @@ export class RoomSystem<TState, TEvents extends Record<string, any>> {
383
386
  }
384
387
  }
385
388
 
386
- private handleSystemEvent(event: string, data: any): void {
389
+ private handleSystemEvent(event: string, data: unknown): void {
387
390
  this.emitGlobal(event, data)
388
391
  }
389
392
 
390
- private emitGlobal(event: string, data: any): void {
393
+ private emitGlobal(event: string, data: unknown): void {
391
394
  const handlers = this.globalSubscriptions.get(event)
392
395
  if (!handlers) return
393
396
 
@@ -395,7 +398,7 @@ export class RoomSystem<TState, TEvents extends Record<string, any>> {
395
398
  try {
396
399
  handler(data)
397
400
  } catch (error) {
398
- console.error(`[RoomSystem:${this.name}] Error in global handler for '${event}':`, error)
401
+ logger.error(`[RoomSystem:${this.name}] Error in global handler for '${event}':`, error)
399
402
  }
400
403
  }
401
404
  }
@@ -448,7 +451,7 @@ export class RoomSystem<TState, TEvents extends Record<string, any>> {
448
451
  // ============================================
449
452
 
450
453
  export function createRoomSystem<
451
- TDef extends { state: any; events: Record<string, any> }
454
+ TDef extends { state: unknown; events: Record<string, unknown> }
452
455
  >(
453
456
  name: string,
454
457
  options?: RoomSystemOptions