npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@yotie/micron

v2.0.0

Published

A hyper-composble micro-framework for serverless functions

Downloads

9

Readme

Writing production-ready lambda services can require quite a bit of boilerplate. micron is here to help improve that experience by providing powerful helpers that allow you to create expressive and hyper-composable serverless functions. This was designed to work seamlessly on Vercel.

Getting Started

Setup

Install the package

$ yarn add @yotie/micron

Create a simple lambda

import { micron } from '@yotie/micron';

export default micron(({ ok }: MicronParams) => {
  return ok({ success: true, hello: 'world' });
});

Example Usage with contrast

BEFORE MICRON

import checkAuth from './checkAuth';

export default function(req: Request, res: Response) {
  try {
    if (!req.method.toUpperCase().equals('POST'))
      return res.status(405).send('Method Unsupported');

    const auth = checkAuth(req.headers['Authorization']);
    if (!auth.isValid) return res.status(401).send('Unauthorized');

    console.log('Logged in with', auth.user);
    return res.status(200).json({
      success: true,
      user: auth.user,
      body: req.body
    });
  } catch(err) {
    return res.status(500).json({ success: false})
  }
}

WITH MICRON

import { createLambda, post } from '@yotie/micron';
import authMiddleWare from './auth';

export default createLambda(
  post(({ req, body, ok, error }) => {
      const { user } = req.auth;
      console.log('Logged in with', user);

      return ok({ success: true, body, user });
  }),
  { middlewares: [authMiddleWare, ...moreMiddleWare]}
);

micron improves the signal-to-noise ratio in your code which increases it readability, while reducing duplication and boilerplate.

API

Type: MicronParams

Vercel provides a useful list of helpers inside of the Request and Response objects passed to the lambda. We've enhanced the experience a bit more by including an additional set of helpers, making it accessible via the MicronParams which is passed on to your functions. While leveraging micron, your serverless functions will change from the default method signature:

(req: IncomingMessage, res: ServerResponse) => res: ServerResponse

to leveraging the MicronLambda function signature:

(params: MicronParams) => res: ServerResponse

Here is a complete list of all the properties contained in the MicronParams:

|Property|Type|Decription| |------|----|----------| |req | Request | The incoming Request object | |res | Response | The outgoing Response object| |body | RequestBody | An object containing the body sent by the request| |cookies | RequestCookies | An object containing the cookies sent by the request| |query | RequestQuery | An object containing the request's query string| |ok | ResponseHelper | Returns a 200 HTTP response with your payload| |brotli | ResponseHelper | Returns a 200 HTTP response with your payload compressed in br encoding| |badRequest | ResponseHelper| Returns a 400 HTTP response with your payload| |unauthorized| ResponseHelper| Returns a 401 HTTP response with your payload| |notFound |ResponseHelper| Returns a 404 HTTP response with your payload| |error| ResponseHelper| Returns a 500 HTTP response with your payload|

The different ResponseHelpers are simple functions that allow you to return a ServerResponse with a preconfigured http status code. Leveraging these functions help enhance the readability and maintainability of your serverless projects by cutting down on some of the bloat. Instead of doing...

return res.status(500).json({ message: 'Catastrophic Failure' });

...you can simplify your code to this:

return error({ message: 'Catastrophic Failure' });

These functions accept String, Array, Object, Buffer as valid inputs which will be passed on as the response body.

micron(fn)

The simplest way of creating a lambda is with the micron helper. This wraps your function in a global exception handler and will add light-weight request logging capabilites.

Usage

export default micron(({ req, ok }: MicronParams) => {
  return ok({
    success: true,
    requestType: req.method
  });
});

Note: lambdas created with the micron function accept requests from any HTTP method type. To restrict the HTTP method that your lambda allows, use one of the following: get, post, put, patch, del

get(fn)

Usage

import { get } from '@yotie/micron';

export default get(({ ok }) => {
  return ok({ success: true });
});

post(fn)

Usage

import { post } from '@yotie/micron';

export default post(({ body, ok }) => {
  return ok({ success: true, payload: body });
});

put(fn)

Usage

import { put } from '@yotie/micron';

export default put(({ ok }) => {
  return ok({ success: true });
});

patch(fn)

Usage

import { patch } from '@yotie/micron';

