Coverage

100%
74
74
0

/Users/jordan/code/nuclear/examples/rest-api-example/src/modules/rest-api/action-types.js

100%
2
2
0
LineHitsSource
11var keyMirror = require('keymirror')
2
31module.exports = keyMirror({
4 API_FETCH_SUCCESS: null,
5 API_FETCH_START: null,
6 API_FETCH_FAIL: null,
7
8 API_SAVE_SUCCESS: null,
9 API_SAVE_START: null,
10 API_SAVE_FAIL: null,
11
12 API_DELETE_SUCCESS: null,
13 API_DELETE_START: null,
14 API_DELETE_FAIL: null,
15})
16

/Users/jordan/code/nuclear/examples/rest-api-example/src/modules/rest-api/create-api-actions.js

100%
37
37
0
LineHitsSource
11var Promise = require('es6-promise').Promise
21var Flux = require('../../flux')
31var actionTypes = require('./action-types')
4
5/**
6 * @param {Object} model
7 * @param {String} model.entity
8 * @param {Function} model.save
9 * @param {Function} model.fetch
10 * @param {Function} model.fetchAll
11 * @param {Function} model.delete
12 * @return {Object}
13 */
141module.exports = function(model) {
1521 var entity = model.entity;
1621 var apiActions = {}
17
1821 apiActions.fetch = function(params) {
196 Flux.dispatch(actionTypes.API_FETCH_START, {
20 model: model,
21 method: 'fetch',
22 params: params,
23 })
246 return model.fetch(params).then(
25 onFetchSuccess.bind(null, model, params),
26 onFetchFail.bind(null, model, params)
27 )
28 }
29
3021 apiActions.fetchAll = function(params) {
318 Flux.dispatch(actionTypes.API_FETCH_START, {
32 model: model,
33 method: 'fetchAll',
34 params: params,
35 })
368 return model.fetchAll(params).then(
37 onFetchSuccess.bind(null, model, params),
38 onFetchFail.bind(null, model, params)
39 )
40 }
41
4221 apiActions.save = function(params) {
435 Flux.dispatch(actionTypes.API_SAVE_START, {
44 params: params,
45 })
465 return model.save(params).then(
47 onSaveSuccess.bind(null, model, params),
48 onSaveFail.bind(null, model, params)
49 )
50 }
51
5221 apiActions['delete'] = function(params) {
534 Flux.dispatch(actionTypes.API_DELETE_START, {
54 params: params,
55 })
564 return model['delete'](params).then(
57 onDeleteSuccess.bind(null, model, params),
58 onDeleteFail.bind(null, model, params)
59 )
60 }
61
6221 return apiActions
63}
64
65/**
66 * Handler for API fetch success, dispatches flux action to store the fetched
67 * result in the api cache
68 * @param {Model} model
69 * @param {*} params used to call the `model.fetch(params)`
70 * @param {Object} result
71 * @return {Object}
72 */
731function onFetchSuccess(model, params, result) {
7410 Flux.dispatch(actionTypes.API_FETCH_SUCCESS, {
75 model: model,
76 params: params,
77 result: result,
78 })
7910 return result
80}
81
82/**
83 * Handler for API fetch success, dispatches flux action to store the fetched
84 * result in the api cache
85 * @param {Model} model
86 * @param {*} params used to call the `model.fetch(params)`
87 * @param {*} reason
88 * @return {Object}
89 */
901function onFetchFail(model, params, reason) {
914 Flux.dispatch(actionTypes.API_FETCH_FAIL, {
92 model: model,
93 params: params,
94 reason: reason,
95 })
964 return Promise.reject(reason)
97}
98
99/**
100 * Handler for API save success, dispatches flux action to update the store with the
101 * saved instance
102 * @param {Model} model
103 * @param {*} params used to call the `model.save(params)`
104 * @param {Object} result
105 * @return {Object}
106 */
1071function onSaveSuccess(model, params, result) {
1083 Flux.dispatch(actionTypes.API_SAVE_SUCCESS, {
109 model: model,
110 params: params,
111 result: result,
112 })
1133 return result
114}
115
116/**
117 * Handler for API save success, dispatches flux action to update the store with the
118 * saved instance
119 * @param {Model} model
120 * @param {*} params used to call the `model.save(params)`
121 * @param {*} reason
122 * @return {Object}
123 */
1241function onSaveFail(model, params, reason) {
1252 Flux.dispatch(actionTypes.API_SAVE_FAIL, {
126 model: model,
127 params: params,
128 reason: reason,
129 })
1302 return Promise.reject(reason)
131}
132
133/**
134 * Handler for API delete success, dispatches flux action to remove the instance from the stores
135 * @param {Model} model
136 * @param {*} params used to call the `model.delete(params)`
137 * @param {Object} result
138 * @return {Object}
139 */
1401function onDeleteSuccess(model, params, result) {
1412 Flux.dispatch(actionTypes.API_DELETE_SUCCESS, {
142 model: model,
143 params: params,
144 result: result,
145 })
1462 return result
147}
148
149/**
150 * Handler for API delete fail
151 * @param {Model} model
152 * @param {*} params used to call the `model.delete(params)`
153 * @param {Object} result
154 * @return {Object}
155 */
1561function onDeleteFail(model, params, reason) {
1572 Flux.dispatch(actionTypes.API_DELETE_FAIL, {
158 model: model,
159 params: params,
160 reason: reason,
161 })
1622 return Promise.reject(reason)
163}
164
165

