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

@samislam/switcher

v3.1.0

Published

Switcher is a small powerful express middleware that allows for switching between different middleware stacks.

Downloads

17

Readme

Switcher is a small powerful express middleware that allows for switching between different middleware stacks.

Examples:

Example #1

@overload: switcher(key: string | function, middlewareStacks: object | function)

//  key: function, middlewareStacks: object
switcher((req) => req.$loggedInUser, {
  admin: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
  market: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
})
//  key: string, middlewareStacks: object
switcher('admin', {
  admin: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
  market: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
})
//  key: function, middlewareStacks: function
switcher(
  (req) => req.$loggedInUser,
  (key, req, res, next) => {
    if (key == 'admin')
      return [
        (req, res, next) => {
          next()
        },
        (req, res, next) => {
          next()
        },
        (req, res, next) => {
          next()
        },
      ]
    if (key == 'market')
      return [
        (req, res, next) => {
          next()
        },
        (req, res, next) => {
          next()
        },
        (req, res, next) => {
          next()
        },
      ]
  }
)
//  key: string, middlewareStacks: function
switcher('admin', (key, req, res, next) => {
  if (key == 'admin')
    return [
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
    ]
  if (key == 'market')
    return [
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
    ]
})

Example #2:

@overload: switcher(key: function)

//  middlewareStacks: function
switcher((req, res, next) => {
  if (req.$loggedInUser == 'admin')
    return [
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
    ]
  if (req.$loggedInUser == 'market')
    return [
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
      (req, res, next) => {
        next()
      },
    ]
  next()
})

Example #3:

// @overload: switcher(key: string | function, middlewareStacks: object | function, options: object | function)
switcher((req) => req.$loggedInUser, {
  admin: (req, res, next) => {
    next()
  },
  market: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
})

// @overload: switcher(key: function)
switcher((req, res, next) => {
  if (req.$loggedInUser == 'admin')
    return (req, res, next) => {
      next()
    }

  if (req.$loggedInUser == 'market')
    return (req, res, next) => {
      next()
    }
  next()
})

// @overload: switcher(key: string | function, middlewareStacks: object | function, options: object | function)
// or as a nice fully-featured valid JavaScript syntax
switcher((req) => req.$loggedInUser, (key, req, res, next)=>({
  admin: (req, res, next) => {
    next()
  },
  market: [
    (req, res, next) => {
      next()
    },
    (req, res, next) => {
      next()
    },
  ],
}[key]))

API reference:

The switcher middleware function comes with two overloads:

@overload switcher(key: string | function, middlewareStacks: object | function, options: object | function): Express middleware

This overload is useful when you have a primitive that you're using to decide which track of stacks to walk on. And in case the middlewareStacks argument was an object, the key is used internally by switcher to switch or to choose the object property you define which matches the provided key.

parameters:

  • key: string | function, whatever you provide here is going be passed and used to the middlewareStacks argument as the first argument.

    • If a function is provided, it will be called with the express (req, res) objects.
  • middlewareStacks: object | function, the middleware stacks to execute.

    • If you provided an object, the key argument value is going to be used as an accessor on your object, in other words, your object is going to get called by switcher as yourObject[key], what you should have in this object is key/value pairs, the value of each key in this object can either be an express middleware or an array of express middlewares. whatever the key matches in your object map, is going to be the middleware-stack to use on the request.
      • if no key in your object matched the key argument value, next() is going to be called automatically, and the request is going to get handled from switcher back to the express middlewares stack executor.
        • If you want to capture these requests, add the key else to your object, and whenever a request comes and the key does not match any of your object's keys, this object property is going to be the middleware stack to use.
        • switcher only calls next when you use an object in place of the argument middlewareStacks without having the else property defined in your object.
    • If a function is provided, it will be called with (key, req, res, next), and your function can either return an express middleware or an array of express middlewares, whatever you return from this function will be the middleware-stack to use on the request.
  • options: object | function, options to configure how swticher works.

    • elseKeyword: string, the keyword marked as the else, whenever the key does not match any of the properties in your object (the middlewareStacks argument), the property name here is going to get used instead of the key value to access the middleware stack in your object (default else).

@overload switcher(key: function): Express middleware

This overload is useful when you don't need that style of key, perhaps you have multiple criterias that you decide based-upon which middleware stack track to walk the request on.

parameters:

  • key: function, a function that returns either return an express middleware or an array of express middlewares, whatever you return from this function will be the middleware-stack to use on the request.
    • Your function will be called with the express objects (req, res, next).

The Behavior of Next()

  • Switcher Does Not call next() internally, you always have to call next, switcher only calls next when you use an object in place of the argument middlewareStacks without having the else property defined in your object.

  • In case a middleware called next(), it'll move to the next middleware in the array you provide, in case you provided a middleware instead of an array of middlewares, or in case it reached the last middleware in the array, the argument next that switcher passes to your middleware will move to the outer middleware (it will go back to the express middleware stack).

  • When you write a middlewares container function style (middlewareStacks in case of the first overload, key in the case of the second overload), if you reached the point where you want to move the request out of the switcher middleware completely (you want to exit from switcher), you can only do one of the following:

    1. call next() at the end of the function.

    2. call next() inside your last middleware in case your return value of the function was an array of middlewares.

    3. inside your function in case your return value was a function.

For example:

// @overload: switcher(key: string | function, middlewareStacks: object | function, options: object | function)
router.route('/users').get(
  switcher((req) => req.$loggedInUser, {
    admin: (req, res, next) => {
      next() // this next will move out of switcher to catchAsync
    },
    market: [
      (req, res, next) => {
        next() // this next will move to the middleware down bellow 👇
      },
      (req, res, next) => {
        next() // this next will move out of switcher to otherMiddlewareXXYY
      },
    ],
  }),
  otherMiddlewareXXYY,
  someOtherMiddleware(x, y, z)
)
// @overload: switcher(key: function)
.post(switcher((req, res, next) => {
  if (req.$loggedInUser == 'admin')
    return (req, res, next) => {
      next() // this next will move out of switcher to otherMiddlewareXXYY
    }

  if (req.$loggedInUser == 'market')
    return (req, res, next) => {
      next() // this next will move out of switcher to otherMiddlewareXXYY
    }
  // in case req.$loggedInUser was non of 'admin' or 'market',
  next() // this next will move out of switcher to otherMiddlewareXXYY
}), otherMiddlewareXXYY)

Tip 💡:

In case you did not understand this section, don't worry, all the information mentioned here is just to revise how the switcher logic works in any code, you don't have to think about any of that while writing your code, since you'll always return something at the end, no changes you'll ever have to make in your code. The code you write will naturally work without any two next() calls in your code.

FAQ:

Q: Why is my request hanging in switcher and not moving to the next middleware?

  • The reason must be in a next call, think of the place next is not being called.

Originally created at: 21 June 2022.