Repository: plexis-js/plexis
Pull request #41 (2019-10-22 02:43:22)

Plexis cache
Hoping to learn more about API design. How does this look? I borrowed a lot from the lodash source.  Ready for review!

https://github.com/plexis-js/plexis/issues/3

vorillaz: @roemhildtg Can you please rebase your branch?
roemhildtg: Yes! I can later today. Not sure why how to fix the failing build. Seems the package needs to be published to make it install/build correctly, but the package doesn't exist yet?
vorillaz: @roemhildtg Try running `yarn bootstrap && yarn && yarn test -u`
roemhildtg: Okay - rebased and still getting that error. Do I need to remove the @plexis/cache from the package.json in plexis?

```
$ yarn bootstrap && yarn && yarn test -u
yarn run v1.17.3
$ lerna bootstrap
lerna notice cli v3.18.2
lerna info Bootstrapping 12 packages
lerna info Installing external dependencies
lerna ERR! yarn install --mutex network:42424 --non-interactive exited 1 in 'plexis'
lerna ERR! yarn install --mutex network:42424 --non-interactive stdout:
info No lockfile found.
[1/4] Resolving packages...
info If you think this is a bug, please open a bug report with the information provided in "C:\\Users\\roemh\\web\\plexis\\packages\\plexis\\yarn-error.log".      
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

lerna ERR! yarn install --mutex network:42424 --non-interactive stderr:
error An unexpected error occurred: "https://registry.yarnpkg.com/@plexis%2fcache: Not found".

lerna ERR! yarn install --mutex network:42424 --non-interactive exited 1 in 'plexis'
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command
```

Patch:
diff --git a/docs/pages/api.md b/docs/pages/api.md
index f72ac19..006ed94 100644
--- a/docs/pages/api.md
+++ b/docs/pages/api.md
@@ -1,5 +1,6 @@
 ## API
 
+- [cache](/packages/cache)
 - [compose](/packages/compose)
 - [isLowerCase](/packages/isLowerCase)
 - [isUpperCase](/packages/isUpperCase)
diff --git a/packages/cache/.npmignore b/packages/cache/.npmignore
new file mode 100644
index 0000000..552cf85
--- /dev/null
+++ b/packages/cache/.npmignore
@@ -0,0 +1,17 @@
+.DS_Store
+*.test.js
+.prettierrc
+.github
+.template
+.package-template
+.nyc_output
+.circleci
+.commitlintrc.js
+coverage
+coverage.lcov
+docs
+babel.config.js
+test
+CONTRIBUTING.md
+CODE_OF_CONDUCT.md
+LICENCE
\ No newline at end of file
diff --git a/packages/cache/README.md b/packages/cache/README.md
new file mode 100644
index 0000000..2801276
--- /dev/null
+++ b/packages/cache/README.md
@@ -0,0 +1,30 @@
+## `@plexis/cache`
+
+A caching mechanism for string operations.
+
+`npm i @plexis/cache`
+
+**Usage**
+
+```javascript
+import cache from '@plexis/cache';
+
+const toLower = x => x.toLowerCase();
+const toLowerCache = cache(toLower);
+
+// We are adding a dummy resolver function which returns the same cache every single time
+const toLowerCacheWithResolver = cache(toLower, x => 'a');
+
+toLowerCache('A'); // returns a;
+toLowerCache('B'); // returns b;
+
+toLowerCacheWithResolver('A'); // returns a;
+toLowerCacheWithResolver('B'); // returns a !!;
+```
+
+**Aliases**
+
+```javascript
+import cache from '@plexis/cache';
+import {cache, memoize} from 'plexis';
+```
diff --git a/packages/cache/package.json b/packages/cache/package.json
new file mode 100644
index 0000000..e2f3e6b
--- /dev/null
+++ b/packages/cache/package.json
@@ -0,0 +1,28 @@
+{
+  "name": "@plexis/cache",
+  "version": "0.0.12",
+  "main": "dist/index.js",
+  "module": "dist/index.esm.js",
+  "jsnext:main": "./src/index.js",
+  "license": "MIT",
+  "description": "A caching mechanism for string operations. ",
+  "authors": [
+    "Theodore Vorillas <vorillaz@gmail.com> (https://vorillaz.com)",
+    "roemhildtg <roemhildtg@gmail.com>"
+  ],
+  "keywords": [
+    "utility",
+    "string",
+    "parse",
+    "format",
+    "validate",
+    "cache"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/plexis-js/plexis.git"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}
\ No newline at end of file
diff --git a/packages/cache/src/index.js b/packages/cache/src/index.js
new file mode 100644
index 0000000..d81a978
--- /dev/null
+++ b/packages/cache/src/index.js
@@ -0,0 +1,30 @@
+/**
+ * @param {Function} [func] The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the caching mechanism.
+ * @returns {Function} Returns the new memoized function.
+ */
+const cache = (func, resolver) => {
+  if (typeof resolver !== 'function') {
+    resolver = null;
+  }
+  const cached = key => {
+    key = resolver ? resolver.call(this, key) : key;
+    const _cache = cached.cache;
+
+    if (_cache.has(key)) {
+      return _cache.get(key);
+    }
+
+    const result = func.call(this, key);
+    cached.cache = _cache.set(key, result) || cache;
+    return result;
+  };
+
+  const CacheConstructor = cache.Cache || Map;
+  cached.cache = new CacheConstructor();
+  return cached;
+};
+
+cache.Cache = Map;
+
+export default cache;


Test patch:
diff --git a/packages/cache/test/index.js b/packages/cache/test/index.js
new file mode 100644
index 0000000..c346fac
--- /dev/null
+++ b/packages/cache/test/index.js
@@ -0,0 +1,27 @@
+import cache from '../src';
+
+const toLower = x => x.toLowerCase();
+
+it('works with basics', () => {
+  const toLowerMock = jest.fn(key => {
+    return toLower(key);
+  });
+
+  const toLowerCache = cache(toLowerMock);
+  expect(toLowerCache('A')).toEqual('a');
+  expect(toLowerCache('A')).toEqual('a');
+  expect(toLowerMock.mock.calls.length).toEqual(1);
+});
+
+it('works with a resolver function', () => {
+  const toLowerCacheWithResolver = cache(toLower, x => 'a');
+  const toLowerCache = cache(toLower);
+  expect(toLowerCacheWithResolver('A')).toEqual('a');
+  expect(toLowerCacheWithResolver('B')).toEqual('a');
+});
+
+it('exposes a .cache object', () => {
+  const toLowerCache = cache(toLower);
+  toLowerCache('A');
+  expect(toLowerCache.cache.get('A')).toEqual('a');
+});