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
@@ -1,228 +1,228 @@
1
- import type { CliCommand } from "../../plugins/types"
2
- import { generatorRegistry } from "./index"
3
- import type { GeneratorContext, GeneratorOptions } from "./types"
4
- import { promptSystem } from "./prompts"
5
-
6
- export const interactiveGenerateCommand: CliCommand = {
7
- name: 'generate:interactive',
8
- description: 'Generate code interactively with prompts',
9
- usage: 'flux generate:interactive',
10
- aliases: ['gi', 'gen:i'],
11
- category: 'Development',
12
- examples: [
13
- 'flux generate:interactive',
14
- 'flux gi'
15
- ],
16
- handler: async (args, options, context) => {
17
- console.log('🎯 FluxStack Interactive Code Generator\n')
18
-
19
- // Select generator type
20
- const generators = generatorRegistry.getAll()
21
- const generatorChoices = generators.map(gen => ({
22
- name: `${gen.name} - ${gen.description}`,
23
- value: gen.name
24
- }))
25
-
26
- const selectedType = await promptSystem.select(
27
- 'What would you like to generate?',
28
- generatorChoices
29
- )
30
-
31
- const generator = generatorRegistry.get(selectedType)
32
- if (!generator) {
33
- console.error(`❌ Generator not found: ${selectedType}`)
34
- return
35
- }
36
-
37
- // Get name
38
- const name = await promptSystem.input(
39
- `Enter the ${selectedType} name:`,
40
- undefined,
41
- (value) => {
42
- if (!value.trim()) {
43
- return 'Name is required'
44
- }
45
- if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value)) {
46
- return 'Name must start with a letter and contain only letters, numbers, hyphens, and underscores'
47
- }
48
- return true
49
- }
50
- )
51
-
52
- // Get template variant (if applicable)
53
- let template: string | undefined
54
- if (selectedType === 'controller') {
55
- template = await promptSystem.select(
56
- 'Choose controller template:',
57
- [
58
- { name: 'CRUD - Full CRUD operations with validation', value: 'crud' },
59
- { name: 'Minimal - Basic structure only', value: 'minimal' }
60
- ]
61
- )
62
- } else if (selectedType === 'component') {
63
- template = await promptSystem.select(
64
- 'Choose component template:',
65
- [
66
- { name: 'Basic - Simple component', value: 'basic' },
67
- { name: 'Functional - Component with hooks', value: 'functional' },
68
- { name: 'Page - Page component with layout', value: 'page' },
69
- { name: 'Form - Form component with validation', value: 'form' },
70
- { name: 'Full - Complete with tests and stories', value: 'full' }
71
- ]
72
- )
73
- } else if (selectedType === 'service') {
74
- template = await promptSystem.select(
75
- 'Choose service template:',
76
- [
77
- { name: 'CRUD - Full service with repository', value: 'crud' },
78
- { name: 'Repository - Service with repository pattern', value: 'repository' },
79
- { name: 'Minimal - Basic structure only', value: 'minimal' }
80
- ]
81
- )
82
- } else if (selectedType === 'route') {
83
- template = await promptSystem.select(
84
- 'Choose route template:',
85
- [
86
- { name: 'CRUD - Full REST API routes', value: 'crud' },
87
- { name: 'Auth - Authentication routes', value: 'auth' },
88
- { name: 'Minimal - Basic routes only', value: 'minimal' }
89
- ]
90
- )
91
- }
92
-
93
- // Get custom path (optional)
94
- const useCustomPath = await promptSystem.confirm(
95
- 'Do you want to specify a custom path?',
96
- false
97
- )
98
-
99
- let customPath: string | undefined
100
- if (useCustomPath) {
101
- customPath = await promptSystem.input(
102
- 'Enter custom path (relative to project root):'
103
- )
104
- }
105
-
106
- // Confirm overwrite if files exist
107
- const force = await promptSystem.confirm(
108
- 'Overwrite existing files if they exist?',
109
- false
110
- )
111
-
112
- // Show dry run first
113
- console.log('\n📋 Preview of files to be generated:\n')
114
-
115
- const generatorContext: GeneratorContext = {
116
- workingDir: context.workingDir,
117
- config: context.config,
118
- logger: context.logger,
119
- utils: context.utils
120
- }
121
-
122
- const generatorOptions: GeneratorOptions = {
123
- name,
124
- path: customPath,
125
- template,
126
- force,
127
- dryRun: true
128
- }
129
-
130
- try {
131
- await generator.generate(generatorContext, generatorOptions)
132
-
133
- const proceed = await promptSystem.confirm(
134
- '\nProceed with generation?',
135
- true
136
- )
137
-
138
- if (!proceed) {
139
- console.log('❌ Generation cancelled')
140
- return
141
- }
142
-
143
- // Generate for real
144
- generatorOptions.dryRun = false
145
- await generator.generate(generatorContext, generatorOptions)
146
-
147
- console.log(`\n✅ Successfully generated ${selectedType}: ${name}`)
148
-
149
- // Ask if user wants to generate related files
150
- await suggestRelatedGenerations(selectedType, name, generatorContext)
151
-
152
- } catch (error) {
153
- console.error(`❌ Failed to generate ${selectedType}:`, error instanceof Error ? error.message : String(error))
154
- throw error
155
- }
156
- }
157
- }
158
-
159
- async function suggestRelatedGenerations(
160
- generatedType: string,
161
- name: string,
162
- context: GeneratorContext
163
- ): Promise<void> {
164
- const suggestions: Array<{ type: string; description: string }> = []
165
-
166
- switch (generatedType) {
167
- case 'controller':
168
- suggestions.push(
169
- { type: 'service', description: `Generate ${name} service for business logic` },
170
- { type: 'route', description: `Generate ${name} routes to expose the controller` }
171
- )
172
- break
173
- case 'service':
174
- suggestions.push(
175
- { type: 'controller', description: `Generate ${name} controller to use this service` }
176
- )
177
- break
178
- case 'route':
179
- suggestions.push(
180
- { type: 'controller', description: `Generate ${name} controller for route handlers` }
181
- )
182
- break
183
- case 'component':
184
- // No automatic suggestions for components
185
- break
186
- }
187
-
188
- if (suggestions.length === 0) {
189
- return
190
- }
191
-
192
- console.log('\n💡 Suggested next steps:')
193
- for (const suggestion of suggestions) {
194
- console.log(` • ${suggestion.description}`)
195
- }
196
-
197
- const generateRelated = await promptSystem.confirm(
198
- '\nWould you like to generate related files now?',
199
- false
200
- )
201
-
202
- if (!generateRelated) {
203
- return
204
- }
205
-
206
- for (const suggestion of suggestions) {
207
- const shouldGenerate = await promptSystem.confirm(
208
- `Generate ${suggestion.type} for ${name}?`,
209
- true
210
- )
211
-
212
- if (shouldGenerate) {
213
- const generator = generatorRegistry.get(suggestion.type)
214
- if (generator) {
215
- try {
216
- await generator.generate(context, {
217
- name,
218
- force: false,
219
- dryRun: false
220
- })
221
- console.log(`✅ Generated ${suggestion.type}: ${name}`)
222
- } catch (error) {
223
- console.error(`❌ Failed to generate ${suggestion.type}:`, error instanceof Error ? error.message : String(error))
224
- }
225
- }
226
- }
227
- }
1
+ import type { CliCommand } from "../../plugins/types"
2
+ import { generatorRegistry } from "./index"
3
+ import type { GeneratorContext, GeneratorOptions } from "./types"
4
+ import { promptSystem } from "./prompts"
5
+
6
+ export const interactiveGenerateCommand: CliCommand = {
7
+ name: 'generate:interactive',
8
+ description: 'Generate code interactively with prompts',
9
+ usage: 'flux generate:interactive',
10
+ aliases: ['gi', 'gen:i'],
11
+ category: 'Development',
12
+ examples: [
13
+ 'flux generate:interactive',
14
+ 'flux gi'
15
+ ],
16
+ handler: async (args, options, context) => {
17
+ console.log('🎯 FluxStack Interactive Code Generator\n')
18
+
19
+ // Select generator type
20
+ const generators = generatorRegistry.getAll()
21
+ const generatorChoices = generators.map(gen => ({
22
+ name: `${gen.name} - ${gen.description}`,
23
+ value: gen.name
24
+ }))
25
+
26
+ const selectedType = await promptSystem.select(
27
+ 'What would you like to generate?',
28
+ generatorChoices
29
+ )
30
+
31
+ const generator = generatorRegistry.get(selectedType)
32
+ if (!generator) {
33
+ console.error(`❌ Generator not found: ${selectedType}`)
34
+ return
35
+ }
36
+
37
+ // Get name
38
+ const name = await promptSystem.input(
39
+ `Enter the ${selectedType} name:`,
40
+ undefined,
41
+ (value) => {
42
+ if (!value.trim()) {
43
+ return 'Name is required'
44
+ }
45
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(value)) {
46
+ return 'Name must start with a letter and contain only letters, numbers, hyphens, and underscores'
47
+ }
48
+ return true
49
+ }
50
+ )
51
+
52
+ // Get template variant (if applicable)
53
+ let template: string | undefined
54
+ if (selectedType === 'controller') {
55
+ template = await promptSystem.select(
56
+ 'Choose controller template:',
57
+ [
58
+ { name: 'CRUD - Full CRUD operations with validation', value: 'crud' },
59
+ { name: 'Minimal - Basic structure only', value: 'minimal' }
60
+ ]
61
+ )
62
+ } else if (selectedType === 'component') {
63
+ template = await promptSystem.select(
64
+ 'Choose component template:',
65
+ [
66
+ { name: 'Basic - Simple component', value: 'basic' },
67
+ { name: 'Functional - Component with hooks', value: 'functional' },
68
+ { name: 'Page - Page component with layout', value: 'page' },
69
+ { name: 'Form - Form component with validation', value: 'form' },
70
+ { name: 'Full - Complete with tests and stories', value: 'full' }
71
+ ]
72
+ )
73
+ } else if (selectedType === 'service') {
74
+ template = await promptSystem.select(
75
+ 'Choose service template:',
76
+ [
77
+ { name: 'CRUD - Full service with repository', value: 'crud' },
78
+ { name: 'Repository - Service with repository pattern', value: 'repository' },
79
+ { name: 'Minimal - Basic structure only', value: 'minimal' }
80
+ ]
81
+ )
82
+ } else if (selectedType === 'route') {
83
+ template = await promptSystem.select(
84
+ 'Choose route template:',
85
+ [
86
+ { name: 'CRUD - Full REST API routes', value: 'crud' },
87
+ { name: 'Auth - Authentication routes', value: 'auth' },
88
+ { name: 'Minimal - Basic routes only', value: 'minimal' }
89
+ ]
90
+ )
91
+ }
92
+
93
+ // Get custom path (optional)
94
+ const useCustomPath = await promptSystem.confirm(
95
+ 'Do you want to specify a custom path?',
96
+ false
97
+ )
98
+
99
+ let customPath: string | undefined
100
+ if (useCustomPath) {
101
+ customPath = await promptSystem.input(
102
+ 'Enter custom path (relative to project root):'
103
+ )
104
+ }
105
+
106
+ // Confirm overwrite if files exist
107
+ const force = await promptSystem.confirm(
108
+ 'Overwrite existing files if they exist?',
109
+ false
110
+ )
111
+
112
+ // Show dry run first
113
+ console.log('\n📋 Preview of files to be generated:\n')
114
+
115
+ const generatorContext: GeneratorContext = {
116
+ workingDir: context.workingDir,
117
+ config: context.config,
118
+ logger: context.logger,
119
+ utils: context.utils
120
+ }
121
+
122
+ const generatorOptions: GeneratorOptions = {
123
+ name,
124
+ path: customPath,
125
+ template,
126
+ force,
127
+ dryRun: true
128
+ }
129
+
130
+ try {
131
+ await generator.generate(generatorContext, generatorOptions)
132
+
133
+ const proceed = await promptSystem.confirm(
134
+ '\nProceed with generation?',
135
+ true
136
+ )
137
+
138
+ if (!proceed) {
139
+ console.log('❌ Generation cancelled')
140
+ return
141
+ }
142
+
143
+ // Generate for real
144
+ generatorOptions.dryRun = false
145
+ await generator.generate(generatorContext, generatorOptions)
146
+
147
+ console.log(`\n✅ Successfully generated ${selectedType}: ${name}`)
148
+
149
+ // Ask if user wants to generate related files
150
+ await suggestRelatedGenerations(selectedType, name, generatorContext)
151
+
152
+ } catch (error) {
153
+ console.error(`❌ Failed to generate ${selectedType}:`, error instanceof Error ? error.message : String(error))
154
+ throw error
155
+ }
156
+ }
157
+ }
158
+
159
+ async function suggestRelatedGenerations(
160
+ generatedType: string,
161
+ name: string,
162
+ context: GeneratorContext
163
+ ): Promise<void> {
164
+ const suggestions: Array<{ type: string; description: string }> = []
165
+
166
+ switch (generatedType) {
167
+ case 'controller':
168
+ suggestions.push(
169
+ { type: 'service', description: `Generate ${name} service for business logic` },
170
+ { type: 'route', description: `Generate ${name} routes to expose the controller` }
171
+ )
172
+ break
173
+ case 'service':
174
+ suggestions.push(
175
+ { type: 'controller', description: `Generate ${name} controller to use this service` }
176
+ )
177
+ break
178
+ case 'route':
179
+ suggestions.push(
180
+ { type: 'controller', description: `Generate ${name} controller for route handlers` }
181
+ )
182
+ break
183
+ case 'component':
184
+ // No automatic suggestions for components
185
+ break
186
+ }
187
+
188
+ if (suggestions.length === 0) {
189
+ return
190
+ }
191
+
192
+ console.log('\n💡 Suggested next steps:')
193
+ for (const suggestion of suggestions) {
194
+ console.log(` • ${suggestion.description}`)
195
+ }
196
+
197
+ const generateRelated = await promptSystem.confirm(
198
+ '\nWould you like to generate related files now?',
199
+ false
200
+ )
201
+
202
+ if (!generateRelated) {
203
+ return
204
+ }
205
+
206
+ for (const suggestion of suggestions) {
207
+ const shouldGenerate = await promptSystem.confirm(
208
+ `Generate ${suggestion.type} for ${name}?`,
209
+ true
210
+ )
211
+
212
+ if (shouldGenerate) {
213
+ const generator = generatorRegistry.get(suggestion.type)
214
+ if (generator) {
215
+ try {
216
+ await generator.generate(context, {
217
+ name,
218
+ force: false,
219
+ dryRun: false
220
+ })
221
+ console.log(`✅ Generated ${suggestion.type}: ${name}`)
222
+ } catch (error) {
223
+ console.error(`❌ Failed to generate ${suggestion.type}:`, error instanceof Error ? error.message : String(error))
224
+ }
225
+ }
226
+ }
227
+ }
228
228
  }