export default patch(({ ok }) => {
  return ok({ success: true });
});

del(fn)

Usage

import { del } from '@yotie/micron';

export default del(({ ok }) => {
  return ok({ success: true });
});

match({})

Usage

import { match } from '@yotie/micron';

export default match({
  async post({ body, ok, error }) {
    const user = await createUser(body);
    return ok(user);
  },
  async get({ query, ok, notFound }) {
    const user = await getUser(query.id);
    if(!user?.id) return notFound();

    return ok(user);
  }
})

createLambda(fn, opts)

Usage

import { get } from '@yotie/micron';
import { traceMiddleware, } from './middlewares';


export default createLambda(
  get(({ ok }) => {
    // some business logic here
    return ok({ success: true });
  }),
  {
    cors: { origin: 'https://example.com, http://localhost:3000' },
    middlewares: [traceMiddleware]
  }
);

Parameters

Name | Type | Default value | ------ | ------ | ------ | fn | Lambda | - | opts | LambdaOptions | see defaults for LambdaOptions|

LambdaOptions

Name | Type | Default value | ------ | ------ | ------ | cors? | CorsOptions | see defaults for CorsOptions | middlewares? | MicronMiddleware[] | [] |


CORS

CorsOptions

|Parameter| type | default | Description| |---------|------|---------|------------| |origin| string | * | | |maxAge| Number | 86400 | | |allowMethods | string[] | [GET, PUT, POST, PATCH, DELETE, OPTIONS] | | |allowHeaders| string[]| [ X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept]| | |allowCredentials | Boolean | true | | |exposeHeaders| string[]| []| |

Note: the origin can support multiple domains being set as well as glob patters


Middlewares

Middleware functions are functions that have access to the request object (req) and the response object (res) to perform some task before the main lambda executes.

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle, example: return badRequest();

createMiddleware(fn, next)

Usage

import { createMiddleware } from '@yotie/micron';

export const auth = createMiddleware(({ req, unauthorized }, next) => {
  const token = req.headers['Authorization'];
  if (!token) return unauthorized();

  req.auth = { user: 'exampleUser' }
  console.log('User is allowed to access this lambda');

  return next();
});

You can also use the micron helper to build out your middlewares w/o using the createMiddleware helper.

Note: Middlewares must have the following signature fn => (req, res) => fn(req, res)

//auth.js

import { micron, NowLambda } from '@yotie/micron';
import { isValid } from './_utils';

const auth = (lambda: NowLambda) => {
  return micron({ req, res, body, unauthorized } => {
    const token = req.headers['Authorization'];

    if (!isValid(token)) return unautorized();

    console.log('User is allowed to access this lambda');
    return lambda(req, res);
  });
}

Testing

import { micron, mockLambda } from '@yotie/micron';

test('Successful api behaviour scenario', async () => {
  const lambda = micron(({ ok }) => ok({ success: true }));
  const { fetch } = await mockLambda(lambda);

  const res = await fetch('?q=searchQuery');
  const { success } = await res.json();

  expect(res.ok).toBe(true);
  expect(success).toBe(true);
});

TODO

  • [x] Create Logo ✅
  • [x] Create banner ✅
  • [ ] Documentation
    • [x] Improve intro and Getting started ✅
    • [ ] Motivation and design principles 🚧
    • [x] Complete list of helpers from MicronParams ✅
    • [ ] MicronHelpers and their scenarios 🚧
      • [x] micron
      • [ ] get 🚧
      • [ ] put 🚧
      • [ ] post 🚧
      • [ ] del 🚧
      • [ ] match 🚧
    • [ ] Document createLambda and use cases 🚧
    • [x] CORS and networking configuration ✅
    • [ ] Middlewares 🚧
      • [x] flexibility of our middleware pattern ✅
    • [ ] Testing and Mocking
      • [x] add query params serialization ✅
    • [ ] Contributing
  • [ ] Test more negative cases
  • [ ] Add file upload support
  • [ ] Split project into monorepo
    • [ ] micron
    • [ ] micron-mock
    • [ ] micron-vercel
    • [ ] micron-netlify
    • [ ] micron-middleware-auth0
    • [ ] micron-middleware-magiclink

Authors

  • Ashley Narcisse @darkfadr
  • Kennet Postigo @kennetpostigo