switched to new config and removed old
This commit is contained in:
parent
6b69bcbcaa
commit
269364fbc8
70 changed files with 889 additions and 2978 deletions
193
libs/config/src/utils/validation.ts
Normal file
193
libs/config/src/utils/validation.ts
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
import { z } from 'zod';
|
||||
import { ConfigValidationError } from '../errors';
|
||||
|
||||
export interface ValidationResult {
|
||||
valid: boolean;
|
||||
errors?: Array<{
|
||||
path: string;
|
||||
message: string;
|
||||
expected?: string;
|
||||
received?: string;
|
||||
}>;
|
||||
warnings?: Array<{
|
||||
path: string;
|
||||
message: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate configuration against a schema
|
||||
*/
|
||||
export function validateConfig<T>(
|
||||
config: unknown,
|
||||
schema: z.ZodSchema<T>
|
||||
): ValidationResult {
|
||||
try {
|
||||
schema.parse(config);
|
||||
return { valid: true };
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
const errors = error.errors.map(err => ({
|
||||
path: err.path.join('.'),
|
||||
message: err.message,
|
||||
expected: 'expected' in err ? String(err.expected) : undefined,
|
||||
received: 'received' in err ? String(err.received) : undefined,
|
||||
}));
|
||||
|
||||
return { valid: false, errors };
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for deprecated configuration options
|
||||
*/
|
||||
export function checkDeprecations(
|
||||
config: Record<string, any>,
|
||||
deprecations: Record<string, string>
|
||||
): ValidationResult['warnings'] {
|
||||
const warnings: ValidationResult['warnings'] = [];
|
||||
|
||||
function checkObject(obj: any, path: string[] = []): void {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const currentPath = [...path, key];
|
||||
const pathStr = currentPath.join('.');
|
||||
|
||||
if (pathStr in deprecations) {
|
||||
warnings?.push({
|
||||
path: pathStr,
|
||||
message: deprecations[pathStr],
|
||||
});
|
||||
}
|
||||
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
||||
checkObject(value, currentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkObject(config);
|
||||
return warnings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for required environment variables
|
||||
*/
|
||||
export function checkRequiredEnvVars(
|
||||
required: string[]
|
||||
): ValidationResult {
|
||||
const errors: ValidationResult['errors'] = [];
|
||||
|
||||
for (const envVar of required) {
|
||||
if (!process.env[envVar]) {
|
||||
errors.push({
|
||||
path: `env.${envVar}`,
|
||||
message: `Required environment variable ${envVar} is not set`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors: errors.length > 0 ? errors : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate configuration completeness
|
||||
*/
|
||||
export function validateCompleteness(
|
||||
config: Record<string, any>,
|
||||
required: string[]
|
||||
): ValidationResult {
|
||||
const errors: ValidationResult['errors'] = [];
|
||||
|
||||
for (const path of required) {
|
||||
const keys = path.split('.');
|
||||
let current: any = config;
|
||||
let found = true;
|
||||
|
||||
for (const key of keys) {
|
||||
if (current && typeof current === 'object' && key in current) {
|
||||
current = current[key];
|
||||
} else {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found || current === undefined || current === null) {
|
||||
errors.push({
|
||||
path,
|
||||
message: `Required configuration value is missing`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors: errors.length > 0 ? errors : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format validation result for display
|
||||
*/
|
||||
export function formatValidationResult(result: ValidationResult): string {
|
||||
const lines: string[] = [];
|
||||
|
||||
if (result.valid) {
|
||||
lines.push('✅ Configuration is valid');
|
||||
} else {
|
||||
lines.push('❌ Configuration validation failed');
|
||||
}
|
||||
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
lines.push('\nErrors:');
|
||||
for (const error of result.errors) {
|
||||
lines.push(` - ${error.path}: ${error.message}`);
|
||||
if (error.expected && error.received) {
|
||||
lines.push(` Expected: ${error.expected}, Received: ${error.received}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.warnings && result.warnings.length > 0) {
|
||||
lines.push('\nWarnings:');
|
||||
for (const warning of result.warnings) {
|
||||
lines.push(` - ${warning.path}: ${warning.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a strict schema that doesn't allow extra properties
|
||||
*/
|
||||
export function createStrictSchema<T extends z.ZodRawShape>(
|
||||
shape: T
|
||||
): z.ZodObject<T, 'strict'> {
|
||||
return z.object(shape).strict();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge multiple schemas
|
||||
*/
|
||||
export function mergeSchemas<T extends z.ZodSchema[]>(
|
||||
...schemas: T
|
||||
): z.ZodIntersection<T[0], T[1]> {
|
||||
if (schemas.length < 2) {
|
||||
throw new Error('At least two schemas required for merge');
|
||||
}
|
||||
|
||||
let result = schemas[0].and(schemas[1]);
|
||||
|
||||
for (let i = 2; i < schemas.length; i++) {
|
||||
result = result.and(schemas[i]) as any;
|
||||
}
|
||||
|
||||
return result as any;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue