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.
- package/create-fluxstack.ts +2 -3
- package/package.json +1 -1
- package/.env +0 -30
- package/LICENSE +0 -21
- package/app/client/README.md +0 -69
- package/app/client/frontend-only.ts +0 -12
- package/app/client/index.html +0 -13
- package/app/client/public/vite.svg +0 -1
- package/app/client/src/App.css +0 -883
- package/app/client/src/App.tsx +0 -669
- package/app/client/src/assets/react.svg +0 -1
- package/app/client/src/components/TestPage.tsx +0 -453
- package/app/client/src/index.css +0 -51
- package/app/client/src/lib/eden-api.ts +0 -110
- package/app/client/src/main.tsx +0 -10
- package/app/client/src/vite-env.d.ts +0 -1
- package/app/client/tsconfig.app.json +0 -43
- package/app/client/tsconfig.json +0 -7
- package/app/client/tsconfig.node.json +0 -25
- package/app/server/app.ts +0 -10
- package/app/server/backend-only.ts +0 -15
- package/app/server/controllers/users.controller.ts +0 -69
- package/app/server/index.ts +0 -104
- package/app/server/routes/index.ts +0 -25
- package/app/server/routes/users.routes.ts +0 -121
- package/app/server/types/index.ts +0 -1
- package/app/shared/types/index.ts +0 -18
- package/bun.lock +0 -1053
- package/core/__tests__/integration.test.ts +0 -227
- package/core/build/index.ts +0 -186
- package/core/cli/command-registry.ts +0 -334
- package/core/cli/index.ts +0 -394
- package/core/cli/plugin-discovery.ts +0 -200
- package/core/client/standalone.ts +0 -57
- package/core/config/__tests__/config-loader.test.ts +0 -591
- 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/config/env-dynamic.ts +0 -326
- package/core/config/env.ts +0 -597
- package/core/config/index.ts +0 -317
- package/core/config/loader.ts +0 -546
- package/core/config/runtime-config.ts +0 -322
- package/core/config/schema.ts +0 -694
- package/core/config/validator.ts +0 -540
- package/core/framework/__tests__/server.test.ts +0 -233
- package/core/framework/client.ts +0 -132
- package/core/framework/index.ts +0 -8
- package/core/framework/server.ts +0 -501
- package/core/framework/types.ts +0 -63
- 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/plugins/built-in/index.ts +0 -142
- package/core/plugins/built-in/logger/index.ts +0 -180
- package/core/plugins/built-in/monitoring/README.md +0 -193
- package/core/plugins/built-in/monitoring/index.ts +0 -912
- package/core/plugins/built-in/static/index.ts +0 -289
- package/core/plugins/built-in/swagger/index.ts +0 -229
- package/core/plugins/built-in/vite/index.ts +0 -316
- package/core/plugins/config.ts +0 -348
- package/core/plugins/discovery.ts +0 -350
- package/core/plugins/executor.ts +0 -351
- package/core/plugins/index.ts +0 -195
- package/core/plugins/manager.ts +0 -583
- package/core/plugins/registry.ts +0 -424
- package/core/plugins/types.ts +0 -254
- package/core/server/framework.ts +0 -123
- package/core/server/index.ts +0 -8
- package/core/server/plugins/database.ts +0 -182
- package/core/server/plugins/logger.ts +0 -47
- package/core/server/plugins/swagger.ts +0 -34
- package/core/server/standalone.ts +0 -91
- package/core/templates/create-project.ts +0 -455
- package/core/types/api.ts +0 -169
- package/core/types/build.ts +0 -174
- package/core/types/config.ts +0 -68
- package/core/types/index.ts +0 -127
- package/core/types/plugin.ts +0 -94
- 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/core/utils/env-runtime-v2.ts +0 -232
- package/core/utils/env-runtime.ts +0 -252
- package/core/utils/errors/codes.ts +0 -115
- package/core/utils/errors/handlers.ts +0 -63
- package/core/utils/errors/index.ts +0 -81
- package/core/utils/helpers.ts +0 -180
- package/core/utils/index.ts +0 -18
- package/core/utils/logger/index.ts +0 -161
- package/core/utils/logger.ts +0 -106
- package/core/utils/monitoring/index.ts +0 -212
- package/tsconfig.json +0 -51
- package/vite.config.ts +0 -42
package/core/config/validator.ts
DELETED
|
@@ -1,540 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration Validation System for FluxStack
|
|
3
|
-
* Provides comprehensive validation with detailed error reporting
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { FluxStackConfig } from './schema'
|
|
7
|
-
import { fluxStackConfigSchema } from './schema'
|
|
8
|
-
|
|
9
|
-
export interface ValidationError {
|
|
10
|
-
path: string
|
|
11
|
-
message: string
|
|
12
|
-
value?: any
|
|
13
|
-
expected?: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ValidationWarning {
|
|
17
|
-
path: string
|
|
18
|
-
message: string
|
|
19
|
-
suggestion?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface ValidationResult {
|
|
23
|
-
valid: boolean
|
|
24
|
-
errors: string[]
|
|
25
|
-
warnings: string[]
|
|
26
|
-
details: {
|
|
27
|
-
errors: ValidationError[]
|
|
28
|
-
warnings: ValidationWarning[]
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* JSON Schema validator implementation
|
|
34
|
-
*/
|
|
35
|
-
class SchemaValidator {
|
|
36
|
-
private validateProperty(
|
|
37
|
-
value: any,
|
|
38
|
-
schema: any,
|
|
39
|
-
path: string = '',
|
|
40
|
-
errors: ValidationError[] = [],
|
|
41
|
-
warnings: ValidationWarning[] = []
|
|
42
|
-
): void {
|
|
43
|
-
if (schema.type) {
|
|
44
|
-
this.validateType(value, schema, path, errors)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (schema.properties && typeof value === 'object' && value !== null) {
|
|
48
|
-
this.validateObject(value, schema, path, errors, warnings)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (schema.items && Array.isArray(value)) {
|
|
52
|
-
this.validateArray(value, schema, path, errors, warnings)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (schema.enum) {
|
|
56
|
-
this.validateEnum(value, schema, path, errors)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (schema.pattern && typeof value === 'string') {
|
|
60
|
-
this.validatePattern(value, schema, path, errors)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (schema.minimum !== undefined && typeof value === 'number') {
|
|
64
|
-
this.validateMinimum(value, schema, path, errors)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (schema.maximum !== undefined && typeof value === 'number') {
|
|
68
|
-
this.validateMaximum(value, schema, path, errors)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (schema.minLength !== undefined && typeof value === 'string') {
|
|
72
|
-
this.validateMinLength(value, schema, path, errors)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (schema.maxLength !== undefined && typeof value === 'string') {
|
|
76
|
-
this.validateMaxLength(value, schema, path, errors)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (schema.minItems !== undefined && Array.isArray(value)) {
|
|
80
|
-
this.validateMinItems(value, schema, path, errors)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private validateType(value: any, schema: any, path: string, errors: ValidationError[]): void {
|
|
85
|
-
const actualType = Array.isArray(value) ? 'array' : typeof value
|
|
86
|
-
const expectedType = schema.type
|
|
87
|
-
|
|
88
|
-
if (actualType !== expectedType) {
|
|
89
|
-
errors.push({
|
|
90
|
-
path,
|
|
91
|
-
message: `Expected ${expectedType}, got ${actualType}`,
|
|
92
|
-
value,
|
|
93
|
-
expected: expectedType
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
private validateObject(
|
|
99
|
-
value: any,
|
|
100
|
-
schema: any,
|
|
101
|
-
path: string,
|
|
102
|
-
errors: ValidationError[],
|
|
103
|
-
warnings: ValidationWarning[]
|
|
104
|
-
): void {
|
|
105
|
-
// Check required properties
|
|
106
|
-
if (schema.required) {
|
|
107
|
-
for (const requiredProp of schema.required) {
|
|
108
|
-
if (!(requiredProp in value)) {
|
|
109
|
-
errors.push({
|
|
110
|
-
path: path ? `${path}.${requiredProp}` : requiredProp,
|
|
111
|
-
message: `Missing required property '${requiredProp}'`,
|
|
112
|
-
expected: 'required property'
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Validate existing properties
|
|
119
|
-
for (const [key, propValue] of Object.entries(value)) {
|
|
120
|
-
const propPath = path ? `${path}.${key}` : key
|
|
121
|
-
const propSchema = schema.properties?.[key]
|
|
122
|
-
|
|
123
|
-
if (propSchema) {
|
|
124
|
-
this.validateProperty(propValue, propSchema, propPath, errors, warnings)
|
|
125
|
-
} else if (schema.additionalProperties === false) {
|
|
126
|
-
warnings.push({
|
|
127
|
-
path: propPath,
|
|
128
|
-
message: `Unknown property '${key}'`,
|
|
129
|
-
suggestion: 'Remove this property or add it to the schema'
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private validateArray(
|
|
136
|
-
value: any[],
|
|
137
|
-
schema: any,
|
|
138
|
-
path: string,
|
|
139
|
-
errors: ValidationError[],
|
|
140
|
-
warnings: ValidationWarning[]
|
|
141
|
-
): void {
|
|
142
|
-
value.forEach((item, index) => {
|
|
143
|
-
const itemPath = `${path}[${index}]`
|
|
144
|
-
this.validateProperty(item, schema.items, itemPath, errors, warnings)
|
|
145
|
-
})
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private validateEnum(value: any, schema: any, path: string, errors: ValidationError[]): void {
|
|
149
|
-
if (!schema.enum.includes(value)) {
|
|
150
|
-
errors.push({
|
|
151
|
-
path,
|
|
152
|
-
message: `Value must be one of: ${schema.enum.join(', ')}`,
|
|
153
|
-
value,
|
|
154
|
-
expected: schema.enum.join(' | ')
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
private validatePattern(value: string, schema: any, path: string, errors: ValidationError[]): void {
|
|
160
|
-
const regex = new RegExp(schema.pattern)
|
|
161
|
-
if (!regex.test(value)) {
|
|
162
|
-
errors.push({
|
|
163
|
-
path,
|
|
164
|
-
message: `Value does not match pattern: ${schema.pattern}`,
|
|
165
|
-
value,
|
|
166
|
-
expected: `pattern: ${schema.pattern}`
|
|
167
|
-
})
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
private validateMinimum(value: number, schema: any, path: string, errors: ValidationError[]): void {
|
|
172
|
-
if (value < schema.minimum) {
|
|
173
|
-
errors.push({
|
|
174
|
-
path,
|
|
175
|
-
message: `Value must be >= ${schema.minimum}`,
|
|
176
|
-
value,
|
|
177
|
-
expected: `>= ${schema.minimum}`
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private validateMaximum(value: number, schema: any, path: string, errors: ValidationError[]): void {
|
|
183
|
-
if (value > schema.maximum) {
|
|
184
|
-
errors.push({
|
|
185
|
-
path,
|
|
186
|
-
message: `Value must be <= ${schema.maximum}`,
|
|
187
|
-
value,
|
|
188
|
-
expected: `<= ${schema.maximum}`
|
|
189
|
-
})
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private validateMinLength(value: string, schema: any, path: string, errors: ValidationError[]): void {
|
|
194
|
-
if (value.length < schema.minLength) {
|
|
195
|
-
errors.push({
|
|
196
|
-
path,
|
|
197
|
-
message: `String must be at least ${schema.minLength} characters long`,
|
|
198
|
-
value,
|
|
199
|
-
expected: `length >= ${schema.minLength}`
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
private validateMaxLength(value: string, schema: any, path: string, errors: ValidationError[]): void {
|
|
205
|
-
if (value.length > schema.maxLength) {
|
|
206
|
-
errors.push({
|
|
207
|
-
path,
|
|
208
|
-
message: `String must be at most ${schema.maxLength} characters long`,
|
|
209
|
-
value,
|
|
210
|
-
expected: `length <= ${schema.maxLength}`
|
|
211
|
-
})
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private validateMinItems(value: any[], schema: any, path: string, errors: ValidationError[]): void {
|
|
216
|
-
if (value.length < schema.minItems) {
|
|
217
|
-
errors.push({
|
|
218
|
-
path,
|
|
219
|
-
message: `Array must have at least ${schema.minItems} items`,
|
|
220
|
-
value,
|
|
221
|
-
expected: `length >= ${schema.minItems}`
|
|
222
|
-
})
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
validate(value: any, schema: any): ValidationResult {
|
|
227
|
-
const errors: ValidationError[] = []
|
|
228
|
-
const warnings: ValidationWarning[] = []
|
|
229
|
-
|
|
230
|
-
this.validateProperty(value, schema, '', errors, warnings)
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
valid: errors.length === 0,
|
|
234
|
-
errors: errors.map(e => `${e.path}: ${e.message}`),
|
|
235
|
-
warnings: warnings.map(w => `${w.path}: ${w.message}${w.suggestion ? ` (${w.suggestion})` : ''}`),
|
|
236
|
-
details: { errors, warnings }
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Business logic validation rules
|
|
243
|
-
*/
|
|
244
|
-
class BusinessValidator {
|
|
245
|
-
validate(config: FluxStackConfig): ValidationResult {
|
|
246
|
-
const errors: ValidationError[] = []
|
|
247
|
-
const warnings: ValidationWarning[] = []
|
|
248
|
-
|
|
249
|
-
// Port conflict validation
|
|
250
|
-
this.validatePortConflicts(config, errors)
|
|
251
|
-
|
|
252
|
-
// CORS validation
|
|
253
|
-
this.validateCorsConfiguration(config, warnings)
|
|
254
|
-
|
|
255
|
-
// Plugin validation
|
|
256
|
-
this.validatePluginConfiguration(config, warnings)
|
|
257
|
-
|
|
258
|
-
// Build configuration validation
|
|
259
|
-
this.validateBuildConfiguration(config, warnings)
|
|
260
|
-
|
|
261
|
-
// Environment-specific validation
|
|
262
|
-
this.validateEnvironmentConfiguration(config, warnings)
|
|
263
|
-
|
|
264
|
-
// Security validation
|
|
265
|
-
this.validateSecurityConfiguration(config, warnings)
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
valid: errors.length === 0,
|
|
269
|
-
errors: errors.map(e => `${e.path}: ${e.message}`),
|
|
270
|
-
warnings: warnings.map(w => `${w.path}: ${w.message}${w.suggestion ? ` (${w.suggestion})` : ''}`),
|
|
271
|
-
details: { errors, warnings }
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
private validatePortConflicts(config: FluxStackConfig, errors: ValidationError[]): void {
|
|
276
|
-
const ports = [config.server.port, config.client.port]
|
|
277
|
-
const uniquePorts = new Set(ports.filter(p => p !== 0)) // 0 means random port
|
|
278
|
-
|
|
279
|
-
if (uniquePorts.size !== ports.filter(p => p !== 0).length) {
|
|
280
|
-
errors.push({
|
|
281
|
-
path: 'ports',
|
|
282
|
-
message: 'Server and client ports must be different',
|
|
283
|
-
value: { server: config.server.port, client: config.client.port }
|
|
284
|
-
})
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
private validateCorsConfiguration(config: FluxStackConfig, warnings: ValidationWarning[]): void {
|
|
289
|
-
const { cors } = config.server
|
|
290
|
-
|
|
291
|
-
// Check for overly permissive CORS
|
|
292
|
-
if (cors.origins.includes('*')) {
|
|
293
|
-
warnings.push({
|
|
294
|
-
path: 'server.cors.origins',
|
|
295
|
-
message: 'Using wildcard (*) for CORS origins is not recommended in production',
|
|
296
|
-
suggestion: 'Specify explicit origins for better security'
|
|
297
|
-
})
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Check for missing common headers
|
|
301
|
-
const commonHeaders = ['Content-Type', 'Authorization']
|
|
302
|
-
const missingHeaders = commonHeaders.filter(h => !cors.headers.includes(h))
|
|
303
|
-
|
|
304
|
-
if (missingHeaders.length > 0) {
|
|
305
|
-
warnings.push({
|
|
306
|
-
path: 'server.cors.headers',
|
|
307
|
-
message: `Consider adding common headers: ${missingHeaders.join(', ')}`,
|
|
308
|
-
suggestion: 'These headers are commonly needed for API requests'
|
|
309
|
-
})
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
private validatePluginConfiguration(config: FluxStackConfig, warnings: ValidationWarning[]): void {
|
|
314
|
-
const { enabled, disabled } = config.plugins
|
|
315
|
-
|
|
316
|
-
// Check for plugins in both enabled and disabled lists
|
|
317
|
-
const conflicts = enabled.filter(p => disabled.includes(p))
|
|
318
|
-
if (conflicts.length > 0) {
|
|
319
|
-
warnings.push({
|
|
320
|
-
path: 'plugins',
|
|
321
|
-
message: `Plugins listed in both enabled and disabled: ${conflicts.join(', ')}`,
|
|
322
|
-
suggestion: 'Remove from one of the lists'
|
|
323
|
-
})
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// Check for essential plugins
|
|
327
|
-
const essentialPlugins = ['logger', 'cors']
|
|
328
|
-
const missingEssential = essentialPlugins.filter(p =>
|
|
329
|
-
!enabled.includes(p) || disabled.includes(p)
|
|
330
|
-
)
|
|
331
|
-
|
|
332
|
-
if (missingEssential.length > 0) {
|
|
333
|
-
warnings.push({
|
|
334
|
-
path: 'plugins.enabled',
|
|
335
|
-
message: `Consider enabling essential plugins: ${missingEssential.join(', ')}`,
|
|
336
|
-
suggestion: 'These plugins provide important functionality'
|
|
337
|
-
})
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
private validateBuildConfiguration(config: FluxStackConfig, warnings: ValidationWarning[]): void {
|
|
342
|
-
const { build } = config
|
|
343
|
-
|
|
344
|
-
// Check for development settings in production
|
|
345
|
-
if (process.env.NODE_ENV === 'production') {
|
|
346
|
-
if (!build.optimization.minify) {
|
|
347
|
-
warnings.push({
|
|
348
|
-
path: 'build.optimization.minify',
|
|
349
|
-
message: 'Minification is disabled in production',
|
|
350
|
-
suggestion: 'Enable minification for better performance'
|
|
351
|
-
})
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (!build.optimization.treeshake) {
|
|
355
|
-
warnings.push({
|
|
356
|
-
path: 'build.optimization.treeshake',
|
|
357
|
-
message: 'Tree-shaking is disabled in production',
|
|
358
|
-
suggestion: 'Enable tree-shaking to reduce bundle size'
|
|
359
|
-
})
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Check for conflicting settings
|
|
364
|
-
if (build.optimization.bundleAnalyzer && process.env.NODE_ENV === 'production') {
|
|
365
|
-
warnings.push({
|
|
366
|
-
path: 'build.optimization.bundleAnalyzer',
|
|
367
|
-
message: 'Bundle analyzer is enabled in production',
|
|
368
|
-
suggestion: 'Disable bundle analyzer in production builds'
|
|
369
|
-
})
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
private validateEnvironmentConfiguration(config: FluxStackConfig, warnings: ValidationWarning[]): void {
|
|
374
|
-
if (config.environments) {
|
|
375
|
-
for (const [env, envConfig] of Object.entries(config.environments)) {
|
|
376
|
-
if (envConfig && typeof envConfig === 'object') {
|
|
377
|
-
// Check for potentially dangerous overrides
|
|
378
|
-
if ('server' in envConfig && envConfig.server && 'port' in envConfig.server) {
|
|
379
|
-
if (envConfig.server.port === 0 && env !== 'test') {
|
|
380
|
-
warnings.push({
|
|
381
|
-
path: `environments.${env}.server.port`,
|
|
382
|
-
message: 'Using random port (0) in non-test environment',
|
|
383
|
-
suggestion: 'Specify a fixed port for predictable deployments'
|
|
384
|
-
})
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
private validateSecurityConfiguration(config: FluxStackConfig, warnings: ValidationWarning[]): void {
|
|
393
|
-
// Check for missing authentication configuration in production
|
|
394
|
-
if (process.env.NODE_ENV === 'production' && !config.auth?.secret) {
|
|
395
|
-
warnings.push({
|
|
396
|
-
path: 'auth.secret',
|
|
397
|
-
message: 'No authentication secret configured for production',
|
|
398
|
-
suggestion: 'Set JWT_SECRET environment variable for secure authentication'
|
|
399
|
-
})
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Check for weak authentication settings
|
|
403
|
-
if (config.auth?.secret && config.auth.secret.length < 32) {
|
|
404
|
-
warnings.push({
|
|
405
|
-
path: 'auth.secret',
|
|
406
|
-
message: 'Authentication secret is too short',
|
|
407
|
-
suggestion: 'Use at least 32 characters for better security'
|
|
408
|
-
})
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// Check for insecure CORS in production
|
|
412
|
-
if (process.env.NODE_ENV === 'production' && config.server.cors.credentials) {
|
|
413
|
-
const hasWildcard = config.server.cors.origins.includes('*')
|
|
414
|
-
if (hasWildcard) {
|
|
415
|
-
warnings.push({
|
|
416
|
-
path: 'server.cors',
|
|
417
|
-
message: 'CORS credentials enabled with wildcard origins in production',
|
|
418
|
-
suggestion: 'Specify explicit origins when using credentials'
|
|
419
|
-
})
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Main configuration validator
|
|
427
|
-
*/
|
|
428
|
-
export function validateConfig(config: FluxStackConfig): ValidationResult {
|
|
429
|
-
const schemaValidator = new SchemaValidator()
|
|
430
|
-
const businessValidator = new BusinessValidator()
|
|
431
|
-
|
|
432
|
-
// Validate against JSON schema
|
|
433
|
-
const schemaResult = schemaValidator.validate(config, fluxStackConfigSchema)
|
|
434
|
-
|
|
435
|
-
// Validate business rules
|
|
436
|
-
const businessResult = businessValidator.validate(config)
|
|
437
|
-
|
|
438
|
-
// Combine results
|
|
439
|
-
return {
|
|
440
|
-
valid: schemaResult.valid && businessResult.valid,
|
|
441
|
-
errors: [...schemaResult.errors, ...businessResult.errors],
|
|
442
|
-
warnings: [...schemaResult.warnings, ...businessResult.warnings],
|
|
443
|
-
details: {
|
|
444
|
-
errors: [...schemaResult.details.errors, ...businessResult.details.errors],
|
|
445
|
-
warnings: [...schemaResult.details.warnings, ...businessResult.details.warnings]
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Validate configuration and throw on errors
|
|
452
|
-
*/
|
|
453
|
-
export function validateConfigStrict(config: FluxStackConfig): void {
|
|
454
|
-
const result = validateConfig(config)
|
|
455
|
-
|
|
456
|
-
if (!result.valid) {
|
|
457
|
-
const errorMessage = [
|
|
458
|
-
'Configuration validation failed:',
|
|
459
|
-
...result.errors.map(e => ` - ${e}`),
|
|
460
|
-
...(result.warnings.length > 0 ? ['Warnings:', ...result.warnings.map(w => ` - ${w}`)] : [])
|
|
461
|
-
].join('\n')
|
|
462
|
-
|
|
463
|
-
throw new Error(errorMessage)
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* Create a configuration validator for a specific environment
|
|
469
|
-
*/
|
|
470
|
-
export function createEnvironmentValidator(environment: string) {
|
|
471
|
-
return (config: FluxStackConfig): ValidationResult => {
|
|
472
|
-
// Apply environment-specific validation rules
|
|
473
|
-
const result = validateConfig(config)
|
|
474
|
-
|
|
475
|
-
// Add environment-specific warnings/errors
|
|
476
|
-
if (environment === 'production') {
|
|
477
|
-
// Additional production validations
|
|
478
|
-
if (config.logging.level === 'debug') {
|
|
479
|
-
result.warnings.push('Debug logging enabled in production - consider using "warn" or "error"')
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
if (!config.monitoring.enabled) {
|
|
483
|
-
result.warnings.push('Monitoring is disabled in production - consider enabling for better observability')
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
if (environment === 'development') {
|
|
488
|
-
// Additional development validations
|
|
489
|
-
if (config.build.optimization.minify) {
|
|
490
|
-
result.warnings.push('Minification enabled in development - this may slow down builds')
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
return result
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Validate partial configuration (useful for updates)
|
|
500
|
-
*/
|
|
501
|
-
export function validatePartialConfig(
|
|
502
|
-
partialConfig: Partial<FluxStackConfig>,
|
|
503
|
-
baseConfig: FluxStackConfig
|
|
504
|
-
): ValidationResult {
|
|
505
|
-
// Merge partial config with base config
|
|
506
|
-
const mergedConfig = { ...baseConfig, ...partialConfig }
|
|
507
|
-
|
|
508
|
-
// Validate the merged configuration
|
|
509
|
-
return validateConfig(mergedConfig)
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/**
|
|
513
|
-
* Get validation suggestions for improving configuration
|
|
514
|
-
*/
|
|
515
|
-
export function getConfigSuggestions(config: FluxStackConfig): string[] {
|
|
516
|
-
const result = validateConfig(config)
|
|
517
|
-
const suggestions: string[] = []
|
|
518
|
-
|
|
519
|
-
// Extract suggestions from warnings
|
|
520
|
-
for (const warning of result.details.warnings) {
|
|
521
|
-
if (warning.suggestion) {
|
|
522
|
-
suggestions.push(`${warning.path}: ${warning.suggestion}`)
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
// Add general suggestions based on configuration
|
|
527
|
-
if (!config.monitoring.enabled) {
|
|
528
|
-
suggestions.push('Consider enabling monitoring for better observability')
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
if (config.plugins.enabled.length === 0) {
|
|
532
|
-
suggestions.push('Consider enabling some plugins to extend functionality')
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
if (!config.database && !config.custom?.database) {
|
|
536
|
-
suggestions.push('Consider adding database configuration if your app needs persistence')
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
return suggestions
|
|
540
|
-
}
|