create-fluxstack 1.16.0 → 1.17.0
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/CHANGELOG.md +80 -0
- package/app/client/src/App.tsx +8 -0
- package/app/client/src/live/AuthDemo.tsx +4 -4
- package/core/build/bundler.ts +40 -26
- package/core/build/flux-plugins-generator.ts +325 -325
- package/core/build/index.ts +92 -21
- package/core/cli/command-registry.ts +44 -46
- package/core/cli/commands/build.ts +11 -6
- package/core/cli/commands/create.ts +7 -5
- package/core/cli/commands/dev.ts +6 -5
- package/core/cli/commands/help.ts +3 -2
- package/core/cli/commands/make-plugin.ts +8 -7
- package/core/cli/commands/plugin-add.ts +60 -43
- package/core/cli/commands/plugin-deps.ts +73 -57
- package/core/cli/commands/plugin-list.ts +44 -41
- package/core/cli/commands/plugin-remove.ts +33 -22
- package/core/cli/generators/component.ts +770 -769
- package/core/cli/generators/controller.ts +9 -8
- package/core/cli/generators/index.ts +148 -146
- package/core/cli/generators/interactive.ts +228 -227
- package/core/cli/generators/plugin.ts +11 -10
- package/core/cli/generators/prompts.ts +83 -82
- package/core/cli/generators/route.ts +7 -6
- package/core/cli/generators/service.ts +10 -9
- package/core/cli/generators/template-engine.ts +2 -1
- package/core/cli/generators/types.ts +7 -7
- package/core/cli/generators/utils.ts +191 -191
- package/core/cli/index.ts +9 -8
- package/core/cli/plugin-discovery.ts +2 -2
- package/core/client/hooks/useAuth.ts +48 -48
- package/core/client/standalone.ts +18 -17
- package/core/client/state/createStore.ts +192 -192
- package/core/client/state/index.ts +14 -14
- package/core/config/index.ts +1 -0
- package/core/framework/client.ts +131 -131
- package/core/framework/index.ts +7 -7
- package/core/framework/server.ts +72 -112
- package/core/framework/types.ts +2 -2
- package/core/plugins/built-in/live-components/commands/create-live-component.ts +6 -3
- package/core/plugins/built-in/monitoring/index.ts +110 -68
- package/core/plugins/built-in/static/index.ts +2 -2
- package/core/plugins/built-in/swagger/index.ts +9 -9
- package/core/plugins/built-in/vite/index.ts +3 -3
- package/core/plugins/built-in/vite/vite-dev.ts +3 -3
- package/core/plugins/config.ts +50 -47
- package/core/plugins/discovery.ts +10 -4
- package/core/plugins/executor.ts +2 -2
- package/core/plugins/index.ts +206 -203
- package/core/plugins/manager.ts +21 -20
- package/core/plugins/registry.ts +76 -12
- package/core/plugins/types.ts +14 -14
- package/core/server/framework.ts +3 -189
- package/core/server/live/auto-generated-components.ts +11 -29
- package/core/server/live/index.ts +41 -31
- package/core/server/live/websocket-plugin.ts +11 -1
- package/core/server/middleware/elysia-helpers.ts +16 -15
- package/core/server/middleware/errorHandling.ts +14 -14
- package/core/server/middleware/index.ts +31 -31
- package/core/server/plugins/database.ts +181 -180
- package/core/server/plugins/static-files-plugin.ts +4 -3
- package/core/server/plugins/swagger.ts +11 -8
- package/core/server/rooms/RoomBroadcaster.ts +11 -10
- package/core/server/rooms/RoomSystem.ts +14 -11
- package/core/server/services/BaseService.ts +7 -7
- package/core/server/services/ServiceContainer.ts +5 -5
- package/core/server/services/index.ts +8 -8
- package/core/templates/create-project.ts +28 -27
- package/core/testing/index.ts +9 -9
- package/core/testing/setup.ts +73 -73
- package/core/types/api.ts +168 -168
- package/core/types/config.ts +5 -5
- package/core/types/index.ts +1 -1
- package/core/types/plugin.ts +2 -2
- package/core/types/types.ts +3 -3
- package/core/utils/build-logger.ts +324 -324
- package/core/utils/config-schema.ts +480 -480
- package/core/utils/env.ts +10 -8
- package/core/utils/errors/codes.ts +114 -114
- package/core/utils/errors/handlers.ts +30 -20
- package/core/utils/errors/index.ts +54 -46
- package/core/utils/errors/middleware.ts +113 -113
- package/core/utils/helpers.ts +19 -16
- package/core/utils/logger/colors.ts +114 -114
- package/core/utils/logger/config.ts +2 -2
- package/core/utils/logger/formatter.ts +82 -82
- package/core/utils/logger/group-logger.ts +101 -101
- package/core/utils/logger/index.ts +13 -3
- package/core/utils/logger/startup-banner.ts +2 -2
- package/core/utils/logger/winston-logger.ts +152 -152
- package/core/utils/monitoring/index.ts +211 -211
- package/core/utils/sync-version.ts +67 -66
- package/core/utils/version.ts +1 -1
- package/package.json +104 -100
- package/playwright-report/index.html +85 -0
- package/playwright.config.ts +31 -0
- package/plugins/crypto-auth/client/CryptoAuthClient.ts +302 -302
- package/plugins/crypto-auth/client/components/index.ts +11 -11
- package/plugins/crypto-auth/client/index.ts +11 -11
- package/plugins/crypto-auth/package.json +65 -65
- package/plugins/crypto-auth/server/CryptoAuthService.ts +185 -185
- package/plugins/crypto-auth/server/middlewares/cryptoAuthAdmin.ts +6 -5
- package/plugins/crypto-auth/server/middlewares/cryptoAuthPermissions.ts +6 -5
- package/plugins/crypto-auth/server/middlewares/cryptoAuthRequired.ts +3 -3
- package/plugins/crypto-auth/server/middlewares/index.ts +22 -22
- package/plugins/crypto-auth/server/middlewares.ts +19 -19
- package/vite.config.ts +13 -0
- package/app/client/.live-stubs/LiveAdminPanel.js +0 -5
- package/app/client/.live-stubs/LiveCounter.js +0 -9
- package/app/client/.live-stubs/LiveForm.js +0 -11
- package/app/client/.live-stubs/LiveLocalCounter.js +0 -8
- package/app/client/.live-stubs/LivePingPong.js +0 -10
- package/app/client/.live-stubs/LiveRoomChat.js +0 -11
- package/app/client/.live-stubs/LiveSharedCounter.js +0 -10
- package/app/client/.live-stubs/LiveUpload.js +0 -15
- package/app/server/live/register-components.ts +0 -19
- package/core/build/live-components-generator.ts +0 -321
- package/core/live/ComponentRegistry.ts +0 -403
- package/core/live/types.ts +0 -241
- package/workspace.json +0 -6
package/core/utils/env.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* Uses Bun.env (runtime) → process.env (fallback) → eval (last resort)
|
|
28
28
|
*/
|
|
29
29
|
class EnvLoader {
|
|
30
|
-
private cache = new Map<string,
|
|
30
|
+
private cache = new Map<string, unknown>()
|
|
31
31
|
private accessor: () => Record<string, string | undefined>
|
|
32
32
|
|
|
33
33
|
constructor() {
|
|
@@ -38,17 +38,19 @@ class EnvLoader {
|
|
|
38
38
|
* Create dynamic accessor to prevent build-time inlining
|
|
39
39
|
*/
|
|
40
40
|
private createAccessor(): () => Record<string, string | undefined> {
|
|
41
|
-
const global = globalThis as
|
|
41
|
+
const global = globalThis as unknown as Record<string, Record<string, unknown> | undefined>
|
|
42
42
|
|
|
43
43
|
return () => {
|
|
44
44
|
// Try Bun.env first (most reliable in Bun)
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
const bun = global['Bun'] as Record<string, unknown> | undefined
|
|
46
|
+
if (bun?.['env']) {
|
|
47
|
+
return bun['env'] as Record<string, string | undefined>
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
// Fallback to process.env
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
const proc = global['process'] as Record<string, unknown> | undefined
|
|
52
|
+
if (proc?.['env']) {
|
|
53
|
+
return proc['env'] as Record<string, string | undefined>
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
return {}
|
|
@@ -63,7 +65,7 @@ class EnvLoader {
|
|
|
63
65
|
// Check cache first
|
|
64
66
|
const cacheKey = `${key}:${typeof defaultValue}`
|
|
65
67
|
if (this.cache.has(cacheKey)) {
|
|
66
|
-
return this.cache.get(cacheKey)
|
|
68
|
+
return this.cache.get(cacheKey) as T
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
const env = this.accessor()
|
|
@@ -75,7 +77,7 @@ class EnvLoader {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
// Auto-detect type from defaultValue
|
|
78
|
-
let result:
|
|
80
|
+
let result: unknown = value
|
|
79
81
|
|
|
80
82
|
if (typeof defaultValue === 'number') {
|
|
81
83
|
const parsed = Number(value)
|
|
@@ -1,115 +1,115 @@
|
|
|
1
|
-
export const ERROR_CODES = {
|
|
2
|
-
// Validation errors (400)
|
|
3
|
-
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
4
|
-
INVALID_INPUT: 'INVALID_INPUT',
|
|
5
|
-
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
|
|
6
|
-
INVALID_FORMAT: 'INVALID_FORMAT',
|
|
7
|
-
|
|
8
|
-
// Authentication errors (401)
|
|
9
|
-
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
10
|
-
INVALID_TOKEN: 'INVALID_TOKEN',
|
|
11
|
-
TOKEN_EXPIRED: 'TOKEN_EXPIRED',
|
|
12
|
-
INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
|
|
13
|
-
|
|
14
|
-
// Authorization errors (403)
|
|
15
|
-
FORBIDDEN: 'FORBIDDEN',
|
|
16
|
-
INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
|
|
17
|
-
ACCESS_DENIED: 'ACCESS_DENIED',
|
|
18
|
-
|
|
19
|
-
// Not found errors (404)
|
|
20
|
-
NOT_FOUND: 'NOT_FOUND',
|
|
21
|
-
RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
|
|
22
|
-
ENDPOINT_NOT_FOUND: 'ENDPOINT_NOT_FOUND',
|
|
23
|
-
|
|
24
|
-
// Conflict errors (409)
|
|
25
|
-
CONFLICT: 'CONFLICT',
|
|
26
|
-
RESOURCE_ALREADY_EXISTS: 'RESOURCE_ALREADY_EXISTS',
|
|
27
|
-
DUPLICATE_ENTRY: 'DUPLICATE_ENTRY',
|
|
28
|
-
|
|
29
|
-
// Server errors (500)
|
|
30
|
-
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
31
|
-
INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
|
|
32
|
-
DATABASE_ERROR: 'DATABASE_ERROR',
|
|
33
|
-
EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
|
|
34
|
-
|
|
35
|
-
// Service unavailable (503)
|
|
36
|
-
SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
|
|
37
|
-
MAINTENANCE_MODE: 'MAINTENANCE_MODE',
|
|
38
|
-
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
|
|
39
|
-
|
|
40
|
-
// Plugin errors
|
|
41
|
-
PLUGIN_ERROR: 'PLUGIN_ERROR',
|
|
42
|
-
PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND',
|
|
43
|
-
PLUGIN_INITIALIZATION_ERROR: 'PLUGIN_INITIALIZATION_ERROR',
|
|
44
|
-
|
|
45
|
-
// Configuration errors
|
|
46
|
-
CONFIG_ERROR: 'CONFIG_ERROR',
|
|
47
|
-
INVALID_CONFIG: 'INVALID_CONFIG',
|
|
48
|
-
MISSING_CONFIG: 'MISSING_CONFIG',
|
|
49
|
-
|
|
50
|
-
// Build errors
|
|
51
|
-
BUILD_ERROR: 'BUILD_ERROR',
|
|
52
|
-
COMPILATION_ERROR: 'COMPILATION_ERROR',
|
|
53
|
-
BUNDLING_ERROR: 'BUNDLING_ERROR'
|
|
54
|
-
} as const
|
|
55
|
-
|
|
56
|
-
export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES]
|
|
57
|
-
|
|
58
|
-
export const getErrorMessage = (code: ErrorCode): string => {
|
|
59
|
-
const messages: Record<ErrorCode, string> = {
|
|
60
|
-
// Validation errors
|
|
61
|
-
VALIDATION_ERROR: 'Validation failed',
|
|
62
|
-
INVALID_INPUT: 'Invalid input provided',
|
|
63
|
-
MISSING_REQUIRED_FIELD: 'Required field is missing',
|
|
64
|
-
INVALID_FORMAT: 'Invalid format',
|
|
65
|
-
|
|
66
|
-
// Authentication errors
|
|
67
|
-
UNAUTHORIZED: 'Authentication required',
|
|
68
|
-
INVALID_TOKEN: 'Invalid authentication token',
|
|
69
|
-
TOKEN_EXPIRED: 'Authentication token has expired',
|
|
70
|
-
INVALID_CREDENTIALS: 'Invalid credentials provided',
|
|
71
|
-
|
|
72
|
-
// Authorization errors
|
|
73
|
-
FORBIDDEN: 'Access forbidden',
|
|
74
|
-
INSUFFICIENT_PERMISSIONS: 'Insufficient permissions',
|
|
75
|
-
ACCESS_DENIED: 'Access denied',
|
|
76
|
-
|
|
77
|
-
// Not found errors
|
|
78
|
-
NOT_FOUND: 'Resource not found',
|
|
79
|
-
RESOURCE_NOT_FOUND: 'Requested resource not found',
|
|
80
|
-
ENDPOINT_NOT_FOUND: 'API endpoint not found',
|
|
81
|
-
|
|
82
|
-
// Conflict errors
|
|
83
|
-
CONFLICT: 'Resource conflict',
|
|
84
|
-
RESOURCE_ALREADY_EXISTS: 'Resource already exists',
|
|
85
|
-
DUPLICATE_ENTRY: 'Duplicate entry',
|
|
86
|
-
|
|
87
|
-
// Server errors
|
|
88
|
-
INTERNAL_ERROR: 'Internal server error',
|
|
89
|
-
INTERNAL_SERVER_ERROR: 'Internal server error',
|
|
90
|
-
DATABASE_ERROR: 'Database operation failed',
|
|
91
|
-
EXTERNAL_SERVICE_ERROR: 'External service error',
|
|
92
|
-
|
|
93
|
-
// Service unavailable
|
|
94
|
-
SERVICE_UNAVAILABLE: 'Service temporarily unavailable',
|
|
95
|
-
MAINTENANCE_MODE: 'Service is under maintenance',
|
|
96
|
-
RATE_LIMIT_EXCEEDED: 'Rate limit exceeded',
|
|
97
|
-
|
|
98
|
-
// Plugin errors
|
|
99
|
-
PLUGIN_ERROR: 'Plugin error',
|
|
100
|
-
PLUGIN_NOT_FOUND: 'Plugin not found',
|
|
101
|
-
PLUGIN_INITIALIZATION_ERROR: 'Plugin initialization failed',
|
|
102
|
-
|
|
103
|
-
// Configuration errors
|
|
104
|
-
CONFIG_ERROR: 'Configuration error',
|
|
105
|
-
INVALID_CONFIG: 'Invalid configuration',
|
|
106
|
-
MISSING_CONFIG: 'Missing configuration',
|
|
107
|
-
|
|
108
|
-
// Build errors
|
|
109
|
-
BUILD_ERROR: 'Build error',
|
|
110
|
-
COMPILATION_ERROR: 'Compilation failed',
|
|
111
|
-
BUNDLING_ERROR: 'Bundling failed'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return messages[code] || 'Unknown error'
|
|
1
|
+
export const ERROR_CODES = {
|
|
2
|
+
// Validation errors (400)
|
|
3
|
+
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
4
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
5
|
+
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
|
|
6
|
+
INVALID_FORMAT: 'INVALID_FORMAT',
|
|
7
|
+
|
|
8
|
+
// Authentication errors (401)
|
|
9
|
+
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
10
|
+
INVALID_TOKEN: 'INVALID_TOKEN',
|
|
11
|
+
TOKEN_EXPIRED: 'TOKEN_EXPIRED',
|
|
12
|
+
INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
|
|
13
|
+
|
|
14
|
+
// Authorization errors (403)
|
|
15
|
+
FORBIDDEN: 'FORBIDDEN',
|
|
16
|
+
INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
|
|
17
|
+
ACCESS_DENIED: 'ACCESS_DENIED',
|
|
18
|
+
|
|
19
|
+
// Not found errors (404)
|
|
20
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
21
|
+
RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
|
|
22
|
+
ENDPOINT_NOT_FOUND: 'ENDPOINT_NOT_FOUND',
|
|
23
|
+
|
|
24
|
+
// Conflict errors (409)
|
|
25
|
+
CONFLICT: 'CONFLICT',
|
|
26
|
+
RESOURCE_ALREADY_EXISTS: 'RESOURCE_ALREADY_EXISTS',
|
|
27
|
+
DUPLICATE_ENTRY: 'DUPLICATE_ENTRY',
|
|
28
|
+
|
|
29
|
+
// Server errors (500)
|
|
30
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
31
|
+
INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
|
|
32
|
+
DATABASE_ERROR: 'DATABASE_ERROR',
|
|
33
|
+
EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',
|
|
34
|
+
|
|
35
|
+
// Service unavailable (503)
|
|
36
|
+
SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
|
|
37
|
+
MAINTENANCE_MODE: 'MAINTENANCE_MODE',
|
|
38
|
+
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
|
|
39
|
+
|
|
40
|
+
// Plugin errors
|
|
41
|
+
PLUGIN_ERROR: 'PLUGIN_ERROR',
|
|
42
|
+
PLUGIN_NOT_FOUND: 'PLUGIN_NOT_FOUND',
|
|
43
|
+
PLUGIN_INITIALIZATION_ERROR: 'PLUGIN_INITIALIZATION_ERROR',
|
|
44
|
+
|
|
45
|
+
// Configuration errors
|
|
46
|
+
CONFIG_ERROR: 'CONFIG_ERROR',
|
|
47
|
+
INVALID_CONFIG: 'INVALID_CONFIG',
|
|
48
|
+
MISSING_CONFIG: 'MISSING_CONFIG',
|
|
49
|
+
|
|
50
|
+
// Build errors
|
|
51
|
+
BUILD_ERROR: 'BUILD_ERROR',
|
|
52
|
+
COMPILATION_ERROR: 'COMPILATION_ERROR',
|
|
53
|
+
BUNDLING_ERROR: 'BUNDLING_ERROR'
|
|
54
|
+
} as const
|
|
55
|
+
|
|
56
|
+
export type ErrorCode = typeof ERROR_CODES[keyof typeof ERROR_CODES]
|
|
57
|
+
|
|
58
|
+
export const getErrorMessage = (code: ErrorCode): string => {
|
|
59
|
+
const messages: Record<ErrorCode, string> = {
|
|
60
|
+
// Validation errors
|
|
61
|
+
VALIDATION_ERROR: 'Validation failed',
|
|
62
|
+
INVALID_INPUT: 'Invalid input provided',
|
|
63
|
+
MISSING_REQUIRED_FIELD: 'Required field is missing',
|
|
64
|
+
INVALID_FORMAT: 'Invalid format',
|
|
65
|
+
|
|
66
|
+
// Authentication errors
|
|
67
|
+
UNAUTHORIZED: 'Authentication required',
|
|
68
|
+
INVALID_TOKEN: 'Invalid authentication token',
|
|
69
|
+
TOKEN_EXPIRED: 'Authentication token has expired',
|
|
70
|
+
INVALID_CREDENTIALS: 'Invalid credentials provided',
|
|
71
|
+
|
|
72
|
+
// Authorization errors
|
|
73
|
+
FORBIDDEN: 'Access forbidden',
|
|
74
|
+
INSUFFICIENT_PERMISSIONS: 'Insufficient permissions',
|
|
75
|
+
ACCESS_DENIED: 'Access denied',
|
|
76
|
+
|
|
77
|
+
// Not found errors
|
|
78
|
+
NOT_FOUND: 'Resource not found',
|
|
79
|
+
RESOURCE_NOT_FOUND: 'Requested resource not found',
|
|
80
|
+
ENDPOINT_NOT_FOUND: 'API endpoint not found',
|
|
81
|
+
|
|
82
|
+
// Conflict errors
|
|
83
|
+
CONFLICT: 'Resource conflict',
|
|
84
|
+
RESOURCE_ALREADY_EXISTS: 'Resource already exists',
|
|
85
|
+
DUPLICATE_ENTRY: 'Duplicate entry',
|
|
86
|
+
|
|
87
|
+
// Server errors
|
|
88
|
+
INTERNAL_ERROR: 'Internal server error',
|
|
89
|
+
INTERNAL_SERVER_ERROR: 'Internal server error',
|
|
90
|
+
DATABASE_ERROR: 'Database operation failed',
|
|
91
|
+
EXTERNAL_SERVICE_ERROR: 'External service error',
|
|
92
|
+
|
|
93
|
+
// Service unavailable
|
|
94
|
+
SERVICE_UNAVAILABLE: 'Service temporarily unavailable',
|
|
95
|
+
MAINTENANCE_MODE: 'Service is under maintenance',
|
|
96
|
+
RATE_LIMIT_EXCEEDED: 'Rate limit exceeded',
|
|
97
|
+
|
|
98
|
+
// Plugin errors
|
|
99
|
+
PLUGIN_ERROR: 'Plugin error',
|
|
100
|
+
PLUGIN_NOT_FOUND: 'Plugin not found',
|
|
101
|
+
PLUGIN_INITIALIZATION_ERROR: 'Plugin initialization failed',
|
|
102
|
+
|
|
103
|
+
// Configuration errors
|
|
104
|
+
CONFIG_ERROR: 'Configuration error',
|
|
105
|
+
INVALID_CONFIG: 'Invalid configuration',
|
|
106
|
+
MISSING_CONFIG: 'Missing configuration',
|
|
107
|
+
|
|
108
|
+
// Build errors
|
|
109
|
+
BUILD_ERROR: 'Build error',
|
|
110
|
+
COMPILATION_ERROR: 'Compilation failed',
|
|
111
|
+
BUNDLING_ERROR: 'Bundling failed'
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return messages[code] || 'Unknown error'
|
|
115
115
|
}
|
|
@@ -21,7 +21,7 @@ export interface ErrorMetricsCollector {
|
|
|
21
21
|
|
|
22
22
|
export interface ErrorRecoveryStrategy {
|
|
23
23
|
canRecover(error: FluxStackError): boolean
|
|
24
|
-
recover(error: FluxStackError, context: ErrorHandlerContext): Promise<
|
|
24
|
+
recover(error: FluxStackError, context: ErrorHandlerContext): Promise<ErrorSerializedResponse> | ErrorSerializedResponse
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export interface ErrorHandlerOptions {
|
|
@@ -144,7 +144,7 @@ export class EnhancedErrorHandler {
|
|
|
144
144
|
/**
|
|
145
145
|
* Format stack trace to readable string (handles Bun CallSite objects)
|
|
146
146
|
*/
|
|
147
|
-
private formatErrorStack(stack:
|
|
147
|
+
private formatErrorStack(stack: unknown): string | undefined {
|
|
148
148
|
if (!stack) return undefined
|
|
149
149
|
|
|
150
150
|
// If stack is already a string, return it
|
|
@@ -153,7 +153,7 @@ export class EnhancedErrorHandler {
|
|
|
153
153
|
// If stack is an array of CallSite objects (Bun), format them
|
|
154
154
|
if (Array.isArray(stack)) {
|
|
155
155
|
return stack
|
|
156
|
-
.map((site:
|
|
156
|
+
.map((site: { getFileName?: () => string; getLineNumber?: () => number; getColumnNumber?: () => number; getFunctionName?: () => string }, index: number) => {
|
|
157
157
|
try {
|
|
158
158
|
const fileName = site.getFileName?.() || 'unknown'
|
|
159
159
|
const lineNumber = site.getLineNumber?.() || 0
|
|
@@ -193,10 +193,10 @@ export class EnhancedErrorHandler {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
// Skip logging for Vite internal routes (even if NOT_FOUND logging is enabled)
|
|
196
|
-
if (error.code === 'NOT_FOUND' && error.metadata?.path) {
|
|
196
|
+
if (error.code === 'NOT_FOUND' && typeof error.metadata?.path === 'string') {
|
|
197
197
|
const path = error.metadata.path
|
|
198
|
-
if (path.startsWith('/@') ||
|
|
199
|
-
path.startsWith('/__vite') ||
|
|
198
|
+
if (path.startsWith('/@') ||
|
|
199
|
+
path.startsWith('/__vite') ||
|
|
200
200
|
path.includes('/.vite/') ||
|
|
201
201
|
path.endsWith('.js.map') ||
|
|
202
202
|
path.endsWith('.css.map')) {
|
|
@@ -228,18 +228,20 @@ export class EnhancedErrorHandler {
|
|
|
228
228
|
return response
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
private sanitizeErrorResponse(errorResponse:
|
|
231
|
+
private sanitizeErrorResponse(errorResponse: ErrorSerializedResponse['error']): ErrorSerializedResponse['error'] {
|
|
232
232
|
const sanitized = { ...errorResponse }
|
|
233
|
-
|
|
233
|
+
|
|
234
234
|
// Remove potentially sensitive fields in production
|
|
235
|
-
if (sanitized.details) {
|
|
235
|
+
if (sanitized.details && typeof sanitized.details === 'object' && sanitized.details !== null) {
|
|
236
236
|
// Remove sensitive fields from details
|
|
237
|
+
const details = sanitized.details as Record<string, unknown>
|
|
237
238
|
const sensitiveFields = ['password', 'token', 'secret', 'key', 'credential']
|
|
238
239
|
for (const field of sensitiveFields) {
|
|
239
|
-
if (
|
|
240
|
-
|
|
240
|
+
if (details[field]) {
|
|
241
|
+
details[field] = '[REDACTED]'
|
|
241
242
|
}
|
|
242
243
|
}
|
|
244
|
+
sanitized.details = details
|
|
243
245
|
}
|
|
244
246
|
|
|
245
247
|
return sanitized
|
|
@@ -249,7 +251,7 @@ export class EnhancedErrorHandler {
|
|
|
249
251
|
this.recoveryStrategies.push(strategy)
|
|
250
252
|
}
|
|
251
253
|
|
|
252
|
-
removeRecoveryStrategy(strategyClass: new (...args:
|
|
254
|
+
removeRecoveryStrategy(strategyClass: new (...args: unknown[]) => ErrorRecoveryStrategy): void {
|
|
253
255
|
this.recoveryStrategies = this.recoveryStrategies.filter(
|
|
254
256
|
strategy => !(strategy instanceof strategyClass)
|
|
255
257
|
)
|
|
@@ -289,12 +291,14 @@ export class RetryRecoveryStrategy implements ErrorRecoveryStrategy {
|
|
|
289
291
|
) {}
|
|
290
292
|
|
|
291
293
|
canRecover(error: FluxStackError): boolean {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
+
const ctx = error.context as Record<string, unknown> | undefined
|
|
295
|
+
return this.retryableCodes.includes(error.code) &&
|
|
296
|
+
(!ctx?.retryCount || (ctx.retryCount as number) < this.maxRetries)
|
|
294
297
|
}
|
|
295
298
|
|
|
296
|
-
async recover(error: FluxStackError, context: ErrorHandlerContext): Promise<
|
|
297
|
-
const
|
|
299
|
+
async recover(error: FluxStackError, context: ErrorHandlerContext): Promise<ErrorSerializedResponse> {
|
|
300
|
+
const ctx = error.context as Record<string, unknown> | undefined
|
|
301
|
+
const retryCount = ((ctx?.retryCount as number) || 0) + 1
|
|
298
302
|
|
|
299
303
|
context.logger.info('Attempting error recovery', {
|
|
300
304
|
errorCode: error.code,
|
|
@@ -313,7 +317,7 @@ export class RetryRecoveryStrategy implements ErrorRecoveryStrategy {
|
|
|
313
317
|
|
|
314
318
|
export class FallbackRecoveryStrategy implements ErrorRecoveryStrategy {
|
|
315
319
|
constructor(
|
|
316
|
-
private fallbackResponse:
|
|
320
|
+
private fallbackResponse: unknown,
|
|
317
321
|
private applicableCodes: string[] = ['EXTERNAL_SERVICE_ERROR']
|
|
318
322
|
) {}
|
|
319
323
|
|
|
@@ -321,15 +325,21 @@ export class FallbackRecoveryStrategy implements ErrorRecoveryStrategy {
|
|
|
321
325
|
return this.applicableCodes.includes(error.code)
|
|
322
326
|
}
|
|
323
327
|
|
|
324
|
-
recover(error: FluxStackError, context: ErrorHandlerContext):
|
|
328
|
+
recover(error: FluxStackError, context: ErrorHandlerContext): ErrorSerializedResponse {
|
|
325
329
|
context.logger.info('Using fallback recovery', {
|
|
326
330
|
errorCode: error.code,
|
|
327
331
|
correlationId: error.metadata.correlationId
|
|
328
332
|
})
|
|
329
333
|
|
|
330
334
|
return {
|
|
331
|
-
|
|
332
|
-
|
|
335
|
+
error: {
|
|
336
|
+
message: 'Fallback data provided due to service unavailability',
|
|
337
|
+
code: error.code,
|
|
338
|
+
statusCode: error.statusCode,
|
|
339
|
+
details: { fallback: this.fallbackResponse },
|
|
340
|
+
timestamp: new Date().toISOString(),
|
|
341
|
+
correlationId: error.metadata.correlationId as string | undefined
|
|
342
|
+
}
|
|
333
343
|
}
|
|
334
344
|
}
|
|
335
345
|
}
|