hot-patcher
v2.0.1
Published
Hot method patching framework for handling environmental method differences
Downloads
95,399
Readme
Hot-Patcher
Hot method patching framework for handling environmental method differences
About
Hot-Patcher provides a simple API to manage patched methods. I found while writing Buttercup that managing overwritten methods between environments (Node/Browser/React-Native) was becoming cumbersome, and having a single agreed-upon method of doing so was the best way to go.
Installation
Install Hot-Patcher from npm:
npm install hot-patcher --save
NB: This is an ESM library.
Usage
Hot-Patcher is a class and can simply be instantiated:
import { HotPatcher } from "hot-patcher";
const hp = new HotPatcher();
Hot-Patcher is designed to be used with patchable tools:
import { HotPatcher } from "hot-patcher";
export class MyHelper {
public patcher: HotPatcher;
constructor() {
this.patcher = new HotPatcher();
}
increment(arg: number): number {
return this.patcher.patchInline<number>("increment", someArg => {
return someArg + 1;
}, arg);
}
}
You can then patch methods when required:
import { MyHelper } from "./MyHelper.js";
export function getHelper() {
const helper = new MyHelper();
helper.patch("increment", (val: number) => val + 2);
return helper;
}
Patched methods can easily be fetched later:
import { getSharedPatcher } from "./patching.js";
const randomString = getSharedPatcher().get("randomString");
randomString(5); // Generates a random string
// Or, execute the method directly:
getSharedPatcher().execute("randomString", 5) // Generates a random string
You can check if a method is patched by using isPatched
: patcher.isPatched("some method")
.
Inline patching and execution
Ideally you could wrap function implementation with a patch call, executing it on demand:
function add(a: number, b: number): number {
return patcher.patchInline("add", (a, b) => a + b, a, b);
}
patcher.isPatched("add"); // false
add(1, 2); // 3
patcher.isPatched("add"); // true
// calling add() multiple times will call the patched method without "re-patching" it
// over and over again..
Plugins - Chaining/Sequencing functions
You can use Hot-Patcher to create sequences of functions:
patcher.plugin("increment", x => x * 2, x => x * 2);
patcher.execute("increment", 2); // 8
Which is basically syntactic sugar for a regular patch()
call:
patcher
.patch("increment", x => x * 2, { chain: true })
.patch("increment", x => x * 2, { chain: true });
patcher.execute("increment", 2); // 8
Executing a regular patch()
without chain: true
will overwrite all chained methods with the new method.
Calling patch()
with chain: true
when a method already exists will simply add the new method after the existing:
patcher
.patch("increment", x => x * 2, { chain: false }) // or simply without `chain` specified
.patch("increment", x => x * 2, { chain: true });
patcher.execute("increment", 2); // still 8
Restoring methods
Methods can be restored to their originally patched function by calling the restore
method:
const methodA = () => {};
const methodB = () => {};
patcher
// methodA is now the current (and original)
.patch("someMethod", methodA)
// methodB is now the current
.patch("someMethod", methodB);
// Restore "someMethod" to methodA (original)
patcher.restore("someMethod");
Use Sparingly
The intention of Hot-Patcher is not to push every method into a patching instance, but to provide a common API for specific methods which require patching in some specific environments or in situations where users/consumers are expected to provide their own custom implementations.