Skip to content

Commit d9208d6

Browse files
authored
Merge pull request #1 from bernabe9/master
Update
2 parents 0275aad + d828343 commit d9208d6

File tree

7 files changed

+4551
-68
lines changed

7 files changed

+4551
-68
lines changed

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Redux React Session
22

33
[![NPM version](https://img.shields.io/npm/v/redux-react-session.svg?style=flat)](https://npmjs.org/package/redux-react-session)
4-
[![Build status: Linux](https://img.shields.io/travis/bernabe9/redux-react-session.svg?style=flat)](https://travis-ci.org/bernabe9/redux-react-session)
4+
[![Build status: Linux](https://travis-ci.org/bernabe9/redux-react-session.svg?branch=master)](https://travis-ci.org/bernabe9/redux-react-session)
55
[![Dependency Status](https://img.shields.io/david/bernabe9/redux-react-session.svg)](https://david-dm.org/bernabe9/redux-react-session)
66
[![Coverage Status](https://img.shields.io/coveralls/bernabe9/redux-react-session.svg)](https://coveralls.io/github/bernabe9/redux-react-session?branch=master)
77

8-
Keep your session sync with localStorage and Redux :key:
8+
Keep your session sync with your local storage and Redux :key:
99

1010
Redux React Session provides an API that allows to manage sessions through the app, with authorization function for [react-router](https://github.com/ReactTraining/react-router) and a persisted session.
1111

@@ -43,7 +43,7 @@ sessionService.initSessionService(store);
4343
## Examples
4444
The examples simulates a simple login/logout that sends requests to a server.
4545

46-
### Run the example
46+
### Run the example for react router v3
4747
1. **get into the folder**:`cd examples/example`
4848
2. **install dependencies**: `npm install`
4949
3. **run the example**: `npm start`
@@ -56,9 +56,13 @@ The examples simulates a simple login/logout that sends requests to a server.
5656

5757
## API
5858

59-
### initSessionService(store, options)
59+
### initSessionService(store, options) : Promise
6060
Initialize an instance of the session service.
6161

62+
The promise will be resolved if the session is valid, and will be rejected if there is no data in the storage.
63+
64+
Once the promise is resolved or rejected the flag `checked` in the redux store will change from `false` to `true`. This allows to check into any component if the session was already checked and it's valid.
65+
6266
Options:
6367
- refreshOnCheckAuth(**default**: false): Refresh Redux store in the `checkAuth` function
6468
- redirectPath(**default**: `"login"`): Path used when a session is rejected or doesn't exist
@@ -67,11 +71,15 @@ Options:
6771
Example:
6872
```javascript
6973
const options = { refreshOnCheckAuth: true, redirectPath: '/home', driver: 'COOKIES' };
70-
sessionService.initSessionService(store, options);
74+
sessionService.initSessionService(store, options)
75+
.then(() => console.log('Redux React Session is ready and a session was refreshed from your storage'))
76+
.catch(() => console.log('Redux React Session is ready and there is no session in your storage'));
7177
```
7278

7379
### refreshFromLocalStorage
74-
Force to refresh the Redux Store from the localStorage.
80+
Force to refresh the Redux Store from the local storage.
81+
82+
The promise will be resolved if the session is valid, and will be rejected if there is no data in the storage.
7583

7684
Note: this function is called once the session service is initialized
7785

__mocks__/localforage.js

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,62 @@ import { USER_SESSION, USER_DATA } from '../src/constants';
44

55
const localforage = jest.genMockFromModule('localforage');
66

7+
function createInstance() {
8+
return new LocalForage();
9+
}
10+
711
let throwError = false;
812
let user = undefined;
913
let session = undefined;
1014

15+
class LocalForage {
16+
constructor() {}
17+
18+
setItem(item, data) {
19+
return new Promise((resolve, reject) => {
20+
if (item === USER_SESSION) {
21+
session = data;
22+
} else if (item === USER_DATA) {
23+
user = data;
24+
}
25+
throwError ? reject() : resolve(data);
26+
});
27+
}
28+
29+
getItem(item) {
30+
return new Promise((resolve) => {
31+
if (item === USER_SESSION) {
32+
return resolve(session);
33+
} else if (item === USER_DATA) {
34+
return resolve(user);
35+
}
36+
});
37+
}
38+
39+
removeItem(item) {
40+
return new Promise((resolve) => {
41+
if (item === USER_SESSION) {
42+
session = undefined;
43+
} else if (item === USER_DATA) {
44+
user = undefined;
45+
}
46+
resolve();
47+
});
48+
}
49+
50+
__setError(error) {
51+
throwError = error;
52+
}
53+
54+
__setUser(item) {
55+
user = item;
56+
}
57+
58+
__setSession(item) {
59+
session = item;
60+
}
61+
}
62+
1163
function __setError(error) {
1264
throwError = error;
1365
}
@@ -20,41 +72,7 @@ function __setSession(item) {
2072
session = item;
2173
}
2274

23-
function setItem(item, data) {
24-
return new Promise((resolve, reject) => {
25-
if (item === USER_SESSION) {
26-
session = data;
27-
} else if (item === USER_DATA) {
28-
user = data;
29-
}
30-
throwError ? reject() : resolve(data);
31-
});
32-
}
33-
34-
function getItem(item) {
35-
return new Promise((resolve) => {
36-
if (item === USER_SESSION) {
37-
return resolve(session);
38-
} else if (item === USER_DATA) {
39-
return resolve(user);
40-
}
41-
});
42-
}
43-
44-
function removeItem(item) {
45-
return new Promise((resolve) => {
46-
if (item === USER_SESSION) {
47-
session = undefined;
48-
} else if (item === USER_DATA) {
49-
user = undefined;
50-
}
51-
resolve();
52-
});
53-
}
54-
55-
localforage.setItem = setItem;
56-
localforage.getItem = getItem;
57-
localforage.removeItem = removeItem;
75+
localforage.createInstance = createInstance;
5876
localforage.__setError = __setError;
5977
localforage.__setUser = __setUser;
6078
localforage.__setSession = __setSession;

_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
theme: jekyll-theme-cayman

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-react-session",
3-
"version": "2.1.0",
3+
"version": "2.3.0",
44
"description": "",
55
"main": "dist/index.js",
66
"scripts": {
@@ -53,7 +53,7 @@
5353
"dependencies": {
5454
"immutable": "^3.8.1",
5555
"js-cookie": "2.1.4",
56-
"localforage": "1.5.0"
56+
"localforage": "1.5.5"
5757
},
5858
"peerDependencies": {
5959
"react": "^0.14.0 || ^15.0.0",

src/__tests__/index.spec.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,23 @@
33
import { sessionService, sessionReducer } from '../index';
44
import { initialState } from '../reducer';
55
import { createStore } from 'redux';
6-
import { __setError, __setSession, __setUser } from 'localforage';
76
import * as Cookies from "js-cookie";
87

98
jest.mock('localforage');
109

10+
const localforage = require('localforage');
11+
const { __setError, __setSession, __setUser } = localforage;
12+
1113
describe('API functions', () => {
1214
let store;
1315
const user = { email: 'test@test.com', firstName: 'test', lastName: 'test' };
1416
const session = { token: '12341234' };
1517
beforeAll((done) => {
1618
store = createStore(sessionReducer, initialState);
17-
18-
// wait for refresh redux store from localStorage
19-
const unsubscribe = store.subscribe(() => {
20-
unsubscribe();
19+
const options = { driver: 'LOCALFORAGE' };
20+
sessionService.initSessionService(store, options).then( () => {
2121
done();
2222
});
23-
sessionService.initSessionService(store);
2423
});
2524

2625
describe('refreshFromLocalStorage', () => {

src/index.js

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { USER_SESSION, USER_DATA } from './constants';
2-
import * as localForage from 'localforage';
32
import * as Cookies from "js-cookie";
43
import {
54
getSessionSuccess,
@@ -32,12 +31,21 @@ export class sessionService {
3231
instance.expires = expires;
3332
instance.driver = driver;
3433
instance.server = server;
35-
driver && driver !== 'COOKIES' && localForage.setDriver(localForage[driver]);
34+
35+
// configure the storage
36+
const storageOptions = {
37+
name: 'redux-react-session'
38+
};
39+
const localforage = require('localforage');
40+
if (driver && driver !== 'COOKIES') {
41+
storageOptions.driver = localforage[driver];
42+
}
43+
instance.storage = localforage.createInstance(storageOptions);
3644
}
3745

3846
static initSessionService(store, options) {
3947
instance = new sessionService(store, options);
40-
sessionService.refreshFromLocalStorage();
48+
return sessionService.refreshFromLocalStorage();
4149
}
4250

4351
static initServerSession(store, req, options) {
@@ -54,25 +62,31 @@ export class sessionService {
5462

5563
return list;
5664
};
57-
sessionService.saveFromClient(parseCookies(req));
65+
return sessionService.saveFromClient(parseCookies(req));
5866
}
5967

6068
static saveFromClient(cookies) {
61-
if (cookies[USER_SESSION]) {
62-
sessionService.saveSession(cookies[USER_SESSION])
63-
.then(() => {
64-
if (cookies[USER_DATA]) {
65-
sessionService.saveUser(cookies[USER_DATA]);
66-
}
67-
});
68-
}
69+
return new Promise((resolve, reject) => {
70+
if (cookies[USER_SESSION]) {
71+
sessionService.saveSession(cookies[USER_SESSION])
72+
.then(() => {
73+
if (cookies[USER_DATA]) {
74+
sessionService.saveUser(cookies[USER_DATA])
75+
.then(() => resolve());
76+
}
77+
});
78+
} else {
79+
instance.store.dispatch(getSessionError());
80+
reject('Session not found');
81+
}
82+
});
6983
}
7084

7185
static refreshFromLocalStorage() {
7286
return sessionService.loadSession()
7387
.then(() => {
7488
instance.store.dispatch(getSessionSuccess());
75-
sessionService.loadUser().then((user) => {
89+
return sessionService.loadUser().then((user) => {
7690
instance.store.dispatch(getUserSessionSuccess(user));
7791
})
7892
.catch(() => {
@@ -116,7 +130,7 @@ export class sessionService {
116130
instance.store.dispatch(getSessionSuccess());
117131
resolve();
118132
} else {
119-
localForage.setItem(USER_SESSION, session)
133+
instance.storage.setItem(USER_SESSION, session)
120134
.then(() => {
121135
instance.store.dispatch(getSessionSuccess());
122136
resolve();
@@ -138,7 +152,7 @@ export class sessionService {
138152
const cookies = Cookies.getJSON(USER_SESSION);
139153
cookies ? resolve(cookies) : reject('Session not found');
140154
} else {
141-
localForage.getItem(USER_SESSION)
155+
instance.storage.getItem(USER_SESSION)
142156
.then((currentSession) => {
143157
if (currentSession) {
144158
resolve(currentSession);
@@ -153,7 +167,7 @@ export class sessionService {
153167
}
154168

155169
static deleteSession() {
156-
return localForage.removeItem(USER_SESSION).then(() => {
170+
return instance.storage.removeItem(USER_SESSION).then(() => {
157171
instance.store.dispatch(getSessionError());
158172
Cookies.remove(USER_SESSION);
159173
delete instance[USER_SESSION];
@@ -171,7 +185,7 @@ export class sessionService {
171185
instance.store.dispatch(getUserSessionSuccess(user));
172186
resolve();
173187
} else {
174-
localForage.setItem(USER_DATA, user)
188+
instance.storage.setItem(USER_DATA, user)
175189
.then((user) => {
176190
instance.store.dispatch(getUserSessionSuccess(user));
177191
resolve();
@@ -193,7 +207,7 @@ export class sessionService {
193207
const cookies = Cookies.getJSON(USER_DATA);
194208
cookies ? resolve(cookies) : reject('User not found');
195209
} else {
196-
localForage.getItem(USER_DATA)
210+
instance.storage.getItem(USER_DATA)
197211
.then((currentUser) => {
198212
if (currentUser) {
199213
resolve(currentUser);
@@ -208,7 +222,7 @@ export class sessionService {
208222
}
209223

210224
static deleteUser() {
211-
return localForage.removeItem(USER_DATA).then(() => {
225+
return instance.storage.removeItem(USER_DATA).then(() => {
212226
instance.store.dispatch(getUserSessionError());
213227
Cookies.remove(USER_DATA);
214228
delete instance[USER_DATA];

0 commit comments

Comments
 (0)