create-fluxstack 1.0.0 → 1.0.2

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 (101) hide show
  1. package/create-fluxstack.ts +32 -17
  2. package/package-template.json +51 -0
  3. package/package.json +2 -1
  4. package/.env +0 -30
  5. package/LICENSE +0 -21
  6. package/app/client/README.md +0 -69
  7. package/app/client/frontend-only.ts +0 -12
  8. package/app/client/index.html +0 -13
  9. package/app/client/public/vite.svg +0 -1
  10. package/app/client/src/App.css +0 -883
  11. package/app/client/src/App.tsx +0 -669
  12. package/app/client/src/assets/react.svg +0 -1
  13. package/app/client/src/components/TestPage.tsx +0 -453
  14. package/app/client/src/index.css +0 -51
  15. package/app/client/src/lib/eden-api.ts +0 -110
  16. package/app/client/src/main.tsx +0 -10
  17. package/app/client/src/vite-env.d.ts +0 -1
  18. package/app/client/tsconfig.app.json +0 -43
  19. package/app/client/tsconfig.json +0 -7
  20. package/app/client/tsconfig.node.json +0 -25
  21. package/app/server/app.ts +0 -10
  22. package/app/server/backend-only.ts +0 -15
  23. package/app/server/controllers/users.controller.ts +0 -69
  24. package/app/server/index.ts +0 -104
  25. package/app/server/routes/index.ts +0 -25
  26. package/app/server/routes/users.routes.ts +0 -121
  27. package/app/server/types/index.ts +0 -1
  28. package/app/shared/types/index.ts +0 -18
  29. package/bun.lock +0 -1053
  30. package/core/__tests__/integration.test.ts +0 -227
  31. package/core/build/index.ts +0 -186
  32. package/core/cli/command-registry.ts +0 -334
  33. package/core/cli/index.ts +0 -394
  34. package/core/cli/plugin-discovery.ts +0 -200
  35. package/core/client/standalone.ts +0 -57
  36. package/core/config/__tests__/config-loader.test.ts +0 -591
  37. package/core/config/__tests__/config-merger.test.ts +0 -657
  38. package/core/config/__tests__/env-converter.test.ts +0 -372
  39. package/core/config/__tests__/env-processor.test.ts +0 -431
  40. package/core/config/__tests__/env.test.ts +0 -452
  41. package/core/config/__tests__/integration.test.ts +0 -418
  42. package/core/config/__tests__/loader.test.ts +0 -331
  43. package/core/config/__tests__/schema.test.ts +0 -129
  44. package/core/config/__tests__/validator.test.ts +0 -318
  45. package/core/config/env-dynamic.ts +0 -326
  46. package/core/config/env.ts +0 -597
  47. package/core/config/index.ts +0 -317
  48. package/core/config/loader.ts +0 -546
  49. package/core/config/runtime-config.ts +0 -322
  50. package/core/config/schema.ts +0 -694
  51. package/core/config/validator.ts +0 -540
  52. package/core/framework/__tests__/server.test.ts +0 -233
  53. package/core/framework/client.ts +0 -132
  54. package/core/framework/index.ts +0 -8
  55. package/core/framework/server.ts +0 -501
  56. package/core/framework/types.ts +0 -63
  57. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  58. package/core/plugins/__tests__/manager.test.ts +0 -398
  59. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  60. package/core/plugins/__tests__/registry.test.ts +0 -335
  61. package/core/plugins/built-in/index.ts +0 -142
  62. package/core/plugins/built-in/logger/index.ts +0 -180
  63. package/core/plugins/built-in/monitoring/README.md +0 -193
  64. package/core/plugins/built-in/monitoring/index.ts +0 -912
  65. package/core/plugins/built-in/static/index.ts +0 -289
  66. package/core/plugins/built-in/swagger/index.ts +0 -229
  67. package/core/plugins/built-in/vite/index.ts +0 -316
  68. package/core/plugins/config.ts +0 -348
  69. package/core/plugins/discovery.ts +0 -350
  70. package/core/plugins/executor.ts +0 -351
  71. package/core/plugins/index.ts +0 -195
  72. package/core/plugins/manager.ts +0 -583
  73. package/core/plugins/registry.ts +0 -424
  74. package/core/plugins/types.ts +0 -254
  75. package/core/server/framework.ts +0 -123
  76. package/core/server/index.ts +0 -8
  77. package/core/server/plugins/database.ts +0 -182
  78. package/core/server/plugins/logger.ts +0 -47
  79. package/core/server/plugins/swagger.ts +0 -34
  80. package/core/server/standalone.ts +0 -91
  81. package/core/templates/create-project.ts +0 -455
  82. package/core/types/api.ts +0 -169
  83. package/core/types/build.ts +0 -174
  84. package/core/types/config.ts +0 -68
  85. package/core/types/index.ts +0 -127
  86. package/core/types/plugin.ts +0 -94
  87. package/core/utils/__tests__/errors.test.ts +0 -139
  88. package/core/utils/__tests__/helpers.test.ts +0 -297
  89. package/core/utils/__tests__/logger.test.ts +0 -141
  90. package/core/utils/env-runtime-v2.ts +0 -232
  91. package/core/utils/env-runtime.ts +0 -252
  92. package/core/utils/errors/codes.ts +0 -115
  93. package/core/utils/errors/handlers.ts +0 -63
  94. package/core/utils/errors/index.ts +0 -81
  95. package/core/utils/helpers.ts +0 -180
  96. package/core/utils/index.ts +0 -18
  97. package/core/utils/logger/index.ts +0 -161
  98. package/core/utils/logger.ts +0 -106
  99. package/core/utils/monitoring/index.ts +0 -212
  100. package/tsconfig.json +0 -51
  101. package/vite.config.ts +0 -42
