Skip to content
This repository has been archived by the owner on Nov 29, 2018. It is now read-only.

Commit

Permalink
Merge pull request #91 from michaelcontento/extract-engines-and-decor…
Browse files Browse the repository at this point in the history
…ators

Extract engines and decorators
  • Loading branch information
michaelcontento committed Feb 10, 2016
2 parents 513b6a3 + 4a60262 commit dd33fb2
Show file tree
Hide file tree
Showing 23 changed files with 59 additions and 835 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[package.json]
indent_size = 2

[Makefile]
indent_style = tab
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# build artefacts
/build/
/engines/

# npm
/node_modules/
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
language: node_js
node_js:
- "5.5"
- "5.4"
- "5.3"
- "5.2"
Expand Down
6 changes: 2 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ node_modules/: package.json
clean:
echo "> Cleaning ..."
rm -rf build/
rm -rf engines/

mrproper: clean
echo "> Cleaning deep ..."
Expand All @@ -32,7 +31,6 @@ mrproper: clean
build: clean install
echo "> Building ..."
$(BIN)/babel src/ --out-dir build/
mv -f ./build/engines ./

build-watch: clean install
echo "> Building forever ..."
Expand All @@ -48,11 +46,11 @@ lint: install

test: install
echo "> Testing ..."
$(BIN)/mocca --require src/__tests__/init.js --globals localStorage
$(BIN)/mocca

test-watch: install
echo "> Testing forever ..."
$(BIN)/mocca --require src/__tests__/init.js --globals localStorage --watch
$(BIN)/mocca --watch

#
# PUBLISH
Expand Down
143 changes: 40 additions & 103 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[redux-storage][]
=================
# [redux-storage][]

