create-fluxstack 1.0.13 → 1.0.15
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.
- package/.env.example +29 -29
- package/app/client/README.md +69 -69
- package/app/client/index.html +14 -13
- package/app/client/src/App.tsx +157 -524
- package/app/client/src/components/ErrorBoundary.tsx +107 -0
- package/app/client/src/components/ErrorDisplay.css +365 -0
- package/app/client/src/components/ErrorDisplay.tsx +258 -0
- package/app/client/src/components/FluxStackConfig.tsx +1321 -0
- package/app/client/src/components/HybridLiveCounter.tsx +140 -0
- package/app/client/src/components/LiveClock.tsx +286 -0
- package/app/client/src/components/MainLayout.tsx +390 -0
- package/app/client/src/components/SidebarNavigation.tsx +391 -0
- package/app/client/src/components/StateDemo.tsx +178 -0
- package/app/client/src/components/SystemMonitor.tsx +1038 -0
- package/app/client/src/components/Teste.tsx +104 -0
- package/app/client/src/components/UserProfile.tsx +809 -0
- package/app/client/src/hooks/useAuth.ts +39 -0
- package/app/client/src/hooks/useNotifications.ts +56 -0
- package/app/client/src/lib/eden-api.ts +189 -53
- package/app/client/src/lib/errors.ts +340 -0
- package/app/client/src/lib/hooks/useErrorHandler.ts +258 -0
- package/app/client/src/lib/index.ts +45 -0
- package/app/client/src/main.tsx +3 -2
- package/app/client/src/pages/ApiDocs.tsx +182 -0
- package/app/client/src/pages/Demo.tsx +174 -0
- package/app/client/src/pages/HybridLive.tsx +263 -0
- package/app/client/src/pages/Overview.tsx +155 -0
- package/app/client/src/store/README.md +43 -0
- package/app/client/src/store/index.ts +16 -0
- package/app/client/src/store/slices/uiSlice.ts +151 -0
- package/app/client/src/store/slices/userSlice.ts +161 -0
- package/app/client/src/test/README.md +257 -0
- package/app/client/src/test/setup.ts +70 -0
- package/app/client/src/test/types.ts +12 -0
- package/app/client/src/vite-env.d.ts +1 -1
- package/app/client/tsconfig.app.json +44 -43
- package/app/client/tsconfig.json +7 -7
- package/app/client/tsconfig.node.json +25 -25
- package/app/client/zustand-setup.md +65 -0
- package/app/server/controllers/users.controller.ts +68 -68
- package/app/server/index.ts +9 -1
- package/app/server/live/CounterComponent.ts +191 -0
- package/app/server/live/FluxStackConfig.ts +529 -0
- package/app/server/live/LiveClockComponent.ts +214 -0
- package/app/server/live/SidebarNavigation.ts +156 -0
- package/app/server/live/SystemMonitor.ts +594 -0
- package/app/server/live/SystemMonitorIntegration.ts +151 -0
- package/app/server/live/TesteComponent.ts +87 -0
- package/app/server/live/UserProfileComponent.ts +135 -0
- package/app/server/live/register-components.ts +28 -0
- package/app/server/middleware/auth.ts +136 -0
- package/app/server/middleware/errorHandling.ts +250 -0
- package/app/server/middleware/index.ts +10 -0
- package/app/server/middleware/rateLimit.ts +193 -0
- package/app/server/middleware/requestLogging.ts +215 -0
- package/app/server/middleware/validation.ts +270 -0
- package/app/server/routes/index.ts +14 -2
- package/app/server/routes/upload.ts +92 -0
- package/app/server/routes/users.routes.ts +2 -9
- package/app/server/services/NotificationService.ts +302 -0
- package/app/server/services/UserService.ts +222 -0
- package/app/server/services/index.ts +46 -0
- package/core/cli/commands/plugin-deps.ts +263 -0
- package/core/cli/generators/README.md +339 -0
- package/core/cli/generators/component.ts +770 -0
- package/core/cli/generators/controller.ts +299 -0
- package/core/cli/generators/index.ts +144 -0
- package/core/cli/generators/interactive.ts +228 -0
- package/core/cli/generators/prompts.ts +83 -0
- package/core/cli/generators/route.ts +513 -0
- package/core/cli/generators/service.ts +465 -0
- package/core/cli/generators/template-engine.ts +154 -0
- package/core/cli/generators/types.ts +71 -0
- package/core/cli/generators/utils.ts +192 -0
- package/core/cli/index.ts +69 -0
- package/core/cli/plugin-discovery.ts +16 -85
- package/core/client/fluxstack.ts +17 -0
- package/core/client/hooks/index.ts +7 -0
- package/core/client/hooks/state-validator.ts +130 -0
- package/core/client/hooks/useAuth.ts +49 -0
- package/core/client/hooks/useChunkedUpload.ts +258 -0
- package/core/client/hooks/useHybridLiveComponent.ts +967 -0
- package/core/client/hooks/useWebSocket.ts +373 -0
- package/core/client/index.ts +47 -0
- package/core/client/state/createStore.ts +193 -0
- package/core/client/state/index.ts +15 -0
- package/core/config/env-dynamic.ts +1 -1
- package/core/config/env.ts +2 -1
- package/core/config/runtime-config.ts +3 -3
- package/core/config/schema.ts +84 -49
- package/core/framework/server.ts +30 -0
- package/core/index.ts +25 -0
- package/core/live/ComponentRegistry.ts +399 -0
- package/core/live/types.ts +164 -0
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +1201 -0
- package/core/plugins/built-in/live-components/index.ts +27 -0
- package/core/plugins/built-in/logger/index.ts +1 -1
- package/core/plugins/built-in/monitoring/index.ts +1 -1
- package/core/plugins/built-in/static/index.ts +1 -1
- package/core/plugins/built-in/swagger/index.ts +1 -1
- package/core/plugins/built-in/vite/index.ts +1 -1
- package/core/plugins/dependency-manager.ts +384 -0
- package/core/plugins/index.ts +5 -1
- package/core/plugins/manager.ts +7 -3
- package/core/plugins/registry.ts +88 -10
- package/core/plugins/types.ts +11 -11
- package/core/server/framework.ts +43 -0
- package/core/server/index.ts +11 -1
- package/core/server/live/ComponentRegistry.ts +1017 -0
- package/core/server/live/FileUploadManager.ts +272 -0
- package/core/server/live/LiveComponentPerformanceMonitor.ts +930 -0
- package/core/server/live/SingleConnectionManager.ts +0 -0
- package/core/server/live/StateSignature.ts +644 -0
- package/core/server/live/WebSocketConnectionManager.ts +688 -0
- package/core/server/live/websocket-plugin.ts +435 -0
- package/core/server/middleware/errorHandling.ts +141 -0
- package/core/server/middleware/index.ts +16 -0
- package/core/server/plugins/static-files-plugin.ts +232 -0
- package/core/server/services/BaseService.ts +95 -0
- package/core/server/services/ServiceContainer.ts +144 -0
- package/core/server/services/index.ts +9 -0
- package/core/templates/create-project.ts +196 -33
- package/core/testing/index.ts +10 -0
- package/core/testing/setup.ts +74 -0
- package/core/types/build.ts +38 -14
- package/core/types/types.ts +319 -0
- package/core/utils/env-runtime.ts +7 -0
- package/core/utils/errors/handlers.ts +264 -39
- package/core/utils/errors/index.ts +528 -18
- package/core/utils/errors/middleware.ts +114 -0
- package/core/utils/logger/formatters.ts +222 -0
- package/core/utils/logger/index.ts +167 -48
- package/core/utils/logger/middleware.ts +253 -0
- package/core/utils/logger/performance.ts +384 -0
- package/core/utils/logger/transports.ts +365 -0
- package/create-fluxstack.ts +296 -296
- package/fluxstack.config.ts +17 -1
- package/package-template.json +66 -66
- package/package.json +31 -6
- package/public/README.md +16 -0
- package/vite.config.ts +29 -14
- package/.claude/settings.local.json +0 -74
- package/.github/workflows/ci-build-tests.yml +0 -480
- package/.github/workflows/dependency-management.yml +0 -324
- package/.github/workflows/release-validation.yml +0 -355
- package/.kiro/specs/fluxstack-architecture-optimization/design.md +0 -700
- package/.kiro/specs/fluxstack-architecture-optimization/requirements.md +0 -127
- package/.kiro/specs/fluxstack-architecture-optimization/tasks.md +0 -330
- package/CLAUDE.md +0 -200
- package/Dockerfile +0 -58
- package/Dockerfile.backend +0 -52
- package/Dockerfile.frontend +0 -54
- package/README-Docker.md +0 -85
- package/ai-context/00-QUICK-START.md +0 -86
- package/ai-context/README.md +0 -88
- package/ai-context/development/eden-treaty-guide.md +0 -362
- package/ai-context/development/patterns.md +0 -382
- package/ai-context/development/plugins-guide.md +0 -572
- package/ai-context/examples/crud-complete.md +0 -626
- package/ai-context/project/architecture.md +0 -399
- package/ai-context/project/overview.md +0 -213
- package/ai-context/recent-changes/eden-treaty-refactor.md +0 -281
- package/ai-context/recent-changes/type-inference-fix.md +0 -223
- package/ai-context/reference/environment-vars.md +0 -384
- package/ai-context/reference/troubleshooting.md +0 -407
- package/app/client/src/components/TestPage.tsx +0 -453
- package/bun.lock +0 -1063
- package/bunfig.toml +0 -16
- package/core/__tests__/integration.test.ts +0 -227
- package/core/build/index.ts +0 -186
- package/core/config/__tests__/config-loader.test.ts +0 -554
- package/core/config/__tests__/config-merger.test.ts +0 -657
- package/core/config/__tests__/env-converter.test.ts +0 -372
- package/core/config/__tests__/env-processor.test.ts +0 -431
- package/core/config/__tests__/env.test.ts +0 -452
- package/core/config/__tests__/integration.test.ts +0 -418
- package/core/config/__tests__/loader.test.ts +0 -331
- package/core/config/__tests__/schema.test.ts +0 -129
- package/core/config/__tests__/validator.test.ts +0 -318
- package/core/framework/__tests__/server.test.ts +0 -233
- package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
- package/core/plugins/__tests__/manager.test.ts +0 -398
- package/core/plugins/__tests__/monitoring.test.ts +0 -401
- package/core/plugins/__tests__/registry.test.ts +0 -335
- package/core/utils/__tests__/errors.test.ts +0 -139
- package/core/utils/__tests__/helpers.test.ts +0 -297
- package/core/utils/__tests__/logger.test.ts +0 -141
- package/create-test-app.ts +0 -156
- package/docker-compose.microservices.yml +0 -75
- package/docker-compose.simple.yml +0 -57
- package/docker-compose.yml +0 -71
- package/eslint.config.js +0 -23
- package/flux-cli.ts +0 -214
- package/nginx-lb.conf +0 -37
- package/publish.sh +0 -63
- package/run-clean.ts +0 -26
- package/run-env-tests.ts +0 -313
- package/tailwind.config.js +0 -34
- package/tests/__mocks__/api.ts +0 -56
- package/tests/fixtures/users.ts +0 -69
- package/tests/integration/api/users.routes.test.ts +0 -221
- package/tests/setup.ts +0 -29
- package/tests/unit/app/client/App-simple.test.tsx +0 -56
- package/tests/unit/app/client/App.test.tsx.skip +0 -237
- package/tests/unit/app/client/eden-api.test.ts +0 -186
- package/tests/unit/app/client/simple.test.tsx +0 -23
- package/tests/unit/app/controllers/users.controller.test.ts +0 -150
- package/tests/unit/core/create-project.test.ts.skip +0 -95
- package/tests/unit/core/framework.test.ts +0 -144
- package/tests/unit/core/plugins/logger.test.ts.skip +0 -268
- package/tests/unit/core/plugins/vite.test.ts.disabled +0 -188
- package/tests/utils/test-helpers.ts +0 -61
- package/vitest.config.ts +0 -50
- package/workspace.json +0 -6
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
|
|
2
|
-
import { ProjectCreator } from '@/core/templates/create-project'
|
|
3
|
-
import { rmdir, mkdir } from 'fs/promises'
|
|
4
|
-
import { join } from 'path'
|
|
5
|
-
|
|
6
|
-
// Mock bun APIs to avoid actual file operations in tests
|
|
7
|
-
vi.mock('bun', async () => {
|
|
8
|
-
const actual = await vi.importActual('bun')
|
|
9
|
-
return {
|
|
10
|
-
...actual,
|
|
11
|
-
spawn: vi.fn(() => ({
|
|
12
|
-
exited: Promise.resolve(0),
|
|
13
|
-
stdout: { readable: null },
|
|
14
|
-
stderr: { readable: null }
|
|
15
|
-
})),
|
|
16
|
-
write: vi.fn(),
|
|
17
|
-
file: vi.fn(() => ({
|
|
18
|
-
exists: () => true,
|
|
19
|
-
text: () => 'mock content'
|
|
20
|
-
}))
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
vi.mock('fs/promises', () => ({
|
|
25
|
-
mkdir: vi.fn(),
|
|
26
|
-
readdir: vi.fn(() => [])
|
|
27
|
-
}))
|
|
28
|
-
|
|
29
|
-
describe('ProjectCreator', () => {
|
|
30
|
-
const testDir = join(process.cwd(), 'test-project-temp')
|
|
31
|
-
let creator: ProjectCreator
|
|
32
|
-
|
|
33
|
-
beforeEach(() => {
|
|
34
|
-
creator = new ProjectCreator({
|
|
35
|
-
name: 'test-project',
|
|
36
|
-
targetDir: testDir,
|
|
37
|
-
template: 'basic'
|
|
38
|
-
})
|
|
39
|
-
vi.clearAllMocks()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
afterEach(async () => {
|
|
43
|
-
try {
|
|
44
|
-
await rmdir(testDir, { recursive: true })
|
|
45
|
-
} catch {
|
|
46
|
-
// Ignore cleanup errors
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
describe('constructor', () => {
|
|
51
|
-
it('should create ProjectCreator with basic options', () => {
|
|
52
|
-
expect(creator).toBeDefined()
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should set default template to basic', () => {
|
|
56
|
-
const defaultCreator = new ProjectCreator({
|
|
57
|
-
name: 'test-project'
|
|
58
|
-
})
|
|
59
|
-
expect(defaultCreator).toBeDefined()
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
it('should handle custom target directory', () => {
|
|
63
|
-
const customCreator = new ProjectCreator({
|
|
64
|
-
name: 'custom-project',
|
|
65
|
-
targetDir: '/custom/path',
|
|
66
|
-
template: 'full'
|
|
67
|
-
})
|
|
68
|
-
expect(customCreator).toBeDefined()
|
|
69
|
-
})
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
describe('validation', () => {
|
|
73
|
-
it('should validate project names correctly', () => {
|
|
74
|
-
// Valid names
|
|
75
|
-
expect(() => new ProjectCreator({ name: 'valid-name' })).not.toThrow()
|
|
76
|
-
expect(() => new ProjectCreator({ name: 'valid_name' })).not.toThrow()
|
|
77
|
-
expect(() => new ProjectCreator({ name: 'validName123' })).not.toThrow()
|
|
78
|
-
})
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
describe('create method', () => {
|
|
82
|
-
it('should handle create process without throwing', async () => {
|
|
83
|
-
// Mock all async operations to succeed
|
|
84
|
-
const mkdirMock = vi.mocked(mkdir)
|
|
85
|
-
mkdirMock.mockResolvedValue(undefined)
|
|
86
|
-
|
|
87
|
-
// We'll test that the method doesn't throw
|
|
88
|
-
// Full integration testing would require actual file system operations
|
|
89
|
-
expect(async () => {
|
|
90
|
-
// In a real test, we'd mock all the dependencies properly
|
|
91
|
-
// For now, we just ensure the class is properly structured
|
|
92
|
-
}).not.toThrow()
|
|
93
|
-
})
|
|
94
|
-
})
|
|
95
|
-
})
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest'
|
|
2
|
-
import { FluxStackFramework } from '@/core/server/framework'
|
|
3
|
-
import type { Plugin } from '@/core/types'
|
|
4
|
-
import type { FluxStackConfig } from '@/core/config/schema'
|
|
5
|
-
|
|
6
|
-
describe('FluxStackFramework', () => {
|
|
7
|
-
let framework: FluxStackFramework
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
framework = new FluxStackFramework({
|
|
11
|
-
server: {
|
|
12
|
-
port: 3001,
|
|
13
|
-
host: 'localhost',
|
|
14
|
-
apiPrefix: '/api',
|
|
15
|
-
cors: {
|
|
16
|
-
origins: ['*'],
|
|
17
|
-
methods: ['GET', 'POST'],
|
|
18
|
-
headers: ['Content-Type'],
|
|
19
|
-
credentials: false,
|
|
20
|
-
maxAge: 86400
|
|
21
|
-
},
|
|
22
|
-
middleware: []
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
describe('constructor', () => {
|
|
28
|
-
it('should create framework with default config', () => {
|
|
29
|
-
const defaultFramework = new FluxStackFramework()
|
|
30
|
-
const context = defaultFramework.getContext()
|
|
31
|
-
|
|
32
|
-
// Environment variables now control default values
|
|
33
|
-
expect(context.config.server.port).toBeDefined()
|
|
34
|
-
expect(context.config.server.apiPrefix).toBe('/api')
|
|
35
|
-
expect(context.config.client.port).toBeDefined()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('should create framework with custom config', () => {
|
|
39
|
-
const config: Partial<FluxStackConfig> = {
|
|
40
|
-
server: {
|
|
41
|
-
port: 4000,
|
|
42
|
-
host: 'localhost',
|
|
43
|
-
apiPrefix: '/custom-api',
|
|
44
|
-
cors: {
|
|
45
|
-
origins: ['*'],
|
|
46
|
-
methods: ['GET', 'POST'],
|
|
47
|
-
headers: ['Content-Type'],
|
|
48
|
-
credentials: false,
|
|
49
|
-
maxAge: 86400
|
|
50
|
-
},
|
|
51
|
-
middleware: []
|
|
52
|
-
},
|
|
53
|
-
client: {
|
|
54
|
-
port: 5174,
|
|
55
|
-
proxy: {
|
|
56
|
-
target: 'http://localhost:4000',
|
|
57
|
-
changeOrigin: true
|
|
58
|
-
},
|
|
59
|
-
build: {
|
|
60
|
-
outDir: 'dist/client',
|
|
61
|
-
sourceMaps: true,
|
|
62
|
-
minify: false,
|
|
63
|
-
target: 'es2020'
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const customFramework = new FluxStackFramework(config)
|
|
69
|
-
const context = customFramework.getContext()
|
|
70
|
-
|
|
71
|
-
expect(context.config.server.port).toBe(4000)
|
|
72
|
-
expect(context.config.client.port).toBe(5174)
|
|
73
|
-
expect(context.config.server.apiPrefix).toBe('/custom-api')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('should set development mode correctly', () => {
|
|
77
|
-
const context = framework.getContext()
|
|
78
|
-
// Environment config manages NODE_ENV now
|
|
79
|
-
expect(typeof context.isDevelopment).toBe('boolean')
|
|
80
|
-
expect(typeof context.isProduction).toBe('boolean')
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
describe('plugin system', () => {
|
|
85
|
-
it('should add plugins correctly', () => {
|
|
86
|
-
const mockPlugin: Plugin = {
|
|
87
|
-
name: 'test-plugin',
|
|
88
|
-
setup: () => {}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const result = framework.use(mockPlugin)
|
|
92
|
-
expect(result).toBe(framework) // Should return framework for chaining
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it('should handle multiple plugins', () => {
|
|
96
|
-
const plugin1: Plugin = {
|
|
97
|
-
name: 'plugin-1',
|
|
98
|
-
setup: () => {}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const plugin2: Plugin = {
|
|
102
|
-
name: 'plugin-2',
|
|
103
|
-
setup: () => {}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
framework.use(plugin1).use(plugin2)
|
|
107
|
-
// Framework should not throw and should allow chaining
|
|
108
|
-
expect(framework).toBeDefined()
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
describe('routes', () => {
|
|
113
|
-
it('should register routes correctly', () => {
|
|
114
|
-
// Test that routes method exists and returns framework
|
|
115
|
-
expect(typeof framework.routes).toBe('function')
|
|
116
|
-
|
|
117
|
-
// Skip actual route registration test to avoid Elysia mock complexity
|
|
118
|
-
// This test verifies the method is available for chaining
|
|
119
|
-
expect(framework).toBeDefined()
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
describe('getApp', () => {
|
|
124
|
-
it('should return Elysia app instance', () => {
|
|
125
|
-
const app = framework.getApp()
|
|
126
|
-
expect(app).toBeDefined()
|
|
127
|
-
// Elysia apps have these methods
|
|
128
|
-
expect(typeof app.get).toBe('function')
|
|
129
|
-
expect(typeof app.post).toBe('function')
|
|
130
|
-
expect(typeof app.listen).toBe('function')
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
describe('getContext', () => {
|
|
135
|
-
it('should return framework context', () => {
|
|
136
|
-
const context = framework.getContext()
|
|
137
|
-
|
|
138
|
-
expect(context).toBeDefined()
|
|
139
|
-
expect(context.config).toBeDefined()
|
|
140
|
-
expect(typeof context.isDevelopment).toBe('boolean')
|
|
141
|
-
expect(typeof context.isProduction).toBe('boolean')
|
|
142
|
-
})
|
|
143
|
-
})
|
|
144
|
-
})
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
import { loggerPlugin } from '@/core/server/plugins/logger'
|
|
3
|
-
import type { FluxStackContext } from '@/core/types'
|
|
4
|
-
|
|
5
|
-
describe('Logger Plugin', () => {
|
|
6
|
-
let mockContext: FluxStackContext
|
|
7
|
-
let mockApp: any
|
|
8
|
-
|
|
9
|
-
beforeEach(() => {
|
|
10
|
-
vi.clearAllMocks()
|
|
11
|
-
|
|
12
|
-
mockContext = {
|
|
13
|
-
config: {
|
|
14
|
-
port: 3000,
|
|
15
|
-
vitePort: 5173,
|
|
16
|
-
clientPath: 'app/client',
|
|
17
|
-
apiPrefix: '/api',
|
|
18
|
-
cors: {
|
|
19
|
-
origins: ['http://localhost:5173'],
|
|
20
|
-
methods: ['GET', 'POST'],
|
|
21
|
-
headers: ['Content-Type']
|
|
22
|
-
},
|
|
23
|
-
build: {
|
|
24
|
-
outDir: 'dist',
|
|
25
|
-
target: 'es2020'
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
isDevelopment: true,
|
|
29
|
-
isProduction: false,
|
|
30
|
-
envConfig: {}
|
|
31
|
-
} as FluxStackContext
|
|
32
|
-
|
|
33
|
-
mockApp = {
|
|
34
|
-
onRequest: vi.fn(),
|
|
35
|
-
onResponse: vi.fn(),
|
|
36
|
-
onError: vi.fn(),
|
|
37
|
-
use: vi.fn()
|
|
38
|
-
}
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('Plugin Setup', () => {
|
|
42
|
-
it('should have correct plugin name', () => {
|
|
43
|
-
expect(loggerPlugin.name).toBe('logger')
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('should have setup function', () => {
|
|
47
|
-
expect(typeof loggerPlugin.setup).toBe('function')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('should setup logger middleware', () => {
|
|
51
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
52
|
-
|
|
53
|
-
// Should register onRequest, onResponse, and onError handlers
|
|
54
|
-
expect(mockApp.onRequest).toHaveBeenCalledWith(expect.any(Function))
|
|
55
|
-
expect(mockApp.onResponse).toHaveBeenCalledWith(expect.any(Function))
|
|
56
|
-
expect(mockApp.onError).toHaveBeenCalledWith(expect.any(Function))
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
describe('Request Logging', () => {
|
|
61
|
-
it('should log request details', () => {
|
|
62
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
63
|
-
|
|
64
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
65
|
-
|
|
66
|
-
// Get the onRequest handler
|
|
67
|
-
const onRequestHandler = mockApp.onRequest.mock.calls[0][0]
|
|
68
|
-
|
|
69
|
-
const mockRequest = new Request('http://localhost:3000/api/users', {
|
|
70
|
-
method: 'GET',
|
|
71
|
-
headers: {
|
|
72
|
-
'user-agent': 'test-agent',
|
|
73
|
-
'accept': 'application/json'
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const mockContext = {
|
|
78
|
-
request: mockRequest,
|
|
79
|
-
set: {}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
onRequestHandler(mockContext)
|
|
83
|
-
|
|
84
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
85
|
-
expect.stringContaining('📥'),
|
|
86
|
-
expect.stringContaining('GET'),
|
|
87
|
-
expect.stringContaining('/api/users')
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
consoleSpy.mockRestore()
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
it('should log POST requests with different styling', () => {
|
|
94
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
95
|
-
|
|
96
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
97
|
-
|
|
98
|
-
const onRequestHandler = mockApp.onRequest.mock.calls[0][0]
|
|
99
|
-
|
|
100
|
-
const mockRequest = new Request('http://localhost:3000/api/users', {
|
|
101
|
-
method: 'POST',
|
|
102
|
-
headers: {
|
|
103
|
-
'content-type': 'application/json'
|
|
104
|
-
}
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
const mockContext = {
|
|
108
|
-
request: mockRequest,
|
|
109
|
-
set: {}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
onRequestHandler(mockContext)
|
|
113
|
-
|
|
114
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
115
|
-
expect.stringContaining('📥'),
|
|
116
|
-
expect.stringContaining('POST'),
|
|
117
|
-
expect.stringContaining('/api/users')
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
consoleSpy.mockRestore()
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
describe('Response Logging', () => {
|
|
125
|
-
it('should log successful responses', () => {
|
|
126
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
127
|
-
|
|
128
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
129
|
-
|
|
130
|
-
const onResponseHandler = mockApp.onResponse.mock.calls[0][0]
|
|
131
|
-
|
|
132
|
-
const mockRequest = new Request('http://localhost:3000/api/users', {
|
|
133
|
-
method: 'GET'
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
const mockResponse = new Response('{"users": []}', {
|
|
137
|
-
status: 200,
|
|
138
|
-
statusText: 'OK',
|
|
139
|
-
headers: {
|
|
140
|
-
'content-type': 'application/json'
|
|
141
|
-
}
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
const mockContext = {
|
|
145
|
-
request: mockRequest,
|
|
146
|
-
response: mockResponse,
|
|
147
|
-
set: { status: 200 }
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
onResponseHandler(mockContext)
|
|
151
|
-
|
|
152
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
153
|
-
expect.stringContaining('📤'),
|
|
154
|
-
expect.stringContaining('GET'),
|
|
155
|
-
expect.stringContaining('/api/users'),
|
|
156
|
-
expect.stringContaining('200')
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
consoleSpy.mockRestore()
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('should log error responses differently', () => {
|
|
163
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
164
|
-
|
|
165
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
166
|
-
|
|
167
|
-
const onResponseHandler = mockApp.onResponse.mock.calls[0][0]
|
|
168
|
-
|
|
169
|
-
const mockRequest = new Request('http://localhost:3000/api/users/999', {
|
|
170
|
-
method: 'GET'
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
const mockResponse = new Response('{"error": "Not found"}', {
|
|
174
|
-
status: 404,
|
|
175
|
-
statusText: 'Not Found'
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
const mockContext = {
|
|
179
|
-
request: mockRequest,
|
|
180
|
-
response: mockResponse,
|
|
181
|
-
set: { status: 404 }
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
onResponseHandler(mockContext)
|
|
185
|
-
|
|
186
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
187
|
-
expect.stringContaining('📤'),
|
|
188
|
-
expect.stringContaining('GET'),
|
|
189
|
-
expect.stringContaining('/api/users/999'),
|
|
190
|
-
expect.stringContaining('404')
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
consoleSpy.mockRestore()
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
describe('Error Logging', () => {
|
|
198
|
-
it('should log errors with stack trace', () => {
|
|
199
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
200
|
-
|
|
201
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
202
|
-
|
|
203
|
-
const onErrorHandler = mockApp.onError.mock.calls[0][0]
|
|
204
|
-
|
|
205
|
-
const mockError = new Error('Test error')
|
|
206
|
-
const mockRequest = new Request('http://localhost:3000/api/test')
|
|
207
|
-
|
|
208
|
-
const mockContext = {
|
|
209
|
-
error: mockError,
|
|
210
|
-
request: mockRequest,
|
|
211
|
-
set: {}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
onErrorHandler(mockContext)
|
|
215
|
-
|
|
216
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
217
|
-
expect.stringContaining('❌ Error:'),
|
|
218
|
-
expect.stringContaining('Test error')
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
consoleSpy.mockRestore()
|
|
222
|
-
})
|
|
223
|
-
|
|
224
|
-
it('should handle errors without stack trace', () => {
|
|
225
|
-
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
|
226
|
-
|
|
227
|
-
loggerPlugin.setup(mockContext, mockApp)
|
|
228
|
-
|
|
229
|
-
const onErrorHandler = mockApp.onError.mock.calls[0][0]
|
|
230
|
-
|
|
231
|
-
const mockError = { message: 'Simple error' }
|
|
232
|
-
const mockRequest = new Request('http://localhost:3000/api/test')
|
|
233
|
-
|
|
234
|
-
const mockContext = {
|
|
235
|
-
error: mockError,
|
|
236
|
-
request: mockRequest,
|
|
237
|
-
set: {}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
onErrorHandler(mockContext)
|
|
241
|
-
|
|
242
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
243
|
-
expect.stringContaining('❌ Error:'),
|
|
244
|
-
expect.stringContaining('Simple error')
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
consoleSpy.mockRestore()
|
|
248
|
-
})
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
describe('Development vs Production', () => {
|
|
252
|
-
it('should work in production mode', () => {
|
|
253
|
-
const productionContext = {
|
|
254
|
-
...mockContext,
|
|
255
|
-
isDevelopment: false,
|
|
256
|
-
isProduction: true
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
expect(() => {
|
|
260
|
-
loggerPlugin.setup(productionContext, mockApp)
|
|
261
|
-
}).not.toThrow()
|
|
262
|
-
|
|
263
|
-
expect(mockApp.onRequest).toHaveBeenCalled()
|
|
264
|
-
expect(mockApp.onResponse).toHaveBeenCalled()
|
|
265
|
-
expect(mockApp.onError).toHaveBeenCalled()
|
|
266
|
-
})
|
|
267
|
-
})
|
|
268
|
-
})
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
2
|
-
|
|
3
|
-
// Mock global fetch before any other imports
|
|
4
|
-
Object.defineProperty(global, 'fetch', {
|
|
5
|
-
value: vi.fn(),
|
|
6
|
-
writable: true,
|
|
7
|
-
configurable: true
|
|
8
|
-
})
|
|
9
|
-
import { vitePlugin } from '@/core/plugins/built-in/vite'
|
|
10
|
-
import type { PluginContext } from '@/core/types'
|
|
11
|
-
|
|
12
|
-
// Remove duplicate global fetch assignment as it's now set above
|
|
13
|
-
|
|
14
|
-
describe.skip('Vite Plugin', () => {
|
|
15
|
-
let mockContext: PluginContext
|
|
16
|
-
let mockApp: any
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
vi.clearAllMocks()
|
|
20
|
-
vi.clearAllTimers()
|
|
21
|
-
vi.useFakeTimers()
|
|
22
|
-
|
|
23
|
-
mockContext = {
|
|
24
|
-
config: {
|
|
25
|
-
server: { port: 3000, host: 'localhost', apiPrefix: '/api', cors: { origins: [], methods: [], headers: [] }, middleware: [] },
|
|
26
|
-
client: { port: 5173, proxy: { target: 'http://localhost:3000' }, build: { outDir: 'dist', target: 'es2020', sourceMaps: true, minify: false } },
|
|
27
|
-
app: { name: 'test', version: '1.0.0' }
|
|
28
|
-
},
|
|
29
|
-
logger: { debug: vi.fn(), info: vi.fn(), warn: vi.fn(), error: vi.fn(), child: vi.fn(), time: vi.fn(), timeEnd: vi.fn(), request: vi.fn() },
|
|
30
|
-
app: mockApp,
|
|
31
|
-
utils: {
|
|
32
|
-
isDevelopment: vi.fn(() => true),
|
|
33
|
-
isProduction: vi.fn(() => false),
|
|
34
|
-
createTimer: vi.fn(),
|
|
35
|
-
formatBytes: vi.fn(),
|
|
36
|
-
getEnvironment: vi.fn(() => 'test'),
|
|
37
|
-
createHash: vi.fn(),
|
|
38
|
-
deepMerge: vi.fn(),
|
|
39
|
-
validateSchema: vi.fn()
|
|
40
|
-
}
|
|
41
|
-
} as any
|
|
42
|
-
|
|
43
|
-
mockApp = {
|
|
44
|
-
get: vi.fn(),
|
|
45
|
-
post: vi.fn(),
|
|
46
|
-
use: vi.fn()
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
afterEach(() => {
|
|
51
|
-
vi.useRealTimers()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
describe('Development Mode', () => {
|
|
55
|
-
it('should set up plugin in development mode', async () => {
|
|
56
|
-
await vitePlugin.setup!(mockContext)
|
|
57
|
-
|
|
58
|
-
expect(mockContext.logger.info).toHaveBeenCalledWith('Setting up Vite integration on localhost:5173')
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('should check for Vite after timeout', async () => {
|
|
62
|
-
// Mock successful Vite check
|
|
63
|
-
vi.mocked(fetch).mockResolvedValueOnce({
|
|
64
|
-
status: 200,
|
|
65
|
-
ok: true
|
|
66
|
-
} as Response)
|
|
67
|
-
|
|
68
|
-
await vitePlugin.setup!(mockContext)
|
|
69
|
-
|
|
70
|
-
// Fast-forward timers to trigger the setTimeout
|
|
71
|
-
vi.advanceTimersByTime(2000)
|
|
72
|
-
|
|
73
|
-
// Wait for the async operation to complete
|
|
74
|
-
await vi.runAllTimersAsync()
|
|
75
|
-
|
|
76
|
-
expect(fetch).toHaveBeenCalledWith('http://localhost:5173', {
|
|
77
|
-
signal: expect.any(AbortSignal)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
expect(mockContext.logger.info).toHaveBeenCalledWith('✓ Vite server detected on localhost:5173')
|
|
81
|
-
expect(mockContext.logger.info).toHaveBeenCalledWith('Hot reload coordination active')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('should handle Vite check failure silently', async () => {
|
|
85
|
-
// Mock failed Vite check
|
|
86
|
-
vi.mocked(fetch).mockRejectedValueOnce(new Error('Connection refused'))
|
|
87
|
-
|
|
88
|
-
await vitePlugin.setup!(mockContext)
|
|
89
|
-
|
|
90
|
-
// Fast-forward timers
|
|
91
|
-
vi.advanceTimersByTime(2000)
|
|
92
|
-
await vi.runAllTimersAsync()
|
|
93
|
-
|
|
94
|
-
expect(fetch).toHaveBeenCalledWith('http://localhost:5173', {
|
|
95
|
-
signal: expect.any(AbortSignal)
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
// Should not log success messages when Vite is not running
|
|
99
|
-
expect(mockContext.logger.info).not.toHaveBeenCalledWith('✓ Vite server detected on localhost:5173')
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('should use custom vite port from context', async () => {
|
|
103
|
-
const customContext = {
|
|
104
|
-
...mockContext,
|
|
105
|
-
config: {
|
|
106
|
-
...mockContext.config,
|
|
107
|
-
client: { ...mockContext.config.client, port: 3001 }
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
vi.mocked(fetch).mockResolvedValueOnce({
|
|
112
|
-
status: 200,
|
|
113
|
-
ok: true
|
|
114
|
-
} as Response)
|
|
115
|
-
|
|
116
|
-
await vitePlugin.setup!(customContext)
|
|
117
|
-
|
|
118
|
-
expect(customContext.logger.info).toHaveBeenCalledWith('Setting up Vite integration on localhost:3001')
|
|
119
|
-
|
|
120
|
-
vi.advanceTimersByTime(2000)
|
|
121
|
-
await vi.runAllTimersAsync()
|
|
122
|
-
|
|
123
|
-
expect(fetch).toHaveBeenCalledWith('http://localhost:3001', {
|
|
124
|
-
signal: expect.any(AbortSignal)
|
|
125
|
-
})
|
|
126
|
-
})
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
describe('Production Mode', () => {
|
|
130
|
-
it('should skip plugin setup in production mode', async () => {
|
|
131
|
-
const productionContext = {
|
|
132
|
-
...mockContext,
|
|
133
|
-
utils: {
|
|
134
|
-
...mockContext.utils,
|
|
135
|
-
isDevelopment: vi.fn(() => false),
|
|
136
|
-
isProduction: vi.fn(() => true)
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
await vitePlugin.setup!(productionContext)
|
|
141
|
-
|
|
142
|
-
expect(productionContext.logger.info).not.toHaveBeenCalled()
|
|
143
|
-
expect(fetch).not.toHaveBeenCalled()
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
describe('Plugin Properties', () => {
|
|
148
|
-
it('should have correct plugin name', () => {
|
|
149
|
-
expect(vitePlugin.name).toBe('vite')
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it('should have setup function', () => {
|
|
153
|
-
expect(typeof vitePlugin.setup).toBe('function')
|
|
154
|
-
})
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
describe('checkViteRunning function', () => {
|
|
158
|
-
it('should return true for successful connection', async () => {
|
|
159
|
-
vi.mocked(fetch).mockResolvedValueOnce({
|
|
160
|
-
status: 200,
|
|
161
|
-
ok: true
|
|
162
|
-
} as Response)
|
|
163
|
-
|
|
164
|
-
// We need to access the checkViteRunning function
|
|
165
|
-
// Since it's not exported, we'll test it indirectly through the plugin
|
|
166
|
-
await vitePlugin.setup!(mockContext)
|
|
167
|
-
vi.advanceTimersByTime(2000)
|
|
168
|
-
await vi.runAllTimersAsync()
|
|
169
|
-
|
|
170
|
-
expect(mockContext.logger.info).toHaveBeenCalledWith('✓ Vite server detected on localhost:5173')
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
it('should return false for connection timeout', async () => {
|
|
174
|
-
vi.mocked(fetch).mockImplementationOnce(() =>
|
|
175
|
-
new Promise((_, reject) => {
|
|
176
|
-
setTimeout(() => reject(new Error('timeout')), 1500)
|
|
177
|
-
})
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
await vitePlugin.setup!(mockContext)
|
|
181
|
-
vi.advanceTimersByTime(2000)
|
|
182
|
-
await vi.runAllTimersAsync()
|
|
183
|
-
|
|
184
|
-
// Should not show success message when timeout occurs
|
|
185
|
-
expect(mockContext.logger.info).not.toHaveBeenCalledWith('✓ Vite server detected on localhost:5173')
|
|
186
|
-
})
|
|
187
|
-
})
|
|
188
|
-
})
|