create-fluxstack 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/.env.example +29 -29
  2. package/app/client/README.md +69 -69
  3. package/app/client/index.html +14 -13
  4. package/app/client/src/App.tsx +157 -524
  5. package/app/client/src/components/ErrorBoundary.tsx +107 -0
  6. package/app/client/src/components/ErrorDisplay.css +365 -0
  7. package/app/client/src/components/ErrorDisplay.tsx +258 -0
  8. package/app/client/src/components/FluxStackConfig.tsx +1321 -0
  9. package/app/client/src/components/HybridLiveCounter.tsx +140 -0
  10. package/app/client/src/components/LiveClock.tsx +286 -0
  11. package/app/client/src/components/MainLayout.tsx +390 -0
  12. package/app/client/src/components/SidebarNavigation.tsx +391 -0
  13. package/app/client/src/components/StateDemo.tsx +178 -0
  14. package/app/client/src/components/SystemMonitor.tsx +1038 -0
  15. package/app/client/src/components/Teste.tsx +104 -0
  16. package/app/client/src/components/UserProfile.tsx +809 -0
  17. package/app/client/src/hooks/useAuth.ts +39 -0
  18. package/app/client/src/hooks/useNotifications.ts +56 -0
  19. package/app/client/src/lib/eden-api.ts +189 -53
  20. package/app/client/src/lib/errors.ts +340 -0
  21. package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
  22. package/app/client/src/lib/index.ts +45 -0
  23. package/app/client/src/main.tsx +3 -2
  24. package/app/client/src/pages/ApiDocs.tsx +182 -0
  25. package/app/client/src/pages/Demo.tsx +174 -0
  26. package/app/client/src/pages/HybridLive.tsx +263 -0
  27. package/app/client/src/pages/Overview.tsx +155 -0
  28. package/app/client/src/store/README.md +43 -0
  29. package/app/client/src/store/index.ts +16 -0
  30. package/app/client/src/store/slices/uiSlice.ts +151 -0
  31. package/app/client/src/store/slices/userSlice.ts +161 -0
  32. package/app/client/src/test/README.md +257 -0
  33. package/app/client/src/test/setup.ts +70 -0
  34. package/app/client/src/test/types.ts +12 -0
  35. package/app/client/src/vite-env.d.ts +1 -1
  36. package/app/client/tsconfig.app.json +44 -43
  37. package/app/client/tsconfig.json +7 -7
  38. package/app/client/tsconfig.node.json +25 -25
  39. package/app/client/zustand-setup.md +65 -0
  40. package/app/server/controllers/users.controller.ts +68 -68
  41. package/app/server/index.ts +9 -1
  42. package/app/server/live/CounterComponent.ts +191 -0
  43. package/app/server/live/FluxStackConfig.ts +529 -0
  44. package/app/server/live/LiveClockComponent.ts +214 -0
  45. package/app/server/live/SidebarNavigation.ts +156 -0
  46. package/app/server/live/SystemMonitor.ts +594 -0
  47. package/app/server/live/SystemMonitorIntegration.ts +151 -0
  48. package/app/server/live/TesteComponent.ts +87 -0
  49. package/app/server/live/UserProfileComponent.ts +135 -0
  50. package/app/server/live/register-components.ts +28 -0
  51. package/app/server/middleware/auth.ts +136 -0
  52. package/app/server/middleware/errorHandling.ts +250 -0
  53. package/app/server/middleware/index.ts +10 -0
  54. package/app/server/middleware/rateLimit.ts +193 -0
  55. package/app/server/middleware/requestLogging.ts +215 -0
  56. package/app/server/middleware/validation.ts +270 -0
  57. package/app/server/routes/index.ts +14 -2
  58. package/app/server/routes/upload.ts +92 -0
  59. package/app/server/routes/users.routes.ts +2 -9
  60. package/app/server/services/NotificationService.ts +302 -0
  61. package/app/server/services/UserService.ts +222 -0
  62. package/app/server/services/index.ts +46 -0
  63. package/core/cli/commands/plugin-deps.ts +263 -0
  64. package/core/cli/generators/README.md +339 -0
  65. package/core/cli/generators/component.ts +770 -0
  66. package/core/cli/generators/controller.ts +299 -0
  67. package/core/cli/generators/index.ts +144 -0
  68. package/core/cli/generators/interactive.ts +228 -0
  69. package/core/cli/generators/prompts.ts +83 -0
  70. package/core/cli/generators/route.ts +513 -0
  71. package/core/cli/generators/service.ts +465 -0
  72. package/core/cli/generators/template-engine.ts +154 -0
  73. package/core/cli/generators/types.ts +71 -0
  74. package/core/cli/generators/utils.ts +192 -0
  75. package/core/cli/index.ts +69 -0
  76. package/core/cli/plugin-discovery.ts +16 -85
  77. package/core/client/fluxstack.ts +17 -0
  78. package/core/client/hooks/index.ts +7 -0
  79. package/core/client/hooks/state-validator.ts +130 -0
  80. package/core/client/hooks/useAuth.ts +49 -0
  81. package/core/client/hooks/useChunkedUpload.ts +258 -0
  82. package/core/client/hooks/useHybridLiveComponent.ts +967 -0
  83. package/core/client/hooks/useWebSocket.ts +373 -0
  84. package/core/client/index.ts +47 -0
  85. package/core/client/state/createStore.ts +193 -0
  86. package/core/client/state/index.ts +15 -0
  87. package/core/config/env-dynamic.ts +1 -1
  88. package/core/config/env.ts +2 -1
  89. package/core/config/runtime-config.ts +3 -3
  90. package/core/config/schema.ts +84 -49
  91. package/core/framework/server.ts +30 -0
  92. package/core/index.ts +25 -0
  93. package/core/live/ComponentRegistry.ts +399 -0
  94. package/core/live/types.ts +164 -0
  95. package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
  96. package/core/plugins/built-in/live-components/index.ts +27 -0
  97. package/core/plugins/built-in/logger/index.ts +1 -1
  98. package/core/plugins/built-in/monitoring/index.ts +1 -1
  99. package/core/plugins/built-in/static/index.ts +1 -1
  100. package/core/plugins/built-in/swagger/index.ts +1 -1
  101. package/core/plugins/built-in/vite/index.ts +1 -1
  102. package/core/plugins/dependency-manager.ts +384 -0
  103. package/core/plugins/index.ts +5 -1
  104. package/core/plugins/manager.ts +7 -3
  105. package/core/plugins/registry.ts +88 -10
  106. package/core/plugins/types.ts +11 -11
  107. package/core/server/framework.ts +43 -0
  108. package/core/server/index.ts +11 -1
  109. package/core/server/live/ComponentRegistry.ts +1017 -0
  110. package/core/server/live/FileUploadManager.ts +272 -0
  111. package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
  112. package/core/server/live/SingleConnectionManager.ts +0 -0
  113. package/core/server/live/StateSignature.ts +644 -0
  114. package/core/server/live/WebSocketConnectionManager.ts +688 -0
  115. package/core/server/live/websocket-plugin.ts +435 -0
  116. package/core/server/middleware/errorHandling.ts +141 -0
  117. package/core/server/middleware/index.ts +16 -0
  118. package/core/server/plugins/static-files-plugin.ts +232 -0
  119. package/core/server/services/BaseService.ts +95 -0
  120. package/core/server/services/ServiceContainer.ts +144 -0
  121. package/core/server/services/index.ts +9 -0
  122. package/core/templates/create-project.ts +46 -2
  123. package/core/testing/index.ts +10 -0
  124. package/core/testing/setup.ts +74 -0
  125. package/core/types/build.ts +38 -14
  126. package/core/types/types.ts +319 -0
  127. package/core/utils/env-runtime.ts +7 -0
  128. package/core/utils/errors/handlers.ts +264 -39
  129. package/core/utils/errors/index.ts +528 -18
  130. package/core/utils/errors/middleware.ts +114 -0
  131. package/core/utils/logger/formatters.ts +222 -0
  132. package/core/utils/logger/index.ts +167 -48
  133. package/core/utils/logger/middleware.ts +253 -0
  134. package/core/utils/logger/performance.ts +384 -0
  135. package/core/utils/logger/transports.ts +365 -0
  136. package/create-fluxstack.ts +296 -296
  137. package/fluxstack.config.ts +17 -1
  138. package/package-template.json +66 -66
  139. package/package.json +31 -6
  140. package/public/README.md +16 -0
  141. package/vite.config.ts +29 -14
  142. package/.claude/settings.local.json +0 -74
  143. package/.github/workflows/ci-build-tests.yml +0 -480
  144. package/.github/workflows/dependency-management.yml +0 -324
  145. package/.github/workflows/release-validation.yml +0 -355
  146. package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
  147. package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
  148. package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
  149. package/CLAUDE.md +0 -200
  150. package/Dockerfile +0 -58
  151. package/Dockerfile.backend +0 -52
  152. package/Dockerfile.frontend +0 -54
  153. package/README-Docker.md +0 -85
  154. package/ai-context/00-QUICK-START.md +0 -86
  155. package/ai-context/README.md +0 -88
  156. package/ai-context/development/eden-treaty-guide.md +0 -362
  157. package/ai-context/development/patterns.md +0 -382
  158. package/ai-context/development/plugins-guide.md +0 -572
  159. package/ai-context/examples/crud-complete.md +0 -626
  160. package/ai-context/project/architecture.md +0 -399
  161. package/ai-context/project/overview.md +0 -213
  162. package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
  163. package/ai-context/recent-changes/type-inference-fix.md +0 -223
  164. package/ai-context/reference/environment-vars.md +0 -384
  165. package/ai-context/reference/troubleshooting.md +0 -407
  166. package/app/client/src/components/TestPage.tsx +0 -453
  167. package/bun.lock +0 -1063
  168. package/bunfig.toml +0 -16
  169. package/core/__tests__/integration.test.ts +0 -227
  170. package/core/build/index.ts +0 -186
  171. package/core/config/__tests__/config-loader.test.ts +0 -554
  172. package/core/config/__tests__/config-merger.test.ts +0 -657
  173. package/core/config/__tests__/env-converter.test.ts +0 -372
  174. package/core/config/__tests__/env-processor.test.ts +0 -431
  175. package/core/config/__tests__/env.test.ts +0 -452
  176. package/core/config/__tests__/integration.test.ts +0 -418
  177. package/core/config/__tests__/loader.test.ts +0 -331
  178. package/core/config/__tests__/schema.test.ts +0 -129
  179. package/core/config/__tests__/validator.test.ts +0 -318
  180. package/core/framework/__tests__/server.test.ts +0 -233
  181. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  182. package/core/plugins/__tests__/manager.test.ts +0 -398
  183. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  184. package/core/plugins/__tests__/registry.test.ts +0 -335
  185. package/core/utils/__tests__/errors.test.ts +0 -139
  186. package/core/utils/__tests__/helpers.test.ts +0 -297
  187. package/core/utils/__tests__/logger.test.ts +0 -141
  188. package/create-test-app.ts +0 -156
  189. package/docker-compose.microservices.yml +0 -75
  190. package/docker-compose.simple.yml +0 -57
  191. package/docker-compose.yml +0 -71
  192. package/eslint.config.js +0 -23
  193. package/flux-cli.ts +0 -214
  194. package/nginx-lb.conf +0 -37
  195. package/publish.sh +0 -63
  196. package/run-clean.ts +0 -26
  197. package/run-env-tests.ts +0 -313
  198. package/tailwind.config.js +0 -34
  199. package/tests/__mocks__/api.ts +0 -56
  200. package/tests/fixtures/users.ts +0 -69
  201. package/tests/integration/api/users.routes.test.ts +0 -221
  202. package/tests/setup.ts +0 -29
  203. package/tests/unit/app/client/App-simple.test.tsx +0 -56
  204. package/tests/unit/app/client/App.test.tsx.skip +0 -237
  205. package/tests/unit/app/client/eden-api.test.ts +0 -186
  206. package/tests/unit/app/client/simple.test.tsx +0 -23
  207. package/tests/unit/app/controllers/users.controller.test.ts +0 -150
  208. package/tests/unit/core/create-project.test.ts.skip +0 -95
  209. package/tests/unit/core/framework.test.ts +0 -144
  210. package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
  211. package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
  212. package/tests/utils/test-helpers.ts +0 -61
  213. package/vitest.config.ts +0 -50
  214. package/workspace.json +0 -6
