create-fluxstack 1.10.1 → 1.12.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 (257) hide show
  1. package/.dockerignore +1 -2
  2. package/Dockerfile +8 -8
  3. package/LLMD/INDEX.md +64 -0
  4. package/LLMD/MAINTENANCE.md +197 -0
  5. package/LLMD/MIGRATION.md +156 -0
  6. package/LLMD/config/.gitkeep +1 -0
  7. package/LLMD/config/declarative-system.md +268 -0
  8. package/LLMD/config/environment-vars.md +327 -0
  9. package/LLMD/config/runtime-reload.md +401 -0
  10. package/LLMD/core/.gitkeep +1 -0
  11. package/LLMD/core/build-system.md +599 -0
  12. package/LLMD/core/framework-lifecycle.md +229 -0
  13. package/LLMD/core/plugin-system.md +451 -0
  14. package/LLMD/patterns/.gitkeep +1 -0
  15. package/LLMD/patterns/anti-patterns.md +297 -0
  16. package/LLMD/patterns/project-structure.md +264 -0
  17. package/LLMD/patterns/type-safety.md +440 -0
  18. package/LLMD/reference/.gitkeep +1 -0
  19. package/LLMD/reference/cli-commands.md +250 -0
  20. package/LLMD/reference/plugin-hooks.md +357 -0
  21. package/LLMD/reference/routing.md +39 -0
  22. package/LLMD/reference/troubleshooting.md +364 -0
  23. package/LLMD/resources/.gitkeep +1 -0
  24. package/LLMD/resources/controllers.md +465 -0
  25. package/LLMD/resources/live-components.md +703 -0
  26. package/LLMD/resources/live-rooms.md +482 -0
  27. package/LLMD/resources/live-upload.md +130 -0
  28. package/LLMD/resources/plugins-external.md +617 -0
  29. package/LLMD/resources/routes-eden.md +254 -0
  30. package/README.md +37 -17
  31. package/app/client/index.html +0 -1
  32. package/app/client/src/App.tsx +107 -150
  33. package/app/client/src/components/AppLayout.tsx +68 -0
  34. package/app/client/src/components/BackButton.tsx +13 -0
  35. package/app/client/src/components/DemoPage.tsx +20 -0
  36. package/app/client/src/components/LiveUploadWidget.tsx +204 -0
  37. package/app/client/src/lib/eden-api.ts +85 -60
  38. package/app/client/src/live/ChatDemo.tsx +107 -0
  39. package/app/client/src/live/CounterDemo.tsx +206 -0
  40. package/app/client/src/live/FormDemo.tsx +119 -0
  41. package/app/client/src/live/RoomChatDemo.tsx +242 -0
  42. package/app/client/src/live/UploadDemo.tsx +21 -0
  43. package/app/client/src/main.tsx +4 -1
  44. package/app/client/src/pages/ApiTestPage.tsx +108 -0
  45. package/app/client/src/pages/HomePage.tsx +76 -0
  46. package/app/server/app.ts +1 -4
  47. package/app/server/controllers/users.controller.ts +36 -44
  48. package/app/server/index.ts +25 -35
  49. package/app/server/live/LiveChat.ts +77 -0
  50. package/app/server/live/LiveCounter.ts +67 -0
  51. package/app/server/live/LiveForm.ts +63 -0
  52. package/app/server/live/LiveLocalCounter.ts +32 -0
  53. package/app/server/live/LiveRoomChat.ts +285 -0
  54. package/app/server/live/LiveUpload.ts +81 -0
  55. package/app/server/routes/index.ts +3 -1
  56. package/app/server/routes/room.routes.ts +117 -0
  57. package/app/server/routes/users.routes.ts +35 -27
  58. package/app/shared/types/index.ts +14 -2
  59. package/config/app.config.ts +2 -62
  60. package/config/client.config.ts +2 -95
  61. package/config/database.config.ts +2 -99
  62. package/config/fluxstack.config.ts +25 -45
  63. package/config/index.ts +57 -38
  64. package/config/monitoring.config.ts +2 -114
  65. package/config/plugins.config.ts +2 -80
  66. package/config/server.config.ts +2 -68
  67. package/config/services.config.ts +2 -130
  68. package/config/system/app.config.ts +29 -0
  69. package/config/system/build.config.ts +49 -0
  70. package/config/system/client.config.ts +68 -0
  71. package/config/system/database.config.ts +17 -0
  72. package/config/system/fluxstack.config.ts +114 -0
  73. package/config/{logger.config.ts → system/logger.config.ts} +3 -1
  74. package/config/system/monitoring.config.ts +114 -0
  75. package/config/system/plugins.config.ts +84 -0
  76. package/config/{runtime.config.ts → system/runtime.config.ts} +1 -1
  77. package/config/system/server.config.ts +68 -0
  78. package/config/system/services.config.ts +46 -0
  79. package/config/{system.config.ts → system/system.config.ts} +1 -1
  80. package/core/build/flux-plugins-generator.ts +325 -325
  81. package/core/build/index.ts +39 -27
  82. package/core/build/live-components-generator.ts +3 -3
  83. package/core/build/optimizer.ts +235 -235
  84. package/core/cli/command-registry.ts +6 -4
  85. package/core/cli/commands/build.ts +79 -0
  86. package/core/cli/commands/create.ts +54 -0
  87. package/core/cli/commands/dev.ts +101 -0
  88. package/core/cli/commands/help.ts +34 -0
  89. package/core/cli/commands/index.ts +34 -0
  90. package/core/cli/commands/make-plugin.ts +90 -0
  91. package/core/cli/commands/plugin-add.ts +197 -0
  92. package/core/cli/commands/plugin-deps.ts +2 -2
  93. package/core/cli/commands/plugin-list.ts +208 -0
  94. package/core/cli/commands/plugin-remove.ts +170 -0
  95. package/core/cli/generators/component.ts +769 -769
  96. package/core/cli/generators/controller.ts +1 -1
  97. package/core/cli/generators/index.ts +146 -146
  98. package/core/cli/generators/interactive.ts +227 -227
  99. package/core/cli/generators/plugin.ts +2 -2
  100. package/core/cli/generators/prompts.ts +82 -82
  101. package/core/cli/generators/route.ts +6 -6
  102. package/core/cli/generators/service.ts +2 -2
  103. package/core/cli/generators/template-engine.ts +4 -3
  104. package/core/cli/generators/types.ts +2 -2
  105. package/core/cli/generators/utils.ts +191 -191
  106. package/core/cli/index.ts +115 -686
  107. package/core/cli/plugin-discovery.ts +2 -2
  108. package/core/client/LiveComponentsProvider.tsx +60 -8
  109. package/core/client/api/eden.ts +183 -0
  110. package/core/client/api/index.ts +11 -0
  111. package/core/client/components/Live.tsx +104 -0
  112. package/core/client/fluxstack.ts +1 -9
  113. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
  114. package/core/client/hooks/state-validator.ts +1 -1
  115. package/core/client/hooks/useAuth.ts +48 -48
  116. package/core/client/hooks/useChunkedUpload.ts +85 -35
  117. package/core/client/hooks/useLiveChunkedUpload.ts +87 -0
  118. package/core/client/hooks/useLiveComponent.ts +800 -0
  119. package/core/client/hooks/useLiveUpload.ts +71 -0
  120. package/core/client/hooks/useRoom.ts +409 -0
  121. package/core/client/hooks/useRoomProxy.ts +382 -0
  122. package/core/client/index.ts +17 -68
  123. package/core/client/standalone-entry.ts +8 -0
  124. package/core/client/standalone.ts +74 -53
  125. package/core/client/state/createStore.ts +192 -192
  126. package/core/client/state/index.ts +14 -14
  127. package/core/config/index.ts +70 -291
  128. package/core/config/schema.ts +42 -723
  129. package/core/framework/client.ts +131 -131
  130. package/core/framework/index.ts +7 -7
  131. package/core/framework/server.ts +47 -40
  132. package/core/framework/types.ts +2 -2
  133. package/core/index.ts +23 -4
  134. package/core/live/ComponentRegistry.ts +3 -3
  135. package/core/live/types.ts +77 -0
  136. package/core/plugins/built-in/index.ts +134 -134
  137. package/core/plugins/built-in/live-components/commands/create-live-component.ts +242 -1066
  138. package/core/plugins/built-in/live-components/index.ts +1 -1
  139. package/core/plugins/built-in/monitoring/index.ts +111 -47
  140. package/core/plugins/built-in/static/index.ts +1 -1
  141. package/core/plugins/built-in/swagger/index.ts +68 -265
  142. package/core/plugins/built-in/vite/index.ts +85 -185
  143. package/core/plugins/built-in/vite/vite-dev.ts +10 -16
  144. package/core/plugins/config.ts +9 -7
  145. package/core/plugins/dependency-manager.ts +31 -1
  146. package/core/plugins/discovery.ts +19 -7
  147. package/core/plugins/executor.ts +2 -2
  148. package/core/plugins/index.ts +203 -203
  149. package/core/plugins/manager.ts +27 -39
  150. package/core/plugins/module-resolver.ts +19 -8
  151. package/core/plugins/registry.ts +255 -19
  152. package/core/plugins/types.ts +20 -53
  153. package/core/server/framework.ts +66 -43
  154. package/core/server/index.ts +15 -15
  155. package/core/server/live/ComponentRegistry.ts +78 -71
  156. package/core/server/live/FileUploadManager.ts +23 -10
  157. package/core/server/live/LiveComponentPerformanceMonitor.ts +1 -1
  158. package/core/server/live/LiveRoomManager.ts +261 -0
  159. package/core/server/live/RoomEventBus.ts +234 -0
  160. package/core/server/live/RoomStateManager.ts +172 -0
  161. package/core/server/live/StateSignature.ts +643 -643
  162. package/core/server/live/WebSocketConnectionManager.ts +30 -19
  163. package/core/server/live/auto-generated-components.ts +21 -9
  164. package/core/server/live/index.ts +14 -0
  165. package/core/server/live/websocket-plugin.ts +214 -67
  166. package/core/server/middleware/elysia-helpers.ts +7 -2
  167. package/core/server/middleware/errorHandling.ts +1 -1
  168. package/core/server/middleware/index.ts +31 -31
  169. package/core/server/plugins/database.ts +180 -180
  170. package/core/server/plugins/static-files-plugin.ts +69 -69
  171. package/core/server/plugins/swagger.ts +1 -1
  172. package/core/server/rooms/RoomBroadcaster.ts +357 -0
  173. package/core/server/rooms/RoomSystem.ts +463 -0
  174. package/core/server/rooms/index.ts +13 -0
  175. package/core/server/services/BaseService.ts +1 -1
  176. package/core/server/services/ServiceContainer.ts +1 -1
  177. package/core/server/services/index.ts +8 -8
  178. package/core/templates/create-project.ts +12 -12
  179. package/core/testing/index.ts +9 -9
  180. package/core/testing/setup.ts +73 -73
  181. package/core/types/api.ts +168 -168
  182. package/core/types/build.ts +219 -219
  183. package/core/types/config.ts +56 -26
  184. package/core/types/index.ts +4 -4
  185. package/core/types/plugin.ts +107 -107
  186. package/core/types/types.ts +353 -14
  187. package/core/utils/build-logger.ts +324 -324
  188. package/core/utils/config-schema.ts +480 -480
  189. package/core/utils/env.ts +2 -8
  190. package/core/utils/errors/codes.ts +114 -114
  191. package/core/utils/errors/handlers.ts +36 -1
  192. package/core/utils/errors/index.ts +49 -5
  193. package/core/utils/errors/middleware.ts +113 -113
  194. package/core/utils/helpers.ts +6 -16
  195. package/core/utils/index.ts +17 -17
  196. package/core/utils/logger/colors.ts +114 -114
  197. package/core/utils/logger/config.ts +13 -9
  198. package/core/utils/logger/formatter.ts +82 -82
  199. package/core/utils/logger/group-logger.ts +101 -101
  200. package/core/utils/logger/index.ts +6 -1
  201. package/core/utils/logger/stack-trace.ts +3 -1
  202. package/core/utils/logger/startup-banner.ts +82 -82
  203. package/core/utils/logger/winston-logger.ts +152 -152
  204. package/core/utils/monitoring/index.ts +211 -211
  205. package/core/utils/sync-version.ts +66 -66
  206. package/core/utils/version.ts +1 -1
  207. package/create-fluxstack.ts +8 -7
  208. package/package.json +12 -13
  209. package/plugins/crypto-auth/cli/make-protected-route.command.ts +1 -1
  210. package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
  211. package/plugins/crypto-auth/client/components/index.ts +11 -11
  212. package/plugins/crypto-auth/client/index.ts +11 -11
  213. package/plugins/crypto-auth/config/index.ts +1 -1
  214. package/plugins/crypto-auth/index.ts +4 -4
  215. package/plugins/crypto-auth/package.json +65 -65
  216. package/plugins/crypto-auth/server/AuthMiddleware.ts +1 -1
  217. package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
  218. package/plugins/crypto-auth/server/index.ts +21 -21
  219. package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +3 -3
  220. package/plugins/crypto-auth/server/middlewares/cryptoAuthOptional.ts +1 -1
  221. package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +2 -2
  222. package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +2 -2
  223. package/plugins/crypto-auth/server/middlewares/helpers.ts +1 -1
  224. package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
  225. package/tsconfig.api-strict.json +16 -0
  226. package/tsconfig.json +48 -52
  227. package/{app/client/tsconfig.node.json → tsconfig.node.json} +25 -25
  228. package/types/global.d.ts +29 -29
  229. package/types/vitest.d.ts +8 -8
  230. package/vite.config.ts +38 -62
  231. package/vitest.config.live.ts +10 -9
  232. package/vitest.config.ts +29 -17
  233. package/app/client/README.md +0 -69
  234. package/app/client/SIMPLIFICATION.md +0 -140
  235. package/app/client/frontend-only.ts +0 -12
  236. package/app/client/src/live/FileUploadExample.tsx +0 -359
  237. package/app/client/src/live/MinimalLiveClock.tsx +0 -47
  238. package/app/client/src/live/QuickUploadTest.tsx +0 -193
  239. package/app/client/tsconfig.app.json +0 -45
  240. package/app/client/tsconfig.json +0 -7
  241. package/app/client/zustand-setup.md +0 -65
  242. package/app/server/backend-only.ts +0 -18
  243. package/app/server/live/LiveClockComponent.ts +0 -215
  244. package/app/server/live/LiveFileUploadComponent.ts +0 -77
  245. package/app/server/routes/env-test.ts +0 -110
  246. package/core/client/hooks/index.ts +0 -7
  247. package/core/client/hooks/useHybridLiveComponent.ts +0 -685
  248. package/core/client/hooks/useTypedLiveComponent.ts +0 -133
  249. package/core/client/hooks/useWebSocket.ts +0 -361
  250. package/core/config/env.ts +0 -546
  251. package/core/config/loader.ts +0 -522
  252. package/core/config/runtime-config.ts +0 -327
  253. package/core/config/validator.ts +0 -540
  254. package/core/server/backend-entry.ts +0 -51
  255. package/core/server/standalone.ts +0 -106
  256. package/core/utils/regenerate-files.ts +0 -69
  257. package/fluxstack.config.ts +0 -354
