create-fluxstack 1.5.4 → 1.7.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 (61) hide show
  1. package/README.md +172 -215
  2. package/app/client/src/App.tsx +45 -19
  3. package/app/client/src/components/FluxStackConfig.tsx +1 -1
  4. package/app/client/src/components/HybridLiveCounter.tsx +1 -1
  5. package/app/client/src/components/LiveClock.tsx +1 -1
  6. package/app/client/src/components/MainLayout.tsx +0 -2
  7. package/app/client/src/components/SidebarNavigation.tsx +1 -1
  8. package/app/client/src/components/SystemMonitor.tsx +16 -10
  9. package/app/client/src/components/UserProfile.tsx +1 -1
  10. package/app/server/live/FluxStackConfig.ts +2 -1
  11. package/app/server/live/LiveClockComponent.ts +8 -7
  12. package/app/server/live/SidebarNavigation.ts +2 -1
  13. package/app/server/live/SystemMonitor.ts +1 -0
  14. package/app/server/live/UserProfileComponent.ts +36 -30
  15. package/config/server.config.ts +1 -0
  16. package/core/cli/command-registry.ts +10 -10
  17. package/core/cli/commands/plugin-deps.ts +13 -5
  18. package/core/cli/plugin-discovery.ts +1 -1
  19. package/core/client/LiveComponentsProvider.tsx +414 -0
  20. package/core/client/hooks/useHybridLiveComponent.ts +194 -530
  21. package/core/client/index.ts +16 -0
  22. package/core/framework/server.ts +144 -63
  23. package/core/index.ts +4 -1
  24. package/core/plugins/built-in/monitoring/index.ts +1 -1
  25. package/core/plugins/built-in/static/index.ts +1 -1
  26. package/core/plugins/built-in/swagger/index.ts +1 -1
  27. package/core/plugins/built-in/vite/index.ts +1 -1
  28. package/core/plugins/config.ts +1 -1
  29. package/core/plugins/discovery.ts +1 -1
  30. package/core/plugins/executor.ts +1 -1
  31. package/core/plugins/index.ts +1 -0
  32. package/core/server/live/ComponentRegistry.ts +3 -1
  33. package/core/server/live/WebSocketConnectionManager.ts +14 -4
  34. package/core/server/live/websocket-plugin.ts +453 -434
  35. package/core/server/middleware/elysia-helpers.ts +3 -5
  36. package/core/server/plugins/database.ts +1 -1
  37. package/core/server/plugins/static-files-plugin.ts +1 -1
  38. package/core/types/index.ts +1 -1
  39. package/core/types/plugin.ts +1 -1
  40. package/core/types/types.ts +6 -2
  41. package/core/utils/logger/colors.ts +4 -4
  42. package/core/utils/logger/index.ts +37 -4
  43. package/core/utils/logger/winston-logger.ts +1 -1
  44. package/core/utils/sync-version.ts +61 -0
  45. package/core/utils/version.ts +6 -5
  46. package/create-fluxstack.ts +1 -1
  47. package/package.json +5 -3
  48. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +1 -1
  49. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  50. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +1 -1
  51. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +1 -1
  52. package/vite.config.ts +8 -0
  53. package/.dockerignore +0 -50
  54. package/CRYPTO-AUTH-MIDDLEWARE-GUIDE.md +0 -475
  55. package/CRYPTO-AUTH-MIDDLEWARES.md +0 -473
  56. package/CRYPTO-AUTH-USAGE.md +0 -491
  57. package/EXEMPLO-ROTA-PROTEGIDA.md +0 -347
  58. package/QUICK-START-CRYPTO-AUTH.md +0 -221
  59. package/app/client/src/components/Teste.tsx +0 -104
  60. package/app/server/live/TesteComponent.ts +0 -87
  61. package/test-crypto-auth.ts +0 -101
@@ -1,7 +1,7 @@
1
1
  // 🔥 System Monitor Dashboard Component
2
2
 
3
3
  import { useState } from 'react'