/Users/jordan/code/nuclear/examples/rest-api-example/src/modules/rest-api/index.js

100%
12
12
0
LineHitsSource
11var toImmutable = require('nuclear-js').toImmutable
21var Flux = require('../../flux')
3
4// register stores with Flux system
51Flux.registerStores({
6 restApiCache: require('./stores/rest-api-cache-store'),
7})
8
91exports.createApiActions = require('./create-api-actions')
10
11/**
12 * Creates a getter to the restApiCache store for a particular entity
13 * This decouples the implementation details of the RestApi module's caching
14 * to consumers of the cached data
15 * @param {Model} model
16 */
171exports.createEntityMapGetter = function(model) {
182 return [
19 ['restApiCache', model.entity],
20 /**
21 * @return {Immutable.Map}
22 */
23 function(entityMap) {
24 // protect the entityMap here from being undefined, there are cases
25 // where an entity type isn't loaded yet, so we need to always to
26 // return an Immutable.Map for getters downstream
272 if (!entityMap) {
281 return toImmutable({})
29 } else {
301 return entityMap
31 }
32 }
33 ]
34}
35
36/**
37 * Creates a function that creates a getter that looks up the entity in the restApiCache by ID
38 * @param {Model} model
39 */
401exports.createByIdGetter = function(model) {
411 return function(id) {
421 return ['restApiCache', model.entity, id]
43 }
44}
45

/Users/jordan/code/nuclear/examples/rest-api-example/src/modules/rest-api/stores/rest-api-cache-store.js

100%
23
23
0
LineHitsSource
1/**
2 * Stores cached entities for the Rest API
3 */
41var _ = require('lodash');
51var Nuclear = require('nuclear-js')
61var toImmutable = Nuclear.toImmutable
71var actionTypes = require('../action-types')
8
91module.exports = new Nuclear.Store({
10 getInitialState: function() {
1125 return toImmutable({})
12 },
13
14 initialize: function() {
151 this.on(actionTypes.API_FETCH_SUCCESS, loadData)
161 this.on(actionTypes.API_SAVE_SUCCESS, loadData)
171 this.on(actionTypes.API_DELETE_SUCCESS, removeData)
18 },
19})
20
21/**
22 * @param {Immutable.Map} state
23 * @param {Object} payload
24 * @param {Model} payload.model
25 * @param {any} payload.params
26 * @param {Object|Array} payload.result
27 */
281function loadData(state, payload) {
2915 var entity = payload.model.entity
3015 var data = payload.result
31
3215 if (!data) {
33 // no-op if no real data was returned
341 return state
35 }
36
3714 if (!_.isArray(data)) {
386 data = [data]
39 }
40
4114 return state.withMutations(function(state) {
4214 data.forEach(function(entry) {
4324 state.setIn([entity, entry.id], toImmutable(entry))
44 })
45 })
46}
47
48/**
49 * @param {Immutable.Map} state
50 * @param {Object} payload
51 * @param {Model} payload.model
52 * @param {any} payload.params
53 * @param {Object|Array} payload.result
54 */
551function removeData(state, payload) {
562 var entity = payload.model.entity
57 // we assume that params is the instance with an `id` property
582 var id = payload.params.id
59
602 return state.removeIn([entity, id]);
61}
62