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

lmf

v1.0.26

Published

Have you ever wished there was an easy way to have a function run before every route in a serverless environment? LMF exists to solve this problem. LMF works by reading your middleware file and injecting that logic before every serverless function.

Downloads

20

Readme

Lambda Middleware Framework

Have you ever wished there was an easy way to have a function run before every route in a serverless environment? LMF exists to solve this problem. LMF works by reading your middleware file and injecting that logic before every serverless function.

Installation

npm install lmf --save-dev

Usage

CLI

Run lmf in your project root.

Setting up a build script

Once you have installed lmf as a dev dependency, add a new build script so you can easily call it.

// package.json

{
    "scripts" : {
        "build:api" : "lmf"
    }
}
$ npm run build:api

Setting up an autobuild + serve script

Install these two packages:

npm install --save-dev concurrently onchange

onchange: Let's us run a script whenever a certain directory changes.

concurrently: Makes it easy to run two processes at the same time. Will be used to start autobuild as well as kick off your dev server.

// package.json

{
    "scripts" : {
        // Basic build
        "build:api" : "lmf",

        // Watch the "api" directory and rebuild on any changes
        "watch:api" : "npm run build:api && onchange api -- npm run build:api",
        
        // Whatever your serve command is. We are using Now CLI.
        "serve"     : "now dev",

        // All together now
        "dev"       : "concurrently 'npm run watch:api' 'npm run serve'"
    }
}
$ npm run dev

Use with Rollup

Here's a simple Rollup plugin that will execute a npm script on every build.

// package.json

{
    "scripts" : {
        "build:api" : "lmf"
    }
}
// rollup.config.js

const rollupPluginBuildAPI = () => ({
    writeBundle() {
        require("child_process").spawn("npm", [ "run", "build:api" ], {
            stdio : [ "ignore", "inherit", "inherit" ],
            shell : true,
        });
    },
});

export default {
    plugins : [
        rollupPluginBuildAPI()
    ]
}

Middleware

File location

By default, LMF assumes your middleware file is located at ./api/middleware.js. You can update this in the config mention below.

File contents

Your middleware file ends up becoming the entry point to every serverless function. Therefore, it needs to be setup as if it were a serverless function. Export an object and recieve the req and res. See example.

Require {route}

Middleware must require "{route}" so you can use it in the next step.

Calling {route}

This value will consist of the current serverless function. Make sure you call it at some point in your middleware so that your function is executed.

Referencing local files

When referencing local files in middleware, you must use the "*" alias which represents the root of your input directory. LMF will replace all of the "*" references with the correct navigation to the local file. For instance, require("*_util/config.js") might become require("../../_util/config.js").

Example

// api/middleware.js

// Current route
const route = require({route});

// Local file reference must start with "*"
const config = require("*_util/config.js");

module.exports = async (req,res) => {
    // Will run before every route

    // Do some middlewarey ish
    req.env = "prod";
    req.token = "xxx-xxx-xxx";
    
    // Finally, execute the route
    return await route(req, res);
}

How it works

Lets say you have the following files in your API. Some folders, some files, some underscore directories/files. By default, LMF assumes your code lives in ./api.

api/
├── auth/
│   ├── _auth.js
│   └── signup.js
└── posts.js
└── middleware.js

Transformation

LMF will read your API and directly copy it to the specified output directory. Your middleware file then ends up becoming the actual route that references your original function. See below:

Note: Files and folders prefixed with "_" will be ignored.

Before

// api/posts.js

module.exports = (req, res) => {
    // Route  code
}
// api/middleware.js

// This will be replaced with a reference to the current route
const route = require({route});

module.exports = async (req,res) => {
    // Will run before every route

    // Do some middlewarey ish
    req.env = "prod";
    req.token = "xxx-xxx-xxx";
    
    // Finally, execute the route
    return await route(req, res);
}

After

Serverless functions are renamed and prefixed with "_lmf."

// api/posts.js -> api/_lmf.posts.js

module.exports = (req, res) => {
    // Route code
}

The contents of middleware are written to a new file next to the original function. The new middleware file takes on the original name of your function and references the updated name.

// api/middleware.js -> api/posts.js

// Reference updated
const route = require("./_lmf.posts.js");

module.exports = async (req,res) => {
    // I will run before every route

    // That middlewarey ish
    req.env = "prod";
    req.token = "xxx-xxx-xxx";
    
    // Finally, execute the referenced route
    return await route(req, res);
}

Output

Ready to serve!

api/
├── auth/
│   ├── _auth.js
│   ├── _lmf.signup.js
│   └── signup.js
├── _lmf._posts.js
└── posts.js

Config

You can optionally add a lmf.config.json to the root of your project.

Options and defaults

{
    // Relative to project root
    "input"      : "api",
    "output"     : "build/api",

    // Path to your middleware file.
    // Middleware path is relative to input
    // so this would be api/middleware.js.
    "middleware" : "middleware.js",

    // Delete output directory before every build
    "clean":     : false
}