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.
Files changed (214) hide show
  1. package/.env.example +29 -29
  2. package/app/client/README.md +69 -69
  3. package/app/client/index.html +14 -13
  4. package/app/client/src/App.tsx +157 -524
  5. package/app/client/src/components/ErrorBoundary.tsx +107 -0
  6. package/app/client/src/components/ErrorDisplay.css +365 -0
  7. package/app/client/src/components/ErrorDisplay.tsx +258 -0
  8. package/app/client/src/components/FluxStackConfig.tsx +1321 -0
  9. package/app/client/src/components/HybridLiveCounter.tsx +140 -0
  10. package/app/client/src/components/LiveClock.tsx +286 -0
  11. package/app/client/src/components/MainLayout.tsx +390 -0
  12. package/app/client/src/components/SidebarNavigation.tsx +391 -0
  13. package/app/client/src/components/StateDemo.tsx +178 -0
  14. package/app/client/src/components/SystemMonitor.tsx +1038 -0
  15. package/app/client/src/components/Teste.tsx +104 -0
  16. package/app/client/src/components/UserProfile.tsx +809 -0
  17. package/app/client/src/hooks/useAuth.ts +39 -0
  18. package/app/client/src/hooks/useNotifications.ts +56 -0
  19. package/app/client/src/lib/eden-api.ts +189 -53
  20. package/app/client/src/lib/errors.ts +340 -0
  21. package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
  22. package/app/client/src/lib/index.ts +45 -0
  23. package/app/client/src/main.tsx +3 -2
  24. package/app/client/src/pages/ApiDocs.tsx +182 -0
  25. package/app/client/src/pages/Demo.tsx +174 -0
  26. package/app/client/src/pages/HybridLive.tsx +263 -0
  27. package/app/client/src/pages/Overview.tsx +155 -0
  28. package/app/client/src/store/README.md +43 -0
  29. package/app/client/src/store/index.ts +16 -0
  30. package/app/client/src/store/slices/uiSlice.ts +151 -0
  31. package/app/client/src/store/slices/userSlice.ts +161 -0
  32. package/app/client/src/test/README.md +257 -0
  33. package/app/client/src/test/setup.ts +70 -0
  34. package/app/client/src/test/types.ts +12 -0
  35. package/app/client/src/vite-env.d.ts +1 -1
  36. package/app/client/tsconfig.app.json +44 -43
  37. package/app/client/tsconfig.json +7 -7
  38. package/app/client/tsconfig.node.json +25 -25
  39. package/app/client/zustand-setup.md +65 -0
  40. package/app/server/controllers/users.controller.ts +68 -68
  41. package/app/server/index.ts +9 -1
  42. package/app/server/live/CounterComponent.ts +191 -0
  43. package/app/server/live/FluxStackConfig.ts +529 -0
  44. package/app/server/live/LiveClockComponent.ts +214 -0
  45. package/app/server/live/SidebarNavigation.ts +156 -0
  46. package/app/server/live/SystemMonitor.ts +594 -0
  47. package/app/server/live/SystemMonitorIntegration.ts +151 -0
  48. package/app/server/live/TesteComponent.ts +87 -0
  49. package/app/server/live/UserProfileComponent.ts +135 -0
  50. package/app/server/live/register-components.ts +28 -0
  51. package/app/server/middleware/auth.ts +136 -0
  52. package/app/server/middleware/errorHandling.ts +250 -0
  53. package/app/server/middleware/index.ts +10 -0
  54. package/app/server/middleware/rateLimit.ts +193 -0
  55. package/app/server/middleware/requestLogging.ts +215 -0
  56. package/app/server/middleware/validation.ts +270 -0
  57. package/app/server/routes/index.ts +14 -2
  58. package/app/server/routes/upload.ts +92 -0
  59. package/app/server/routes/users.routes.ts +2 -9
  60. package/app/server/services/NotificationService.ts +302 -0
  61. package/app/server/services/UserService.ts +222 -0
  62. package/app/server/services/index.ts +46 -0
  63. package/core/cli/commands/plugin-deps.ts +263 -0
  64. package/core/cli/generators/README.md +339 -0
  65. package/core/cli/generators/component.ts +770 -0
  66. package/core/cli/generators/controller.ts +299 -0
  67. package/core/cli/generators/index.ts +144 -0
  68. package/core/cli/generators/interactive.ts +228 -0
  69. package/core/cli/generators/prompts.ts +83 -0
  70. package/core/cli/generators/route.ts +513 -0
  71. package/core/cli/generators/service.ts +465 -0
  72. package/core/cli/generators/template-engine.ts +154 -0
  73. package/core/cli/generators/types.ts +71 -0
  74. package/core/cli/generators/utils.ts +192 -0
  75. package/core/cli/index.ts +69 -0
  76. package/core/cli/plugin-discovery.ts +16 -85
  77. package/core/client/fluxstack.ts +17 -0
  78. package/core/client/hooks/index.ts +7 -0
  79. package/core/client/hooks/state-validator.ts +130 -0
  80. package/core/client/hooks/useAuth.ts +49 -0
  81. package/core/client/hooks/useChunkedUpload.ts +258 -0
  82. package/core/client/hooks/useHybridLiveComponent.ts +967 -0
  83. package/core/client/hooks/useWebSocket.ts +373 -0
  84. package/core/client/index.ts +47 -0
  85. package/core/client/state/createStore.ts +193 -0
  86. package/core/client/state/index.ts +15 -0
  87. package/core/config/env-dynamic.ts +1 -1
  88. package/core/config/env.ts +2 -1
  89. package/core/config/runtime-config.ts +3 -3
  90. package/core/config/schema.ts +84 -49
  91. package/core/framework/server.ts +30 -0
  92. package/core/index.ts +25 -0
  93. package/core/live/ComponentRegistry.ts +399 -0
  94. package/core/live/types.ts +164 -0
  95. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  96. package/core/plugins/built-in/live-components/index.ts +27 -0
  97. package/core/plugins/built-in/logger/index.ts +1 -1
  98. package/core/plugins/built-in/monitoring/index.ts +1 -1
  99. package/core/plugins/built-in/static/index.ts +1 -1
  100. package/core/plugins/built-in/swagger/index.ts +1 -1
  101. package/core/plugins/built-in/vite/index.ts +1 -1
  102. package/core/plugins/dependency-manager.ts +384 -0
  103. package/core/plugins/index.ts +5 -1
  104. package/core/plugins/manager.ts +7 -3
  105. package/core/plugins/registry.ts +88 -10
  106. package/core/plugins/types.ts +11 -11
  107. package/core/server/framework.ts +43 -0
  108. package/core/server/index.ts +11 -1
  109. package/core/server/live/ComponentRegistry.ts +1017 -0
  110. package/core/server/live/FileUploadManager.ts +272 -0
  111. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  112. package/core/server/live/SingleConnectionManager.ts +0 -0
  113. package/core/server/live/StateSignature.ts +644 -0
  114. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  115. package/core/server/live/websocket-plugin.ts +435 -0
  116. package/core/server/middleware/errorHandling.ts +141 -0
  117. package/core/server/middleware/index.ts +16 -0
  118. package/core/server/plugins/static-files-plugin.ts +232 -0
  119. package/core/server/services/BaseService.ts +95 -0
  120. package/core/server/services/ServiceContainer.ts +144 -0
  121. package/core/server/services/index.ts +9 -0
  122. package/core/templates/create-project.ts +196 -33
  123. package/core/testing/index.ts +10 -0
  124. package/core/testing/setup.ts +74 -0
  125. package/core/types/build.ts +38 -14
  126. package/core/types/types.ts +319 -0
  127. package/core/utils/env-runtime.ts +7 -0
  128. package/core/utils/errors/handlers.ts +264 -39
  129. package/core/utils/errors/index.ts +528 -18
  130. package/core/utils/errors/middleware.ts +114 -0
  131. package/core/utils/logger/formatters.ts +222 -0
  132. package/core/utils/logger/index.ts +167 -48
  133. package/core/utils/logger/middleware.ts +253 -0
  134. package/core/utils/logger/performance.ts +384 -0
  135. package/core/utils/logger/transports.ts +365 -0
  136. package/create-fluxstack.ts +296 -296
  137. package/fluxstack.config.ts +17 -1
  138. package/package-template.json +66 -66
  139. package/package.json +31 -6
  140. package/public/README.md +16 -0
  141. package/vite.config.ts +29 -14
  142. package/.claude/settings.local.json +0 -74
  143. package/.github/workflows/ci-build-tests.yml +0 -480
  144. package/.github/workflows/dependency-management.yml +0 -324
  145. package/.github/workflows/release-validation.yml +0 -355
  146. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  147. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  148. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  149. package/CLAUDE.md +0 -200
  150. package/Dockerfile +0 -58
  151. package/Dockerfile.backend +0 -52
  152. package/Dockerfile.frontend +0 -54
  153. package/README-Docker.md +0 -85
  154. package/ai-context/00-QUICK-START.md +0 -86
  155. package/ai-context/README.md +0 -88
  156. package/ai-context/development/eden-treaty-guide.md +0 -362
  157. package/ai-context/development/patterns.md +0 -382
  158. package/ai-context/development/plugins-guide.md +0 -572
  159. package/ai-context/examples/crud-complete.md +0 -626
  160. package/ai-context/project/architecture.md +0 -399
  161. package/ai-context/project/overview.md +0 -213
  162. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  163. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  164. package/ai-context/reference/environment-vars.md +0 -384
  165. package/ai-context/reference/troubleshooting.md +0 -407
  166. package/app/client/src/components/TestPage.tsx +0 -453
  167. package/bun.lock +0 -1063
  168. package/bunfig.toml +0 -16
  169. package/core/__tests__/integration.test.ts +0 -227
  170. package/core/build/index.ts +0 -186
  171. package/core/config/__tests__/config-loader.test.ts +0 -554
  172. package/core/config/__tests__/config-merger.test.ts +0 -657
  173. package/core/config/__tests__/env-converter.test.ts +0 -372
  174. package/core/config/__tests__/env-processor.test.ts +0 -431
  175. package/core/config/__tests__/env.test.ts +0 -452
  176. package/core/config/__tests__/integration.test.ts +0 -418
  177. package/core/config/__tests__/loader.test.ts +0 -331
  178. package/core/config/__tests__/schema.test.ts +0 -129
  179. package/core/config/__tests__/validator.test.ts +0 -318
  180. package/core/framework/__tests__/server.test.ts +0 -233
  181. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  182. package/core/plugins/__tests__/manager.test.ts +0 -398
  183. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  184. package/core/plugins/__tests__/registry.test.ts +0 -335
  185. package/core/utils/__tests__/errors.test.ts +0 -139
  186. package/core/utils/__tests__/helpers.test.ts +0 -297
  187. package/core/utils/__tests__/logger.test.ts +0 -141
  188. package/create-test-app.ts +0 -156
  189. package/docker-compose.microservices.yml +0 -75
  190. package/docker-compose.simple.yml +0 -57
  191. package/docker-compose.yml +0 -71
  192. package/eslint.config.js +0 -23
  193. package/flux-cli.ts +0 -214
  194. package/nginx-lb.conf +0 -37
  195. package/publish.sh +0 -63
  196. package/run-clean.ts +0 -26
  197. package/run-env-tests.ts +0 -313
  198. package/tailwind.config.js +0 -34
  199. package/tests/__mocks__/api.ts +0 -56
  200. package/tests/fixtures/users.ts +0 -69
  201. package/tests/integration/api/users.routes.test.ts +0 -221
  202. package/tests/setup.ts +0 -29
  203. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  204. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  205. package/tests/unit/app/client/eden-api.test.ts +0 -186
  206. package/tests/unit/app/client/simple.test.tsx +0 -23
  207. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  208. package/tests/unit/core/create-project.test.ts.skip +0 -95
  209. package/tests/unit/core/framework.test.ts +0 -144
  210. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  211. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  212. package/tests/utils/test-helpers.ts +0 -61
  213. package/vitest.config.ts +0 -50
  214. package/workspace.json +0 -6
