@daisugi/daisugi
Version:
Daisugi is a minimalist functional middleware engine.
86 lines • 3.1 kB
JavaScript
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