Skip to content

Commit 7d5b471

Browse files
committed
feat(init): initial commit
1 parent 9696c1f commit 7d5b471

File tree

9 files changed

+4013
-2
lines changed

9 files changed

+4013
-2
lines changed

.babelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"presets": ["es2015"]
3+
}

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist
2+
__snapshots__
3+
node_modules

.travis.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sudo: false
2+
language: node_js
3+
cache:
4+
directories:
5+
- node_modules
6+
node_js:
7+
- '6'
8+
script:
9+
- yarn run lint
10+
- yarn run build
11+
- yarn run test -- --coverage
12+
after_success:
13+
- yarn run report-coverage
14+
- yarn run release
15+
branches:
16+
only:
17+
- master

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
# entities-reducer
2-
Redux high order reducer for FSA normalized payloads
1+
# Entities reducer
2+
3+
-- TODO: Write some docs
4+
5+
For now read the tests :)
6+

package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "entities-reducer",
3+
"scripts": {
4+
"test": "jest",
5+
"build": "rimraf dist && babel --copy-files --out-dir dist --ignore *.spec.js,__mocks__,__snapshots__ src",
6+
"release": "semantic-release pre && npm publish && semantic-release post",
7+
"lint": "eslint .",
8+
"report-coverage": "codecov"
9+
},
10+
"version": "0.0.0-alpha",
11+
"description": "Redux normalized entity reducer",
12+
"main": "dist/index.js",
13+
"files": [
14+
"dist"
15+
],
16+
"repository": {
17+
"type": "git",
18+
"url": "https://github.com/kentcdodds/prettier-eslint.git"
19+
},
20+
"bugs": {
21+
"url": "https://github.com/kwelch/entities-reducer/issues"
22+
},
23+
"homepage": "https://github.com/kwelch/entities-reducer.git#readme",
24+
"author": "Kyle Welch <kwelch0626@gmail.com>",
25+
"license": "MIT",
26+
"devDependencies": {
27+
"babel-cli": "^6.22.2",
28+
"babel-eslint": "^7.1.1",
29+
"babel-jest": "^18.0.0",
30+
"babel-polyfill": "^6.22.0",
31+
"babel-preset-es2015": "^6.22.0",
32+
"codecov": "^1.0.1",
33+
"eslint": "^3.14.1",
34+
"jest": "^18.1.0",
35+
"rimraf": "^2.5.4",
36+
"semantic-release": "^6.3.2"
37+
},
38+
"eslintConfig": {
39+
"extends": [
40+
"eslint:recommended"
41+
],
42+
"parser": "babel-eslint",
43+
"env": {
44+
"es6": true,
45+
"jest": true
46+
}
47+
}
48+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
exports[`entitiesReducer should allow customer reducers 1`] = `
2+
Object {
3+
"users": Object {},
4+
}
5+
`;
6+
7+
exports[`entitiesReducer should reduce entities from payload 1`] = `
8+
Object {
9+
"users": Object {
10+
"1": Object {
11+
"firstName": "Kyle",
12+
"id": 1,
13+
"lastName": "Welch",
14+
"middleName": "Ryan",
15+
},
16+
},
17+
}
18+
`;
19+
20+
exports[`entitiesReducer should reduce entities from payload 2`] = `
21+
Object {
22+
"roles": Object {
23+
"1": Object {
24+
"id": 1,
25+
"type": "Admin",
26+
},
27+
},
28+
"users": Object {
29+
"1": Object {
30+
"firstName": "Kyle",
31+
"id": 1,
32+
"lastName": "Welch",
33+
"middleName": "Ryan",
34+
"role": 1,
35+
},
36+
},
37+
}
38+
`;
39+
40+
exports[`entitiesReducer should reduce entities from payload 3`] = `
41+
Object {
42+
"roles": Object {
43+
"1": Object {
44+
"id": 1,
45+
"type": "Admin",
46+
},
47+
},
48+
"users": Object {
49+
"1": Object {
50+
"address": Object {
51+
"city": "IL",
52+
},
53+
"firstName": "Kyle",
54+
"id": 1,
55+
"lastName": "Welch",
56+
"middleName": "Ryan",
57+
},
58+
},
59+
}
60+
`;
61+
62+
exports[`entitiesReducer should reduce entities from payload 4`] = `
63+
Object {
64+
"roles": Object {
65+
"1": Object {
66+
"id": 1,
67+
"type": "Admin",
68+
},
69+
},
70+
"users": Object {
71+
"1": Object {
72+
"address": Object {
73+
"city": "TN",
74+
},
75+
"firstName": "Kyle",
76+
"id": 1,
77+
"lastName": "Welch",
78+
"middleName": "Ryan",
79+
},
80+
},
81+
}
82+
`;

