{"id":15093,"library":"catering","title":"Callback/Promise Catering Utility","description":"catering is a lightweight utility designed to enable JavaScript modules to be consumed seamlessly using both traditional Node.js-style callbacks and modern Promises. It provides `fromCallback` to wrap internal callback-based logic for promise consumption and `fromPromise` to adapt promise-based logic for callback consumption. The package is currently at version 2.1.1 and appears to be in active maintenance, receiving updates as needed. Its primary differentiator is its focused approach to providing this dual-consumption pattern without imposing a heavy dependency footprint. It explicitly handles error propagation in `fromPromise` by calling the callback in a `queueMicrotask` to prevent errors from being caught by the promise chain, ensuring clear error reporting to the consumer. It is suitable for both Node.js (>=6) and browser environments, and ships with TypeScript types.","status":"active","version":"2.1.1","language":"javascript","source_language":"en","source_url":"https://github.com/vweevers/catering","tags":["javascript","callback","promise","promisify","typescript"],"install":[{"cmd":"npm install catering","lang":"bash","label":"npm"},{"cmd":"yarn add catering","lang":"bash","label":"yarn"},{"cmd":"pnpm add catering","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ESM is preferred. CommonJS `require` is also supported.","wrong":"const { fromCallback } = require('catering')","symbol":"fromCallback","correct":"import { fromCallback } from 'catering'"},{"note":"ESM is preferred. CommonJS `require` is also supported.","wrong":"const { fromPromise } = require('catering')","symbol":"fromPromise","correct":"import { fromPromise } from 'catering'"},{"note":"The `kPromise` symbol is used internally by `fromCallback` to attach the promise instance. While exported, direct use is uncommon.","wrong":"const { kPromise } = require('catering')","symbol":"kPromise","correct":"import { kPromise } from 'catering'"},{"note":"For Node.js CommonJS modules, destructuring `require('catering')` is the standard way to get exported utilities.","symbol":"Module (CommonJS)","correct":"const { fromCallback, fromPromise } = require('catering')"}],"quickstart":{"code":"import { fromCallback, fromPromise } from 'catering';\n\nconst kPromise = Symbol('promise');\n\n// Example: Internally uses callbacks\nfunction createCallbackModule(callback) {\n  callback = fromCallback(callback, kPromise);\n  setTimeout(() => {\n    // Simulate async operation\n    if (Math.random() > 0.5) {\n      callback(null, 'Data from callback source');\n    } else {\n      callback(new Error('Failed to get callback data'));\n    }\n  }, 100);\n  return callback[kPromise];\n}\n\n// Example: Internally uses promises\nfunction createPromiseModule(callback) {\n  const promise = new Promise((resolve, reject) => {\n    setTimeout(() => {\n      // Simulate async operation\n      if (Math.random() > 0.5) {\n        resolve('Data from promise source');\n      } else {\n        reject(new Error('Failed to get promise data'));\n      }\n    }, 100);\n  });\n  return fromPromise(promise, callback);\n}\n\nasync function runExamples() {\n  console.log('--- Callback Module Example ---');\n  try {\n    const result = await createCallbackModule();\n    console.log('Async/await result:', result);\n  } catch (error) {\n    console.error('Async/await error:', error.message);\n  }\n\n  createCallbackModule((err, result) => {\n    if (err) console.error('Callback error:', err.message);\n    else console.log('Callback result:', result);\n  });\n\n  console.log('\\n--- Promise Module Example ---');\n  try {\n    const result = await createPromiseModule();\n    console.log('Async/await result:', result);\n  } catch (error) {\n    console.error('Async/await error:', error.message);\n  }\n\n  createPromiseModule((err, result) => {\n    if (err) console.error('Callback error:', err.message);\n    else console.log('Callback result:', result);\n  });\n}\n\nrunExamples();","lang":"typescript","description":"Demonstrates how to create modules that internally use either callbacks or promises, and how `catering` enables them to be consumed with both `async/await` and traditional Node.js callbacks."},"warnings":[{"fix":"Ensure `return callback[kPromise]` is the last statement in your module's function when using `fromCallback`.","message":"When using `fromCallback`, the `kPromise` symbol must be passed and returned to correctly expose the Promise API. Forgetting to return `callback[kPromise]` will result in a module that only supports callbacks.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Handle errors delivered to the callback via the `(err, result)` signature. Do not rely on `.catch()` on the promise returned by `fromPromise` to handle errors for the callback path.","message":"The `fromPromise` function internally calls the provided callback in a `queueMicrotask` (or equivalent next tick behavior). This is intentional to \"escape the promise chain\" and prevent promise rejections from implicitly catching errors that should go directly to the callback. This means callback errors are not catchable by a `.catch()` attached to the promise returned by `fromPromise`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Upgrade to a current Node.js LTS version (e.g., Node.js 18 or 20) for optimal compatibility and security.","message":"While `catering` supports older Node.js versions (>=6), it is generally recommended to use modern Node.js environments (LTS or current) to benefit from performance improvements, security patches, and full ES module support.","severity":"gotcha","affected_versions":"<=12.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure `return callback[kPromise]` is present at the end of the module's function when using `fromCallback` to expose the promise interface.","cause":"The module wrapped with `fromCallback` was called without returning `callback[kPromise]`, causing the promise-based consumption to receive `undefined`.","error":"TypeError: Cannot read properties of undefined (reading 'then')"},{"fix":"Ensure that if your module's function accepts a `callback` argument, you either pass a function or `undefined` (if the consumer intends to use promises). `catering` handles the `undefined` case for promise consumption.","cause":"When defining a module using `fromPromise` or `fromCallback`, the first argument `callback` is expected to be a function if the user is consuming it with a callback. If it's `undefined` or not a function and the internal logic attempts to call it directly (before `fromCallback` or `fromPromise` has processed it), this error can occur.","error":"Error: callback is not a function"}],"ecosystem":"npm"}