4
- import { useHybridLiveComponent } from 'fluxstack'
4
+ import { useHybridLiveComponent } from '@/core/client'
5
5
  import {
6
6
  FaServer,
7
7
  FaHome,
@@ -688,7 +688,9 @@ export function SystemMonitor() {
688
688
  gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
689
689
  gap: '1rem'
690
690
  }}>
691
- {Object.entries(state.componentsByType).map(([type, count]) => (
691
+ {Object.entries(state.componentsByType).map(([type, count]) => {
692
+ const countNum = count as number
693
+ return (
692
694
  <div key={type} style={{
693
695
  padding: '1.5rem',
694
696
  backgroundColor: '#f8fafc',
@@ -707,19 +709,20 @@ export function SystemMonitor() {
707
709
  margin: 0,
708
710
  fontSize: '2rem',
709
711
  fontWeight: 'bold',
710
- color: count > 0 ? '#10b981' : '#6b7280'
712
+ color: countNum > 0 ? '#10b981' : '#6b7280'
711
713
  }}>
712
- {count}
714
+ {countNum}
713
715
  </p>
714
716
  <p style={{
715
717
  margin: 0,
716
718
  fontSize: '0.9rem',
717
719
  color: '#6b7280'
718
720
  }}>
719
- {count === 1 ? 'instância' : 'instâncias'}
721
+ {countNum === 1 ? 'instância' : 'instâncias'}
720
722
  </p>
721
723
  </div>
722
- ))}
724
+ )
725
+ })}
723
726
  </div>
724
727
  </div>
725
728
 
@@ -747,7 +750,9 @@ export function SystemMonitor() {
747
750
  gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
748
751
  gap: '1rem'
749
752
  }}>
