first commit

This commit is contained in:
Missdrop
2025-07-16 16:30:56 +00:00
commit 7ee33927cb
11326 changed files with 1230901 additions and 0 deletions

6
node_modules/moize/.prettierrc.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
trailingComma: 'es5',
semi: true,
singleQuote: true,
tabWidth: 4,
};

18
node_modules/moize/.release-it.beta.json generated vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"github": {
"release": true
},
"npm": {
"tag": "next"
},
"preReleaseId": "beta",
"hooks": {
"before:init": [
"npm run lint",
"npm run typecheck",
"npm run test",
"npm run dist",
"npm run copy:mjs"
]
}
}

21
node_modules/moize/.release-it.json generated vendored Normal file
View File

@@ -0,0 +1,21 @@
{
"github": {
"release": true,
"tagName": "v${version}"
},
"hooks": {
"before:init": [
"npm run lint",
"npm run typecheck",
"npm run test",
"npm run dist",
"npm run copy:mjs"
],
"before:release": [
"npm run docs",
"git add .",
"git commit -m 'Update docs'",
"git push"
]
}
}

527
node_modules/moize/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,527 @@
# moize CHANGELOG
## 6.1.6
- [#196](https://github.com/planttheidea/moize/issues/196) - Fix `mjs` typing not flowing through due to deep-linking ignoring `index.d.ts`
## 6.1.5
- [#186](https://github.com/planttheidea/moize/issues/186) - Avoid type issues when using in project where React is unused
## 6.1.4
- [#184](https://github.com/planttheidea/moize/issues/184) - Fix pass-through typing for `micro-memoize` dependency
## 6.1.3
- [#179](https://github.com/planttheidea/moize/issues/179) - Invalid types for namespace methods which give the impression that chaining of those methods is possible
## 6.1.2
- [#176](https://github.com/planttheidea/moize/issues/176) - Remove use of `new Error().stack` in derivation of fallback `profileName`, due to potential for OOM crashes in specific scenarios
## 6.1.1
- Update `fast-equals` to latest major version
## 6.1.0
- [#161](https://github.com/planttheidea/moize/issues/161) - Provide custom function name when supported
## 6.0.3
- [#153](https://github.com/planttheidea/moize/issues/153) - Fix ESM/CommonJS cross-compatibility issues in NextJS
## 6.0.2
- Update dependencies to latest (`fast-equals` in particular to prevent surfacing of [an issue it faced](https://github.com/planttheidea/fast-equals/pull/41))
## 6.0.1
- [#146](https://github.com/planttheidea/moize/issues/146) - Fix reading deprecated properties on function object
## 6.0.0
**BREAKING CHANGES**
- `moize` v5 and below had a default cache size of `Infinity`, however starting with v6 the default cache size will be `1`. If you want to maintain a cache history of multiple entries, it is recommended to use `moize.maxSize` to set the size of history desired. To replicate usage from v5 and below, use `moize.infinite`.
- `isReact` option and `moize.react` shorthand method now memoizes on a per-instance basis (previously shared cache across all instances).
- `moize.simple` and `moize.reactSimple` have been removed due to default cache size being 1.
- `isSerialized` option and `moize.serialize` shorthand method will now serialize functions by default.
- `shouldSerializeFunctions` option has been removed, as serializing functions is now the default.
- `equals` option has been renamed to `matchesArg` for alignment with `matchesKey`.
**ENHANCEMENTS**
- New options:
- `isShallowEqual` (compares each arg in the `key` based on shallow equality)
- `updateCacheForKey` (if truthy value returned, will update the cached value for the given `key`)
- New shorthand methods:
- `moize.infinite` (shorthand for `maxSize` option set to `Infinity`)
- `moize.matchesArg` (shorthand for `matchesArg` option)
- `moize.matchesKey` (shorthand for `matchesKey` option)
- `moize.serializeWith` (shorthand for `isSerialized` and `serializer` option)
- `moize.shallow` (shorthand for `isShallowEqual` option)
- `moize.transformArgs` (shorthand for `transformArgs` option)
- `moize.updateCacheForKey` (shorthand for `updateCacheForKey` option)
**INTERNALS**
- Rewritten in TypeScript, with much better type declarations.
- Changed unit test framework to `jest`
- Used latest external dependencies for better ESM support in Node 14
## 5.4.7
- Fix ESM usage in NodeJS 14 [#128](https://github.com/planttheidea/moize/issues/128) (thanks [@tozz](https://github.com/tozz))
## 5.4.6
- Fix issue where `setTimeout` causes processes to hang in NodeJS [#122](https://github.com/planttheidea/moize/issues/122)
## 5.4.5
- Improve TypeScript typings
## 5.4.4
- Fix export in TypeScript declarations([#105](https://github.com/planttheidea/moize/pull/105))
## 5.4.3
- Improve typings for TypeScript ([#103](https://github.com/planttheidea/moize/pull/103))
## 5.4.2
- Ignore when `maxArgs` or `maxSize` arguments are negative
## 5.4.1
- Upgrade to `babel@7`
- Add `"sideEffects": false` to `package.json` for better tree-shaking in `webpack`
## 5.4.0
- Add ESM support for NodeJS with separate [`.mjs` extension](https://nodejs.org/api/esm.html) exports
## 5.3.2
**BUGFIXES**
- Bump `micro-memoize` dependency to fix recursive race condition issue
## 5.3.1
**BUGFIXES**
- Clean up logic surrounding `update` function to not unnecessarily assign the value twice
## 5.3.0
**NEW FEATURES**
- Add the [`moized.update`](README.md#updatekey-value) method for direct cache manipulation
## 5.2.3
**BUGFIXES**
- Actually fix the issue that `5.2.2` was supposed to fix (appreciate the persistence [@vlad-zhukov](https://github.com/vlad-zhukov))
## 5.2.2
**BUGFIXES**
- Fix issue where manually removing a key from `cache` would not clear / remove the expiration timeout
## 5.2.1
**BUGFIXES**
- Fix `Object.assign` usage on functions (derp)
## 5.2.0
**NEW FEATURES**
- Add `collectStats` as a convenience method on the main `moize` object
**BUGFIXES**
- Fix naming convention for determining if statistics are being collected on the `moize`d function (`isCollectingStats` now, was mistakenly `collectStats` before)
## 5.1.2
**BUGFIXES**
- Reference the correct option name for `micro-memoize` (isMatchingKey) instead of `moize` (matchesKey) for instance methods (oops)
## 5.1.1
**BUGFIXES**
- Ensure instance methods that update the cache work correctly with new `matchesKey` option
## 5.1.0
**NEW FEATURES**
- Add [`matchesKey`](#matcheskey) option
- Change `isSerialized` to use `matchesKey` with custom `isMatchingKey` instead of standard `isEqual`
**BUGFIXES**
- Prevent `isDeepEqual` from being passed to the `micro-memoize` options
## 5.0.1
- Include `fast-equals` as an explicit dependency
## 5.0.0
- Complete refactor to leverage [`micro-memoize`](https://github.com/planttheidea/micro-memoize) under the hood (doubles the speed, and allows for more functionality)
**BREAKING CHANGES**
- The default `equals` option now uses [SameValueZero](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) equality instead of strict equality
- `equals` option is now performed iteratively on each argument in the key, rather on the key as a whole
- `matchesKey` option now performs the full-key comparison that `equals` did in v4
- `serialize` option has been changed to `isSerialized`
- `serializeFunctions` option has been changed to `shouldSerializeFunctions`
- CommonJS consumers must now use `require('moize').default`
- The shape of the `cache` object has changed
- If you were modifying it directly instead of using the [convenience methods](#direct-cache-manipulation), you may experience breakages
- `moize.promise` now sets both `isPromise` and `updateExpire` options (v4 and below only set `isPromise`)
- When `isPromise` is `true` and a `maxAge` is applied, the `maxAge` now begins when the function is created rather than the resolution of the promise
- If you want the `maxAge` to apply upon resolution, then either set the `updateExpire` option or use the `moize.promise` convenience method
**NEW FEATURES**
- Deep equality now available without custom `equals` function (either [`isDeepEqual`](README.md#isdeepequal) option, or [`moize.deep`](README.md#moizedeep) convenience method)
- Statistics can now be collected for both global and method-specific contexts (see [Collecting statistics](#collecting-statistics) and [`profileName`](README.md#profilename))
- Statistics-based introspection methods exist to support reading stats
- [`getStats`](README.md#getstats) will get the stats for the `profileName` passed, or if none is passed then gets the global stats
- [`isCollectingStats`](README.md#iscollectingstats) returns whether stats are being collected
- Cache change listeners are now available to listen for changes
- [`onCacheAdd`](README.md#oncacheadd) will fire when a new entry is added to the cache
- [`onCacheChange`](README.md#oncachechange) will fire when the cache is added to or the LRU order has changed
- [`onCacheHit`](README.md#oncachehit) will fire when an existing entry in cache is used
**BUGFIXES**
- `isPromise` methods that resolved had the values re-wrapped in a new promise, which obfuscated chaining on the method (now the original promise is maintained)
- Internal de-circularizer for serialized methods was flaky in deeply-nested scenarios (now uses [`json-stringify-safe`](https://github.com/moll/json-stringify-safe))
**DEPRECATIONS**
- `promiseLibrary` is no longer a supported option (it is no longer needed, as the original promise is now maintained)
## 4.0.4
- Add `default` property to `moize` which points to itself, allowing TypeScript to import correctly as an ES module
## 4.0.3
- Fix issue where items manually added to cache did not have the same options (`maxAge`, `maxSize`, etc.) applied to them as those added to cache through function call
## 4.0.2
- Remove duplicate internal method
## 4.0.1
- Update issue where `onExpire` was firing prior to removal of the key from cache
## 4.0.0
- Add programmatic update of expiration based on return from `onExpire`
**BREAKING CHANGES**
- `onExpire` will update the expiration if `false` is returned
- In prior versions, the return of `onExpire` was ignored entirely
## 3.5.0
- Add `updateExpire` option, which if true will reset the expiration countdown based on `maxAge` when a cached value for that key has been hit
- Update TypeScript typings (thanks @Joshuaweiss)
## 3.4.2
- Remove unneeded constants declarations for smaller footprint
## 3.4.1
- Remove code duplication and unnecessary cache key segregation (reduced library size by ~10.6%)
- Improve Flow typings (no longer driven off of TypeScript typings)
## 3.4.0
- Add `onExpire` callback that fires when a cache item expires
## 3.3.1
- Fix TypeScript definitions with correct declarations (thanks @iHaiduk)
## 3.3.0
- Add `es` transpilation in addition to standard `lib`, preserving ES2015 modules for [`pkg.module`](https://github.com/rollup/rollup/wiki/pkg.module)
## 3.2.2
- Refactor `ReactCacheKey` to double the speed (yes, double)
## 3.2.1
- Fix issue where `MultipleParameterCacheKey` and `ReactCacheKey` were not applying `equals` correctly
## 3.2.0
- Add `transformArgs` option, which allows trasformation of the arguments prior to being used as a key
## 3.1.2
- Fix `clear` referencing incorrect object
- Fix `equals` not using `matchesCustom` when used in conjunction with `serialize`
## 3.1.1
- BAD PUBLISH - do not use!
## 3.1.0
- New: add `isMoized` introspection method
- New; add FlowType declarations based on TypeScript typings
- New: add `prettier` to project, with pre-commit hooks to format the code
- Fix: only serialize key once when attempting to match in cache (was serializing on every iteration)
## 3.0.2
- Improve performance of `take` by making it a higher-order function
## 3.0.1
- Update TypeScript typings to include new `equals` option
## 3.0.0
- Improve performance of multiple parameter cache matching (~3x faster)
- Improve performance of `react` functional component cache matching (~9.5x faster)
- Improve performance of serialized parameter cache matching (~1.5x faster)
- Improve performance of use with `maxArgs`
- Add `equals` option for ability to provide custom equality comparison method
- Add `moize.reactSimple` shortcut method to limit `react` cache size to `1` (mimics the `PureComponent` optimization)
- Add `isReact` option for simpler `react` configuration via `options`
- Fix issue where `moize` was only able to curry `options` once
- Fix issue with `react` cache where different functions with identical names / body contents were seen as equal
- Fix issue where `maxArgs` was not always respected for `serialize` caches
**BREAKING CHANGES**
- Custom `cache` is no longer available in `options`
- `moize.react` now performs a shallow equal comparison of `props` and `context` instead of deep value comparison
- If you want to perform a deep value equality comparison (if you are mutation props, for example), pass a deep equality comparison method via the `equals` option such as `lodash`'s `isEqual`
- If you want to continue using the v2 version of `moize.react`, you can manually apply the options: `moize.serialize(fn, {maxArgs: 2, serializeFunctions: true})`
- The direct cache manipulation `delete` method has been renamed to `remove`
- The direct cache manipulation `hasCacheFor` method has been renamed to `has`
- The `key` passed to direct cache manipulation methods (`add`, `has`, `remove`) must now be an array
- The array reflects the arguments passed to the method (`moized.hasCacheFor('foo', 'bar')` => `moized.has(['foo', 'bar'])`)
## 2.5.1
- Surface types for TypeScript correctly
## 2.5.0
- Add TypeScript definitions (thanks [vhfmag](https://github.com/vhfmag))
- Skip unneeded first entry iteration when getting the multi-parameter key or finding the index of a key
## 2.4.1
- Make positive integer checker use regex instead of bitwise operation
## 2.4.0
- Add `hasCacheFor` method to determine if the memoized function has cache for given arguments
## 2.3.3
- Remove unneeded iterator key generator method
- Various micro-optimizations
## 2.3.2
- Add `lodash-webpack-plugin` for smaller `dist` builds
## 2.3.1
- Streamline the creation of curriable shortcuts (`moize.maxAge`, `moize.maxSize`)
- Add curriable shortcut for `moize.maxArgs` (missed in initial release)
## 2.3.0
- More options have shortcut methods
- `maxAge`
- Curried method (example: `moize.maxAge(5000)(method)`)
- `maxSize`
- Curried method (example: `moize.maxSize(5)(method)`)
- `promise` (shortcut for `isPromise: true`)
- `serialize`
- `simple` (shortcut for `maxSize: 1`)
- `moize` functions are now composable (example usage: `moize.compose(moize.react, moize.simple)`)
## 2.2.3
- Simplify internal vs custom cache recognition
- Typing and documentation cleanup
## 2.2.2
- Abstract out `promiseResolver` and `promiseRejecter` into separate testable functions
- Various code cleanups and typing enhancements
## 2.2.1
- Fix issue with `delete` checking `size` of the `Cache` before it had actually updated
## 2.2.0
- Added `promiseLibrary` option to allow use of custom promise implementation
- Bolster `isPromise` logic, auto-removing from cache when the promise is rejected
- Update README for more detailed information on both `isPromise` and `promiseLibrary` options
- Convert `Cache` key iteration to use custom iterator instead of standard loop for more stable iteration
## 2.1.6
- Code cleanup
## 2.1.5
- Fix issue where `delete` would always set the `lastItem` to `undefined` even when items still remained in cache
## 2.1.4
- Move multiple-parameter key matching to cache (allows for custom `cache` to have its own implementation)
- Update documentation for the custom `cache` implementation, as it requires `getMultiParamKey` now, plus give a better example of an alternative `cache`
- Make `keys()` and `values()` methods no-ops when cache implementation is custom
- Make `deleteItemFromCache` method safe with custom `cache` implementations
## 2.1.3
- Enhance `Cache` more for multiple-parameter functions (now benchmarks faster in all categories)
## 2.1.2
- Have `areArraysShallowEqual` use `isEqual` instead of strict equality to allow for `NaN` as key
## 2.1.1
- Optimize cache class to be more efficient in both `has` and `get` operations
- Fix issue with `delete` that was preventing delete of falsy keys
## 2.1.0
- Add `add` method on cache to allow for manual cache insertion
## 2.0.3
- Ensure `maxArgs` is respected for unserialized functions
- Change the arguments length check from `=== 1` to `>` so that zero arguments (`undefined` key) pulls from cache directly instead of tries to go through key matching for multiparam
## 2.0.2
- Prevent memoization on `moize.react` based on third parameter to functional components (object of all internal react functions)
## 2.0.1
- Fix static types applied to functional components not being applied to memoized component
## 2.0.0
- Refactor to use object equality instead of serialization (vast speed improvements over 1.x.x with multiple parameters)
**BREAKING CHANGES**
- If you were relying on the serialization (using value equality instead of object equality), it will no longer memoize (you can set `serialize: true` if you want to continue using that option)
- If you were using `moize` to memoize React components, you should change your invocations from `moize` to `moize.react` ([see README](README.md#usage-with-functional-react-components))
## 1.5.0
- Add `values` method on memoized function (gets list of computed values stored in cache)
- Fix issue with `clear` method not being present on `Cache`
## 1.4.5
- Switch to using Cache for caching instead of native Map (was previously only used for polyfilling, but is twice as fast ... I feel silly for not testing its performance prior)
- Simplify and optimize Cache to crank out as much speed as possible
## 1.4.4
- Add `displayName` property to memoized function for better display of memoized `react` components in DevTools
- Throw a `TypeError` when the parameter passed to moize is not a function
## 1.4.3
- Move internal serializer generation to utils, for further partial application leveraging
## 1.4.2
- Leverage partial functions in a number of places (less arguments passed around, improves performance by ~6%)
## 1.4.1
- Correct README error explaining `serializeFunctions` option
## 1.4.0
- Add `serializeFunctions` option
## 1.3.3
- Ensure all numeric parameters (`maxAge`, `maxArgs`, `maxSize`) are a finite positive integer
## 1.3.2
- Replace array-based decycle with Map (performance on circular objects)
## 1.3.1
- Fix README errors
## 1.3.0
- Add keys method to memoized function, to know the size and also get keys for potential deletion
- Update decycle method with modern techniques and helper functions for better circular reference performance
## 1.2.0
- Add `maxArgs` configuration option to limit the number of arguments to use in the key creation for cache
## 1.1.2
- Remove external dependencies in favor of local `Cache` and `decycle` implementation (smaller bundle size)
## 1.1.1
- Make handling of circular handling automatic by stringifying in `try` / `catch`, and remove manual `isCircular` configuration option
## 1.1.0
- Add `cycle` dependency to handle circular objects
- Add `clear` and `delete` methods on the memoized function to allow for direct cache manipulation
## 1.0.3
- Remove warning related to `map-or-similar` dependency consumption
## 1.0.2
- Remove no-longer-needed dependencies
## 1.0.1
- Remove unneeded folders and files from npm package
## 1.0.0
- Initial release

21
node_modules/moize/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Tony Quetano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1346
node_modules/moize/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

35
node_modules/moize/__tests__/compose.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import moize from '../src';
const foo = 'foo';
const bar = 'bar';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
describe('moize.compose', () => {
it('should compose the moize methods into a new method with options combined', async () => {
const maxSize = moize.maxSize(5);
const maxAge = moize.maxAge(500);
const serialize = moize.serialize;
const composedMoizer = moize.compose(maxSize, maxAge, serialize);
const composed = composedMoizer(method);
expect(composed.options).toEqual(
expect.objectContaining({
maxAge: 500,
maxSize: 5,
isSerialized: true,
})
);
composed(foo, bar);
expect(composed.cache.keys).toEqual([['|foo|bar|']]);
await new Promise((resolve) => setTimeout(resolve, 1000));
expect(composed.cache.size).toBe(0);
});
});

26
node_modules/moize/__tests__/deepEqual.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import moize from '../src';
type Arg = {
one: number;
two: {
deep: 2;
};
};
const method = jest.fn(function ({ one, two }: Arg) {
return [one, two.deep];
});
const memoized = moize.deep(method);
describe('moize.deep', () => {
it('should memoized based on the deep values', () => {
const resultA = memoized({ one: 1, two: { deep: 2 } });
const resultB = memoized({ one: 1, two: { deep: 2 } });
expect(resultA).toEqual([1, 2]);
expect(resultA).toBe(resultB);
expect(method).toHaveBeenCalledTimes(1);
});
});

437
node_modules/moize/__tests__/default.ts generated vendored Normal file
View File

@@ -0,0 +1,437 @@
import { sameValueZeroEqual } from 'fast-equals';
import microMemoize from 'micro-memoize';
import moize from '../src';
import type { Moized } from '../index.d';
const foo = 'foo';
const bar = 'bar';
const _default = 'default';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
const methodDefaulted = jest.fn(function (one: string, two = _default) {
return { one, two };
});
const memoized = moize(method);
const memoizedDefaulted = moize(methodDefaulted);
describe('moize', () => {
afterEach(() => {
jest.clearAllMocks();
memoized.clear();
memoized.clearStats();
memoizedDefaulted.clear();
memoizedDefaulted.clearStats();
moize.collectStats(false);
});
describe('main', () => {
it('should handle a standard use-case', () => {
const result = memoized(foo, bar);
expect(result).toEqual({ one: foo, two: bar });
expect(method).toHaveBeenCalled();
method.mockClear();
let newResult;
for (let index = 0; index < 10; index++) {
newResult = memoized(foo, bar);
expect(newResult).toEqual({ one: foo, two: bar });
expect(method).not.toHaveBeenCalled();
}
});
it('should handle default parameters', () => {
const result = memoizedDefaulted(foo);
expect(result).toEqual({ one: foo, two: _default });
expect(methodDefaulted).toHaveBeenCalled();
methodDefaulted.mockClear();
let newResult;
for (let index = 0; index < 10; index++) {
newResult = memoizedDefaulted(foo);
expect(newResult).toEqual({ one: foo, two: _default });
expect(methodDefaulted).not.toHaveBeenCalled();
}
});
it('should handle a curried call of options creation', () => {
const moizer = moize({ isSerialized: true })({ maxSize: 5 })({
maxAge: 1000,
});
expect(moizer).toBeInstanceOf(Function);
const moized = moizer(jest.fn());
expect(moized.options).toEqual(
expect.objectContaining({
isSerialized: true,
maxAge: 1000,
maxSize: 5,
})
);
});
it('should handle moizing an already-moized function with additional options', () => {
const moized = moize(memoized, { maxSize: 5 });
expect(moized.originalFunction).toBe(memoized.originalFunction);
expect(moized.options).toEqual({
...memoized.options,
maxSize: 5,
});
});
it('should copy static properties from the source function', () => {
const fn = (a: any, b: any) => [a, b];
fn.foo = 'bar';
const memoized = moize(fn);
expect(memoized.foo).toBe(fn.foo);
});
});
describe('cache manipulation', () => {
it('should add an entry to cache if it does not exist', () => {
memoized(foo, bar);
const value = 'something else';
memoized.set([bar, foo], value);
expect(memoized.cacheSnapshot).toEqual({
keys: [[bar, foo]],
size: 1,
values: [value],
});
});
it('should add an entry to cache and remove the oldest one', () => {
const singleMemoized = moize(method);
singleMemoized(foo, bar);
const value = 'something else';
singleMemoized.set([bar, foo], value);
expect(singleMemoized.cacheSnapshot).toEqual({
keys: [[bar, foo]],
size: 1,
values: [value],
});
});
it('should notify of cache manipulation when adding', () => {
// eslint-disable-next-line prefer-const
let withNotifiers: Moized<typeof memoized>;
const onCacheOperation = jest.fn(function (cache, options, moized) {
expect(cache).toBe(withNotifiers.cache);
expect(options).toBe(withNotifiers.options);
expect(moized).toBe(withNotifiers);
});
withNotifiers = moize(memoized, {
onCacheAdd: onCacheOperation,
onCacheChange: onCacheOperation,
});
withNotifiers(foo, bar);
const value = 'something else';
withNotifiers.set([bar, foo], value);
expect(withNotifiers.cacheSnapshot).toEqual({
keys: [[bar, foo]],
size: 1,
values: [value],
});
expect(withNotifiers.options.onCacheAdd).toHaveBeenCalled();
expect(withNotifiers.options.onCacheChange).toHaveBeenCalled();
});
it('should update an entry to cache if it exists', () => {
memoized(foo, bar);
const value = 'something else';
memoized.set([foo, bar], value);
expect(memoized.cacheSnapshot).toEqual({
keys: [[foo, bar]],
size: 1,
values: [value],
});
});
it('should notify of cache manipulation when updating', () => {
const withNotifiers = moize(memoized, {
onCacheChange: jest.fn(function (cache, options, moized) {
expect(cache).toBe(withNotifiers.cache);
expect(options).toBe(withNotifiers.options);
expect(moized).toBe(withNotifiers);
}),
});
withNotifiers(foo, bar);
const value = 'something else';
withNotifiers.set([foo, bar], value);
expect(withNotifiers.cacheSnapshot).toEqual({
keys: [[foo, bar]],
size: 1,
values: [value],
});
expect(withNotifiers.options.onCacheChange).toHaveBeenCalled();
});
it('should get the entry in cache if it exists', () => {
const result = memoized(foo, bar);
expect(memoized.get([foo, bar])).toBe(result);
expect(memoized.get([bar, foo])).toBe(undefined);
});
it('should correctly identify the entry in cache if it exists', () => {
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
expect(memoized.has([bar, foo])).toBe(false);
});
it('should remove the entry in cache if it exists', () => {
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
const result = memoized.remove([foo, bar]);
expect(memoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
});
it('should not remove the entry in cache if does not exist', () => {
memoized(foo, bar);
expect(memoized.has([bar, foo])).toBe(false);
const result = memoized.remove([bar, foo]);
expect(memoized.has([bar, foo])).toBe(false);
expect(memoized.has([foo, bar])).toBe(true);
expect(result).toBe(false);
});
it('should notify of cache change on removal and clear the expiration', () => {
const expiringMemoized = moize(method, {
maxAge: 2000,
onCacheChange: jest.fn(),
});
expiringMemoized(foo, bar);
expect(expiringMemoized.has([foo, bar])).toBe(true);
expect(expiringMemoized.expirations.length).toBe(1);
const result = expiringMemoized.remove([foo, bar]);
expect(expiringMemoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
expect(expiringMemoized.options.onCacheChange).toHaveBeenCalledWith(
expiringMemoized.cache,
expiringMemoized.options,
expiringMemoized
);
expect(expiringMemoized.expirations.length).toBe(0);
});
it('should clear the cache', () => {
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
const result = memoized.clear();
expect(memoized.cache.size).toBe(0);
expect(memoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
});
it('should notify of the cache change on clear', () => {
const changeMemoized = moize(method, {
onCacheChange: jest.fn(),
});
changeMemoized(foo, bar);
expect(changeMemoized.has([foo, bar])).toBe(true);
const result = changeMemoized.clear();
expect(memoized.cache.size).toBe(0);
expect(changeMemoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
expect(changeMemoized.options.onCacheChange).toHaveBeenCalledWith(
changeMemoized.cache,
changeMemoized.options,
changeMemoized
);
});
it('should have the keys and values from cache', () => {
memoized(foo, bar);
const cache = memoized.cacheSnapshot;
expect(memoized.keys()).toEqual(cache.keys);
expect(memoized.values()).toEqual(cache.values);
});
it('should allow stats management of the method', () => {
moize.collectStats();
const profiled = moize(memoized, { profileName: 'profiled' });
profiled(foo, bar);
profiled(foo, bar);
profiled(foo, bar);
profiled(foo, bar);
expect(profiled.getStats()).toEqual({
calls: 4,
hits: 3,
usage: '75.0000%',
});
profiled.clearStats();
expect(profiled.getStats()).toEqual({
calls: 0,
hits: 0,
usage: '0.0000%',
});
});
});
describe('properties', () => {
it('should have the micro-memoize options', () => {
const mmResult = microMemoize(method, { maxSize: 1 });
const { isEqual, ...options } = memoized._microMemoizeOptions;
const { isEqual: _isEqualIgnored, ...resultOptions } =
mmResult.options;
expect(options).toEqual(resultOptions);
expect(isEqual).toBe(sameValueZeroEqual);
});
it('should have cache and cacheSnapshot', () => {
memoized(foo, bar);
expect(memoized.cache).toEqual(
expect.objectContaining({
keys: [[foo, bar]],
values: [{ one: foo, two: bar }],
})
);
expect(memoized.cache.size).toBe(1);
expect(memoized.cacheSnapshot).toEqual(
expect.objectContaining({
keys: [[foo, bar]],
values: [{ one: foo, two: bar }],
})
);
expect(memoized.cacheSnapshot.size).toBe(1);
});
it('should have expirations and expirationsSnapshot', () => {
const expiringMemoized = moize(method, {
maxAge: 2000,
});
expiringMemoized(foo, bar);
expect(expiringMemoized.expirations).toEqual([
expect.objectContaining({
expirationMethod: expect.any(Function),
key: [foo, bar],
timeoutId: expect.any(Number),
}),
]);
expect(expiringMemoized.expirationsSnapshot).toEqual([
expect.objectContaining({
expirationMethod: expect.any(Function),
key: [foo, bar],
timeoutId: expect.any(Number),
}),
]);
});
it('should have the original function', () => {
expect(memoized.originalFunction).toBe(method);
});
});
describe('edge cases', () => {
it('should have a self-referring `default` property for mixed ESM/CJS environments', () => {
// @ts-ignore - `default` is not surfaced because it exists invisibly for edge-case import cross-compatibility
expect(moize.default).toBe(moize);
});
it('should prefer the `profileName` when provided', () => {
function myNamedFunction() {}
const memoized = moize(myNamedFunction, {
profileName: 'custom profile name',
});
expect(memoized.name).toBe('moized(custom profile name)');
});
it('should wrap the original function name', () => {
function myNamedFunction() {}
const memoized = moize(myNamedFunction);
expect(memoized.name).toBe('moized(myNamedFunction)');
});
it('should have an ultimate fallback for an anonymous function', () => {
const memoized = moize(() => {});
expect(memoized.name).toBe('moized(anonymous)');
});
});
});

436
node_modules/moize/__tests__/infinite.ts generated vendored Normal file
View File

@@ -0,0 +1,436 @@
import { sameValueZeroEqual } from 'fast-equals';
import microMemoize from 'micro-memoize';
import moize from '../src';
import type { Moized } from '../index.d';
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
const _default = 'default';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
const methodDefaulted = jest.fn(function (one: string, two = _default) {
return { one, two };
});
const memoized = moize.infinite(method);
const memoizedDefaulted = moize.infinite(methodDefaulted);
describe('moize', () => {
afterEach(() => {
jest.clearAllMocks();
memoized.clear();
memoized.clearStats();
memoizedDefaulted.clear();
memoizedDefaulted.clearStats();
moize.collectStats(false);
});
describe('main', () => {
it('should handle a standard use-case', () => {
const result = memoized(foo, bar);
expect(result).toEqual({ one: foo, two: bar });
expect(method).toHaveBeenCalled();
method.mockClear();
let newResult;
for (let index = 0; index < 10; index++) {
newResult = memoized(foo, bar);
expect(newResult).toEqual({ one: foo, two: bar });
expect(method).not.toHaveBeenCalled();
}
});
it('should handle default parameters', () => {
const result = memoizedDefaulted(foo);
expect(result).toEqual({ one: foo, two: _default });
expect(methodDefaulted).toHaveBeenCalled();
methodDefaulted.mockClear();
let newResult;
for (let index = 0; index < 10; index++) {
newResult = memoizedDefaulted(foo);
expect(newResult).toEqual({ one: foo, two: _default });
expect(methodDefaulted).not.toHaveBeenCalled();
}
});
it('should handle a curried call of options creation', () => {
const moizer = moize({ isSerialized: true })({ maxSize: 5 })({
maxAge: 1000,
});
expect(moizer).toBeInstanceOf(Function);
const moized = moizer(jest.fn());
expect(moized.options).toEqual(
expect.objectContaining({
isSerialized: true,
maxAge: 1000,
maxSize: 5,
})
);
});
it('should handle moizing an already-moized function with additional options', () => {
const moized = moize(memoized, { maxSize: 5 });
expect(moized.originalFunction).toBe(memoized.originalFunction);
expect(moized.options).toEqual({
...memoized.options,
maxSize: 5,
});
});
});
describe('cache manipulation', () => {
it('should add an entry to cache if it does not exist', () => {
memoized(foo, bar);
const value = 'something else';
memoized.set([bar, foo], value);
expect(memoized.cacheSnapshot).toEqual({
keys: [
[bar, foo],
[foo, bar],
],
size: 2,
values: [value, { one: foo, two: bar }],
});
});
it('should add an entry to cache and remove the oldest one', () => {
const singleMemoized = moize(method);
singleMemoized(foo, bar);
const value = 'something else';
singleMemoized.set([bar, foo], value);
expect(singleMemoized.cacheSnapshot).toEqual({
keys: [[bar, foo]],
size: 1,
values: [value],
});
});
it('should notify of cache manipulation when adding', () => {
// eslint-disable-next-line prefer-const
let withNotifiers: Moized<typeof memoized>;
const onCacheOperation = jest.fn(function (cache, options, moized) {
expect(cache).toBe(withNotifiers.cache);
expect(options).toBe(withNotifiers.options);
expect(moized).toBe(withNotifiers);
});
withNotifiers = moize(memoized, {
onCacheAdd: onCacheOperation,
onCacheChange: onCacheOperation,
});
withNotifiers(foo, bar);
const value = 'something else';
withNotifiers.set([bar, foo], value);
expect(withNotifiers.cacheSnapshot).toEqual({
keys: [
[bar, foo],
[foo, bar],
],
size: 2,
values: [value, { one: foo, two: bar }],
});
expect(withNotifiers.options.onCacheAdd).toHaveBeenCalled();
expect(withNotifiers.options.onCacheChange).toHaveBeenCalled();
});
it('should update an entry to cache if it exists', () => {
memoized(foo, bar);
const value = 'something else';
memoized.set([foo, bar], value);
expect(memoized.cacheSnapshot).toEqual({
keys: [[foo, bar]],
size: 1,
values: [value],
});
});
it('should order the cache by LRU when updating', () => {
memoized(foo, bar);
memoized(bar, foo);
expect(memoized.cacheSnapshot).toEqual({
keys: [
[bar, foo],
[foo, bar],
],
size: 2,
values: [
{ one: bar, two: foo },
{ one: foo, two: bar },
],
});
const value = 'something else';
memoized.set([foo, bar], value);
expect(memoized.cacheSnapshot).toEqual({
keys: [
[foo, bar],
[bar, foo],
],
size: 2,
values: [value, { one: bar, two: foo }],
});
});
it('should notify of cache manipulation when updating', () => {
const withNotifiers = moize(memoized, {
onCacheChange: jest.fn(function (cache, options, moized) {
expect(cache).toBe(withNotifiers.cache);
expect(options).toBe(withNotifiers.options);
expect(moized).toBe(withNotifiers);
}),
});
withNotifiers(foo, bar);
const value = 'something else';
withNotifiers.set([foo, bar], value);
expect(withNotifiers.cacheSnapshot).toEqual({
keys: [[foo, bar]],
size: 1,
values: [value],
});
expect(withNotifiers.options.onCacheChange).toHaveBeenCalled();
});
it('should get the entry in cache if it exists', () => {
const result = memoized(foo, bar);
expect(memoized.get([foo, bar])).toBe(result);
expect(memoized.get([bar, foo])).toBe(undefined);
});
it('should correctly identify the entry in cache if it exists', () => {
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
expect(memoized.has([bar, foo])).toBe(false);
});
it('should remove the entry in cache if it exists', () => {
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
const result = memoized.remove([foo, bar]);
expect(memoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
});
it('should not remove the entry in cache if does not exist', () => {
memoized(foo, bar);
expect(memoized.has([bar, foo])).toBe(false);
const result = memoized.remove([bar, foo]);
expect(memoized.has([bar, foo])).toBe(false);
expect(memoized.has([foo, bar])).toBe(true);
expect(result).toBe(false);
});
it('should notify of cache change on removal and clear the expiration', () => {
const expiringMemoized = moize(method, {
maxAge: 2000,
onCacheChange: jest.fn(),
});
expiringMemoized(foo, bar);
expect(expiringMemoized.has([foo, bar])).toBe(true);
expect(expiringMemoized.expirations.length).toBe(1);
const result = expiringMemoized.remove([foo, bar]);
expect(expiringMemoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
expect(expiringMemoized.options.onCacheChange).toHaveBeenCalledWith(
expiringMemoized.cache,
expiringMemoized.options,
expiringMemoized
);
expect(expiringMemoized.expirations.length).toBe(0);
});
it('should clear the cache', () => {
memoized(foo, bar);
memoized(bar, baz);
expect(memoized.has([foo, bar])).toBe(true);
expect(memoized.has([bar, baz])).toBe(true);
const result = memoized.clear();
expect(memoized.cache.size).toBe(0);
expect(memoized.has([foo, bar])).toBe(false);
expect(memoized.has([bar, baz])).toBe(false);
expect(result).toBe(true);
});
it('should notify of the cache change on clear', () => {
const changeMemoized = moize(method, {
onCacheChange: jest.fn(),
});
changeMemoized(foo, bar);
expect(changeMemoized.has([foo, bar])).toBe(true);
const result = changeMemoized.clear();
expect(memoized.cache.size).toBe(0);
expect(changeMemoized.has([foo, bar])).toBe(false);
expect(result).toBe(true);
expect(changeMemoized.options.onCacheChange).toHaveBeenCalledWith(
changeMemoized.cache,
changeMemoized.options,
changeMemoized
);
});
it('should have the keys and values from cache', () => {
memoized(foo, bar);
const cache = memoized.cacheSnapshot;
expect(memoized.keys()).toEqual(cache.keys);
expect(memoized.values()).toEqual(cache.values);
});
it('should allow stats management of the method', () => {
moize.collectStats();
const profiled = moize(memoized, { profileName: 'profiled' });
profiled(foo, bar);
profiled(foo, bar);
profiled(foo, bar);
profiled(foo, bar);
expect(profiled.getStats()).toEqual({
calls: 4,
hits: 3,
usage: '75.0000%',
});
profiled.clearStats();
expect(profiled.getStats()).toEqual({
calls: 0,
hits: 0,
usage: '0.0000%',
});
});
});
describe('properties', () => {
it('should have the micro-memoize options', () => {
const mmResult = microMemoize(method, { maxSize: Infinity });
const { isEqual, ...options } = memoized._microMemoizeOptions;
const { isEqual: _isEqualIgnored, ...resultOptions } =
mmResult.options;
expect(options).toEqual(resultOptions);
expect(isEqual).toBe(sameValueZeroEqual);
});
it('should have cache and cacheSnapshot', () => {
memoized(foo, bar);
expect(memoized.cache).toEqual(
expect.objectContaining({
keys: [[foo, bar]],
values: [{ one: foo, two: bar }],
})
);
expect(memoized.cache.size).toBe(1);
expect(memoized.cacheSnapshot).toEqual(
expect.objectContaining({
keys: [[foo, bar]],
values: [{ one: foo, two: bar }],
})
);
expect(memoized.cacheSnapshot.size).toBe(1);
});
it('should have expirations and expirationsSnapshot', () => {
const expiringMemoized = moize(method, {
maxAge: 2000,
});
expiringMemoized(foo, bar);
expect(expiringMemoized.expirations).toEqual([
expect.objectContaining({
expirationMethod: expect.any(Function),
key: [foo, bar],
timeoutId: expect.any(Number),
}),
]);
expect(expiringMemoized.expirationsSnapshot).toEqual([
expect.objectContaining({
expirationMethod: expect.any(Function),
key: [foo, bar],
timeoutId: expect.any(Number),
}),
]);
});
it('should have the original function', () => {
expect(memoized.originalFunction).toBe(method);
});
});
});

22
node_modules/moize/__tests__/isMoized.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
import moize from '../src';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
describe('moize.isMoized', () => {
it('should validate if the function passed is moized', () => {
const memoized = moize(method);
expect(moize.isMoized(method)).toBe(false);
expect(moize.isMoized(memoized)).toBe(true);
});
it('should handle random data types', () => {
const types = [undefined, null, 'string', 123, [], {}];
types.forEach((type) => {
expect(moize.isMoized(type)).toBe(false);
});
});
});

26
node_modules/moize/__tests__/matchesArg.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import moize from '../src';
const method = jest.fn(function (one: string, two?: string) {
return { one, two };
});
function argMatcher(cacheKeyArg: string, keyArg: string) {
return cacheKeyArg === 'foo' || keyArg === 'foo';
}
const memoized = moize.matchesArg(argMatcher)(method);
const foo = 'foo';
const bar = 'bar';
describe('moize.matchesArg', () => {
it('performs a custom equality check of specific args in the key', () => {
const resultA = memoized(foo, bar);
const resultB = memoized(bar, foo);
expect(resultA).toEqual({ one: foo, two: bar });
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
});

29
node_modules/moize/__tests__/matchesKey.ts generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import moize from '../src';
import type { Key } from '../index.d';
const method = jest.fn(function (one: string, two?: string, three?: string) {
return { one, two, three };
});
function keyMatcher(_cacheKey: Key, key: Key) {
return key.includes('foo') && !key.includes('quz');
}
const memoized = moize.matchesKey(keyMatcher)(method);
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
describe('moize.matchesKey', () => {
it('performs a custom equality check of the key', () => {
const resultA = memoized(foo, bar, baz);
const resultB = memoized(foo);
expect(resultA).toEqual({ one: foo, two: bar, three: baz });
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
});

162
node_modules/moize/__tests__/maxAge.ts generated vendored Normal file
View File

@@ -0,0 +1,162 @@
import moize from '../src';
function method(one: string, two: string) {
return [one, two];
}
const foo = 'foo';
const bar = 'bar';
describe('moize.maxAge', () => {
it('removes the item from cache after the time passed', async () => {
const memoized = moize.maxAge(1000)(method, {
onExpire: jest.fn(),
});
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
expect(memoized.options.onExpire).not.toHaveBeenCalled();
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(memoized.has([foo, bar])).toBe(false);
expect(memoized.options.onExpire).toHaveBeenCalled();
});
it('notifies of cache change on removal if onCacheChange', async () => {
const memoized = moize.maxAge(1000)(method, {
onCacheChange: jest.fn(),
});
memoized(foo, bar);
expect(memoized.has([foo, bar])).toBe(true);
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(memoized.has([foo, bar])).toBe(false);
expect(memoized.options.onCacheChange).toHaveBeenCalledWith(
memoized.cache,
memoized.options,
memoized
);
});
it('updates the expiration when called and cache is hit', async () => {
const withUpdateExpire = moize.maxAge(1000, true)(method);
withUpdateExpire(foo, bar);
setTimeout(() => {
expect(withUpdateExpire.has([foo, bar])).toBe(true);
}, 1000);
await new Promise((resolve) => setTimeout(resolve, 700));
withUpdateExpire(foo, bar);
expect(withUpdateExpire.has([foo, bar])).toBe(true);
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(withUpdateExpire.has([foo, bar])).toBe(false);
});
it('calls the onExpire method when the item is removed from cache', async () => {
const onExpire = jest.fn();
const withOnExpire = moize.maxAge(1000, onExpire)(method);
withOnExpire(foo, bar);
expect(withOnExpire.has([foo, bar])).toBe(true);
expect(withOnExpire.options.onExpire).not.toHaveBeenCalled();
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(withOnExpire.has([foo, bar])).toBe(false);
expect(withOnExpire.options.onExpire).toHaveBeenCalledTimes(1);
});
it('updates the expiration timing and calls the onExpire method when the item is removed from cache', async () => {
const onExpire = jest.fn();
const withExpireOptions = moize.maxAge(1000, {
onExpire,
updateExpire: true,
})(method);
withExpireOptions(foo, bar);
setTimeout(() => {
expect(withExpireOptions.has([foo, bar])).toBe(true);
}, 1000);
await new Promise((resolve) => setTimeout(resolve, 700));
withExpireOptions(foo, bar);
await new Promise((resolve) => setTimeout(resolve, 1500));
expect(withExpireOptions.has([foo, bar])).toBe(false);
expect(withExpireOptions.options.onExpire).toHaveBeenCalledTimes(1);
});
it('allows the expiration to be re-established if onExpire returns false', async () => {
const onExpire = jest
.fn()
.mockReturnValueOnce(false)
.mockReturnValue(true);
const withOnExpire = moize.maxAge(1000, onExpire)(method);
withOnExpire(foo, bar);
expect(withOnExpire.has([foo, bar])).toBe(true);
expect(withOnExpire.options.onExpire).not.toHaveBeenCalled();
await new Promise((resolve) => setTimeout(resolve, 1100));
expect(withOnExpire.has([foo, bar])).toBe(true);
expect(withOnExpire.options.onExpire).toHaveBeenCalledTimes(1);
await new Promise((resolve) => setTimeout(resolve, 1100));
expect(withOnExpire.has([foo, bar])).toBe(false);
expect(withOnExpire.options.onExpire).toHaveBeenCalledTimes(2);
});
it('notifies of cache change when expiration re-established if onCacheChange', async () => {
const onExpire = jest
.fn()
.mockReturnValueOnce(false)
.mockReturnValue(true);
const withOnExpire = moize.maxAge(1000, onExpire)(method, {
onCacheChange: jest.fn(),
});
withOnExpire(foo, bar);
expect(withOnExpire.has([foo, bar])).toBe(true);
expect(withOnExpire.options.onExpire).not.toHaveBeenCalled();
await new Promise((resolve) => setTimeout(resolve, 1100));
expect(withOnExpire.has([foo, bar])).toBe(true);
expect(withOnExpire.options.onExpire).toHaveBeenCalledTimes(1);
await new Promise((resolve) => setTimeout(resolve, 1100));
expect(withOnExpire.has([foo, bar])).toBe(false);
expect(withOnExpire.options.onExpire).toHaveBeenCalledTimes(2);
expect(withOnExpire.options.onCacheChange).toHaveBeenCalledWith(
withOnExpire.cache,
withOnExpire.options,
withOnExpire
);
});
});

65
node_modules/moize/__tests__/maxArgs.ts generated vendored Normal file
View File

@@ -0,0 +1,65 @@
import moize from '../src';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
const qux = 'qux';
const quz = 'quz';
describe('moize.maxArgs', () => {
afterEach(jest.clearAllMocks);
[1, 2, 3, 4].forEach((limit) => {
it(`limits the args to ${limit}`, () => {
const memoized = moize.maxArgs(limit)(method);
const args = [foo, bar, baz, qux, quz];
const limitedArgs = args.slice(0, limit);
const resultA = memoized.apply(null, args);
const resultB = memoized.apply(null, limitedArgs);
expect(resultA).toEqual({ one: foo, two: bar });
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
});
it('will always return from cache if 0', () => {
const memoized = moize.maxArgs(0)(method);
const result = memoized(foo, bar);
expect(result).toEqual({ one: foo, two: bar });
// @ts-ignore - allow bunk
memoized(baz);
// @ts-ignore - allow bunk
memoized(123);
// @ts-ignore - allow bunk
memoized({});
// @ts-ignore - allow bunk
memoized();
expect(method).toHaveBeenCalledTimes(1);
});
it('will use the args passed if less than the size limited', () => {
const memoized = moize.maxArgs(10)(method);
const args = [foo, bar, baz, qux, quz];
const resultA = memoized.apply(null, args);
const resultB = memoized.apply(null, [foo, bar, baz, qux, 'nope']);
expect(resultA).toEqual({ one: foo, two: bar });
expect(resultB).not.toBe(resultA);
expect(method).toHaveBeenCalledTimes(2);
});
});

147
node_modules/moize/__tests__/promise.ts generated vendored Normal file
View File

@@ -0,0 +1,147 @@
import Bluebird from 'bluebird';
import moize from '../src';
import { type Moizeable, type Moized } from '../index.d';
function createMethod(
type: string,
method: 'resolve' | 'reject',
PromiseLibrary: PromiseConstructor
) {
if (method === 'reject') {
return function (number: number, otherNumber: number) {
return PromiseLibrary.reject(
new Error(`rejected ${number * otherNumber}`)
);
};
}
return function (number: number, otherNumber: number) {
return PromiseLibrary.resolve(number * otherNumber);
};
}
const bluebirdMemoizedResolve = moize.promise(
createMethod(
'bluebird',
'resolve',
Bluebird as unknown as PromiseConstructor
),
{ profileName: 'bluebird (reject)' }
);
const bluebirdMemoizedReject = moize.promise(
createMethod(
'bluebird',
'reject',
Bluebird as unknown as PromiseConstructor
),
{ profileName: 'bluebird (reject)' }
);
const bluebirdMemoizedExpiring = moize.promise(
createMethod(
'native',
'resolve',
Bluebird as unknown as PromiseConstructor
),
{
maxAge: 1500,
onCacheHit: jest.fn(),
onExpire: jest.fn(),
profileName: 'bluebird (expiring)',
}
);
const nativeMemoizedResolve = moize.promise(
createMethod('native', 'resolve', Promise),
{
profileName: 'native',
}
);
const nativeMemoizedReject = moize.promise(
createMethod('native', 'reject', Promise),
{
profileName: 'native (reject)',
}
);
const nativeMemoizedExpiring = moize.promise(
createMethod('native', 'resolve', Promise),
{
maxAge: 1500,
onCacheHit: jest.fn(),
onExpire: jest.fn(),
profileName: 'native (expiring)',
}
);
function testItem<MoizeableFn extends Moizeable>(
key: number[],
method: Moized<MoizeableFn>,
Constructor: any
) {
const [number, otherNumber] = key;
return method(number, otherNumber).then((result: number) => {
expect(method.get(key)).toBeInstanceOf(Constructor);
expect(method.get(key.slice().reverse())).toBe(undefined);
expect(result).toEqual(number * otherNumber);
});
}
const TYPES = {
bluebird: Bluebird,
native: Promise,
};
const METHODS = {
bluebird: {
resolve: bluebirdMemoizedResolve,
reject: bluebirdMemoizedReject,
expiring: bluebirdMemoizedExpiring,
},
native: {
resolve: nativeMemoizedResolve,
reject: nativeMemoizedReject,
expiring: nativeMemoizedExpiring,
},
};
describe('moize.promise', () => {
['native', 'bluebird'].forEach((type) => {
const Constructor = TYPES[type as keyof typeof TYPES];
['resolve', 'reject', 'expiring'].forEach((test) => {
const methodType = METHODS[type as keyof typeof METHODS];
const method = methodType[test as keyof typeof methodType];
it(`should handle ${test}`, async () => {
try {
await testItem([6, 9], method, Constructor);
if (test === 'reject') {
throw new Error(`${test} should have rejected`);
}
} catch (error) {
if (test !== 'reject') {
throw error;
}
}
if (test === 'expiring') {
expect(method.options.onCacheHit).toHaveBeenCalledWith(
method.cache,
method.options,
method
);
await new Promise((resolve) =>
setTimeout(resolve, method.options.maxAge * 2)
).then(() => {
expect(method.options.onExpire).toHaveBeenCalledTimes(
1
);
});
}
});
});
});
});

272
node_modules/moize/__tests__/react.tsx generated vendored Normal file
View File

@@ -0,0 +1,272 @@
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import moize from '../src';
import { copyStaticProperties } from '../src/instance';
describe('moize.react', () => {
type ValueBarProps = {
bar?: string;
fn: (...args: any[]) => any;
key?: string;
object?: Record<string, unknown>;
value?: any;
};
function _ValueBar({ bar, value }: ValueBarProps) {
return (
<div>
{value} {bar}
</div>
);
}
_ValueBar.propTypes = {
bar: PropTypes.string.isRequired,
fn: PropTypes.func.isRequired,
object: PropTypes.object.isRequired,
value: PropTypes.string.isRequired,
};
_ValueBar.defaultProps = {
bar: 'default',
};
const ValueBar = jest.fn(_ValueBar) as (
props: ValueBarProps
) => JSX.Element;
// force static properties to be passed to mock
copyStaticProperties(_ValueBar, ValueBar);
const Memoized = moize.react(ValueBar);
it('should have the correct static values', () => {
expect(Memoized.propTypes).toBe(_ValueBar.propTypes);
expect(Memoized.defaultProps).toBe(_ValueBar.defaultProps);
expect(Memoized.displayName).toBe(`Moized(${ValueBar.name})`);
});
it('should memoize the component renders', () => {
type Props = { id: string; unused?: boolean };
const Component = ({ id }: Props) => <div id={id} />;
const ComponentSpy = jest.fn(Component) as typeof Component;
const MoizedComponent = moize.react(ComponentSpy);
const App = ({ id, unused }: Props) => (
<MoizedComponent id={id} unused={unused} />
);
const app = document.createElement('div');
document.body.appendChild(app);
new Array(100).fill('id').forEach((id, index) => {
ReactDOM.render(<App id={id} unused={index === 53} />, app);
});
// The number of calls is 3 because cache breaks twice, when `unused` prop is toggled.
expect(ComponentSpy).toHaveBeenCalledTimes(3);
});
it('should memoize the component renders with custom options', () => {
type Props = { id: string; unused?: boolean };
const Component = ({ id }: Props) => <div id={id} />;
const ComponentSpy = jest.fn(Component) as typeof Component;
const MoizedComponent = moize.react(ComponentSpy, { maxSize: 2 });
const App = ({ id, unused }: Props) => (
<MoizedComponent id={id} unused={unused} />
);
const app = document.createElement('div');
document.body.appendChild(app);
new Array(100).fill('id').forEach((id, index) => {
ReactDOM.render(<App id={id} unused={index === 53} />, app);
});
// The number of calls is 2 because both `unused` values are stored in cache.
expect(ComponentSpy).toHaveBeenCalledTimes(2);
});
it('should memoize the component renders including legacy context', () => {
type Props = { id: string; unused?: boolean };
const Component = ({ id }: Props) => <div id={id} />;
const ComponentSpy = jest.fn(
Component
) as unknown as typeof Component & {
contextTypes: Record<string, any>;
};
ComponentSpy.contextTypes = { unused: PropTypes.bool.isRequired };
const MoizedComponent = moize.react(ComponentSpy);
class App extends React.Component<Props> {
static childContextTypes = {
unused: PropTypes.bool.isRequired,
};
getChildContext() {
return {
unused: this.props.unused,
};
}
render() {
return <MoizedComponent id={this.props.id} />;
}
}
const app = document.createElement('div');
document.body.appendChild(app);
new Array(100).fill('id').forEach((id, index) => {
ReactDOM.render(<App id={id} unused={index === 53} />, app);
});
// The number of calls is 3 because cache breaks twice, when `unused` context value is toggled.
expect(ComponentSpy).toHaveBeenCalledTimes(3);
});
it('should memoize on a per-instance basis on render', async () => {
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
const data = [
{
fn() {
return foo;
},
object: { value: foo },
value: foo,
},
{
bar,
fn() {
return bar;
},
object: { value: bar },
value: bar,
},
{
fn() {
return baz;
},
object: { value: baz },
value: baz,
},
];
class App extends React.Component<{ isRerender?: boolean }> {
MoizedComponent: typeof Memoized;
componentDidMount() {
expect(ValueBar).toHaveBeenCalledTimes(3);
}
componentDidUpdate() {
// only one component rerendered based on dynamic props
expect(ValueBar).toHaveBeenCalledTimes(4);
}
setMoizedComponent = (Ref: {
MoizedComponent: typeof Memoized;
}) => {
this.MoizedComponent = Ref.MoizedComponent;
};
render() {
const { isRerender } = this.props;
return (
<div>
<h1 style={{ margin: 0 }}>App</h1>
<div>
<h3>Memoized data list</h3>
{data.map((values, index) => (
<Memoized
key={`called-${values.value}`}
{...values}
isDynamic={index === 2 && isRerender}
ref={this.setMoizedComponent}
/>
))}
</div>
</div>
);
}
}
function renderApp(
isRerender?: boolean,
onRender?: (value?: unknown) => void
) {
ReactDOM.render(<App isRerender={isRerender} />, app, onRender);
}
const app = document.createElement('div');
document.body.appendChild(app);
renderApp();
expect(ValueBar).toHaveBeenCalledTimes(data.length);
await new Promise((resolve) =>
setTimeout(() => {
renderApp(true, resolve);
}, 1000)
);
expect(ValueBar).toHaveBeenCalledTimes(data.length + 1);
});
it('should allow use of hooks', async () => {
const timing = 1000;
const app = document.createElement('div');
document.body.appendChild(app);
const spy = jest.fn();
const TestComponent = moize.react(() => {
const [txt, setTxt] = React.useState(0);
React.useEffect(() => {
setTimeout(() => {
setTxt(Date.now());
spy();
}, timing);
}, []);
return <span>{txt}</span>;
});
ReactDOM.render(<TestComponent />, app);
expect(spy).not.toHaveBeenCalled();
await new Promise((resolve) => setTimeout(resolve, timing + 200));
expect(spy).toHaveBeenCalled();
});
describe('edge cases', () => {
it('should retain the original function name', () => {
function MyComponent(): null {
return null;
}
const memoized = moize.react(MyComponent);
expect(memoized.name).toBe('moized(MyComponent)');
});
});
});

106
node_modules/moize/__tests__/serialize.ts generated vendored Normal file
View File

@@ -0,0 +1,106 @@
import cloneDeep from 'lodash/cloneDeep';
import moize from '../src';
type Arg = {
one: number;
two: number;
three: () => void;
four: symbol;
five: null;
};
const method = jest.fn(function ({ one, two, three, four, five }: Arg) {
return [one, two, three, four, five];
});
const memoized = moize.serialize(method);
describe('moize.serialize', () => {
afterEach(jest.clearAllMocks);
it('serializes the args passed by', () => {
const three = function () {};
const four = Symbol('foo');
const resultA = memoized({ one: 1, two: 2, three, four, five: null });
const resultB = memoized({
one: 1,
two: 2,
three() {},
four: Symbol('foo'),
five: null,
});
expect(resultA).toEqual([1, 2, three, four, null]);
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
it('handles circular objects', () => {
type Arg = {
deeply: {
nested: {
circular: Arg | {};
};
};
};
const circularMethod = jest.fn((arg: Arg) => arg);
const circularMemoized = moize.serialize(circularMethod);
const circular: Arg = {
deeply: {
nested: {
circular: {},
},
},
};
circular.deeply.nested.circular = circular;
const resultA = circularMemoized(cloneDeep(circular));
const resultB = circularMemoized(cloneDeep(circular));
expect(resultB).toBe(resultA);
expect(circularMethod).toHaveBeenCalledTimes(1);
expect(circularMemoized.cache.keys).toEqual([
['|{"deeply":{"nested":{"circular":"[ref=.]"}}}|'],
]);
});
});
describe('moize.serializeWith', () => {
afterEach(jest.clearAllMocks);
it('serializes the arguments passed with the custom serializer', () => {
const withSerializer = moize.serializeWith((args: any[]) => [
JSON.stringify(args),
])(method);
const three = function () {};
const four = Symbol('foo');
const resultA = withSerializer({
one: 1,
two: 2,
three,
four,
five: null,
});
const resultB = withSerializer({
one: 1,
two: 2,
three() {},
four: Symbol('foo'),
five: null,
});
expect(resultA).toEqual([1, 2, three, four, null]);
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
});

35
node_modules/moize/__tests__/shallowEqual.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import moize from '../src';
type Arg = {
one: number;
two: {
deep: number;
};
};
const method = jest.fn(function ({ one, two }: Arg) {
return [one, two.deep];
});
const memoized = moize.shallow(method);
describe('moize.shallow', () => {
it('should memoized based on the shallow values', () => {
const two = { deep: 2 };
const resultA = memoized({ one: 1, two });
const resultB = memoized({ one: 1, two });
expect(resultA).toEqual([1, 2]);
expect(resultA).toBe(resultB);
expect(method).toHaveBeenCalledTimes(1);
const resultC = memoized({ one: 1, two: { ...two } });
expect(resultC).toEqual(resultA);
expect(resultC).not.toBe(resultA);
expect(method).toHaveBeenCalledTimes(2);
});
});

178
node_modules/moize/__tests__/stats.ts generated vendored Normal file
View File

@@ -0,0 +1,178 @@
import moize from '../src';
const foo = 'foo';
const bar = 'bar';
const method = jest.fn(function (one: string, two: string) {
return { one, two };
});
describe('moize.isCollectingStats', () => {
it('should identify if stats are being collected', () => {
expect(moize.isCollectingStats()).toBe(false);
moize.collectStats();
expect(moize.isCollectingStats()).toBe(true);
moize.collectStats(false);
expect(moize.isCollectingStats()).toBe(false);
});
});
describe('moize.profile', () => {
beforeEach(() => {
moize.collectStats();
});
afterEach(() => {
moize.collectStats(false);
moize.clearStats();
});
it('should create a memoized method with the profileName passed', () => {
const profileName = 'profileName';
const profiled = moize.profile(profileName)(method);
profiled(foo, bar);
profiled(foo, bar);
expect(profiled.getStats()).toEqual({
calls: 2,
hits: 1,
usage: '50.0000%',
});
profiled.clearStats();
expect(profiled.getStats()).toEqual({
calls: 0,
hits: 0,
usage: '0.0000%',
});
});
it('should handle collecting more stats after clearing', () => {
const profileName = 'profileName';
const profiled = moize.profile(profileName)(method);
profiled(foo, bar);
profiled(foo, bar);
expect(profiled.getStats()).toEqual({
calls: 2,
hits: 1,
usage: '50.0000%',
});
profiled.clearStats();
expect(profiled.getStats()).toEqual({
calls: 0,
hits: 0,
usage: '0.0000%',
});
profiled(foo, bar);
profiled(foo, bar);
expect(profiled.getStats()).toEqual({
calls: 2,
hits: 2,
usage: '100.0000%',
});
});
it('should profile a fallback name if one is not provided', () => {
const originalError = global.Error;
// @ts-ignore - dummy override
global.Error = function () {
return {};
};
const memoized = moize(method);
memoized(foo, bar);
memoized(foo, bar);
expect(moize.getStats()).toEqual({
calls: 2,
hits: 1,
profiles: {
[memoized.options.profileName]: {
calls: 2,
hits: 1,
usage: '50.0000%',
},
},
usage: '50.0000%',
});
global.Error = originalError;
});
});
describe('moize.getStats', () => {
beforeEach(() => {
moize.collectStats();
});
afterEach(() => {
moize.collectStats(false);
moize.clearStats();
});
it('should handle stats for all usages', () => {
const profileName = 'profileName';
const profiled = moize.profile(profileName)(method);
profiled(foo, bar);
profiled(foo, bar);
// specific stats
expect(moize.getStats(profileName)).toEqual({
calls: 2,
hits: 1,
usage: '50.0000%',
});
// global stats
expect(moize.getStats()).toEqual({
calls: 2,
hits: 1,
profiles: {
[profileName]: {
calls: 2,
hits: 1,
usage: '50.0000%',
},
},
usage: '50.0000%',
});
moize.clearStats();
expect(moize.getStats()).toEqual({
calls: 0,
hits: 0,
profiles: {},
usage: '0.0000%',
});
});
it('should warn when getting stats and stats are not being collected', () => {
moize.collectStats(false);
const warn = jest.spyOn(console, 'warn');
moize.getStats();
expect(warn).toHaveBeenCalledWith(
'Stats are not currently being collected, please run "collectStats" to enable them.'
);
warn.mockRestore();
});
});

35
node_modules/moize/__tests__/transformArgs.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
import moize from '../src';
const method = jest.fn(function (one: string, two: string, three: string) {
return { one, two, three };
});
function transformer(args: string[]) {
const newKey: string[] = [];
let index = args.length;
while (--index) {
newKey[index - 1] = args[index];
}
return newKey;
}
const memoized = moize.transformArgs(transformer)(method);
const foo = 'foo';
const bar = 'bar';
const baz = 'baz';
describe('moize.transformArgs', () => {
it('limits the args memoized by', () => {
const resultA = memoized(foo, bar, baz);
const resultB = memoized(null, bar, baz);
expect(resultA).toEqual({ one: foo, two: bar, three: baz });
expect(resultB).toBe(resultA);
expect(method).toHaveBeenCalledTimes(1);
});
});

311
node_modules/moize/__tests__/updateCacheForKey.ts generated vendored Normal file
View File

@@ -0,0 +1,311 @@
import moize from '../src';
type Type = {
number: number;
};
const method = (one: number, two: Type) => one + two.number;
const promiseMethodResolves = (one: number, two: Type) =>
new Promise((resolve) => setTimeout(() => resolve(one + two.number), 1000));
const promiseMethodRejects =
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(one: number, two: Type) =>
new Promise((resolve, reject) =>
setTimeout(() => reject(new Error('boom')), 1000)
);
describe('moize.updateCacheForKey', () => {
describe('success', () => {
it('will refresh the cache', () => {
const moized = moize.maxSize(2)(method, {
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const mutated = { number: 5 };
const result = moized(6, mutated);
expect(result).toBe(11);
mutated.number = 11;
const mutatedResult = moized(6, mutated);
// Result was not recalculated because `updateCacheForKey` returned `false` and the values are
// seen as unchanged.
expect(mutatedResult).toBe(result);
mutated.number = 10;
const refreshedResult = moized(6, mutated);
// Result was recalculated because `updateCacheForKey` returned `true`.
expect(refreshedResult).not.toBe(result);
expect(refreshedResult).toBe(16);
const { keys, values } = moized.cacheSnapshot;
expect(keys).toEqual([[6, mutated]]);
expect(values).toEqual([16]);
});
it('will refresh the cache based on external values', async () => {
const mockMethod = jest.fn(method);
let lastUpdate = Date.now();
const moized = moize.maxSize(2)(mockMethod, {
updateCacheForKey() {
const now = Date.now();
const last = lastUpdate;
lastUpdate = now;
return last + 1000 < now;
},
});
const mutated = { number: 5 };
moized(6, mutated);
moized(6, mutated);
moized(6, mutated);
expect(mockMethod).toHaveBeenCalledTimes(1);
await new Promise((resolve) => setTimeout(resolve, 2000));
moized(6, mutated);
expect(mockMethod).toHaveBeenCalledTimes(2);
});
it('will refresh the cache when used with promises', async () => {
const moized = moize.maxSize(2)(promiseMethodResolves, {
isPromise: true,
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const mutated = { number: 5 };
const result = await moized(6, mutated);
expect(result).toBe(11);
mutated.number = 11;
const mutatedResult = await moized(6, mutated);
// Result was not recalculated because `updateCacheForKey` returned `false` and the values are
// seen as unchanged.
expect(mutatedResult).toBe(result);
mutated.number = 10;
const refreshedResult = await moized(6, mutated);
// Result was recalculated because `updateCacheForKey` returned `true`.
expect(refreshedResult).not.toBe(result);
expect(refreshedResult).toBe(16);
const { keys, values } = moized.cacheSnapshot;
expect(keys).toEqual([[6, mutated]]);
expect(values).toEqual([Promise.resolve(16)]);
});
it('will refresh the cache when used with custom key transformers', () => {
type ConditionalIncrement = {
force?: boolean;
};
let count = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const increment = (_?: ConditionalIncrement) => ++count;
const moized = moize.maxSize(2)(increment, {
isSerialized: true,
updateCacheForKey: (args: [ConditionalIncrement]) =>
args[0] && args[0].force === true,
serializer: () => ['always same'],
});
expect(moized()).toBe(1);
expect(moized()).toBe(1);
expect(moized({ force: true })).toBe(2);
expect(moized()).toBe(2);
});
it('will refresh the cache with shorthand', () => {
const moized = moize.updateCacheForKey(
(args) => args[1].number % 2 === 0
)(method);
const mutated = { number: 5 };
const result = moized(6, mutated);
expect(result).toBe(11);
mutated.number = 11;
const mutatedResult = moized(6, mutated);
// Result was not recalculated because `updateCacheForKey` returned `false` and the values are
// seen as unchanged.
expect(mutatedResult).toBe(result);
mutated.number = 10;
const refreshedResult = moized(6, mutated);
// Result was recalculated because `updateCacheForKey` returned `true`.
expect(refreshedResult).not.toBe(result);
expect(refreshedResult).toBe(16);
const { keys, values } = moized.cacheSnapshot;
expect(keys).toEqual([[6, mutated]]);
expect(values).toEqual([16]);
});
it('will refresh the cache with composed shorthand', () => {
const moizer = moize.compose(
moize.maxSize(2),
moize.updateCacheForKey((args) => args[1].number % 2 === 0)
);
const moized = moizer(method);
const mutated = { number: 5 };
const result = moized(6, mutated);
expect(result).toBe(11);
mutated.number = 11;
const mutatedResult = moized(6, mutated);
// Result was not recalculated because `updateCacheForKey` returned `false` and the values are
// seen as unchanged.
expect(mutatedResult).toBe(result);
mutated.number = 10;
const refreshedResult = moized(6, mutated);
// Result was recalculated because `updateCacheForKey` returned `true`.
expect(refreshedResult).not.toBe(result);
expect(refreshedResult).toBe(16);
const { keys, values } = moized.cacheSnapshot;
expect(keys).toEqual([[6, mutated]]);
expect(values).toEqual([16]);
});
});
describe('fail', () => {
it('surfaces the error if the function fails', () => {
const moized = moize.maxSize(2)(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(_1: number, _2: Type) => {
throw new Error('boom');
},
{
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
}
);
const mutated = { number: 5 };
expect(() => moized(6, mutated)).toThrow(new Error('boom'));
});
it('surfaces the error if the promise rejects', async () => {
const moized = moize.maxSize(2)(promiseMethodRejects, {
isPromise: true,
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const mutated = { number: 5 };
await expect(moized(6, mutated)).rejects.toEqual(new Error('boom'));
});
it('should have nothing in cache if promise is rejected and key was never present', async () => {
const moized = moize.maxSize(2)(promiseMethodRejects, {
isPromise: true,
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const mutated = { number: 5 };
await expect(moized(6, mutated)).rejects.toEqual(new Error('boom'));
expect(moized.keys()).toEqual([]);
expect(moized.values()).toEqual([]);
});
// For some reason, this is causing `jest` to crash instead of handle the rejection
it.skip('should have nothing in cache if promise is rejected and key was present', async () => {
const moized = moize.maxSize(2)(promiseMethodRejects, {
isPromise: true,
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const mutated = { number: 5 };
moized.set([6, mutated], Promise.resolve(11));
expect(moized.get([6, mutated])).toEqual(Promise.resolve(11));
mutated.number = 10;
await expect(moized(6, mutated)).rejects.toEqual(new Error('boom'));
expect(moized.keys()).toEqual([]);
expect(moized.values()).toEqual([]);
});
});
describe('infrastructure', () => {
it('should have all the static properties of a standard moized method', () => {
const moized = moize.maxSize(2)(promiseMethodResolves, {
updateCacheForKey(args) {
return args[1].number % 2 === 0;
},
});
const standardMoized = moize.maxSize(2)(promiseMethodResolves);
expect(Object.getOwnPropertyNames(moized)).toEqual(
Object.getOwnPropertyNames(standardMoized)
);
});
});
describe('edge cases', () => {
it('should retain the original function name', () => {
function myNamedFunction() {}
const memoized = moize(myNamedFunction, {
updateCacheForKey: () => false,
});
expect(memoized.name).toBe('moized(myNamedFunction)');
});
});
});

1477
node_modules/moize/dist/moize.cjs.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/moize/dist/moize.cjs.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

1475
node_modules/moize/dist/moize.esm.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/moize/dist/moize.esm.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

1480
node_modules/moize/dist/moize.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/moize/dist/moize.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

2
node_modules/moize/dist/moize.min.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
node_modules/moize/dist/moize.min.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

60
node_modules/moize/es-to-mjs.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const fs = require('fs');
const path = require('path');
const pkg = require('./package.json');
const BASE_PATH = __dirname;
const SOURCE_ENTRY = path.join(BASE_PATH, pkg.module);
const SOURCE_MAP = `${SOURCE_ENTRY}.map`;
const SOURCE_TYPES = path.join(BASE_PATH, 'index.d.ts');
const DESTINATION = 'mjs';
const DESTINATION_ENTRY = path.join(BASE_PATH, DESTINATION, 'index.mjs');
const DESTINATION_MAP = `${DESTINATION_ENTRY}.map`;
const DESTINATION_TYPES = path.join(BASE_PATH, DESTINATION, 'index.d.mts');
function getFileName(filename) {
return filename.replace(`${BASE_PATH}/`, '');
}
try {
if (!fs.existsSync(path.join(__dirname, 'mjs'))) {
fs.mkdirSync(path.join(__dirname, 'mjs'));
}
fs.copyFileSync(SOURCE_ENTRY, DESTINATION_ENTRY);
const contents = fs
.readFileSync(DESTINATION_ENTRY, { encoding: 'utf8' })
.replace('fast-equals', 'fast-equals/dist/fast-equals.mjs')
.replace('fast-stringify', 'fast-stringify/mjs/index.mjs')
.replace('micro-memoize', 'micro-memoize/mjs/index.mjs')
.replace(/\/\/# sourceMappingURL=(.*)/, (match, value) => {
return match.replace(value, 'index.mjs.map');
});
fs.writeFileSync(DESTINATION_ENTRY, contents, { encoding: 'utf8' });
console.log(
`Copied ${getFileName(SOURCE_ENTRY)} to ${getFileName(
DESTINATION_ENTRY
)}`
);
fs.copyFileSync(SOURCE_MAP, DESTINATION_MAP);
console.log(`Copied ${SOURCE_MAP} to ${getFileName(DESTINATION_MAP)}`);
fs.copyFileSync(SOURCE_TYPES, DESTINATION_TYPES);
console.log(
`Copied ${getFileName(SOURCE_TYPES)} to ${getFileName(
DESTINATION_TYPES
)}`
);
} catch (error) {
console.error(error);
process.exit(1);
}

293
node_modules/moize/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,293 @@
/* eslint-disable */
import {
Cache as BaseCache,
Memoized as BaseMemoized,
Options as BaseOptions,
} from 'micro-memoize';
export type AnyFn = (...args: any[]) => any;
export type Moizeable = AnyFn & Record<string, any>;
interface MoizedReactElement {
type: any;
props: any;
key: string | number | null;
}
/**
* @deprecated
*
* Use `AnyFn` instead, as it is more flexible and works better with type inference.
*/
export type Fn<Arg extends any = any, Result extends any = any> = (
...args: Arg[]
) => Result;
/**
* @deprecated
*
* This should not longer need to be explicitly used, as inference of the function
* returning the element should suffice.
*/
export type FunctionalComponent<Props extends object> = ((
props: Props
) => MoizedReactElement) & {
displayName?: string;
};
export type Key<Arg extends any = any> = Arg[];
export type Value = any;
export type Cache<MoizeableFn extends Moizeable = Moizeable> =
BaseCache<MoizeableFn>;
export type MicroMemoizeOptions<MoizeableFn extends Moizeable = Moizeable> =
BaseOptions<MoizeableFn>;
export type Expiration = {
expirationMethod: () => void;
key: Key;
timeoutId: ReturnType<typeof setTimeout>;
};
export type OnCacheOperation<MoizeableFn extends Moizeable = Moizeable> = (
cache: Cache<MoizeableFn>,
options: Options<MoizeableFn>,
moized: (...args: any[]) => any
) => void;
export type IsEqual = (cacheKeyArg: any, keyArg: any) => boolean;
export type IsMatchingKey = (cacheKey: Key, key: Key) => boolean;
export type OnExpire = (key: Key) => any;
export type Serialize = (key: Key) => string[];
export type TransformKey = (key: Key) => Key;
export type UpdateCacheForKey = (key: Key) => boolean;
export type Options<MoizeableFn extends Moizeable = Moizeable> = Partial<{
isDeepEqual: boolean;
isPromise: boolean;
isReact: boolean;
isSerialized: boolean;
isShallowEqual: boolean;
matchesArg: IsEqual;
matchesKey: IsMatchingKey;
maxAge: number;
maxArgs: number;
maxSize: number;
onCacheAdd: OnCacheOperation<MoizeableFn>;
onCacheChange: OnCacheOperation<MoizeableFn>;
onCacheHit: OnCacheOperation<MoizeableFn>;
onExpire: OnExpire;
profileName: string;
serializer: Serialize;
transformArgs: TransformKey;
updateCacheForKey: UpdateCacheForKey;
updateExpire: boolean;
}>;
export type StatsProfile = {
calls: number;
hits: number;
};
export type StatsObject = {
calls: number;
hits: number;
usage: string;
};
export type GlobalStatsObject = StatsObject & {
profiles?: Record<string, StatsProfile>;
};
export type StatsCache = {
anonymousProfileNameCounter: number;
isCollectingStats: boolean;
profiles: Record<string, StatsProfile>;
};
export type Memoized<MoizeableFn extends Moizeable = Moizeable> =
BaseMemoized<MoizeableFn>;
export type Moized<
MoizeableFn extends Moizeable = Moizeable,
CombinedOptions extends Options<MoizeableFn> = Options<MoizeableFn>
> = Memoized<MoizeableFn> & {
// values
_microMemoizeOptions: Pick<
CombinedOptions,
'isPromise' | 'maxSize' | 'onCacheAdd' | 'onCacheChange' | 'onCacheHit'
> & {
isEqual: CombinedOptions['matchesArg'];
isMatchingKey: CombinedOptions['matchesKey'];
transformKey: CombinedOptions['transformArgs'];
};
cache: Cache<MoizeableFn>;
cacheSnapshot: Cache<MoizeableFn>;
expirations: Expiration[];
expirationsSnapshot: Expiration[];
options: CombinedOptions;
originalFunction: MoizeableFn;
// react-specific values
contextTypes?: Record<string, Function>;
defaultProps?: Record<string, unknown>;
displayName?: string;
propTypes: Record<string, Function>;
// methods
clear: () => void;
clearStats: () => void;
get: (key: Key) => any;
getStats: () => StatsProfile;
has: (key: Key) => boolean;
isCollectingStats: () => boolean;
isMoized: () => true;
keys: () => Cache<MoizeableFn>['keys'];
remove: (key: Key) => void;
set: (key: Key, value: any) => void;
values: () => Cache<MoizeableFn>['values'];
};
export type MoizeConfiguration<MoizeableFn extends Moizeable = Moizeable> = {
expirations: Expiration[];
options: Options<MoizeableFn>;
originalFunction: MoizeableFn;
};
export type CurriedMoize<OriginalOptions> = <
CurriedFn extends Moizeable,
CurriedOptions extends Options<CurriedFn>
>(
curriedFn: CurriedFn | CurriedOptions,
curriedOptions?: CurriedOptions
) =>
| Moized<CurriedFn, OriginalOptions & CurriedOptions>
| CurriedMoize<OriginalOptions & CurriedOptions>;
export interface MaxAge {
<MaxAge extends number>(maxAge: MaxAge): Moizer<{ maxAge: MaxAge }>;
<MaxAge extends number, UpdateExpire extends boolean>(
maxAge: MaxAge,
expireOptions: UpdateExpire
): Moizer<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
<MaxAge extends number, ExpireHandler extends OnExpire>(
maxAge: MaxAge,
expireOptions: ExpireHandler
): Moizer<{ maxAge: MaxAge; onExpire: ExpireHandler }>;
<
MaxAge extends number,
ExpireHandler extends OnExpire,
ExpireOptions extends {
onExpire: ExpireHandler;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{ maxAge: MaxAge; onExpire: ExpireOptions['onExpire'] }>;
<
MaxAge extends number,
UpdateExpire extends boolean,
ExpireOptions extends {
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
<
MaxAge extends number,
ExpireHandler extends OnExpire,
UpdateExpire extends boolean,
ExpireOptions extends {
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{
maxAge: MaxAge;
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}>;
}
export interface Moizer<
DefaultOptions extends Options<Moizeable> = Options<Moizeable>
> {
<MoizeableFn extends Moizeable>(fn: MoizeableFn): Moized<
MoizeableFn,
Options<MoizeableFn> & DefaultOptions
>;
<MoizeableFn extends Moizeable, PassedOptions extends Options<MoizeableFn>>(
fn: MoizeableFn,
options: PassedOptions
): Moized<
MoizeableFn,
Options<MoizeableFn> & DefaultOptions & PassedOptions
>;
<MoizedFn extends Moized<Moizeable>>(fn: MoizedFn): Moized<
MoizedFn['fn'],
Options<MoizedFn> & DefaultOptions
>;
<
MoizedFn extends Moized<Moizeable>,
PassedOptions extends Options<MoizedFn>
>(
fn: MoizedFn,
options: PassedOptions
): Moized<
MoizedFn['fn'],
Options<MoizedFn> & DefaultOptions & PassedOptions
>;
<PassedOptions extends Options<Moizeable>>(
options: PassedOptions
): Moizer<PassedOptions>;
}
export interface Moize<
DefaultOptions extends Options<Moizeable> = Options<Moizeable>
> extends Moizer<DefaultOptions> {
clearStats: (profileName?: string) => void;
collectStats: (isCollectingStats?: boolean) => void;
compose: (...moizers: Array<Moize | Moizer>) => Moizer;
deep: Moizer<{ isDeepEqual: true }>;
getStats: (profileName?: string) => StatsObject;
infinite: Moizer;
isCollectingStats: () => boolean;
isMoized: (value: any) => value is Moized;
matchesArg: <Matcher extends IsEqual>(
argMatcher: Matcher
) => Moizer<{ matchesArg: Matcher }>;
matchesKey: <Matcher extends IsMatchingKey>(
keyMatcher: Matcher
) => Moizer<{ matchesKey: Matcher }>;
maxAge: MaxAge;
maxArgs: <MaxArgs extends number>(
args: MaxArgs
) => Moizer<{ maxArgs: MaxArgs }>;
maxSize: <MaxSize extends number>(
size: MaxSize
) => Moizer<{ maxSize: MaxSize }>;
profile: <ProfileName extends string>(
profileName: ProfileName
) => Moizer<{ profileName: ProfileName }>;
promise: Moizer<{ isPromise: true }>;
react: Moizer<{ isReact: true }>;
serialize: Moizer<{ isSerialized: true }>;
serializeWith: <Serializer extends Serialize>(
serializer: Serializer
) => Moizer<{ isSerialized: true; serializer: Serializer }>;
shallow: Moizer<{ isShallowEqual: true }>;
transformArgs: <Transformer extends TransformKey>(
transformer: Transformer
) => Moizer<{ transformArgs: Transformer }>;
updateCacheForKey: <UpdateWhen extends UpdateCacheForKey>(
updateCacheForKey: UpdateWhen
) => Moizer<{ updateCacheForKey: UpdateWhen }>;
}
declare const moize: Moize;
export default moize;

12
node_modules/moize/jest.config.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
module.exports = {
coveragePathIgnorePatterns: ['node_modules', 'src/types.ts'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
roots: ['<rootDir>'],
setupFiles: ['<rootDir>/jest.init.js'],
testEnvironment: 'jsdom',
testRegex: '/__tests__/.*\\.(ts|tsx|js)$',
transform: {
'\\.(js|ts|tsx)$': 'babel-jest',
},
verbose: true,
};

2
node_modules/moize/jest.init.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
require('core-js');
require('regenerator-runtime/runtime');

10
node_modules/moize/mjs-test.mjs generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import moize from './mjs';
moize.collectStats();
const memoized = moize((a, b) => a + b, {profileName: 'memoized'});
const result = new Array(10).fill(null).map(() => memoized(1, 2));
console.log(result);
console.log(memoized.getStats());

293
node_modules/moize/mjs/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,293 @@
/* eslint-disable */
import {
Cache as BaseCache,
Memoized as BaseMemoized,
Options as BaseOptions,
} from 'micro-memoize';
export type AnyFn = (...args: any[]) => any;
export type Moizeable = AnyFn & Record<string, any>;
interface MoizedReactElement {
type: any;
props: any;
key: string | number | null;
}
/**
* @deprecated
*
* Use `AnyFn` instead, as it is more flexible and works better with type inference.
*/
export type Fn<Arg extends any = any, Result extends any = any> = (
...args: Arg[]
) => Result;
/**
* @deprecated
*
* This should not longer need to be explicitly used, as inference of the function
* returning the element should suffice.
*/
export type FunctionalComponent<Props extends object> = ((
props: Props
) => MoizedReactElement) & {
displayName?: string;
};
export type Key<Arg extends any = any> = Arg[];
export type Value = any;
export type Cache<MoizeableFn extends Moizeable = Moizeable> =
BaseCache<MoizeableFn>;
export type MicroMemoizeOptions<MoizeableFn extends Moizeable = Moizeable> =
BaseOptions<MoizeableFn>;
export type Expiration = {
expirationMethod: () => void;
key: Key;
timeoutId: ReturnType<typeof setTimeout>;
};
export type OnCacheOperation<MoizeableFn extends Moizeable = Moizeable> = (
cache: Cache<MoizeableFn>,
options: Options<MoizeableFn>,
moized: (...args: any[]) => any
) => void;
export type IsEqual = (cacheKeyArg: any, keyArg: any) => boolean;
export type IsMatchingKey = (cacheKey: Key, key: Key) => boolean;
export type OnExpire = (key: Key) => any;
export type Serialize = (key: Key) => string[];
export type TransformKey = (key: Key) => Key;
export type UpdateCacheForKey = (key: Key) => boolean;
export type Options<MoizeableFn extends Moizeable = Moizeable> = Partial<{
isDeepEqual: boolean;
isPromise: boolean;
isReact: boolean;
isSerialized: boolean;
isShallowEqual: boolean;
matchesArg: IsEqual;
matchesKey: IsMatchingKey;
maxAge: number;
maxArgs: number;
maxSize: number;
onCacheAdd: OnCacheOperation<MoizeableFn>;
onCacheChange: OnCacheOperation<MoizeableFn>;
onCacheHit: OnCacheOperation<MoizeableFn>;
onExpire: OnExpire;
profileName: string;
serializer: Serialize;
transformArgs: TransformKey;
updateCacheForKey: UpdateCacheForKey;
updateExpire: boolean;
}>;
export type StatsProfile = {
calls: number;
hits: number;
};
export type StatsObject = {
calls: number;
hits: number;
usage: string;
};
export type GlobalStatsObject = StatsObject & {
profiles?: Record<string, StatsProfile>;
};
export type StatsCache = {
anonymousProfileNameCounter: number;
isCollectingStats: boolean;
profiles: Record<string, StatsProfile>;
};
export type Memoized<MoizeableFn extends Moizeable = Moizeable> =
BaseMemoized<MoizeableFn>;
export type Moized<
MoizeableFn extends Moizeable = Moizeable,
CombinedOptions extends Options<MoizeableFn> = Options<MoizeableFn>
> = Memoized<MoizeableFn> & {
// values
_microMemoizeOptions: Pick<
CombinedOptions,
'isPromise' | 'maxSize' | 'onCacheAdd' | 'onCacheChange' | 'onCacheHit'
> & {
isEqual: CombinedOptions['matchesArg'];
isMatchingKey: CombinedOptions['matchesKey'];
transformKey: CombinedOptions['transformArgs'];
};
cache: Cache<MoizeableFn>;
cacheSnapshot: Cache<MoizeableFn>;
expirations: Expiration[];
expirationsSnapshot: Expiration[];
options: CombinedOptions;
originalFunction: MoizeableFn;
// react-specific values
contextTypes?: Record<string, Function>;
defaultProps?: Record<string, unknown>;
displayName?: string;
propTypes: Record<string, Function>;
// methods
clear: () => void;
clearStats: () => void;
get: (key: Key) => any;
getStats: () => StatsProfile;
has: (key: Key) => boolean;
isCollectingStats: () => boolean;
isMoized: () => true;
keys: () => Cache<MoizeableFn>['keys'];
remove: (key: Key) => void;
set: (key: Key, value: any) => void;
values: () => Cache<MoizeableFn>['values'];
};
export type MoizeConfiguration<MoizeableFn extends Moizeable = Moizeable> = {
expirations: Expiration[];
options: Options<MoizeableFn>;
originalFunction: MoizeableFn;
};
export type CurriedMoize<OriginalOptions> = <
CurriedFn extends Moizeable,
CurriedOptions extends Options<CurriedFn>
>(
curriedFn: CurriedFn | CurriedOptions,
curriedOptions?: CurriedOptions
) =>
| Moized<CurriedFn, OriginalOptions & CurriedOptions>
| CurriedMoize<OriginalOptions & CurriedOptions>;
export interface MaxAge {
<MaxAge extends number>(maxAge: MaxAge): Moizer<{ maxAge: MaxAge }>;
<MaxAge extends number, UpdateExpire extends boolean>(
maxAge: MaxAge,
expireOptions: UpdateExpire
): Moizer<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
<MaxAge extends number, ExpireHandler extends OnExpire>(
maxAge: MaxAge,
expireOptions: ExpireHandler
): Moizer<{ maxAge: MaxAge; onExpire: ExpireHandler }>;
<
MaxAge extends number,
ExpireHandler extends OnExpire,
ExpireOptions extends {
onExpire: ExpireHandler;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{ maxAge: MaxAge; onExpire: ExpireOptions['onExpire'] }>;
<
MaxAge extends number,
UpdateExpire extends boolean,
ExpireOptions extends {
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
<
MaxAge extends number,
ExpireHandler extends OnExpire,
UpdateExpire extends boolean,
ExpireOptions extends {
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moizer<{
maxAge: MaxAge;
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}>;
}
export interface Moizer<
DefaultOptions extends Options<Moizeable> = Options<Moizeable>
> {
<MoizeableFn extends Moizeable>(fn: MoizeableFn): Moized<
MoizeableFn,
Options<MoizeableFn> & DefaultOptions
>;
<MoizeableFn extends Moizeable, PassedOptions extends Options<MoizeableFn>>(
fn: MoizeableFn,
options: PassedOptions
): Moized<
MoizeableFn,
Options<MoizeableFn> & DefaultOptions & PassedOptions
>;
<MoizedFn extends Moized<Moizeable>>(fn: MoizedFn): Moized<
MoizedFn['fn'],
Options<MoizedFn> & DefaultOptions
>;
<
MoizedFn extends Moized<Moizeable>,
PassedOptions extends Options<MoizedFn>
>(
fn: MoizedFn,
options: PassedOptions
): Moized<
MoizedFn['fn'],
Options<MoizedFn> & DefaultOptions & PassedOptions
>;
<PassedOptions extends Options<Moizeable>>(
options: PassedOptions
): Moizer<PassedOptions>;
}
export interface Moize<
DefaultOptions extends Options<Moizeable> = Options<Moizeable>
> extends Moizer<DefaultOptions> {
clearStats: (profileName?: string) => void;
collectStats: (isCollectingStats?: boolean) => void;
compose: (...moizers: Array<Moize | Moizer>) => Moizer;
deep: Moizer<{ isDeepEqual: true }>;
getStats: (profileName?: string) => StatsObject;
infinite: Moizer;
isCollectingStats: () => boolean;
isMoized: (value: any) => value is Moized;
matchesArg: <Matcher extends IsEqual>(
argMatcher: Matcher
) => Moizer<{ matchesArg: Matcher }>;
matchesKey: <Matcher extends IsMatchingKey>(
keyMatcher: Matcher
) => Moizer<{ matchesKey: Matcher }>;
maxAge: MaxAge;
maxArgs: <MaxArgs extends number>(
args: MaxArgs
) => Moizer<{ maxArgs: MaxArgs }>;
maxSize: <MaxSize extends number>(
size: MaxSize
) => Moizer<{ maxSize: MaxSize }>;
profile: <ProfileName extends string>(
profileName: ProfileName
) => Moizer<{ profileName: ProfileName }>;
promise: Moizer<{ isPromise: true }>;
react: Moizer<{ isReact: true }>;
serialize: Moizer<{ isSerialized: true }>;
serializeWith: <Serializer extends Serialize>(
serializer: Serializer
) => Moizer<{ isSerialized: true; serializer: Serializer }>;
shallow: Moizer<{ isShallowEqual: true }>;
transformArgs: <Transformer extends TransformKey>(
transformer: Transformer
) => Moizer<{ transformArgs: Transformer }>;
updateCacheForKey: <UpdateWhen extends UpdateCacheForKey>(
updateCacheForKey: UpdateWhen
) => Moizer<{ updateCacheForKey: UpdateWhen }>;
}
declare const moize: Moize;
export default moize;

1475
node_modules/moize/mjs/index.mjs generated vendored Normal file

File diff suppressed because it is too large Load Diff

1
node_modules/moize/mjs/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

131
node_modules/moize/package.json generated vendored Normal file
View File

@@ -0,0 +1,131 @@
{
"author": "planttheidea",
"browser": "dist/moize.js",
"browserslist": [
"defaults",
"Explorer >= 9",
"Safari >= 6",
"Opera >= 15",
"iOS >= 8",
"Android >= 4"
],
"bugs": {
"url": "https://github.com/planttheidea/moize/issues"
},
"dependencies": {
"fast-equals": "^3.0.1",
"micro-memoize": "^4.1.2"
},
"description": "Blazing fast memoization based on all parameters passed",
"devDependencies": {
"@babel/cli": "^7.21.5",
"@babel/core": "^7.21.8",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.5",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-terser": "^0.4.1",
"@types/bluebird": "^3.5.38",
"@types/eslint": "^8.37.0",
"@types/jest": "^29.5.1",
"@types/lodash": "^4.14.194",
"@types/memoizee": "^0.4.8",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"babel-jest": "^29.5.0",
"babel-loader": "^9.1.2",
"benchmark": "^2.1.4",
"bluebird": "^3.7.2",
"cli-table2": "^0.2.0",
"core-js": "^3.30.2",
"eslint": "^8.40.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-plugin-react": "^7.32.2",
"eslint-webpack-plugin": "^4.0.1",
"fast-memoize": "^2.5.2",
"html-webpack-plugin": "^5.5.1",
"in-publish": "^2.0.1",
"ink-docstrap": "^1.3.2",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"jsdoc": "^4.0.2",
"jsdoc-babel": "^0.5.0",
"lodash": "^4.17.21",
"lru-memoize": "^1.1.0",
"mem": "^8.1.1",
"memoizee": "^0.4.15",
"memoizerific": "^1.11.3",
"ora": "^5.4.1",
"prop-types": "^15.8.1",
"q": "^1.5.1",
"ramda": "^0.29.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"regenerator-runtime": "^0.13.11",
"release-it": "^15.10.3",
"rimraf": "^5.0.0",
"rollup": "^3.21.5",
"tslib": "^2.5.0",
"typedoc": "^0.24.7",
"typescript": "^5.0.4",
"underscore": "^1.13.6",
"webpack": "^5.82.0",
"webpack-cli": "^5.1.0",
"webpack-dev-server": "^4.15.0"
},
"homepage": "https://github.com/planttheidea/moize#readme",
"keywords": [
"cache",
"expire",
"lru",
"memoize",
"memoization",
"optimize",
"performance",
"promise",
"ttl"
],
"license": "MIT",
"main": "dist/moize.cjs.js",
"module": "dist/moize.esm.js",
"name": "moize",
"repository": {
"type": "git",
"url": "git+https://github.com/planttheidea/moize.git"
},
"scripts": {
"benchmark": "npm run dist && node benchmark/index.js",
"benchmark:alternative": "npm run transpile:lib -- --no-comments && BENCHMARK_SUITE=alternative node benchmark/index.js",
"benchmark:array": "npm run transpile:lib -- --no-comments && BENCHMARK_SUITE=array node benchmark/index.js",
"benchmark:object": "npm run transpile:lib -- --no-comments && BENCHMARK_SUITE=object node benchmark/index.js",
"benchmark:primitive": "npm run transpile:lib -- --no-comments && BENCHMARK_SUITE=primitive node benchmark/index.js",
"benchmark:react": "npm run transpile:lib -- --no-comments && BENCHMARK_SUITE=react node benchmark/index.js",
"build": "NODE_ENV=production rollup -c --bundleConfigAsCjs",
"clean:dist": "rimraf dist",
"clean:docs": "rimraf docs",
"clean:mjs": "rimraf mjs",
"copy:mjs": "npm run clean:mjs && node ./es-to-mjs.js",
"copy:types": "cp src/types.ts index.d.ts",
"dev": "NODE_ENV=development webpack serve --progress --config=webpack/webpack.config.js",
"dist": "npm run clean:dist && npm run build",
"docs": "npm run clean:docs && typedoc",
"lint": "NODE_ENV=test eslint src/*.ts",
"lint:fix": "npm run lint -- --fix",
"release": "release-it",
"release:beta": "release-it --config=.release-it.beta.json",
"release:scripts": "npm run lint && npm run typecheck && npm run test:coverage && npm run dist && npm run copy:mjs",
"start": "npm run dev",
"test": "NODE_ENV=test NODE_PATH=. jest",
"test:coverage": "npm test -- --coverage",
"test:watch": "npm test -- --watch",
"typecheck": "tsc --noEmit"
},
"sideEffects": false,
"types": "./index.d.ts",
"version": "6.1.6"
}

97
node_modules/moize/src/component.ts generated vendored Normal file
View File

@@ -0,0 +1,97 @@
import { copyStaticProperties } from './instance';
import { setName } from './utils';
import type {
Moize,
Moized as MoizedFunction,
Moizeable,
Options,
} from '../index.d';
// This was stolen from React internals, which allows us to create React elements without needing
// a dependency on the React library itself.
const REACT_ELEMENT_TYPE =
typeof Symbol === 'function' && Symbol.for
? Symbol.for('react.element')
: 0xeac7;
/**
* @private
*
* @description
* Create a component that memoizes based on `props` and legacy `context`
* on a per-instance basis. This requires creating a component class to
* store the memoized function. The cost is quite low, and avoids the
* need to have access to the React dependency by basically re-creating
* the basic essentials for a component class and the results of the
* `createElement` function.
*
* @param moizer the top-level moize method
* @param fn the component to memoize
* @param options the memoization options
* @returns the memoized component
*/
export function createMoizedComponent<MoizeableFn extends Moizeable>(
moizer: Moize,
fn: MoizeableFn,
options: Options<MoizeableFn>
) {
/**
* This is a hack override setting the necessary options
* for a React component to be memoized. In the main `moize`
* method, if the `isReact` option is set it is short-circuited
* to call this function, and these overrides allow the
* necessary transformKey method to be derived.
*
* The order is based on:
* 1) Set the necessary aspects of transformKey for React components.
* 2) Allow setting of other options and overrides of those aspects
* if desired (for example, `isDeepEqual` will use deep equality).
* 3) Always set `isReact` to false to prevent infinite loop.
*/
const reactMoizer = moizer({
maxArgs: 2,
isShallowEqual: true,
...options,
isReact: false,
});
if (!fn.displayName) {
// @ts-ignore - allow setting of displayName
fn.displayName = fn.name || 'Component';
}
function Moized<Props extends Record<string, unknown>, Context, Updater>(
this: any,
props: Props,
context: Context,
updater: Updater
) {
this.props = props;
this.context = context;
this.updater = updater;
this.MoizedComponent = reactMoizer(fn);
}
Moized.prototype.isReactComponent = {};
Moized.prototype.render = function (): ReturnType<MoizeableFn> {
return {
$$typeof: REACT_ELEMENT_TYPE,
type: this.MoizedComponent,
props: this.props,
ref: null,
key: null,
_owner: null,
} as ReturnType<MoizeableFn>;
};
copyStaticProperties(fn, Moized, ['contextType', 'contextTypes']);
Moized.displayName = `Moized(${fn.displayName || fn.name || 'Component'})`;
setName(Moized as MoizedFunction, fn.name, options.profileName);
return Moized;
}

25
node_modules/moize/src/constants.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
import type { AnyFn, Options } from '../index.d';
/**
* @private
*
* @constant DEFAULT_OPTIONS
*/
export const DEFAULT_OPTIONS: Options<AnyFn> = {
isDeepEqual: false,
isPromise: false,
isReact: false,
isSerialized: false,
isShallowEqual: false,
matchesArg: undefined,
matchesKey: undefined,
maxAge: undefined,
maxArgs: undefined,
maxSize: 1,
onExpire: undefined,
profileName: undefined,
serializer: undefined,
updateCacheForKey: undefined,
transformArgs: undefined,
updateExpire: false,
};

616
node_modules/moize/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,616 @@
import memoize from 'micro-memoize';
import { createMoizedComponent } from './component';
import { DEFAULT_OPTIONS } from './constants';
import { createMoizeInstance } from './instance';
import { getMaxAgeOptions } from './maxAge';
import {
createOnCacheOperation,
getIsEqual,
getIsMatchingKey,
getTransformKey,
} from './options';
import {
clearStats,
collectStats,
getDefaultProfileName,
getStats,
getStatsOptions,
statsCache,
} from './stats';
import { createRefreshableMoized } from './updateCacheForKey';
import { combine, compose, isMoized, mergeOptions, setName } from './utils';
import type {
Expiration,
IsEqual,
IsMatchingKey,
MicroMemoizeOptions,
Moize,
Moizeable,
Moized,
OnExpire,
Options,
Serialize,
TransformKey,
UpdateCacheForKey,
} from '../index.d';
/**
* @module moize
*/
/**
* @description
* memoize a function based its arguments passed, potentially improving runtime performance
*
* @example
* import moize from 'moize';
*
* // standard implementation
* const fn = (foo, bar) => `${foo} ${bar}`;
* const memoizedFn = moize(fn);
*
* // implementation with options
* const fn = async (id) => get(`http://foo.com/${id}`);
* const memoizedFn = moize(fn, {isPromise: true, maxSize: 5});
*
* // implementation with convenience methods
* const Foo = ({foo}) => <div>{foo}</div>;
* const MemoizedFoo = moize.react(Foo);
*
* @param fn the function to memoized, or a list of options when currying
* @param [options=DEFAULT_OPTIONS] the options to apply
* @returns the memoized function
*/
const moize: Moize = function <
MoizeableFn extends Moizeable,
PassedOptions extends Options<MoizeableFn>
>(fn: MoizeableFn | PassedOptions, passedOptions?: PassedOptions) {
type CombinedOptions = Omit<Options<MoizeableFn>, keyof PassedOptions> &
PassedOptions;
const options: Options<MoizeableFn> = passedOptions || DEFAULT_OPTIONS;
if (isMoized(fn)) {
const moizeable = fn.originalFunction as MoizeableFn;
const mergedOptions = mergeOptions(
fn.options,
options
) as CombinedOptions;
return moize<MoizeableFn, CombinedOptions>(moizeable, mergedOptions);
}
if (typeof fn === 'object') {
return function <
CurriedFn extends Moizeable,
CurriedOptions extends Options<CurriedFn>
>(
curriedFn: CurriedFn | CurriedOptions,
curriedOptions: CurriedOptions
) {
type CombinedCurriedOptions = Omit<
CombinedOptions,
keyof CurriedOptions
> &
CurriedOptions;
if (typeof curriedFn === 'function') {
const mergedOptions = mergeOptions(
fn as CombinedOptions,
curriedOptions
) as CombinedCurriedOptions;
return moize(curriedFn, mergedOptions);
}
const mergedOptions = mergeOptions(
fn as CombinedOptions,
curriedFn as CurriedOptions
);
return moize(mergedOptions);
};
}
if (options.isReact) {
return createMoizedComponent(moize, fn, options);
}
const coalescedOptions: Options<MoizeableFn> = {
...DEFAULT_OPTIONS,
...options,
maxAge:
typeof options.maxAge === 'number' && options.maxAge >= 0
? options.maxAge
: DEFAULT_OPTIONS.maxAge,
maxArgs:
typeof options.maxArgs === 'number' && options.maxArgs >= 0
? options.maxArgs
: DEFAULT_OPTIONS.maxArgs,
maxSize:
typeof options.maxSize === 'number' && options.maxSize >= 0
? options.maxSize
: DEFAULT_OPTIONS.maxSize,
profileName: options.profileName || getDefaultProfileName(fn),
};
const expirations: Array<Expiration> = [];
const {
matchesArg: equalsIgnored,
isDeepEqual: isDeepEqualIgnored,
isPromise,
isReact: isReactIgnored,
isSerialized: isSerialzedIgnored,
isShallowEqual: isShallowEqualIgnored,
matchesKey: matchesKeyIgnored,
maxAge: maxAgeIgnored,
maxArgs: maxArgsIgnored,
maxSize,
onCacheAdd,
onCacheChange,
onCacheHit,
onExpire: onExpireIgnored,
profileName: profileNameIgnored,
serializer: serializerIgnored,
updateCacheForKey,
transformArgs: transformArgsIgnored,
updateExpire: updateExpireIgnored,
...customOptions
} = coalescedOptions;
const isEqual = getIsEqual(coalescedOptions);
const isMatchingKey = getIsMatchingKey(coalescedOptions);
const maxAgeOptions = getMaxAgeOptions(
expirations,
coalescedOptions,
isEqual,
isMatchingKey
);
const statsOptions = getStatsOptions(coalescedOptions);
const transformKey = getTransformKey(coalescedOptions);
const microMemoizeOptions: MicroMemoizeOptions<MoizeableFn> = {
...customOptions,
isEqual,
isMatchingKey,
isPromise,
maxSize,
onCacheAdd: createOnCacheOperation(
combine(
onCacheAdd,
maxAgeOptions.onCacheAdd,
statsOptions.onCacheAdd
)
),
onCacheChange: createOnCacheOperation(onCacheChange),
onCacheHit: createOnCacheOperation(
combine(
onCacheHit,
maxAgeOptions.onCacheHit,
statsOptions.onCacheHit
)
),
transformKey,
};
const memoized = memoize(fn, microMemoizeOptions);
let moized = createMoizeInstance<MoizeableFn, CombinedOptions>(memoized, {
expirations,
options: coalescedOptions,
originalFunction: fn,
});
if (updateCacheForKey) {
moized = createRefreshableMoized<typeof moized>(moized);
}
setName(moized, (fn as Moizeable).name, options.profileName);
return moized;
};
/**
* @function
* @name clearStats
* @memberof module:moize
* @alias moize.clearStats
*
* @description
* clear all existing stats stored
*/
moize.clearStats = clearStats;
/**
* @function
* @name collectStats
* @memberof module:moize
* @alias moize.collectStats
*
* @description
* start collecting statistics
*/
moize.collectStats = collectStats;
/**
* @function
* @name compose
* @memberof module:moize
* @alias moize.compose
*
* @description
* method to compose moized methods and return a single moized function
*
* @param moized the functions to compose
* @returns the composed function
*/
moize.compose = function (...moized: Moize[]) {
return compose<Moize>(...moized) || moize;
};
/**
* @function
* @name deep
* @memberof module:moize
* @alias moize.deep
*
* @description
* should deep equality check be used
*
* @returns the moizer function
*/
moize.deep = moize({ isDeepEqual: true });
/**
* @function
* @name getStats
* @memberof module:moize
* @alias moize.getStats
*
* @description
* get the statistics of a given profile, or overall usage
*
* @returns statistics for a given profile or overall usage
*/
moize.getStats = getStats;
/**
* @function
* @name infinite
* @memberof module:moize
* @alias moize.infinite
*
* @description
* a moized method that will remove all limits from the cache size
*
* @returns the moizer function
*/
moize.infinite = moize({ maxSize: Infinity });
/**
* @function
* @name isCollectingStats
* @memberof module:moize
* @alias moize.isCollectingStats
*
* @description
* are stats being collected
*
* @returns are stats being collected
*/
moize.isCollectingStats = function isCollectingStats(): boolean {
return statsCache.isCollectingStats;
};
/**
* @function
* @name isMoized
* @memberof module:moize
* @alias moize.isMoized
*
* @description
* is the fn passed a moized function
*
* @param fn the object to test
* @returns is fn a moized function
*/
moize.isMoized = function isMoized(fn: any): fn is Moized {
return typeof fn === 'function' && !!fn.isMoized;
};
/**
* @function
* @name matchesArg
* @memberof module:moize
* @alias moize.matchesArg
*
* @description
* a moized method where the arg matching method is the custom one passed
*
* @param keyMatcher the method to compare against those in cache
* @returns the moizer function
*/
moize.matchesArg = function (argMatcher: IsEqual) {
return moize({ matchesArg: argMatcher });
};
/**
* @function
* @name matchesKey
* @memberof module:moize
* @alias moize.matchesKey
*
* @description
* a moized method where the key matching method is the custom one passed
*
* @param keyMatcher the method to compare against those in cache
* @returns the moizer function
*/
moize.matchesKey = function (keyMatcher: IsMatchingKey) {
return moize({ matchesKey: keyMatcher });
};
function maxAge<MaxAge extends number>(
maxAge: MaxAge
): Moize<{ maxAge: MaxAge }>;
function maxAge<MaxAge extends number, UpdateExpire extends boolean>(
maxAge: MaxAge,
expireOptions: UpdateExpire
): Moize<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
function maxAge<MaxAge extends number, ExpireHandler extends OnExpire>(
maxAge: MaxAge,
expireOptions: ExpireHandler
): Moize<{ maxAge: MaxAge; onExpire: ExpireHandler }>;
function maxAge<
MaxAge extends number,
ExpireHandler extends OnExpire,
ExpireOptions extends {
onExpire: ExpireHandler;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moize<{ maxAge: MaxAge; onExpire: ExpireOptions['onExpire'] }>;
function maxAge<
MaxAge extends number,
UpdateExpire extends boolean,
ExpireOptions extends {
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moize<{ maxAge: MaxAge; updateExpire: UpdateExpire }>;
function maxAge<
MaxAge extends number,
ExpireHandler extends OnExpire,
UpdateExpire extends boolean,
ExpireOptions extends {
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions: ExpireOptions
): Moize<{
maxAge: MaxAge;
onExpire: ExpireHandler;
updateExpire: UpdateExpire;
}>;
function maxAge<
MaxAge extends number,
ExpireHandler extends OnExpire,
UpdateExpire extends boolean,
ExpireOptions extends {
onExpire?: ExpireHandler;
updateExpire?: UpdateExpire;
}
>(
maxAge: MaxAge,
expireOptions?: ExpireHandler | UpdateExpire | ExpireOptions
) {
if (expireOptions === true) {
return moize({
maxAge,
updateExpire: expireOptions,
});
}
if (typeof expireOptions === 'object') {
const { onExpire, updateExpire } = expireOptions;
return moize({
maxAge,
onExpire,
updateExpire,
});
}
if (typeof expireOptions === 'function') {
return moize({
maxAge,
onExpire: expireOptions,
updateExpire: true,
});
}
return moize({ maxAge });
}
/**
* @function
* @name maxAge
* @memberof module:moize
* @alias moize.maxAge
*
* @description
* a moized method where the age of the cache is limited to the number of milliseconds passed
*
* @param maxAge the TTL of the value in cache
* @returns the moizer function
*/
moize.maxAge = maxAge;
/**
* @function
* @name maxArgs
* @memberof module:moize
* @alias moize.maxArgs
*
* @description
* a moized method where the number of arguments used for determining cache is limited to the value passed
*
* @param maxArgs the number of args to base the key on
* @returns the moizer function
*/
moize.maxArgs = function maxArgs(maxArgs: number) {
return moize({ maxArgs });
};
/**
* @function
* @name maxSize
* @memberof module:moize
* @alias moize.maxSize
*
* @description
* a moized method where the total size of the cache is limited to the value passed
*
* @param maxSize the maximum size of the cache
* @returns the moizer function
*/
moize.maxSize = function maxSize(maxSize: number) {
return moize({ maxSize });
};
/**
* @function
* @name profile
* @memberof module:moize
* @alias moize.profile
*
* @description
* a moized method with a profile name
*
* @returns the moizer function
*/
moize.profile = function (profileName: string) {
return moize({ profileName });
};
/**
* @function
* @name promise
* @memberof module:moize
* @alias moize.promise
*
* @description
* a moized method specific to caching resolved promise / async values
*
* @returns the moizer function
*/
moize.promise = moize({
isPromise: true,
updateExpire: true,
});
/**
* @function
* @name react
* @memberof module:moize
* @alias moize.react
*
* @description
* a moized method specific to caching React element values
*
* @returns the moizer function
*/
moize.react = moize({ isReact: true });
/**
* @function
* @name serialize
* @memberof module:moize
* @alias moize.serialize
*
* @description
* a moized method that will serialize the arguments passed to use as the cache key
*
* @returns the moizer function
*/
moize.serialize = moize({ isSerialized: true });
/**
* @function
* @name serializeWith
* @memberof module:moize
* @alias moize.serializeWith
*
* @description
* a moized method that will serialize the arguments passed to use as the cache key
* based on the serializer passed
*
* @returns the moizer function
*/
moize.serializeWith = function (serializer: Serialize) {
return moize({ isSerialized: true, serializer });
};
/**
* @function
* @name shallow
* @memberof module:moize
* @alias moize.shallow
*
* @description
* should shallow equality check be used
*
* @returns the moizer function
*/
moize.shallow = moize({ isShallowEqual: true });
/**
* @function
* @name transformArgs
* @memberof module:moize
* @alias moize.transformArgs
*
* @description
* transform the args to allow for specific cache key comparison
*
* @param transformArgs the args transformer
* @returns the moizer function
*/
moize.transformArgs = <Transformer extends TransformKey>(
transformArgs: Transformer
) => moize({ transformArgs });
/**
* @function
* @name updateCacheForKey
* @memberof module:moize
* @alias moize.updateCacheForKey
*
* @description
* update the cache for a given key when the method passed returns truthy
*
* @param updateCacheForKey the method to determine when to update cache
* @returns the moizer function
*/
moize.updateCacheForKey = <UpdateWhen extends UpdateCacheForKey>(
updateCacheForKey: UpdateWhen
) => moize({ updateCacheForKey });
// Add self-referring `default` property for edge-case cross-compatibility of mixed ESM/CommonJS usage.
// This property is frozen and non-enumerable to avoid visibility on iteration or accidental overrides.
Object.defineProperty(moize, 'default', {
configurable: false,
enumerable: false,
value: moize,
writable: false,
});
export default moize;

326
node_modules/moize/src/instance.ts generated vendored Normal file
View File

@@ -0,0 +1,326 @@
import { clearExpiration } from './maxAge';
import { clearStats, getStats } from './stats';
import { createFindKeyIndex } from './utils';
import type {
Key,
Memoized,
Moizeable,
MoizeConfiguration,
Moized,
Options,
StatsProfile,
} from '../index.d';
const ALWAYS_SKIPPED_PROPERTIES: Record<string, boolean> = {
arguments: true,
callee: true,
caller: true,
constructor: true,
length: true,
name: true,
prototype: true,
};
/**
* @private
*
* @description
* copy the static properties from the original function to the moized
* function
*
* @param originalFn the function copying from
* @param newFn the function copying to
* @param skippedProperties the list of skipped properties, if any
*/
export function copyStaticProperties<
OriginalMoizeableFn extends Moizeable,
NewMoizeableFn extends Moizeable
>(
originalFn: OriginalMoizeableFn,
newFn: NewMoizeableFn,
skippedProperties: string[] = []
) {
Object.getOwnPropertyNames(originalFn).forEach((property) => {
if (
!ALWAYS_SKIPPED_PROPERTIES[property] &&
skippedProperties.indexOf(property) === -1
) {
const descriptor = Object.getOwnPropertyDescriptor(
originalFn,
property
);
if (descriptor.get || descriptor.set) {
Object.defineProperty(newFn, property, descriptor);
} else {
// @ts-expect-error - properites may not align
newFn[property] = originalFn[property];
}
}
});
}
/**
* @private
*
* @description
* add methods to the moized fuction object that allow extra features
*
* @param memoized the memoized function from micro-memoize
*/
export function addInstanceMethods<MoizeableFn extends Moizeable>(
memoized: Moizeable,
{ expirations }: MoizeConfiguration<MoizeableFn>
) {
const { options } = memoized;
const findKeyIndex = createFindKeyIndex(
options.isEqual,
options.isMatchingKey
);
const moized = memoized as unknown as Moized<
MoizeableFn,
Options<MoizeableFn>
>;
moized.clear = function () {
const {
_microMemoizeOptions: { onCacheChange },
cache,
} = moized;
cache.keys.length = 0;
cache.values.length = 0;
if (onCacheChange) {
onCacheChange(cache, moized.options, moized);
}
return true;
};
moized.clearStats = function () {
clearStats(moized.options.profileName);
};
moized.get = function (key: Key) {
const {
_microMemoizeOptions: { transformKey },
cache,
} = moized;
const cacheKey = transformKey ? transformKey(key) : key;
const keyIndex = findKeyIndex(cache.keys, cacheKey);
return keyIndex !== -1 ? moized.apply(this, key) : undefined;
};
moized.getStats = function (): StatsProfile {
return getStats(moized.options.profileName);
};
moized.has = function (key: Key) {
const { transformKey } = moized._microMemoizeOptions;
const cacheKey = transformKey ? transformKey(key) : key;
return findKeyIndex(moized.cache.keys, cacheKey) !== -1;
};
moized.keys = function () {
return moized.cacheSnapshot.keys;
};
moized.remove = function (key: Key) {
const {
_microMemoizeOptions: { onCacheChange, transformKey },
cache,
} = moized;
const keyIndex = findKeyIndex(
cache.keys,
transformKey ? transformKey(key) : key
);
if (keyIndex === -1) {
return false;
}
const existingKey = cache.keys[keyIndex];
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
if (onCacheChange) {
onCacheChange(cache, moized.options, moized);
}
clearExpiration(expirations, existingKey, true);
return true;
};
moized.set = function (key: Key, value: any) {
const { _microMemoizeOptions, cache, options } = moized;
const { onCacheAdd, onCacheChange, transformKey } =
_microMemoizeOptions;
const cacheKey = transformKey ? transformKey(key) : key;
const keyIndex = findKeyIndex(cache.keys, cacheKey);
if (keyIndex === -1) {
const cutoff = options.maxSize - 1;
if (cache.size > cutoff) {
cache.keys.length = cutoff;
cache.values.length = cutoff;
}
cache.keys.unshift(cacheKey);
cache.values.unshift(value);
if (options.isPromise) {
cache.updateAsyncCache(moized);
}
if (onCacheAdd) {
onCacheAdd(cache, options, moized);
}
if (onCacheChange) {
onCacheChange(cache, options, moized);
}
} else {
const existingKey = cache.keys[keyIndex];
cache.values[keyIndex] = value;
if (keyIndex > 0) {
cache.orderByLru(existingKey, value, keyIndex);
}
if (options.isPromise) {
cache.updateAsyncCache(moized);
}
if (typeof onCacheChange === 'function') {
onCacheChange(cache, options, moized);
}
}
};
moized.values = function () {
return moized.cacheSnapshot.values;
};
}
/**
* @private
*
* @description
* add propeties to the moized fuction object that surfaces extra information
*
* @param memoized the memoized function
* @param expirations the list of expirations for cache items
* @param options the options passed to the moizer
* @param originalFunction the function that is being memoized
*/
export function addInstanceProperties<MoizeableFn extends Moizeable>(
memoized: Memoized<MoizeableFn>,
{
expirations,
options: moizeOptions,
originalFunction,
}: MoizeConfiguration<MoizeableFn>
) {
const { options: microMemoizeOptions } = memoized;
Object.defineProperties(memoized, {
_microMemoizeOptions: {
configurable: true,
get() {
return microMemoizeOptions;
},
},
cacheSnapshot: {
configurable: true,
get() {
const { cache: currentCache } = memoized;
return {
keys: currentCache.keys.slice(0),
size: currentCache.size,
values: currentCache.values.slice(0),
};
},
},
expirations: {
configurable: true,
get() {
return expirations;
},
},
expirationsSnapshot: {
configurable: true,
get() {
return expirations.slice(0);
},
},
isMoized: {
configurable: true,
get() {
return true;
},
},
options: {
configurable: true,
get() {
return moizeOptions;
},
},
originalFunction: {
configurable: true,
get() {
return originalFunction;
},
},
});
const moized = memoized as unknown as Moized<
MoizeableFn,
Options<MoizeableFn>
>;
copyStaticProperties(originalFunction, moized);
}
/**
* @private
*
* @description
* add methods and properties to the memoized function for more features
*
* @param memoized the memoized function
* @param configuration the configuration object for the instance
* @returns the memoized function passed
*/
export function createMoizeInstance<
MoizeableFn extends Moizeable,
CombinedOptions extends Options<MoizeableFn>
>(
memoized: Memoized<MoizeableFn>,
configuration: MoizeConfiguration<MoizeableFn>
) {
addInstanceMethods<MoizeableFn>(memoized, configuration);
addInstanceProperties<MoizeableFn>(memoized, configuration);
return memoized as Moized<MoizeableFn, CombinedOptions>;
}

197
node_modules/moize/src/maxAge.ts generated vendored Normal file
View File

@@ -0,0 +1,197 @@
import { createFindKeyIndex, findExpirationIndex } from './utils';
import type {
AnyFn,
Cache,
Expiration,
IsEqual,
IsMatchingKey,
Key,
OnCacheOperation,
Options,
} from '../index.d';
/**
* @private
*
* @description
* clear an active expiration and remove it from the list if applicable
*
* @param expirations the list of expirations
* @param key the key to clear
* @param shouldRemove should the expiration be removed from the list
*/
export function clearExpiration(
expirations: Expiration[],
key: Key,
shouldRemove?: boolean
) {
const expirationIndex = findExpirationIndex(expirations, key);
if (expirationIndex !== -1) {
clearTimeout(expirations[expirationIndex].timeoutId);
if (shouldRemove) {
expirations.splice(expirationIndex, 1);
}
}
}
/**
* @private
*
* @description
* Create the timeout for the given expiration method. If the ability to `unref`
* exists, then apply it to avoid process locks in NodeJS.
*
* @param expirationMethod the method to fire upon expiration
* @param maxAge the time to expire after
* @returns the timeout ID
*/
export function createTimeout(expirationMethod: () => void, maxAge: number) {
const timeoutId = setTimeout(expirationMethod, maxAge);
if (typeof timeoutId.unref === 'function') {
timeoutId.unref();
}
return timeoutId;
}
/**
* @private
*
* @description
* create a function that, when an item is added to the cache, adds an expiration for it
*
* @param expirations the mutable expirations array
* @param options the options passed on initialization
* @param isEqual the function to check argument equality
* @param isMatchingKey the function to check complete key equality
* @returns the onCacheAdd function to handle expirations
*/
export function createOnCacheAddSetExpiration<MoizeableFn extends AnyFn>(
expirations: Expiration[],
options: Options<MoizeableFn>,
isEqual: IsEqual,
isMatchingKey: IsMatchingKey
): OnCacheOperation<MoizeableFn> {
const { maxAge } = options;
return function onCacheAdd(
cache: Cache<MoizeableFn>,
moizedOptions: Options<MoizeableFn>,
moized: MoizeableFn
) {
const key: any = cache.keys[0];
if (findExpirationIndex(expirations, key) === -1) {
const expirationMethod = function () {
const findKeyIndex = createFindKeyIndex(isEqual, isMatchingKey);
const keyIndex: number = findKeyIndex(cache.keys, key);
const value: any = cache.values[keyIndex];
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
if (typeof options.onCacheChange === 'function') {
options.onCacheChange(cache, moizedOptions, moized);
}
}
clearExpiration(expirations, key, true);
if (
typeof options.onExpire === 'function' &&
options.onExpire(key) === false
) {
cache.keys.unshift(key);
cache.values.unshift(value);
onCacheAdd(cache, moizedOptions, moized);
if (typeof options.onCacheChange === 'function') {
options.onCacheChange(cache, moizedOptions, moized);
}
}
};
expirations.push({
expirationMethod,
key,
timeoutId: createTimeout(expirationMethod, maxAge),
});
}
};
}
/**
* @private
*
* @description
* creates a function that, when a cache item is hit, reset the expiration
*
* @param expirations the mutable expirations array
* @param options the options passed on initialization
* @returns the onCacheAdd function to handle expirations
*/
export function createOnCacheHitResetExpiration<MoizeableFn extends AnyFn>(
expirations: Expiration[],
options: Options<MoizeableFn>
): OnCacheOperation<MoizeableFn> {
return function onCacheHit(cache: Cache<MoizeableFn>) {
const key = cache.keys[0];
const expirationIndex = findExpirationIndex(expirations, key);
if (~expirationIndex) {
clearExpiration(expirations, key, false);
expirations[expirationIndex].timeoutId = createTimeout(
expirations[expirationIndex].expirationMethod,
options.maxAge
);
}
};
}
/**
* @private
*
* @description
* get the micro-memoize options specific to the maxAge option
*
* @param expirations the expirations for the memoized function
* @param options the options passed to the moizer
* @param isEqual the function to test equality of the key on a per-argument basis
* @param isMatchingKey the function to test equality of the whole key
* @returns the object of options based on the entries passed
*/
export function getMaxAgeOptions<MoizeableFn extends AnyFn>(
expirations: Expiration[],
options: Options<MoizeableFn>,
isEqual: IsEqual,
isMatchingKey: IsMatchingKey
): {
onCacheAdd: OnCacheOperation<MoizeableFn> | undefined;
onCacheHit: OnCacheOperation<MoizeableFn> | undefined;
} {
const onCacheAdd =
typeof options.maxAge === 'number' && isFinite(options.maxAge)
? createOnCacheAddSetExpiration(
expirations,
options,
isEqual,
isMatchingKey
)
: undefined;
return {
onCacheAdd,
onCacheHit:
onCacheAdd && options.updateExpire
? createOnCacheHitResetExpiration(expirations, options)
: undefined,
};
}

42
node_modules/moize/src/maxArgs.ts generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import type { Key } from '../index.d';
export function createGetInitialArgs(size: number) {
/**
* @private
*
* @description
* take the first N number of items from the array (faster than slice)
*
* @param args the args to take from
* @returns the shortened list of args as an array
*/
return function (args: Key): Key {
if (size >= args.length) {
return args;
}
if (size === 0) {
return [];
}
if (size === 1) {
return [args[0]];
}
if (size === 2) {
return [args[0], args[1]];
}
if (size === 3) {
return [args[0], args[1], args[2]];
}
const clone = [];
for (let index = 0; index < size; index++) {
clone[index] = args[index];
}
return clone;
};
}

87
node_modules/moize/src/options.ts generated vendored Normal file
View File

@@ -0,0 +1,87 @@
import { deepEqual, sameValueZeroEqual, shallowEqual } from 'fast-equals';
import { createGetInitialArgs } from './maxArgs';
import { getIsSerializedKeyEqual, getSerializerFunction } from './serialize';
import { compose } from './utils';
import type {
Cache,
IsEqual,
IsMatchingKey,
MicroMemoizeOptions,
Moizeable,
Moized,
OnCacheOperation,
Options,
TransformKey,
} from '../index.d';
export function createOnCacheOperation<MoizeableFn extends Moizeable>(
fn?: OnCacheOperation<MoizeableFn>
): OnCacheOperation<MoizeableFn> {
if (typeof fn === 'function') {
return (
_cacheIgnored: Cache<MoizeableFn>,
_microMemoizeOptionsIgnored: MicroMemoizeOptions<MoizeableFn>,
memoized: Moized
): void => fn(memoized.cache, memoized.options, memoized);
}
}
/**
* @private
*
* @description
* get the isEqual method passed to micro-memoize
*
* @param options the options passed to the moizer
* @returns the isEqual method to apply
*/
export function getIsEqual<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
): IsEqual {
return (
options.matchesArg ||
(options.isDeepEqual && deepEqual) ||
(options.isShallowEqual && shallowEqual) ||
sameValueZeroEqual
);
}
/**
* @private
*
* @description
* get the isEqual method passed to micro-memoize
*
* @param options the options passed to the moizer
* @returns the isEqual method to apply
*/
export function getIsMatchingKey<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
): IsMatchingKey | undefined {
return (
options.matchesKey ||
(options.isSerialized && getIsSerializedKeyEqual) ||
undefined
);
}
/**
* @private
*
* @description
* get the function that will transform the key based on the arguments passed
*
* @param options the options passed to the moizer
* @returns the function to transform the key with
*/
export function getTransformKey<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
): TransformKey | undefined {
return compose(
options.isSerialized && getSerializerFunction(options),
typeof options.transformArgs === 'function' && options.transformArgs,
typeof options.maxArgs === 'number' &&
createGetInitialArgs(options.maxArgs)
) as TransformKey;
}

142
node_modules/moize/src/serialize.ts generated vendored Normal file
View File

@@ -0,0 +1,142 @@
import type { Key, Moizeable, Options } from '../index.d';
/**
* @function getCutoff
*
* @description
* faster `Array.prototype.indexOf` implementation build for slicing / splicing
*
* @param array the array to match the value in
* @param value the value to match
* @returns the matching index, or -1
*/
function getCutoff(array: any[], value: any) {
const { length } = array;
for (let index = 0; index < length; ++index) {
if (array[index] === value) {
return index + 1;
}
}
return 0;
}
/**
* @private
*
* @description
* custom replacer for the stringify function
*
* @returns if function then toString of it, else the value itself
*/
export function createDefaultReplacer() {
const cache: any[] = [];
const keys: string[] = [];
return function defaultReplacer(key: string, value: any) {
const type = typeof value;
if (type === 'function' || type === 'symbol') {
return value.toString();
}
if (typeof value === 'object') {
if (cache.length) {
const thisCutoff = getCutoff(cache, this);
if (thisCutoff === 0) {
cache[cache.length] = this;
} else {
cache.splice(thisCutoff);
keys.splice(thisCutoff);
}
keys[keys.length] = key;
const valueCutoff = getCutoff(cache, value);
if (valueCutoff !== 0) {
return `[ref=${
keys.slice(0, valueCutoff).join('.') || '.'
}]`;
}
} else {
cache[0] = value;
keys[0] = key;
}
return value;
}
return '' + value;
};
}
/**
* @private
*
* @description
* get the stringified version of the argument passed
*
* @param arg argument to stringify
* @returns the stringified argument
*/
export function getStringifiedArgument<Type>(arg: Type) {
const typeOfArg = typeof arg;
return arg && (typeOfArg === 'object' || typeOfArg === 'function')
? JSON.stringify(arg, createDefaultReplacer())
: arg;
}
/**
* @private
*
* @description
* serialize the arguments passed
*
* @param options the options passed to the moizer
* @param options.maxArgs the cap on the number of arguments used in serialization
* @returns argument serialization method
*/
export function defaultArgumentSerializer(args: Key) {
let key = '|';
for (let index = 0; index < args.length; index++) {
key += getStringifiedArgument(args[index]) + '|';
}
return [key];
}
/**
* @private
*
* @description
* based on the options passed, either use the serializer passed or generate the internal one
*
* @param options the options passed to the moized function
* @returns the function to use in serializing the arguments
*/
export function getSerializerFunction<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
) {
return typeof options.serializer === 'function'
? options.serializer
: defaultArgumentSerializer;
}
/**
* @private
*
* @description
* are the serialized keys equal to one another
*
* @param cacheKey the cache key to compare
* @param key the key to test
* @returns are the keys equal
*/
export function getIsSerializedKeyEqual(cacheKey: Key, key: Key) {
return cacheKey[0] === key[0];
}

206
node_modules/moize/src/stats.ts generated vendored Normal file
View File

@@ -0,0 +1,206 @@
import type {
GlobalStatsObject,
Moizeable,
OnCacheOperation,
Options,
StatsCache,
StatsProfile,
} from '../index.d';
export const statsCache: StatsCache = {
anonymousProfileNameCounter: 1,
isCollectingStats: false,
profiles: {},
};
let hasWarningDisplayed = false;
export function clearStats(profileName?: string) {
if (profileName) {
delete statsCache.profiles[profileName];
} else {
statsCache.profiles = {};
}
}
/**
* @private
*
* @description
* activate stats collection
*
* @param isCollectingStats should stats be collected
*/
export function collectStats(isCollectingStats = true) {
statsCache.isCollectingStats = isCollectingStats;
}
/**
* @private
*
* @description
* create a function that increments the number of calls for the specific profile
*/
export function createOnCacheAddIncrementCalls<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
) {
const { profileName } = options;
return function () {
if (profileName && !statsCache.profiles[profileName]) {
statsCache.profiles[profileName] = {
calls: 0,
hits: 0,
};
}
statsCache.profiles[profileName].calls++;
};
}
/**
* @private
*
* @description
* create a function that increments the number of calls and cache hits for the specific profile
*/
export function createOnCacheHitIncrementCallsAndHits<
MoizeableFn extends Moizeable
>(options: Options<MoizeableFn>) {
return function () {
const { profiles } = statsCache;
const { profileName } = options;
if (!profiles[profileName]) {
profiles[profileName] = {
calls: 0,
hits: 0,
};
}
profiles[profileName].calls++;
profiles[profileName].hits++;
};
}
/**
* @private
*
* @description
* get the profileName for the function when one is not provided
*
* @param fn the function to be memoized
* @returns the derived profileName for the function
*/
export function getDefaultProfileName<MoizeableFn extends Moizeable>(
fn: MoizeableFn
) {
return (
fn.displayName ||
fn.name ||
`Anonymous ${statsCache.anonymousProfileNameCounter++}`
);
}
/**
* @private
*
* @description
* get the usage percentage based on the number of hits and total calls
*
* @param calls the number of calls made
* @param hits the number of cache hits when called
* @returns the usage as a percentage string
*/
export function getUsagePercentage(calls: number, hits: number) {
return calls ? `${((hits / calls) * 100).toFixed(4)}%` : '0.0000%';
}
/**
* @private
*
* @description
* get the statistics for a given method or all methods
*
* @param [profileName] the profileName to get the statistics for (get all when not provided)
* @returns the object with stats information
*/
export function getStats(profileName?: string): GlobalStatsObject {
if (!statsCache.isCollectingStats && !hasWarningDisplayed) {
console.warn(
'Stats are not currently being collected, please run "collectStats" to enable them.'
); // eslint-disable-line no-console
hasWarningDisplayed = true;
}
const { profiles } = statsCache;
if (profileName) {
if (!profiles[profileName]) {
return {
calls: 0,
hits: 0,
usage: '0.0000%',
};
}
const { [profileName]: profile } = profiles;
return {
...profile,
usage: getUsagePercentage(profile.calls, profile.hits),
};
}
const completeStats: StatsProfile = Object.keys(statsCache.profiles).reduce(
(completeProfiles, profileName) => {
completeProfiles.calls += profiles[profileName].calls;
completeProfiles.hits += profiles[profileName].hits;
return completeProfiles;
},
{
calls: 0,
hits: 0,
}
);
return {
...completeStats,
profiles: Object.keys(profiles).reduce(
(computedProfiles, profileName) => {
computedProfiles[profileName] = getStats(profileName);
return computedProfiles;
},
{} as Record<string, StatsProfile>
),
usage: getUsagePercentage(completeStats.calls, completeStats.hits),
};
}
/**
* @private
*
* @function getStatsOptions
*
* @description
* get the options specific to storing statistics
*
* @param {Options} options the options passed to the moizer
* @returns {Object} the options specific to keeping stats
*/
export function getStatsOptions<MoizeableFn extends Moizeable>(
options: Options<MoizeableFn>
): {
onCacheAdd?: OnCacheOperation<MoizeableFn>;
onCacheHit?: OnCacheOperation<MoizeableFn>;
} {
return statsCache.isCollectingStats
? {
onCacheAdd: createOnCacheAddIncrementCalls(options),
onCacheHit: createOnCacheHitIncrementCallsAndHits(options),
}
: {};
}

42
node_modules/moize/src/updateCacheForKey.ts generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import { copyStaticProperties } from './instance';
import type { Moized } from '../index.d';
export function createRefreshableMoized<MoizedFn extends Moized>(
moized: MoizedFn
) {
const {
options: { updateCacheForKey },
} = moized;
/**
* @private
*
* @description
* Wrapper around already-`moize`d function which will intercept the memoization
* and call the underlying function directly with the purpose of updating the cache
* for the given key.
*
* Promise values use a tweak of the logic that exists at cache.updateAsyncCache, which
* reverts to the original value if the promise is rejected and there was already a cached
* value.
*/
const refreshableMoized = function refreshableMoized(
this: any,
...args: Parameters<typeof moized.fn>
) {
if (!updateCacheForKey(args)) {
return moized.apply(this, args);
}
const result = moized.fn.apply(this, args);
moized.set(args, result);
return result;
} as typeof moized;
copyStaticProperties(moized, refreshableMoized);
return refreshableMoized;
}

196
node_modules/moize/src/utils.ts generated vendored Normal file
View File

@@ -0,0 +1,196 @@
import { DEFAULT_OPTIONS } from './constants';
import type {
AnyFn,
Expiration,
IsEqual,
IsMatchingKey,
Key,
Moizeable,
Moized,
Options,
} from '../index.d';
/**
* @private
*
* @description
* method to combine functions and return a single function that fires them all
*
* @param functions the functions to compose
* @returns the composed function
*/
export function combine<Args extends any[], Result>(
...functions: Array<(...args: Args) => any>
): ((...args: Args) => Result) | undefined {
return functions.reduce(function (f: any, g: any) {
if (typeof f === 'function') {
return typeof g === 'function'
? function (this: any) {
f.apply(this, arguments);
g.apply(this, arguments);
}
: f;
}
if (typeof g === 'function') {
return g;
}
});
}
/**
* @private
*
* @description
* method to compose functions and return a single function
*
* @param functions the functions to compose
* @returns the composed function
*/
export function compose<Method>(...functions: Method[]): Method {
return functions.reduce(function (f: any, g: any) {
if (typeof f === 'function') {
return typeof g === 'function'
? function (this: any) {
return f(g.apply(this, arguments));
}
: f;
}
if (typeof g === 'function') {
return g;
}
});
}
/**
* @private
*
* @description
* find the index of the expiration based on the key
*
* @param expirations the list of expirations
* @param key the key to match
* @returns the index of the expiration
*/
export function findExpirationIndex(expirations: Expiration[], key: Key) {
for (let index = 0; index < expirations.length; index++) {
if (expirations[index].key === key) {
return index;
}
}
return -1;
}
/**
* @private
*
* @description
* create function that finds the index of the key in the list of cache keys
*
* @param isEqual the function to test individual argument equality
* @param isMatchingKey the function to test full key equality
* @returns the function that finds the index of the key
*/
export function createFindKeyIndex(
isEqual: IsEqual,
isMatchingKey: IsMatchingKey | undefined
) {
const areKeysEqual: IsMatchingKey =
typeof isMatchingKey === 'function'
? isMatchingKey
: function (cacheKey: Key, key: Key) {
for (let index = 0; index < key.length; index++) {
if (!isEqual(cacheKey[index], key[index])) {
return false;
}
}
return true;
};
return function (keys: Key[], key: Key) {
for (let keysIndex = 0; keysIndex < keys.length; keysIndex++) {
if (
keys[keysIndex].length === key.length &&
areKeysEqual(keys[keysIndex], key)
) {
return keysIndex;
}
}
return -1;
};
}
type MergedOptions<
OriginalOptions extends Options<Moizeable>,
NewOptions extends Options<Moizeable>
> = Omit<OriginalOptions, keyof NewOptions> & NewOptions;
/**
* @private
*
* @description
* merge two options objects, combining or composing functions as necessary
*
* @param originalOptions the options that already exist on the method
* @param newOptions the new options to merge
* @returns the merged options
*/
export function mergeOptions<
OriginalOptions extends Options<Moizeable>,
NewOptions extends Options<Moizeable>
>(
originalOptions: OriginalOptions,
newOptions: NewOptions | undefined
): MergedOptions<OriginalOptions, NewOptions> {
if (!newOptions || newOptions === DEFAULT_OPTIONS) {
return originalOptions as unknown as MergedOptions<
OriginalOptions,
NewOptions
>;
}
return {
...originalOptions,
...newOptions,
onCacheAdd: combine(originalOptions.onCacheAdd, newOptions.onCacheAdd),
onCacheChange: combine(
originalOptions.onCacheChange,
newOptions.onCacheChange
),
onCacheHit: combine(originalOptions.onCacheHit, newOptions.onCacheHit),
transformArgs: compose(
originalOptions.transformArgs,
newOptions.transformArgs
),
};
}
export function isMoized(
fn: Moizeable | Moized | Options<AnyFn>
): fn is Moized {
return typeof fn === 'function' && (fn as Moizeable).isMoized;
}
export function setName(
fn: Moized,
originalFunctionName: string,
profileName: string
) {
try {
const name = profileName || originalFunctionName || 'anonymous';
Object.defineProperty(fn, 'name', {
configurable: true,
enumerable: false,
value: `moized(${name})`,
writable: true,
});
} catch {
// For engines where `function.name` is not configurable, do nothing.
}
}

21
node_modules/moize/tsconfig.json generated vendored Normal file
View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"allowJs": true,
"baseUrl": "src",
"esModuleInterop": true,
"jsx": "react",
"lib": ["dom", "es2015"],
"module": "esNext",
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "./dist",
"sourceMap": true,
"target": "es5"
},
"exclude": ["node_modules"],
"include": ["src/*", "__tests__/*"],
"typedocOptions": {
"out": "docs",
"entryPoints": ["src/index.ts"]
}
}