@@ -1,398 +0,0 @@
1
- /**
2
- * Tests for Plugin Manager
3
- */
4
-
5
- import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
6
- import { PluginManager } from '../manager'
7
- import type { Plugin, PluginContext } from '../types'
8
- import type { Logger } from '../../utils/logger/index'
9
- import type { FluxStackConfig } from '../../config/schema'
10
-
11
- // Mock logger
12
- const mockLogger: Logger = {
13
- debug: vi.fn(),
14
- info: vi.fn(),
15
- warn: vi.fn(),
16
- error: vi.fn(),
17
- child: vi.fn(() => mockLogger),
18
- time: vi.fn(),
19
- timeEnd: vi.fn(),
20
- request: vi.fn()
21
- }
22
-
23
- // Mock config
24
- const mockConfig: FluxStackConfig = {
25
- app: { name: 'test-app', version: '1.0.0' },
26
- server: {
27
- port: 3000,
28
- host: 'localhost',
29
- apiPrefix: '/api',
30
- cors: {
31
- origins: ['*'],
32
- methods: ['GET', 'POST'],
33
- headers: ['Content-Type']
34
- },
35
- middleware: []
36
- },
37
- client: {
38
- port: 5173,
39
- proxy: { target: 'http://localhost:3000' },
40
- build: {
41
- sourceMaps: true,
42
- minify: false,
43
- target: 'esnext',
44
- outDir: 'dist/client'
45
- }
46
- },
47
- build: {
48
- target: 'bun',
49
- outDir: 'dist',
50
- optimization: {
51
- minify: false,
52
- treeshake: false,
53
- compress: false,
54
- splitChunks: false,
55
- bundleAnalyzer: false
56
- },
57
- sourceMaps: true,
58
- clean: true
59
- },
60
- plugins: {
61
- enabled: [], // Enable all plugins by default for testing
62
- disabled: [],
63
- config: {}
64
- },
65
- logging: {
66
- level: 'info',
67
- format: 'pretty',
68
- transports: []
69
- },
70
- monitoring: {
71
- enabled: false,
72
- metrics: {
73
- enabled: false,
74
- collectInterval: 5000,
75
- httpMetrics: false,
76
- systemMetrics: false,
77
- customMetrics: false
78
- },
79
- profiling: {
80
- enabled: false,
81
- sampleRate: 0.1,
82
- memoryProfiling: false,
83
- cpuProfiling: false
84
- },
85
- exporters: []
86
- }
87
- }
88
-
89
- describe('PluginManager', () => {
90
- let manager: PluginManager
91
- let mockApp: any
92
-
93
- beforeEach(() => {
94
- mockApp = { use: vi.fn(), get: vi.fn(), post: vi.fn() }
95
- manager = new PluginManager({
96
- config: mockConfig,
97
- logger: mockLogger,
98
- app: mockApp
99
- })
100
- vi.clearAllMocks()
101
- })
102
-
103
- afterEach(async () => {
104
- if (manager) {
105
- await manager.shutdown()
106
- }
107
- })
108
-
109
- describe('Initialization', () => {
110
- it('should initialize successfully', async () => {
111
- await manager.initialize()
112
- expect(mockLogger.info).toHaveBeenCalledWith('Initializing plugin manager')
113
- expect(mockLogger.info).toHaveBeenCalledWith('Plugin manager initialized successfully', expect.any(Object))
114
- })
115
-
116
- it('should not initialize twice', async () => {
117
- await manager.initialize()
118
- await manager.initialize() // Second call should be ignored
119
-
120
- // Should only log initialization once
121
- expect(mockLogger.info).toHaveBeenCalledTimes(3) // discovery + init start + init complete
122
- })
123
- })
124
-
125
- describe('Plugin Registration', () => {
126
- it('should register a plugin', async () => {
127
- const plugin: Plugin = {
128
- name: 'test-plugin',
129
- setup: vi.fn()
130
- }
131
-
132
- await manager.registerPlugin(plugin)
133
-
134
- const registry = manager.getRegistry()
135
- expect(registry.get('test-plugin')).toBe(plugin)
136
- })
137
-
138
- it('should execute setup hook when registering after initialization', async () => {
139
- const setupSpy = vi.fn()
140
- const plugin: Plugin = {
141
- name: 'test-plugin',
142
- setup: setupSpy
143
- }
144
-
145
- await manager.initialize()
146
- await manager.registerPlugin(plugin)
147
-
148
- expect(setupSpy).toHaveBeenCalled()
149
- })
150
-
151
- it('should unregister a plugin', async () => {
152
- const plugin: Plugin = {
153
- name: 'removable-plugin'
154
- }
155
-
156
- await manager.registerPlugin(plugin)
157
- manager.unregisterPlugin('removable-plugin')
158
-
159
- const registry = manager.getRegistry()
160
- expect(registry.get('removable-plugin')).toBeUndefined()
161
- })
162
- })
163
-
164
- describe('Hook Execution', () => {
165
- it('should execute setup hook on all plugins', async () => {
166
- const setupSpy1 = vi.fn()
167
- const setupSpy2 = vi.fn()
168
-
169
- const plugin1: Plugin = {
170
- name: 'plugin-1',
171
- setup: setupSpy1
172
- }
173
-
174
- const plugin2: Plugin = {
175
- name: 'plugin-2',
176
- setup: setupSpy2
177
- }
178
-
179
- await manager.registerPlugin(plugin1)
180
- await manager.registerPlugin(plugin2)
181
-
182
- const results = await manager.executeHook('setup')
183
-
184
- expect(results).toHaveLength(2)
185
- expect(results.every(r => r.success)).toBe(true)
186
- expect(setupSpy1).toHaveBeenCalled()
187
- expect(setupSpy2).toHaveBeenCalled()
188
- })
189
-
190
- it('should execute hooks in dependency order', async () => {
191
- const executionOrder: string[] = []
192
-
193
- const pluginA: Plugin = {
194
- name: 'plugin-a',
195
- setup: () => { executionOrder.push('plugin-a') }
196
- }
197
-
198
- const pluginB: Plugin = {
199
- name: 'plugin-b',
200
- dependencies: ['plugin-a'],
201
- setup: () => { executionOrder.push('plugin-b') }
202
- }
203
-
204
- await manager.registerPlugin(pluginA)
205
- await manager.registerPlugin(pluginB)
206
-
207
- await manager.executeHook('setup')
208
-
209
- expect(executionOrder).toEqual(['plugin-a', 'plugin-b'])
210
- })
211
-
212
- it('should respect plugin priorities', async () => {
213
- const executionOrder: string[] = []
214
-
215
- const lowPriorityPlugin: Plugin = {
216
- name: 'low-priority',
217
- priority: 1,
218
- setup: () => { executionOrder.push('low-priority') }
219
- }
220
-
221
- const highPriorityPlugin: Plugin = {
222
- name: 'high-priority',
223
- priority: 10,
224
- setup: () => { executionOrder.push('high-priority') }
225
- }
226
-
227
- await manager.registerPlugin(lowPriorityPlugin)
228
- await manager.registerPlugin(highPriorityPlugin)
229
-
230
- await manager.executeHook('setup')
231
-
232
- expect(executionOrder.indexOf('high-priority')).toBeLessThan(executionOrder.indexOf('low-priority'))
233
- })
234
-
235
- it('should handle plugin hook errors gracefully', async () => {
236
- const errorPlugin: Plugin = {
237
- name: 'error-plugin',
238
- setup: () => {
239
- throw new Error('Plugin setup failed')
240
- }
241
- }
242
-
243
- const goodPlugin: Plugin = {
244
- name: 'good-plugin',
245
- setup: vi.fn()
246
- }
247
-
248
- await manager.registerPlugin(errorPlugin)
249
- await manager.registerPlugin(goodPlugin)
250
-
251
- const results = await manager.executeHook('setup')
252
-
253
- expect(results).toHaveLength(2)
254
- expect(results.find(r => r.plugin === 'error-plugin')?.success).toBe(false)
255
- expect(results.find(r => r.plugin === 'good-plugin')?.success).toBe(true)
256
- })
257
-
258
- it('should execute hooks in parallel when specified', async () => {
259
- const startTimes: Record<string, number> = {}
260
- const endTimes: Record<string, number> = {}
261
-
262
- const plugin1: Plugin = {
263
- name: 'plugin-1',
264
- setup: async () => {
265
- startTimes['plugin-1'] = Date.now()
266
- await new Promise(resolve => setTimeout(resolve, 50))
267
- endTimes['plugin-1'] = Date.now()
268
- }
269
- }
270
-
271
- const plugin2: Plugin = {
272
- name: 'plugin-2',
273
- setup: async () => {
274
- startTimes['plugin-2'] = Date.now()
275
- await new Promise(resolve => setTimeout(resolve, 50))
276
- endTimes['plugin-2'] = Date.now()
277
- }
278
- }
279
-
280
- await manager.registerPlugin(plugin1)
281
- await manager.registerPlugin(plugin2)
282
-
283
- await manager.executeHook('setup', undefined, { parallel: true })
284
-
285
- // In parallel execution, both should start around the same time
286
- const timeDiff = Math.abs(startTimes['plugin-1'] - startTimes['plugin-2'])
287
- expect(timeDiff).toBeLessThan(20) // Allow for small timing differences
288
- })
289
-
290
- it('should handle hook timeout', async () => {
291
- const slowPlugin: Plugin = {
292
- name: 'slow-plugin',
293
- setup: async () => {
294
- await new Promise(resolve => setTimeout(resolve, 200))
295
- }
296
- }
297
-
298
- await manager.registerPlugin(slowPlugin)
299
-
300
- const results = await manager.executeHook('setup', undefined, { timeout: 100 })
301
-
302
- expect(results).toHaveLength(1)
303
- expect(results[0].success).toBe(false)
304
- expect(results[0].error?.message).toContain('timed out')
305
- })
306
- })
307
-
308
- describe('Plugin Context', () => {
309
- it('should provide correct context to plugins', async () => {
310
- let receivedContext: PluginContext | undefined
311
-
312
- const plugin: Plugin = {
313
- name: 'context-plugin',
314
- setup: (context) => {
315
- receivedContext = context
316
- }
317
- }
318
-
319
- await manager.registerPlugin(plugin)
320
- await manager.executeHook('setup')
321
-
322
- expect(receivedContext).toBeDefined()
323
- expect(receivedContext?.config).toBe(mockConfig)
324
- expect(receivedContext?.app).toBe(mockApp)
325
- expect(receivedContext?.logger).toBeDefined()
326
- expect(receivedContext?.utils).toBeDefined()
327
- })
328
-
329
- it('should provide plugin-specific logger', async () => {
330
- const plugin: Plugin = {
331
- name: 'logger-plugin',
332
- setup: (_context) => {
333
- // Logger context is available but not used in this test
334
- }
335
- }
336
-
337
- await manager.registerPlugin(plugin)
338
- await manager.executeHook('setup')
339
-
340
- expect(mockLogger.child).toHaveBeenCalledWith({ plugin: 'logger-plugin' })
341
- })
342
- })
343
-
344
- describe('Plugin Metrics', () => {
345
- it('should track plugin metrics', async () => {
346
- const plugin: Plugin = {
347
- name: 'metrics-plugin',
348
- setup: async () => {
349
- await new Promise(resolve => setTimeout(resolve, 10))
350
- }
351
- }
352
-
353
- await manager.registerPlugin(plugin)
354
- await manager.executeHook('setup')
355
-
356
- const metrics = manager.getPluginMetrics('metrics-plugin')
357
- expect(metrics).toBeDefined()
358
- expect(typeof metrics).toBe('object')
359
- expect((metrics as any).hookExecutions).toBeDefined()
360
- })
361
-
362
- it('should get all plugin metrics', async () => {
363
- const plugin1: Plugin = { name: 'plugin-1', setup: vi.fn() }
364
- const plugin2: Plugin = { name: 'plugin-2', setup: vi.fn() }
365
-
366
- await manager.registerPlugin(plugin1)
367
- await manager.registerPlugin(plugin2)
368
- await manager.executeHook('setup')
369
-
370
- const allMetrics = manager.getPluginMetrics()
371
- expect(allMetrics instanceof Map).toBe(true)
372
- expect((allMetrics as Map<string, any>).size).toBe(2)
373
- })
374
- })
375
-
376
- describe('Shutdown', () => {
377
- it('should shutdown gracefully', async () => {
378
- const shutdownSpy = vi.fn()
379
-
380
- const plugin: Plugin = {
381
- name: 'shutdown-plugin',
382
- onServerStop: shutdownSpy
383
- }
384
-
385
- await manager.registerPlugin(plugin)
386
- await manager.initialize()
387
- await manager.shutdown()
388
-
389
- expect(shutdownSpy).toHaveBeenCalled()
390
- expect(mockLogger.info).toHaveBeenCalledWith('Shutting down plugin manager')
391
- })
392
-
393
- it('should not shutdown if not initialized', async () => {
394
- await manager.shutdown()
395
- expect(mockLogger.info).not.toHaveBeenCalledWith('Shutting down plugin manager')
396
- })
397
- })
398
- })