750
- {Object.entries(state.roomDetails).map(([room, count]) => (
753
+ {Object.entries(state.roomDetails).map(([room, count]) => {
754
+ const countNum = count as number
755
+ return (
751
756
  <div key={room} style={{
752
757
  padding: '1.5rem',
753
758
  backgroundColor: '#f0f9ff',
@@ -768,17 +773,18 @@ export function SystemMonitor() {
768
773
  fontWeight: 'bold',
769
774
  color: '#0284c7'
770
775
  }}>
771
- {count}
776
+ {countNum}
772
777
  </p>
773
778
  <p style={{
774
779
  margin: 0,
775
780
  fontSize: '0.9rem',
776
781
  color: '#0369a1'
777
782
  }}>
778
- {count === 1 ? 'componente' : 'componentes'}
783
+ {countNum === 1 ? 'componente' : 'componentes'}
779
784
  </p>
780
785
  </div>
781
- ))}
786
+ )
787
+ })}
782
788
  </div>
783
789
  ) : (
784
790
  <div style={{
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react';
2
- import { useHybridLiveComponent, useChunkedUpload } from 'fluxstack';
2
+ import { useHybridLiveComponent, useChunkedUpload } from '@/core/client';
3
3
  import {
4
4
  FaUser,
5
5
  FaEdit,
@@ -5,6 +5,7 @@ import { appConfig } from '@/config/app.config'
5
5
  import { serverConfig } from '@/config/server.config'
6
6
  import { loggerConfig } from '@/config/logger.config'
7
7
  import { systemConfig, systemRuntimeInfo } from '@/config/system.config'
8
+ import { FLUXSTACK_VERSION } from '@/core/utils/version'
8
9
 
9
10
  export interface FluxStackConfigState {
10
11
  // Environment Configuration
@@ -165,7 +166,7 @@ export class FluxStackConfig extends LiveComponent<FluxStackConfigState> {
165
166
 
166
167
  framework: {
167
168
  name: 'FluxStack',
168
- version: '1.5.4',
169
+ version: FLUXSTACK_VERSION,
169
170
  description: 'Modern Full-Stack TypeScript Framework with Live Components',
170
171
  author: 'FluxStack Team',
171
172
  license: 'MIT'
@@ -1,14 +1,15 @@
1
1
  // 🔥 LiveClock - Real-time Clock Live Component
2
+ // Automatically updates every second and broadcasts to all connected clients
2
3
  import { LiveComponent } from "@/core/types/types";
3
4
 
4
5
  interface LiveClockState {
5
- currentTime: string;
6
- timeZone: string;
7
- format: '12h' | '24h';
8
- showSeconds: boolean;
9
- showDate: boolean;
10
- lastSync: Date;
11
- serverUptime: number;
6
+ currentTime: string; // Formatted time string
7
+ timeZone: string; // IANA timezone (e.g., 'America/Sao_Paulo')
8
+ format: '12h' | '24h'; // Time format preference
9
+ showSeconds: boolean; // Toggle seconds display
10
+ showDate: boolean; // Toggle date display
11
+ lastSync: Date; // Last sync timestamp
12
+ serverUptime: number; // Server uptime in seconds
12
13
  }
13
14
 
14
15
  export class LiveClockComponent extends LiveComponent<LiveClockState> {
@@ -132,7 +132,8 @@ export class SidebarNavigation extends LiveComponent<SidebarNavigationState> {
132
132
  profile: 0,
133
133
  settings: 0,
134
134
  files: 0,
135
- analytics: 0
135
+ analytics: 0,
136
+ config: 0
136
137
  }
137
138
  })
138
139
 
@@ -63,6 +63,7 @@ export class SystemMonitor extends LiveComponent<SystemMonitorState> {
63
63
  private startTime = Date.now()
64
64
  private pushInterval = 1000 // Push every 1 second
65
65
  private isActive = true // Control flag for stopping all activities
66
+ private version = 1 // Component version
66
67
 
67
68
  constructor(initialState: SystemMonitorState, ws: any, options?: any) {
68
69
  super(initialState, ws, options)
@@ -1,3 +1,4 @@
1
+ // 🔥 User Profile - Live Component
1
2
  import { LiveComponent } from "@/core/types/types";
2
3
 
3
4
  interface UserProfileState {
@@ -12,7 +13,7 @@ interface UserProfileState {
12
13
  following: number;
13
14
  posts: number;
14
15
  isEditing: boolean;
15
- lastActivity: string;
16
+ lastUpdated: Date; // ✅ Padronizado para Date
16
17
  theme: 'light' | 'dark';
17
18
  notifications: number;
18
19
  }
@@ -21,7 +22,7 @@ export class UserProfileComponent extends LiveComponent<UserProfileState> {
21
22
  constructor(initialState: UserProfileState, ws: any, options?: { room?: string; userId?: string }) {
22
23
  const defaultState: UserProfileState = {
23
24
  name: "João Silva",
24
- email: "joao.silva@example.com",
25
+ email: "joao.silva@example.com",
25
26
  avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=150&h=150&fit=crop&crop=face",
26
27
  status: "online",
27
28
  bio: "Desenvolvedor Full-Stack apaixonado por tecnologia e inovação. Sempre em busca de novos desafios!",
@@ -31,7 +32,7 @@ export class UserProfileComponent extends LiveComponent<UserProfileState> {
31
32
  following: 567,
32
33
  posts: 89,
33
34
  isEditing: false,
34
- lastActivity: new Date().toISOString(),
35
+ lastUpdated: new Date(),
35
36
  theme: "light",
36
37
  notifications: 5,
37
38
  ...initialState
@@ -43,7 +44,7 @@ export class UserProfileComponent extends LiveComponent<UserProfileState> {
43
44
 
44
45
  async updateProfile(payload: { name?: string; bio?: string; location?: string }) {
45
46
  const updates: Partial<UserProfileState> = {
46
- lastActivity: new Date().toISOString()
47
+ lastUpdated: new Date()
47
48
  };
48
49
 
49
50
  if (payload.name) updates.name = payload.name;
@@ -59,53 +60,53 @@ export class UserProfileComponent extends LiveComponent<UserProfileState> {
59
60
  const statuses: UserProfileState['status'][] = ['online', 'away', 'busy', 'offline'];
60
61
  const currentIndex = statuses.indexOf(this.state.status);
61
62
  const nextStatus = statuses[(currentIndex + 1) % statuses.length];
62
-
63
- this.setState({
63
+
64
+ this.setState({
64
65
  status: nextStatus,
65
- lastActivity: new Date().toISOString()
66
+ lastUpdated: new Date()
66
67
  });
67
-
68
+
68
69
  console.log('👤 Status changed:', this.id, { from: this.state.status, to: nextStatus });
69
70
  return { success: true, newStatus: nextStatus };
70
71
  }
71
72
 
72
73
  async toggleTheme() {
73
74
  const newTheme = this.state.theme === 'light' ? 'dark' : 'light';
74
- this.setState({
75
+ this.setState({
75
76
  theme: newTheme,
76
- lastActivity: new Date().toISOString()
77
+ lastUpdated: new Date()
77
78
  });
78
-
79
+
79
80
  console.log('👤 Theme changed:', this.id, { to: newTheme });
80
81
  return { success: true, theme: newTheme };
81
82
  }
82
83
 
83
84
  async followUser() {
84
- this.setState({
85
+ this.setState({
85
86
  followers: this.state.followers + 1,
86
- lastActivity: new Date().toISOString()
87
+ lastUpdated: new Date()
87
88
  });
88
-
89
+
89
90
  console.log('👤 New follower:', this.id, { followers: this.state.followers + 1 });
90
91
  return { success: true, followers: this.state.followers };
91
92
  }
92
93
 
93
94
  async toggleEdit() {
94
- this.setState({
95
+ this.setState({
95
96
  isEditing: !this.state.isEditing,
96
- lastActivity: new Date().toISOString()
97
+ lastUpdated: new Date()
97
98
  });
98
-
99
+
99
100
  console.log('👤 Edit mode toggled:', this.id, { isEditing: !this.state.isEditing });
100
101
  return { success: true, isEditing: this.state.isEditing };
101
102
  }
102
103
 
103
104
  async clearNotifications() {
104
- this.setState({
105
+ this.setState({
105
106
  notifications: 0,
106
- lastActivity: new Date().toISOString()
107
+ lastUpdated: new Date()
107
108
  });
108
-
109
+
109
110
  console.log('👤 Notifications cleared:', this.id);
110
111
  return { success: true };
111
112
  }
@@ -115,21 +116,26 @@ export class UserProfileComponent extends LiveComponent<UserProfileState> {
115
116
  throw new Error('Invalid image URL');
116
117
  }
117
118
 
118
- // Update avatar URL - in a real app, you might want to validate the URL format
119
- this.setState({
119
+ this.setState({
120
120
  avatar: payload.imageUrl,
121
- lastActivity: new Date().toISOString()
121
+ lastUpdated: new Date()
122
122
  });
123
-
124
- console.log('👤 Avatar updated:', this.id, {
123
+
124
+ console.log('👤 Avatar updated:', this.id, {
125
125
  newAvatar: payload.imageUrl,
126
- previousAvatar: this.state.avatar
126
+ previousAvatar: this.state.avatar
127
127
  });
128
-
129
- return {
130
- success: true,
128
+
129
+ return {
130
+ success: true,
131
131
  avatar: payload.imageUrl,
132
- message: 'Avatar updated successfully!'
132
+ message: 'Avatar updated successfully!'
133
133
  };
134
134
  }
135
+
136
+ // Override destroy for cleanup
137
+ public destroy() {
138
+ console.log(`🗑️ UserProfile component ${this.id} destroyed`)
139
+ super.destroy()
140
+ }
135
141
  }
@@ -35,6 +35,7 @@ const serverConfigSchema = {
35
35
  enableSwagger: config.boolean('ENABLE_SWAGGER', true),
36
36
  enableMetrics: config.boolean('ENABLE_METRICS', false),
37
37
  enableMonitoring: config.boolean('ENABLE_MONITORING', false),
38
+ enableRequestLogging: config.boolean('ENABLE_REQUEST_LOGGING', true),
38
39
 
39
40
  // Vite/Development
40
41
  enableViteProxyLogs: config.boolean('ENABLE_VITE_PROXY_LOGS', false)
@@ -14,13 +14,13 @@ export class CliCommandRegistry {
14
14
  this.context = {
15
15
  config,
16
16
  logger: {
17
- debug: (message: string, meta?: any) => logger.debug(message, meta),
18
- info: (message: string, meta?: any) => logger.info(message, meta),
19
- warn: (message: string, meta?: any) => logger.warn(message, meta),
20
- error: (message: string, meta?: any) => logger.error(message, meta),
21
- child: (context: any) => (logger as any).child(context),
22
- time: (label: string) => (logger as any).time(label),
23
- timeEnd: (label: string) => (logger as any).timeEnd(label),
17
+ debug: (message: string, meta?: unknown) => logger.debug(message, meta),
18
+ info: (message: string, meta?: unknown) => logger.info(message, meta),
19
+ warn: (message: string, meta?: unknown) => logger.warn(message, meta),
20
+ error: (message: string, meta?: unknown) => logger.error(message, meta),
21
+ child: (context: Record<string, unknown>) => logger,
22
+ time: (label: string) => logger.time(label),
23
+ timeEnd: (label: string) => logger.timeEnd(label),
24
24
  request: (method: string, path: string, status?: number, duration?: number) =>
25
25
  logger.request(method, path, status, duration)
26
26
  },
@@ -34,18 +34,18 @@ export class CliCommandRegistry {
34
34
  const crypto = require('crypto')
35
35
  return crypto.createHash('sha256').update(data).digest('hex')
36
36
  },
37
- deepMerge: (target: any, source: any) => {
37
+ deepMerge: (target: Record<string, unknown>, source: Record<string, unknown>) => {
38
38
  const result = { ...target }
39
39
  for (const key in source) {
40
40
  if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
41
- result[key] = this.context.utils.deepMerge(result[key] || {}, source[key])
41
+ result[key] = this.context.utils.deepMerge(result[key] as Record<string, unknown> || {}, source[key] as Record<string, unknown>)
42
42
  } else {
43
43
  result[key] = source[key]
44
44
  }
45
45
  }
46
46
  return result
47
47
  },
48
- validateSchema: (_data: any, _schema: any) => {
48
+ validateSchema: (_data: unknown, _schema: unknown) => {
49
49
  try {
50
50
  return { valid: true, errors: [] }
51
51
  } catch (error) {
@@ -242,20 +242,28 @@ function findPluginDirectory(pluginName: string): string | null {
242
242
  return null
243
243
  }
244
244
 
245
- function createConsoleLogger() {
245
+ interface ConsoleLogger {
246
+ debug: (msg: string, meta?: unknown) => void
247
+ info: (msg: string, meta?: unknown) => void
248
+ warn: (msg: string, meta?: unknown) => void
249
+ error: (msg: string, meta?: unknown) => void
250
+ child: () => ConsoleLogger
251
+ }
252
+
253
+ function createConsoleLogger(): ConsoleLogger {
246
254
  return {
247
- debug: (msg: string, meta?: any) => {
255
+ debug: (msg: string, meta?: unknown) => {
248
256
  if (process.env.DEBUG) {
249
257
  console.log(chalk.gray(`[DEBUG] ${msg}`), meta || '')
250
258
  }
251
259
  },
252
- info: (msg: string, meta?: any) => {
260
+ info: (msg: string, meta?: unknown) => {
253
261
  console.log(chalk.blue(`[INFO] ${msg}`), meta || '')
254
262
  },
255
- warn: (msg: string, meta?: any) => {
263
+ warn: (msg: string, meta?: unknown) => {
256
264
  console.log(chalk.yellow(`[WARN] ${msg}`), meta || '')
257
265
  },
258
- error: (msg: string, meta?: any) => {
266
+ error: (msg: string, meta?: unknown) => {
259
267
  console.log(chalk.red(`[ERROR] ${msg}`), meta || '')
260
268
  },
261
269
  child: () => createConsoleLogger()
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'fs'
2
2
  import { join } from 'path'
3
- import type { Plugin } from '../plugins/types'
3
+ import type { FluxStack } from '../plugins/types'
4
4
  import { cliRegistry } from './command-registry'
5
5
  import { logger } from '../utils/logger'
6
6