0.1.7 • Published 7 months ago

pipio v0.1.7

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

pipio

NPM version NPM downloads Build Status

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.

# npm
npm install pipio

# yarn
yarn add pipio

# pnpm
pnpm add pipio

Usage

CommonJS

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+)

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
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

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

0.1.7

7 months ago

0.1.6

7 months ago

0.1.5

8 months ago

0.1.4

8 months ago

0.1.0

8 months ago

0.0.0-beta

8 months ago