src/index.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const updateEntity = (state, entities) => {
2+
return Object.assign({}, state, entities);
3+
};
4+
5+
const updateEntities = (state, key, entities) => {
6+
return Object.assign({}, state, { [key]: updateEntity(state[key], entities[key]) });
7+
};
8+
9+
export default (reducers) => (state = {}, action) => {
10+
const { payload } = action;
11+
let newState = state;
12+
if (payload && !payload.error && payload.entities) {
13+
const { entities } = payload;
14+
newState = Object.keys(entities).reduce((acc, key) => updateEntities(acc, key, entities), newState);
15+
}
16+
newState = Object.keys(reducers).reduce((acc, key) => {
17+
const reducerReturn = reducers[key](acc[key], action);
18+
return Object.assign({}, acc, { [key]: reducerReturn });
19+
}, newState);
20+
return newState;
21+
};

src/index.spec.js

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import entitiesReducer from './index';
2+
3+
describe('entitiesReducer', () => {
4+
const initialState = {
5+
users: {
6+
1: {
7+
id: 1,
8+
firstName: 'Kyle',
9+
lastName: 'Welch',
10+
},
11+
},
12+
};
13+
14+
it('should reduce entities from payload', () => {
15+
let newState = entitiesReducer({})(initialState, {
16+
payload: {
17+
entities: {
18+
users: {
19+
1: {
20+
firstName: "Kyle",
21+
id: 1,
22+
lastName: "Welch",
23+
middleName: "Ryan",
24+
},
25+
},
26+
},
27+
result: 1,
28+
},
29+
type: "ENTITY/ENTITY_NORMALIZE",
30+
});
31+
expect(newState).toMatchSnapshot();
32+
33+
newState = entitiesReducer({})(newState, {
34+
payload: {
35+
entities: {
36+
users: {
37+
1: {
38+
firstName: "Kyle",
39+
id: 1,
40+
lastName: "Welch",
41+
middleName: "Ryan",
42+
role: 1,
43+
}
44+
},
45+
roles: {
46+
1: {
47+
type: "Admin",
48+
id: 1,
49+
},
50+
},
51+
},
52+
result: 2,
53+
},
54+
type: "ENTITY/ENTITY_NORMALIZE",
55+
});
56+
expect(newState).toMatchSnapshot();
57+
58+
newState = entitiesReducer({})(newState, {
59+
payload: {
60+
entities: {
61+
users: {
62+
1: {
63+
firstName: "Kyle",
64+
id: 1,
65+
lastName: "Welch",
66+
middleName: "Ryan",
67+
address: {
68+
city: "IL",
69+
}
70+
},
71+
},
72+
},
73+
result: 1,
74+
},
75+
type: "ENTITY/ENTITY_NORMALIZE",
76+
});
77+
expect(newState).toMatchSnapshot();
78+
79+
newState = entitiesReducer({})(newState, {
80+
payload: {
81+
entities: {
82+
users: {
83+
1: {
84+
firstName: "Kyle",
85+
id: 1,
86+
lastName: "Welch",
87+
middleName: "Ryan",
88+
address: {
89+
city: "TN",
90+
}
91+
},
92+
},
93+
},
94+
result: 1,
95+
},
96+
type: "ENTITY/ENTITY_NORMALIZE",
97+
});
98+
expect(newState).toMatchSnapshot();
99+
});
100+
101+
it('should return state when `!action.payload`', () => {
102+
const newState = entitiesReducer({})(initialState, {});
103+
expect(newState).toEqual(initialState);
104+
});
105+
106+
it('should return state when `action.payload.error`', () => {
107+
const newState = entitiesReducer({})(initialState, {});
108+
expect(newState).toEqual(initialState);
109+
});
110+
111+
it('should allow customer reducers ', () => {
112+
const customUserReducer = (state = {}, action) => {
113+
switch(action.type) {
114+
case "ENTITY/DELETE": {
115+
const newState = Object.assign({}, state);
116+
delete newState[action.payload.result];
117+
return newState;
118+
}
119+
}
120+
};
121+
let newState = entitiesReducer({ users: customUserReducer, })(newState, {
122+
payload: {
123+
entities: {
124+
users: {
125+
1: {
126+
firstName: "Kyle",
127+
id: 1,
128+
lastName: "Welch",
129+
middleName: "Ryan",
130+
address: {
131+
city: "TN",
132+
}
133+
},
134+
},
135+
},
136+
result: 1,
137+
},
138+
type: "ENTITY/DELETE",
139+
});
140+
expect(newState).toMatchSnapshot();
141+
});
142+
});

0 commit comments

Comments
 (0)