{"id":12021,"library":"shimmer","title":"Safe Monkeypatching for JavaScript","description":"The `shimmer` package (version 1.2.1) is a JavaScript utility designed for safe monkeypatching of functions, primarily within Node.js CommonJS environments. It provides a set of tools, including `wrap`, `massWrap`, `unwrap`, and `massUnwrap`, to intercept and augment the behavior of existing functions on objects or entire modules. The library's core philosophy is to add behavior around an original function, rather than replacing it, and includes important guidelines for maintaining function integrity (e.g., preserving return values, not altering async/sync nature). Released approximately seven years ago, its current status suggests it is in maintenance mode rather than active development. It differentiates itself by providing explicit safety mechanisms and logging for potential issues during monkeypatching, defaulting to `console.error` for non-throwing error reporting. This makes it suitable for extending or observing existing Node.js module functionality with reduced risk compared to direct function reassignment.","status":"maintenance","version":"1.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/othiym23/shimmer","tags":["javascript","monkeypatch","swizzle","wrapping","danger","hmm","shim"],"install":[{"cmd":"npm install shimmer","lang":"bash","label":"npm"},{"cmd":"yarn add shimmer","lang":"bash","label":"yarn"},{"cmd":"pnpm add shimmer","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primarily designed for CommonJS. While `import shimmer from 'shimmer'` might work with bundlers or specific Node.js configurations, it's not the intended or officially supported import style for this older library version.","symbol":"shimmer","correct":"const shimmer = require('shimmer');"},{"note":"`wrap` is a method on the default `shimmer` export. Ensure you import the main `shimmer` object first.","wrong":"import { wrap } from 'shimmer'; // Not directly exported as named export","symbol":"shimmer.wrap","correct":"const shimmer = require('shimmer');\nshimmer.wrap(targetModule, 'methodName', function (original) { /* ... */ });"},{"note":"`unwrap` is a method on the default `shimmer` export. It restores the function to its state before `shimmer` patched it, logging if another patch is present or if double-unwrapping occurs.","wrong":"import { unwrap } from 'shimmer'; // Not directly exported as named export","symbol":"shimmer.unwrap","correct":"const shimmer = require('shimmer');\nshimmer.unwrap(targetModule, 'methodName');"},{"note":"This allows configuring the logger used by shimmer. It returns a new shimmer instance with the provided options. The default logger is `console.error`.","wrong":"import shimmer from 'shimmer'; shimmer({ logger: myCustomLogger }); // ESM import might not initialize the configurable instance correctly without CJS interop","symbol":"shimmer(options)","correct":"const shimmer = require('shimmer');\nconst customShimmer = shimmer({ logger: myCustomLogger });"}],"quickstart":{"code":"const http = require('http');\nconst shimmer = require('shimmer');\n\nconsole.log('Original http.request is:', http.request.__wrapped ? 'wrapped' : 'not wrapped');\n\nshimmer.wrap(http, 'request', function (original) {\n  return function () {\n    console.log('>>> Intercepting http.request: Starting request!');\n    const args = Array.from(arguments);\n    const options = typeof args[0] === 'string' ? new URL(args[0]) : args[0];\n    console.log('    Request options:', options);\n    const returned = original.apply(this, arguments);\n    console.log('<<< Intercepting http.request: Done setting up request.');\n    return returned;\n  };\n});\n\nconsole.log('Patched http.request is:', http.request.__wrapped ? 'wrapped' : 'not wrapped');\n\n// Example usage to trigger the wrapped function\nconst req = http.request('http://www.google.com', (res) => {\n  console.log(`STATUS: ${res.statusCode}`);\n  res.setEncoding('utf8');\n  res.on('data', (chunk) => {\n    // console.log(`BODY: ${chunk}`);\n  });\n  res.on('end', () => {\n    console.log('No more data in response.');\n  });\n});\n\nreq.on('error', (e) => {\n  console.error(`problem with request: ${e.message}`);\n});\n\nreq.end();\n\n// Clean up\nshimmer.unwrap(http, 'request');\nconsole.log('Unwrapped http.request is:', http.request.__wrapped ? 'wrapped' : 'not wrapped');","lang":"javascript","description":"This example demonstrates how to use `shimmer.wrap` to intercept and log details of `http.request` calls in Node.js, and then `shimmer.unwrap` to restore the original function."},"warnings":[{"fix":"For new projects, consider alternatives or carefully test `shimmer` in your specific environment. Evaluate if monkeypatching is truly necessary, as it can lead to fragile code.","message":"This library is an older package (last updated ~7 years ago) and is not actively maintained. Compatibility with very recent Node.js versions or complex ESM setups may not be guaranteed without specific workarounds.","severity":"breaking","affected_versions":"<=1.2.1"},{"fix":"Ensure you fully understand the implications of modifying core module behavior. Use it only when no other extension point (e.g., events, dependency injection) is available.","message":"Monkeypatching is inherently risky. The library includes a 'mandatory disclaimer' that modifying runtime behavior on the fly is rarely a good idea and should only be done out of necessity, not for fun.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always include `original.apply(this, arguments)` in your wrapper to ensure the original functionality is executed, capturing and returning its result. Forgetting this will likely break the patched function.","message":"When providing a `wrapper` function, you *must* call the `original.apply(this, arguments)` unless you are intentionally transforming arguments or replacing the function's logic.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure your wrapper returns `original.apply(this, arguments)` or the result of processing its return value. Example: `const result = original.apply(this, arguments); return result;`","message":"Always capture and return the return value from the `original` function within your `wrapper`. Ignoring it can lead to unexpected behavior later, especially with callbacks or promise-based APIs.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Maintain the original function's synchronous or asynchronous nature. If it was async, your wrapper should also handle its asynchronous return (e.g., promises, callbacks).","message":"Do not change an asynchronous function to be synchronous or vice versa within your `wrapper`. This fundamentally alters the contract of the original function and can cause significant issues in consuming code.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Configure a custom logger via `shimmer({ logger: myCustomLogger })` for more controlled error handling or to integrate with your application's logging infrastructure. Regularly check logs for `shimmer`-related messages.","message":"`shimmer` defaults to logging failures via `console.error` rather than throwing exceptions, making it unobtrusive but potentially masking immediate errors.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Be aware of the order of monkeypatching in your application. If multiple libraries patch the same function, the last one to patch will be the active one, and `shimmer.unwrap` may not fully restore the original behavior if it's not the last layer.","message":"`shimmer.unwrap` will not unwrap a function if it has been monkeypatched by another library *after* your `shimmer` patch, and it will only log this event.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure your `wrapper` function signature is `function (original) { return function () { /* ... */ original.apply(this, arguments); } }` and that `name` points to an actual function on the `nodule`.","cause":"The `wrapper` function did not correctly receive or invoke the `original` function, or the `name` provided to `shimmer.wrap` referred to a non-function property.","error":"TypeError: original.apply is not a function"},{"fix":"Run `npm install shimmer` or `yarn add shimmer` to install the package.","cause":"The `shimmer` package is not installed or the Node.js runtime cannot locate it.","error":"Error: Cannot find module 'shimmer'"},{"fix":"Add `const shimmer = require('shimmer');` at the top of your file to import the module in CommonJS environments.","cause":"The `shimmer` module was not imported or required correctly before use.","error":"ReferenceError: shimmer is not defined"}],"ecosystem":"npm"}