@@ -110,7 +110,7 @@ export class PluginGenerator implements Generator {
110
110
  * Declarative config using FluxStack config system
111
111
  */
112
112
 
113
- import { defineConfig, config } from '@/core/utils/config-schema'
113
+ import { defineConfig, config } from '@core/utils/config-schema'
114
114
 
115
115
  const {{camelName}}ConfigSchema = {
116
116
  // Enable/disable plugin
@@ -131,7 +131,7 @@ export default {{camelName}}Config
131
131
  },
132
132
  {
133
133
  path: 'plugins/{{name}}/index.ts',
134
- content: `import type { ErrorContext, FluxStack, PluginContext, RequestContext, ResponseContext } from "@/core/plugins/types"
134
+ content: `import type { ErrorContext, FluxStack, PluginContext, RequestContext, ResponseContext } from "@core/plugins/types"
135
135
  // ✅ Plugin imports its own configuration
136
136
  import { {{camelName}}Config } from './config'
137
137
 
@@ -1,83 +1,83 @@
1
- import type { PromptConfig } from "./types"
2
-
3
- export class PromptSystem {
4
- async prompt(config: PromptConfig): Promise<any> {
5
- // Simple implementation using process.stdin
6
- // In a real implementation, you'd use a library like inquirer or prompts
7
-
8
- return new Promise((resolve) => {
9
- process.stdout.write(`${config.message} `)
10
-
11
- if (config.default !== undefined) {
12
- process.stdout.write(`(${config.default}) `)
13
- }
14
-
15
- if (config.choices) {
16
- process.stdout.write(`\nChoices: ${config.choices.map(c => c.name || c.value).join(', ')}\n`)
17
- }
18
-
19
- process.stdout.write(': ')
20
-
21
- process.stdin.once('data', (data) => {
22
- const input = data.toString().trim()
23
-
24
- if (!input && config.default !== undefined) {
25
- resolve(config.default)
26
- return
27
- }
28
-
29
- if (config.validate) {
30
- const validation = config.validate(input)
31
- if (validation !== true) {
32
- console.log(`Error: ${validation}`)
33
- // In a real implementation, you'd re-prompt
34
- resolve(input)
35
- return
36
- }
37
- }
38
-
39
- if (config.choices) {
40
- const choice = config.choices.find(c =>
41
- c.name === input || c.value === input
42
- )
43
- if (choice) {
44
- resolve(choice.value)
45
- return
46
- }
47
- }
48
-
49
- resolve(input)
50
- })
51
- })
52
- }
53
-
54
- async confirm(message: string, defaultValue: boolean = false): Promise<boolean> {
55
- return this.prompt({
56
- type: 'confirm',
57
- message: `${message} (y/n)`,
58
- default: defaultValue
59
- }).then(result => {
60
- const value = String(result).toLowerCase()
61
- return value === 'y' || value === 'yes' || value === 'true'
62
- })
63
- }
64
-
65
- async select(message: string, choices: Array<{ name: string; value: any; description?: string }>): Promise<any> {
66
- return this.prompt({
67
- type: 'select',
68
- message,
69
- choices
70
- })
71
- }
72
-
73
- async input(message: string, defaultValue?: string, validate?: (value: string) => boolean | string): Promise<string> {
74
- return this.prompt({
75
- type: 'input',
76
- message,
77
- default: defaultValue,
78
- validate
79
- })
80
- }
81
- }
82
-
1
+ import type { PromptConfig } from "./types"
2
+
3
+ export class PromptSystem {
4
+ async prompt(config: PromptConfig): Promise<any> {
5
+ // Simple implementation using process.stdin
6
+ // In a real implementation, you'd use a library like inquirer or prompts
7
+
8
+ return new Promise((resolve) => {
9
+ process.stdout.write(`${config.message} `)
10
+
11
+ if (config.default !== undefined) {
12
+ process.stdout.write(`(${config.default}) `)
13
+ }
14
+
15
+ if (config.choices) {
16
+ process.stdout.write(`\nChoices: ${config.choices.map(c => c.name || c.value).join(', ')}\n`)
17
+ }
18
+
19
+ process.stdout.write(': ')
20
+
21
+ process.stdin.once('data', (data) => {
22
+ const input = data.toString().trim()
23
+
24
+ if (!input && config.default !== undefined) {
25
+ resolve(config.default)
26
+ return
27
+ }
28
+
29
+ if (config.validate) {
30
+ const validation = config.validate(input)
31
+ if (validation !== true) {
32
+ console.log(`Error: ${validation}`)
33
+ // In a real implementation, you'd re-prompt
34
+ resolve(input)
35
+ return
36
+ }
37
+ }
38
+
39
+ if (config.choices) {
40
+ const choice = config.choices.find(c =>
41
+ c.name === input || c.value === input
42
+ )
43
+ if (choice) {
44
+ resolve(choice.value)
45
+ return
46
+ }
47
+ }
48
+
49
+ resolve(input)
50
+ })
51
+ })
52
+ }
53
+
54
+ async confirm(message: string, defaultValue: boolean = false): Promise<boolean> {
55
+ return this.prompt({
56
+ type: 'confirm',
57
+ message: `${message} (y/n)`,
58
+ default: defaultValue
59
+ }).then(result => {
60
+ const value = String(result).toLowerCase()
61
+ return value === 'y' || value === 'yes' || value === 'true'
62
+ })
63
+ }
64
+
65
+ async select(message: string, choices: Array<{ name: string; value: any; description?: string }>): Promise<any> {
66
+ return this.prompt({
67
+ type: 'select',
68
+ message,
69
+ choices
70
+ })
71
+ }
72
+
73
+ async input(message: string, defaultValue?: string, validate?: (value: string) => boolean | string): Promise<string> {
74
+ return this.prompt({
75
+ type: 'input',
76
+ message,
77
+ default: defaultValue,
78
+ validate
79
+ })
80
+ }
81
+ }
82
+
83
83
  export const promptSystem = new PromptSystem()
@@ -54,8 +54,8 @@ export class RouteGenerator implements Generator {
54
54
  path: 'app/server/routes/{{kebabName}}.routes.ts',
55
55
  content: `import { Elysia, t } from 'elysia'
56
56
  import { {{pascalName}}Controller } from '../controllers/{{kebabName}}.controller'
57
- import { errorHandler } from '@/core/utils/errors/middleware'
58
- import { logger } from '@/core/utils/logger'
57
+ import { errorHandler } from '@core/utils/errors/middleware'
58
+ import { logger } from '@core/utils/logger'
59
59
 
60
60
  const controller = new {{pascalName}}Controller()
61
61
 
@@ -308,9 +308,9 @@ export const {{camelName}}Routes = new Elysia({ prefix: '/api/{{kebabName}}s' })
308
308
  path: 'app/server/routes/auth.routes.ts',
309
309
  content: `import { Elysia, t } from 'elysia'
310
310
  import { AuthController } from '../controllers/auth.controller'
311
- import { errorHandler } from '@/core/utils/errors/middleware'
311
+ import { errorHandler } from '@core/utils/errors/middleware'
312
312
  import { authMiddleware } from '../middleware/auth.middleware'
313
- import { logger } from '@/core/utils/logger'
313
+ import { logger } from '@core/utils/logger'
314
314
 
315
315
  const controller = new AuthController()
316
316
 
@@ -472,8 +472,8 @@ export const authRoutes = new Elysia({ prefix: '/api/auth' })
472
472
  {
473
473
  path: 'app/server/middleware/auth.middleware.ts',
474
474
  content: `import { Context } from 'elysia'
475
- import { UnauthorizedError } from '@/core/utils/errors'
476
- import { logger } from '@/core/utils/logger'
475
+ import { UnauthorizedError } from '@core/utils/errors'
476
+ import { logger } from '@core/utils/logger'
477
477
 
478
478
  // JWT verification function (implement based on your JWT library)
479
479
  async function verifyJWT(token: string): Promise<any> {