@@ -0,0 +1,192 @@
1
+ import { existsSync } from "fs"
2
+ import { join } from "path"
3
+
4
+ export class GeneratorUtils {
5
+ static validateName(name: string): { valid: boolean; error?: string } {
6
+ if (!name || typeof name !== 'string') {
7
+ return { valid: false, error: 'Name is required' }
8
+ }
9
+
10
+ const trimmed = name.trim()
11
+ if (trimmed.length === 0) {
12
+ return { valid: false, error: 'Name cannot be empty' }
13
+ }
14
+
15
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(trimmed)) {
16
+ return { valid: false, error: 'Name must start with a letter and contain only letters, numbers, hyphens, and underscores' }
17
+ }
18
+
19
+ if (trimmed.length > 100) {
20
+ return { valid: false, error: 'Name must be less than 100 characters' }
21
+ }
22
+
23
+ return { valid: true }
24
+ }
25
+
26
+ static validatePath(path: string): { valid: boolean; error?: string } {
27
+ if (!path || typeof path !== 'string') {
28
+ return { valid: true } // Path is optional
29
+ }
30
+
31
+ const trimmed = path.trim()
32
+ if (trimmed.length === 0) {
33
+ return { valid: true }
34
+ }
35
+
36
+ // Check for invalid characters
37
+ if (/[<>:"|?*]/.test(trimmed)) {
38
+ return { valid: false, error: 'Path contains invalid characters' }
39
+ }
40
+
41
+ // Check for absolute paths (should be relative)
42
+ if (trimmed.startsWith('/') || /^[a-zA-Z]:/.test(trimmed)) {
43
+ return { valid: false, error: 'Path should be relative to project root' }
44
+ }
45
+
46
+ return { valid: true }
47
+ }
48
+
49
+ static checkFileExists(workingDir: string, filePath: string): boolean {
50
+ const fullPath = join(workingDir, filePath)
51
+ return existsSync(fullPath)
52
+ }
53
+
54
+ static getDefaultPath(type: string, name: string): string {
55
+ const kebabName = this.toKebabCase(name)
56
+ const pascalName = this.toPascalCase(name)
57
+
58
+ switch (type) {
59
+ case 'controller':
60
+ return `app/server/controllers/${kebabName}.controller.ts`
61
+ case 'service':
62
+ return `app/server/services/${kebabName}.service.ts`
63
+ case 'route':
64
+ return `app/server/routes/${kebabName}.routes.ts`
65
+ case 'component':
66
+ return `app/client/src/components/${pascalName}/${pascalName}.tsx`
67
+ default:
68
+ return `${kebabName}.ts`
69
+ }
70
+ }
71
+
72
+ static getRelatedFiles(type: string, name: string): string[] {
73
+ const kebabName = this.toKebabCase(name)
74
+ const pascalName = this.toPascalCase(name)
75
+
76
+ switch (type) {
77
+ case 'controller':
78
+ return [
79
+ `app/server/services/${kebabName}.service.ts`,
80
+ `app/server/schemas/${kebabName}.schema.ts`,
81
+ `app/server/routes/${kebabName}.routes.ts`
82
+ ]
83
+ case 'service':
84
+ return [
85
+ `app/server/repositories/${kebabName}.repository.ts`,
86
+ `app/server/controllers/${kebabName}.controller.ts`
87
+ ]
88
+ case 'component':
89
+ return [
90
+ `app/client/src/components/${pascalName}/${pascalName}.css`,
91
+ `app/client/src/components/${pascalName}/index.ts`,
92
+ `app/client/src/components/${pascalName}/${pascalName}.test.tsx`,
93
+ `app/client/src/components/${pascalName}/${pascalName}.stories.tsx`
94
+ ]
95
+ case 'route':
96
+ return [
97
+ `app/server/controllers/${kebabName}.controller.ts`,
98
+ `app/server/middleware/${kebabName}.middleware.ts`
99
+ ]
100
+ default:
101
+ return []
102
+ }
103
+ }
104
+
105
+ static formatFileSize(bytes: number): string {
106
+ const units = ['B', 'KB', 'MB', 'GB']
107
+ let size = bytes
108
+ let unitIndex = 0
109
+
110
+ while (size >= 1024 && unitIndex < units.length - 1) {
111
+ size /= 1024
112
+ unitIndex++
113
+ }
114
+
115
+ return `${size.toFixed(1)} ${units[unitIndex]}`
116
+ }
117
+
118
+ static getTemplateVariables(name: string, additionalVars: Record<string, any> = {}): Record<string, any> {
119
+ return {
120
+ name,
121
+ Name: this.capitalize(name),
122
+ NAME: name.toUpperCase(),
123
+ kebabName: this.toKebabCase(name),
124
+ camelName: this.toCamelCase(name),
125
+ pascalName: this.toPascalCase(name),
126
+ snakeName: this.toSnakeCase(name),
127
+ timestamp: new Date().toISOString(),
128
+ date: new Date().toLocaleDateString(),
129
+ time: new Date().toLocaleTimeString(),
130
+ year: new Date().getFullYear(),
131
+ month: new Date().getMonth() + 1,
132
+ day: new Date().getDate(),
133
+ ...additionalVars
134
+ }
135
+ }
136
+
137
+ // String transformation utilities
138
+ static capitalize(str: string): string {
139
+ return str.charAt(0).toUpperCase() + str.slice(1)
140
+ }
141
+
142
+ static toCamelCase(str: string): string {
143
+ return str
144
+ .replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
145
+ .replace(/^[A-Z]/, char => char.toLowerCase())
146
+ }
147
+
148
+ static toPascalCase(str: string): string {
149
+ return this.capitalize(this.toCamelCase(str))
150
+ }
151
+
152
+ static toKebabCase(str: string): string {
153
+ return str
154
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
155
+ .replace(/[\s_]+/g, '-')
156
+ .toLowerCase()
157
+ }
158
+
159
+ static toSnakeCase(str: string): string {
160
+ return str
161
+ .replace(/([a-z])([A-Z])/g, '$1_$2')
162
+ .replace(/[\s-]+/g, '_')
163
+ .toLowerCase()
164
+ }
165
+
166
+ static pluralize(str: string): string {
167
+ // Simple pluralization - in a real implementation you'd use a proper library
168
+ if (str.endsWith('y')) {
169
+ return str.slice(0, -1) + 'ies'
170
+ }
171
+ if (str.endsWith('s') || str.endsWith('sh') || str.endsWith('ch') || str.endsWith('x') || str.endsWith('z')) {
172
+ return str + 'es'
173
+ }
174
+ return str + 's'
175
+ }
176
+
177
+ static singularize(str: string): string {
178
+ // Simple singularization - in a real implementation you'd use a proper library
179
+ if (str.endsWith('ies')) {
180
+ return str.slice(0, -3) + 'y'
181
+ }
182
+ if (str.endsWith('es')) {
183
+ return str.slice(0, -2)
184
+ }
185
+ if (str.endsWith('s') && !str.endsWith('ss')) {
186
+ return str.slice(0, -1)
187
+ }
188
+ return str
189
+ }
190
+ }
191
+
192
+ export const generatorUtils = GeneratorUtils
package/core/cli/index.ts CHANGED
@@ -5,12 +5,81 @@ import { ProjectCreator } from "../templates/create-project"
5
5
  import { getConfigSync } from "../config"
