@whook/whook
Version:
Build strong and efficient REST web services.
89 lines (88 loc) • 3.44 kB
JavaScript
import { autoService, location } from 'knifecycle';
import { noop } from '../libs/utils.js';
import Ajv from 'ajv/dist/2020.js';
import addAJVFormats from 'ajv-formats';
/* Architecture Note #2.11.2.1: Schema validators
Maintain a single place for JSON schema validation
since it may repeat for several routes. Also
warrantying that the same schema leads to the
same reference for the Siso router parameters
unity checks.
*/
export const DEFAULT_SCHEMA_VALIDATORS_OPTIONS = {
lazy: false,
optimistic: true,
};
export default location(autoService(initSchemaValidators), import.meta.url);
/**
* Initialize the schema validator service for
* application schemas validation. This central
* place is aimed to compile schemas once and
* use them many times.
* @param {Object} services
* The services it depends on
* @param {Object} [services.SCHEMA_VALIDATORS_OPTIONS={}]
* Options for the schema validators registry
* @param {Object} [services.ENV={}]
* An optional environment object
* @param {Object} [services.log=noop]
* An optional logging service
* @param {Object} services.API
* A valid Open API file
* @return {Promise<Number>}
* A promise of a schema validators registry
*/
async function initSchemaValidators({ DEBUG_NODE_ENVS, SCHEMA_VALIDATORS_OPTIONS = DEFAULT_SCHEMA_VALIDATORS_OPTIONS, API, ENV, log = noop, }) {
log('debug', `🖃 - Initializing the validators service.`);
const validatorsMap = {};
const ajv = new Ajv.default({
verbose: DEBUG_NODE_ENVS.includes(ENV.NODE_ENV),
strict: true,
logger: {
log: (...args) => log('debug', ...args),
warn: (...args) => log('warning', ...args),
error: (...args) => log('error', ...args),
},
});
addAJVFormats.default(ajv);
if (API?.components?.schemas) {
for (const key of Object.keys(API.components.schemas)) {
ajv.addSchema(API.components.schemas[key], '#/components/schemas/' + key);
}
if (!SCHEMA_VALIDATORS_OPTIONS.lazy) {
for (const key of Object.keys(API.components.schemas)) {
validatorsMap['#/components/schemas/' + key] = ajv.getSchema('#/components/schemas/' + key);
}
}
}
return (schema) => {
if (schema === true) {
if (!validatorsMap['special://true']) {
validatorsMap['special://true'] = ajv.compile(true);
}
return validatorsMap['special://true'];
}
if (schema === false) {
if (!validatorsMap['special://false']) {
validatorsMap['special://false'] = ajv.compile(false);
}
return validatorsMap['special://false'];
}
if ('$ref' in schema && typeof schema.$ref === 'string') {
if (!validatorsMap[schema.$ref]) {
validatorsMap[schema.$ref] = ajv.getSchema(schema.$ref);
}
return validatorsMap[schema.$ref];
}
if (SCHEMA_VALIDATORS_OPTIONS.optimistic !== true) {
const key = 'data:text/plain;base64,' +
Buffer.from(JSON.stringify(schema)).toString('base64');
if (!validatorsMap[key]) {
validatorsMap[key] = ajv.compile(schema);
}
return validatorsMap[key];
}
return ajv.compile(schema);
};
}
//# sourceMappingURL=schemaValidators.js.map