UNPKG

nats-micro

Version:

NATS micro compatible extra-lightweight microservice library

104 lines (88 loc) 2.91 kB
import { ZodError } from 'zod'; // eslint-disable-next-line import/no-cycle import { callHandler } from './callHandler.js'; import { errorToString } from './misc.js'; import { addContextHeadersToThreadContext, threadContext } from './threadContext.js'; import { Broker } from '../broker.js'; import { debug } from '../debug.js'; import { Handler, MessageHandler, MicroserviceHandlerInfo } from '../types/index.js'; export function wrapMethodSafe<T, R>( broker: Broker, callback: Handler<T, R>, handlerInfo: MicroserviceHandlerInfo<T, R>, ): MessageHandler<T> { return async (msg, subject) => { try { const store = new Map(); threadContext.enterWith(store); let input = msg.data; if (handlerInfo.methodConfig.request) { // eslint-disable-next-line @typescript-eslint/no-explicit-any if ((handlerInfo.methodConfig.request._def as any).typeName === 'ZodVoid') // eslint-disable-next-line @typescript-eslint/no-explicit-any input = undefined as any; else try { input = handlerInfo.methodConfig.request.parse(input); } catch (err) { if (err instanceof ZodError) { throw new Error(`Error parsing request fields: ${err.issues.map((i) => `${i.path.join('.')} (${i.message})`).join(', ')}`); } throw err; } } addContextHeadersToThreadContext(msg.headers); debug.ms.thread.debug(`Executing safe ${handlerInfo.method}(${JSON.stringify(msg.data)})`); const output = await callHandler( callback, input, subject, msg.headers ?? [], handlerInfo, ); if ((typeof (output.data) !== 'symbol') && 'replyTo' in msg && msg.replyTo) { if (handlerInfo.methodConfig.response) { try { output.data = handlerInfo.methodConfig.response.parse(output.data); } catch (err) { if (err instanceof ZodError) throw new Error(`Invalid response type: ${err.issues.map((i) => i.message).join(',')}`); else throw err; } } broker.send( msg.replyTo, output.data, { headers: output.headers, }, ); } } catch (err: unknown) { const error = errorToString(err); debug.error(error); if ('replyTo' in msg && msg.replyTo) { const headers: [string, string][] = [ ...( (typeof (err) === 'object') && err && ('status' in err) ? [['X-Error-Status', String(err.status)] as [string, string]] : [] ), ['X-Error-Message', error], ]; broker.send( msg.replyTo, 'ERROR', { headers, }, ); } // throw err; } }; }