6
6
  import { cliRegistry } from "./command-registry"
7
7
  import { pluginDiscovery } from "./plugin-discovery"
8
+ import { generateCommand, interactiveGenerateCommand } from "./generators/index.js"
8
9
 
9
10
  const command = process.argv[2]
10
11
  const args = process.argv.slice(3)
11
12
 
12
13
  // Register built-in commands
13
14
  async function registerBuiltInCommands() {
15
+ // Register generate commands
16
+ cliRegistry.register(generateCommand)
17
+ cliRegistry.register(interactiveGenerateCommand)
18
+
19
+ // Register plugin dependency commands
20
+ cliRegistry.register({
21
+ name: 'plugin:deps',
22
+ description: 'Gerenciar dependências de plugins',
23
+ category: 'Plugins',
24
+ handler: async (args, options, context) => {
25
+ if (args.length === 0) {
26
+ console.log(`
27
+ ⚡ FluxStack Plugin Dependencies Manager
28
+
29
+ Usage:
30
+ flux plugin:deps install Install plugin dependencies
31
+ flux plugin:deps list List plugin dependencies
32
+ flux plugin:deps check Check for dependency conflicts
33
+ flux plugin:deps clean Clean unused dependencies
34
+
35
+ Examples:
36
+ flux plugin:deps install --dry-run # Show what would be installed
37
+ flux plugin:deps list --plugin crypto-auth # Show specific plugin deps
38
+ flux plugin:deps check # Check for conflicts
39
+ `)
40
+ return
41
+ }
42
+
43
+ // Handle subcommands
44
+ const subcommand = args[0]
45
+ const subArgs = args.slice(1)
46
+
47
+ // Import dinamicamente para evitar problemas de inicialização
48
+ const { createPluginDepsCommand } = await import('./commands/plugin-deps')
49
+ const cmd = createPluginDepsCommand()
50
+
51
+ switch (subcommand) {
52
+ case 'install':
53
+ const installCmd = cmd.commands.find(c => c.name() === 'install')
54
+ if (installCmd) {
55
+ await installCmd.parseAsync(['node', 'cli', ...subArgs], { from: 'user' })
56
+ }
57
+ break
58
+ case 'list':
59
+ const listCmd = cmd.commands.find(c => c.name() === 'list')
60
+ if (listCmd) {
61
+ await listCmd.parseAsync(['node', 'cli', ...subArgs], { from: 'user' })
62
+ }
63
+ break
64
+ case 'check':
65
+ const checkCmd = cmd.commands.find(c => c.name() === 'check')
66
+ if (checkCmd) {
67
+ await checkCmd.parseAsync(['node', 'cli', ...subArgs], { from: 'user' })
68
+ }
69
+ break
70
+ case 'clean':
71
+ const cleanCmd = cmd.commands.find(c => c.name() === 'clean')
72
+ if (cleanCmd) {
73
+ await cleanCmd.parseAsync(['node', 'cli', ...subArgs], { from: 'user' })
74
+ }
75
+ break
76
+ default:
77
+ console.error(`❌ Unknown subcommand: ${subcommand}`)
78
+ console.error('Available subcommands: install, list, check, clean')
79
+ }
80
+ }
81
+ })
82
+
14
83
  // Help command
15
84
  cliRegistry.register({
16
85
  name: 'help',
@@ -11,39 +11,35 @@ export class CliPluginDiscovery {
11
11
  // 1. Load built-in plugins with CLI commands
12
12
  await this.loadBuiltInPlugins()
13
13
 
14
- // 2. Load external plugins from node_modules
15
- await this.loadExternalPlugins()
16
-
17
- // 3. Load local plugins from project
14
+ // 2. Load local plugins from project
18
15
  await this.loadLocalPlugins()
19
16
  }
20
17
 
21
18
  private async loadBuiltInPlugins(): Promise<void> {
22
- const builtInPluginsDir = join(__dirname, '../server/plugins')
19
+ const builtInPluginsDir = join(__dirname, '../plugins/built-in')
23
20
 
24
21
  if (!existsSync(builtInPluginsDir)) {
25
22
  return
26
23
  }
27
24
 
28
25
  try {
29
- // For now, we'll manually list built-in plugins that might have CLI commands
30
- const potentialPlugins = [
31
- 'logger',
32
- 'vite',
33
- 'swagger',
34
- 'static',
35
- 'database'
36
- ]
26
+ const fs = await import('fs')
27
+ const potentialPlugins = fs.readdirSync(builtInPluginsDir, { withFileTypes: true })
28
+ .filter(entry => entry.isDirectory())
29
+ .map(entry => entry.name)
37
30
 
38
31
  for (const pluginName of potentialPlugins) {
39
32
  try {
40
- const pluginPath = join(builtInPluginsDir, `${pluginName}.ts`)
33
+ const pluginPath = join(builtInPluginsDir, pluginName, 'index.ts')
41
34
  if (existsSync(pluginPath)) {
42
35
  const pluginModule = await import(pluginPath)
43
- const plugin = pluginModule[`${pluginName}Plugin`] as Plugin
44
36
 
45
- if (plugin && plugin.commands) {
46
- this.registerPluginCommands(plugin)
37
+ if (pluginModule.commands) {
38
+ for (const command of pluginModule.commands) {
39
+ cliRegistry.register(command)
40
+ }
41
+ this.loadedPlugins.add(pluginName)
42
+ logger.debug(`Registered ${pluginModule.commands.length} CLI commands from built-in plugin: ${pluginName}`)
47
43
  }
48
44
  }
49
45
  } catch (error) {
@@ -55,74 +51,9 @@ export class CliPluginDiscovery {
55
51
  }
56
52
  }
57
53
 
58
- private async loadExternalPlugins(): Promise<void> {
59
- const nodeModulesDir = join(process.cwd(), 'node_modules')
60
-
61
- if (!existsSync(nodeModulesDir)) {
62
- return
63
- }
64
-
65
- try {
66
- const fs = await import('fs')
67
- const entries = fs.readdirSync(nodeModulesDir, { withFileTypes: true })
68
-
69
- for (const entry of entries) {
70
- if (!entry.isDirectory()) continue
71
-
72
- // Check for FluxStack plugins (convention: fluxstack-plugin-*)
73
- if (entry.name.startsWith('fluxstack-plugin-')) {
74
- await this.loadExternalPlugin(entry.name)
75
- }
76
-
77
- // Check for scoped packages (@fluxstack/plugin-*)
78
- if (entry.name.startsWith('@fluxstack')) {
79
- const scopedDir = join(nodeModulesDir, entry.name)
80
- if (existsSync(scopedDir)) {
81
- const scopedEntries = fs.readdirSync(scopedDir, { withFileTypes: true })
82
- for (const scopedEntry of scopedEntries) {
83
- if (scopedEntry.isDirectory() && scopedEntry.name.startsWith('plugin-')) {
84
- await this.loadExternalPlugin(`${entry.name}/${scopedEntry.name}`)
85
- }
86
- }
87
- }
88
- }
89
- }
90
- } catch (error) {
91
- logger.debug('Failed to scan external plugins:', error)
92
- }
93
- }
94
-
95
- private async loadExternalPlugin(packageName: string): Promise<void> {
96
- try {
97
- const packagePath = join(process.cwd(), 'node_modules', packageName)
98
- const packageJsonPath = join(packagePath, 'package.json')
99
-
100
- if (!existsSync(packageJsonPath)) {
101
- return
102
- }
103
-
104
- const packageJson = JSON.parse(await import('fs').then(fs =>
105
- fs.readFileSync(packageJsonPath, 'utf-8')
106
- ))
107
-
108
- // Check if this is a FluxStack plugin
109
- if (packageJson.fluxstack?.plugin) {
110
- const entryPoint = packageJson.main || 'index.js'
111
- const pluginPath = join(packagePath, entryPoint)
112
-
113
- if (existsSync(pluginPath)) {
114
- const pluginModule = await import(pluginPath)
115
- const plugin = pluginModule.default || pluginModule[packageJson.fluxstack.plugin] as Plugin
116
-
117
- if (plugin && plugin.commands) {
118
- this.registerPluginCommands(plugin)
119
- }
120
- }
121
- }
122
- } catch (error) {
123
- logger.debug(`Failed to load external plugin ${packageName}:`, error)
124
- }
125
- }
54
+ // Métodos removidos - não carregamos mais plugins do node_modules
55
+ // private async loadExternalPlugins(): Promise<void> { ... }
56
+ // private async loadExternalPlugin(packageName: string): Promise<void> { ... }
126
57
 
127
58
  private async loadLocalPlugins(): Promise<void> {
128
59
  const localPluginsDir = join(process.cwd(), 'plugins')
@@ -0,0 +1,17 @@
1
+ // 🔥 FluxStack Client Library - Main Entry Point
2
+ // This is the primary interface for all FluxStack client functionality
3
+
4
+ // Re-export everything from the main index
5
+ export * from './index'
6
+
7
+ // Convenience aliases for common hooks and utilities
8
+ export {
9
+ useHybridLiveComponent as useLive,
10
+ useWebSocket as useWS,
11
+ useChunkedUpload as useUpload,
12
+ StateValidator as Validator
13
+ } from './index'
14
+
15
+ // Default export for easy importing
16
+ import * as FluxStack from './index'
17
+ export default FluxStack
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Core Client Hooks
3
+ * FluxStack hook utilities exports
4
+ */
5
+
6
+ export { createAuthHook } from './useAuth.js'
7
+ export type { AuthHook } from './useAuth.js'
@@ -0,0 +1,130 @@
1
+ // 🔥 State Validation Utilities
2
+
3
+ import type { StateValidation, StateConflict, HybridState } from '../../types/types'
4
+
5
+ export class StateValidator {
6
+ /**
7
+ * Generate checksum for state object
8
+ */
9
+ static generateChecksum(state: any): string {
10
+ const json = JSON.stringify(state, Object.keys(state).sort())
11
+ let hash = 0
12
+ for (let i = 0; i < json.length; i++) {
13
+ const char = json.charCodeAt(i)
14
+ hash = ((hash << 5) - hash) + char
15
+ hash = hash & hash // Convert to 32-bit integer
16
+ }
17
+ return Math.abs(hash).toString(16)
18
+ }
19
+
20
+ /**
21
+ * Create validation metadata
22
+ */
23
+ static createValidation(
24
+ state: any,
25
+ source: 'client' | 'server' | 'mount' = 'client'
26
+ ): StateValidation {
27
+ return {
28
+ checksum: this.generateChecksum(state),
29
+ version: Date.now(),
30
+ timestamp: Date.now(),
31
+ source
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Compare two states and detect conflicts
37
+ */
38
+ static detectConflicts<T>(
39
+ clientState: T,
40
+ serverState: T,
41
+ excludeFields: string[] = ['lastUpdated', 'version']
42
+ ): StateConflict[] {
43
+ const conflicts: StateConflict[] = []
44
+
45
+ const clientKeys = Object.keys(clientState as any)
46
+ const serverKeys = Object.keys(serverState as any)
47
+ const allKeys = Array.from(new Set([...clientKeys, ...serverKeys]))
48
+
49
+ for (const key of allKeys) {
50
+ if (excludeFields.includes(key)) continue
51
+
52
+ const clientValue = (clientState as any)?.[key]
53
+ const serverValue = (serverState as any)?.[key]
54
+
55
+ if (JSON.stringify(clientValue) !== JSON.stringify(serverValue)) {
56
+ conflicts.push({
57
+ property: key as string,
58
+ clientValue,
59
+ serverValue,
60
+ timestamp: Date.now(),
61
+ resolved: false
62
+ })
63
+ }
64
+ }
65
+
66
+ return conflicts
67
+ }
68
+
69
+ /**
70
+ * Merge states with conflict resolution
71
+ */
72
+ static mergeStates<T>(
73
+ clientState: T,
74
+ serverState: T,
75
+ conflicts: StateConflict[],
76
+ strategy: 'client' | 'server' | 'smart' = 'smart'
77
+ ): T {
78
+ const merged = { ...clientState }
79
+
80
+ for (const conflict of conflicts) {
81
+ switch (strategy) {
82
+ case 'client':
83
+ // Keep client value
84
+ break
85
+
86
+ case 'server':
87
+ (merged as any)[conflict.property] = conflict.serverValue
88
+ break
89
+
90
+ case 'smart':
91
+ // Smart resolution based on field type and context
92
+ if (conflict.property === 'lastUpdated') {
93
+ // Server timestamp wins
94
+ (merged as any)[conflict.property] = conflict.serverValue
95
+ } else if (typeof conflict.serverValue === 'number' && typeof conflict.clientValue === 'number') {
96
+ // For numbers, use the higher value (e.g., counters)
97
+ (merged as any)[conflict.property] = Math.max(conflict.serverValue, conflict.clientValue)
98
+ } else {
99
+ // Default to server for other types
100
+ (merged as any)[conflict.property] = conflict.serverValue
101
+ }
102
+ break
103
+ }
104
+ }
105
+
106
+ return merged
107
+ }
108
+
109
+ /**
110
+ * Validate state integrity
111
+ */
112
+ static validateState<T>(hybridState: HybridState<T>): boolean {
113
+ const currentChecksum = this.generateChecksum(hybridState.data)
114
+ return currentChecksum === hybridState.validation.checksum
115
+ }
116
+
117
+ /**
118
+ * Update validation after state change
119
+ */
120
+ static updateValidation<T>(
121
+ hybridState: HybridState<T>,
122
+ source: 'client' | 'server' | 'mount' = 'client'
123
+ ): HybridState<T> {
124
+ return {
125
+ ...hybridState,
126
+ validation: this.createValidation(hybridState.data, source),
127
+ status: 'synced'
128
+ }
129
+ }
130
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Authentication Hook
3
+ * Core FluxStack authentication utilities
4
+ */
5
+
6
+ import type { BaseUser, BaseUserStore } from '../state/index.js'
7
+
8
+ /**
9
+ * Create authentication hook for a user store
10
+ */
11
+ export function createAuthHook(useUserStore: () => BaseUserStore) {
12
+ return function useAuth() {
13
+ const store = useUserStore()
14
+
15
+ return {
16
+ // State
17
+ currentUser: store.currentUser,
18
+ isAuthenticated: store.isAuthenticated,
19
+ isLoading: store.isLoading,
20
+ error: store.error,
21
+
22
+ // Computed
23
+ isAdmin: store.currentUser?.role === 'admin',
24
+
25
+ // Actions
26
+ login: store.login,
27
+ register: store.register,
28
+ logout: store.logout,
29
+ updateProfile: store.updateProfile,
30
+ clearError: store.clearError
31
+ }
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Base auth hook interface
37
+ */
38
+ export interface AuthHook {
39
+ currentUser: BaseUser | null
40
+ isAuthenticated: boolean
41
+ isLoading: boolean
42
+ error: string | null
43
+ isAdmin: boolean
44
+ login: (credentials: { email: string; password: string }) => Promise<void>
45
+ register: (data: { email: string; password: string; name: string }) => Promise<void>
46
+ logout: () => void
47
+ updateProfile: (data: Partial<BaseUser>) => Promise<void>
48
+ clearError: () => void
49
+ }