-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Sergio Daniel Xalambrí
committed
Apr 20, 2016
1 parent
4917031
commit ebf1573
Showing
8 changed files
with
307 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"plugins": [ | ||
"transform-es2015-modules-commonjs", | ||
"transform-es2015-arrow-functions", | ||
"transform-es2015-parameters", | ||
"transform-es2015-block-scoping", | ||
"transform-es2015-computed-properties", | ||
"transform-object-rest-spread", | ||
"transform-es2015-shorthand-properties" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "airbnb", | ||
"parser": "babel-eslint" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,3 +31,5 @@ node_modules | |
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
node_modules | ||
lib | ||
test | ||
logs | ||
*.log | ||
.babelrc | ||
.eslintrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,56 @@ | ||
# redux-duck | ||
Helper function to create Redux modules easy using `ducks-modular-redux` proposal | ||
Helper function to create Redux modules using the `ducks-modular-redux` proposal. | ||
|
||
## Installation | ||
```bash | ||
npm i -S redux-duck | ||
``` | ||
|
||
## API | ||
### Create duck | ||
```javascript | ||
import { createDuck } from 'redux-duck'; | ||
|
||
const myDuck = createDuck('duck-name', 'application-name'); | ||
``` | ||
* `createDuck` receive 2 arguments, the second argument is optional. | ||
* The first argument is the duck name. | ||
* The second, and optional, argument is the application or module name. | ||
|
||
### Define action types | ||
```javascript | ||
const ACTION_TYPE = myDuck.defineType('ACTION_TYPE'); | ||
``` | ||
* `defineType` receive just one argument. | ||
* The argument is the name of the action. | ||
* The result should be an string like `application-name/duck-name/ACTION_TYPE` or `duck-name/ACTION_TYPE` if the application or module name was not defined. | ||
|
||
### Create action creators | ||
```javascript | ||
const actionType = myDuck.createAction(ACTION_TYPE); | ||
``` | ||
* `createAction` receive just one argument. | ||
* This argument should be the defined action type string. | ||
* It should return a function who will receive the action payload and return a valid (FSA compilant) action object. | ||
* The action creator will receive an optional argument with the action payload. | ||
|
||
### Create reducer | ||
```javascript | ||
const initialState = { | ||
list: Immutable.List(), | ||
data: Immutable.Map(), | ||
}; | ||
|
||
const reducer = myDuck.createReducer({ | ||
[ACTION_TYPE]: (state, action) => ({ | ||
...state, | ||
list: state.list.push(action.payload.id), | ||
data: state.map.set(action.payload.id+'', action.payload), | ||
}), | ||
}, initialState); | ||
``` | ||
* `createReducer` receive two arguments, both required. | ||
* The first argument is an object with the possible action cases. | ||
* The second argument is the reducer initial state. | ||
* The first argument should use the previously defined *action types* as keys. | ||
* Each key in the first argument object should be a function who will receive the current state and the dispatched action as arguments and return the updated state. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
export function createDuck(name, app) { | ||
function defineType(type) { | ||
if (app) { | ||
return `${app}/${name}/${type}`; | ||
} | ||
return `${name}/${type}`; | ||
} | ||
|
||
function createReducer(cases, defaultState = {}) { | ||
return function reducer(state = defaultState, action = {}) { | ||
if (state === undefined) return defaultState; | ||
for (const caseName in cases) { | ||
if (action.type === caseName) return cases[caseName](state, action); | ||
} | ||
return state; | ||
}; | ||
} | ||
|
||
function createAction(type) { | ||
return function actionCreator(payload) { | ||
const action = { | ||
type, | ||
}; | ||
|
||
if (payload) action.payload = payload; | ||
|
||
return action; | ||
}; | ||
} | ||
|
||
return { | ||
defineType, | ||
createReducer, | ||
createAction, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
{ | ||
"name": "redux-duck", | ||
"version": "1.0.0", | ||
"description": "Helper function to create Redux modules using the ducks-modular-redux proposal.", | ||
"main": "build/index.js", | ||
"directories": { | ||
"test": "test" | ||
}, | ||
"scripts": { | ||
"lint": "eslint lib/index.js", | ||
"prebuild": "npm run lint", | ||
"build": "babel lib --out-dir build", | ||
"pretest": "npm run build", | ||
"test": "babel-node test/index.js | tap-spec", | ||
"prepublish": "npm run test" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/sergiodxa/redux-duck.git" | ||
}, | ||
"keywords": [ | ||
"redux", | ||
"duck", | ||
"module", | ||
"helper" | ||
], | ||
"author": "Sergio Daniel Xalambrí <[email protected]> (http://sergio.xalambri.com.ar/)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/sergiodxa/redux-duck/issues" | ||
}, | ||
"homepage": "http://sergio.xalambri.com.ar/redux-duck/", | ||
"devDependencies": { | ||
"babel": "6.5.2", | ||
"babel-cli": "6.7.5", | ||
"babel-core": "6.7.6", | ||
"babel-eslint": "6.0.3", | ||
"babel-plugin-transform-es2015-arrow-functions": "6.5.2", | ||
"babel-plugin-transform-es2015-block-scoping": "6.7.1", | ||
"babel-plugin-transform-es2015-computed-properties": "6.6.5", | ||
"babel-plugin-transform-es2015-modules-commonjs": "6.7.4", | ||
"babel-plugin-transform-es2015-parameters": "6.7.0", | ||
"babel-plugin-transform-es2015-shorthand-properties": "6.5.0", | ||
"babel-plugin-transform-object-rest-spread": "6.6.5", | ||
"eslint": "2.8.0", | ||
"eslint-config-airbnb": "7.0.0", | ||
"eslint-plugin-jsx-a11y": "0.6.2", | ||
"eslint-plugin-react": "4.3.0", | ||
"tap-spec": "4.1.1", | ||
"tape": "4.5.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import test from 'tape'; | ||
import { createDuck } from '../build/index.js'; | ||
|
||
test('create duck', t => { | ||
t.plan(6); | ||
|
||
const duck = createDuck('test', 'redux-duck'); | ||
|
||
t.ok(duck.defineType, 'it should had a key `defineType`'); | ||
t.equals( | ||
typeof duck.defineType, | ||
'function', | ||
'it should be a function' | ||
); | ||
|
||
t.ok(duck.createReducer, 'it should had a key `createReducer`'); | ||
t.equals( | ||
typeof duck.createReducer, | ||
'function', | ||
'it should be a function' | ||
); | ||
|
||
t.ok(duck.createAction, 'it should had a key `createAction`'); | ||
t.equals( | ||
typeof duck.createAction, | ||
'function', | ||
'it should be a function' | ||
); | ||
}); | ||
|
||
test('define type', t => { | ||
t.plan(2); | ||
|
||
const duck1 = createDuck('test1', 'redux-duck'); | ||
const duck2 = createDuck('test2', 'redux-duck'); | ||
|
||
const type1 = duck1.defineType('TYPE'); | ||
const type2 = duck2.defineType('TYPE'); | ||
|
||
t.equals( | ||
type1, | ||
'redux-duck/test1/TYPE', | ||
'it should be the expected action type string' | ||
); | ||
|
||
t.equals( | ||
type2, | ||
'redux-duck/test2/TYPE', | ||
'it should be the expected action type string' | ||
); | ||
}); | ||
|
||
test('create action creator', t => { | ||
t.plan(3); | ||
|
||
const duck = createDuck('test', 'redux-duck'); | ||
|
||
const type = duck.defineType('TYPE'); | ||
|
||
const createType = duck.createAction(type); | ||
|
||
const testData = { | ||
id: 123, | ||
message: 'hello world', | ||
}; | ||
|
||
const action = createType(testData); | ||
|
||
const emptyActon = createType(); | ||
|
||
t.equals( | ||
typeof createType, | ||
'function', | ||
'it should create a valid function' | ||
); | ||
|
||
t.deepEquals( | ||
action, | ||
{ | ||
type, | ||
payload: testData, | ||
}, | ||
'it should create a valid action object' | ||
); | ||
|
||
t.deepEquals( | ||
emptyActon, | ||
{ | ||
type, | ||
}, | ||
'it should be able to create an action without payload' | ||
); | ||
}); | ||
|
||
test('create reducer', t => { | ||
t.plan(3); | ||
|
||
const duck = createDuck('test', 'redux-duck'); | ||
|
||
const type = duck.defineType('TYPE'); | ||
|
||
const reducer = duck.createReducer({ | ||
[type]: (state, action) => ({ | ||
...state, | ||
[action.payload.id]: action.payload, | ||
}), | ||
}, {}); | ||
|
||
const testData = { | ||
id: 123, | ||
message: 'hello world', | ||
}; | ||
|
||
const testAction = { | ||
type, | ||
payload: testData, | ||
}; | ||
|
||
const state = reducer({}, testAction); | ||
|
||
t.equals( | ||
typeof reducer, | ||
'function', | ||
'the reducer should be a function' | ||
); | ||
|
||
t.deepEquals( | ||
reducer(), | ||
{}, | ||
'the reducer should be able to return the default state' | ||
); | ||
|
||
t.deepEquals( | ||
state, | ||
{ | ||
[testData.id]: testData, | ||
}, | ||
'the reducer should work with the defined cases' | ||
); | ||
}); |