create-fluxstack 1.0.1 → 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 (100) hide show
  1. package/create-fluxstack.ts +2 -3
  2. package/package.json +1 -1
  3. package/.env +0 -30
  4. package/LICENSE +0 -21
  5. package/app/client/README.md +0 -69
  6. package/app/client/frontend-only.ts +0 -12
  7. package/app/client/index.html +0 -13
  8. package/app/client/public/vite.svg +0 -1
  9. package/app/client/src/App.css +0 -883
  10. package/app/client/src/App.tsx +0 -669
  11. package/app/client/src/assets/react.svg +0 -1
  12. package/app/client/src/components/TestPage.tsx +0 -453
  13. package/app/client/src/index.css +0 -51
  14. package/app/client/src/lib/eden-api.ts +0 -110
  15. package/app/client/src/main.tsx +0 -10
  16. package/app/client/src/vite-env.d.ts +0 -1
  17. package/app/client/tsconfig.app.json +0 -43
  18. package/app/client/tsconfig.json +0 -7
  19. package/app/client/tsconfig.node.json +0 -25
  20. package/app/server/app.ts +0 -10
  21. package/app/server/backend-only.ts +0 -15
  22. package/app/server/controllers/users.controller.ts +0 -69
  23. package/app/server/index.ts +0 -104
  24. package/app/server/routes/index.ts +0 -25
  25. package/app/server/routes/users.routes.ts +0 -121
  26. package/app/server/types/index.ts +0 -1
  27. package/app/shared/types/index.ts +0 -18
  28. package/bun.lock +0 -1053
  29. package/core/__tests__/integration.test.ts +0 -227
  30. package/core/build/index.ts +0 -186
  31. package/core/cli/command-registry.ts +0 -334
  32. package/core/cli/index.ts +0 -394
  33. package/core/cli/plugin-discovery.ts +0 -200
  34. package/core/client/standalone.ts +0 -57
  35. package/core/config/__tests__/config-loader.test.ts +0 -591
  36. package/core/config/__tests__/config-merger.test.ts +0 -657
  37. package/core/config/__tests__/env-converter.test.ts +0 -372
  38. package/core/config/__tests__/env-processor.test.ts +0 -431
  39. package/core/config/__tests__/env.test.ts +0 -452
  40. package/core/config/__tests__/integration.test.ts +0 -418
  41. package/core/config/__tests__/loader.test.ts +0 -331
  42. package/core/config/__tests__/schema.test.ts +0 -129
  43. package/core/config/__tests__/validator.test.ts +0 -318
  44. package/core/config/env-dynamic.ts +0 -326
  45. package/core/config/env.ts +0 -597
  46. package/core/config/index.ts +0 -317
  47. package/core/config/loader.ts +0 -546
  48. package/core/config/runtime-config.ts +0 -322
  49. package/core/config/schema.ts +0 -694
  50. package/core/config/validator.ts +0 -540
  51. package/core/framework/__tests__/server.test.ts +0 -233
  52. package/core/framework/client.ts +0 -132
  53. package/core/framework/index.ts +0 -8
  54. package/core/framework/server.ts +0 -501
  55. package/core/framework/types.ts +0 -63
  56. package/core/plugins/__tests__/built-in.test.ts.disabled +0 -366
  57. package/core/plugins/__tests__/manager.test.ts +0 -398
  58. package/core/plugins/__tests__/monitoring.test.ts +0 -401
  59. package/core/plugins/__tests__/registry.test.ts +0 -335
  60. package/core/plugins/built-in/index.ts +0 -142
  61. package/core/plugins/built-in/logger/index.ts +0 -180
  62. package/core/plugins/built-in/monitoring/README.md +0 -193
  63. package/core/plugins/built-in/monitoring/index.ts +0 -912
  64. package/core/plugins/built-in/static/index.ts +0 -289
  65. package/core/plugins/built-in/swagger/index.ts +0 -229
  66. package/core/plugins/built-in/vite/index.ts +0 -316
  67. package/core/plugins/config.ts +0 -348
  68. package/core/plugins/discovery.ts +0 -350
  69. package/core/plugins/executor.ts +0 -351
  70. package/core/plugins/index.ts +0 -195
  71. package/core/plugins/manager.ts +0 -583
  72. package/core/plugins/registry.ts +0 -424
  73. package/core/plugins/types.ts +0 -254
  74. package/core/server/framework.ts +0 -123
  75. package/core/server/index.ts +0 -8
  76. package/core/server/plugins/database.ts +0 -182
  77. package/core/server/plugins/logger.ts +0 -47
  78. package/core/server/plugins/swagger.ts +0 -34
  79. package/core/server/standalone.ts +0 -91
  80. package/core/templates/create-project.ts +0 -455
  81. package/core/types/api.ts +0 -169
  82. package/core/types/build.ts +0 -174
  83. package/core/types/config.ts +0 -68
  84. package/core/types/index.ts +0 -127
  85. package/core/types/plugin.ts +0 -94
  86. package/core/utils/__tests__/errors.test.ts +0 -139
  87. package/core/utils/__tests__/helpers.test.ts +0 -297
  88. package/core/utils/__tests__/logger.test.ts +0 -141
  89. package/core/utils/env-runtime-v2.ts +0 -232
  90. package/core/utils/env-runtime.ts +0 -252
  91. package/core/utils/errors/codes.ts +0 -115
  92. package/core/utils/errors/handlers.ts +0 -63
  93. package/core/utils/errors/index.ts +0 -81
  94. package/core/utils/helpers.ts +0 -180
  95. package/core/utils/index.ts +0 -18
  96. package/core/utils/logger/index.ts +0 -161
  97. package/core/utils/logger.ts +0 -106
  98. package/core/utils/monitoring/index.ts +0 -212
  99. package/tsconfig.json +0 -51
  100. package/vite.config.ts +0 -42
