UNPKG

fets

Version:

TypeScript HTTP Framework focusing on e2e type-safety, easy setup, performance & great developer experience

147 lines (146 loc) 6.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useTypeBox = useTypeBox; const typebox_1 = require("@sinclair/typebox"); const compiler_1 = require("@sinclair/typebox/compiler"); const value_1 = require("@sinclair/typebox/value"); const server_1 = require("@whatwg-node/server"); const utils_js_1 = require("./utils.js"); function createValidateFn(schema) { try { const validator = compiler_1.TypeCompiler.Compile(schema); return function getErrors(data) { return validator.Errors(data); }; } catch (e) { return function getErrors(data) { return value_1.Value.Errors(schema, data); }; } } function sanitizeError({ schema, type, ...error }, name) { return { ...error, name, }; } function useTypeBox({ components = {}, } = {}) { const validateFnBySchema = new WeakMap(); function getValidateFn(schema) { let validateFn = validateFnBySchema.get(schema); if (!validateFn) { validateFn = createValidateFn({ ...schema, components, }); validateFnBySchema.set(schema, validateFn); } return validateFn; } return { onRouteHandle({ route: { schemas }, request }) { if (schemas?.request?.headers && typebox_1.TypeGuard.IsSchema(schemas.request.headers)) { const validateFn = getValidateFn(schemas.request.headers); const headersObj = (0, utils_js_1.getHeadersObj)(request.headers); const errors = [...validateFn(headersObj)].map(error => sanitizeError(error, 'headers')); if (errors.length) { throw new server_1.HTTPError(400, 'Bad Request', { 'x-error-type': 'validation', }, { errors, }); } } if (schemas?.request?.params && typebox_1.TypeGuard.IsSchema(schemas.request.params)) { const validateFn = getValidateFn(schemas.request.params); const errors = [...validateFn(request.params)].map(error => sanitizeError(error, 'params')); if (errors.length) { throw new server_1.HTTPError(400, 'Bad Request', { 'x-error-type': 'validation', }, { errors, }); } } if (schemas?.request?.query && typebox_1.TypeGuard.IsSchema(schemas.request.query)) { const validateFn = getValidateFn(schemas.request.query); const errors = [...validateFn(request.query)].map(error => sanitizeError(error, 'query')); if (errors.length) { throw new server_1.HTTPError(400, 'Bad Request', { 'x-error-type': 'validation', }, { errors, }); } } if (schemas?.request?.json && typebox_1.TypeGuard.IsSchema(schemas.request.json)) { const validateFn = getValidateFn(schemas.request.json); const origReqJsonMethod = request.json.bind(request); Object.defineProperty(request, 'json', { value: () => origReqJsonMethod().then(jsonObj => { const errors = [...validateFn(jsonObj)].map(({ schema, type, ...error }) => ({ name: 'json', ...error, })); if (errors.length) { throw new server_1.HTTPError(400, 'Bad Request', { 'x-error-type': 'validation', }, { errors, }); } return jsonObj; }), configurable: true, }); } if (schemas?.request?.formData && typebox_1.TypeGuard.IsSchema(schemas.request.formData)) { const validateFn = getValidateFn(schemas.request.formData); const origMethod = request.formData.bind(request); Object.defineProperty(request, 'formData', { configurable: true, value: () => origMethod().then(formData => { const formDataObj = {}; const jobs = []; formData.forEach((value, key) => { if (value != null) { if (typeof value === 'string') { formDataObj[key] = value; } else { jobs.push(value.arrayBuffer().then(buffer => { const typedArray = isByteArray(buffer) ? buffer : new Uint8Array(buffer); const binaryStrParts = []; typedArray.forEach((byte, index) => { binaryStrParts[index] = String.fromCharCode(byte); }); formDataObj[key] = binaryStrParts.join(''); })); } } }); function handleErrors() { const errors = [...validateFn(formDataObj)].map(error => sanitizeError(error, 'formData')); if (errors.length) { throw new server_1.HTTPError(400, 'Bad Request', { 'x-error-type': 'validation', }, { errors, }); } return formDataObj; } if (jobs.length) { return Promise.all(jobs).then(handleErrors); } return handleErrors(); }), }); } }, }; } function isByteArray(value) { return value?.forEach != null; }