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,14 +1,41 @@
|
|
|
1
|
+
export interface ErrorMetadata {
|
|
2
|
+
correlationId?: string
|
|
3
|
+
userId?: string
|
|
4
|
+
requestId?: string
|
|
5
|
+
userAgent?: string
|
|
6
|
+
ip?: string
|
|
7
|
+
[key: string]: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ErrorSerializedResponse {
|
|
11
|
+
error: {
|
|
12
|
+
message: string
|
|
13
|
+
code: string
|
|
14
|
+
statusCode: number
|
|
15
|
+
details?: any
|
|
16
|
+
timestamp: string
|
|
17
|
+
correlationId?: string
|
|
18
|
+
stack?: string
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
1
22
|
export class FluxStackError extends Error {
|
|
2
23
|
public readonly code: string
|
|
3
24
|
public readonly statusCode: number
|
|
4
25
|
public readonly context?: any
|
|
5
26
|
public readonly timestamp: Date
|
|
27
|
+
public readonly metadata: ErrorMetadata
|
|
28
|
+
public readonly isOperational: boolean
|
|
29
|
+
public readonly userMessage?: string
|
|
6
30
|
|
|
7
31
|
constructor(
|
|
8
32
|
message: string,
|
|
9
33
|
code: string,
|
|
10
34
|
statusCode: number = 500,
|
|
11
|
-
context?: any
|
|
35
|
+
context?: any,
|
|
36
|
+
metadata: ErrorMetadata = {},
|
|
37
|
+
isOperational: boolean = true,
|
|
38
|
+
userMessage?: string
|
|
12
39
|
) {
|
|
13
40
|
super(message)
|
|
14
41
|
this.name = 'FluxStackError'
|
|
@@ -16,6 +43,14 @@ export class FluxStackError extends Error {
|
|
|
16
43
|
this.statusCode = statusCode
|
|
17
44
|
this.context = context
|
|
18
45
|
this.timestamp = new Date()
|
|
46
|
+
this.metadata = metadata
|
|
47
|
+
this.isOperational = isOperational
|
|
48
|
+
this.userMessage = userMessage
|
|
49
|
+
|
|
50
|
+
// Maintain proper stack trace
|
|
51
|
+
if (Error.captureStackTrace) {
|
|
52
|
+
Error.captureStackTrace(this, FluxStackError)
|
|
53
|
+
}
|
|
19
54
|
}
|
|
20
55
|
|
|
21
56
|
toJSON() {
|
|
@@ -26,56 +61,531 @@ export class FluxStackError extends Error {
|
|
|
26
61
|
statusCode: this.statusCode,
|
|
27
62
|
context: this.context,
|
|
28
63
|
timestamp: this.timestamp,
|
|
64
|
+
metadata: this.metadata,
|
|
65
|
+
isOperational: this.isOperational,
|
|
66
|
+
userMessage: this.userMessage,
|
|
29
67
|
stack: this.stack
|
|
30
68
|
}
|
|
31
69
|
}
|
|
70
|
+
|
|
71
|
+
toResponse(isDevelopment: boolean = false): ErrorSerializedResponse {
|
|
72
|
+
return {
|
|
73
|
+
error: {
|
|
74
|
+
message: this.userMessage || this.message,
|
|
75
|
+
code: this.code,
|
|
76
|
+
statusCode: this.statusCode,
|
|
77
|
+
...(this.context && { details: this.context }),
|
|
78
|
+
timestamp: this.timestamp.toISOString(),
|
|
79
|
+
...(this.metadata.correlationId && { correlationId: this.metadata.correlationId }),
|
|
80
|
+
...(isDevelopment && { stack: this.stack })
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
withMetadata(metadata: ErrorMetadata): FluxStackError {
|
|
86
|
+
return new FluxStackError(
|
|
87
|
+
this.message,
|
|
88
|
+
this.code,
|
|
89
|
+
this.statusCode,
|
|
90
|
+
this.context,
|
|
91
|
+
{ ...this.metadata, ...metadata },
|
|
92
|
+
this.isOperational,
|
|
93
|
+
this.userMessage
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
withCorrelationId(correlationId: string): FluxStackError {
|
|
98
|
+
return this.withMetadata({ correlationId })
|
|
99
|
+
}
|
|
32
100
|
}
|
|
33
101
|
|
|
102
|
+
// Validation Errors (400)
|
|
34
103
|
export class ValidationError extends FluxStackError {
|
|
35
|
-
constructor(message: string, context?: any) {
|
|
36
|
-
super(
|
|
104
|
+
constructor(message: string, context?: any, metadata?: ErrorMetadata) {
|
|
105
|
+
super(
|
|
106
|
+
message,
|
|
107
|
+
'VALIDATION_ERROR',
|
|
108
|
+
400,
|
|
109
|
+
context,
|
|
110
|
+
metadata,
|
|
111
|
+
true,
|
|
112
|
+
'Please check your input and try again'
|
|
113
|
+
)
|
|
37
114
|
this.name = 'ValidationError'
|
|
38
115
|
}
|
|
39
116
|
}
|
|
40
117
|
|
|
41
|
-
export class
|
|
42
|
-
constructor(
|
|
43
|
-
super(
|
|
44
|
-
|
|
118
|
+
export class InvalidInputError extends FluxStackError {
|
|
119
|
+
constructor(field: string, value?: any, metadata?: ErrorMetadata) {
|
|
120
|
+
super(
|
|
121
|
+
`Invalid input for field: ${field}`,
|
|
122
|
+
'INVALID_INPUT',
|
|
123
|
+
400,
|
|
124
|
+
{ field, value },
|
|
125
|
+
metadata,
|
|
126
|
+
true,
|
|
127
|
+
`The value provided for ${field} is not valid`
|
|
128
|
+
)
|
|
129
|
+
this.name = 'InvalidInputError'
|
|
45
130
|
}
|
|
46
131
|
}
|
|
47
132
|
|
|
133
|
+
export class MissingRequiredFieldError extends FluxStackError {
|
|
134
|
+
constructor(field: string, metadata?: ErrorMetadata) {
|
|
135
|
+
super(
|
|
136
|
+
`Missing required field: ${field}`,
|
|
137
|
+
'MISSING_REQUIRED_FIELD',
|
|
138
|
+
400,
|
|
139
|
+
{ field },
|
|
140
|
+
metadata,
|
|
141
|
+
true,
|
|
142
|
+
`The field ${field} is required`
|
|
143
|
+
)
|
|
144
|
+
this.name = 'MissingRequiredFieldError'
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Authentication Errors (401)
|
|
48
149
|
export class UnauthorizedError extends FluxStackError {
|
|
49
|
-
constructor(message: string = '
|
|
50
|
-
super(
|
|
150
|
+
constructor(message: string = 'Authentication required', context?: any, metadata?: ErrorMetadata) {
|
|
151
|
+
super(
|
|
152
|
+
message,
|
|
153
|
+
'UNAUTHORIZED',
|
|
154
|
+
401,
|
|
155
|
+
context,
|
|
156
|
+
metadata,
|
|
157
|
+
true,
|
|
158
|
+
'Please log in to access this resource'
|
|
159
|
+
)
|
|
51
160
|
this.name = 'UnauthorizedError'
|
|
52
161
|
}
|
|
53
162
|
}
|
|
54
163
|
|
|
164
|
+
export class InvalidTokenError extends FluxStackError {
|
|
165
|
+
constructor(metadata?: ErrorMetadata) {
|
|
166
|
+
super(
|
|
167
|
+
'Invalid authentication token',
|
|
168
|
+
'INVALID_TOKEN',
|
|
169
|
+
401,
|
|
170
|
+
undefined,
|
|
171
|
+
metadata,
|
|
172
|
+
true,
|
|
173
|
+
'Your session has expired. Please log in again'
|
|
174
|
+
)
|
|
175
|
+
this.name = 'InvalidTokenError'
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export class TokenExpiredError extends FluxStackError {
|
|
180
|
+
constructor(metadata?: ErrorMetadata) {
|
|
181
|
+
super(
|
|
182
|
+
'Authentication token has expired',
|
|
183
|
+
'TOKEN_EXPIRED',
|
|
184
|
+
401,
|
|
185
|
+
undefined,
|
|
186
|
+
metadata,
|
|
187
|
+
true,
|
|
188
|
+
'Your session has expired. Please log in again'
|
|
189
|
+
)
|
|
190
|
+
this.name = 'TokenExpiredError'
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Authorization Errors (403)
|
|
55
195
|
export class ForbiddenError extends FluxStackError {
|
|
56
|
-
constructor(message: string = '
|
|
57
|
-
super(
|
|
196
|
+
constructor(message: string = 'Access forbidden', context?: any, metadata?: ErrorMetadata) {
|
|
197
|
+
super(
|
|
198
|
+
message,
|
|
199
|
+
'FORBIDDEN',
|
|
200
|
+
403,
|
|
201
|
+
context,
|
|
202
|
+
metadata,
|
|
203
|
+
true,
|
|
204
|
+
'You do not have permission to access this resource'
|
|
205
|
+
)
|
|
58
206
|
this.name = 'ForbiddenError'
|
|
59
207
|
}
|
|
60
208
|
}
|
|
61
209
|
|
|
210
|
+
export class InsufficientPermissionsError extends FluxStackError {
|
|
211
|
+
constructor(requiredPermission: string, metadata?: ErrorMetadata) {
|
|
212
|
+
super(
|
|
213
|
+
`Insufficient permissions: ${requiredPermission} required`,
|
|
214
|
+
'INSUFFICIENT_PERMISSIONS',
|
|
215
|
+
403,
|
|
216
|
+
{ requiredPermission },
|
|
217
|
+
metadata,
|
|
218
|
+
true,
|
|
219
|
+
'You do not have the required permissions for this action'
|
|
220
|
+
)
|
|
221
|
+
this.name = 'InsufficientPermissionsError'
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Not Found Errors (404)
|
|
226
|
+
export class NotFoundError extends FluxStackError {
|
|
227
|
+
constructor(resource: string, context?: any, metadata?: ErrorMetadata) {
|
|
228
|
+
super(
|
|
229
|
+
`${resource} not found`,
|
|
230
|
+
'NOT_FOUND',
|
|
231
|
+
404,
|
|
232
|
+
context,
|
|
233
|
+
metadata,
|
|
234
|
+
true,
|
|
235
|
+
'The requested resource could not be found'
|
|
236
|
+
)
|
|
237
|
+
this.name = 'NotFoundError'
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export class ResourceNotFoundError extends FluxStackError {
|
|
242
|
+
constructor(resourceType: string, identifier: string, metadata?: ErrorMetadata) {
|
|
243
|
+
super(
|
|
244
|
+
`${resourceType} with identifier '${identifier}' not found`,
|
|
245
|
+
'RESOURCE_NOT_FOUND',
|
|
246
|
+
404,
|
|
247
|
+
{ resourceType, identifier },
|
|
248
|
+
metadata,
|
|
249
|
+
true,
|
|
250
|
+
`The requested ${resourceType.toLowerCase()} could not be found`
|
|
251
|
+
)
|
|
252
|
+
this.name = 'ResourceNotFoundError'
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export class EndpointNotFoundError extends FluxStackError {
|
|
257
|
+
constructor(method: string, path: string, metadata?: ErrorMetadata) {
|
|
258
|
+
super(
|
|
259
|
+
`Endpoint not found: ${method} ${path}`,
|
|
260
|
+
'ENDPOINT_NOT_FOUND',
|
|
261
|
+
404,
|
|
262
|
+
{ method, path },
|
|
263
|
+
metadata,
|
|
264
|
+
true,
|
|
265
|
+
'The requested API endpoint does not exist'
|
|
266
|
+
)
|
|
267
|
+
this.name = 'EndpointNotFoundError'
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Conflict Errors (409)
|
|
62
272
|
export class ConflictError extends FluxStackError {
|
|
63
|
-
constructor(message: string, context?: any) {
|
|
64
|
-
super(
|
|
273
|
+
constructor(message: string, context?: any, metadata?: ErrorMetadata) {
|
|
274
|
+
super(
|
|
275
|
+
message,
|
|
276
|
+
'CONFLICT',
|
|
277
|
+
409,
|
|
278
|
+
context,
|
|
279
|
+
metadata,
|
|
280
|
+
true,
|
|
281
|
+
'There was a conflict with the current state of the resource'
|
|
282
|
+
)
|
|
65
283
|
this.name = 'ConflictError'
|
|
66
284
|
}
|
|
67
285
|
}
|
|
68
286
|
|
|
287
|
+
export class ResourceAlreadyExistsError extends FluxStackError {
|
|
288
|
+
constructor(resourceType: string, identifier: string, metadata?: ErrorMetadata) {
|
|
289
|
+
super(
|
|
290
|
+
`${resourceType} with identifier '${identifier}' already exists`,
|
|
291
|
+
'RESOURCE_ALREADY_EXISTS',
|
|
292
|
+
409,
|
|
293
|
+
{ resourceType, identifier },
|
|
294
|
+
metadata,
|
|
295
|
+
true,
|
|
296
|
+
`A ${resourceType.toLowerCase()} with that identifier already exists`
|
|
297
|
+
)
|
|
298
|
+
this.name = 'ResourceAlreadyExistsError'
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Rate Limiting Errors (429)
|
|
303
|
+
export class RateLimitExceededError extends FluxStackError {
|
|
304
|
+
constructor(limit: number, windowMs: number, metadata?: ErrorMetadata) {
|
|
305
|
+
super(
|
|
306
|
+
`Rate limit exceeded: ${limit} requests per ${windowMs}ms`,
|
|
307
|
+
'RATE_LIMIT_EXCEEDED',
|
|
308
|
+
429,
|
|
309
|
+
{ limit, windowMs },
|
|
310
|
+
metadata,
|
|
311
|
+
true,
|
|
312
|
+
'Too many requests. Please try again later'
|
|
313
|
+
)
|
|
314
|
+
this.name = 'RateLimitExceededError'
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Server Errors (500)
|
|
69
319
|
export class InternalServerError extends FluxStackError {
|
|
70
|
-
constructor(message: string = 'Internal server error', context?: any) {
|
|
71
|
-
super(
|
|
320
|
+
constructor(message: string = 'Internal server error', context?: any, metadata?: ErrorMetadata) {
|
|
321
|
+
super(
|
|
322
|
+
message,
|
|
323
|
+
'INTERNAL_SERVER_ERROR',
|
|
324
|
+
500,
|
|
325
|
+
context,
|
|
326
|
+
metadata,
|
|
327
|
+
false,
|
|
328
|
+
'An unexpected error occurred. Please try again later'
|
|
329
|
+
)
|
|
72
330
|
this.name = 'InternalServerError'
|
|
73
331
|
}
|
|
74
332
|
}
|
|
75
333
|
|
|
334
|
+
export class DatabaseError extends FluxStackError {
|
|
335
|
+
constructor(operation: string, details?: any, metadata?: ErrorMetadata) {
|
|
336
|
+
super(
|
|
337
|
+
`Database operation failed: ${operation}`,
|
|
338
|
+
'DATABASE_ERROR',
|
|
339
|
+
500,
|
|
340
|
+
{ operation, details },
|
|
341
|
+
metadata,
|
|
342
|
+
false,
|
|
343
|
+
'A database error occurred. Please try again later'
|
|
344
|
+
)
|
|
345
|
+
this.name = 'DatabaseError'
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export class ExternalServiceError extends FluxStackError {
|
|
350
|
+
constructor(service: string, details?: any, metadata?: ErrorMetadata) {
|
|
351
|
+
super(
|
|
352
|
+
`External service error: ${service}`,
|
|
353
|
+
'EXTERNAL_SERVICE_ERROR',
|
|
354
|
+
500,
|
|
355
|
+
{ service, details },
|
|
356
|
+
metadata,
|
|
357
|
+
false,
|
|
358
|
+
'An external service is currently unavailable. Please try again later'
|
|
359
|
+
)
|
|
360
|
+
this.name = 'ExternalServiceError'
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Service Unavailable Errors (503)
|
|
76
365
|
export class ServiceUnavailableError extends FluxStackError {
|
|
77
|
-
constructor(message: string = 'Service unavailable', context?: any) {
|
|
78
|
-
super(
|
|
366
|
+
constructor(message: string = 'Service unavailable', context?: any, metadata?: ErrorMetadata) {
|
|
367
|
+
super(
|
|
368
|
+
message,
|
|
369
|
+
'SERVICE_UNAVAILABLE',
|
|
370
|
+
503,
|
|
371
|
+
context,
|
|
372
|
+
metadata,
|
|
373
|
+
true,
|
|
374
|
+
'The service is temporarily unavailable. Please try again later'
|
|
375
|
+
)
|
|
79
376
|
this.name = 'ServiceUnavailableError'
|
|
80
377
|
}
|
|
81
|
-
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export class MaintenanceModeError extends FluxStackError {
|
|
381
|
+
constructor(estimatedDuration?: string, metadata?: ErrorMetadata) {
|
|
382
|
+
super(
|
|
383
|
+
'Service is under maintenance',
|
|
384
|
+
'MAINTENANCE_MODE',
|
|
385
|
+
503,
|
|
386
|
+
{ estimatedDuration },
|
|
387
|
+
metadata,
|
|
388
|
+
true,
|
|
389
|
+
estimatedDuration
|
|
390
|
+
? `The service is under maintenance. Expected to be back ${estimatedDuration}`
|
|
391
|
+
: 'The service is under maintenance. Please try again later'
|
|
392
|
+
)
|
|
393
|
+
this.name = 'MaintenanceModeError'
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Plugin Errors
|
|
398
|
+
export class PluginError extends FluxStackError {
|
|
399
|
+
constructor(pluginName: string, message: string, context?: any, metadata?: ErrorMetadata) {
|
|
400
|
+
super(
|
|
401
|
+
`Plugin error in ${pluginName}: ${message}`,
|
|
402
|
+
'PLUGIN_ERROR',
|
|
403
|
+
500,
|
|
404
|
+
{ pluginName, ...context },
|
|
405
|
+
metadata,
|
|
406
|
+
false,
|
|
407
|
+
'A plugin error occurred. Please contact support if this persists'
|
|
408
|
+
)
|
|
409
|
+
this.name = 'PluginError'
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export class PluginNotFoundError extends FluxStackError {
|
|
414
|
+
constructor(pluginName: string, metadata?: ErrorMetadata) {
|
|
415
|
+
super(
|
|
416
|
+
`Plugin not found: ${pluginName}`,
|
|
417
|
+
'PLUGIN_NOT_FOUND',
|
|
418
|
+
404,
|
|
419
|
+
{ pluginName },
|
|
420
|
+
metadata,
|
|
421
|
+
true,
|
|
422
|
+
`The requested plugin '${pluginName}' is not available`
|
|
423
|
+
)
|
|
424
|
+
this.name = 'PluginNotFoundError'
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Configuration Errors
|
|
429
|
+
export class ConfigError extends FluxStackError {
|
|
430
|
+
constructor(message: string, context?: any, metadata?: ErrorMetadata) {
|
|
431
|
+
super(
|
|
432
|
+
`Configuration error: ${message}`,
|
|
433
|
+
'CONFIG_ERROR',
|
|
434
|
+
500,
|
|
435
|
+
context,
|
|
436
|
+
metadata,
|
|
437
|
+
false,
|
|
438
|
+
'A configuration error occurred. Please check your settings'
|
|
439
|
+
)
|
|
440
|
+
this.name = 'ConfigError'
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export class InvalidConfigError extends FluxStackError {
|
|
445
|
+
constructor(field: string, value?: any, metadata?: ErrorMetadata) {
|
|
446
|
+
super(
|
|
447
|
+
`Invalid configuration for field: ${field}`,
|
|
448
|
+
'INVALID_CONFIG',
|
|
449
|
+
500,
|
|
450
|
+
{ field, value },
|
|
451
|
+
metadata,
|
|
452
|
+
false,
|
|
453
|
+
'Invalid configuration detected. Please check your settings'
|
|
454
|
+
)
|
|
455
|
+
this.name = 'InvalidConfigError'
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Build Errors
|
|
460
|
+
export class BuildError extends FluxStackError {
|
|
461
|
+
constructor(message: string, context?: any, metadata?: ErrorMetadata) {
|
|
462
|
+
super(
|
|
463
|
+
`Build error: ${message}`,
|
|
464
|
+
'BUILD_ERROR',
|
|
465
|
+
500,
|
|
466
|
+
context,
|
|
467
|
+
metadata,
|
|
468
|
+
false,
|
|
469
|
+
'A build error occurred'
|
|
470
|
+
)
|
|
471
|
+
this.name = 'BuildError'
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export class CompilationError extends FluxStackError {
|
|
476
|
+
constructor(file: string, details?: any, metadata?: ErrorMetadata) {
|
|
477
|
+
super(
|
|
478
|
+
`Compilation failed for file: ${file}`,
|
|
479
|
+
'COMPILATION_ERROR',
|
|
480
|
+
500,
|
|
481
|
+
{ file, details },
|
|
482
|
+
metadata,
|
|
483
|
+
false,
|
|
484
|
+
'Compilation failed'
|
|
485
|
+
)
|
|
486
|
+
this.name = 'CompilationError'
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// Utility functions for error handling
|
|
491
|
+
export const isFluxStackError = (error: any): error is FluxStackError => {
|
|
492
|
+
return error instanceof FluxStackError
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
export const isOperationalError = (error: any): boolean => {
|
|
496
|
+
return isFluxStackError(error) && error.isOperational
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
export const createErrorFromCode = (
|
|
500
|
+
code: string,
|
|
501
|
+
message?: string,
|
|
502
|
+
context?: any,
|
|
503
|
+
metadata?: ErrorMetadata
|
|
504
|
+
): FluxStackError => {
|
|
505
|
+
switch (code) {
|
|
506
|
+
case 'VALIDATION_ERROR':
|
|
507
|
+
return new ValidationError(message || 'Validation failed', context, metadata)
|
|
508
|
+
case 'INVALID_INPUT':
|
|
509
|
+
return new InvalidInputError(context?.field || 'unknown', context?.value, metadata)
|
|
510
|
+
case 'MISSING_REQUIRED_FIELD':
|
|
511
|
+
return new MissingRequiredFieldError(context?.field || 'unknown', metadata)
|
|
512
|
+
case 'UNAUTHORIZED':
|
|
513
|
+
return new UnauthorizedError(message, context, metadata)
|
|
514
|
+
case 'INVALID_TOKEN':
|
|
515
|
+
return new InvalidTokenError(metadata)
|
|
516
|
+
case 'TOKEN_EXPIRED':
|
|
517
|
+
return new TokenExpiredError(metadata)
|
|
518
|
+
case 'FORBIDDEN':
|
|
519
|
+
return new ForbiddenError(message, context, metadata)
|
|
520
|
+
case 'INSUFFICIENT_PERMISSIONS':
|
|
521
|
+
return new InsufficientPermissionsError(context?.requiredPermission || 'unknown', metadata)
|
|
522
|
+
case 'NOT_FOUND':
|
|
523
|
+
return new NotFoundError(context?.resource || 'Resource', context, metadata)
|
|
524
|
+
case 'RESOURCE_NOT_FOUND':
|
|
525
|
+
return new ResourceNotFoundError(
|
|
526
|
+
context?.resourceType || 'Resource',
|
|
527
|
+
context?.identifier || 'unknown',
|
|
528
|
+
metadata
|
|
529
|
+
)
|
|
530
|
+
case 'ENDPOINT_NOT_FOUND':
|
|
531
|
+
return new EndpointNotFoundError(
|
|
532
|
+
context?.method || 'GET',
|
|
533
|
+
context?.path || '/unknown',
|
|
534
|
+
metadata
|
|
535
|
+
)
|
|
536
|
+
case 'CONFLICT':
|
|
537
|
+
return new ConflictError(message || 'Resource conflict', context, metadata)
|
|
538
|
+
case 'RESOURCE_ALREADY_EXISTS':
|
|
539
|
+
return new ResourceAlreadyExistsError(
|
|
540
|
+
context?.resourceType || 'Resource',
|
|
541
|
+
context?.identifier || 'unknown',
|
|
542
|
+
metadata
|
|
543
|
+
)
|
|
544
|
+
case 'RATE_LIMIT_EXCEEDED':
|
|
545
|
+
return new RateLimitExceededError(
|
|
546
|
+
context?.limit || 100,
|
|
547
|
+
context?.windowMs || 60000,
|
|
548
|
+
metadata
|
|
549
|
+
)
|
|
550
|
+
case 'INTERNAL_SERVER_ERROR':
|
|
551
|
+
return new InternalServerError(message, context, metadata)
|
|
552
|
+
case 'DATABASE_ERROR':
|
|
553
|
+
return new DatabaseError(context?.operation || 'unknown', context?.details, metadata)
|
|
554
|
+
case 'EXTERNAL_SERVICE_ERROR':
|
|
555
|
+
return new ExternalServiceError(context?.service || 'unknown', context?.details, metadata)
|
|
556
|
+
case 'SERVICE_UNAVAILABLE':
|
|
557
|
+
return new ServiceUnavailableError(message, context, metadata)
|
|
558
|
+
case 'MAINTENANCE_MODE':
|
|
559
|
+
return new MaintenanceModeError(context?.estimatedDuration, metadata)
|
|
560
|
+
case 'PLUGIN_ERROR':
|
|
561
|
+
return new PluginError(
|
|
562
|
+
context?.pluginName || 'unknown',
|
|
563
|
+
message || 'Plugin error',
|
|
564
|
+
context,
|
|
565
|
+
metadata
|
|
566
|
+
)
|
|
567
|
+
case 'PLUGIN_NOT_FOUND':
|
|
568
|
+
return new PluginNotFoundError(context?.pluginName || 'unknown', metadata)
|
|
569
|
+
case 'CONFIG_ERROR':
|
|
570
|
+
return new ConfigError(message || 'Configuration error', context, metadata)
|
|
571
|
+
case 'INVALID_CONFIG':
|
|
572
|
+
return new InvalidConfigError(context?.field || 'unknown', context?.value, metadata)
|
|
573
|
+
case 'BUILD_ERROR':
|
|
574
|
+
return new BuildError(message || 'Build error', context, metadata)
|
|
575
|
+
case 'COMPILATION_ERROR':
|
|
576
|
+
return new CompilationError(context?.file || 'unknown', context?.details, metadata)
|
|
577
|
+
default:
|
|
578
|
+
return new FluxStackError(message || 'Unknown error', code, 500, context, metadata)
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export const wrapError = (error: Error, metadata?: ErrorMetadata): FluxStackError => {
|
|
583
|
+
if (isFluxStackError(error)) {
|
|
584
|
+
return metadata ? error.withMetadata(metadata) : error
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return new InternalServerError(error.message, { originalError: error.name }, metadata)
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Re-export error codes for convenience
|
|
591
|
+
export { ERROR_CODES, type ErrorCode, getErrorMessage } from './codes'
|