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,365 @@
1
+ /**
2
+ * FluxStack Logger Transports
3
+ * Multiple transport implementations for different logging needs
4
+ */
5
+
6
+ import { writeFile, mkdir, stat, readdir, unlink } from 'fs/promises'
7
+ import { join, dirname } from 'path'
8
+ import { createGzip } from 'zlib'
9
+ import { pipeline } from 'stream/promises'
10
+ import { createReadStream, createWriteStream } from 'fs'
11
+
12
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error'
13
+
14
+ export interface LogEntry {
15
+ timestamp: string
16
+ level: LogLevel
17
+ message: string
18
+ meta?: any
19
+ context?: any
20
+ }
21
+
22
+ export interface LogTransport {
23
+ name: string
24
+ level: LogLevel
25
+ write(entry: LogEntry): Promise<void> | void
26
+ close?(): Promise<void> | void
27
+ }
28
+
29
+ export interface ConsoleTransportConfig {
30
+ level?: LogLevel
31
+ colors?: boolean
32
+ timestamp?: boolean
33
+ }
34
+
35
+ export interface FileTransportConfig {
36
+ level?: LogLevel
37
+ filename: string
38
+ maxSize?: number // in bytes
39
+ maxFiles?: number
40
+ compress?: boolean
41
+ }
42
+
43
+ export interface JSONTransportConfig {
44
+ level?: LogLevel
45
+ filename?: string
46
+ pretty?: boolean
47
+ }
48
+
49
+ /**
50
+ * Console Transport with colored output for development
51
+ */
52
+ export class ConsoleTransport implements LogTransport {
53
+ name = 'console'
54
+ level: LogLevel
55
+ private colors: boolean
56
+ private timestamp: boolean
57
+
58
+ private colorMap = {
59
+ debug: '\x1b[36m', // cyan
60
+ info: '\x1b[32m', // green
61
+ warn: '\x1b[33m', // yellow
62
+ error: '\x1b[31m', // red
63
+ reset: '\x1b[0m'
64
+ }
65
+
66
+ constructor(config: ConsoleTransportConfig = {}) {
67
+ this.level = config.level || 'info'
68
+ this.colors = config.colors !== false
69
+ this.timestamp = config.timestamp !== false
70
+ }
71
+
72
+ private shouldLog(level: LogLevel): boolean {
73
+ const levels: Record<LogLevel, number> = {
74
+ debug: 0,
75
+ info: 1,
76
+ warn: 2,
77
+ error: 3
78
+ }
79
+ return levels[level] >= levels[this.level]
80
+ }
81
+
82
+ private formatMessage(entry: LogEntry): string {
83
+ const { timestamp, level, message, meta, context } = entry
84
+
85
+ let formatted = ''
86
+
87
+ // Add timestamp
88
+ if (this.timestamp) {
89
+ const color = this.colors ? '\x1b[90m' : '' // gray
90
+ const reset = this.colors ? this.colorMap.reset : ''
91
+ formatted += `${color}[${timestamp}]${reset} `
92
+ }
93
+
94
+ // Add level with color
95
+ const levelColor = this.colors ? this.colorMap[level] : ''
96
+ const reset = this.colors ? this.colorMap.reset : ''
97
+ const levelStr = level.toUpperCase().padEnd(5)
98
+ formatted += `${levelColor}${levelStr}${reset} `
99
+
100
+ // Add context if available
101
+ if (context && Object.keys(context).length > 0) {
102
+ const contextStr = Object.entries(context)
103
+ .map(([key, value]) => `${key}=${value}`)
104
+ .join(' ')
105
+ const contextColor = this.colors ? '\x1b[90m' : '' // gray
106
+ formatted += `${contextColor}[${contextStr}]${reset} `
107
+ }
108
+
109
+ // Add message
110
+ formatted += message
111
+
112
+ // Add meta if available
113
+ if (meta && typeof meta === 'object') {
114
+ const metaColor = this.colors ? '\x1b[90m' : '' // gray
115
+ formatted += ` ${metaColor}${JSON.stringify(meta)}${reset}`
116
+ } else if (meta !== undefined) {
117
+ formatted += ` ${meta}`
118
+ }
119
+
120
+ return formatted
121
+ }
122
+
123
+ write(entry: LogEntry): void {
124
+ if (!this.shouldLog(entry.level)) return
125
+
126
+ const formatted = this.formatMessage(entry)
127
+
128
+ // Use appropriate console method
129
+ switch (entry.level) {
130
+ case 'debug':
131
+ console.debug(formatted)
132
+ break
133
+ case 'info':
134
+ console.info(formatted)
135
+ break
136
+ case 'warn':
137
+ console.warn(formatted)
138
+ break
139
+ case 'error':
140
+ console.error(formatted)
141
+ break
142
+ }
143
+ }
144
+ }
145
+
146
+ /**
147
+ * File Transport with rotation and compression
148
+ */
149
+ export class FileTransport implements LogTransport {
150
+ name = 'file'
151
+ level: LogLevel
152
+ private filename: string
153
+ private maxSize: number
154
+ private maxFiles: number
155
+ private compress: boolean
156
+ private currentSize = 0
157
+
158
+ constructor(config: FileTransportConfig) {
159
+ this.level = config.level || 'info'
160
+ this.filename = config.filename
161
+ this.maxSize = config.maxSize || 10 * 1024 * 1024 // 10MB default
162
+ this.maxFiles = config.maxFiles || 5
163
+ this.compress = config.compress !== false
164
+
165
+ this.ensureDirectory()
166
+ this.getCurrentSize()
167
+ }
168
+
169
+ private async ensureDirectory(): Promise<void> {
170
+ const dir = dirname(this.filename)
171
+ try {
172
+ await mkdir(dir, { recursive: true })
173
+ } catch (error) {
174
+ // Directory might already exist
175
+ }
176
+ }
177
+
178
+ private async getCurrentSize(): Promise<void> {
179
+ try {
180
+ const stats = await stat(this.filename)
181
+ this.currentSize = stats.size
182
+ } catch (error) {
183
+ this.currentSize = 0
184
+ }
185
+ }
186
+
187
+ private shouldLog(level: LogLevel): boolean {
188
+ const levels: Record<LogLevel, number> = {
189
+ debug: 0,
190
+ info: 1,
191
+ warn: 2,
192
+ error: 3
193
+ }
194
+ return levels[level] >= levels[this.level]
195
+ }
196
+
197
+ private formatMessage(entry: LogEntry): string {
198
+ const { timestamp, level, message, meta, context } = entry
199
+
200
+ let formatted = `[${timestamp}] ${level.toUpperCase().padEnd(5)}`
201
+
202
+ // Add context if available
203
+ if (context && Object.keys(context).length > 0) {
204
+ const contextStr = Object.entries(context)
205
+ .map(([key, value]) => `${key}=${value}`)
206
+ .join(' ')
207
+ formatted += ` [${contextStr}]`
208
+ }
209
+
210
+ formatted += ` ${message}`
211
+
212
+ // Add meta if available
213
+ if (meta && typeof meta === 'object') {
214
+ formatted += ` ${JSON.stringify(meta)}`
215
+ } else if (meta !== undefined) {
216
+ formatted += ` ${meta}`
217
+ }
218
+
219
+ return formatted + '\n'
220
+ }
221
+
222
+ private async rotateFile(): Promise<void> {
223
+ // Rotate existing files
224
+ for (let i = this.maxFiles - 1; i >= 1; i--) {
225
+ const oldFile = `${this.filename}.${i}`
226
+ const newFile = `${this.filename}.${i + 1}`
227
+
228
+ try {
229
+ await stat(oldFile)
230
+ if (i === this.maxFiles - 1) {
231
+ // Delete the oldest file
232
+ await unlink(oldFile)
233
+ } else {
234
+ // Rename to next number
235
+ const { rename } = await import('fs/promises')
236
+ await rename(oldFile, newFile)
237
+ }
238
+ } catch (error) {
239
+ // File doesn't exist, continue
240
+ }
241
+ }
242
+
243
+ // Move current file to .1
244
+ try {
245
+ await stat(this.filename)
246
+ const rotatedFile = `${this.filename}.1`
247
+
248
+ if (this.compress) {
249
+ // Compress the rotated file
250
+ await this.compressFile(this.filename, `${rotatedFile}.gz`)
251
+ await unlink(this.filename)
252
+ } else {
253
+ const { rename } = await import('fs/promises')
254
+ await rename(this.filename, rotatedFile)
255
+ }
256
+ } catch (error) {
257
+ // File doesn't exist, continue
258
+ }
259
+
260
+ this.currentSize = 0
261
+ }
262
+
263
+ private async compressFile(source: string, destination: string): Promise<void> {
264
+ const gzip = createGzip()
265
+ const sourceStream = createReadStream(source)
266
+ const destStream = createWriteStream(destination)
267
+
268
+ await pipeline(sourceStream, gzip, destStream)
269
+ }
270
+
271
+ async write(entry: LogEntry): Promise<void> {
272
+ if (!this.shouldLog(entry.level)) return
273
+
274
+ const formatted = this.formatMessage(entry)
275
+ const messageSize = Buffer.byteLength(formatted, 'utf8')
276
+
277
+ // Check if rotation is needed
278
+ if (this.currentSize + messageSize > this.maxSize) {
279
+ await this.rotateFile()
280
+ }
281
+
282
+ // Write to file
283
+ await writeFile(this.filename, formatted, { flag: 'a' })
284
+ this.currentSize += messageSize
285
+ }
286
+
287
+ async close(): Promise<void> {
288
+ // Nothing to close for file transport
289
+ }
290
+ }
291
+
292
+ /**
293
+ * JSON Transport for structured production logging
294
+ */
295
+ export class JSONTransport implements LogTransport {
296
+ name = 'json'
297
+ level: LogLevel
298
+ private filename?: string
299
+ private pretty: boolean
300
+
301
+ constructor(config: JSONTransportConfig = {}) {
302
+ this.level = config.level || 'info'
303
+ this.filename = config.filename
304
+ this.pretty = config.pretty || false
305
+
306
+ if (this.filename) {
307
+ this.ensureDirectory()
308
+ }
309
+ }
310
+
311
+ private async ensureDirectory(): Promise<void> {
312
+ if (!this.filename) return
313
+
314
+ const dir = dirname(this.filename)
315
+ try {
316
+ await mkdir(dir, { recursive: true })
317
+ } catch (error) {
318
+ // Directory might already exist
319
+ }
320
+ }
321
+
322
+ private shouldLog(level: LogLevel): boolean {
323
+ const levels: Record<LogLevel, number> = {
324
+ debug: 0,
325
+ info: 1,
326
+ warn: 2,
327
+ error: 3
328
+ }
329
+ return levels[level] >= levels[this.level]
330
+ }
331
+
332
+ private formatEntry(entry: LogEntry): string {
333
+ const jsonEntry = {
334
+ timestamp: entry.timestamp,
335
+ level: entry.level,
336
+ message: entry.message,
337
+ ...(entry.context && { context: entry.context }),
338
+ ...(entry.meta && { meta: entry.meta })
339
+ }
340
+
341
+ const json = this.pretty
342
+ ? JSON.stringify(jsonEntry, null, 2)
343
+ : JSON.stringify(jsonEntry)
344
+
345
+ return json + '\n'
346
+ }
347
+
348
+ async write(entry: LogEntry): Promise<void> {
349
+ if (!this.shouldLog(entry.level)) return
350
+
351
+ const formatted = this.formatEntry(entry)
352
+
353
+ if (this.filename) {
354
+ // Write to file
355
+ await writeFile(this.filename, formatted, { flag: 'a' })
356
+ } else {
357
+ // Write to console as JSON
358
+ process.stdout.write(formatted)
359
+ }
360
+ }
361
+
362
+ async close(): Promise<void> {
363
+ // Nothing to close for JSON transport
364
+ }
365
+ }