diff --git a/@vates/decorate-with/README.md b/@vates/decorate-with/README.md index 45e5efb78..0a52f6783 100644 --- a/@vates/decorate-with/README.md +++ b/@vates/decorate-with/README.md @@ -70,6 +70,25 @@ decorateMethodsWith(Foo, { }) ``` +### `perInstance(fn, ...args)` + +Helper to decorate the method by instance instead of for the whole class. + +This is often necessary for caching or deduplicating calls. + +```js +import { perInstance } from '@vates/decorateWith' + +class Foo { + @decorateWith(perInstance, lodash.memoize) + bar() { + // body + } +} +``` + +Because it's a normal function, it can also be used with `decorateMethodsWith`, with `compose` or even by itself. + ## Contributions Contributions are _very_ welcomed, either on the documentation or on diff --git a/@vates/decorate-with/USAGE.md b/@vates/decorate-with/USAGE.md index bcde95c76..583b81d0c 100644 --- a/@vates/decorate-with/USAGE.md +++ b/@vates/decorate-with/USAGE.md @@ -51,3 +51,22 @@ decorateMethodsWith(Foo, { ]) }) ``` + +### `perInstance(fn, ...args)` + +Helper to decorate the method by instance instead of for the whole class. + +This is often necessary for caching or deduplicating calls. + +```js +import { perInstance } from '@vates/decorateWith' + +class Foo { + @decorateWith(perInstance, lodash.memoize) + bar() { + // body + } +} +``` + +Because it's a normal function, it can also be used with `decorateMethodsWith`, with `compose` or even by itself. diff --git a/@vates/decorate-with/index.js b/@vates/decorate-with/index.js index 8c63013ef..9c4003866 100644 --- a/@vates/decorate-with/index.js +++ b/@vates/decorate-with/index.js @@ -19,3 +19,15 @@ exports.decorateMethodsWith = function decorateMethodsWith(klass, map) { } return klass } + +exports.perInstance = function perInstance(fn, decorator, ...args) { + const map = new WeakMap() + return function () { + let decorated = map.get(this) + if (decorated === undefined) { + decorated = decorator(fn, ...args) + map.set(this, decorated) + } + return decorated.apply(this, arguments) + } +}