@@ -19,30 +19,39 @@ export class FluxStackBuilder {
19
19
  this.config = config
20
20
  this.pluginRegistry = pluginRegistry
21
21
 
22
+ const optimization = this.config.optimization || {
23
+ minify: true,
24
+ treeshake: true,
25
+ compress: true,
26
+ removeUnusedCSS: false,
27
+ optimizeImages: false,
28
+ bundleAnalyzer: false
29
+ }
30
+
22
31
  // Initialize bundler with configuration
23
32
  this.bundler = new Bundler({
24
- target: config.build.target,
25
- outDir: config.build.outDir,
26
- sourceMaps: config.build.sourceMaps,
27
- minify: config.build.minify,
28
- external: config.build.external
33
+ target: config.build.target ?? 'bun',
34
+ outDir: config.build.outDir ?? 'dist',
35
+ sourceMaps: config.build.sourceMaps ?? false,
36
+ minify: optimization.minify,
37
+ external: config.build.external || []
29
38
  })
30
39
 
31
40
  // Initialize optimizer with configuration
32
41
  this.optimizer = new Optimizer({
33
- treeshake: config.build.treeshake,
34
- compress: config.build.compress || false,
35
- removeUnusedCSS: config.build.removeUnusedCSS || false,
36
- optimizeImages: config.build.optimizeImages || false,
37
- bundleAnalysis: config.build.bundleAnalysis || false
42
+ treeshake: optimization.treeshake ?? true,
43
+ compress: optimization.compress || false,
44
+ removeUnusedCSS: optimization.removeUnusedCSS || false,
45
+ optimizeImages: optimization.optimizeImages || false,
46
+ bundleAnalysis: optimization.bundleAnalyzer || false
38
47
  })
39
48
  }
