43 lines
1.4 KiB
JavaScript
43 lines
1.4 KiB
JavaScript
|
|
export default class APIContract {
|
||
|
|
static validateResponse(response, schema, logger = null) {
|
||
|
|
const errors = [];
|
||
|
|
|
||
|
|
for (const [field, expectedType] of Object.entries(schema)) {
|
||
|
|
if (!(field in response)) {
|
||
|
|
errors.push(`Missing required field: ${field}`);
|
||
|
|
} else {
|
||
|
|
const actualType = typeof response[field];
|
||
|
|
if (actualType !== expectedType) {
|
||
|
|
errors.push(
|
||
|
|
`Field '${field}' type mismatch: expected ${expectedType}, got ${actualType}`
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (errors.length > 0) {
|
||
|
|
const message = `API Contract Violation:\n${errors.join('\n')}`;
|
||
|
|
logger?.error(message);
|
||
|
|
throw new Error(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
return response;
|
||
|
|
}
|
||
|
|
|
||
|
|
static validateArray(array, itemSchema, logger = null) {
|
||
|
|
if (!Array.isArray(array)) {
|
||
|
|
logger?.error('Expected array but got non-array');
|
||
|
|
throw new Error('Expected array response');
|
||
|
|
}
|
||
|
|
|
||
|
|
return array.map((item, index) => {
|
||
|
|
try {
|
||
|
|
return this.validateResponse(item, itemSchema, logger);
|
||
|
|
} catch (error) {
|
||
|
|
logger?.error(`Array item ${index} validation failed`, error);
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|