first commit
This commit is contained in:
6
node_modules/moize/.prettierrc.js
generated
vendored
Normal file
6
node_modules/moize/.prettierrc.js
generated
vendored
Normal 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
18
node_modules/moize/.release-it.beta.json
generated
vendored
Normal 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
21
node_modules/moize/.release-it.json
generated
vendored
Normal 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
527
node_modules/moize/CHANGELOG.md
generated
vendored
Normal 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
21
node_modules/moize/LICENSE
generated
vendored
Normal 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
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
35
node_modules/moize/__tests__/compose.ts
generated
vendored
Normal 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
26
node_modules/moize/__tests__/deepEqual.ts
generated
vendored
Normal 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
437
node_modules/moize/__tests__/default.ts
generated
vendored
Normal 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
436
node_modules/moize/__tests__/infinite.ts
generated
vendored
Normal 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
22
node_modules/moize/__tests__/isMoized.ts
generated
vendored
Normal 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
26
node_modules/moize/__tests__/matchesArg.ts
generated
vendored
Normal 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
29
node_modules/moize/__tests__/matchesKey.ts
generated
vendored
Normal 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
162
node_modules/moize/__tests__/maxAge.ts
generated
vendored
Normal 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
65
node_modules/moize/__tests__/maxArgs.ts
generated
vendored
Normal 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
147
node_modules/moize/__tests__/promise.ts
generated
vendored
Normal 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
272
node_modules/moize/__tests__/react.tsx
generated
vendored
Normal 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
106
node_modules/moize/__tests__/serialize.ts
generated
vendored
Normal 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
35
node_modules/moize/__tests__/shallowEqual.ts
generated
vendored
Normal 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
178
node_modules/moize/__tests__/stats.ts
generated
vendored
Normal 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
35
node_modules/moize/__tests__/transformArgs.ts
generated
vendored
Normal 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
311
node_modules/moize/__tests__/updateCacheForKey.ts
generated
vendored
Normal 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
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
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
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
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
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
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
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
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
60
node_modules/moize/es-to-mjs.js
generated
vendored
Normal 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
293
node_modules/moize/index.d.ts
generated
vendored
Normal 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
12
node_modules/moize/jest.config.js
generated
vendored
Normal 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
2
node_modules/moize/jest.init.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
require('core-js');
|
||||
require('regenerator-runtime/runtime');
|
||||
10
node_modules/moize/mjs-test.mjs
generated
vendored
Normal file
10
node_modules/moize/mjs-test.mjs
generated
vendored
Normal 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
293
node_modules/moize/mjs/index.d.mts
generated
vendored
Normal 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
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
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
131
node_modules/moize/package.json
generated
vendored
Normal 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
97
node_modules/moize/src/component.ts
generated
vendored
Normal 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
25
node_modules/moize/src/constants.ts
generated
vendored
Normal 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
616
node_modules/moize/src/index.ts
generated
vendored
Normal 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
326
node_modules/moize/src/instance.ts
generated
vendored
Normal 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
197
node_modules/moize/src/maxAge.ts
generated
vendored
Normal 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
42
node_modules/moize/src/maxArgs.ts
generated
vendored
Normal 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
87
node_modules/moize/src/options.ts
generated
vendored
Normal 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
142
node_modules/moize/src/serialize.ts
generated
vendored
Normal 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
206
node_modules/moize/src/stats.ts
generated
vendored
Normal 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
42
node_modules/moize/src/updateCacheForKey.ts
generated
vendored
Normal 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
196
node_modules/moize/src/utils.ts
generated
vendored
Normal 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
21
node_modules/moize/tsconfig.json
generated
vendored
Normal 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"]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user