@@ -1,252 +0,0 @@
1
- /**
2
- * Runtime Environment Loader V2 - Simplified API
3
- * Mais elegante com casting automático e acesso direto
4
- */
5
-
6
- /**
7
- * Enhanced environment variable loader with smart casting
8
- */
9
- class SmartEnvLoader {
10
- private envAccessor: () => Record<string, string | undefined>
11
-
12
- constructor() {
13
- this.envAccessor = this.createDynamicAccessor()
14
- }
15
-
16
- private createDynamicAccessor(): () => Record<string, string | undefined> {
17
- const globalScope = globalThis as any
18
-
19
- return () => {
20
- // Try Bun.env first (most reliable in Bun runtime)
21
- if (globalScope['Bun'] && globalScope['Bun']['env']) {
22
- return globalScope['Bun']['env']
23
- }
24
-
25
- // Fallback to process.env with dynamic access
26
- if (globalScope['process'] && globalScope['process']['env']) {
27
- return globalScope['process']['env']
28
- }
29
-
30
- // Final fallback
31
- const proc = eval('typeof process !== "undefined" ? process : null')
32
- return proc?.env || {}
33
- }
34
- }
35
-
36
- /**
37
- * Smart get with automatic type conversion based on default value
38
- */
39
- get<T>(key: string, defaultValue?: T): T {
40
- const env = this.envAccessor()
41
- const value = env[key]
42
-
43
- if (!value || value === '') {
44
- return defaultValue as T
45
- }
46
-
47
- // Auto-detect type from default value
48
- if (typeof defaultValue === 'number') {
49
- const parsed = parseInt(value, 10)
50
- return (isNaN(parsed) ? defaultValue : parsed) as T
51
- }
52
-
53
- if (typeof defaultValue === 'boolean') {
54
- return ['true', '1', 'yes', 'on'].includes(value.toLowerCase()) as T
55
- }
56
-
57
- if (Array.isArray(defaultValue)) {
58
- return value.split(',').map(v => v.trim()).filter(Boolean) as T
59
- }
60
-
61
- if (typeof defaultValue === 'object' && defaultValue !== null) {
62
- try {
63
- return JSON.parse(value) as T
64
- } catch {
65
- return defaultValue
66
- }
67
- }
68
-
69
- return value as T
70
- }
71
-
72
- /**
73
- * Check if environment variable exists
74
- */
75
- has(key: string): boolean {
76
- const env = this.envAccessor()
77
- return key in env && env[key] !== undefined && env[key] !== ''
78
- }
79
-
80
- /**
81
- * Get all environment variables
82
- */
83
- all(): Record<string, string> {
84
- const env = this.envAccessor()
85
- const result: Record<string, string> = {}
86
-
87
- for (const [key, value] of Object.entries(env)) {
88
- if (value !== undefined && value !== '') {
89
- result[key] = value
90
- }
91
- }
92
-
93
- return result
94
- }
95
- }
96
-
97
- // Create singleton instance
98
- const smartEnv = new SmartEnvLoader()
99
-
100
- /**
101
- * Simplified env API with smart casting
102
- */
103
- export const env = {
104
- /**
105
- * Smart get - automatically casts based on default value type
106
- * Usage:
107
- * env.get('PORT', 3000) -> number
108
- * env.get('DEBUG', false) -> boolean
109
- * env.get('ORIGINS', ['*']) -> string[]
110
- * env.get('HOST', 'localhost') -> string
111
- */
112
- get: <T>(key: string, defaultValue?: T): T => smartEnv.get(key, defaultValue),
113
-
114
- /**
115
- * Check if env var exists
116
- */
117
- has: (key: string) => smartEnv.has(key),
118
-
119
- /**
120
- * Get number value
121
- */
122
- num: (key: string, defaultValue?: number) => Number(smartEnv.get(key, defaultValue?.toString() || '0')),
123
-
124
- /**
125
- * Get boolean value
126
- */
127
- bool: (key: string, defaultValue?: boolean) => smartEnv.get(key, defaultValue?.toString() || 'false') === 'true',
128
-
129
- /**
130
- * Get array value
131
- */
132
- array: (key: string, defaultValue?: string[]) => smartEnv.get(key, defaultValue?.join(',') || '').split(',').filter(Boolean),
133
-
134
- /**
135
- * Get all env vars
136
- */
137
- all: () => smartEnv.all(),
138
-
139
- // Common environment variables as properties with smart defaults
140
- get NODE_ENV() { return this.get('NODE_ENV', 'development') },
141
- get PORT() { return this.get('PORT', 3000) },
142
- get HOST() { return this.get('HOST', 'localhost') },
143
- get DEBUG() { return this.get('DEBUG', false) },
144
- get LOG_LEVEL() { return this.get('LOG_LEVEL', 'info') },
145
- get DATABASE_URL() { return this.get('DATABASE_URL', '') },
146
- get JWT_SECRET() { return this.get('JWT_SECRET', '') },
147
- get CORS_ORIGINS() { return this.get('CORS_ORIGINS', ['*']) },
148
- get VITE_PORT() { return this.get('VITE_PORT', 5173) },
149
- get API_PREFIX() { return this.get('API_PREFIX', '/api') },
150
-
151
- // App specific
152
- get FLUXSTACK_APP_NAME() { return this.get('FLUXSTACK_APP_NAME', 'FluxStack') },
153
- get FLUXSTACK_APP_VERSION() { return this.get('FLUXSTACK_APP_VERSION', '1.0.0') },
154
-
155
- // Monitoring
156
- get ENABLE_MONITORING() { return this.get('ENABLE_MONITORING', false) },
157
- get ENABLE_SWAGGER() { return this.get('ENABLE_SWAGGER', true) },
158
- get ENABLE_METRICS() { return this.get('ENABLE_METRICS', false) },
159
-
160
- // Database
161
- get DB_HOST() { return this.get('DB_HOST', 'localhost') },
162
- get DB_PORT() { return this.get('DB_PORT', 5432) },
163
- get DB_NAME() { return this.get('DB_NAME', '') },
164
- get DB_USER() { return this.get('DB_USER', '') },
165
- get DB_PASSWORD() { return this.get('DB_PASSWORD', '') },
166
- get DB_SSL() { return this.get('DB_SSL', false) },
167
-
168
- // SMTP
169
- get SMTP_HOST() { return this.get('SMTP_HOST', '') },
170
- get SMTP_PORT() { return this.get('SMTP_PORT', 587) },
171
- get SMTP_USER() { return this.get('SMTP_USER', '') },
172
- get SMTP_PASSWORD() { return this.get('SMTP_PASSWORD', '') },
173
- get SMTP_SECURE() { return this.get('SMTP_SECURE', false) }
174
- }
175
-
176
- /**
177
- * Create namespaced environment access
178
- * Usage: const db = createNamespace('DATABASE_')
179
- * db.get('URL') -> reads DATABASE_URL
180
- */
181
- export function createNamespace(prefix: string) {
182
- return {
183
- get: <T>(key: string, defaultValue?: T): T =>
184
- smartEnv.get(`${prefix}${key}`, defaultValue),
185
-
186
- has: (key: string) => smartEnv.has(`${prefix}${key}`),
187
-
188
- all: () => {
189
- const allEnv = smartEnv.all()
190
- const namespaced: Record<string, string> = {}
191
-
192
- for (const [key, value] of Object.entries(allEnv)) {
193
- if (key.startsWith(prefix)) {
194
- namespaced[key.slice(prefix.length)] = value
195
- }
196
- }
197
-
198
- return namespaced
199
- }
200
- }
201
- }
202
-
203
- /**
204
- * Environment validation
205
- */
206
- export const validate = {
207
- require(keys: string[]): void {
208
- const missing = keys.filter(key => !smartEnv.has(key))
209
- if (missing.length > 0) {
210
- throw new Error(`Missing required environment variables: ${missing.join(', ')}`)
211
- }
212
- },
213
-
214
- oneOf(key: string, validValues: string[]): void {
215
- const value = smartEnv.get(key, '')
216
- if (value && !validValues.includes(value)) {
217
- throw new Error(`${key} must be one of: ${validValues.join(', ')}, got: ${value}`)
218
- }
219
- }
220
- }
221
-
222
- /**
223
- * Convenience functions
224
- */
225
- export const helpers = {
226
- isDevelopment: () => env.NODE_ENV === 'development',
227
- isProduction: () => env.NODE_ENV === 'production',
228
- isTest: () => env.NODE_ENV === 'test',
229
-
230
- getDatabaseUrl: () => {
231
- const url = env.DATABASE_URL
232
- if (url) return url
233
-
234
- const { DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD } = env
235
- if (DB_HOST && DB_NAME) {
236
- const auth = DB_USER ? `${DB_USER}:${DB_PASSWORD}@` : ''
237
- return `postgres://${auth}${DB_HOST}:${DB_PORT}/${DB_NAME}`
238
- }
239
-
240
- return null
241
- },
242
-
243
- getServerUrl: () => `http://${env.HOST}:${env.PORT}`,
244
- getClientUrl: () => `http://${env.HOST}:${env.VITE_PORT}`
245
- }
246
-
247
- export default env
248
-
249
- // Legacy exports for compatibility
250
- export const runtimeEnv = env
251
- export const envValidation = validate
252
- export const createEnvNamespace = createNamespace
@@ -1,115 +0,0 @@
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
- }
@@ -1,63 +0,0 @@
1
- import { FluxStackError } from "./index"
2
- import type { Logger } from "../logger/index"
3
-
4
- export interface ErrorHandlerContext {
5
- logger: Logger
6
- isDevelopment: boolean
7
- request?: Request
8
- path?: string
9
- }
10
-
11
- export const errorHandler = (error: Error, context: ErrorHandlerContext) => {
12
- const { logger, isDevelopment, request, path } = context
13
-
14
- if (error instanceof FluxStackError) {
15
- // Log FluxStack errors with appropriate level
16
- const logLevel = error.statusCode >= 500 ? 'error' : 'warn'
17
- logger[logLevel](error.message, {
18
- code: error.code,
19
- statusCode: error.statusCode,
20
- context: error.context,
21
- path,
22
- method: request?.method,
23
- stack: isDevelopment ? error.stack : undefined
24
- })
25
-
26
- return {
27
- error: {
28
- message: error.message,
29
- code: error.code,
30
- statusCode: error.statusCode,
31
- ...(error.context && { details: error.context }),
32
- ...(isDevelopment && { stack: error.stack })
33
- }
34
- }
35
- }
36
-
37
- // Handle unknown errors - skip logging for NOT_FOUND unless explicitly enabled
38
- if (error.message === 'NOT_FOUND' && !process.env.ENABLE_NOT_FOUND_LOGS) {
39
- // Skip logging NOT_FOUND errors to reduce noise
40
- } else {
41
- logger.error('Unhandled error', {
42
- error: error.message,
43
- stack: error.stack,
44
- path,
45
- method: request?.method
46
- })
47
- }
48
-
49
- return {
50
- error: {
51
- message: isDevelopment ? error.message : 'Internal server error',
52
- code: 'INTERNAL_ERROR',
53
- statusCode: 500,
54
- ...(isDevelopment && { stack: error.stack })
55
- }
56
- }
57
- }
58
-
59
- export const createErrorHandler = (context: Omit<ErrorHandlerContext, 'request' | 'path'>) => {
60
- return (error: Error, request?: Request, path?: string) => {
61
- return errorHandler(error, { ...context, request, path })
62
- }
63
- }
@@ -1,81 +0,0 @@
1
- export class FluxStackError extends Error {
2
- public readonly code: string
3
- public readonly statusCode: number
4
- public readonly context?: any
5
- public readonly timestamp: Date
6
-
7
- constructor(
8
- message: string,
9
- code: string,
10
- statusCode: number = 500,
11
- context?: any
12
- ) {
13
- super(message)
14
- this.name = 'FluxStackError'
15
- this.code = code
16
- this.statusCode = statusCode
17
- this.context = context
18
- this.timestamp = new Date()
19
- }
20
-
21
- toJSON() {
22
- return {
23
- name: this.name,
24
- message: this.message,
25
- code: this.code,
26
- statusCode: this.statusCode,
27
- context: this.context,
28
- timestamp: this.timestamp,
29
- stack: this.stack
30
- }
31
- }
32
- }
33
-
34
- export class ValidationError extends FluxStackError {
35
- constructor(message: string, context?: any) {
36
- super(message, 'VALIDATION_ERROR', 400, context)
37
- this.name = 'ValidationError'
38
- }
39
- }
40
-
41
- export class NotFoundError extends FluxStackError {
42
- constructor(resource: string, context?: any) {
43
- super(`${resource} not found`, 'NOT_FOUND', 404, context)
44
- this.name = 'NotFoundError'
45
- }
46
- }
47
-
48
- export class UnauthorizedError extends FluxStackError {
49
- constructor(message: string = 'Unauthorized', context?: any) {
50
- super(message, 'UNAUTHORIZED', 401, context)
51
- this.name = 'UnauthorizedError'
52
- }
53
- }
54
-
55
- export class ForbiddenError extends FluxStackError {
56
- constructor(message: string = 'Forbidden', context?: any) {
57
- super(message, 'FORBIDDEN', 403, context)
58
- this.name = 'ForbiddenError'
59
- }
60
- }
61
-
62
- export class ConflictError extends FluxStackError {
63
- constructor(message: string, context?: any) {
64
- super(message, 'CONFLICT', 409, context)
65
- this.name = 'ConflictError'
66
- }
67
- }
68
-
69
- export class InternalServerError extends FluxStackError {
70
- constructor(message: string = 'Internal server error', context?: any) {
71
- super(message, 'INTERNAL_SERVER_ERROR', 500, context)
72
- this.name = 'InternalServerError'
73
- }
74
- }
75
-
76
- export class ServiceUnavailableError extends FluxStackError {
77
- constructor(message: string = 'Service unavailable', context?: any) {
78
- super(message, 'SERVICE_UNAVAILABLE', 503, context)
79
- this.name = 'ServiceUnavailableError'
80
- }
81
- }
@@ -1,180 +0,0 @@
1
- /**
2
- * General utility functions for FluxStack
3
- */
4
-
5
- export const formatBytes = (bytes: number, decimals: number = 2): string => {
6
- if (bytes === 0) return '0 Bytes'
7
-
8
- const k = 1024
9
- const dm = decimals < 0 ? 0 : decimals
10
- const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
11
-
12
- const i = Math.floor(Math.log(bytes) / Math.log(k))
13
-
14
- return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
15
- }
16
-
17
- export const createTimer = (label: string) => {
18
- const start = Date.now()
19
-
20
- return {
21
- end: (): number => {
22
- const duration = Date.now() - start
23
- return duration
24
- },
25
- label
26
- }
27
- }
28
-
29
- export const delay = (ms: number): Promise<void> => {
30
- return new Promise(resolve => setTimeout(resolve, ms))
31
- }
32
-
33
- export const retry = async <T>(
34
- fn: () => Promise<T>,
35
- maxAttempts: number = 3,
36
- delayMs: number = 1000
37
- ): Promise<T> => {
38
- let lastError: Error
39
-
40
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
41
- try {
42
- return await fn()
43
- } catch (error) {
44
- lastError = error as Error
45
-
46
- if (attempt === maxAttempts) {
47
- throw lastError
48
- }
49
-
50
- await delay(delayMs * attempt) // Exponential backoff
51
- }
52
- }
53
-
54
- throw lastError!
55
- }
56
-
57
- export const debounce = <T extends (...args: any[]) => any>(
58
- func: T,
59
- wait: number
60
- ): ((...args: Parameters<T>) => void) => {
61
- let timeout: NodeJS.Timeout | null = null
62
-
63
- return (...args: Parameters<T>) => {
64
- if (timeout) {
65
- clearTimeout(timeout)
66
- }
67
-
68
- timeout = setTimeout(() => {
69
- func(...args)
70
- }, wait)
71
- }
72
- }
73
-
74
- export const throttle = <T extends (...args: any[]) => any>(
75
- func: T,
76
- limit: number
77
- ): ((...args: Parameters<T>) => void) => {
78
- let inThrottle: boolean = false
79
-
80
- return (...args: Parameters<T>) => {
81
- if (!inThrottle) {
82
- func(...args)
83
- inThrottle = true
84
- setTimeout(() => inThrottle = false, limit)
85
- }
86
- }
87
- }
88
-
89
- export const isProduction = (): boolean => {
90
- return process.env.NODE_ENV === 'production'
91
- }
92
-
93
- export const isDevelopment = (): boolean => {
94
- return process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
95
- }
96
-
97
- export const isTest = (): boolean => {
98
- return process.env.NODE_ENV === 'test'
99
- }
100
-
101
- export const deepMerge = <T extends Record<string, any>>(target: T, source: Partial<T>): T => {
102
- const result = { ...target }
103
-
104
- for (const key in source) {
105
- if (source.hasOwnProperty(key)) {
106
- const sourceValue = source[key]
107
- const targetValue = result[key]
108
-
109
- if (
110
- sourceValue &&
111
- typeof sourceValue === 'object' &&
112
- !Array.isArray(sourceValue) &&
113
- targetValue &&
114
- typeof targetValue === 'object' &&
115
- !Array.isArray(targetValue)
116
- ) {
117
- result[key] = deepMerge(targetValue, sourceValue)
118
- } else {
119
- result[key] = sourceValue as T[Extract<keyof T, string>]
120
- }
121
- }
122
- }
123
-
124
- return result
125
- }
126
-
127
- export const pick = <T extends Record<string, any>, K extends keyof T>(
128
- obj: T,
129
- keys: K[]
130
- ): Pick<T, K> => {
131
- const result = {} as Pick<T, K>
132
-
133
- for (const key of keys) {
134
- if (key in obj) {
135
- result[key] = obj[key]
136
- }
137
- }
138
-
139
- return result
140
- }
141
-
142
- export const omit = <T extends Record<string, any>, K extends keyof T>(
143
- obj: T,
144
- keys: K[]
145
- ): Omit<T, K> => {
146
- const result = { ...obj }
147
-
148
- for (const key of keys) {
149
- delete result[key]
150
- }
151
-
152
- return result
153
- }
154
-
155
- export const generateId = (length: number = 8): string => {
156
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
157
- let result = ''
158
-
159
- for (let i = 0; i < length; i++) {
160
- result += chars.charAt(Math.floor(Math.random() * chars.length))
161
- }
162
-
163
- return result
164
- }
165
-
166
- export const safeJsonParse = <T = any>(json: string, fallback: T): T => {
167
- try {
168
- return JSON.parse(json)
169
- } catch {
170
- return fallback
171
- }
172
- }
173
-
174
- export const safeJsonStringify = (obj: any, fallback: string = '{}'): string => {
175
- try {
176
- return JSON.stringify(obj)
177
- } catch {
178
- return fallback
179
- }
180
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * FluxStack Utilities
3
- * Main exports for utility functions and classes
4
- */
5
-
6
- // Logger utilities
7
- export { logger, log } from "./logger"
8
- export type { Logger } from "./logger/index"
9
-
10
- // Error handling
11
- export * from "./errors"
12
-
13
- // Monitoring
14
- export { MetricsCollector } from "./monitoring"
15
- export type * from "./monitoring"
16
-
17
- // General helpers
18
- export * from "./helpers"