{"id":17600,"library":"execute-middleware","title":"Express-style Middleware Executor","description":"execute-middleware is a JavaScript utility designed for the standalone execution of Express-style middleware logic, outside of a full Express application. It processes both standard middleware (expecting `(req, res, next)`) and error-handling middleware (expecting `(err, req, res, next)`), automatically differentiating between them by the number of arguments. The library supports complex nesting of middleware arrays and correctly handles error propagation: when `next(err)` is called, subsequent normal middleware is skipped until an error handler is encountered. It offers both serial and concurrent execution modes for middleware chains. The current stable version is 1.0.3. While no explicit release cadence is stated, it appears to be a mature, stable utility providing a focused solution for running Express middleware patterns in a more controlled or isolated environment.","status":"active","version":"1.0.3","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","middleware","run","execute","chain","express","node","mw"],"install":[{"cmd":"npm install execute-middleware","lang":"bash","label":"npm"},{"cmd":"yarn add execute-middleware","lang":"bash","label":"yarn"},{"cmd":"pnpm add execute-middleware","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"CommonJS `require` is shown in old examples, but ESM `import` is preferred for modern Node.js and browser environments.","wrong":"const executeMW = require('execute-middleware');","symbol":"executeMW","correct":"import executeMW from 'execute-middleware';"},{"note":"For direct access to the `serial` function, named import is often cleaner. Assuming `serial` is also a named export.","wrong":"import executeMW from 'execute-middleware'; const serial = executeMW.serial;","symbol":"serial","correct":"import { serial } from 'execute-middleware';"},{"note":"Similar to `serial`, `concurrent` can be imported directly if available as a named export, which is common for modular libraries.","wrong":"const { concurrent } = require('execute-middleware');","symbol":"concurrent","correct":"import { concurrent } from 'execute-middleware';"}],"quickstart":{"code":"import executeMW from 'execute-middleware';\n\n// Mock Express-like objects for demonstration\nconst req = {\n  url: '/',\n  method: 'GET',\n  params: {},\n  query: {},\n  body: {},\n  data: {} // For middleware to attach data\n};\nconst res = {\n  statusCode: 200,\n  _body: null,\n  _headers: {},\n  send: function(data) {\n    this._body = data;\n    console.log('Response sent:', data);\n  },\n  status: function(code) {\n    this.statusCode = code;\n    return this;\n  },\n  json: function(data) {\n    this.send(JSON.stringify(data));\n  },\n  set: function(name, value) {\n    this._headers[name.toLowerCase()] = value;\n    return this;\n  }\n};\n\n// The final `next` function for the entire chain\nconst finalNext = (err) => {\n  if (err) {\n    console.error('Final next caught an error:', err.message);\n    if (!res._body) { // Only send if no middleware already sent one\n      res.status(500).json({ error: err.message || 'Internal Server Error' });\n    }\n  } else {\n    console.log('All middleware in chain completed successfully.');\n    if (!res._body) { // If no middleware sent a response\n      res.status(200).send('No response sent by middleware, but chain completed.');\n    }\n  }\n};\n\n// Some middleware\nconst SOME_MIDDLEWARE = [\n  (req, res, next) => {\n    console.log('Middleware 1: Initializing request data.');\n    req.data.message = 'Hello from MW1';\n    next();\n  },\n  [ // Nested middleware array\n    (req, res, next) => {\n      console.log('Middleware 2.1: Processing:', req.data.message);\n      req.data.processed = true;\n      next();\n    },\n    (err, req, res, next) => { // This is an error handler, won't be called here in normal flow\n      console.log('Middleware 2.2 (Error Handler): This should be skipped in normal flow.');\n      next(err); // Pass error along if called\n    }\n  ],\n  (req, res, next) => {\n      console.log('Middleware 3: Final step, received:', req.data);\n      // Simulate sending a response\n      res.status(200).json({ status: 'success', data: req.data });\n      // Do not call next() here if response is sent, typically ends the chain\n  }\n];\n\nasync function runSerialExample() {\n  console.log('--- Running Serial Middleware Example (Normal Flow) ---');\n  // Pass in the middleware array, then the usual express (req, res, next) values\n  await executeMW.serial(SOME_MIDDLEWARE, req, res, finalNext);\n  console.log('--- Serial Middleware Finished (Normal Flow) ---\\n');\n\n  // Example with error propagation\n  const errorReq = { ...req, data: {} }; // Fresh request object\n  const errorRes = { ...res, _body: null }; // Fresh response object\n\n  const ERROR_MIDDLEWARE = [\n    (req, res, next) => {\n      console.log('Error MW 1: About to trigger an error.');\n      // Simulate an asynchronous operation that throws an error\n      setTimeout(() => {\n        next(new Error('Validation failed for input!'));\n      }, 50);\n    },\n    (req, res, next) => {\n      console.log('Error MW 2: This middleware should be skipped because of the error.');\n      next(); // This next() will not be called as error handler takes over\n    },\n    (err, req, res, next) => { // This is an error handler middleware\n      console.error('Error MW 3 (Error Handler): Caught error:', err.message);\n      errorRes.status(400).json({ message: 'Request Error', detail: err.message });\n      next(); // Call next to complete the error handling chain, allowing finalNext to run\n    }\n  ];\n  console.log('--- Running Serial Middleware with Error Example ---');\n  await executeMW.serial(ERROR_MIDDLEWARE, errorReq, errorRes, finalNext);\n  console.log('--- Serial Middleware Finished (Error Flow) ---');\n}\n\nrunSerialExample();","lang":"typescript","description":"Demonstrates serial execution of Express-style middleware, including nested arrays and error handling. It shows how `req`, `res`, and `next` are passed as arguments to `executeMW.serial` and how errors propagate, skipping normal middleware to reach an error handler."},"warnings":[{"fix":"Ensure your middleware functions match the expected `(req, res, next)` or `(err, req, res, next)` signatures based on their intended purpose.","message":"Middleware functions are distinguished by argument count: 3 arguments `(req, res, next)` for normal middleware, and 4 arguments `(err, req, res, next)` for error-handling middleware. Incorrect argument counts will lead to unexpected behavior (e.g., an error handler being treated as normal middleware).","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Only pass an `Error` object (or an object that evaluates to true) to `next()` if you intend to trigger the error handling chain. For normal continuation, call `next()` without arguments.","message":"Calling `next(someValue)` where `someValue` is not an `Error` object will still cause `execute-middleware` to treat it as an error and trigger the error handling flow, skipping subsequent normal middleware. This mirrors Express's behavior.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always ensure that `next()` or `next(err)` is called exactly once after all asynchronous operations within a middleware function have completed, even if in a `finally` block or an error handler.","message":"Asynchronous operations within middleware (e.g., database calls, API requests) must explicitly call `next()` or `next(err)` upon completion. If `next()` is not called, the middleware chain will hang indefinitely, never progressing to the next step.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Verify your import statement. For CommonJS, use `const executeMW = require('execute-middleware');`. For ESM, use `import executeMW from 'execute-middleware';` or `import { serial } from 'execute-middleware';`.","cause":"Attempting to call `.serial` or `.concurrent` on an `executeMW` object that was not correctly imported or is `undefined`. This often happens with incorrect CommonJS `require` syntax in an ESM project or vice-versa.","error":"TypeError: (intermediate value).serial is not a function"},{"fix":"Ensure you are passing valid `req`, `res`, and `next` mock objects/functions as the second, third, and fourth arguments respectively to `executeMW.serial()` or `executeMW.concurrent()`.","cause":"The `next` argument was not provided when invoking `executeMW.serial` or `executeMW.concurrent`, or a non-function value was passed in its place. The `execute-middleware` library expects `req`, `res`, and `next` arguments after the middleware array.","error":"TypeError: next is not a function"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}