├── .editorconfig
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .npmrc
├── .travis.yml
├── .verb.md
├── CHANGELOG.md
├── LICENSE
├── README.md
├── examples
├── clear.js
├── custom-prop.js
├── defaults.js
├── del.js
├── merge.js
└── set.js
├── index.js
├── package.json
└── test
├── custom-property.js
├── events.js
├── fixtures
├── a.yml
├── data
│ ├── alert.json
│ ├── data.json
│ └── test.json
└── namespace
│ ├── a.yml
│ ├── b.yml
│ └── c.json
└── test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org/
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [{**/{actual,fixtures,expected,templates}/**,*.md}]
13 | trim_trailing_whitespace = false
14 | insert_final_newline = false
15 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "eslint:recommended"
4 | ],
5 |
6 | "env": {
7 | "browser": false,
8 | "es6": true,
9 | "node": true,
10 | "mocha": true
11 | },
12 |
13 | "parserOptions":{
14 | "ecmaVersion": 9,
15 | "sourceType": "module",
16 | "ecmaFeatures": {
17 | "modules": true,
18 | "experimentalObjectRestSpread": true
19 | }
20 | },
21 |
22 | "globals": {
23 | "document": false,
24 | "navigator": false,
25 | "window": false
26 | },
27 |
28 | "rules": {
29 | "accessor-pairs": 2,
30 | "arrow-spacing": [2, { "before": true, "after": true }],
31 | "block-spacing": [2, "always"],
32 | "brace-style": [2, "1tbs", { "allowSingleLine": true }],
33 | "comma-dangle": [2, "never"],
34 | "comma-spacing": [2, { "before": false, "after": true }],
35 | "comma-style": [2, "last"],
36 | "constructor-super": 2,
37 | "curly": [2, "multi-line"],
38 | "dot-location": [2, "property"],
39 | "eol-last": 2,
40 | "eqeqeq": [2, "allow-null"],
41 | "generator-star-spacing": [2, { "before": true, "after": true }],
42 | "handle-callback-err": [2, "^(err|error)$" ],
43 | "indent": [2, 2, { "SwitchCase": 1 }],
44 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }],
45 | "keyword-spacing": [2, { "before": true, "after": true }],
46 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }],
47 | "new-parens": 2,
48 | "no-array-constructor": 2,
49 | "no-caller": 2,
50 | "no-class-assign": 2,
51 | "no-cond-assign": 2,
52 | "no-const-assign": 2,
53 | "no-control-regex": 2,
54 | "no-debugger": 2,
55 | "no-delete-var": 2,
56 | "no-dupe-args": 2,
57 | "no-dupe-class-members": 2,
58 | "no-dupe-keys": 2,
59 | "no-duplicate-case": 2,
60 | "no-empty-character-class": 2,
61 | "no-eval": 2,
62 | "no-ex-assign": 2,
63 | "no-extend-native": 2,
64 | "no-extra-bind": 2,
65 | "no-extra-boolean-cast": 2,
66 | "no-extra-parens": [2, "functions"],
67 | "no-fallthrough": 2,
68 | "no-floating-decimal": 2,
69 | "no-func-assign": 2,
70 | "no-implied-eval": 2,
71 | "no-inner-declarations": [2, "functions"],
72 | "no-invalid-regexp": 2,
73 | "no-irregular-whitespace": 2,
74 | "no-iterator": 2,
75 | "no-label-var": 2,
76 | "no-labels": 2,
77 | "no-lone-blocks": 2,
78 | "no-mixed-spaces-and-tabs": 2,
79 | "no-multi-spaces": 2,
80 | "no-multi-str": 2,
81 | "no-multiple-empty-lines": [2, { "max": 1 }],
82 | "no-native-reassign": 0,
83 | "no-negated-in-lhs": 2,
84 | "no-new": 2,
85 | "no-new-func": 2,
86 | "no-new-object": 2,
87 | "no-new-require": 2,
88 | "no-new-wrappers": 2,
89 | "no-obj-calls": 2,
90 | "no-octal": 2,
91 | "no-octal-escape": 2,
92 | "no-proto": 0,
93 | "no-redeclare": 2,
94 | "no-regex-spaces": 2,
95 | "no-return-assign": 2,
96 | "no-self-compare": 2,
97 | "no-sequences": 2,
98 | "no-shadow-restricted-names": 2,
99 | "no-spaced-func": 2,
100 | "no-sparse-arrays": 2,
101 | "no-this-before-super": 2,
102 | "no-throw-literal": 2,
103 | "no-trailing-spaces": 0,
104 | "no-undef": 2,
105 | "no-undef-init": 2,
106 | "no-unexpected-multiline": 2,
107 | "no-unneeded-ternary": [2, { "defaultAssignment": false }],
108 | "no-unreachable": 2,
109 | "no-unused-vars": [2, { "vars": "all", "args": "none" }],
110 | "no-useless-call": 0,
111 | "no-with": 2,
112 | "one-var": [0, { "initialized": "never" }],
113 | "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }],
114 | "padded-blocks": [0, "never"],
115 | "quotes": [2, "single", "avoid-escape"],
116 | "radix": 2,
117 | "semi": [2, "always"],
118 | "semi-spacing": [2, { "before": false, "after": true }],
119 | "space-before-blocks": [2, "always"],
120 | "space-before-function-paren": [2, "never"],
121 | "space-in-parens": [2, "never"],
122 | "space-infix-ops": 2,
123 | "space-unary-ops": [2, { "words": true, "nonwords": false }],
124 | "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }],
125 | "use-isnan": 2,
126 | "valid-typeof": 2,
127 | "wrap-iife": [2, "any"],
128 | "yoda": [2, "never"]
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Enforce Unix newlines
2 | * text eol=lf
3 |
4 | # binaries
5 | *.ai binary
6 | *.psd binary
7 | *.jpg binary
8 | *.gif binary
9 | *.png binary
10 | *.jpeg binary
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # always ignore files
2 | *.DS_Store
3 | .idea
4 | .vscode
5 | *.sublime-*
6 |
7 | # test related, or directories generated by tests
8 | test/actual
9 | actual
10 | coverage
11 | .nyc*
12 |
13 | # npm
14 | node_modules
15 | npm-debug.log
16 |
17 | # yarn
18 | yarn.lock
19 | yarn-error.log
20 |
21 | # misc
22 | _gh_pages
23 | _draft
24 | _drafts
25 | bower_components
26 | vendor
27 | temp
28 | tmp
29 | TODO.md
30 | package-lock.json
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | os:
3 | - linux
4 | - osx
5 | language: node_js
6 | node_js:
7 | - node
8 | - '9'
9 | - '8'
10 | - '7'
11 | - '6'
12 |
--------------------------------------------------------------------------------
/.verb.md:
--------------------------------------------------------------------------------
1 | ## Quickstart
2 |
3 | ```js
4 | const CacheBase = require('cache-base');
5 | const app = new CacheBase();
6 |
7 | app.set('a.b', 'c');
8 |
9 | console.log(app.cache.a); //=> { b: 'c' }
10 | console.log(app.cache.a.b); //=> 'c'
11 |
12 | console.log(app.get('a')); //=> { b: 'c' }
13 | console.log(app.get('a.b')); //=> 'c'
14 | ```
15 |
16 | More [usage examples](#usage-examples) below.
17 |
18 |
19 | ## API
20 |
21 | {%= apidocs("index.js") %}
22 |
23 |
24 | ## Usage examples
25 |
26 | **Create an instance of cache-base**
27 |
28 | ```js
29 | const app = new CacheBase();
30 |
31 | app.set('a', 'b');
32 | app.set('c.d', 'e');
33 |
34 | console.log(app.get('a'));
35 | //=> 'b'
36 | console.log(app.get('c'));
37 | //=> { d: 'e' }
38 | console.log(app);
39 | //=> CacheBase { a: 'b' }
40 | ```
41 |
42 | **Initialize with an object**
43 |
44 | ```js
45 | const app = new CacheBase({ a: 'b', c: { d: 'e' } });
46 |
47 | console.log(app.get('a'));
48 | //=> 'b'
49 | console.log(app.get('c'));
50 | //=> { d: 'e' }
51 | console.log(app.get('c.d'));
52 | //=> 'e'
53 | console.log(app);
54 | //=> CacheBase { cache: { a: 'b' } }
55 | ```
56 |
57 | **Inherit**
58 |
59 | ```js
60 | class MyApp extends CacheBase {}
61 |
62 | const app = new MyApp();
63 | app.set('a', 'b');
64 | app.set('c', 'd');
65 |
66 | console.log(app.get('a'));
67 | //=> 'b'
68 |
69 | console.log(app);
70 | //=> MyApp { cache: { a: 'b', c: 'd' } }
71 | ```
72 |
73 | **Custom namespace**
74 |
75 | Pass a string as the first value to the contructor to define a custom property name to use for the cache. By default values are stored on the `cache` property.
76 |
77 | ```js
78 | const CacheBase = require('cache-base');
79 | const app = new CacheBase('data', { a: 'b' });
80 | app.set('c.d', 'e');
81 |
82 | // get values
83 | console.log(app.get('a'));
84 | //=> 'b'
85 | console.log(app.get('c'));
86 | //=> { d: 'e' }
87 | console.log(app.data);
88 | //=> { a: 'b', c: { d: 'e' } }
89 | console.log(app);
90 | //=> CacheBase { data: { a: 'b', c: { d: 'e' } } }
91 | ```
92 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Release history
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | This changelog's format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6 | and versioning in this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7 |
8 |
9 | Guiding Principles
10 |
11 | - Changelogs are for humans, not machines.
12 | - There should be an entry for every single version.
13 | - The same types of changes should be grouped.
14 | - Versions and sections should be linkable.
15 | - The latest version comes first.
16 | - The release date of each versions is displayed.
17 | - Mention whether you follow Semantic Versioning.
18 |
19 |
20 |
21 |
22 | Types of changes
23 |
24 | Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_):
25 |
26 | - `Added` for new features.
27 | - `Changed` for changes in existing functionality.
28 | - `Deprecated` for soon-to-be removed features.
29 | - `Removed` for now removed features.
30 | - `Fixed` for any bug fixes.
31 | - `Security` in case of vulnerabilities.
32 |
33 |
34 |
35 |
36 | ## [3.0.0] - 2018-01-27
37 |
38 | **Changed**
39 |
40 | - adds `.prime()` and `.default()` methods
41 |
42 |
43 | ## [2.0.0] - 2017-12-17
44 |
45 | **Changed**
46 |
47 | - convert to class
48 | - refactor to allow namespace to be set on constructor, thus `.namespace` was removed from the main export. Please see the readme for details.
49 |
50 |
51 | ## [1.0.1] - 2017-07-22
52 |
53 | - run update, lint, update deps
54 |
55 |
56 | ## [0.8.5] - 2017-02-25
57 |
58 | - Bump `isobject`.
59 | - Bump `set-value`.
60 | - Merge pull request #7 from wtgtybhertgeghgtwtg/bump-dependencies
61 | - run udpate
62 |
63 | ## [0.8.4] - 2016-05-30
64 |
65 | - run update
66 | - adds `.union` method. resolves https://github.com/jonschlinkert/cache-base/issues/3
67 | - generate docs
68 | - run update, update deps
69 | - make `.union` key behavior consistent with other methods
70 | - generate docs
71 |
72 | ## [0.8.2] - 2016-03-02
73 |
74 | - handle single arg key as an array
75 | - generate docs
76 |
77 | ## [0.8.1] - 2016-02-29
78 |
79 | - ensure value is a non-array object, only clear if `prop` is defined
80 |
81 | ## [0.8.0] - 2016-02-09
82 |
83 | - run update
84 | - run update, lint
85 | - minor refactor
86 | - generate docs with verb
87 |
88 | ## [0.7.1] - 2015-11-23
89 |
90 | - update deps
91 | - lint
92 | - adds lazy-cache, event emitting
93 | - events tests
94 |
95 | ## [0.7.0] - 2015-11-23
96 |
97 | - use eslint, lint
98 | - refactor, simplify
99 |
100 | ## [0.6.0] - 2015-03-11
101 |
102 | - fix pick docs
103 | - lint
104 | - get rid of deps
105 |
106 | ## [0.4.0] - 2015-02-14
107 |
108 | - adds `.pick()` and `.omit()` methods
109 | - adds tests
110 | - build docs/readme
111 |
112 | ## [0.3.0] - 2015-02-13
113 |
114 | - adds npmignore
115 | - adds travis
116 | - rename
117 | - copyright year, lint
118 | - update deps
119 | - build readme
120 |
121 | ## [0.2.0] - 2014-11-15
122 |
123 | - remove namespace stuff
124 | - update fixtures
125 | - update verbfile
126 | - clean up, refactor a number of methods:
127 | - update docs, run verb
128 |
129 | ## 0.1.0
130 |
131 | - first commit
132 |
133 | [2.0.0]: https://github.com/jonschlinkert/cache-base/compare/1.0.1...2.0.0
134 | [1.0.1]: https://github.com/jonschlinkert/cache-base/compare/1.0.0...1.0.1
135 | [1.0.0]: https://github.com/jonschlinkert/cache-base/compare/0.8.5...1.0.0
136 | [0.8.5]: https://github.com/jonschlinkert/cache-base/compare/0.8.4...0.8.5
137 | [0.8.4]: https://github.com/jonschlinkert/cache-base/compare/0.8.2...0.8.4
138 | [0.8.2]: https://github.com/jonschlinkert/cache-base/compare/0.8.1...0.8.2
139 | [0.8.1]: https://github.com/jonschlinkert/cache-base/compare/0.8.0...0.8.1
140 | [0.8.0]: https://github.com/jonschlinkert/cache-base/compare/0.7.1...0.8.0
141 | [0.7.1]: https://github.com/jonschlinkert/cache-base/compare/0.7.0...0.7.1
142 | [0.7.0]: https://github.com/jonschlinkert/cache-base/compare/0.6.0...0.7.0
143 | [0.6.0]: https://github.com/jonschlinkert/cache-base/compare/0.4.0...0.6.0
144 | [0.4.0]: https://github.com/jonschlinkert/cache-base/compare/0.3.0...0.4.0
145 | [0.3.0]: https://github.com/jonschlinkert/cache-base/compare/0.2.0...0.3.0
146 |
147 | [keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog
148 |
149 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2018, Jon Schlinkert.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cache-base [](https://www.npmjs.com/package/cache-base) [](https://npmjs.org/package/cache-base) [](https://npmjs.org/package/cache-base) [](https://travis-ci.org/jonschlinkert/cache-base)
2 |
3 | > Basic object cache with `get`, `set`, `del`, and `has` methods for node.js/javascript projects.
4 |
5 | Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
6 |
7 | - [Install](#install)
8 | - [Quickstart](#quickstart)
9 | - [API](#api)
10 | - [Usage examples](#usage-examples)
11 | - [About](#about)
12 |
13 | _(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_
14 |
15 | ## Install
16 |
17 | Install with [npm](https://www.npmjs.com/):
18 |
19 | ```sh
20 | $ npm install --save cache-base
21 | ```
22 |
23 | ## Quickstart
24 |
25 | ```js
26 | const CacheBase = require('cache-base');
27 | const app = new CacheBase();
28 |
29 | app.set('a.b', 'c');
30 |
31 | console.log(app.cache.a); //=> { b: 'c' }
32 | console.log(app.cache.a.b); //=> 'c'
33 |
34 | console.log(app.get('a')); //=> { b: 'c' }
35 | console.log(app.get('a.b')); //=> 'c'
36 | ```
37 |
38 | More [usage examples](#usage-examples) below.
39 |
40 | ## API
41 |
42 | **Params**
43 |
44 | * `prop` **{String|Object}**: (optional) Property name to use for the cache, or the object to initialize with.
45 | * `cache` **{Object}**: (optional) An object to initialize with.
46 |
47 | **Example**
48 |
49 | ```js
50 | const app = new CacheBase();
51 | ```
52 |
53 | ### [.set](index.js#L65)
54 |
55 | Assign `value` to `key`. Also emits `set` with the key and value.
56 |
57 | **Params**
58 |
59 | * `key` **{String|Array}**: The name of the property to set. Dot-notation may be used to set nested properties.
60 | * `value` **{any}**
61 | * `returns` **{Object}**: Returns the instance for chaining.
62 |
63 | **Events**
64 |
65 | * `emits`: `set` with `key` and `value` as arguments.
66 |
67 | **Example**
68 |
69 | ```js
70 | app.on('set', function(key, val) {
71 | // do something when `set` is emitted
72 | });
73 |
74 | app.set('admin', true);
75 |
76 | // also takes an object or an array of objects
77 | app.set({ name: 'Brian' });
78 | app.set([{ foo: 'bar' }, { baz: 'quux' }]);
79 | console.log(app);
80 | //=> { name: 'Brian', foo: 'bar', baz: 'quux' }
81 | ```
82 |
83 | ### [.get](index.js#L90)
84 |
85 | Return the value of `key`.
86 |
87 | **Params**
88 |
89 | * `key` **{String|Array}**: The name of the property to get. Dot-notation may be used to set nested properties.
90 | * `returns` **{any}**: Returns the value of `key`
91 |
92 | **Events**
93 |
94 | * `emits`: `get` with `key` and `value` as arguments.
95 |
96 | **Example**
97 |
98 | ```js
99 | app.set('a.b.c', 'd');
100 | app.get('a.b');
101 | //=> { c: 'd' }
102 | ```
103 |
104 | ### [.prime](index.js#L120)
105 |
106 | Create a property on the cache with the given `value` only if it doesn't already exist.
107 |
108 | **Params**
109 |
110 | * `key` **{String}**: Property name or object path notation.
111 | * `val` **{any}**
112 | * `returns` **{Object}**: Returns the instance for chaining.
113 |
114 | **Example**
115 |
116 | ```js
117 | console.log(app.cache); //=> {}
118 | app.set('one', { foo: 'bar' });
119 | app.prime('one', { a: 'b' });
120 | app.prime('two', { c: 'd' });
121 | console.log(app.cache.one); //=> { foo: 'bar' }
122 | console.log(app.cache.two); //=> { c: 'd' }
123 | ```
124 |
125 | ### [.default](index.js#L162)
126 |
127 | Set a default value to be used when `.get()` is called and the value is not defined on the cache. Returns a value from the defaults when only a key is passed.
128 |
129 | **Params**
130 |
131 | * `key` **{String|Array}**: The name of the property to set. Dot-notation may be used to set nested properties.
132 | * `value` **{any}**: (optional) The value to set on the defaults object.
133 | * `returns` **{Object}**: Returns the instance for chaining.
134 |
135 | **Example**
136 |
137 | ```js
138 | app.set('foo', 'xxx');
139 | app.default('foo', 'one');
140 | app.default('bar', 'two');
141 | app.default('baz', 'three');
142 | app.set('baz', 'zzz');
143 |
144 | console.log(app.get('foo'));
145 | //=> 'xxx'
146 |
147 | console.log(app.get('bar'));
148 | //=> 'two'
149 |
150 | console.log(app.get('baz'));
151 | //=> 'zzz'
152 |
153 | console.log(app);
154 | // CacheBase {
155 | // cache: { foo: 'xxx', bar: 'two', baz: 'zzz' },
156 | // defaults: { foo: 'one', bar: 'two', baz: 'three' } }
157 | ```
158 |
159 | ### [.union](index.js#L199)
160 |
161 | Set an array of unique values on cache `key`.
162 |
163 | **Params**
164 |
165 | * `key` **{String|Array}**: The name of the property to union. Dot-notation may be used to set nested properties.
166 | * `value` **{any}**
167 | * `returns` **{Object}**: Returns the instance for chaining.
168 |
169 | **Example**
170 |
171 | ```js
172 | app.union('a.b.c', 'foo');
173 | app.union('a.b.c', 'bar');
174 | app.union('a.b.c', ['bar', 'baz']);
175 | console.log(app.get('a'));
176 | //=> { b: { c: ['foo', 'bar', 'baz'] } }
177 | ```
178 |
179 | ### [.has](index.js#L223)
180 |
181 | Return true if the value of property `key` is not `undefined`.
182 |
183 | **Params**
184 |
185 | * `key` **{String|Array}**: The name of the property to check. Dot-notation may be used to set nested properties.
186 | * `returns` **{Boolean}**
187 |
188 | **Example**
189 |
190 | ```js
191 | app.set('foo', true);
192 | app.set('baz', null);
193 | app.set('bar', undefined);
194 |
195 | app.has('foo'); //=> true
196 | app.has('bar'); //=> true
197 | app.has('baz'); //=> false
198 | ```
199 |
200 | ### [.hasOwn](index.js#L253)
201 |
202 | Returns true if the specified property is an own (not inherited) property. Similar to [.has()](#has), but returns true if the key exists, even if the value is `undefined`.
203 |
204 | **Params**
205 |
206 | * `key` **{String}**
207 | * `returns` **{Boolean}**: Returns true if object `key` exists. Dot-notation may be used to set nested properties.
208 |
209 | **Example**
210 |
211 | ```js
212 | app.set('a.b.c', 'd');
213 | app.set('x', false);
214 | app.set('y', null);
215 | app.set('z', undefined);
216 |
217 | app.hasOwn('a'); //=> true
218 | app.hasOwn('b'); //=> true
219 | app.hasOwn('c'); //=> true
220 | app.hasOwn('a.b.c'); //=> true
221 | app.hasOwn('x'); //=> true
222 | app.hasOwn('y'); //=> true
223 | app.hasOwn('z'); //=> true
224 | app.hasOwn('lslsls'); //=> false
225 | ```
226 |
227 | ### [.del](index.js#L278)
228 |
229 | Delete one or more properties from the instance.
230 |
231 | **Params**
232 |
233 | * `key` **{String|Array}**: The name of the property to delete. Dot-notation may be used to set nested properties.
234 | * `returns` **{Object}**: Returns the instance for chaining.
235 |
236 | **Events**
237 |
238 | * `emits`: `del` with the `key` as the only argument.
239 |
240 | **Example**
241 |
242 | ```js
243 | // setup a listener to update a property with a default
244 | // value when it's deleted by the user
245 | app.on('del', key => app.set(key, app.default(key)));
246 |
247 | app.del(); // delete all properties on the cache
248 | // or
249 | app.del('foo');
250 | // or an array of keys
251 | app.del(['foo', 'bar']);
252 | ```
253 |
254 | ### [.clear](index.js#L301)
255 |
256 | Reset the entire cache to an empty object. Note that this does not also clear the `defaults` object, since you can manually do `cache.defaults = {}` if you want to reset that object as well.
257 |
258 | **Example**
259 |
260 | ```js
261 | // clear "defaults" whenever the cache is cleared
262 | app.on('clear', key => (app.defaults = {}));
263 | app.clear();
264 | ```
265 |
266 | ### [.visit](index.js#L318)
267 |
268 | Visit (or map visit) the specified method (`key`) over the properties in the
269 | given object or array.
270 |
271 | **Params**
272 |
273 | * `key` **{String|Array}**: The name of the method to visit.
274 | * `val` **{Object|Array}**: The object or array to iterate over.
275 | * `returns` **{Object}**: Returns the instance for chaining.
276 |
277 | ### [.keys](index.js#L338)
278 |
279 | Gets an array of names of all enumerable properties on the cache.
280 |
281 | **Example**
282 |
283 | ```js
284 | const app = new CacheBase();
285 | app.set('user', true);
286 | app.set('admin', false);
287 |
288 | console.log(app.keys);
289 | //=> ['user', 'admin']
290 | ```
291 |
292 | ### [.size](index.js#L357)
293 |
294 | Gets the length of [keys](#keys).
295 |
296 | **Example**
297 |
298 | ```js
299 | const app = new CacheBase();
300 | app.set('user', true);
301 | app.set('admin', false);
302 |
303 | console.log(app.size);
304 | //=> 2
305 | ```
306 |
307 | ## Usage examples
308 |
309 | **Create an instance of cache-base**
310 |
311 | ```js
312 | const app = new CacheBase();
313 |
314 | app.set('a', 'b');
315 | app.set('c.d', 'e');
316 |
317 | console.log(app.get('a'));
318 | //=> 'b'
319 | console.log(app.get('c'));
320 | //=> { d: 'e' }
321 | console.log(app);
322 | //=> CacheBase { a: 'b' }
323 | ```
324 |
325 | **Initialize with an object**
326 |
327 | ```js
328 | const app = new CacheBase({ a: 'b', c: { d: 'e' } });
329 |
330 | console.log(app.get('a'));
331 | //=> 'b'
332 | console.log(app.get('c'));
333 | //=> { d: 'e' }
334 | console.log(app.get('c.d'));
335 | //=> 'e'
336 | console.log(app);
337 | //=> CacheBase { cache: { a: 'b' } }
338 | ```
339 |
340 | **Inherit**
341 |
342 | ```js
343 | class MyApp extends CacheBase {}
344 |
345 | const app = new MyApp();
346 | app.set('a', 'b');
347 | app.set('c', 'd');
348 |
349 | console.log(app.get('a'));
350 | //=> 'b'
351 |
352 | console.log(app);
353 | //=> MyApp { cache: { a: 'b', c: 'd' } }
354 | ```
355 |
356 | **Custom namespace**
357 |
358 | Pass a string as the first value to the contructor to define a custom property name to use for the cache. By default values are stored on the `cache` property.
359 |
360 | ```js
361 | const CacheBase = require('cache-base');
362 | const app = new CacheBase('data', { a: 'b' });
363 | app.set('c.d', 'e');
364 |
365 | // get values
366 | console.log(app.get('a'));
367 | //=> 'b'
368 | console.log(app.get('c'));
369 | //=> { d: 'e' }
370 | console.log(app.data);
371 | //=> { a: 'b', c: { d: 'e' } }
372 | console.log(app);
373 | //=> CacheBase { data: { a: 'b', c: { d: 'e' } } }
374 | ```
375 |
376 | ## About
377 |
378 |
379 | Contributing
380 |
381 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
382 |
383 |
384 |
385 |
386 | Running Tests
387 |
388 | Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
389 |
390 | ```sh
391 | $ npm install && npm test
392 | ```
393 |
394 |
395 |
396 |
397 | Building docs
398 |
399 | _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
400 |
401 | To generate the readme, run the following command:
402 |
403 | ```sh
404 | $ npm install -g verbose/verb#dev verb-generate-readme && verb
405 | ```
406 |
407 |
408 |
409 | ### Related projects
410 |
411 | You might also be interested in these projects:
412 |
413 | * [base-methods](https://www.npmjs.com/package/base-methods): base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting… [more](https://github.com/jonschlinkert/base-methods) | [homepage](https://github.com/jonschlinkert/base-methods "base-methods is the foundation for creating modular, unit testable and highly pluggable node.js applications, starting with a handful of common methods, like `set`, `get`, `del` and `use`.")
414 | * [get-value](https://www.npmjs.com/package/get-value): Use property paths like 'a.b.c' to get a nested value from an object. Even works… [more](https://github.com/jonschlinkert/get-value) | [homepage](https://github.com/jonschlinkert/get-value "Use property paths like 'a.b.c' to get a nested value from an object. Even works when keys have dots in them (no other dot-prop library can do this!).")
415 | * [has-value](https://www.npmjs.com/package/has-value): Returns true if a value exists, false if empty. Works with deeply nested values using… [more](https://github.com/jonschlinkert/has-value) | [homepage](https://github.com/jonschlinkert/has-value "Returns true if a value exists, false if empty. Works with deeply nested values using object paths.")
416 | * [option-cache](https://www.npmjs.com/package/option-cache): Simple API for managing options in JavaScript applications. | [homepage](https://github.com/jonschlinkert/option-cache "Simple API for managing options in JavaScript applications.")
417 | * [set-value](https://www.npmjs.com/package/set-value): Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths. | [homepage](https://github.com/jonschlinkert/set-value "Create nested values and any intermediaries using dot notation (`'a.b.c'`) paths.")
418 | * [unset-value](https://www.npmjs.com/package/unset-value): Delete nested properties from an object using dot notation. | [homepage](https://github.com/jonschlinkert/unset-value "Delete nested properties from an object using dot notation.")
419 |
420 | ### Contributors
421 |
422 | | **Commits** | **Contributor** |
423 | | --- | --- |
424 | | 67 | [jonschlinkert](https://github.com/jonschlinkert) |
425 | | 2 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
426 |
427 | ### Author
428 |
429 | **Jon Schlinkert**
430 |
431 | * [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
432 | * [GitHub Profile](https://github.com/jonschlinkert)
433 | * [Twitter Profile](https://twitter.com/jonschlinkert)
434 |
435 | ### License
436 |
437 | Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
438 | Released under the [MIT License](LICENSE).
439 |
440 | ***
441 |
442 | _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on March 23, 2018._
--------------------------------------------------------------------------------
/examples/clear.js:
--------------------------------------------------------------------------------
1 | const CacheBase = require('..');
2 | const app = new CacheBase();
3 |
4 | app.default('foo', 42);
5 | app.default('fez', 42);
6 | app.set('foo', 1);
7 | app.set('bar', 2);
8 | app.set('baz', 3);
9 | app.set('qux', 4);
10 | app.set('fez', 5);
11 |
12 | console.log(app.cache);
13 | console.log(app.defaults);
14 | console.log('---');
15 |
16 | app.clear();
17 |
18 | console.log(app.cache);
19 | console.log(app.defaults);
20 | console.log('---');
21 |
22 | app.on('clear', key => (app.defaults = {}));
23 | app.clear();
24 |
25 | console.log(app.cache);
26 | console.log(app.defaults);
27 | console.log('---');
28 |
--------------------------------------------------------------------------------
/examples/custom-prop.js:
--------------------------------------------------------------------------------
1 | const Cache = require('..');
2 | const app = new Cache('data');
3 |
4 | app.set('a', 'b');
5 | app.set({ c: 'd' });
6 | app.set('e.f', 'g')
7 |
8 | console.log(app.get('e.f'));
9 | //=> 'g'
10 |
11 | console.log(app.get());
12 | //=> { a: 'b', c: 'd', e: { f: 'g' } }
13 |
14 | console.log(app.data);
15 | //=> { a: 'b', c: 'd', e: { f: 'g' } }
16 |
17 | console.log(app);
18 | //=> Cache { data: { a: 'b', c: 'd', e: { f: 'g' } } }
19 |
--------------------------------------------------------------------------------
/examples/defaults.js:
--------------------------------------------------------------------------------
1 | const CacheBase = require('..');
2 | const app = new CacheBase();
3 |
4 | app.set('foo', 'xxx');
5 | app.default('foo', 'one');
6 | app.default('bar', 'two');
7 | app.default('baz', 'three');
8 | app.set('baz', 'zzz');
9 |
10 | console.log(app.get('foo'));
11 | //=> 'xxx'
12 |
13 | console.log(app.get('bar'));
14 | //=> 'two'
15 |
16 | console.log(app.get('baz'));
17 | //=> 'zzz'
18 |
19 | console.log(app);
20 | // Cache {
21 | // cache: { foo: 'xxx', bar: 'two', baz: 'zzz' },
22 | // defaults: { foo: 'one', bar: 'two', baz: 'three' } }
23 |
--------------------------------------------------------------------------------
/examples/del.js:
--------------------------------------------------------------------------------
1 | const CacheBase = require('..');
2 | const app = new CacheBase();
3 |
4 | // app.on('del', key => app.set(key, app.default(key)));
5 |
6 | app.set('foo', 'xxx');
7 | app.default('foo', 'one');
8 |
9 | console.log(app.get('foo')); //=> 'xxx'
10 | console.log(app.cache.foo); //=> 'xxx'
11 | app.del('foo');
12 |
13 | console.log(app.get('foo')); //=> 'xxx'
14 | console.log(app.cache.foo); //=> undefined
15 |
--------------------------------------------------------------------------------
/examples/merge.js:
--------------------------------------------------------------------------------
1 | const CacheBase = require('..');
2 | const app = new CacheBase();
3 |
4 | app.set('foo', 'xxx');
5 | app.default('foo', 'one');
6 | app.default('bar', 'two');
7 | app.default('baz', 'three');
8 | app.default('qux', 'faz');
9 | app.set('baz', 'zzz');
10 |
11 | console.log(app.get('foo'));
12 | //=> 'xxx'
13 |
14 | console.log(app.get('bar'));
15 | //=> 'two'
16 |
17 | console.log(app.get('baz'));
18 | //=> 'zzz'
19 |
20 | console.log(app.merge());
21 | //=> { foo: 'xxx', bar: 'two', baz: 'zzz', qux: 'faz' }
22 |
23 | console.log(app.merge({qux: 'aaa'}));
24 | //=> { foo: 'xxx', bar: 'two', baz: 'zzz', qux: 'aaa' }
25 |
26 | console.log(app);
27 | // Cache {
28 | // cache: { foo: 'xxx', bar: 'two', baz: 'zzz' },
29 | // defaults: { foo: 'one', bar: 'two', baz: 'three' } }
30 |
--------------------------------------------------------------------------------
/examples/set.js:
--------------------------------------------------------------------------------
1 | const Cache = require('..');
2 | const app = new Cache();
3 |
4 | app.set('a', 'b');
5 | app.set({ c: 'd' });
6 | app.set('e.f', 'g')
7 |
8 | console.log(app.get('e.f')); //=> 'g'
9 | console.log(app.get()); //=> { a: 'b', c: 'd', e: { f: 'g' } }
10 | console.log(app.data); //=> { a: 'b', c: 'd', e: { f: 'g' } }
11 | console.log(app);
12 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const typeOf = require('kind-of');
4 | const Emitter = require('@sellside/emitter');
5 | const visit = require('collection-visit');
6 | const hasOwn = require('has-own-deep');
7 | const union = require('union-value');
8 | const del = require('unset-value');
9 | const get = require('get-value');
10 | const set = require('set-value');
11 |
12 | /**
13 | * Create an instance of `CacheBase`.
14 | *
15 | * ```js
16 | * const app = new CacheBase();
17 | * ```
18 | * @param {String|Object} `prop` (optional) Property name to use for the cache, or the object to initialize with.
19 | * @param {Object} `cache` (optional) An object to initialize with.
20 | * @constructor
21 | * @api public
22 | */
23 |
24 | class CacheBase extends Emitter {
25 | constructor(prop, cache) {
26 | super();
27 |
28 | if (typeof prop !== 'string') {
29 | cache = prop || cache;
30 | prop = 'cache';
31 | }
32 |
33 | Reflect.defineProperty(this, 'prop', { value: prop });
34 | this[this.prop] = {};
35 |
36 | if (cache) {
37 | this.set(cache);
38 | }
39 | }
40 |
41 | /**
42 | * Assign `value` to `key`. Also emits `set` with the key and value.
43 | *
44 | * ```js
45 | * app.on('set', function(key, val) {
46 | * // do something when `set` is emitted
47 | * });
48 | *
49 | * app.set('admin', true);
50 | *
51 | * // also takes an object or an array of objects
52 | * app.set({ name: 'Brian' });
53 | * app.set([{ foo: 'bar' }, { baz: 'quux' }]);
54 | * console.log(app);
55 | * //=> { name: 'Brian', foo: 'bar', baz: 'quux' }
56 | * ```
57 | * @name .set
58 | * @emits `set` with `key` and `value` as arguments.
59 | * @param {String|Array} `key` The name of the property to set. Dot-notation may be used to set nested properties.
60 | * @param {any} `value`
61 | * @return {Object} Returns the instance for chaining.
62 | * @api public
63 | */
64 |
65 | set(key, ...rest) {
66 | if (isObject(key) || (rest.length === 0 && Array.isArray(key))) {
67 | return this.visit('set', key, ...rest);
68 | }
69 | if (Array.isArray(key)) key = key.join('.');
70 | set(this[this.prop], key, ...rest);
71 | this.emit('set', key, ...rest);
72 | return this;
73 | }
74 |
75 | /**
76 | * Return the value of `key`.
77 | *
78 | * ```js
79 | * app.set('a.b.c', 'd');
80 | * app.get('a.b');
81 | * //=> { c: 'd' }
82 | * ```
83 | * @name .get
84 | * @emits `get` with `key` and `value` as arguments.
85 | * @param {String|Array} `key` The name of the property to get. Dot-notation may be used to set nested properties.
86 | * @return {any} Returns the value of `key`
87 | * @api public
88 | */
89 |
90 | get(key) {
91 | if (Array.isArray(key)) key = key.join('.');
92 | let val = get(this[this.prop], key);
93 |
94 | if (typeof val === 'undefined' && this.defaults) {
95 | val = get(this.defaults, key);
96 | }
97 |
98 | this.emit('get', key, val);
99 | return val;
100 | }
101 |
102 | /**
103 | * Create a property on the cache with the given `value` only if it doesn't
104 | * already exist.
105 | *
106 | * ```js
107 | * console.log(app.cache); //=> {}
108 | * app.set('one', { foo: 'bar' });
109 | * app.prime('one', { a: 'b' });
110 | * app.prime('two', { c: 'd' });
111 | * console.log(app.cache.one); //=> { foo: 'bar' }
112 | * console.log(app.cache.two); //=> { c: 'd' }
113 | * ```
114 | * @name .prime
115 | * @param {String} `key` Property name or object path notation.
116 | * @param {any} `val`
117 | * @return {Object} Returns the instance for chaining.
118 | * @api public
119 | */
120 |
121 | prime(key, ...rest) {
122 | if (isObject(key) || (rest.length === 0 && Array.isArray(key))) {
123 | return this.visit('prime', key, ...rest);
124 | }
125 | if (Array.isArray(key)) key = key.join('.');
126 | if (!this.has(key)) {
127 | this.set(key, ...rest);
128 | }
129 | return this;
130 | }
131 |
132 | /**
133 | * Set a default value to be used when `.get()` is called and the value is not defined
134 | * on the cache. Returns a value from the defaults when only a key is passed.
135 | *
136 | * ```js
137 | * app.set('foo', 'xxx');
138 | * app.default('foo', 'one');
139 | * app.default('bar', 'two');
140 | * app.default('baz', 'three');
141 | * app.set('baz', 'zzz');
142 | *
143 | * console.log(app.get('foo'));
144 | * //=> 'xxx'
145 | *
146 | * console.log(app.get('bar'));
147 | * //=> 'two'
148 | *
149 | * console.log(app.get('baz'));
150 | * //=> 'zzz'
151 | *
152 | * console.log(app);
153 | * // CacheBase {
154 | * // cache: { foo: 'xxx', bar: 'two', baz: 'zzz' },
155 | * // defaults: { foo: 'one', bar: 'two', baz: 'three' } }
156 | * ```
157 | * @name .default
158 | * @param {String|Array} `key` The name of the property to set. Dot-notation may be used to set nested properties.
159 | * @param {any} `value` (optional) The value to set on the defaults object.
160 | * @return {Object} Returns the instance for chaining.
161 | * @api public
162 | */
163 |
164 | default(key, ...rest) {
165 | this.defaults = this.defaults || {};
166 |
167 | if (isObject(key) || (rest.length === 0 && Array.isArray(key))) {
168 | return this.visit('default', key, ...rest);
169 | }
170 |
171 | if (Array.isArray(key)) key = key.join('.');
172 | if (!isString(key)) {
173 | throw new TypeError('expected "key" to be a string, object or array');
174 | }
175 |
176 | if (rest.length === 0) {
177 | return get(this.defaults, key);
178 | }
179 |
180 | set(this.defaults, key, ...rest);
181 | this.emit('default', key, rest);
182 | return this;
183 | }
184 |
185 | /**
186 | * Set an array of unique values on cache `key`.
187 | *
188 | * ```js
189 | * app.union('a.b.c', 'foo');
190 | * app.union('a.b.c', 'bar');
191 | * app.union('a.b.c', ['bar', 'baz']);
192 | * console.log(app.get('a'));
193 | * //=> { b: { c: ['foo', 'bar', 'baz'] } }
194 | * ```
195 | * @name .union
196 | * @param {String|Array} `key` The name of the property to union. Dot-notation may be used to set nested properties.
197 | * @param {any} `value`
198 | * @return {Object} Returns the instance for chaining.
199 | * @api public
200 | */
201 |
202 | union(key, ...rest) {
203 | if (Array.isArray(key)) key = key.join('.');
204 | union(this[this.prop], key, ...rest);
205 | this.emit('union', ...rest);
206 | return this;
207 | }
208 |
209 | /**
210 | * Return true if the value of property `key` is not `undefined`.
211 | *
212 | * ```js
213 | * app.set('foo', true);
214 | * app.set('baz', null);
215 | * app.set('bar', undefined);
216 | *
217 | * app.has('foo'); //=> true
218 | * app.has('bar'); //=> true
219 | * app.has('baz'); //=> false
220 | * ```
221 | * @name .has
222 | * @param {String|Array} `key` The name of the property to check. Dot-notation may be used to set nested properties.
223 | * @return {Boolean}
224 | * @api public
225 | */
226 |
227 | has(key) {
228 | if (Array.isArray(key)) key = key.join('.');
229 | return typeof get(this[this.prop], key) !== 'undefined';
230 | }
231 |
232 | /**
233 | * Returns true if the specified property is an own (not inherited) property.
234 | * Similar to [.has()](#has), but returns true if the key exists, even if the
235 | * value is `undefined`.
236 | *
237 | * ```js
238 | * app.set('a.b.c', 'd');
239 | * app.set('x', false);
240 | * app.set('y', null);
241 | * app.set('z', undefined);
242 | *
243 | * app.hasOwn('a'); //=> true
244 | * app.hasOwn('b'); //=> true
245 | * app.hasOwn('c'); //=> true
246 | * app.hasOwn('a.b.c'); //=> true
247 | * app.hasOwn('x'); //=> true
248 | * app.hasOwn('y'); //=> true
249 | * app.hasOwn('z'); //=> true
250 | * app.hasOwn('lslsls'); //=> false
251 | * ```
252 | * @name .hasOwn
253 | * @param {String} `key`
254 | * @return {Boolean} Returns true if object `key` exists. Dot-notation may be used to set nested properties.
255 | * @api public
256 | */
257 |
258 | hasOwn(key) {
259 | if (Array.isArray(key)) key = key.join('.');
260 | return hasOwn(this[this.prop], key);
261 | }
262 |
263 | /**
264 | * Delete one or more properties from the instance.
265 | *
266 | * ```js
267 | * // setup a listener to update a property with a default
268 | * // value when it's deleted by the user
269 | * app.on('del', key => app.set(key, app.default(key)));
270 | *
271 | * app.del(); // delete all properties on the cache
272 | * // or
273 | * app.del('foo');
274 | * // or an array of keys
275 | * app.del(['foo', 'bar']);
276 | * ```
277 | * @name .del
278 | * @emits `del` with the `key` as the only argument.
279 | * @param {string} `key` The name of the property to delete. Dot-notation may be used to delete nested properties. This method does not accept key as an array.
280 | * @return {Object} Returns the instance for chaining.
281 | * @api public
282 | */
283 |
284 | del(key) {
285 | if (!key) return this.clear();
286 | del(this[this.prop], key);
287 | this.emit('del', key);
288 | return this;
289 | }
290 |
291 | /**
292 | * Reset the entire cache to an empty object. Note that this does not also clear the `defaults`
293 | * object, since you can manually do `cache.defaults = {}` if you want to reset that object as well.
294 | *
295 | * ```js
296 | * // clear "defaults" whenever the cache is cleared
297 | * app.on('clear', key => (app.defaults = {}));
298 | * app.clear();
299 | * ```
300 | * @name .clear
301 | * @api public
302 | */
303 |
304 | clear() {
305 | this[this.prop] = {};
306 | this.emit('clear');
307 | return this;
308 | }
309 |
310 | /**
311 | * Visit (or map visit) the specified method (`key`) over the properties in the
312 | * given object or array.
313 | *
314 | * @name .visit
315 | * @param {String|Array} `key` The name of the method to visit.
316 | * @param {Object|Array} `val` The object or array to iterate over.
317 | * @return {Object} Returns the instance for chaining.
318 | * @api public
319 | */
320 |
321 | visit(key, ...rest) {
322 | visit(this, key, ...rest);
323 | return this;
324 | }
325 |
326 | /**
327 | * Gets an array of names of all enumerable properties on the cache.
328 | *
329 | * ```js
330 | * const app = new CacheBase();
331 | * app.set('user', true);
332 | * app.set('admin', false);
333 | *
334 | * console.log(app.keys);
335 | * //=> ['user', 'admin']
336 | * ```
337 | * @name .keys
338 | * @api public
339 | */
340 |
341 | get keys() {
342 | return Object.keys(this[this.prop]);
343 | }
344 |
345 | /**
346 | * Gets the length of [keys](#keys).
347 | *
348 | * ```js
349 | * const app = new CacheBase();
350 | * app.set('user', true);
351 | * app.set('admin', false);
352 | *
353 | * console.log(app.size);
354 | * //=> 2
355 | * ```
356 | * @name .size
357 | * @api public
358 | */
359 |
360 | get size() {
361 | return this.keys.length;
362 | }
363 | }
364 |
365 | /**
366 | * Returns true if `value` is a non-empty string.
367 | */
368 |
369 | function isString(value) {
370 | return typeof value === 'string' && value !== '';
371 | }
372 |
373 | /**
374 | * Returns true if `value` is an object
375 | */
376 |
377 | function isObject(value) {
378 | return typeOf(value) === 'object';
379 | }
380 |
381 | /**
382 | * Expose `CacheBase`
383 | */
384 |
385 | module.exports = CacheBase;
386 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cache-base",
3 | "description": "Basic object cache with `get`, `set`, `del`, and `has` methods for node.js/javascript projects.",
4 | "version": "4.0.2",
5 | "homepage": "https://github.com/jonschlinkert/cache-base",
6 | "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
7 | "contributors": [
8 | "Jon Schlinkert (http://twitter.com/jonschlinkert)",
9 | "(https://github.com/wtgtybhertgeghgtwtg)"
10 | ],
11 | "repository": "jonschlinkert/cache-base",
12 | "bugs": {
13 | "url": "https://github.com/jonschlinkert/cache-base/issues"
14 | },
15 | "license": "MIT",
16 | "files": [
17 | "index.js"
18 | ],
19 | "main": "index.js",
20 | "engines": {
21 | "node": ">=6"
22 | },
23 | "scripts": {
24 | "test": "nyc --reporter=text --reporter=html mocha"
25 | },
26 | "dependencies": {
27 | "@sellside/emitter": "^1.2.1",
28 | "collection-visit": "^1.0.0",
29 | "get-value": "^3.0.1",
30 | "has-own-deep": "^1.1.0",
31 | "kind-of": "^6.0.2",
32 | "set-value": "^4.1.0",
33 | "union-value": "^1.0.0",
34 | "unset-value": "^1.0.0"
35 | },
36 | "devDependencies": {
37 | "gulp-format-md": "^1.0.0",
38 | "mocha": "^3.5.3",
39 | "nyc": "^11.6.0"
40 | },
41 | "keywords": [
42 | "base",
43 | "cache",
44 | "config",
45 | "data",
46 | "get",
47 | "has",
48 | "hash",
49 | "hasown",
50 | "object",
51 | "set",
52 | "store"
53 | ],
54 | "verb": {
55 | "run": true,
56 | "toc": true,
57 | "layout": "default",
58 | "tasks": [
59 | "readme"
60 | ],
61 | "plugins": [
62 | "gulp-format-md"
63 | ],
64 | "related": {
65 | "highligh": "base",
66 | "list": [
67 | "base-methods",
68 | "get-value",
69 | "has-value",
70 | "option-cache",
71 | "set-value",
72 | "unset-value"
73 | ]
74 | },
75 | "reflinks": [
76 | "verb"
77 | ],
78 | "lint": {
79 | "reflinks": true
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/test/custom-property.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * cache-base
3 | *
4 | * Copyright (c) 2014-2018, Jon Schlinkert.
5 | * Licensed under the MIT License.
6 | */
7 |
8 | 'use strict';
9 |
10 | require('mocha');
11 | const assert = require('assert');
12 | const Cache = require('../');
13 | let app, cache;
14 |
15 | describe('custom property', function() {
16 | beforeEach(function() {
17 | app = new Cache('data');
18 | });
19 |
20 | describe('constructor:', function() {
21 | it('should create an instance of Cache', function() {
22 | assert(app instanceof Cache);
23 | });
24 |
25 | it('should set ', function() {
26 | app = new Cache('data', { one: 1, two: 2 });
27 | assert.equal(app.data.one, 1);
28 | assert.equal(app.data.two, 2);
29 | });
30 | });
31 |
32 | describe('get/set:', function() {
33 | describe('set() - add:', function() {
34 | it('should set a new property with the given value', function() {
35 | app.set('one', 1);
36 | assert.equal(app.get('one'), 1);
37 | assert.equal(app.data.one, 1);
38 | });
39 | });
40 |
41 | describe('set() - update:', function() {
42 | it('should update an existing property with the given value', function() {
43 | app.set('one', 2);
44 | assert.equal(app.get('one'), 2);
45 | assert.equal(app.data.one, 2);
46 | });
47 |
48 | it('should get the given property', function() {
49 | app.set('a', 'b');
50 | assert.equal(app.get('a'), 'b');
51 | assert.equal(app.data.a, 'b');
52 | });
53 | });
54 | });
55 |
56 | describe('.set()', function() {
57 | it('should set a value', function() {
58 | app.set('a', 'b');
59 | assert.equal(app.get('a'), 'b');
60 | assert.equal(app.data.a, 'b');
61 | });
62 |
63 | it('should set properties on the `data` object', function() {
64 | app.set('a', 'b');
65 | assert.equal(app.data.a, 'b');
66 | });
67 |
68 | it('should allow an object to be set directly', function() {
69 | app.set({x: 'y'});
70 | assert.equal(app.data.x, 'y');
71 | assert.equal(app.get('x'), 'y');
72 | });
73 |
74 | it('should set nested properties on the `data` object', function() {
75 | app.set('c', {d: 'e'});
76 | assert.equal(app.get('c').d, 'e');
77 | });
78 |
79 | it('should return the instance', function() {
80 | assert.equal(app.set('a', 'b'), app);
81 | });
82 |
83 | it('should be chainable', function() {
84 | app
85 | .set('aa', 'bb')
86 | .set('bb', 'cc')
87 | .set('cc', 'dd');
88 |
89 | assert.equal(app.get('aa'), 'bb');
90 | assert.equal(app.get('bb'), 'cc');
91 | assert.equal(app.get('cc'), 'dd');
92 |
93 | assert.equal(app.data.aa, 'bb');
94 | assert.equal(app.data.bb, 'cc');
95 | assert.equal(app.data.cc, 'dd');
96 | });
97 |
98 | it('should return undefined when not set', function() {
99 | assert.equal(app.set('sfsfsdfs', undefined), app);
100 | });
101 | });
102 |
103 | describe('.get()', function() {
104 | it('should otherwise return the value', function() {
105 | app.set('a', 'b');
106 | assert.equal(app.get('a'), 'b');
107 | assert.equal(app.data.a, 'b');
108 | assert.equal(app.get('zllzzl'), undefined);
109 | });
110 | });
111 | });
112 |
--------------------------------------------------------------------------------
/test/events.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * cache-base
3 | *
4 | * Copyright (c) 2014-2018, Jon Schlinkert.
5 | * Licensed under the MIT License.
6 | */
7 |
8 | 'use strict';
9 |
10 | require('mocha');
11 | const assert = require('assert');
12 | const Cache = require('../');
13 | let app, cache;
14 |
15 | describe('events', function() {
16 | beforeEach(function() {
17 | app = new Cache();
18 | });
19 |
20 | describe('set', function() {
21 | it('should emit a "set" event', function(cb) {
22 | app.on('set', () => cb());
23 | app.set('a', 'b');
24 | });
25 |
26 | it('should emit the key with "set" events', function(cb) {
27 | app.on('set', function(key, val) {
28 | assert.equal(key, 'a');
29 | cb();
30 | });
31 | app.set('a', 'b');
32 | });
33 |
34 | it('should emit the value with "set" events', function(cb) {
35 | app.on('set', function(key, val) {
36 | assert.equal(val, 'b');
37 | cb();
38 | });
39 | app.set('a', 'b');
40 | });
41 | });
42 |
43 | describe('get', function() {
44 | it('should emit a get event', function(cb) {
45 | app.on('get', () => cb());
46 | app.get('a');
47 | });
48 |
49 | it('should emit the key with "get" events', function(cb) {
50 | app.on('get', function(key, val) {
51 | assert.equal(key, 'a');
52 | cb();
53 | });
54 | app.set('a', 'b');
55 | app.get('a');
56 | });
57 |
58 | it('should emit the value with "get" events', function(cb) {
59 | app.on('get', function(key, val) {
60 | assert.equal(val, 'b');
61 | cb();
62 | });
63 | app.set('a', 'b');
64 | app.get('a');
65 | });
66 | });
67 |
68 | describe('del', function() {
69 | it('should emit a del event', function(cb) {
70 | app.on('del', () => cb());
71 | app.del('a');
72 | });
73 |
74 | it('should emit the key with "del" events', function(cb) {
75 | app.on('del', function(key) {
76 | assert.equal(key, 'a');
77 | cb();
78 | });
79 | app.set('a', 'b');
80 | app.del('a');
81 | });
82 |
83 | it('should emit each deleted key when multiple properties are deleted', function(cb) {
84 | var keys = [];
85 | app.on('del', key => keys.push(key));
86 |
87 | app.set('a', 'b');
88 | app.set('c', 'd');
89 |
90 | app.del('a');
91 | app.del('c');
92 | assert.deepEqual(keys, ['a', 'c']);
93 | assert(!app.a);
94 | assert(!app.c);
95 | cb();
96 | });
97 | });
98 | });
99 |
--------------------------------------------------------------------------------
/test/fixtures/a.yml:
--------------------------------------------------------------------------------
1 | a: b
--------------------------------------------------------------------------------
/test/fixtures/data/alert.json:
--------------------------------------------------------------------------------
1 | {
2 | "success": {
3 | "test": true,
4 | "strong": "Heads up! This is a warning!",
5 | "text": "You forgot a field!"
6 | }
7 | }
--------------------------------------------------------------------------------
/test/fixtures/data/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": "Whoa, I should be at the root!"
3 | }
--------------------------------------------------------------------------------
/test/fixtures/data/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "alpha": "one",
3 | "beta": "two"
4 | }
--------------------------------------------------------------------------------
/test/fixtures/namespace/a.yml:
--------------------------------------------------------------------------------
1 | one: ${site.two}
--------------------------------------------------------------------------------
/test/fixtures/namespace/b.yml:
--------------------------------------------------------------------------------
1 | two: ${site.three}
--------------------------------------------------------------------------------
/test/fixtures/namespace/c.json:
--------------------------------------------------------------------------------
1 | {
2 | "three": "data was processed!"
3 | }
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * cache-base
3 | *
4 | * Copyright (c) 2014-2018, Jon Schlinkert.
5 | * Licensed under the MIT License.
6 | */
7 |
8 | 'use strict';
9 |
10 | require('mocha');
11 | const assert = require('assert');
12 | const Cache = require('../');
13 | let app, cache;
14 |
15 | describe('cache-base', function() {
16 | beforeEach(function() {
17 | app = new Cache();
18 | });
19 |
20 | describe('constructor:', function() {
21 | it('should create an instance of Cache', function() {
22 | assert(app instanceof Cache);
23 | });
24 |
25 | it('should set values passed on the ctor', function() {
26 | app = new Cache({ one: 1, two: 2 });
27 | assert.equal(app.cache.one, 1);
28 | assert.equal(app.cache.two, 2);
29 | });
30 | });
31 |
32 | describe('prime', function() {
33 | it('should prime a property on the cache with the given value', function() {
34 | app.prime('life', 42);
35 | assert.equal(app.cache.life, 42);
36 | });
37 |
38 | it('should not prime a property if it already exists', function() {
39 | app.set('life', 51);
40 | app.prime('life', 42);
41 | assert.equal(app.cache.life, 51);
42 | });
43 |
44 | it('should prime an object', function() {
45 | app.prime({ life: 42 });
46 | assert.equal(app.cache.life, 42);
47 | });
48 | });
49 |
50 | describe('default', function() {
51 | it('should set a default value on cache.defaults', function() {
52 | app.default('life', 42);
53 | assert.equal(app.defaults.life, 42);
54 | });
55 |
56 | it('should not set a default value on the cache object', function() {
57 | app.default('life', 42);
58 | assert.equal(app.cache.life, undefined);
59 | });
60 |
61 | it('should be overridden when values are set', function() {
62 | app.default('life', 42);
63 | app.set('life', 51);
64 | assert.equal(app.cache.life, 51);
65 | });
66 |
67 | it('should not set a default if it already exists', function() {
68 | app.set('life', 51);
69 | app.default('life', 42);
70 | assert.equal(app.cache.life, 51);
71 | });
72 |
73 | it('should take an object', function() {
74 | app.default({ life: 41 });
75 | assert.equal(app.defaults.life, 41);
76 | });
77 |
78 | it('should take an array of objects', function() {
79 | app.default([{ meaning: 41, life: 42 }]);
80 | assert.equal(app.defaults.meaning, 41);
81 | assert.equal(app.defaults.life, 42);
82 | });
83 |
84 | it('should return a value from cache.defaults when only the key is passed', function() {
85 | app.default({ foo: 1, bar: 2 });
86 | assert.equal(app.default('foo'), 1);
87 | });
88 |
89 | it('should return the default value with `.get()`', function() {
90 | app.default({ foo: 1, bar: 2 });
91 |
92 | app.set('foo', 42);
93 | assert.equal(app.get('foo'), 42);
94 |
95 | app.del('foo');
96 | assert.equal(app.get('foo'), 1);
97 | assert.equal(app.get('bar'), 2);
98 | });
99 | });
100 |
101 | describe('set', function() {
102 | it('should set a value', function() {
103 | app.set('a', 'b');
104 | assert.equal(app.get('a'), 'b');
105 | });
106 |
107 | it('should set properties on `app.cache` when defined as key-value pairs', function() {
108 | app.set('a', 'b');
109 | assert.equal(app.cache.a, 'b');
110 | });
111 |
112 | it('should set properties on `app.cache` when defined as as an object', function() {
113 | app.set({x: 'y'});
114 | assert.equal(app.cache.x, 'y');
115 | assert.equal(app.get('x'), 'y');
116 | });
117 |
118 | it('should set nested properties on the `app.cache`', function() {
119 | app.set('c', {d: 'e'});
120 | assert.equal(app.get('c.d'), 'e');
121 | });
122 |
123 | it('should be chainable', function() {
124 | assert.equal(app.set('a', 'b'), app);
125 | app
126 | .set('aa', 'bb')
127 | .set('bb', 'cc')
128 | .set('cc', 'dd');
129 | assert.equal(app.get('aa'), 'bb');
130 | assert.equal(app.get('bb'), 'cc');
131 | assert.equal(app.get('cc'), 'dd');
132 | });
133 |
134 | it('should return undefined when not set', function() {
135 | assert.equal(app.set('a', undefined), app);
136 | });
137 | });
138 |
139 | describe('get', function() {
140 | it('should return undefined when no set', function() {
141 | assert(app.get('a') === undefined);
142 | });
143 |
144 | it('should get a value', function() {
145 | app.set('a', 'b');
146 | assert.equal(app.get('a'), 'b');
147 | });
148 |
149 | it('should get a nested property value', function() {
150 | app.set('a.b.c', 'z');
151 | assert.equal(app.cache.a.b.c, 'z');
152 | assert.deepEqual(app.get('a.b'), {c: 'z'});
153 | });
154 |
155 | it('should support passing key as an array', function() {
156 | app.set('a.b.c', 'z');
157 | assert.equal(app.cache.a.b.c, 'z');
158 | assert.deepEqual(app.get(['a', 'b']), {c: 'z'});
159 | });
160 | });
161 |
162 | describe('union', function() {
163 | it('should union a string value', function() {
164 | app.union('a', 'b');
165 | assert.deepEqual(app.get('a'), ['b']);
166 | });
167 |
168 | it('should union multiple string values', function() {
169 | app.union('a', 'b');
170 | app.union('a', 'c');
171 | app.union('a', 'd');
172 | assert.deepEqual(app.get('a'), ['b', 'c', 'd']);
173 | });
174 |
175 | it('should union multiple arrays', function() {
176 | app.union('a', ['b']);
177 | app.union('a', ['c']);
178 | app.union('a', ['d']);
179 | assert.deepEqual(app.get('a'), ['b', 'c', 'd']);
180 | });
181 |
182 | it('should union strings and arrays', function() {
183 | app.union('a', 'a');
184 | app.union('a', ['b']);
185 | app.union('a', ['c', 'd']);
186 | assert.deepEqual(app.get('a'), ['a', 'b', 'c', 'd']);
187 | });
188 |
189 | it('should union nested string values', function() {
190 | app.union('a.b', 'b');
191 | app.union('a.b', 'c');
192 | app.union('a.b', 'd');
193 | assert.deepEqual(app.get('a'), {b: ['b', 'c', 'd']});
194 | });
195 |
196 | it('should union and uniquify arrays', function() {
197 | app.union('a.b', ['b', 'foo']);
198 | app.union('a.b', ['c', 'foo']);
199 | app.union('a.b', ['d', 'foo']);
200 | assert.deepEqual(app.get('a'), {b: ['b', 'foo', 'c', 'd']});
201 | });
202 | });
203 |
204 | describe('has', function() {
205 | it('should return true if cache has a value for the given key', function() {
206 | app.set('foo', 'bar');
207 | app.set('baz', null);
208 | app.set('qux', undefined);
209 |
210 | assert(app.has('foo'));
211 | assert(!app.has('bar'));
212 | assert(app.has('baz'));
213 | assert(!app.has('qux'));
214 | });
215 |
216 | it('should work with escaped keys', function() {
217 | app.set('foo\\.baz', 'bar');
218 |
219 | assert(!app.has('foo'));
220 | assert(!app.has('bar'));
221 | assert(app.has('foo.baz'));
222 | });
223 |
224 | it('should return true if a nested key value on the cache', function() {
225 | app.set('a.b.c.d', { x: 'zzz' });
226 | app.set('a.b.c.e', { f: null });
227 | app.set('a.b.g.j', { k: undefined });
228 |
229 | assert(app.has('a'));
230 | assert(app.has('a.b'));
231 | assert(app.has('a.b.c'));
232 | assert(app.has('a.b.c.d'));
233 | assert(app.has('a.b.c.d.x'));
234 | assert(app.has('a.b.c.e.f'));
235 | assert(!app.has('a.b.g.j.k'));
236 |
237 | assert(!app.has('a.b.bar'));
238 | assert(!app.has('a.b.c.d.z'));
239 | assert(!app.has('a.b.c.e.bar'));
240 | assert(!app.has('a.b.g.j.foo'));
241 | });
242 | });
243 |
244 | describe('hasOwn', function() {
245 | it('should return true if a cache has own key', function() {
246 | app.set('foo', 'bar');
247 | app.set('baz', null);
248 | app.set('qux', undefined);
249 |
250 | assert(app.hasOwn('foo'));
251 | assert(!app.hasOwn('bar'));
252 | assert(app.hasOwn('baz'));
253 | assert(!app.hasOwn('qux'));
254 | });
255 |
256 | it('should work with escaped keys', function() {
257 | app.set('foo\\.baz', 'bar');
258 | app.set('baz', null);
259 | app.set('qux', undefined);
260 |
261 | assert(!app.hasOwn('foo'));
262 | assert(!app.hasOwn('bar'));
263 | assert(app.hasOwn('foo.baz'));
264 | assert(app.hasOwn('baz'));
265 | assert(!app.hasOwn('qux'));
266 | });
267 |
268 | it('should return true if a nested key exists `.hasOwn()` on the cache', function() {
269 | app.set('a.b.c.d', { x: 'zzz' });
270 | app.set('a.b.c.e', { f: null });
271 | app.set('a.b.g.j', { k: undefined });
272 |
273 | assert(app.hasOwn('a'));
274 | assert(app.hasOwn('a.b'));
275 | assert(app.hasOwn('a.b.c'));
276 | assert(app.hasOwn('a.b.c.d'));
277 | assert(app.hasOwn('a.b.c.d.x'));
278 | assert(app.hasOwn('a.b.c.e.f'));
279 | assert(app.hasOwn('a.b.g.j.k'));
280 | assert(app.hasOwn('a.b.g.j.k'));
281 | assert(app.hasOwn('a.b.c.e.f'));
282 |
283 | assert(!app.hasOwn('a.b.bar'));
284 | assert(!app.hasOwn('a.b.c.d.z'));
285 | assert(!app.hasOwn('a.b.c.e.bar'));
286 | assert(!app.hasOwn('a.b.g.j.foo'));
287 | });
288 | });
289 |
290 | describe('del', function() {
291 | it('should delete a property from the cache', function() {
292 | app.set('foo', 42);
293 | app.set('bar', 43);
294 |
295 | assert.equal(app.get('foo'), 42);
296 | assert.equal(app.get('bar'), 43);
297 | app.del('foo');
298 |
299 | assert.equal(app.get('foo'), undefined);
300 | assert.equal(app.get('bar'), 43);
301 | });
302 |
303 | it('should delete all property from the cache when no key is passed', function() {
304 | app.set('foo', 42);
305 | app.set('bar', 43);
306 |
307 | assert.equal(app.get('foo'), 42);
308 | assert.equal(app.get('bar'), 43);
309 | app.del();
310 |
311 | assert.equal(app.get('foo'), undefined);
312 | assert.equal(app.get('bar'), undefined);
313 | });
314 | });
315 |
316 | describe('keys', function() {
317 | it('should return all enumerable property names from the cache', function() {
318 | app.set('foo', 42);
319 | app.set('bar', null);
320 | app.set('baz', undefined);
321 |
322 | assert.deepEqual(app.keys, ['foo', 'bar']);
323 | });
324 | });
325 |
326 | describe('size', function() {
327 | it('should return the length of cache.keys', function() {
328 | app.set('foo', 'bar');
329 | app.set('baz', null);
330 | app.set('qux', undefined);
331 |
332 | assert.equal(app.size, 2);
333 | });
334 | });
335 | });
336 |
--------------------------------------------------------------------------------