UNPKG

@daisugi/daisugi

Version:

Daisugi is a minimalist functional middleware engine.

86 lines 3.1 kB
import { Result } from '@daisugi/anzen'; import { Ayamari } from '@daisugi/ayamari'; const { errFn, errCode } = new Ayamari(); // Duck type validation. function isFnAsync(handler) { return handler.constructor.name === 'AsyncFunction'; } function decorateHandler(userHandler, userHandlerDecorators, nextHandler) { const isAsync = isFnAsync(userHandler); const { injectToolkit } = userHandler.meta || {}; let toolkit; // Declare `toolkit` variable. if (injectToolkit) { toolkit = { nextWith(...args) { if (nextHandler) { return nextHandler(...args); } return null; }, failWith: Daisugi.failWith, }; } const decoratedUserHandler = userHandlerDecorators.reduce((currentUserHandler, userHandlerDecorator) => { const decoratedHandler = userHandlerDecorator(currentUserHandler, toolkit); decoratedHandler.meta = currentUserHandler.meta; return decoratedHandler; }, userHandler); // Maybe use of arguments instead. function handler(...args) { // Duck type condition, maybe use instanceof and result class here. if (args[0]?.isFailure) { const firstArg = args[0]; if (firstArg.getError().code === errCode.Fail) { return firstArg; } if (firstArg.getError().code === errCode.StopPropagation) { return firstArg.getError().meta.value; } } if (injectToolkit) { // Add runtime `toolkit` properties whose depend of the arguments. Object.defineProperty(toolkit, 'next', { get() { return toolkit.nextWith(...args); }, configurable: true, }); return decoratedUserHandler(...args, toolkit); } if (!nextHandler) { return decoratedUserHandler(...args); } if (isAsync) { return decoratedUserHandler(...args).then(nextHandler); } if (nextHandler.__meta__?.isAsync) { return Promise.resolve(decoratedUserHandler(...args)).then(nextHandler); } return nextHandler(decoratedUserHandler(...args)); } handler.__meta__ = { isAsync }; return handler; } function createSequenceOf(userHandlerDecorators) { return (userHandlers) => userHandlers.reduceRight((nextHandler, userHandler) => { return decorateHandler(userHandler, userHandlerDecorators, nextHandler); }, null); } export class Daisugi { sequenceOf; constructor(userHandlerDecorators = []) { this.sequenceOf = createSequenceOf(userHandlerDecorators); } static stopPropagationWith(value) { return Result.failure(errFn.StopPropagation('Daisugi stop propagation.', { meta: { value }, })); } static failWith(value) { return Result.failure(errFn.Fail('Daisugi fail.', { meta: { value }, })); } } //# sourceMappingURL=daisugi.js.map