create-fluxstack 1.10.1 → 1.12.1

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 +161 -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 +127 -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
@@ -1,324 +1,324 @@
1
- /**
2
- * FluxStack Build Logger - Beautiful terminal output for build process
3
- * Provides formatted tables, boxes, and colored output
4
- */
5
-
6
- // ANSI Color codes
7
- const colors = {
8
- reset: '\x1b[0m',
9
- bright: '\x1b[1m',
10
- dim: '\x1b[2m',
11
-
12
- // Text colors
13
- cyan: '\x1b[36m',
14
- blue: '\x1b[34m',
15
- green: '\x1b[32m',
16
- yellow: '\x1b[33m',
17
- red: '\x1b[31m',
18
- magenta: '\x1b[35m',
19
- white: '\x1b[37m',
20
- gray: '\x1b[90m',
21
-
22
- // Background colors
23
- bgCyan: '\x1b[46m',
24
- bgBlue: '\x1b[44m',
25
- bgGreen: '\x1b[42m',
26
- bgYellow: '\x1b[43m',
27
- bgRed: '\x1b[41m',
28
- }
29
-
30
- // Box drawing characters
31
- const box = {
32
- topLeft: '╭',
33
- topRight: '╮',
34
- bottomLeft: '╰',
35
- bottomRight: '╯',
36
- horizontal: '─',
37
- vertical: '│',
38
- verticalRight: '├',
39
- verticalLeft: '┤',
40
- horizontalDown: '┬',
41
- horizontalUp: '┴',
42
- cross: '┼',
43
- }
44
-
45
- export interface TableColumn {
46
- header: string
47
- key: string
48
- width?: number
49
- align?: 'left' | 'right' | 'center'
50
- color?: keyof typeof colors
51
- }
52
-
53
- export interface TableRow {
54
- [key: string]: string | number
55
- }
56
-
57
- export class BuildLogger {
58
- private indent = ''
59
- private startTime = Date.now()
60
-
61
- /**
62
- * Print a beautiful header banner
63
- */
64
- header(title: string) {
65
- const width = 60
66
- const padding = Math.floor((width - title.length - 2) / 2)
67
- const paddingRight = width - title.length - 2 - padding
68
-
69
- console.log()
70
- console.log(colors.cyan + colors.bright + box.topLeft + box.horizontal.repeat(width) + box.topRight + colors.reset)
71
- console.log(colors.cyan + box.vertical + ' '.repeat(padding) + colors.bright + colors.white + title + colors.cyan + ' '.repeat(paddingRight) + box.vertical + colors.reset)
72
- console.log(colors.cyan + box.bottomLeft + box.horizontal.repeat(width) + box.bottomRight + colors.reset)
73
- console.log()
74
- }
75
-
76
- /**
77
- * Print a section header
78
- */
79
- section(title: string, icon: string = '📦') {
80
- console.log()
81
- console.log(colors.bright + colors.blue + `${icon} ${title}` + colors.reset)
82
- console.log(colors.dim + colors.gray + box.horizontal.repeat(50) + colors.reset)
83
- }
84
-
85
- /**
86
- * Print a success message
87
- */
88
- success(message: string) {
89
- console.log(colors.green + '✓ ' + colors.reset + message)
90
- }
91
-
92
- /**
93
- * Print an error message
94
- */
95
- error(message: string) {
96
- console.log(colors.red + '✗ ' + colors.reset + message)
97
- }
98
-
99
- /**
100
- * Print a warning message
101
- */
102
- warn(message: string) {
103
- console.log(colors.yellow + '⚠ ' + colors.reset + message)
104
- }
105
-
106
- /**
107
- * Print an info message
108
- */
109
- info(message: string, icon: string = '→') {
110
- console.log(colors.cyan + icon + ' ' + colors.reset + message)
111
- }
112
-
113
- /**
114
- * Print a step message
115
- */
116
- step(message: string, icon: string = '▸') {
117
- console.log(colors.dim + colors.gray + icon + ' ' + colors.reset + message)
118
- }
119
-
120
- /**
121
- * Print a table
122
- */
123
- table(columns: TableColumn[], rows: TableRow[]) {
124
- if (rows.length === 0) {
125
- this.warn('No data to display')
126
- return
127
- }
128
-
129
- // Calculate column widths
130
- const widths = columns.map(col => {
131
- if (col.width) return col.width
132
- const maxContentWidth = Math.max(
133
- col.header.length,
134
- ...rows.map(row => String(row[col.key] || '').length)
135
- )
136
- return Math.min(maxContentWidth, 40) // Max 40 chars per column
137
- })
138
-
139
- const totalWidth = widths.reduce((sum, w) => sum + w, 0) + (columns.length - 1) * 3 + 4
140
-
141
- // Print top border
142
- console.log(
143
- colors.gray + box.topLeft +
144
- widths.map((w, i) =>
145
- box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.horizontalDown : '')
146
- ).join('') +
147
- box.topRight + colors.reset
148
- )
149
-
150
- // Print header
151
- const headerRow = columns.map((col, i) => {
152
- const content = this.padContent(col.header, widths[i], 'center')
153
- return colors.bright + colors.white + content + colors.reset
154
- }).join(colors.gray + ' │ ' + colors.reset)
155
-
156
- console.log(colors.gray + box.vertical + ' ' + colors.reset + headerRow + colors.gray + ' ' + box.vertical + colors.reset)
157
-
158
- // Print header separator
159
- console.log(
160
- colors.gray + box.verticalRight +
161
- widths.map((w, i) =>
162
- box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.cross : '')
163
- ).join('') +
164
- box.verticalLeft + colors.reset
165
- )
166
-
167
- // Print rows
168
- rows.forEach((row, rowIndex) => {
169
- const rowContent = columns.map((col, i) => {
170
- const value = String(row[col.key] || '')
171
- const content = this.padContent(value, widths[i], col.align || 'left')
172
- const color = col.color ? colors[col.color] : ''
173
- return color + content + colors.reset
174
- }).join(colors.gray + ' │ ' + colors.reset)
175
-
176
- console.log(colors.gray + box.vertical + ' ' + colors.reset + rowContent + colors.gray + ' ' + box.vertical + colors.reset)
177
- })
178
-
179
- // Print bottom border
180
- console.log(
181
- colors.gray + box.bottomLeft +
182
- widths.map((w, i) =>
183
- box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.horizontalUp : '')
184
- ).join('') +
185
- box.bottomRight + colors.reset
186
- )
187
- }
188
-
189
- /**
190
- * Print a simple info box
191
- */
192
- box(title: string, items: Array<{ label: string; value: string | number; color?: keyof typeof colors }>) {
193
- const maxLabelWidth = Math.max(...items.map(i => i.label.length))
194
- const maxValueWidth = Math.max(...items.map(i => String(i.value).length))
195
- const contentWidth = maxLabelWidth + maxValueWidth + 3
196
- const boxWidth = Math.max(contentWidth, title.length) + 4
197
-
198
- // Top border with title
199
- console.log()
200
- console.log(colors.cyan + box.topLeft + box.horizontal.repeat(2) + colors.bright + colors.white + title + colors.cyan + box.horizontal.repeat(boxWidth - title.length - 2) + box.topRight + colors.reset)
201
-
202
- // Content
203
- items.forEach(item => {
204
- const label = item.label.padEnd(maxLabelWidth)
205
- const value = String(item.value)
206
- const valueColor = item.color ? colors[item.color] : colors.white
207
- console.log(
208
- colors.cyan + box.vertical + ' ' + colors.reset +
209
- colors.gray + label + colors.reset +
210
- colors.dim + ' : ' + colors.reset +
211
- valueColor + colors.bright + value + colors.reset +
212
- ' '.repeat(boxWidth - label.length - value.length - 3) +
213
- colors.cyan + box.vertical + colors.reset
214
- )
215
- })
216
-
217
- // Bottom border
218
- console.log(colors.cyan + box.bottomLeft + box.horizontal.repeat(boxWidth) + box.bottomRight + colors.reset)
219
- console.log()
220
- }
221
-
222
- /**
223
- * Print a progress indicator
224
- */
225
- progress(current: number, total: number, label: string) {
226
- const percentage = Math.round((current / total) * 100)
227
- const barLength = 30
228
- const filled = Math.round((percentage / 100) * barLength)
229
- const empty = barLength - filled
230
-
231
- const bar = colors.green + '█'.repeat(filled) + colors.gray + '░'.repeat(empty) + colors.reset
232
- console.log(`${label} [${bar}] ${percentage}% (${current}/${total})`)
233
- }
234
-
235
- /**
236
- * Start a timer
237
- */
238
- startTimer(label?: string) {
239
- this.startTime = Date.now()
240
- if (label) {
241
- this.info(label, '⏱')
242
- }
243
- }
244
-
245
- /**
246
- * End timer and print elapsed time
247
- */
248
- endTimer(label: string = 'Completed') {
249
- const elapsed = Date.now() - this.startTime
250
- const seconds = (elapsed / 1000).toFixed(2)
251
- this.success(`${label} in ${colors.bright}${seconds}s${colors.reset}`)
252
- }
253
-
254
- /**
255
- * Print a summary box
256
- */
257
- summary(title: string, stats: Array<{ label: string; value: string | number; highlight?: boolean }>) {
258
- console.log()
259
- console.log(colors.bright + colors.green + '╔═══════════════════════════════════════════════════════════╗' + colors.reset)
260
- console.log(colors.bright + colors.green + '║' + colors.reset + colors.bright + colors.white + ` ${title}`.padEnd(60) + colors.bright + colors.green + '║' + colors.reset)
261
- console.log(colors.bright + colors.green + '╠═══════════════════════════════════════════════════════════╣' + colors.reset)
262
-
263
- stats.forEach(stat => {
264
- const label = ` ${stat.label}:`
265
- const value = String(stat.value)
266
- const valueColor = stat.highlight ? colors.yellow + colors.bright : colors.white
267
- const padding = 60 - label.length - value.length - 1
268
- console.log(
269
- colors.bright + colors.green + '║' + colors.reset +
270
- colors.cyan + label + colors.reset +
271
- ' '.repeat(Math.max(padding, 1)) +
272
- valueColor + value + colors.reset +
273
- colors.bright + colors.green + ' ║' + colors.reset
274
- )
275
- })
276
-
277
- console.log(colors.bright + colors.green + '╚═══════════════════════════════════════════════════════════╝' + colors.reset)
278
- console.log()
279
- }
280
-
281
- /**
282
- * Pad content based on alignment
283
- */
284
- private padContent(content: string, width: number, align: 'left' | 'right' | 'center' = 'left'): string {
285
- if (content.length >= width) {
286
- return content.slice(0, width)
287
- }
288
-
289
- const padding = width - content.length
290
-
291
- switch (align) {
292
- case 'right':
293
- return ' '.repeat(padding) + content
294
- case 'center':
295
- const leftPad = Math.floor(padding / 2)
296
- const rightPad = padding - leftPad
297
- return ' '.repeat(leftPad) + content + ' '.repeat(rightPad)
298
- default:
299
- return content + ' '.repeat(padding)
300
- }
301
- }
302
-
303
- /**
304
- * Format file size
305
- */
306
- formatSize(bytes: number): string {
307
- if (bytes === 0) return '0 B'
308
- const k = 1024
309
- const sizes = ['B', 'KB', 'MB', 'GB']
310
- const i = Math.floor(Math.log(bytes) / Math.log(k))
311
- return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
312
- }
313
-
314
- /**
315
- * Format duration
316
- */
317
- formatDuration(ms: number): string {
318
- if (ms < 1000) return `${ms}ms`
319
- return `${(ms / 1000).toFixed(2)}s`
320
- }
321
- }
322
-
323
- // Export singleton instance
324
- export const buildLogger = new BuildLogger()
1
+ /**
2
+ * FluxStack Build Logger - Beautiful terminal output for build process
3
+ * Provides formatted tables, boxes, and colored output
4
+ */
5
+
6
+ // ANSI Color codes
7
+ const colors = {
8
+ reset: '\x1b[0m',
9
+ bright: '\x1b[1m',
10
+ dim: '\x1b[2m',
11
+
12
+ // Text colors
13
+ cyan: '\x1b[36m',
14
+ blue: '\x1b[34m',
15
+ green: '\x1b[32m',
16
+ yellow: '\x1b[33m',
17
+ red: '\x1b[31m',
18
+ magenta: '\x1b[35m',
19
+ white: '\x1b[37m',
20
+ gray: '\x1b[90m',
21
+
22
+ // Background colors
23
+ bgCyan: '\x1b[46m',
24
+ bgBlue: '\x1b[44m',
25
+ bgGreen: '\x1b[42m',
26
+ bgYellow: '\x1b[43m',
27
+ bgRed: '\x1b[41m',
28
+ }
29
+
30
+ // Box drawing characters
31
+ const box = {
32
+ topLeft: '╭',
33
+ topRight: '╮',
34
+ bottomLeft: '╰',
35
+ bottomRight: '╯',
36
+ horizontal: '─',
37
+ vertical: '│',
38
+ verticalRight: '├',
39
+ verticalLeft: '┤',
40
+ horizontalDown: '┬',
41
+ horizontalUp: '┴',
42
+ cross: '┼',
43
+ }
44
+
45
+ export interface TableColumn {
46
+ header: string
47
+ key: string
48
+ width?: number
49
+ align?: 'left' | 'right' | 'center'
50
+ color?: keyof typeof colors
51
+ }
52
+
53
+ export interface TableRow {
54
+ [key: string]: string | number
55
+ }
56
+
57
+ export class BuildLogger {
58
+ private indent = ''
59
+ private startTime = Date.now()
60
+
61
+ /**
62
+ * Print a beautiful header banner
63
+ */
64
+ header(title: string) {
65
+ const width = 60
66
+ const padding = Math.floor((width - title.length - 2) / 2)
67
+ const paddingRight = width - title.length - 2 - padding
68
+
69
+ console.log()
70
+ console.log(colors.cyan + colors.bright + box.topLeft + box.horizontal.repeat(width) + box.topRight + colors.reset)
71
+ console.log(colors.cyan + box.vertical + ' '.repeat(padding) + colors.bright + colors.white + title + colors.cyan + ' '.repeat(paddingRight) + box.vertical + colors.reset)
72
+ console.log(colors.cyan + box.bottomLeft + box.horizontal.repeat(width) + box.bottomRight + colors.reset)
73
+ console.log()
74
+ }
75
+
76
+ /**
77
+ * Print a section header
78
+ */
79
+ section(title: string, icon: string = '📦') {
80
+ console.log()
81
+ console.log(colors.bright + colors.blue + `${icon} ${title}` + colors.reset)
82
+ console.log(colors.dim + colors.gray + box.horizontal.repeat(50) + colors.reset)
83
+ }
84
+
85
+ /**
86
+ * Print a success message
87
+ */
88
+ success(message: string) {
89
+ console.log(colors.green + '✓ ' + colors.reset + message)
90
+ }
91
+
92
+ /**
93
+ * Print an error message
94
+ */
95
+ error(message: string) {
96
+ console.log(colors.red + '✗ ' + colors.reset + message)
97
+ }
98
+
99
+ /**
100
+ * Print a warning message
101
+ */
102
+ warn(message: string) {
103
+ console.log(colors.yellow + '⚠ ' + colors.reset + message)
104
+ }
105
+
106
+ /**
107
+ * Print an info message
108
+ */
109
+ info(message: string, icon: string = '→') {
110
+ console.log(colors.cyan + icon + ' ' + colors.reset + message)
111
+ }
112
+
113
+ /**
114
+ * Print a step message
115
+ */
116
+ step(message: string, icon: string = '▸') {
117
+ console.log(colors.dim + colors.gray + icon + ' ' + colors.reset + message)
118
+ }
119
+
120
+ /**
121
+ * Print a table
122
+ */
123
+ table(columns: TableColumn[], rows: TableRow[]) {
124
+ if (rows.length === 0) {
125
+ this.warn('No data to display')
126
+ return
127
+ }
128
+
129
+ // Calculate column widths
130
+ const widths = columns.map(col => {
131
+ if (col.width) return col.width
132
+ const maxContentWidth = Math.max(
133
+ col.header.length,
134
+ ...rows.map(row => String(row[col.key] || '').length)
135
+ )
136
+ return Math.min(maxContentWidth, 40) // Max 40 chars per column
137
+ })
138
+
139
+ const totalWidth = widths.reduce((sum, w) => sum + w, 0) + (columns.length - 1) * 3 + 4
140
+
141
+ // Print top border
142
+ console.log(
143
+ colors.gray + box.topLeft +
144
+ widths.map((w, i) =>
145
+ box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.horizontalDown : '')
146
+ ).join('') +
147
+ box.topRight + colors.reset
148
+ )
149
+
150
+ // Print header
151
+ const headerRow = columns.map((col, i) => {
152
+ const content = this.padContent(col.header, widths[i], 'center')
153
+ return colors.bright + colors.white + content + colors.reset
154
+ }).join(colors.gray + ' │ ' + colors.reset)
155
+
156
+ console.log(colors.gray + box.vertical + ' ' + colors.reset + headerRow + colors.gray + ' ' + box.vertical + colors.reset)
157
+
158
+ // Print header separator
159
+ console.log(
160
+ colors.gray + box.verticalRight +
161
+ widths.map((w, i) =>
162
+ box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.cross : '')
163
+ ).join('') +
164
+ box.verticalLeft + colors.reset
165
+ )
166
+
167
+ // Print rows
168
+ rows.forEach((row, rowIndex) => {
169
+ const rowContent = columns.map((col, i) => {
170
+ const value = String(row[col.key] || '')
171
+ const content = this.padContent(value, widths[i], col.align || 'left')
172
+ const color = col.color ? colors[col.color] : ''
173
+ return color + content + colors.reset
174
+ }).join(colors.gray + ' │ ' + colors.reset)
175
+
176
+ console.log(colors.gray + box.vertical + ' ' + colors.reset + rowContent + colors.gray + ' ' + box.vertical + colors.reset)
177
+ })
178
+
179
+ // Print bottom border
180
+ console.log(
181
+ colors.gray + box.bottomLeft +
182
+ widths.map((w, i) =>
183
+ box.horizontal.repeat(w + 2) + (i < widths.length - 1 ? box.horizontalUp : '')
184
+ ).join('') +
185
+ box.bottomRight + colors.reset
186
+ )
187
+ }
188
+
189
+ /**
190
+ * Print a simple info box
191
+ */
192
+ box(title: string, items: Array<{ label: string; value: string | number; color?: keyof typeof colors }>) {
193
+ const maxLabelWidth = Math.max(...items.map(i => i.label.length))
194
+ const maxValueWidth = Math.max(...items.map(i => String(i.value).length))
195
+ const contentWidth = maxLabelWidth + maxValueWidth + 3
196
+ const boxWidth = Math.max(contentWidth, title.length) + 4
197
+
198
+ // Top border with title
199
+ console.log()
200
+ console.log(colors.cyan + box.topLeft + box.horizontal.repeat(2) + colors.bright + colors.white + title + colors.cyan + box.horizontal.repeat(boxWidth - title.length - 2) + box.topRight + colors.reset)
201
+
202
+ // Content
203
+ items.forEach(item => {
204
+ const label = item.label.padEnd(maxLabelWidth)
205
+ const value = String(item.value)
206
+ const valueColor = item.color ? colors[item.color] : colors.white
207
+ console.log(
208
+ colors.cyan + box.vertical + ' ' + colors.reset +
209
+ colors.gray + label + colors.reset +
210
+ colors.dim + ' : ' + colors.reset +
211
+ valueColor + colors.bright + value + colors.reset +
212
+ ' '.repeat(boxWidth - label.length - value.length - 3) +
213
+ colors.cyan + box.vertical + colors.reset
214
+ )
215
+ })
216
+
217
+ // Bottom border
218
+ console.log(colors.cyan + box.bottomLeft + box.horizontal.repeat(boxWidth) + box.bottomRight + colors.reset)
219
+ console.log()
220
+ }
221
+
222
+ /**
223
+ * Print a progress indicator
224
+ */
225
+ progress(current: number, total: number, label: string) {
226
+ const percentage = Math.round((current / total) * 100)
227
+ const barLength = 30
228
+ const filled = Math.round((percentage / 100) * barLength)
229
+ const empty = barLength - filled
230
+
231
+ const bar = colors.green + '█'.repeat(filled) + colors.gray + '░'.repeat(empty) + colors.reset
232
+ console.log(`${label} [${bar}] ${percentage}% (${current}/${total})`)
233
+ }
234
+
235
+ /**
236
+ * Start a timer
237
+ */
238
+ startTimer(label?: string) {
239
+ this.startTime = Date.now()
240
+ if (label) {
241
+ this.info(label, '⏱')
242
+ }
243
+ }
244
+
245
+ /**
246
+ * End timer and print elapsed time
247
+ */
248
+ endTimer(label: string = 'Completed') {
249
+ const elapsed = Date.now() - this.startTime
250
+ const seconds = (elapsed / 1000).toFixed(2)
251
+ this.success(`${label} in ${colors.bright}${seconds}s${colors.reset}`)
252
+ }
253
+
254
+ /**
255
+ * Print a summary box
256
+ */
257
+ summary(title: string, stats: Array<{ label: string; value: string | number; highlight?: boolean }>) {
258
+ console.log()
259
+ console.log(colors.bright + colors.green + '╔═══════════════════════════════════════════════════════════╗' + colors.reset)
260
+ console.log(colors.bright + colors.green + '║' + colors.reset + colors.bright + colors.white + ` ${title}`.padEnd(60) + colors.bright + colors.green + '║' + colors.reset)
261
+ console.log(colors.bright + colors.green + '╠═══════════════════════════════════════════════════════════╣' + colors.reset)
262
+
263
+ stats.forEach(stat => {
264
+ const label = ` ${stat.label}:`
265
+ const value = String(stat.value)
266
+ const valueColor = stat.highlight ? colors.yellow + colors.bright : colors.white
267
+ const padding = 60 - label.length - value.length - 1
268
+ console.log(
269
+ colors.bright + colors.green + '║' + colors.reset +
270
+ colors.cyan + label + colors.reset +
271
+ ' '.repeat(Math.max(padding, 1)) +
272
+ valueColor + value + colors.reset +
273
+ colors.bright + colors.green + ' ║' + colors.reset
274
+ )
275
+ })
276
+
277
+ console.log(colors.bright + colors.green + '╚═══════════════════════════════════════════════════════════╝' + colors.reset)
278
+ console.log()
279
+ }
280
+
281
+ /**
282
+ * Pad content based on alignment
283
+ */
284
+ private padContent(content: string, width: number, align: 'left' | 'right' | 'center' = 'left'): string {
285
+ if (content.length >= width) {
286
+ return content.slice(0, width)
287
+ }
288
+
289
+ const padding = width - content.length
290
+
291
+ switch (align) {
292
+ case 'right':
293
+ return ' '.repeat(padding) + content
294
+ case 'center':
295
+ const leftPad = Math.floor(padding / 2)
296
+ const rightPad = padding - leftPad
297
+ return ' '.repeat(leftPad) + content + ' '.repeat(rightPad)
298
+ default:
299
+ return content + ' '.repeat(padding)
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Format file size
305
+ */
306
+ formatSize(bytes: number): string {
307
+ if (bytes === 0) return '0 B'
308
+ const k = 1024
309
+ const sizes = ['B', 'KB', 'MB', 'GB']
310
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
311
+ return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`
312
+ }
313
+
314
+ /**
315
+ * Format duration
316
+ */
317
+ formatDuration(ms: number): string {
318
+ if (ms < 1000) return `${ms}ms`
319
+ return `${(ms / 1000).toFixed(2)}s`
320
+ }
321
+ }
322
+
323
+ // Export singleton instance
324
+ export const buildLogger = new BuildLogger()