[![build](https://travis-ci.org/michaelcontento/redux-storage.svg)](https://travis-ci.org/michaelcontento/redux-storage)
[![dependencies](https://david-dm.org/michaelcontento/redux-storage.svg)](https://david-dm.org/michaelcontento/redux-storage)
Expand All @@ -15,8 +14,9 @@ Save and load the [Redux][] state with ease.
## Features

* Flexible storage engines
* [localStorage][] based on `window.localStorage`
* [reactNativeAsyncStorage][] based on `react-native/AsyncStorage`
* [localStorage][]: based on window.localStorage
* Or for environments without `Promise` support [localStorageFakePromise][]
* [reactNativeAsyncStorage][]: based on `react-native/AsyncStorage`
* Storage engines can be async
* Load and save actions that can be observed
* [SAVE][]: `{ type: 'REDUX_STORAGE_SAVE', payload: /* state tree */ }`
Expand All @@ -25,13 +25,16 @@ Save and load the [Redux][] state with ease.
* [debounce][]: batch multiple save operations
* [filter][]: only store a subset of the whole state tree
* [immutablejs][]: load parts of the state tree as [Immutable][] objects
* [migrate][]: Versioned storage with migrations
* [migrate][]: versioned storage with migrations
* Black- and whitelist actions from issuing a save operation

## Installation

npm install --save redux-storage

And you need to install at least one [redux-storage-engine][npm-engine], as
[redux-storage][] is only the *"management core"*.

## Usage

```js
Expand All @@ -51,7 +54,7 @@ const reducer = storage.reducer(combineReducers(reducers));
// Now it's time to decide which storage engine should be used
//
// Note: The arguments to `createEngine` are different for every engine!
import createEngine from 'redux-storage/engines/reactNativeAsyncStorage';
import createEngine from 'redux-storage-engine-localStorage';
const engine = createEngine('my-save-key');

// And with the engine we can create our middleware function. The middleware
Expand Down Expand Up @@ -88,37 +91,12 @@ load(store)

## Details

### Engines

#### reactNativeAsyncStorage

This will use `AsyncStorage` out of [react-native][].

```js
import createEngine from 'redux-storage/engines/reactNativeAsyncStorage';
const engine = createEngine('my-save-key');
```

**Warning**: [react-native][] is *not* a dependency of [redux-storage][]! You
have to install it separately.
### Engines & Decorators

#### localStorage

Stores everything inside `window.localStorage`.

```js
import createEngine from 'redux-storage/engines/localStorage';
const engine = createEngine('my-save-key');
```

**Warning**: `localStorage` does not expose a async API and every save/load
operation will block the JS thread!

**Warning**: Some browsers like IE<=11 does not support Promises. For this you
might use [localStorageFakePromise][] which should work too - **BUT** other
parts of [redux-storage][] might depend on Promises too! So this is a possible
workaround for very limited cases only. The best solution is to use a polyfill
like [es6-promise][].
Both are published as own packages on npm. But as a convention all engines share
the keyword [redux-storage-engine][npm-engine] and decorators can be found with
[redux-storage-decorator][npm-decorator]. So it's pretty trivial to find all
the additions to [redux-storage][] you need

### Actions

Expand Down Expand Up @@ -170,82 +148,41 @@ import { SHOULD_SAVE } from './constants';
const middleware = createMiddleware(engine, [], [ SHOULD_SAVE ]);
```

### Decorators
## License

Decorators simply wrap your engine instance and modify/enhance it's behaviour.
The MIT License (MIT)

#### Filter
Copyright (c) 2015 Michael Contento

Use this decorator to write only part of your state tree to disk.

It will write the state corresponding to the whitelisted keys minus the blacklisted ones.

```js
import { decorators } from 'redux-storage'

engine = decorators.filter(engine, [
'whitelisted-key',
['nested', 'key'],
['another', 'very', 'nested', 'key']
],
[
'backlisted-key',
['nested', 'blacklisted-key'],
]);
```

#### Debounce

This decorator will delay the expensive save operation for the given ms. Every
new change to the state tree will reset the timeout!

```js
import { decorators } from 'redux-storage'

engine = decorators.debounce(engine, 1500);
```

#### Immutablejs

Convert parts of the state tree into [Immutable][] objects on `engine.load`.

```js
import { decorators } from 'redux-storage'

engine = decorators.immutablejs(engine, [
['immutablejs-reducer'],
['plain-object-reducer', 'with-immutablejs-key']
]);
```

#### Migration

Versioned storage with migrations.

```js
import { decorators } from 'redux-storage'

engine = decorators.migrate(engine, 3);
engine.addMigration(1, (state) => { /* migration step for 1 */ return state; });
engine.addMigration(2, (state) => { /* migration step for 2 */ return state; });
engine.addMigration(3, (state) => { /* migration step for 3 */ return state; });
```
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:

## Todo
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

- Write tests for everything!
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.

[npm-engine]: https://www.npmjs.com/browse/keyword/redux-storage-engine
[npm-decorator]: https://www.npmjs.com/browse/keyword/redux-storage-decorator
[Redux]: https://github.com/gaearon/redux
[Immutable]: https://github.com/facebook/immutable-js
[redux-storage]: https://github.com/michaelcontento/redux-storage
[react-native]: https://facebook.github.io/react-native/
[localStorage]: https://github.com/michaelcontento/redux-storage/blob/master/src/engines/localStorage.js
[localStorageFakePromise]: https://github.com/michaelcontento/redux-storage/blob/master/src/engines/localStorageFakePromise.js
[reactNativeAsyncStorage]: https://github.com/michaelcontento/redux-storage/blob/master/src/engines/reactNativeAsyncStorage.js
[localStorage]: https://github.com/michaelcontento/redux-storage-engine-localStorage
[localStorageFakePromise]: https://github.com/michaelcontento/redux-storage-engine-localStorageFakePromise
[reactNativeAsyncStorage]: https://github.com/michaelcontento/redux-storage-engine-reactNativeAsyncStorage
[LOAD]: https://github.com/michaelcontento/redux-storage/blob/master/src/constants.js#L1
[SAVE]: https://github.com/michaelcontento/redux-storage/blob/master/src/constants.js#L2
[debounce]: https://github.com/michaelcontento/redux-storage/blob/master/src/decorators/debounce.js
[filter]: https://github.com/michaelcontento/redux-storage/blob/master/src/decorators/filter.js
[immutablejs]: https://github.com/michaelcontento/redux-storage/blob/master/src/decorators/immutablejs.js
[migrate]: https://github.com/michaelcontento/redux-storage/blob/master/src/decorators/migrate.js
[es6-promise]: https://www.npmjs.com/package/es6-promise
[debounce]: https://github.com/michaelcontento/redux-storage-decorator-debounce
[filter]: https://github.com/michaelcontento/redux-storage-decorator-filter
[migrate]: https://github.com/mathieudutour/redux-storage-decorator-migrate
[immutablejs]: https://github.com/michaelcontento/redux-storage-decorator-immutablejs
10 changes: 2 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "redux-storage",
"version": "2.2.0",
"version": "3.0.0",
"description": "Persistence layer for redux with flexible backends",
"main": "build/index.js",
"jsnext:main": "src/index.js",
Expand All @@ -15,9 +15,6 @@
"keywords": [
"redux",
"redux-middleware",
"react-native",
"promise",
"middleware",
"fsa",
"flux-standard-action",
"flux",
Expand All @@ -29,7 +26,6 @@
"author": "Michael Contento <[email protected]>",
"files": [
"build/",
"engines/",
"src",
"!**/__tests__/**"
],
Expand All @@ -45,17 +41,15 @@
"eslint": "^1.10.3",
"eslint-config-michaelcontento": "^1.1.1",
"eslint-plugin-mocha-only": "0.0.3",
"immutable": "^3.7.6",
"mocca": "^0.3.0",
"release-it": "^2.3.1"
},
"dependencies": {
"immutable": "^3.7.6",
"lodash.isarray": "^4.0.0",
"lodash.isfunction": "^3.0.7",
"lodash.isobject": "^3.0.2",
"lodash.merge": "^4.0.2",
"lodash.set": "^4.0.0",
"lodash.unset": "^4.1.0",
"redux-actions": "^0.9.0"
},
"peerDependencies": {
Expand Down
7 changes: 1 addition & 6 deletions src/__tests__/index-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import defaultImport from '../';
import * as fullImport from '../';
import { LOAD, SAVE, createLoader, createMiddleware, decorators, reducer } from '../';
import { LOAD, SAVE, createLoader, createMiddleware, reducer } from '../';

describe('index', () => {
it('should export everything by default', () => {
Expand All @@ -25,11 +25,6 @@ describe('index', () => {
createMiddleware.should.be.a.func;
});

it('should export decorators', () => {
decorators.should.be.a.object;
decorators.should.not.be.empty;
});

it('should export reducer', () => {
reducer.should.be.a.func;
});
Expand Down
1 change: 0 additions & 1 deletion src/__tests__/init.js

This file was deleted.

47 changes: 0 additions & 47 deletions src/decorators/__tests__/debounce-test.js

This file was deleted.

Loading

0 comments on commit dd33fb2

Please sign in to comment.