40
49
 
41
50
  async buildClient() {
42
51
  return await this.bundler.bundleClient({
43
52
  env: {
44
- VITE_BUILD_OUTDIR: this.config.client.build.outDir,
45
- VITE_BUILD_SOURCEMAPS: this.config.client.build.sourceMaps.toString()
53
+ VITE_BUILD_OUTDIR: this.config.clientBuild.outDir ?? 'dist/client',
54
+ VITE_BUILD_SOURCEMAPS: (this.config.clientBuild.sourceMaps ?? false).toString()
46
55
  }
47
56
  })
48
57
  }
@@ -60,7 +69,7 @@ export class FluxStackBuilder {
60
69
  async createDockerFiles() {
61
70
  buildLogger.section('Docker Configuration', '🐳')
62
71
 
63
- const distDir = this.config.build.outDir
72
+ const distDir = this.config.build.outDir ?? 'dist'
64
73
  buildLogger.step(`Output directory: ${distDir}`)
65
74
 
66
75
  // Ensure dist directory exists
@@ -72,9 +81,12 @@ export class FluxStackBuilder {
72
81
  buildLogger.success('Directory already exists')
73
82
  }
74
83
 
84
+ // Get current Bun version for Docker image
85
+ const bunVersion = typeof Bun !== 'undefined' ? Bun.version : '1.3'
86
+
75
87
  // Dockerfile optimizado para produção
76
88
  const dockerfile = `# FluxStack Production Docker Image
77
- FROM oven/bun:1.1-alpine AS production
89
+ FROM oven/bun:${bunVersion}-alpine AS production
78
90
 
79
91
  WORKDIR /app
80
92
 
@@ -245,9 +257,9 @@ MONITORING_ENABLED=true
245
257
  const startTime = Date.now()
246
258
 
247
259
  const buildContext: BuildContext = {
248
- target: this.config.build.target,
249
- outDir: this.config.build.outDir,
250
- mode: (this.config.build.mode || 'production') as 'development' | 'production',
260
+ target: this.config.build.target ?? 'bun',
261
+ outDir: this.config.build.outDir ?? 'dist',
262
+ mode: (this.config.build.mode ?? 'production') as 'development' | 'production',
251
263
  config: this.config
252
264
  }
253
265
 
@@ -307,12 +319,12 @@ MONITORING_ENABLED=true
307
319
  }
308
320
 
309
321
  // Process assets and execute onBuildAsset hooks
310
- await this.processAssets(this.config.build.outDir)
322
+ await this.processAssets(this.config.build.outDir ?? 'dist')
311
323
 
312
324
  // Optimize build if enabled
313
325
  let optimizationResult
314
326
  if (this.config.build.optimize) {
315
- optimizationResult = await this.optimizer.optimize(this.config.build.outDir)
327
+ optimizationResult = await this.optimizer.optimize(this.config.build.outDir ?? 'dist')
316
328
  }
317
329
 
318
330
  // Create Docker files
@@ -329,7 +341,7 @@ MONITORING_ENABLED=true
329
341
  // Print build summary
330
342
  buildLogger.summary('Build Completed Successfully', [
331
343
  { label: 'Build Time', value: buildLogger.formatDuration(duration), highlight: true },
332
- { label: 'Output Directory', value: this.config.build.outDir },
344
+ { label: 'Output Directory', value: this.config.build.outDir ?? 'dist' },
333
345
  { label: 'Client Assets', value: clientResult.assets?.length || 0 },
334
346
  { label: 'Total Size', value: buildLogger.formatSize(optimizationResult?.optimizedSize || 0) },
335
347
  { label: 'Compression', value: optimizationResult?.compressionRatio ? `${optimizationResult.compressionRatio.toFixed(2)}%` : 'N/A' },
@@ -422,10 +434,10 @@ MONITORING_ENABLED=true
422
434
  optimizationResult?: any
423
435
  ): Promise<BuildManifest> {
424
436
  return {
425
- version: this.config.app.version,
437
+ version: this.config.app.version ?? '0.0.0',
426
438
  timestamp: new Date().toISOString(),
427
- target: this.config.build.target,
428
- mode: this.config.build.mode || 'production',
439
+ target: this.config.build.target ?? 'bun',
440
+ mode: this.config.build.mode ?? 'production',
429
441
  client: {
430
442
  entryPoints: [],
431
443
  chunks: [],
@@ -439,9 +451,9 @@ MONITORING_ENABLED=true
439
451
  },
440
452
  assets: [],
441
453
  optimization: {
442
- minified: this.config.build.minify,
443
- treeshaken: this.config.build.treeshake,
444
- compressed: this.config.build.compress || false,
454
+ minified: this.config.optimization?.minify ?? false,
455
+ treeshaken: this.config.optimization?.treeshake ?? false,
456
+ compressed: this.config.optimization?.compress ?? false,
445
457
  originalSize: optimizationResult?.originalSize || 0,
446
458
  optimizedSize: optimizationResult?.optimizedSize || 0,
447
459
  compressionRatio: optimizationResult?.compressionRatio || 0
@@ -533,4 +545,4 @@ MONITORING_ENABLED=true
533
545
 
534
546
  return 'other'
535
547
  }
536
- }
548
+ }
@@ -18,7 +18,7 @@ export class LiveComponentsGenerator {
18
18
  private backupFilePath: string
19
19
  private entryPointPath: string
20
20
  private entryPointBackupPath: string
21
- private readonly importLine = 'import "@/core/server/live/auto-generated-components"'
21
+ private readonly importLine = 'import "@core/server/live/auto-generated-components"'
22
22
 
23
23
  constructor() {
24
24
  // Scan components from app/ directory (user code)
@@ -75,7 +75,7 @@ export class LiveComponentsGenerator {
75
75
  className,
76
76
  componentName,
77
77
  // Path relative to core/server/live/ where the generated file will be
78
- filePath: `@/app/server/live/${fileName}`
78
+ filePath: `@app/server/live/${fileName}`
79
79
  })
80
80
 
81
81
  buildLogger.step(`Discovered component: ${className} → ${componentName}`)
@@ -116,7 +116,7 @@ export class LiveComponentsGenerator {
116
116
  // Generated at: ${new Date().toISOString()}
117
117
 
118
118
  ${imports}
119
- import { componentRegistry } from "@/core/server/live/ComponentRegistry"
119
+ import { componentRegistry } from "@core/server/live/ComponentRegistry"
120
120
 
121
121
  // Register all components statically for production bundle
122
122
  function registerAllComponents() {
@@ -1,236 +1,236 @@
1
- import { readFileSync, writeFileSync, statSync, readdirSync } from "fs"
2
- import { join, extname } from "path"
3
- import { gzipSync } from "zlib"
4
- import type { OptimizationConfig, OptimizationResult } from "../types/build"
5
- import { buildLogger } from "../utils/build-logger"
6
-
7
- export interface OptimizerConfig {
8
- treeshake: boolean
9
- compress: boolean
10
- removeUnusedCSS: boolean
11
- optimizeImages: boolean
12
- bundleAnalysis: boolean
13
- }
14
-
15
- export class Optimizer {
16
- private config: OptimizerConfig
17
-
18
- constructor(config: OptimizerConfig) {
19
- this.config = config
20
- }
21
-
22
- async optimize(buildPath: string): Promise<OptimizationResult> {
23
- buildLogger.section('Build Optimization', '🔧')
24
-
25
- const startTime = Date.now()
26
- const results: OptimizationResult = {
27
- success: true,
28
- duration: 0,
29
- originalSize: 0,
30
- optimizedSize: 0,
31
- compressionRatio: 0,
32
- optimizations: []
33
- }
34
-
35
- try {
36
- // Get original size
37
- results.originalSize = await this.calculateDirectorySize(buildPath)
38
- buildLogger.step(`Original size: ${buildLogger.formatSize(results.originalSize)}`)
39
-
40
- // Apply optimizations (minification removed for compatibility)
41
-
42
- if (this.config.compress) {
43
- await this.compressAssets(buildPath, results)
44
- }
45
-
46
- if (this.config.removeUnusedCSS) {
47
- await this.removeUnusedCSS(buildPath, results)
48
- }
49
-
50
- if (this.config.optimizeImages) {
51
- await this.optimizeImages(buildPath, results)
52
- }
53
-
54
- if (this.config.bundleAnalysis) {
55
- await this.analyzeBundles(buildPath, results)
56
- }
57
-
58
- // Calculate final size and compression ratio
59
- results.optimizedSize = await this.calculateDirectorySize(buildPath)
60
- results.compressionRatio = results.originalSize > 0
61
- ? ((results.originalSize - results.optimizedSize) / results.originalSize) * 100
62
- : 0
63
-
64
- results.duration = Date.now() - startTime
65
-
66
- buildLogger.success(`Optimization completed in ${buildLogger.formatDuration(results.duration)}`)
67
-
68
- // Create optimization summary table
69
- const optimizationData = results.optimizations.map(opt => ({
70
- type: opt.type,
71
- description: opt.description,
72
- saved: buildLogger.formatSize(opt.sizeSaved)
73
- }))
74
-
75
- if (optimizationData.length > 0) {
76
- buildLogger.table(
77
- [
78
- { header: 'Optimization', key: 'type', width: 20, align: 'left', color: 'cyan' },
79
- { header: 'Description', key: 'description', width: 35, align: 'left' },
80
- { header: 'Size Saved', key: 'saved', width: 12, align: 'right', color: 'green' }
81
- ],
82
- optimizationData
83
- )
84
- }
85
-
86
- return results
87
-
88
- } catch (error) {
89
- results.success = false
90
- results.duration = Date.now() - startTime
91
- results.error = error instanceof Error ? error.message : "Unknown optimization error"
92
-
93
- buildLogger.error(`Optimization failed: ${results.error}`)
94
- return results
95
- }
96
- }
97
-
98
- // Minification methods removed for compatibility with Bun bundler
99
-
100
- private async compressAssets(buildPath: string, results: OptimizationResult): Promise<void> {
101
- buildLogger.step("Compressing assets...")
102
-
103
- const files = this.getFilesRecursively(buildPath)
104
- let compressedCount = 0
105
-
106
- for (const file of files) {
107
- const ext = extname(file).toLowerCase()
108
-
109
- if (['.js', '.css', '.html', '.json', '.svg'].includes(ext)) {
110
- try {
111
- const content = readFileSync(file)
112
- const compressed = gzipSync(content)
113
-
114
- // Only create .gz file if it's significantly smaller
115
- if (compressed.length < content.length * 0.9) {
116
- writeFileSync(file + '.gz', compressed)
117
- compressedCount++
118
- }
119
- } catch (error) {
120
- // Silently skip files that can't be compressed
121
- }
122
- }
123
- }
124
-
125
- buildLogger.success(`Compressed ${compressedCount} files`)
126
- results.optimizations.push({
127
- type: 'compression',
128
- description: `Created gzip versions for ${compressedCount} files`,
129
- sizeSaved: 0
130
- })
131
- }
132
-
133
- private async removeUnusedCSS(buildPath: string, results: OptimizationResult): Promise<void> {
134
- buildLogger.step("Analyzing CSS...")
135
-
136
- // This is a placeholder - real implementation would use PurgeCSS or similar
137
- results.optimizations.push({
138
- type: 'css-purging',
139
- description: 'CSS purging not implemented yet',
140
- sizeSaved: 0
141
- })
142
- }
143
-
144
- private async optimizeImages(buildPath: string, results: OptimizationResult): Promise<void> {
145
- buildLogger.step("Optimizing images...")
146
-
147
- // This is a placeholder - real implementation would use imagemin or similar
148
- results.optimizations.push({
149
- type: 'image-optimization',
150
- description: 'Image optimization not implemented yet',
151
- sizeSaved: 0
152
- })
153
- }
154
-
155
- private async analyzeBundles(buildPath: string, results: OptimizationResult): Promise<void> {
156
- buildLogger.step("Analyzing bundles...")
157
-
158
- const files = this.getFilesRecursively(buildPath)
159
- const jsFiles = files.filter(f => extname(f) === '.js')
160
-
161
- let totalJSSize = 0
162
- for (const file of jsFiles) {
163
- totalJSSize += statSync(file).size
164
- }
165
-
166
- results.optimizations.push({
167
- type: 'bundle-analysis',
168
- description: `Analyzed ${jsFiles.length} JS bundles (${(totalJSSize / 1024).toFixed(2)} KB total)`,
169
- sizeSaved: 0
170
- })
171
- }
172
-
173
- private async calculateDirectorySize(dirPath: string): Promise<number> {
174
- const files = this.getFilesRecursively(dirPath)
175
- let totalSize = 0
176
-
177
- for (const file of files) {
178
- try {
179
- totalSize += statSync(file).size
180
- } catch (error) {
181
- // Ignore files that can't be read
182
- }
183
- }
184
-
185
- return totalSize
186
- }
187
-
188
- private getFilesRecursively(dir: string): string[] {
189
- const files: string[] = []
190
-
191
- try {
192
- const items = readdirSync(dir, { withFileTypes: true })
193
-
194
- for (const item of items) {
195
- const fullPath = join(dir, item.name)
196
-
197
- if (item.isDirectory()) {
198
- files.push(...this.getFilesRecursively(fullPath))
199
- } else {
200
- files.push(fullPath)
201
- }
202
- }
203
- } catch (error) {
204
- // Ignore directories that can't be read
205
- }
206
-
207
- return files
208
- }
209
-
210
- async createOptimizationReport(result: OptimizationResult): Promise<string> {
211
- const report = `
212
- # Build Optimization Report
213
-
214
- ## Summary
215
- - **Status**: ${result.success ? '✅ Success' : '❌ Failed'}
216
- - **Duration**: ${result.duration}ms
217
- - **Original Size**: ${(result.originalSize / 1024).toFixed(2)} KB
218
- - **Optimized Size**: ${(result.optimizedSize / 1024).toFixed(2)} KB
219
- - **Size Reduction**: ${result.compressionRatio.toFixed(2)}%
220
-
221
- ## Optimizations Applied
222
-
223
- ${result.optimizations.map(opt =>
224
- `### ${opt.type.charAt(0).toUpperCase() + opt.type.slice(1)}
225
- - ${opt.description}
226
- - Size Saved: ${(opt.sizeSaved / 1024).toFixed(2)} KB`
227
- ).join('\n\n')}
228
-
229
- ${result.error ? `## Error\n${result.error}` : ''}
230
-
231
- Generated at: ${new Date().toISOString()}
232
- `
233
-
234
- return report.trim()
235
- }
1
+ import { readFileSync, writeFileSync, statSync, readdirSync } from "fs"
2
+ import { join, extname } from "path"
3
+ import { gzipSync } from "zlib"
4
+ import type { OptimizationConfig, OptimizationResult } from "../types/build"
5
+ import { buildLogger } from "../utils/build-logger"
6
+
7
+ export interface OptimizerConfig {
8
+ treeshake: boolean
9
+ compress: boolean
10
+ removeUnusedCSS: boolean
11
+ optimizeImages: boolean
12
+ bundleAnalysis: boolean
13
+ }
14
+
15
+ export class Optimizer {
16
+ private config: OptimizerConfig
17
+
18
+ constructor(config: OptimizerConfig) {
19
+ this.config = config
20
+ }
21
+
22
+ async optimize(buildPath: string): Promise<OptimizationResult> {
23
+ buildLogger.section('Build Optimization', '🔧')
24
+
25
+ const startTime = Date.now()
26
+ const results: OptimizationResult = {
27
+ success: true,
28
+ duration: 0,
29
+ originalSize: 0,
30
+ optimizedSize: 0,
31
+ compressionRatio: 0,
32
+ optimizations: []
33
+ }
34
+
35
+ try {
36
+ // Get original size
37
+ results.originalSize = await this.calculateDirectorySize(buildPath)
38
+ buildLogger.step(`Original size: ${buildLogger.formatSize(results.originalSize)}`)
39
+
40
+ // Apply optimizations (minification removed for compatibility)
41
+
42
+ if (this.config.compress) {
43
+ await this.compressAssets(buildPath, results)
44
+ }
45
+
46
+ if (this.config.removeUnusedCSS) {
47
+ await this.removeUnusedCSS(buildPath, results)
48
+ }
49
+
50
+ if (this.config.optimizeImages) {
51
+ await this.optimizeImages(buildPath, results)
52
+ }
53
+
54
+ if (this.config.bundleAnalysis) {
55
+ await this.analyzeBundles(buildPath, results)
56
+ }
57
+
58
+ // Calculate final size and compression ratio
59
+ results.optimizedSize = await this.calculateDirectorySize(buildPath)
60
+ results.compressionRatio = results.originalSize > 0
61
+ ? ((results.originalSize - results.optimizedSize) / results.originalSize) * 100
62
+ : 0
63
+
64
+ results.duration = Date.now() - startTime
65
+
66
+ buildLogger.success(`Optimization completed in ${buildLogger.formatDuration(results.duration)}`)
67
+
68
+ // Create optimization summary table
69
+ const optimizationData = results.optimizations.map(opt => ({
70
+ type: opt.type,
71
+ description: opt.description,
72
+ saved: buildLogger.formatSize(opt.sizeSaved)
73
+ }))
74
+
75
+ if (optimizationData.length > 0) {
76
+ buildLogger.table(
77
+ [
78
+ { header: 'Optimization', key: 'type', width: 20, align: 'left', color: 'cyan' },
79
+ { header: 'Description', key: 'description', width: 35, align: 'left' },
80
+ { header: 'Size Saved', key: 'saved', width: 12, align: 'right', color: 'green' }
81
+ ],
82
+ optimizationData
83
+ )
84
+ }
85
+
86
+ return results
87
+
88
+ } catch (error) {
89
+ results.success = false
90
+ results.duration = Date.now() - startTime
91
+ results.error = error instanceof Error ? error.message : "Unknown optimization error"
92
+
93
+ buildLogger.error(`Optimization failed: ${results.error}`)
94
+ return results
95
+ }
96
+ }
97
+
98
+ // Minification methods removed for compatibility with Bun bundler
99
+
100
+ private async compressAssets(buildPath: string, results: OptimizationResult): Promise<void> {
101
+ buildLogger.step("Compressing assets...")
102
+
103
+ const files = this.getFilesRecursively(buildPath)
104
+ let compressedCount = 0
105
+
106
+ for (const file of files) {
107
+ const ext = extname(file).toLowerCase()
108
+
109
+ if (['.js', '.css', '.html', '.json', '.svg'].includes(ext)) {
110
+ try {
111
+ const content = readFileSync(file)
112
+ const compressed = gzipSync(content)
113
+
114
+ // Only create .gz file if it's significantly smaller
115
+ if (compressed.length < content.length * 0.9) {
116
+ writeFileSync(file + '.gz', compressed)
117
+ compressedCount++
118
+ }
119
+ } catch (error) {
120
+ // Silently skip files that can't be compressed
121
+ }
122
+ }
123
+ }
124
+
125
+ buildLogger.success(`Compressed ${compressedCount} files`)
126
+ results.optimizations.push({
127
+ type: 'compression',
128
+ description: `Created gzip versions for ${compressedCount} files`,
129
+ sizeSaved: 0
130
+ })
131
+ }
132
+
133
+ private async removeUnusedCSS(buildPath: string, results: OptimizationResult): Promise<void> {
134
+ buildLogger.step("Analyzing CSS...")
135
+
136
+ // This is a placeholder - real implementation would use PurgeCSS or similar
137
+ results.optimizations.push({
138
+ type: 'css-purging',
139
+ description: 'CSS purging not implemented yet',
140
+ sizeSaved: 0
141
+ })
142
+ }
143
+
144
+ private async optimizeImages(buildPath: string, results: OptimizationResult): Promise<void> {
145
+ buildLogger.step("Optimizing images...")
146
+
147
+ // This is a placeholder - real implementation would use imagemin or similar
148
+ results.optimizations.push({
149
+ type: 'image-optimization',
150
+ description: 'Image optimization not implemented yet',
151
+ sizeSaved: 0
152
+ })
153
+ }
154
+
155
+ private async analyzeBundles(buildPath: string, results: OptimizationResult): Promise<void> {
156
+ buildLogger.step("Analyzing bundles...")
157
+
158
+ const files = this.getFilesRecursively(buildPath)
159
+ const jsFiles = files.filter(f => extname(f) === '.js')
160
+
161
+ let totalJSSize = 0
162
+ for (const file of jsFiles) {
163
+ totalJSSize += statSync(file).size
164
+ }
165
+
166
+ results.optimizations.push({
167
+ type: 'bundle-analysis',
168
+ description: `Analyzed ${jsFiles.length} JS bundles (${(totalJSSize / 1024).toFixed(2)} KB total)`,
169
+ sizeSaved: 0
170
+ })
171
+ }
172
+
173
+ private async calculateDirectorySize(dirPath: string): Promise<number> {
174
+ const files = this.getFilesRecursively(dirPath)
175
+ let totalSize = 0
176
+
177
+ for (const file of files) {
178
+ try {
179
+ totalSize += statSync(file).size
180
+ } catch (error) {
181
+ // Ignore files that can't be read
182
+ }
183
+ }
184
+
185
+ return totalSize
186
+ }
187
+
188
+ private getFilesRecursively(dir: string): string[] {
189
+ const files: string[] = []
190
+
191
+ try {
192
+ const items = readdirSync(dir, { withFileTypes: true })
193
+
194
+ for (const item of items) {
195
+ const fullPath = join(dir, item.name)
196
+
197
+ if (item.isDirectory()) {
198
+ files.push(...this.getFilesRecursively(fullPath))
199
+ } else {
200
+ files.push(fullPath)
201
+ }
202
+ }
203
+ } catch (error) {
204
+ // Ignore directories that can't be read
205
+ }
206
+
207
+ return files
208
+ }
209
+
210
+ async createOptimizationReport(result: OptimizationResult): Promise<string> {
211
+ const report = `
212
+ # Build Optimization Report
213
+
214
+ ## Summary
215
+ - **Status**: ${result.success ? '✅ Success' : '❌ Failed'}
216
+ - **Duration**: ${result.duration}ms
217
+ - **Original Size**: ${(result.originalSize / 1024).toFixed(2)} KB
218
+ - **Optimized Size**: ${(result.optimizedSize / 1024).toFixed(2)} KB
219
+ - **Size Reduction**: ${result.compressionRatio.toFixed(2)}%
220
+
221
+ ## Optimizations Applied
222
+
223
+ ${result.optimizations.map(opt =>
224
+ `### ${opt.type.charAt(0).toUpperCase() + opt.type.slice(1)}
225
+ - ${opt.description}
226
+ - Size Saved: ${(opt.sizeSaved / 1024).toFixed(2)} KB`
227
+ ).join('\n\n')}
228
+
229
+ ${result.error ? `## Error\n${result.error}` : ''}
230
+
231
+ Generated at: ${new Date().toISOString()}
232
+ `
233
+
234
+ return report.trim()
235
+ }
236
236
  }
@@ -1,6 +1,6 @@
1
1
  import type { CliCommand, CliContext, CliArgument, CliOption } from "../plugins/types"
2
- import { getConfigSync } from "@/core/config"
3
- import { logger } from "@/core/utils/logger"
2
+ import { fluxStackConfig } from "@config"
3
+ import { logger } from "@core/utils/logger"
4
4
  import { createTimer, formatBytes, isProduction, isDevelopment } from "../utils/helpers"
5
5
 
6
6
  export class CliCommandRegistry {
@@ -9,7 +9,7 @@ export class CliCommandRegistry {
9
9
  private context: CliContext
10
10
 
11
11
  constructor() {
12
- const config = getConfigSync()
12
+ const config = fluxStackConfig
13
13
 
14
14
  this.context = {
15
15
  config,
@@ -321,4 +321,6 @@ Use "flux help <command>" for more information about a specific command.`)
321
321
  }
322
322
 
323
323
  // Global registry instance
324
- export const cliRegistry = new CliCommandRegistry()
324
+ export const cliRegistry = new CliCommandRegistry()
325
+
326
+ export type CLICommand = CliCommand