UNPKG

pipio

Version:

Chain functions together and handle a complex workflow

232 lines (179 loc) 4.99 kB
# pipio [![NPM version][npm-image]](https://npmjs.com/package/pipio) [![NPM downloads][downloads-image]](https://npmjs.com/package/pipio) [![Build Status][github-actions-publish-npm-package]](https://github.com/ham3dz/pipio/actions/workflows/publish_npm_package.yml) ## About Pipio helps developers compose complex business logic from reusable blocks of code (functions) in sync and async manner. ## Installation To install this package, run the command below. ```sh # npm npm install pipio # yarn yarn add pipio # pnpm pnpm add pipio ``` ## Usage ### CommonJS ```js const { pipio } = require('./pipio'); const handler = pipio(async () => { // bootstrap application return { serviceName: 'S1', logger: console.log }; }) // step 1 .use(async ({ serviceName, logger }) => { logger(`${serviceName} is called`); return { serviceName, logger, result: { id: 123, title: 'Todo 1' } }; }) // step 2 .use(async ({ serviceName, logger, result }) => { logger(`${serviceName} is called`); return { status: 200, body: result } }) .build({ onError: (err) => { if (err instanceof BadRequestError) { return { status: 400, body: 'ValidationFailed' } } return { status: 500, body: 'Failed' } }, }); ``` ### ESModule (TypeScript/ES6+) ```js import { pipio } from './pipio'; const handler = pipio(async () => { // bootstrap application return { serviceName: 'S1', logger: console.log }; }) // step 1 .use(async ({ serviceName, logger }) => { logger(`${serviceName} is called`); return { serviceName, logger, result: { id: 123, title: 'Todo 1' } }; }) // step 2 .use(async ({ serviceName, logger, result }) => { logger(`${serviceName} is called`); return { status: 200, body: result } }) .build({ onError: (err) => { if (err instanceof BadRequestError) { return { status: 400, body: 'ValidationFailed' } } return { status: 500, body: 'Failed' } }, }); ``` ## Examples ### Example 1 Without pipio, your handler would be like this. - Unnecessary variable declaration - Complicated error handling (e.g. multiple early returns, not accessing to variables due to variable scope in a try/catch block) - Not testable - Hard to maintain ```js const handler = async (event, context) => { // initialize application (1-time operation) const { validator, database, notification } = await bootstrap(); // parse JSON const parsedResponse = JSON.parse(event.body); // validate input if (validator.isValid(parsedResponse) === false) { return { status: 400, }; } // save in database const savedItem = await database.save(parsedResponse); // notify others await notification.send({ event: 'item.created', item: savedItem }); // map response return { status: 200, body: savedItem, }; }; ``` With pipio, your handler would be like this ```js const handler = pipio(lambdaWrapper()) // bootstrap .use(async (opts) => { // destructure the opts parameter const { event, context } = opts; // initialize application (1-time operation) const { validator, database, notification } = await bootstrap(); return { event, context, validator, database, notification }; }) // parse JSON .use(async (opts) => { try { // parse JSON const parsedResponse = JSON.parse(event.body); } catch (err) { throw new Error('MalformedJSON'); } return { ...opts, parsedResponse }; }) // validate input .use(async (opts) => { // destructure the opts parameter const { event, parsedResponse, validator } = opts; if (validator.isValid(parsedResponse) === false) { throw new Error('BadRequest'); } return opts; }) // save in database .use(async (opts) => { // destructure the opts parameter const { database, parsedResponse } = opts; // save in database const savedItem = await database.save(parsedResponse); return { ...opts, savedItem }; }) // notify others .use(async (opts) => { // destructure the opts parameter const { notification, savedItem } = opts; // notify others await notification.send({ event: 'item.created', item: savedItem }); return opts; }) // map response .use(async (opts) => { // destructure the opts parameter const { savedItem } = opts; return { status: 200, body: savedItem, }; }) // convert to handler .build({ onError: (err) => {}, }); ``` And you're good to go! ## License MIT [npm-image]: https://img.shields.io/npm/v/pipio [npm-url]: https://github.com/ham3dz/pipio [github-actions-publish-npm-package]: https://github.com/ham3dz/pipio/actions/workflows/publish_npm_package.yml/badge.svg [downloads-image]: https://img.shields.io/npm/dw/pipio [downloads-url]: https://github.com/ham3dz/pipio