README
@daisugi/daisugi
Daisugi is a minimalist functional middleware engine.
This project is part of the @daisugi monorepo.
Well tested. | Without any external code dependencies and small size.
Daisugi was created with the purpose of organizing your code in an understandable execution pipeline.
Usage
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
function addName(arg) {
return `${arg} Benadryl`;
}
function addLastName(arg) {
return `${arg} Cumberbatch.`;
}
const handler = sequenceOf([addName, addLastName]);
handler('Hi');
// -> Hi Benadryl Cumberbatch.
Table of contents
Install
Using npm:
npm install @daisugi/daisugi
Using yarn:
yarn add @daisugi/daisugi
Downstream and downstream/upstream
Daisugi allows both types, perform sequential executions like traditional pipes do, by downstream
, to accomplish it you need to use simple functions (handlers
).
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
function addName(arg) {
return `${arg} Benadryl.`;
}
sequenceOf([addName])('Hi');
// -> Hi Benadryl.
Or by yielding downstream
, then flowing the control back upstream
, often used in middleware (like Koa does). This effect is called cascading. To get it, you only need to provide the injectToolkit
property to the meta
data of the function, that tells to Daisugi include the toolkit
with flow utilities (next
, nextWith
) as the last argument to your function.
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
function addName(arg, toolkit) {
arg.value = `${arg.value} Benadryl`;
return toolkit.next;
}
addName.meta = {
injectToolkit: true,
};
function addLastName(arg) {
return `${arg.value} Cumberbatch.`;
}
sequenceOf([addName])({ value: 'Hi' });
// -> 'Hi Benadryl.'
By default the type used is downstream
, its use is more common. But you can always switch to cascading to get more complex behavior (tracing, logger ...). Or you can mix the both types in the same sequence.
Synchronous and asynchronous
Daisugi allows handlers
to be synchronous or asynchronous.
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
async function addName(arg, toolkit) {
return await toolkit.next;
}
addName.meta = {
injectToolkit: true,
};
async function addName(arg) {
return `${arg} Benadryl.`;
}
await sequenceOf([addName])('Hi');
// -> Hi Benadryl.
Nesting
Daisugi allows you to nest as many sequences within each other as needed, because each sequence is nothing more than a new handler
.
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
function addName(arg) {
return `${arg} Benadryl`;
}
function addLastName(arg) {
return `${arg} Cumberbatch.`;
}
sequenceOf([addName, sequenceOf([addLastName])])('Hi');
// -> Hi Benadryl Cumberbatch.
Flow control
In Daisugi you are the owner of the data flow, for that purpose you have available a few methods:
stopPropagationWith
, gives you the possibility to stop and exit the execution of the current sequence.failWith
, stops the execution and exits from all sequences.
const {
daisugi,
stopPropagationWith,
} = require('@daisugi/daisugi');
const { sequenceOf } = daisugi();
function addName(arg) {
return stopPropagationWith(`${arg} Benadryl.`);
}
function addLastName(arg) {
return `${arg} Cumberbatch.`;
}
sequenceOf([addName, addLastName])('Hi');
// -> Hi Benadryl.
const { daisugi, failWith } = require('@daisugi/daisugi');
const { sequenceOf } = daisugi();
function addName(arg) {
return failWith(`${arg} Benadryl`);
}
function addLastName(arg) {
return `${arg} Cumberbatch.`;
}
sequenceOf([addName, addLastName])('Hi');
// -> Result.error.value<'Hi Benadryl'>.
Multiple arguments
The title speaks for itself, you can provide to the handlers
, nextWith
among others, much arguments as needed.
import { daisugi } from '@daisugi/daisugi';
const { sequenceOf } = daisugi();
function addName(arg1, arg2, arg3) {
return `${arg} ${arg2} ${arg3}.`;
}
sequenceOf([addName])('Hi', 'Benadryl', 'Cumberbatch');
// -> Hi Benadryl Cumberbatch.
Extendable
Daisugi gives you the freedom to extend any handler
at execution time or during initialization, using the decorators.
import { daisugi } from '@daisugi/daisugi';
function decorator(handler) {
return function addName(arg) {
handler(`${arg} ${handler.meta.arg}`);
};
}
const { sequenceOf } = daisugi([decorator]);
function addLastName(arg) {
return `${arg} Cumberbatch.`;
}
addLastName.meta = {
arg: 'Benadryl',
};
sequenceOf([addLastName])('Hi');
// -> Hi Benadryl Cumberbatch.
Goal
Daisugi goal is to keep the core as simple as possible, and extend its functionality through the provided tools.
Etymology
Daisugi is a Japanese forestry technique, originated in the 14th century, where specially planted cedar trees are pruned heavily to produce "shoots" that become perfectly uniform, straight and completely knot free lumber.
More info: https://twitter.com/wrathofgnon/status/1250287741247426565
Other projects
Project | Version | Changelog | Description |
---|---|---|---|
Kintsugi | changelog | Is a set of utilities to help build a fault tolerant services. | |
Kado | changelog | Is a minimal and unobtrusive inversion of control container. | |
Oza | changelog | Is a fast, opinionated, minimalist web framework for NodeJS. | |
JavaScript style guide |