@@ -0,0 +1,83 @@
1
+ import type { PromptConfig } from "./types.js"
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
+ export const promptSystem = new PromptSystem()
@@ -0,0 +1,513 @@
1
+ import type { Generator } from "./index.js"
2
+ import type { GeneratorContext, GeneratorOptions, Template } from "./types.js"
3
+ import { templateEngine } from "./template-engine.js"
4
+
5
+ export class RouteGenerator implements Generator {
6
+ name = 'route'
7
+ description = 'Generate API routes with controllers'
8
+
9
+ async generate(context: GeneratorContext, options: GeneratorOptions): Promise<void> {
10
+ const template = this.getTemplate(options.template)
11
+
12
+ if (template.hooks?.beforeGenerate) {
13
+ await template.hooks.beforeGenerate(context, options)
14
+ }
15
+
16
+ const files = await templateEngine.processTemplate(template, context, options)
17
+
18
+ if (options.dryRun) {
19
+ console.log(`\n📋 Would generate route '${options.name}':\n`)
20
+ for (const file of files) {
21
+ console.log(`${file.action === 'create' ? '📄' : '✏️'} ${file.path}`)
22
+ }
23
+ return
24
+ }
25
+
26
+ await templateEngine.generateFiles(files, options.dryRun)
27
+
28
+ if (template.hooks?.afterGenerate) {
29
+ const filePaths = files.map(f => f.path)
30
+ await template.hooks.afterGenerate(context, options, filePaths)
31
+ }
32
+
33
+ console.log(`\n✅ Generated route '${options.name}' with ${files.length} files`)
34
+ }
35
+
36
+ private getTemplate(templateName?: string): Template {
37
+ switch (templateName) {
38
+ case 'minimal':
39
+ return this.getMinimalTemplate()
40
+ case 'auth':
41
+ return this.getAuthTemplate()
42
+ case 'crud':
43
+ default:
44
+ return this.getCrudTemplate()
45
+ }
46
+ }
47
+
48
+ private getCrudTemplate(): Template {
49
+ return {
50
+ name: 'crud-route',
51
+ description: 'Full CRUD API routes with validation',
52
+ files: [
53
+ {
54
+ path: 'app/server/routes/{{kebabName}}.routes.ts',
55
+ content: `import { Elysia, t } from 'elysia'
56
+ import { {{pascalName}}Controller } from '../controllers/{{kebabName}}.controller'
57
+ import { errorHandler } from '../../../core/utils/errors/middleware'
58
+ import { logger } from '../../../core/utils/logger'
59
+
60
+ const controller = new {{pascalName}}Controller()
61
+
62
+ export const {{camelName}}Routes = new Elysia({ prefix: '/api/{{kebabName}}s' })
63
+ .use(errorHandler)
64
+ .onBeforeHandle(({ request }) => {
65
+ logger.request(request.method, new URL(request.url).pathname)
66
+ })
67
+ .get('/', async () => {
68
+ return await controller.getAll()
69
+ }, {
70
+ detail: {
71
+ tags: ['{{pascalName}}'],
72
+ summary: 'Get all {{camelName}}s',
73
+ description: 'Retrieve a list of all {{camelName}}s'
74
+ }
75
+ })
76
+ .get('/:id', async ({ params }) => {
77
+ return await controller.getById({ params })
78
+ }, {
79
+ params: t.Object({
80
+ id: t.String({
81
+ description: '{{pascalName}} ID',
82
+ example: '{{kebabName}}_123'
83
+ })
84
+ }),
85
+ detail: {
86
+ tags: ['{{pascalName}}'],
87
+ summary: 'Get {{camelName}} by ID',
88
+ description: 'Retrieve a specific {{camelName}} by its ID'
89
+ }
90
+ })
91
+ .post('/', async ({ body }) => {
92
+ return await controller.create({ body })
93
+ }, {
94
+ body: t.Object({
95
+ name: t.String({
96
+ minLength: 1,
97
+ maxLength: 100,
98
+ description: '{{pascalName}} name',
99
+ example: 'Sample {{pascalName}}'
100
+ }),
101
+ description: t.Optional(t.String({
102
+ maxLength: 500,
103
+ description: '{{pascalName}} description',
104
+ example: 'This is a sample {{camelName}} description'
105
+ }))
106
+ }),
107
+ detail: {
108
+ tags: ['{{pascalName}}'],
109
+ summary: 'Create new {{camelName}}',
110
+ description: 'Create a new {{camelName}} with the provided data'
111
+ }
112
+ })
113
+ .put('/:id', async ({ params, body }) => {
114
+ return await controller.update({ params, body })
115
+ }, {
116
+ params: t.Object({
117
+ id: t.String({
118
+ description: '{{pascalName}} ID',
119
+ example: '{{kebabName}}_123'
120
+ })
121
+ }),
122
+ body: t.Partial(t.Object({
123
+ name: t.String({
124
+ minLength: 1,
125
+ maxLength: 100,
126
+ description: '{{pascalName}} name',
127
+ example: 'Updated {{pascalName}}'
128
+ }),
129
+ description: t.String({
130
+ maxLength: 500,
131
+ description: '{{pascalName}} description',
132
+ example: 'Updated description'
133
+ })
134
+ })),
135
+ detail: {
136
+ tags: ['{{pascalName}}'],
137
+ summary: 'Update {{camelName}}',
138
+ description: 'Update an existing {{camelName}} with new data'
139
+ }
140
+ })
141
+ .delete('/:id', async ({ params }) => {
142
+ return await controller.delete({ params })
143
+ }, {
144
+ params: t.Object({
145
+ id: t.String({
146
+ description: '{{pascalName}} ID',
147
+ example: '{{kebabName}}_123'
148
+ })
149
+ }),
150
+ detail: {
151
+ tags: ['{{pascalName}}'],
152
+ summary: 'Delete {{camelName}}',
153
+ description: 'Delete a {{camelName}} by its ID'
154
+ }
155
+ })
156
+ .get('/search', async ({ query }) => {
157
+ // Assuming controller has a search method
158
+ return await (controller as any).search({ query })
159
+ }, {
160
+ query: t.Object({
161
+ q: t.String({
162
+ minLength: 1,
163
+ description: 'Search query',
164
+ example: 'search term'
165
+ }),
166
+ limit: t.Optional(t.Number({
167
+ minimum: 1,
168
+ maximum: 100,
169
+ default: 10,
170
+ description: 'Maximum number of results'
171
+ })),
172
+ offset: t.Optional(t.Number({
173
+ minimum: 0,
174
+ default: 0,
175
+ description: 'Number of results to skip'
176
+ }))
177
+ }),
178
+ detail: {
179
+ tags: ['{{pascalName}}'],
180
+ summary: 'Search {{camelName}}s',
181
+ description: 'Search for {{camelName}}s using a query string'
182
+ }
183
+ })
184
+ `
185
+ },
186
+ {
187
+ path: 'app/server/routes/index.ts',
188
+ content: `import { Elysia } from 'elysia'
189
+ import { {{camelName}}Routes } from './{{kebabName}}.routes'
190
+
191
+ // Import other route modules here
192
+ // import { userRoutes } from './user.routes'
193
+ // import { authRoutes } from './auth.routes'
194
+
195
+ export const apiRoutes = new Elysia({ prefix: '/api' })
196
+ .use({{camelName}}Routes)
197
+ // Add other routes here
198
+ // .use(userRoutes)
199
+ // .use(authRoutes)
200
+ .get('/health', () => ({
201
+ status: 'ok',
202
+ timestamp: new Date().toISOString(),
203
+ service: '{{projectName}}'
204
+ }), {
205
+ detail: {
206
+ tags: ['Health'],
207
+ summary: 'Health check',
208
+ description: 'Check if the API is running'
209
+ }
210
+ })
211
+
212
+ export default apiRoutes
213
+ `,
214
+ condition: (variables) => !variables.skipIndex
215
+ }
216
+ ],
217
+ hooks: {
218
+ afterGenerate: async (context, options, files) => {
219
+ context.logger.info(`Generated route files:`)
220
+ files.forEach(file => {
221
+ context.logger.info(` - ${file}`)
222
+ })
223
+ context.logger.info(`\nNext steps:`)
224
+ context.logger.info(`1. Generate the corresponding controller: flux generate controller ${options.name}`)
225
+ context.logger.info(`2. Import and use the routes in your main server file`)
226
+ context.logger.info(`3. Test the API endpoints using the Swagger documentation`)
227
+ context.logger.info(`\nAPI endpoints created:`)
228
+ context.logger.info(` GET /api/${options.name}s`)
229
+ context.logger.info(` GET /api/${options.name}s/:id`)
230
+ context.logger.info(` POST /api/${options.name}s`)
231
+ context.logger.info(` PUT /api/${options.name}s/:id`)
232
+ context.logger.info(` DELETE /api/${options.name}s/:id`)
233
+ context.logger.info(` GET /api/${options.name}s/search`)
234
+ }
235
+ }
236
+ }
237
+ }
238
+
239
+ private getMinimalTemplate(): Template {
240
+ return {
241
+ name: 'minimal-route',
242
+ description: 'Minimal API route with basic endpoints',
243
+ files: [
244
+ {
245
+ path: 'app/server/routes/{{kebabName}}.routes.ts',
246
+ content: `import { Elysia } from 'elysia'
247
+
248
+ export const {{camelName}}Routes = new Elysia({ prefix: '/api/{{kebabName}}s' })
249
+ .get('/', () => {
250
+ // TODO: Implement list logic
251
+ return {
252
+ success: true,
253
+ data: [],
254
+ message: 'List {{camelName}}s'
255
+ }
256
+ })
257
+ .get('/:id', ({ params }) => {
258
+ // TODO: Implement get by id logic
259
+ return {
260
+ success: true,
261
+ data: { id: params.id },
262
+ message: 'Get {{camelName}}'
263
+ }
264
+ })
265
+ .post('/', ({ body }) => {
266
+ // TODO: Implement create logic
267
+ return {
268
+ success: true,
269
+ data: body,
270
+ message: '{{pascalName}} created'
271
+ }
272
+ })
273
+ .put('/:id', ({ params, body }) => {
274
+ // TODO: Implement update logic
275
+ return {
276
+ success: true,
277
+ data: { id: params.id, ...body },
278
+ message: '{{pascalName}} updated'
279
+ }
280
+ })
281
+ .delete('/:id', ({ params }) => {
282
+ // TODO: Implement delete logic
283
+ return {
284
+ success: true,
285
+ message: '{{pascalName}} deleted'
286
+ }
287
+ })
288
+ `
289
+ }
290
+ ]
291
+ }
292
+ }
293
+
294
+ private getAuthTemplate(): Template {
295
+ return {
296
+ name: 'auth-route',
297
+ description: 'Authentication routes with JWT',
298
+ files: [
299
+ {
300
+ path: 'app/server/routes/auth.routes.ts',
301
+ content: `import { Elysia, t } from 'elysia'
302
+ import { AuthController } from '../controllers/auth.controller'
303
+ import { errorHandler } from '../../../core/utils/errors/middleware'
304
+ import { authMiddleware } from '../middleware/auth.middleware'
305
+ import { logger } from '../../../core/utils/logger'
306
+
307
+ const controller = new AuthController()
308
+
309
+ export const authRoutes = new Elysia({ prefix: '/api/auth' })
310
+ .use(errorHandler)
311
+ .onBeforeHandle(({ request }) => {
312
+ logger.request(request.method, new URL(request.url).pathname)
313
+ })
314
+ .post('/register', async ({ body }) => {
315
+ return await controller.register({ body })
316
+ }, {
317
+ body: t.Object({
318
+ email: t.String({
319
+ format: 'email',
320
+ description: 'User email address',
321
+ example: 'user@example.com'
322
+ }),
323
+ password: t.String({
324
+ minLength: 8,
325
+ description: 'User password (minimum 8 characters)',
326
+ example: 'securePassword123'
327
+ }),
328
+ name: t.String({
329
+ minLength: 1,
330
+ maxLength: 100,
331
+ description: 'User full name',
332
+ example: 'John Doe'
333
+ })
334
+ }),
335
+ detail: {
336
+ tags: ['Authentication'],
337
+ summary: 'Register new user',
338
+ description: 'Create a new user account'
339
+ }
340
+ })
341
+ .post('/login', async ({ body }) => {
342
+ return await controller.login({ body })
343
+ }, {
344
+ body: t.Object({
345
+ email: t.String({
346
+ format: 'email',
347
+ description: 'User email address',
348
+ example: 'user@example.com'
349
+ }),
350
+ password: t.String({
351
+ minLength: 1,
352
+ description: 'User password',
353
+ example: 'securePassword123'
354
+ })
355
+ }),
356
+ detail: {
357
+ tags: ['Authentication'],
358
+ summary: 'User login',
359
+ description: 'Authenticate user and return JWT token'
360
+ }
361
+ })
362
+ .post('/logout', async ({ headers }) => {
363
+ return await controller.logout({ headers })
364
+ }, {
365
+ beforeHandle: authMiddleware,
366
+ detail: {
367
+ tags: ['Authentication'],
368
+ summary: 'User logout',
369
+ description: 'Logout user and invalidate token'
370
+ }
371
+ })
372
+ .get('/me', async ({ headers }) => {
373
+ return await controller.getProfile({ headers })
374
+ }, {
375
+ beforeHandle: authMiddleware,
376
+ detail: {
377
+ tags: ['Authentication'],
378
+ summary: 'Get user profile',
379
+ description: 'Get current user profile information'
380
+ }
381
+ })
382
+ .put('/me', async ({ headers, body }) => {
383
+ return await controller.updateProfile({ headers, body })
384
+ }, {
385
+ beforeHandle: authMiddleware,
386
+ body: t.Partial(t.Object({
387
+ name: t.String({
388
+ minLength: 1,
389
+ maxLength: 100,
390
+ description: 'User full name'
391
+ }),
392
+ email: t.String({
393
+ format: 'email',
394
+ description: 'User email address'
395
+ })
396
+ })),
397
+ detail: {
398
+ tags: ['Authentication'],
399
+ summary: 'Update user profile',
400
+ description: 'Update current user profile information'
401
+ }
402
+ })
403
+ .post('/refresh', async ({ body }) => {
404
+ return await controller.refreshToken({ body })
405
+ }, {
406
+ body: t.Object({
407
+ refreshToken: t.String({
408
+ description: 'Refresh token',
409
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
410
+ })
411
+ }),
412
+ detail: {
413
+ tags: ['Authentication'],
414
+ summary: 'Refresh access token',
415
+ description: 'Get new access token using refresh token'
416
+ }
417
+ })
418
+ .post('/forgot-password', async ({ body }) => {
419
+ return await controller.forgotPassword({ body })
420
+ }, {
421
+ body: t.Object({
422
+ email: t.String({
423
+ format: 'email',
424
+ description: 'User email address',
425
+ example: 'user@example.com'
426
+ })
427
+ }),
428
+ detail: {
429
+ tags: ['Authentication'],
430
+ summary: 'Forgot password',
431
+ description: 'Send password reset email'
432
+ }
433
+ })
434
+ .post('/reset-password', async ({ body }) => {
435
+ return await controller.resetPassword({ body })
436
+ }, {
437
+ body: t.Object({
438
+ token: t.String({
439
+ description: 'Password reset token',
440
+ example: 'reset-token-123'
441
+ }),
442
+ password: t.String({
443
+ minLength: 8,
444
+ description: 'New password (minimum 8 characters)',
445
+ example: 'newSecurePassword123'
446
+ })
447
+ }),
448
+ detail: {
449
+ tags: ['Authentication'],
450
+ summary: 'Reset password',
451
+ description: 'Reset user password using reset token'
452
+ }
453
+ })
454
+ `
455
+ },
456
+ {
457
+ path: 'app/server/middleware/auth.middleware.ts',
458
+ content: `import { Context } from 'elysia'
459
+ import { UnauthorizedError } from '../../../core/utils/errors'
460
+ import { logger } from '../../../core/utils/logger'
461
+
462
+ // JWT verification function (implement based on your JWT library)
463
+ async function verifyJWT(token: string): Promise<any> {
464
+ // TODO: Implement JWT verification
465
+ // This is a placeholder - replace with actual JWT verification
466
+ if (!token || token === 'invalid') {
467
+ throw new Error('Invalid token')
468
+ }
469
+
470
+ return {
471
+ userId: 'user_123',
472
+ email: 'user@example.com',
473
+ name: 'John Doe'
474
+ }
475
+ }
476
+
477
+ export async function authMiddleware(context: Context) {
478
+ try {
479
+ const authorization = context.headers.authorization
480
+
481
+ if (!authorization) {
482
+ throw new UnauthorizedError('Authorization header is required')
483
+ }
484
+
485
+ const token = authorization.replace('Bearer ', '')
486
+
487
+ if (!token) {
488
+ throw new UnauthorizedError('Bearer token is required')
489
+ }
490
+
491
+ const user = await verifyJWT(token)
492
+
493
+ // Add user to context for use in route handlers
494
+ ;(context as any).user = user
495
+
496
+ logger.debug('User authenticated', { userId: user.userId })
497
+
498
+ } catch (error) {
499
+ logger.warn('Authentication failed', { error: error instanceof Error ? error.message : 'Unknown error' })
500
+
501
+ if (error instanceof UnauthorizedError) {
502
+ throw error
503
+ }
504
+
505
+ throw new UnauthorizedError('Invalid or expired token')
506
+ }
507
+ }
508
+ `
509
+ }
510
+ ]
511
+ }
512
+ }
513
+ }