UNPKG

@iopa/router

Version:

Lightweight and fast router for IOPA applications

74 lines (65 loc) 2.22 kB
/* * Internet Open Protocol Abstraction (IOPA) * Copyright (c) 2016 - 2022 Internet Open Protocols Alliance * Portions Copyright (c) 2021 Yusuke Wada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { IContextIopa, AppHandler } from '@iopa/types' import { TraceEvent } from 'iopa' type NamedAppHandler = AppHandler & { id: string } export function compose( middleware: NamedAppHandler[] ): (context: IContextIopa) => Promise<void> { return async (context: IContextIopa) => { let index = -1 return dispatch(0) async function dispatch(i: number): Promise<void> { if (i <= index) { return Promise.reject(new Error('next() called multiple times')) } const handler = middleware[i] index = i if (i > 0) { const prev = middleware[i - 1] context.dispatchEvent(new TraceEvent('trace-next', { label: prev.id })) } if (!handler) { if (i > 0) { const prev = middleware[i - 1] context.dispatchEvent( new TraceEvent('trace-next-resume', { label: prev.id }) ) } return } context.dispatchEvent( new TraceEvent('trace-start', { label: handler.id }) ) return Promise.resolve(handler(context, dispatch.bind(null, i + 1))).then( async (res) => { context.respondWith(res) context.dispatchEvent( new TraceEvent('trace-end', { label: handler.id }) ) if (i > 0) { const prev = middleware[i - 1] context.dispatchEvent( new TraceEvent('trace-next-resume', { label: prev.id }) ) } } ) } } }