├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── dist
├── index.js
├── lib
│ ├── combineUrl.js
│ ├── createAction.js
│ ├── createEventSource.js
│ ├── eventHandlers.js
│ └── sendRequest.js
└── reducers.js
├── docs
└── Introduction.md
├── package.json
├── src
├── index.js
├── lib
│ ├── combineUrl.js
│ ├── createAction.js
│ ├── createEventSource.js
│ ├── eventHandlers.js
│ └── sendRequest.js
└── reducers.js
└── test
├── createAction.js
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | build
3 | lib-cov
4 | *.seed
5 | *.log
6 | *.csv
7 | *.dat
8 | *.out
9 | *.pid
10 | *.gz
11 | _book
12 |
13 | pids
14 | logs
15 | results
16 | package-lock.json
17 | npm-debug.log
18 | node_modules
19 | *.sublime*
20 | *.node
21 | coverage
22 | *.orig
23 | .idea
24 | sandbox
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 | env:
5 | - CXX=g++-4.8
6 | addons:
7 | apt:
8 | sources:
9 | - ubuntu-toolchain-r-test
10 | packages:
11 | - g++-4.8
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Contra
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Dead-simple API/EventSource actions for Redux
4 |
5 |
6 | This is a work in progress - There is sparse documentation, no tests, and it's not on npm. Use at your own risk while we finish up!
7 |
8 | ## Install
9 |
10 | One command and you're ready to roll:
11 |
12 | ```
13 | npm install tahoe
14 | ```
15 |
16 | **Now**, check out the [documentation](http://shasta.tools/tahoe/docs) to get started!
17 |
18 | ## Example
19 |
20 | Coming soon
21 |
22 | [downloads-image]: http://img.shields.io/npm/dm/tahoe.svg
23 | [npm-url]: https://npmjs.org/package/tahoe
24 | [npm-image]: http://img.shields.io/npm/v/tahoe.svg
25 |
26 | [travis-url]: https://travis-ci.org/shastajs/tahoe
27 | [travis-image]: https://travis-ci.org/shastajs/tahoe.png?branch=master
28 |
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _createAction = require('./lib/createAction');
8 |
9 | var _createAction2 = _interopRequireDefault(_createAction);
10 |
11 | var _reducers = require('./reducers');
12 |
13 | var reducers = _interopRequireWildcard(_reducers);
14 |
15 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
16 |
17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18 |
19 | exports.default = {
20 | createAction: _createAction2.default,
21 | reducers: reducers
22 | };
23 | module.exports = exports['default'];
24 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5qcyJdLCJuYW1lcyI6WyJyZWR1Y2VycyIsImNyZWF0ZUFjdGlvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7Ozs7QUFDQTs7SUFBWUEsUTs7Ozs7O2tCQUVHO0FBQ2JDLHNDQURhO0FBRWJELFlBQVVBO0FBRkcsQyIsImZpbGUiOiJpbmRleC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjcmVhdGVBY3Rpb24gZnJvbSAnLi9saWIvY3JlYXRlQWN0aW9uJ1xuaW1wb3J0ICogYXMgcmVkdWNlcnMgZnJvbSAnLi9yZWR1Y2VycydcblxuZXhwb3J0IGRlZmF1bHQge1xuICBjcmVhdGVBY3Rpb24sXG4gIHJlZHVjZXJzOiByZWR1Y2Vyc1xufVxuIl19
--------------------------------------------------------------------------------
/dist/lib/combineUrl.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _extends2 = require('babel-runtime/helpers/extends');
8 |
9 | var _extends3 = _interopRequireDefault(_extends2);
10 |
11 | var _url = require('url');
12 |
13 | var _url2 = _interopRequireDefault(_url);
14 |
15 | var _qs = require('qs');
16 |
17 | var _qs2 = _interopRequireDefault(_qs);
18 |
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20 |
21 | exports.default = function (endpoint, query) {
22 | var parsed = _url2.default.parse(endpoint);
23 |
24 | var q = _qs2.default.stringify((0, _extends3.default)({}, _qs2.default.parse(parsed.query, { strictNullHandling: true }), query), { strictNullHandling: true });
25 |
26 | return _url2.default.format({
27 | protocol: parsed.protocol,
28 | auth: parsed.auth,
29 | port: parsed.port,
30 | host: parsed.host,
31 | pathname: parsed.pathname,
32 | search: q
33 | });
34 | };
35 |
36 | module.exports = exports['default'];
37 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvY29tYmluZVVybC5qcyJdLCJuYW1lcyI6WyJlbmRwb2ludCIsInF1ZXJ5IiwicGFyc2VkIiwidXJsIiwicGFyc2UiLCJxIiwicXMiLCJzdHJpbmdpZnkiLCJzdHJpY3ROdWxsSGFuZGxpbmciLCJmb3JtYXQiLCJwcm90b2NvbCIsImF1dGgiLCJwb3J0IiwiaG9zdCIsInBhdGhuYW1lIiwic2VhcmNoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7Ozs7QUFDQTs7Ozs7O2tCQUVlLFVBQUNBLFFBQUQsRUFBV0MsS0FBWCxFQUFxQjtBQUNsQyxNQUFNQyxTQUFTQyxjQUFJQyxLQUFKLENBQVVKLFFBQVYsQ0FBZjs7QUFFQSxNQUFNSyxJQUFJQyxhQUFHQyxTQUFILDRCQUNMRCxhQUFHRixLQUFILENBQVNGLE9BQU9ELEtBQWhCLEVBQXVCLEVBQUVPLG9CQUFvQixJQUF0QixFQUF2QixDQURLLEVBRUxQLEtBRkssR0FHUCxFQUFFTyxvQkFBb0IsSUFBdEIsRUFITyxDQUFWOztBQUtBLFNBQU9MLGNBQUlNLE1BQUosQ0FBVztBQUNoQkMsY0FBVVIsT0FBT1EsUUFERDtBQUVoQkMsVUFBTVQsT0FBT1MsSUFGRztBQUdoQkMsVUFBTVYsT0FBT1UsSUFIRztBQUloQkMsVUFBTVgsT0FBT1csSUFKRztBQUtoQkMsY0FBVVosT0FBT1ksUUFMRDtBQU1oQkMsWUFBUVY7QUFOUSxHQUFYLENBQVA7QUFRRCxDIiwiZmlsZSI6ImNvbWJpbmVVcmwuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdXJsIGZyb20gJ3VybCdcbmltcG9ydCBxcyBmcm9tICdxcydcblxuZXhwb3J0IGRlZmF1bHQgKGVuZHBvaW50LCBxdWVyeSkgPT4ge1xuICBjb25zdCBwYXJzZWQgPSB1cmwucGFyc2UoZW5kcG9pbnQpXG5cbiAgY29uc3QgcSA9IHFzLnN0cmluZ2lmeSh7XG4gICAgLi4ucXMucGFyc2UocGFyc2VkLnF1ZXJ5LCB7IHN0cmljdE51bGxIYW5kbGluZzogdHJ1ZSB9KSxcbiAgICAuLi5xdWVyeVxuICB9LCB7IHN0cmljdE51bGxIYW5kbGluZzogdHJ1ZSB9KVxuXG4gIHJldHVybiB1cmwuZm9ybWF0KHtcbiAgICBwcm90b2NvbDogcGFyc2VkLnByb3RvY29sLFxuICAgIGF1dGg6IHBhcnNlZC5hdXRoLFxuICAgIHBvcnQ6IHBhcnNlZC5wb3J0LFxuICAgIGhvc3Q6IHBhcnNlZC5ob3N0LFxuICAgIHBhdGhuYW1lOiBwYXJzZWQucGF0aG5hbWUsXG4gICAgc2VhcmNoOiBxXG4gIH0pXG59XG4iXX0=
--------------------------------------------------------------------------------
/dist/lib/createAction.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.mergeOptions = undefined;
7 |
8 | var _regenerator = require('babel-runtime/regenerator');
9 |
10 | var _regenerator2 = _interopRequireDefault(_regenerator);
11 |
12 | var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
13 |
14 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
15 |
16 | var _lodash = require('lodash.mapvalues');
17 |
18 | var _lodash2 = _interopRequireDefault(_lodash);
19 |
20 | var _lodash3 = require('lodash.merge');
21 |
22 | var _lodash4 = _interopRequireDefault(_lodash3);
23 |
24 | var _sendRequest = require('./sendRequest');
25 |
26 | var _sendRequest2 = _interopRequireDefault(_sendRequest);
27 |
28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29 |
30 | var reserved = ['onResponse', 'onError', 'onGlobalError'];
31 | var result = function result(fn, arg) {
32 | return typeof fn === 'function' ? fn(arg) : fn;
33 | };
34 |
35 | // TODO:0 check entities cache in store and dont fetch if we have it already
36 |
37 | /*
38 | app must have redux-thunk installed
39 | possible options:
40 |
41 | - subset (optional)(string)
42 | - tail (default false)(boolean)
43 | - method (required)(get, post, put, delete, or patch)
44 | - params (object)
45 | - endpoint (required)(url tring)
46 | - collection (default false)(boolean)
47 | - fresh (default to false)(boolean)
48 |
49 | all options can either be a value, or a function that returns a value.
50 | if you define a function, it will receive options.params as an argument
51 | */
52 |
53 | // merge our multitude of option objects together
54 | // defaults = options defined in createAction
55 | // opt = options specified in action creator
56 | var isReserved = function isReserved(k) {
57 | return reserved.indexOf(k) !== -1;
58 | };
59 |
60 | var resolveFunctions = function resolveFunctions(o, params) {
61 | return (0, _lodash2.default)(o, function (v, k) {
62 | return isReserved(k) ? v : result(v, params);
63 | });
64 | };
65 |
66 | var mergeOptions = exports.mergeOptions = function mergeOptions(defaults, opt) {
67 | var defaultParams = defaults.params ? result(defaults.params) : {};
68 | var optParams = opt.params ? result(opt.params) : {};
69 | var params = (0, _lodash4.default)({}, optParams, defaultParams);
70 | return (0, _lodash4.default)({}, resolveFunctions(opt, params), resolveFunctions(defaults, params));
71 | };
72 |
73 | exports.default = function () {
74 | var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
75 |
76 | var nfn = function nfn() {
77 | var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
78 |
79 | var options = mergeOptions(defaults, opt);
80 | if (!options.method) throw new Error('Missing method');
81 | if (!options.endpoint) throw new Error('Missing endpoint');
82 | var fn = function () {
83 | var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(dispatch) {
84 | return _regenerator2.default.wrap(function _callee$(_context) {
85 | while (1) {
86 | switch (_context.prev = _context.next) {
87 | case 0:
88 | return _context.abrupt('return', (0, _sendRequest2.default)({ options: options, dispatch: dispatch }));
89 |
90 | case 1:
91 | case 'end':
92 | return _context.stop();
93 | }
94 | }
95 | }, _callee, undefined);
96 | }));
97 |
98 | return function fn(_x3) {
99 | return _ref.apply(this, arguments);
100 | };
101 | }();
102 | fn.options = options;
103 | return fn;
104 | };
105 | nfn.options = defaults;
106 | return nfn;
107 | };
108 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvY3JlYXRlQWN0aW9uLmpzIl0sIm5hbWVzIjpbInJlc2VydmVkIiwicmVzdWx0IiwiZm4iLCJhcmciLCJpc1Jlc2VydmVkIiwiayIsImluZGV4T2YiLCJyZXNvbHZlRnVuY3Rpb25zIiwibyIsInBhcmFtcyIsInYiLCJtZXJnZU9wdGlvbnMiLCJkZWZhdWx0cyIsIm9wdCIsImRlZmF1bHRQYXJhbXMiLCJvcHRQYXJhbXMiLCJuZm4iLCJvcHRpb25zIiwibWV0aG9kIiwiRXJyb3IiLCJlbmRwb2ludCIsImRpc3BhdGNoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBLElBQU1BLFdBQVcsQ0FDZixZQURlLEVBRWYsU0FGZSxFQUdmLGVBSGUsQ0FBakI7QUFLQSxJQUFNQyxTQUFTLFNBQVRBLE1BQVMsQ0FBQ0MsRUFBRCxFQUFLQyxHQUFMO0FBQUEsU0FBYSxPQUFPRCxFQUFQLEtBQWMsVUFBZCxHQUEyQkEsR0FBR0MsR0FBSCxDQUEzQixHQUFxQ0QsRUFBbEQ7QUFBQSxDQUFmOztBQUVBOztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBO0FBQ0E7QUFDQTtBQUNBLElBQU1FLGFBQWEsU0FBYkEsVUFBYSxDQUFDQyxDQUFEO0FBQUEsU0FBT0wsU0FBU00sT0FBVCxDQUFpQkQsQ0FBakIsTUFBd0IsQ0FBQyxDQUFoQztBQUFBLENBQW5COztBQUVBLElBQU1FLG1CQUFtQixTQUFuQkEsZ0JBQW1CLENBQUNDLENBQUQsRUFBSUMsTUFBSjtBQUFBLFNBQ3ZCLHNCQUFVRCxDQUFWLEVBQWEsVUFBQ0UsQ0FBRCxFQUFJTCxDQUFKO0FBQUEsV0FDWEQsV0FBV0MsQ0FBWCxJQUFnQkssQ0FBaEIsR0FBb0JULE9BQU9TLENBQVAsRUFBVUQsTUFBVixDQURUO0FBQUEsR0FBYixDQUR1QjtBQUFBLENBQXpCOztBQUtPLElBQU1FLHNDQUFlLFNBQWZBLFlBQWUsQ0FBQ0MsUUFBRCxFQUFXQyxHQUFYLEVBQW1CO0FBQzdDLE1BQU1DLGdCQUFnQkYsU0FBU0gsTUFBVCxHQUFrQlIsT0FBT1csU0FBU0gsTUFBaEIsQ0FBbEIsR0FBNEMsRUFBbEU7QUFDQSxNQUFNTSxZQUFZRixJQUFJSixNQUFKLEdBQWFSLE9BQU9ZLElBQUlKLE1BQVgsQ0FBYixHQUFrQyxFQUFwRDtBQUNBLE1BQU1BLFNBQVMsc0JBQU0sRUFBTixFQUFVTSxTQUFWLEVBQXFCRCxhQUFyQixDQUFmO0FBQ0EsU0FBTyxzQkFBTSxFQUFOLEVBQVVQLGlCQUFpQk0sR0FBakIsRUFBc0JKLE1BQXRCLENBQVYsRUFBeUNGLGlCQUFpQkssUUFBakIsRUFBMkJILE1BQTNCLENBQXpDLENBQVA7QUFDRCxDQUxNOztrQkFPUSxZQUFtQjtBQUFBLE1BQWxCRyxRQUFrQix1RUFBUCxFQUFPOztBQUNoQyxNQUFNSSxNQUFNLFNBQU5BLEdBQU0sR0FBYztBQUFBLFFBQWJILEdBQWEsdUVBQVAsRUFBTzs7QUFDeEIsUUFBTUksVUFBVU4sYUFBYUMsUUFBYixFQUF1QkMsR0FBdkIsQ0FBaEI7QUFDQSxRQUFJLENBQUNJLFFBQVFDLE1BQWIsRUFBcUIsTUFBTSxJQUFJQyxLQUFKLENBQVUsZ0JBQVYsQ0FBTjtBQUNyQixRQUFJLENBQUNGLFFBQVFHLFFBQWIsRUFBdUIsTUFBTSxJQUFJRCxLQUFKLENBQVUsa0JBQVYsQ0FBTjtBQUN2QixRQUFNakI7QUFBQSwwRkFBSyxpQkFBT21CLFFBQVA7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGlEQUFvQiwyQkFBWSxFQUFFSixnQkFBRixFQUFXSSxrQkFBWCxFQUFaLENBQXBCOztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE9BQUw7O0FBQUE7QUFBQTtBQUFBO0FBQUEsT0FBTjtBQUNBbkIsT0FBR2UsT0FBSCxHQUFhQSxPQUFiO0FBQ0EsV0FBT2YsRUFBUDtBQUNELEdBUEQ7QUFRQWMsTUFBSUMsT0FBSixHQUFjTCxRQUFkO0FBQ0EsU0FBT0ksR0FBUDtBQUNELEMiLCJmaWxlIjoiY3JlYXRlQWN0aW9uLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG1hcFZhbHVlcyBmcm9tICdsb2Rhc2gubWFwdmFsdWVzJ1xuaW1wb3J0IG1lcmdlIGZyb20gJ2xvZGFzaC5tZXJnZSdcbmltcG9ydCBzZW5kUmVxdWVzdCBmcm9tICcuL3NlbmRSZXF1ZXN0J1xuXG5jb25zdCByZXNlcnZlZCA9IFtcbiAgJ29uUmVzcG9uc2UnLFxuICAnb25FcnJvcicsXG4gICdvbkdsb2JhbEVycm9yJ1xuXVxuY29uc3QgcmVzdWx0ID0gKGZuLCBhcmcpID0+IHR5cGVvZiBmbiA9PT0gJ2Z1bmN0aW9uJyA/IGZuKGFyZykgOiBmblxuXG4vLyBUT0RPOjAgY2hlY2sgZW50aXRpZXMgY2FjaGUgaW4gc3RvcmUgYW5kIGRvbnQgZmV0Y2ggaWYgd2UgaGF2ZSBpdCBhbHJlYWR5XG5cbi8qXG5hcHAgbXVzdCBoYXZlIHJlZHV4LXRodW5rIGluc3RhbGxlZFxucG9zc2libGUgb3B0aW9uczpcblxuLSBzdWJzZXQgKG9wdGlvbmFsKShzdHJpbmcpXG4tIHRhaWwgKGRlZmF1bHQgZmFsc2UpKGJvb2xlYW4pXG4tIG1ldGhvZCAocmVxdWlyZWQpKGdldCwgcG9zdCwgcHV0LCBkZWxldGUsIG9yIHBhdGNoKVxuLSBwYXJhbXMgKG9iamVjdClcbi0gZW5kcG9pbnQgKHJlcXVpcmVkKSh1cmwgdHJpbmcpXG4tIGNvbGxlY3Rpb24gKGRlZmF1bHQgZmFsc2UpKGJvb2xlYW4pXG4tIGZyZXNoIChkZWZhdWx0IHRvIGZhbHNlKShib29sZWFuKVxuXG5hbGwgb3B0aW9ucyBjYW4gZWl0aGVyIGJlIGEgdmFsdWUsIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgdmFsdWUuXG5pZiB5b3UgZGVmaW5lIGEgZnVuY3Rpb24sIGl0IHdpbGwgcmVjZWl2ZSBvcHRpb25zLnBhcmFtcyBhcyBhbiBhcmd1bWVudFxuKi9cblxuLy8gbWVyZ2Ugb3VyIG11bHRpdHVkZSBvZiBvcHRpb24gb2JqZWN0cyB0b2dldGhlclxuLy8gZGVmYXVsdHMgPSBvcHRpb25zIGRlZmluZWQgaW4gY3JlYXRlQWN0aW9uXG4vLyBvcHQgPSBvcHRpb25zIHNwZWNpZmllZCBpbiBhY3Rpb24gY3JlYXRvclxuY29uc3QgaXNSZXNlcnZlZCA9IChrKSA9PiByZXNlcnZlZC5pbmRleE9mKGspICE9PSAtMVxuXG5jb25zdCByZXNvbHZlRnVuY3Rpb25zID0gKG8sIHBhcmFtcykgPT5cbiAgbWFwVmFsdWVzKG8sICh2LCBrKSA9PlxuICAgIGlzUmVzZXJ2ZWQoaykgPyB2IDogcmVzdWx0KHYsIHBhcmFtcylcbiAgKVxuXG5leHBvcnQgY29uc3QgbWVyZ2VPcHRpb25zID0gKGRlZmF1bHRzLCBvcHQpID0+IHtcbiAgY29uc3QgZGVmYXVsdFBhcmFtcyA9IGRlZmF1bHRzLnBhcmFtcyA/IHJlc3VsdChkZWZhdWx0cy5wYXJhbXMpIDoge31cbiAgY29uc3Qgb3B0UGFyYW1zID0gb3B0LnBhcmFtcyA/IHJlc3VsdChvcHQucGFyYW1zKSA6IHt9XG4gIGNvbnN0IHBhcmFtcyA9IG1lcmdlKHt9LCBvcHRQYXJhbXMsIGRlZmF1bHRQYXJhbXMpXG4gIHJldHVybiBtZXJnZSh7fSwgcmVzb2x2ZUZ1bmN0aW9ucyhvcHQsIHBhcmFtcyksIHJlc29sdmVGdW5jdGlvbnMoZGVmYXVsdHMsIHBhcmFtcykpXG59XG5cbmV4cG9ydCBkZWZhdWx0IChkZWZhdWx0cyA9IHt9KSA9PiB7XG4gIGNvbnN0IG5mbiA9IChvcHQgPSB7fSkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtZXJnZU9wdGlvbnMoZGVmYXVsdHMsIG9wdClcbiAgICBpZiAoIW9wdGlvbnMubWV0aG9kKSB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgbWV0aG9kJylcbiAgICBpZiAoIW9wdGlvbnMuZW5kcG9pbnQpIHRocm93IG5ldyBFcnJvcignTWlzc2luZyBlbmRwb2ludCcpXG4gICAgY29uc3QgZm4gPSBhc3luYyAoZGlzcGF0Y2gpID0+IHNlbmRSZXF1ZXN0KHsgb3B0aW9ucywgZGlzcGF0Y2ggfSlcbiAgICBmbi5vcHRpb25zID0gb3B0aW9uc1xuICAgIHJldHVybiBmblxuICB9XG4gIG5mbi5vcHRpb25zID0gZGVmYXVsdHNcbiAgcmV0dXJuIG5mblxufVxuIl19
--------------------------------------------------------------------------------
/dist/lib/createEventSource.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _regenerator = require('babel-runtime/regenerator');
8 |
9 | var _regenerator2 = _interopRequireDefault(_regenerator);
10 |
11 | var _keys = require('babel-runtime/core-js/object/keys');
12 |
13 | var _keys2 = _interopRequireDefault(_keys);
14 |
15 | var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
16 |
17 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
18 |
19 | var _combineUrl = require('./combineUrl');
20 |
21 | var _combineUrl2 = _interopRequireDefault(_combineUrl);
22 |
23 | var _eventHandlers = require('./eventHandlers');
24 |
25 | var _eventHandlers2 = _interopRequireDefault(_eventHandlers);
26 |
27 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28 |
29 | var tryParse = function tryParse(_ref) {
30 | var data = _ref.data,
31 | options = _ref.options,
32 | dispatch = _ref.dispatch;
33 |
34 | try {
35 | return JSON.parse(data);
36 | } catch (err) {
37 | dispatch({
38 | type: 'tahoe.failure',
39 | meta: options,
40 | payload: err
41 | });
42 | }
43 | };
44 |
45 | exports.default = function () {
46 | var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(_ref3) {
47 | var options = _ref3.options,
48 | dispatch = _ref3.dispatch;
49 | var finalUrl, src;
50 | return _regenerator2.default.wrap(function _callee$(_context) {
51 | while (1) {
52 | switch (_context.prev = _context.next) {
53 | case 0:
54 | finalUrl = (0, _combineUrl2.default)(options.endpoint, options.query);
55 | src = new EventSource(finalUrl, { withCredentials: options.withCredentials });
56 |
57 | // wire up listeners n shiz
58 |
59 | (0, _keys2.default)(_eventHandlers2.default).forEach(function (eventName) {
60 | var handler = _eventHandlers2.default[eventName];
61 | src.addEventListener(eventName, function (_ref4) {
62 | var data = _ref4.data;
63 |
64 | var parsed = data && tryParse({ options: options, dispatch: dispatch, data: data });
65 | if (data && typeof parsed === 'undefined') return;
66 | handler({ options: options, dispatch: dispatch, data: parsed });
67 | }, false);
68 | });
69 |
70 | case 3:
71 | case 'end':
72 | return _context.stop();
73 | }
74 | }
75 | }, _callee, undefined);
76 | }));
77 |
78 | return function (_x) {
79 | return _ref2.apply(this, arguments);
80 | };
81 | }();
82 |
83 | module.exports = exports['default'];
84 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvY3JlYXRlRXZlbnRTb3VyY2UuanMiXSwibmFtZXMiOlsidHJ5UGFyc2UiLCJkYXRhIiwib3B0aW9ucyIsImRpc3BhdGNoIiwiSlNPTiIsInBhcnNlIiwiZXJyIiwidHlwZSIsIm1ldGEiLCJwYXlsb2FkIiwiZmluYWxVcmwiLCJlbmRwb2ludCIsInF1ZXJ5Iiwic3JjIiwiRXZlbnRTb3VyY2UiLCJ3aXRoQ3JlZGVudGlhbHMiLCJoYW5kbGVycyIsImZvckVhY2giLCJldmVudE5hbWUiLCJoYW5kbGVyIiwiYWRkRXZlbnRMaXN0ZW5lciIsInBhcnNlZCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7Ozs7QUFDQTs7Ozs7O0FBRUEsSUFBTUEsV0FBVyxTQUFYQSxRQUFXLE9BQWlDO0FBQUEsTUFBOUJDLElBQThCLFFBQTlCQSxJQUE4QjtBQUFBLE1BQXhCQyxPQUF3QixRQUF4QkEsT0FBd0I7QUFBQSxNQUFmQyxRQUFlLFFBQWZBLFFBQWU7O0FBQ2hELE1BQUk7QUFDRixXQUFPQyxLQUFLQyxLQUFMLENBQVdKLElBQVgsQ0FBUDtBQUNELEdBRkQsQ0FFRSxPQUFPSyxHQUFQLEVBQVk7QUFDWkgsYUFBUztBQUNQSSxZQUFNLGVBREM7QUFFUEMsWUFBTU4sT0FGQztBQUdQTyxlQUFTSDtBQUhGLEtBQVQ7QUFLRDtBQUNGLENBVkQ7Ozt1RkFZZTtBQUFBLFFBQVNKLE9BQVQsU0FBU0EsT0FBVDtBQUFBLFFBQWtCQyxRQUFsQixTQUFrQkEsUUFBbEI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ1BPLG9CQURPLEdBQ0ksMEJBQVdSLFFBQVFTLFFBQW5CLEVBQTZCVCxRQUFRVSxLQUFyQyxDQURKO0FBRVBDLGVBRk8sR0FFRCxJQUFJQyxXQUFKLENBQWdCSixRQUFoQixFQUEwQixFQUFFSyxpQkFBaUJiLFFBQVFhLGVBQTNCLEVBQTFCLENBRkM7O0FBSWI7O0FBQ0EsZ0NBQVlDLHVCQUFaLEVBQXNCQyxPQUF0QixDQUE4QixVQUFDQyxTQUFELEVBQWU7QUFDM0Msa0JBQU1DLFVBQVVILHdCQUFTRSxTQUFULENBQWhCO0FBQ0FMLGtCQUFJTyxnQkFBSixDQUFxQkYsU0FBckIsRUFBZ0MsaUJBQWM7QUFBQSxvQkFBWGpCLElBQVcsU0FBWEEsSUFBVzs7QUFDNUMsb0JBQU1vQixTQUFTcEIsUUFBUUQsU0FBUyxFQUFFRSxnQkFBRixFQUFXQyxrQkFBWCxFQUFxQkYsVUFBckIsRUFBVCxDQUF2QjtBQUNBLG9CQUFJQSxRQUFRLE9BQU9vQixNQUFQLEtBQWtCLFdBQTlCLEVBQTJDO0FBQzNDRix3QkFBUSxFQUFFakIsZ0JBQUYsRUFBV0Msa0JBQVgsRUFBcUJGLE1BQU1vQixNQUEzQixFQUFSO0FBQ0QsZUFKRCxFQUlHLEtBSkg7QUFLRCxhQVBEOztBQUxhO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEciLCJmaWxlIjoiY3JlYXRlRXZlbnRTb3VyY2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY29tYmluZVVybCBmcm9tICcuL2NvbWJpbmVVcmwnXG5pbXBvcnQgaGFuZGxlcnMgZnJvbSAnLi9ldmVudEhhbmRsZXJzJ1xuXG5jb25zdCB0cnlQYXJzZSA9ICh7IGRhdGEsIG9wdGlvbnMsIGRpc3BhdGNoIH0pID0+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShkYXRhKVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBkaXNwYXRjaCh7XG4gICAgICB0eXBlOiAndGFob2UuZmFpbHVyZScsXG4gICAgICBtZXRhOiBvcHRpb25zLFxuICAgICAgcGF5bG9hZDogZXJyXG4gICAgfSlcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBhc3luYyAoeyBvcHRpb25zLCBkaXNwYXRjaCB9KSA9PiB7XG4gIGNvbnN0IGZpbmFsVXJsID0gY29tYmluZVVybChvcHRpb25zLmVuZHBvaW50LCBvcHRpb25zLnF1ZXJ5KVxuICBjb25zdCBzcmMgPSBuZXcgRXZlbnRTb3VyY2UoZmluYWxVcmwsIHsgd2l0aENyZWRlbnRpYWxzOiBvcHRpb25zLndpdGhDcmVkZW50aWFscyB9KVxuXG4gIC8vIHdpcmUgdXAgbGlzdGVuZXJzIG4gc2hpelxuICBPYmplY3Qua2V5cyhoYW5kbGVycykuZm9yRWFjaCgoZXZlbnROYW1lKSA9PiB7XG4gICAgY29uc3QgaGFuZGxlciA9IGhhbmRsZXJzW2V2ZW50TmFtZV1cbiAgICBzcmMuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsICh7IGRhdGEgfSkgPT4ge1xuICAgICAgY29uc3QgcGFyc2VkID0gZGF0YSAmJiB0cnlQYXJzZSh7IG9wdGlvbnMsIGRpc3BhdGNoLCBkYXRhIH0pXG4gICAgICBpZiAoZGF0YSAmJiB0eXBlb2YgcGFyc2VkID09PSAndW5kZWZpbmVkJykgcmV0dXJuXG4gICAgICBoYW5kbGVyKHsgb3B0aW9ucywgZGlzcGF0Y2gsIGRhdGE6IHBhcnNlZCB9KVxuICAgIH0sIGZhbHNlKVxuICB9KVxufVxuIl19
--------------------------------------------------------------------------------
/dist/lib/eventHandlers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var handlers = {};
8 | handlers.open = function (_ref) {
9 | var options = _ref.options,
10 | dispatch = _ref.dispatch;
11 | return dispatch({
12 | type: 'tahoe.tail.open',
13 | meta: options
14 | });
15 | };
16 |
17 | handlers.insert = function (_ref2) {
18 | var options = _ref2.options,
19 | dispatch = _ref2.dispatch,
20 | next = _ref2.data.next;
21 | return dispatch({
22 | type: 'tahoe.tail.insert',
23 | meta: options,
24 | payload: {
25 | raw: next
26 | }
27 | });
28 | };
29 |
30 | handlers.update = function (_ref3) {
31 | var options = _ref3.options,
32 | dispatch = _ref3.dispatch,
33 | _ref3$data = _ref3.data,
34 | prev = _ref3$data.prev,
35 | next = _ref3$data.next;
36 | return dispatch({
37 | type: 'tahoe.tail.update',
38 | meta: options,
39 | payload: {
40 | raw: {
41 | prev: prev,
42 | next: next
43 | }
44 | }
45 | });
46 | };
47 |
48 | handlers.delete = function (_ref4) {
49 | var options = _ref4.options,
50 | dispatch = _ref4.dispatch,
51 | prev = _ref4.data.prev;
52 | return dispatch({
53 | type: 'tahoe.tail.delete',
54 | meta: options,
55 | payload: {
56 | raw: prev
57 | }
58 | });
59 | };
60 |
61 | exports.default = handlers;
62 | module.exports = exports['default'];
63 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvZXZlbnRIYW5kbGVycy5qcyJdLCJuYW1lcyI6WyJoYW5kbGVycyIsIm9wZW4iLCJvcHRpb25zIiwiZGlzcGF0Y2giLCJ0eXBlIiwibWV0YSIsImluc2VydCIsIm5leHQiLCJkYXRhIiwicGF5bG9hZCIsInJhdyIsInVwZGF0ZSIsInByZXYiLCJkZWxldGUiXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLElBQU1BLFdBQVcsRUFBakI7QUFDQUEsU0FBU0MsSUFBVCxHQUFnQjtBQUFBLE1BQUdDLE9BQUgsUUFBR0EsT0FBSDtBQUFBLE1BQVlDLFFBQVosUUFBWUEsUUFBWjtBQUFBLFNBQ2RBLFNBQVM7QUFDUEMsVUFBTSxpQkFEQztBQUVQQyxVQUFNSDtBQUZDLEdBQVQsQ0FEYztBQUFBLENBQWhCOztBQU1BRixTQUFTTSxNQUFULEdBQWtCO0FBQUEsTUFBR0osT0FBSCxTQUFHQSxPQUFIO0FBQUEsTUFBWUMsUUFBWixTQUFZQSxRQUFaO0FBQUEsTUFBOEJJLElBQTlCLFNBQXNCQyxJQUF0QixDQUE4QkQsSUFBOUI7QUFBQSxTQUNoQkosU0FBUztBQUNQQyxVQUFNLG1CQURDO0FBRVBDLFVBQU1ILE9BRkM7QUFHUE8sYUFBUztBQUNQQyxXQUFLSDtBQURFO0FBSEYsR0FBVCxDQURnQjtBQUFBLENBQWxCOztBQVNBUCxTQUFTVyxNQUFULEdBQWtCO0FBQUEsTUFBR1QsT0FBSCxTQUFHQSxPQUFIO0FBQUEsTUFBWUMsUUFBWixTQUFZQSxRQUFaO0FBQUEseUJBQXNCSyxJQUF0QjtBQUFBLE1BQThCSSxJQUE5QixjQUE4QkEsSUFBOUI7QUFBQSxNQUFvQ0wsSUFBcEMsY0FBb0NBLElBQXBDO0FBQUEsU0FDaEJKLFNBQVM7QUFDUEMsVUFBTSxtQkFEQztBQUVQQyxVQUFNSCxPQUZDO0FBR1BPLGFBQVM7QUFDUEMsV0FBSztBQUNIRSxjQUFNQSxJQURIO0FBRUhMLGNBQU1BO0FBRkg7QUFERTtBQUhGLEdBQVQsQ0FEZ0I7QUFBQSxDQUFsQjs7QUFhQVAsU0FBU2EsTUFBVCxHQUFrQjtBQUFBLE1BQUdYLE9BQUgsU0FBR0EsT0FBSDtBQUFBLE1BQVlDLFFBQVosU0FBWUEsUUFBWjtBQUFBLE1BQThCUyxJQUE5QixTQUFzQkosSUFBdEIsQ0FBOEJJLElBQTlCO0FBQUEsU0FDaEJULFNBQVM7QUFDUEMsVUFBTSxtQkFEQztBQUVQQyxVQUFNSCxPQUZDO0FBR1BPLGFBQVM7QUFDUEMsV0FBS0U7QUFERTtBQUhGLEdBQVQsQ0FEZ0I7QUFBQSxDQUFsQjs7a0JBU2VaLFEiLCJmaWxlIjoiZXZlbnRIYW5kbGVycy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc3QgaGFuZGxlcnMgPSB7fVxuaGFuZGxlcnMub3BlbiA9ICh7IG9wdGlvbnMsIGRpc3BhdGNoIH0pID0+XG4gIGRpc3BhdGNoKHtcbiAgICB0eXBlOiAndGFob2UudGFpbC5vcGVuJyxcbiAgICBtZXRhOiBvcHRpb25zXG4gIH0pXG5cbmhhbmRsZXJzLmluc2VydCA9ICh7IG9wdGlvbnMsIGRpc3BhdGNoLCBkYXRhOiB7IG5leHQgfSB9KSA9PlxuICBkaXNwYXRjaCh7XG4gICAgdHlwZTogJ3RhaG9lLnRhaWwuaW5zZXJ0JyxcbiAgICBtZXRhOiBvcHRpb25zLFxuICAgIHBheWxvYWQ6IHtcbiAgICAgIHJhdzogbmV4dFxuICAgIH1cbiAgfSlcblxuaGFuZGxlcnMudXBkYXRlID0gKHsgb3B0aW9ucywgZGlzcGF0Y2gsIGRhdGE6IHsgcHJldiwgbmV4dCB9IH0pID0+XG4gIGRpc3BhdGNoKHtcbiAgICB0eXBlOiAndGFob2UudGFpbC51cGRhdGUnLFxuICAgIG1ldGE6IG9wdGlvbnMsXG4gICAgcGF5bG9hZDoge1xuICAgICAgcmF3OiB7XG4gICAgICAgIHByZXY6IHByZXYsXG4gICAgICAgIG5leHQ6IG5leHRcbiAgICAgIH1cbiAgICB9XG4gIH0pXG5cblxuaGFuZGxlcnMuZGVsZXRlID0gKHsgb3B0aW9ucywgZGlzcGF0Y2gsIGRhdGE6IHsgcHJldiB9IH0pID0+XG4gIGRpc3BhdGNoKHtcbiAgICB0eXBlOiAndGFob2UudGFpbC5kZWxldGUnLFxuICAgIG1ldGE6IG9wdGlvbnMsXG4gICAgcGF5bG9hZDoge1xuICAgICAgcmF3OiBwcmV2XG4gICAgfVxuICB9KVxuXG5leHBvcnQgZGVmYXVsdCBoYW5kbGVyc1xuIl19
--------------------------------------------------------------------------------
/dist/lib/sendRequest.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 |
7 | var _regenerator = require('babel-runtime/regenerator');
8 |
9 | var _regenerator2 = _interopRequireDefault(_regenerator);
10 |
11 | var _promise = require('babel-runtime/core-js/promise');
12 |
13 | var _promise2 = _interopRequireDefault(_promise);
14 |
15 | var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
16 |
17 | var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
18 |
19 | var _superagent = require('superagent');
20 |
21 | var _superagent2 = _interopRequireDefault(_superagent);
22 |
23 | var _createEventSource = require('./createEventSource');
24 |
25 | var _createEventSource2 = _interopRequireDefault(_createEventSource);
26 |
27 | var _qs = require('qs');
28 |
29 | var _qs2 = _interopRequireDefault(_qs);
30 |
31 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32 |
33 | var createResponseHandler = function createResponseHandler(_ref) {
34 | var options = _ref.options,
35 | dispatch = _ref.dispatch,
36 | reject = _ref.reject,
37 | resolve = _ref.resolve;
38 |
39 | var debug = options.method.toUpperCase() + ' ' + options.endpoint;
40 | return function (err, res) {
41 | if (!res && !err) {
42 | err = new Error('Connection failed: ' + debug);
43 | }
44 | if (err) {
45 | err.res = res;
46 | dispatch({
47 | type: 'tahoe.failure',
48 | meta: options,
49 | payload: err
50 | });
51 | if (options.onGlobalError) options.onGlobalError(err, res);
52 | if (options.onError) options.onError(err, res);
53 | return reject(err);
54 | }
55 |
56 | // handle json responses
57 | dispatch({
58 | type: 'tahoe.success',
59 | meta: options,
60 | payload: {
61 | raw: res.body,
62 | text: res.text
63 | }
64 | });
65 | if (options.onResponse) options.onResponse(res);
66 | resolve(res);
67 | };
68 | };
69 |
70 | exports.default = function () {
71 | var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(_ref3) {
72 | var options = _ref3.options,
73 | dispatch = _ref3.dispatch;
74 | var req;
75 | return _regenerator2.default.wrap(function _callee$(_context) {
76 | while (1) {
77 | switch (_context.prev = _context.next) {
78 | case 0:
79 | dispatch({
80 | type: 'tahoe.request',
81 | payload: options
82 | });
83 |
84 | if (!options.tail) {
85 | _context.next = 3;
86 | break;
87 | }
88 |
89 | return _context.abrupt('return', (0, _createEventSource2.default)({ options: options, dispatch: dispatch }));
90 |
91 | case 3:
92 | req = _superagent2.default[options.method.toLowerCase()](options.endpoint);
93 |
94 | if (options.headers) {
95 | req.set(options.headers);
96 | }
97 | if (options.query) {
98 | req.query(typeof options.query === 'string' ? options.query : _qs2.default.stringify(options.query, { strictNullHandling: true }));
99 | }
100 | if (options.body) {
101 | req.send(options.body);
102 | }
103 | if (options.withCredentials) {
104 | req.withCredentials();
105 | }
106 |
107 | return _context.abrupt('return', new _promise2.default(function (resolve, reject) {
108 | req.end(createResponseHandler({
109 | options: options,
110 | dispatch: dispatch,
111 | reject: reject,
112 | resolve: resolve
113 | }));
114 | }));
115 |
116 | case 9:
117 | case 'end':
118 | return _context.stop();
119 | }
120 | }
121 | }, _callee, undefined);
122 | }));
123 |
124 | return function (_x) {
125 | return _ref2.apply(this, arguments);
126 | };
127 | }();
128 |
129 | module.exports = exports['default'];
130 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvc2VuZFJlcXVlc3QuanMiXSwibmFtZXMiOlsiY3JlYXRlUmVzcG9uc2VIYW5kbGVyIiwib3B0aW9ucyIsImRpc3BhdGNoIiwicmVqZWN0IiwicmVzb2x2ZSIsImRlYnVnIiwibWV0aG9kIiwidG9VcHBlckNhc2UiLCJlbmRwb2ludCIsImVyciIsInJlcyIsIkVycm9yIiwidHlwZSIsIm1ldGEiLCJwYXlsb2FkIiwib25HbG9iYWxFcnJvciIsIm9uRXJyb3IiLCJyYXciLCJib2R5IiwidGV4dCIsIm9uUmVzcG9uc2UiLCJ0YWlsIiwicmVxIiwicmVxdWVzdCIsInRvTG93ZXJDYXNlIiwiaGVhZGVycyIsInNldCIsInF1ZXJ5IiwicXMiLCJzdHJpbmdpZnkiLCJzdHJpY3ROdWxsSGFuZGxpbmciLCJzZW5kIiwid2l0aENyZWRlbnRpYWxzIiwiZW5kIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBLElBQU1BLHdCQUF3QixTQUF4QkEscUJBQXdCLE9BQTRDO0FBQUEsTUFBekNDLE9BQXlDLFFBQXpDQSxPQUF5QztBQUFBLE1BQWhDQyxRQUFnQyxRQUFoQ0EsUUFBZ0M7QUFBQSxNQUF0QkMsTUFBc0IsUUFBdEJBLE1BQXNCO0FBQUEsTUFBZEMsT0FBYyxRQUFkQSxPQUFjOztBQUN4RSxNQUFNQyxRQUFXSixRQUFRSyxNQUFSLENBQWVDLFdBQWYsRUFBWCxTQUEyQ04sUUFBUU8sUUFBekQ7QUFDQSxTQUFPLFVBQUNDLEdBQUQsRUFBTUMsR0FBTixFQUFjO0FBQ25CLFFBQUksQ0FBQ0EsR0FBRCxJQUFRLENBQUNELEdBQWIsRUFBa0I7QUFDaEJBLFlBQU0sSUFBSUUsS0FBSix5QkFBZ0NOLEtBQWhDLENBQU47QUFDRDtBQUNELFFBQUlJLEdBQUosRUFBUztBQUNQQSxVQUFJQyxHQUFKLEdBQVVBLEdBQVY7QUFDQVIsZUFBUztBQUNQVSxjQUFNLGVBREM7QUFFUEMsY0FBTVosT0FGQztBQUdQYSxpQkFBU0w7QUFIRixPQUFUO0FBS0EsVUFBSVIsUUFBUWMsYUFBWixFQUEyQmQsUUFBUWMsYUFBUixDQUFzQk4sR0FBdEIsRUFBMkJDLEdBQTNCO0FBQzNCLFVBQUlULFFBQVFlLE9BQVosRUFBcUJmLFFBQVFlLE9BQVIsQ0FBZ0JQLEdBQWhCLEVBQXFCQyxHQUFyQjtBQUNyQixhQUFPUCxPQUFPTSxHQUFQLENBQVA7QUFDRDs7QUFFRDtBQUNBUCxhQUFTO0FBQ1BVLFlBQU0sZUFEQztBQUVQQyxZQUFNWixPQUZDO0FBR1BhLGVBQVM7QUFDUEcsYUFBS1AsSUFBSVEsSUFERjtBQUVQQyxjQUFNVCxJQUFJUztBQUZIO0FBSEYsS0FBVDtBQVFBLFFBQUlsQixRQUFRbUIsVUFBWixFQUF3Qm5CLFFBQVFtQixVQUFSLENBQW1CVixHQUFuQjtBQUN4Qk4sWUFBUU0sR0FBUjtBQUNELEdBM0JEO0FBNEJELENBOUJEOzs7dUZBZ0NlO0FBQUEsUUFBU1QsT0FBVCxTQUFTQSxPQUFUO0FBQUEsUUFBa0JDLFFBQWxCLFNBQWtCQSxRQUFsQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDYkEscUJBQVM7QUFDUFUsb0JBQU0sZUFEQztBQUVQRSx1QkFBU2I7QUFGRixhQUFUOztBQURhLGlCQU1UQSxRQUFRb0IsSUFOQztBQUFBO0FBQUE7QUFBQTs7QUFBQSw2Q0FPSixpQ0FBa0IsRUFBRXBCLGdCQUFGLEVBQVdDLGtCQUFYLEVBQWxCLENBUEk7O0FBQUE7QUFVUG9CLGVBVk8sR0FVREMscUJBQVF0QixRQUFRSyxNQUFSLENBQWVrQixXQUFmLEVBQVIsRUFBc0N2QixRQUFRTyxRQUE5QyxDQVZDOztBQVdiLGdCQUFJUCxRQUFRd0IsT0FBWixFQUFxQjtBQUNuQkgsa0JBQUlJLEdBQUosQ0FBUXpCLFFBQVF3QixPQUFoQjtBQUNEO0FBQ0QsZ0JBQUl4QixRQUFRMEIsS0FBWixFQUFtQjtBQUNqQkwsa0JBQUlLLEtBQUosQ0FBVSxPQUFPMUIsUUFBUTBCLEtBQWYsS0FBeUIsUUFBekIsR0FDTjFCLFFBQVEwQixLQURGLEdBRU5DLGFBQUdDLFNBQUgsQ0FBYTVCLFFBQVEwQixLQUFyQixFQUE0QixFQUFFRyxvQkFBb0IsSUFBdEIsRUFBNUIsQ0FGSjtBQUdEO0FBQ0QsZ0JBQUk3QixRQUFRaUIsSUFBWixFQUFrQjtBQUNoQkksa0JBQUlTLElBQUosQ0FBUzlCLFFBQVFpQixJQUFqQjtBQUNEO0FBQ0QsZ0JBQUlqQixRQUFRK0IsZUFBWixFQUE2QjtBQUMzQlYsa0JBQUlVLGVBQUo7QUFDRDs7QUF4QlksNkNBMEJOLHNCQUFZLFVBQUM1QixPQUFELEVBQVVELE1BQVYsRUFBcUI7QUFDdENtQixrQkFBSVcsR0FBSixDQUFRakMsc0JBQXNCO0FBQzVCQyxnQ0FENEI7QUFFNUJDLGtDQUY0QjtBQUc1QkMsOEJBSDRCO0FBSTVCQztBQUo0QixlQUF0QixDQUFSO0FBTUQsYUFQTSxDQTFCTTs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxHIiwiZmlsZSI6InNlbmRSZXF1ZXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHJlcXVlc3QgZnJvbSAnc3VwZXJhZ2VudCdcbmltcG9ydCBjcmVhdGVFdmVudFNvdXJjZSBmcm9tICcuL2NyZWF0ZUV2ZW50U291cmNlJ1xuaW1wb3J0IHFzIGZyb20gJ3FzJ1xuXG5jb25zdCBjcmVhdGVSZXNwb25zZUhhbmRsZXIgPSAoeyBvcHRpb25zLCBkaXNwYXRjaCwgcmVqZWN0LCByZXNvbHZlIH0pID0+IHtcbiAgY29uc3QgZGVidWcgPSBgJHtvcHRpb25zLm1ldGhvZC50b1VwcGVyQ2FzZSgpfSAke29wdGlvbnMuZW5kcG9pbnR9YFxuICByZXR1cm4gKGVyciwgcmVzKSA9PiB7XG4gICAgaWYgKCFyZXMgJiYgIWVycikge1xuICAgICAgZXJyID0gbmV3IEVycm9yKGBDb25uZWN0aW9uIGZhaWxlZDogJHtkZWJ1Z31gKVxuICAgIH1cbiAgICBpZiAoZXJyKSB7XG4gICAgICBlcnIucmVzID0gcmVzXG4gICAgICBkaXNwYXRjaCh7XG4gICAgICAgIHR5cGU6ICd0YWhvZS5mYWlsdXJlJyxcbiAgICAgICAgbWV0YTogb3B0aW9ucyxcbiAgICAgICAgcGF5bG9hZDogZXJyXG4gICAgICB9KVxuICAgICAgaWYgKG9wdGlvbnMub25HbG9iYWxFcnJvcikgb3B0aW9ucy5vbkdsb2JhbEVycm9yKGVyciwgcmVzKVxuICAgICAgaWYgKG9wdGlvbnMub25FcnJvcikgb3B0aW9ucy5vbkVycm9yKGVyciwgcmVzKVxuICAgICAgcmV0dXJuIHJlamVjdChlcnIpXG4gICAgfVxuXG4gICAgLy8gaGFuZGxlIGpzb24gcmVzcG9uc2VzXG4gICAgZGlzcGF0Y2goe1xuICAgICAgdHlwZTogJ3RhaG9lLnN1Y2Nlc3MnLFxuICAgICAgbWV0YTogb3B0aW9ucyxcbiAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgcmF3OiByZXMuYm9keSxcbiAgICAgICAgdGV4dDogcmVzLnRleHRcbiAgICAgIH1cbiAgICB9KVxuICAgIGlmIChvcHRpb25zLm9uUmVzcG9uc2UpIG9wdGlvbnMub25SZXNwb25zZShyZXMpXG4gICAgcmVzb2x2ZShyZXMpXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgKHsgb3B0aW9ucywgZGlzcGF0Y2ggfSkgPT4ge1xuICBkaXNwYXRjaCh7XG4gICAgdHlwZTogJ3RhaG9lLnJlcXVlc3QnLFxuICAgIHBheWxvYWQ6IG9wdGlvbnNcbiAgfSlcblxuICBpZiAob3B0aW9ucy50YWlsKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUV2ZW50U291cmNlKHsgb3B0aW9ucywgZGlzcGF0Y2ggfSlcbiAgfVxuXG4gIGNvbnN0IHJlcSA9IHJlcXVlc3Rbb3B0aW9ucy5tZXRob2QudG9Mb3dlckNhc2UoKV0ob3B0aW9ucy5lbmRwb2ludClcbiAgaWYgKG9wdGlvbnMuaGVhZGVycykge1xuICAgIHJlcS5zZXQob3B0aW9ucy5oZWFkZXJzKVxuICB9XG4gIGlmIChvcHRpb25zLnF1ZXJ5KSB7XG4gICAgcmVxLnF1ZXJ5KHR5cGVvZiBvcHRpb25zLnF1ZXJ5ID09PSAnc3RyaW5nJ1xuICAgICAgPyBvcHRpb25zLnF1ZXJ5XG4gICAgICA6IHFzLnN0cmluZ2lmeShvcHRpb25zLnF1ZXJ5LCB7IHN0cmljdE51bGxIYW5kbGluZzogdHJ1ZSB9KSlcbiAgfVxuICBpZiAob3B0aW9ucy5ib2R5KSB7XG4gICAgcmVxLnNlbmQob3B0aW9ucy5ib2R5KVxuICB9XG4gIGlmIChvcHRpb25zLndpdGhDcmVkZW50aWFscykge1xuICAgIHJlcS53aXRoQ3JlZGVudGlhbHMoKVxuICB9XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICByZXEuZW5kKGNyZWF0ZVJlc3BvbnNlSGFuZGxlcih7XG4gICAgICBvcHRpb25zLFxuICAgICAgZGlzcGF0Y2gsXG4gICAgICByZWplY3QsXG4gICAgICByZXNvbHZlXG4gICAgfSkpXG4gIH0pXG59XG4iXX0=
--------------------------------------------------------------------------------
/dist/reducers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.api = undefined;
7 |
8 | var _reduxActions = require('redux-actions');
9 |
10 | var _immutable = require('immutable');
11 |
12 | var toImmutable = function toImmutable(v) {
13 | return (0, _immutable.fromJS)(v, function (key, value) {
14 | return _immutable.Iterable.isIndexed(value) ? value.toList() : value.toOrderedMap();
15 | });
16 | };
17 |
18 | var initialState = (0, _immutable.OrderedMap)({
19 | subsets: (0, _immutable.OrderedMap)()
20 | });
21 |
22 | // subset state
23 | var createSubset = function createSubset(state, _ref) {
24 | var _ref$payload = _ref.payload,
25 | subset = _ref$payload.subset,
26 | fresh = _ref$payload.fresh;
27 |
28 | if (!subset) return state;
29 | var path = ['subsets', subset];
30 | if (!fresh && state.hasIn(path)) return state;
31 | var record = (0, _immutable.OrderedMap)({
32 | id: subset,
33 | pending: true
34 | });
35 | return state.setIn(path, record);
36 | };
37 |
38 | var setSubsetData = function setSubsetData(state, _ref2) {
39 | var subset = _ref2.meta.subset,
40 | _ref2$payload = _ref2.payload,
41 | raw = _ref2$payload.raw,
42 | text = _ref2$payload.text;
43 |
44 | if (!subset) return state;
45 | var path = ['subsets', subset];
46 | if (!state.hasIn(path)) return state; // subset doesnt exist
47 | return state.updateIn(path, function (subset) {
48 | return subset.set('data', toImmutable(raw)).set('text', text).set('pending', false).set('error', null);
49 | });
50 | };
51 |
52 | var setSubsetError = function setSubsetError(state, _ref3) {
53 | var subset = _ref3.meta.subset,
54 | payload = _ref3.payload;
55 |
56 | if (!subset) return state;
57 | var path = ['subsets', subset];
58 | if (!state.hasIn(path)) return state; // subset doesnt exist
59 | return state.updateIn(path, function (subset) {
60 | return subset.delete('data').delete('text').set('error', payload).set('pending', false);
61 | });
62 | };
63 |
64 | var setSubsetOpen = function setSubsetOpen(state, _ref4) {
65 | var _ref4$meta = _ref4.meta,
66 | subset = _ref4$meta.subset,
67 | collection = _ref4$meta.collection;
68 |
69 | if (!subset) return state;
70 | var path = ['subsets', subset];
71 | if (!state.hasIn(path)) return state; // subset doesnt exist
72 | return state.updateIn(path, function (subset) {
73 | return subset.set('pending', false).set('data', collection ? (0, _immutable.List)() : (0, _immutable.OrderedMap)());
74 | });
75 | };
76 |
77 | var insertSubsetDataItem = function insertSubsetDataItem(state, _ref5) {
78 | var _ref5$meta = _ref5.meta,
79 | subset = _ref5$meta.subset,
80 | collection = _ref5$meta.collection,
81 | raw = _ref5.payload.raw;
82 |
83 | if (!subset) return state;
84 | var path = ['subsets', subset];
85 | if (!state.hasIn(path)) return state; // subset doesnt exist
86 | var newData = toImmutable(raw);
87 | return state.updateIn(path, function (subset) {
88 | return subset.set('pending', false).update('data', function (data) {
89 | // first event, initialize the value
90 | if (data == null && collection) return (0, _immutable.List)([newData]);
91 | // value exists, either push or replace
92 | return collection ? data.push(newData) : newData;
93 | });
94 | });
95 | };
96 |
97 | var updateSubsetDataItem = function updateSubsetDataItem(state, _ref6) {
98 | var _ref6$meta = _ref6.meta,
99 | subset = _ref6$meta.subset,
100 | collection = _ref6$meta.collection,
101 | raw = _ref6.payload.raw;
102 |
103 | if (!subset) return state;
104 | var path = ['subsets', subset];
105 | if (!state.hasIn(path)) return state; // subset doesnt exist
106 | var dataPath = [].concat(path, ['data']);
107 | if (!state.hasIn(dataPath)) return state; // subset has no data to update
108 | var next = toImmutable(raw.next);
109 | return state.updateIn(dataPath, function (data) {
110 | // not a list item, replace with new value
111 | if (!collection) return next;
112 |
113 | // list item, find the index and do the update
114 | var idx = data.findIndex(function (i) {
115 | return i.get('id') === raw.prev.id;
116 | });
117 | if (idx == null) return data; // not our data?
118 | return data.set(idx, next);
119 | });
120 | };
121 | var deleteSubsetDataItem = function deleteSubsetDataItem(state, _ref7) {
122 | var _ref7$meta = _ref7.meta,
123 | subset = _ref7$meta.subset,
124 | collection = _ref7$meta.collection,
125 | raw = _ref7.payload.raw;
126 |
127 | if (!subset) return state;
128 | var path = ['subsets', subset];
129 | if (!state.hasIn(path)) return state; // subset doesnt exist
130 | var dataPath = [].concat(path, ['data']);
131 | if (!state.hasIn(dataPath)) return state; // subset has no data to update
132 |
133 | // not a list, just wipe the val
134 | if (!collection) {
135 | return state.removeIn(dataPath);
136 | }
137 | // item in a list, remove the specific item
138 | return state.updateIn(dataPath, function (data) {
139 | var idx = data.findIndex(function (i) {
140 | return i.get('id') === raw.id;
141 | });
142 | if (idx == null) return data; // not our data?
143 | return data.delete(idx);
144 | });
145 | };
146 |
147 | // exported actions
148 | var api = exports.api = (0, _reduxActions.handleActions)({
149 | 'tahoe.request': createSubset,
150 | 'tahoe.failure': setSubsetError,
151 | 'tahoe.success': setSubsetData,
152 | 'tahoe.tail.open': setSubsetOpen,
153 | 'tahoe.tail.insert': insertSubsetDataItem,
154 | 'tahoe.tail.update': updateSubsetDataItem,
155 | 'tahoe.tail.delete': deleteSubsetDataItem
156 | }, initialState);
157 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9yZWR1Y2Vycy5qcyJdLCJuYW1lcyI6WyJ0b0ltbXV0YWJsZSIsInYiLCJrZXkiLCJ2YWx1ZSIsIkl0ZXJhYmxlIiwiaXNJbmRleGVkIiwidG9MaXN0IiwidG9PcmRlcmVkTWFwIiwiaW5pdGlhbFN0YXRlIiwic3Vic2V0cyIsImNyZWF0ZVN1YnNldCIsInN0YXRlIiwicGF5bG9hZCIsInN1YnNldCIsImZyZXNoIiwicGF0aCIsImhhc0luIiwicmVjb3JkIiwiaWQiLCJwZW5kaW5nIiwic2V0SW4iLCJzZXRTdWJzZXREYXRhIiwibWV0YSIsInJhdyIsInRleHQiLCJ1cGRhdGVJbiIsInNldCIsInNldFN1YnNldEVycm9yIiwiZGVsZXRlIiwic2V0U3Vic2V0T3BlbiIsImNvbGxlY3Rpb24iLCJpbnNlcnRTdWJzZXREYXRhSXRlbSIsIm5ld0RhdGEiLCJ1cGRhdGUiLCJkYXRhIiwicHVzaCIsInVwZGF0ZVN1YnNldERhdGFJdGVtIiwiZGF0YVBhdGgiLCJuZXh0IiwiaWR4IiwiZmluZEluZGV4IiwiaSIsImdldCIsInByZXYiLCJkZWxldGVTdWJzZXREYXRhSXRlbSIsInJlbW92ZUluIiwiYXBpIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBRUEsSUFBTUEsY0FBYyxTQUFkQSxXQUFjLENBQUNDLENBQUQ7QUFBQSxTQUNsQix1QkFBT0EsQ0FBUCxFQUFVLFVBQUNDLEdBQUQsRUFBTUMsS0FBTjtBQUFBLFdBQ1JDLG9CQUFTQyxTQUFULENBQW1CRixLQUFuQixJQUE0QkEsTUFBTUcsTUFBTixFQUE1QixHQUE2Q0gsTUFBTUksWUFBTixFQURyQztBQUFBLEdBQVYsQ0FEa0I7QUFBQSxDQUFwQjs7QUFLQSxJQUFNQyxlQUFlLDJCQUFXO0FBQzlCQyxXQUFTO0FBRHFCLENBQVgsQ0FBckI7O0FBSUE7QUFDQSxJQUFNQyxlQUFlLFNBQWZBLFlBQWUsQ0FBQ0MsS0FBRCxRQUEyQztBQUFBLDBCQUFqQ0MsT0FBaUM7QUFBQSxNQUF0QkMs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LFNBQUYsRUFBYUYsTUFBYixDQUFiO0FBQ0EsTUFBSSxDQUFDRixNQUFNSyxLQUFOLENBQVlELElBQVosQ0FBTCxFQUF3QixPQUFPSixLQUFQLENBSGtFLENBR3JEO0FBQ3JDLE1BQU0wQixxQkFBZ0J0QixJQUFoQixHQUFzQixNQUF0QixFQUFOO0FBQ0EsTUFBSSxDQUFDSixNQUFNSyxLQUFOLENBQVlxQixRQUFaLENBQUwsRUFBNEIsT0FBTzFCLEtBQVAsQ0FMOEQsQ0FLakQ7O0FBRXpDO0FBQ0EsTUFBSSxDQUFDbUIsVUFBTCxFQUFpQjtBQUNmLFdBQU9uQixNQUFNa0MsUUFBTixDQUFlUixRQUFmLENBQVA7QUFDRDtBQUNEO0FBQ0EsU0FBTzFCLE1BQU1jLFFBQU4sQ0FBZVksUUFBZixFQUF5QixVQUFDSCxJQUFELEVBQVU7QUFDeEMsUUFBTUssTUFBTUwsS0FBS00sU0FBTCxDQUFlLFVBQUNDLENBQUQ7QUFBQSxhQUFPQSxFQUFFQyxHQUFGLENBQU0sSUFBTixNQUFnQm5CLElBQUlMLEVBQTNCO0FBQUEsS0FBZixDQUFaO0FBQ0EsUUFBSXFCLE9BQU8sSUFBWCxFQUFpQixPQUFPTCxJQUFQLENBRnVCLENBRVg7QUFDN0IsV0FBT0EsS0FBS04sTUFBTCxDQUFZVyxHQUFaLENBQVA7QUFDRCxHQUpNLENBQVA7QUFLRCxDQWpCRDs7QUFtQkE7QUFDTyxJQUFNTyxvQkFBTSxpQ0FBYztBQUMvQixtQkFBaUJwQyxZQURjO0FBRS9CLG1CQUFpQmlCLGNBRmM7QUFHL0IsbUJBQWlCTixhQUhjO0FBSS9CLHFCQUFtQlEsYUFKWTtBQUsvQix1QkFBcUJFLG9CQUxVO0FBTS9CLHVCQUFxQkssb0JBTlU7QUFPL0IsdUJBQXFCUTtBQVBVLENBQWQsRUFRaEJwQyxZQVJnQixDQUFaIiwiZmlsZSI6InJlZHVjZXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgaGFuZGxlQWN0aW9ucyB9IGZyb20gJ3JlZHV4LWFjdGlvbnMnXG5pbXBvcnQgeyBPcmRlcmVkTWFwLCBMaXN0LCBmcm9tSlMsIEl0ZXJhYmxlIH0gZnJvbSAnaW1tdXRhYmxlJ1xuXG5jb25zdCB0b0ltbXV0YWJsZSA9ICh2KSA9PlxuICBmcm9tSlModiwgKGtleSwgdmFsdWUpID0+XG4gICAgSXRlcmFibGUuaXNJbmRleGVkKHZhbHVlKSA/IHZhbHVlLnRvTGlzdCgpIDogdmFsdWUudG9PcmRlcmVkTWFwKClcbiAgKVxuXG5jb25zdCBpbml0aWFsU3RhdGUgPSBPcmRlcmVkTWFwKHtcbiAgc3Vic2V0czogT3JkZXJlZE1hcCgpXG59KVxuXG4vLyBzdWJzZXQgc3RhdGVcbmNvbnN0IGNyZWF0ZVN1YnNldCA9IChzdGF0ZSwgeyBwYXlsb2FkOiB7IHN1YnNldCwgZnJlc2ggfSB9KSA9PiB7XG4gIGlmICghc3Vic2V0KSByZXR1cm4gc3RhdGVcbiAgY29uc3QgcGF0aCA9IFsgJ3N1YnNldHMnLCBzdWJzZXQgXVxuICBpZiAoIWZyZXNoICYmIHN0YXRlLmhhc0luKHBhdGgpKSByZXR1cm4gc3RhdGVcbiAgY29uc3QgcmVjb3JkID0gT3JkZXJlZE1hcCh7XG4gICAgaWQ6IHN1YnNldCxcbiAgICBwZW5kaW5nOiB0cnVlXG4gIH0pXG4gIHJldHVybiBzdGF0ZS5zZXRJbihwYXRoLCByZWNvcmQpXG59XG5cbmNvbnN0IHNldFN1YnNldERhdGEgPSAoc3RhdGUsIHsgbWV0YTogeyBzdWJzZXQgfSwgcGF5bG9hZDogeyByYXcsIHRleHQgfSB9KSA9PiB7XG4gIGlmICghc3Vic2V0KSByZXR1cm4gc3RhdGVcbiAgY29uc3QgcGF0aCA9IFsgJ3N1YnNldHMnLCBzdWJzZXQgXVxuICBpZiAoIXN0YXRlLmhhc0luKHBhdGgpKSByZXR1cm4gc3RhdGUgLy8gc3Vic2V0IGRvZXNudCBleGlzdFxuICByZXR1cm4gc3RhdGUudXBkYXRlSW4ocGF0aCwgKHN1YnNldCkgPT5cbiAgICBzdWJzZXRcbiAgICAgIC5zZXQoJ2RhdGEnLCB0b0ltbXV0YWJsZShyYXcpKVxuICAgICAgLnNldCgndGV4dCcsIHRleHQpXG4gICAgICAuc2V0KCdwZW5kaW5nJywgZmFsc2UpXG4gICAgICAuc2V0KCdlcnJvcicsIG51bGwpXG4gIClcbn1cblxuY29uc3Qgc2V0U3Vic2V0RXJyb3IgPSAoc3RhdGUsIHsgbWV0YTogeyBzdWJzZXQgfSwgcGF5bG9hZCB9KSA9PiB7XG4gIGlmICghc3Vic2V0KSByZXR1cm4gc3RhdGVcbiAgY29uc3QgcGF0aCA9IFsgJ3N1YnNldHMnLCBzdWJzZXQgXVxuICBpZiAoIXN0YXRlLmhhc0luKHBhdGgpKSByZXR1cm4gc3RhdGUgLy8gc3Vic2V0IGRvZXNudCBleGlzdFxuICByZXR1cm4gc3RhdGUudXBkYXRlSW4ocGF0aCwgKHN1YnNldCkgPT5cbiAgICBzdWJzZXRcbiAgICAgIC5kZWxldGUoJ2RhdGEnKVxuICAgICAgLmRlbGV0ZSgndGV4dCcpXG4gICAgICAuc2V0KCdlcnJvcicsIHBheWxvYWQpXG4gICAgICAuc2V0KCdwZW5kaW5nJywgZmFsc2UpXG4gIClcbn1cblxuY29uc3Qgc2V0U3Vic2V0T3BlbiA9IChzdGF0ZSwgeyBtZXRhOiB7IHN1YnNldCwgY29sbGVjdGlvbiB9IH0pID0+IHtcbiAgaWYgKCFzdWJzZXQpIHJldHVybiBzdGF0ZVxuICBjb25zdCBwYXRoID0gWyAnc3Vic2V0cycsIHN1YnNldCBdXG4gIGlmICghc3RhdGUuaGFzSW4ocGF0aCkpIHJldHVybiBzdGF0ZSAvLyBzdWJzZXQgZG9lc250IGV4aXN0XG4gIHJldHVybiBzdGF0ZS51cGRhdGVJbihwYXRoLCAoc3Vic2V0KSA9PlxuICAgIHN1YnNldFxuICAgICAgLnNldCgncGVuZGluZycsIGZhbHNlKVxuICAgICAgLnNldCgnZGF0YScsIGNvbGxlY3Rpb24gPyBMaXN0KCkgOiBPcmRlcmVkTWFwKCkpXG4gIClcbn1cblxuY29uc3QgaW5zZXJ0U3Vic2V0RGF0YUl0ZW0gPSAoc3RhdGUsIHsgbWV0YTogeyBzdWJzZXQsIGNvbGxlY3Rpb24gfSwgcGF5bG9hZDogeyByYXcgfSB9KSA9PiB7XG4gIGlmICghc3Vic2V0KSByZXR1cm4gc3RhdGVcbiAgY29uc3QgcGF0aCA9IFsgJ3N1YnNldHMnLCBzdWJzZXQgXVxuICBpZiAoIXN0YXRlLmhhc0luKHBhdGgpKSByZXR1cm4gc3RhdGUgLy8gc3Vic2V0IGRvZXNudCBleGlzdFxuICBjb25zdCBuZXdEYXRhID0gdG9JbW11dGFibGUocmF3KVxuICByZXR1cm4gc3RhdGUudXBkYXRlSW4ocGF0aCwgKHN1YnNldCkgPT5cbiAgICBzdWJzZXRcbiAgICAgIC5zZXQoJ3BlbmRpbmcnLCBmYWxzZSlcbiAgICAgIC51cGRhdGUoJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgICAgICAvLyBmaXJzdCBldmVudCwgaW5pdGlhbGl6ZSB0aGUgdmFsdWVcbiAgICAgICAgaWYgKGRhdGEgPT0gbnVsbCAmJiBjb2xsZWN0aW9uKSByZXR1cm4gTGlzdChbIG5ld0RhdGEgXSlcbiAgICAgICAgLy8gdmFsdWUgZXhpc3RzLCBlaXRoZXIgcHVzaCBvciByZXBsYWNlXG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uID8gZGF0YS5wdXNoKG5ld0RhdGEpIDogbmV3RGF0YVxuICAgICAgfSlcbiAgKVxufVxuXG5jb25zdCB1cGRhdGVTdWJzZXREYXRhSXRlbSA9IChzdGF0ZSwgeyBtZXRhOiB7IHN1YnNldCwgY29sbGVjdGlvbiB9LCBwYXlsb2FkOiB7IHJhdyB9IH0pID0+IHtcbiAgaWYgKCFzdWJzZXQpIHJldHVybiBzdGF0ZVxuICBjb25zdCBwYXRoID0gWyAnc3Vic2V0cycsIHN1YnNldCBdXG4gIGlmICghc3RhdGUuaGFzSW4ocGF0aCkpIHJldHVybiBzdGF0ZSAvLyBzdWJzZXQgZG9lc250IGV4aXN0XG4gIGNvbnN0IGRhdGFQYXRoID0gWyAuLi5wYXRoLCAnZGF0YScgXVxuICBpZiAoIXN0YXRlLmhhc0luKGRhdGFQYXRoKSkgcmV0dXJuIHN0YXRlIC8vIHN1YnNldCBoYXMgbm8gZGF0YSB0byB1cGRhdGVcbiAgY29uc3QgbmV4dCA9IHRvSW1tdXRhYmxlKHJhdy5uZXh0KVxuICByZXR1cm4gc3RhdGUudXBkYXRlSW4oZGF0YVBhdGgsIChkYXRhKSA9PiB7XG4gICAgLy8gbm90IGEgbGlzdCBpdGVtLCByZXBsYWNlIHdpdGggbmV3IHZhbHVlXG4gICAgaWYgKCFjb2xsZWN0aW9uKSByZXR1cm4gbmV4dFxuXG4gICAgLy8gbGlzdCBpdGVtLCBmaW5kIHRoZSBpbmRleCBhbmQgZG8gdGhlIHVwZGF0ZVxuICAgIGNvbnN0IGlkeCA9IGRhdGEuZmluZEluZGV4KChpKSA9PiBpLmdldCgnaWQnKSA9PT0gcmF3LnByZXYuaWQpXG4gICAgaWYgKGlkeCA9PSBudWxsKSByZXR1cm4gZGF0YSAvLyBub3Qgb3VyIGRhdGE/XG4gICAgcmV0dXJuIGRhdGEuc2V0KGlkeCwgbmV4dClcbiAgfSlcbn1cbmNvbnN0IGRlbGV0ZVN1YnNldERhdGFJdGVtID0gKHN0YXRlLCB7IG1ldGE6IHsgc3Vic2V0LCBjb2xsZWN0aW9uIH0sIHBheWxvYWQ6IHsgcmF3IH0gfSkgPT4ge1xuICBpZiAoIXN1YnNldCkgcmV0dXJuIHN0YXRlXG4gIGNvbnN0IHBhdGggPSBbICdzdWJzZXRzJywgc3Vic2V0IF1cbiAgaWYgKCFzdGF0ZS5oYXNJbihwYXRoKSkgcmV0dXJuIHN0YXRlIC8vIHN1YnNldCBkb2VzbnQgZXhpc3RcbiAgY29uc3QgZGF0YVBhdGggPSBbIC4uLnBhdGgsICdkYXRhJyBdXG4gIGlmICghc3RhdGUuaGFzSW4oZGF0YVBhdGgpKSByZXR1cm4gc3RhdGUgLy8gc3Vic2V0IGhhcyBubyBkYXRhIHRvIHVwZGF0ZVxuXG4gIC8vIG5vdCBhIGxpc3QsIGp1c3Qgd2lwZSB0aGUgdmFsXG4gIGlmICghY29sbGVjdGlvbikge1xuICAgIHJldHVybiBzdGF0ZS5yZW1vdmVJbihkYXRhUGF0aClcbiAgfVxuICAvLyBpdGVtIGluIGEgbGlzdCwgcmVtb3ZlIHRoZSBzcGVjaWZpYyBpdGVtXG4gIHJldHVybiBzdGF0ZS51cGRhdGVJbihkYXRhUGF0aCwgKGRhdGEpID0+IHtcbiAgICBjb25zdCBpZHggPSBkYXRhLmZpbmRJbmRleCgoaSkgPT4gaS5nZXQoJ2lkJykgPT09IHJhdy5pZClcbiAgICBpZiAoaWR4ID09IG51bGwpIHJldHVybiBkYXRhIC8vIG5vdCBvdXIgZGF0YT9cbiAgICByZXR1cm4gZGF0YS5kZWxldGUoaWR4KVxuICB9KVxufVxuXG4vLyBleHBvcnRlZCBhY3Rpb25zXG5leHBvcnQgY29uc3QgYXBpID0gaGFuZGxlQWN0aW9ucyh7XG4gICd0YWhvZS5yZXF1ZXN0JzogY3JlYXRlU3Vic2V0LFxuICAndGFob2UuZmFpbHVyZSc6IHNldFN1YnNldEVycm9yLFxuICAndGFob2Uuc3VjY2Vzcyc6IHNldFN1YnNldERhdGEsXG4gICd0YWhvZS50YWlsLm9wZW4nOiBzZXRTdWJzZXRPcGVuLFxuICAndGFob2UudGFpbC5pbnNlcnQnOiBpbnNlcnRTdWJzZXREYXRhSXRlbSxcbiAgJ3RhaG9lLnRhaWwudXBkYXRlJzogdXBkYXRlU3Vic2V0RGF0YUl0ZW0sXG4gICd0YWhvZS50YWlsLmRlbGV0ZSc6IGRlbGV0ZVN1YnNldERhdGFJdGVtXG59LCBpbml0aWFsU3RhdGUpXG4iXX0=
--------------------------------------------------------------------------------
/docs/Introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | Test page
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tahoe",
3 | "version": "1.1.1",
4 | "description": "Dead-simple API/EventSource actions for Redux",
5 | "main": "dist/index.js",
6 | "keywords": [
7 | "redux",
8 | "react",
9 | "immutable",
10 | "api",
11 | "rest",
12 | "http",
13 | "request",
14 | "resource",
15 | "actions",
16 | "shasta",
17 | "shastajs",
18 | "shastaplugin"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/shastajs/tahoe.git"
23 | },
24 | "author": "Contra (http://contra.io)",
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/shastajs/tahoe/issues"
28 | },
29 | "homepage": "https://github.com/shastajs/tahoe#readme",
30 | "files": [
31 | "dist"
32 | ],
33 | "scripts": {
34 | "preversion": "npm run clean && npm run build",
35 | "build": "babel src --out-dir dist",
36 | "clean": "rimraf dist",
37 | "lint": "eslint src",
38 | "test": "npm run-script lint && npm run test:node && npm run test:browser",
39 | "test:node": "mocha --compilers js:babel-register --recursive --reporter spec",
40 | "test:browser": "mochify --transform babelify --recursive --reporter spec"
41 | },
42 | "devDependencies": {
43 | "babel-cli": "^6.26.0",
44 | "babel-core": "^6.26.0",
45 | "babel-eslint": "^8.2.5",
46 | "babel-loader": "^7.1.3",
47 | "babel-plugin-add-module-exports": "^0.2.1",
48 | "babel-plugin-transform-runtime": "^6.4.3",
49 | "babel-preset-es2015": "^6.3.13",
50 | "babel-preset-es2015-loose": "^8.0.0",
51 | "babel-preset-react": "^6.3.13",
52 | "babel-preset-stage-0": "^6.3.13",
53 | "babel-register": "^6.26.0",
54 | "babelify": "^8.0.0",
55 | "eslint": "^4.18.1",
56 | "eslint-cli": "^1.1.1",
57 | "eslint-config-rackt": "^1.1.1",
58 | "eslint-plugin-react": "^7.10.0",
59 | "mocha": "^5.0.0",
60 | "mochify": "^5.0.0",
61 | "rimraf": "^2.6.2",
62 | "should": "^13.2.1"
63 | },
64 | "babel": {
65 | "sourceMaps": "inline",
66 | "presets": [
67 | "es2015",
68 | "react",
69 | "stage-0"
70 | ],
71 | "plugins": [
72 | "transform-runtime",
73 | "add-module-exports"
74 | ]
75 | },
76 | "eslintConfig": {
77 | "parser": "babel-eslint",
78 | "extends": "rackt",
79 | "plugins": [
80 | "react"
81 | ],
82 | "env": {
83 | "browser": true,
84 | "node": true,
85 | "es6": true
86 | },
87 | "globals": {
88 | "__DEV__": true,
89 | "__PROD__": true,
90 | "__INITIAL_STATE__": true
91 | },
92 | "rules": {
93 | "semi": [
94 | 2,
95 | "never"
96 | ]
97 | }
98 | },
99 | "dependencies": {
100 | "babel-runtime": "^6.26.0",
101 | "immutable": "^3.8.2",
102 | "lodash.mapvalues": "^4.6.0",
103 | "lodash.merge": "^4.6.1",
104 | "qs": "^6.5.1",
105 | "redux-actions": "^2.2.1",
106 | "superagent": "^3.8.2",
107 | "url": "^0.11.0",
108 | "url-join": "^4.0.0"
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import createAction from './lib/createAction'
2 | import * as reducers from './reducers'
3 |
4 | export default {
5 | createAction,
6 | reducers: reducers
7 | }
8 |
--------------------------------------------------------------------------------
/src/lib/combineUrl.js:
--------------------------------------------------------------------------------
1 | import url from 'url'
2 | import qs from 'qs'
3 |
4 | export default (endpoint, query) => {
5 | const parsed = url.parse(endpoint)
6 |
7 | const q = qs.stringify({
8 | ...qs.parse(parsed.query, { strictNullHandling: true }),
9 | ...query
10 | }, { strictNullHandling: true })
11 |
12 | return url.format({
13 | protocol: parsed.protocol,
14 | auth: parsed.auth,
15 | port: parsed.port,
16 | host: parsed.host,
17 | pathname: parsed.pathname,
18 | search: q
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/src/lib/createAction.js:
--------------------------------------------------------------------------------
1 | import mapValues from 'lodash.mapvalues'
2 | import merge from 'lodash.merge'
3 | import sendRequest from './sendRequest'
4 |
5 | const reserved = [
6 | 'onResponse',
7 | 'onError',
8 | 'onGlobalError'
9 | ]
10 | const result = (fn, arg) => typeof fn === 'function' ? fn(arg) : fn
11 |
12 | // TODO:0 check entities cache in store and dont fetch if we have it already
13 |
14 | /*
15 | app must have redux-thunk installed
16 | possible options:
17 |
18 | - subset (optional)(string)
19 | - tail (default false)(boolean)
20 | - method (required)(get, post, put, delete, or patch)
21 | - params (object)
22 | - endpoint (required)(url tring)
23 | - collection (default false)(boolean)
24 | - fresh (default to false)(boolean)
25 |
26 | all options can either be a value, or a function that returns a value.
27 | if you define a function, it will receive options.params as an argument
28 | */
29 |
30 | // merge our multitude of option objects together
31 | // defaults = options defined in createAction
32 | // opt = options specified in action creator
33 | const isReserved = (k) => reserved.indexOf(k) !== -1
34 |
35 | const resolveFunctions = (o, params) =>
36 | mapValues(o, (v, k) =>
37 | isReserved(k) ? v : result(v, params)
38 | )
39 |
40 | export const mergeOptions = (defaults, opt) => {
41 | const defaultParams = defaults.params ? result(defaults.params) : {}
42 | const optParams = opt.params ? result(opt.params) : {}
43 | const params = merge({}, optParams, defaultParams)
44 | return merge({}, resolveFunctions(opt, params), resolveFunctions(defaults, params))
45 | }
46 |
47 | export default (defaults = {}) => {
48 | const nfn = (opt = {}) => {
49 | const options = mergeOptions(defaults, opt)
50 | if (!options.method) throw new Error('Missing method')
51 | if (!options.endpoint) throw new Error('Missing endpoint')
52 | const fn = async (dispatch) => sendRequest({ options, dispatch })
53 | fn.options = options
54 | return fn
55 | }
56 | nfn.options = defaults
57 | return nfn
58 | }
59 |
--------------------------------------------------------------------------------
/src/lib/createEventSource.js:
--------------------------------------------------------------------------------
1 | import combineUrl from './combineUrl'
2 | import handlers from './eventHandlers'
3 |
4 | const tryParse = ({ data, options, dispatch }) => {
5 | try {
6 | return JSON.parse(data)
7 | } catch (err) {
8 | dispatch({
9 | type: 'tahoe.failure',
10 | meta: options,
11 | payload: err
12 | })
13 | }
14 | }
15 |
16 | export default async ({ options, dispatch }) => {
17 | const finalUrl = combineUrl(options.endpoint, options.query)
18 | const src = new EventSource(finalUrl, { withCredentials: options.withCredentials })
19 |
20 | // wire up listeners n shiz
21 | Object.keys(handlers).forEach((eventName) => {
22 | const handler = handlers[eventName]
23 | src.addEventListener(eventName, ({ data }) => {
24 | const parsed = data && tryParse({ options, dispatch, data })
25 | if (data && typeof parsed === 'undefined') return
26 | handler({ options, dispatch, data: parsed })
27 | }, false)
28 | })
29 | }
30 |
--------------------------------------------------------------------------------
/src/lib/eventHandlers.js:
--------------------------------------------------------------------------------
1 |
2 | const handlers = {}
3 | handlers.open = ({ options, dispatch }) =>
4 | dispatch({
5 | type: 'tahoe.tail.open',
6 | meta: options
7 | })
8 |
9 | handlers.insert = ({ options, dispatch, data: { next } }) =>
10 | dispatch({
11 | type: 'tahoe.tail.insert',
12 | meta: options,
13 | payload: {
14 | raw: next
15 | }
16 | })
17 |
18 | handlers.update = ({ options, dispatch, data: { prev, next } }) =>
19 | dispatch({
20 | type: 'tahoe.tail.update',
21 | meta: options,
22 | payload: {
23 | raw: {
24 | prev: prev,
25 | next: next
26 | }
27 | }
28 | })
29 |
30 |
31 | handlers.delete = ({ options, dispatch, data: { prev } }) =>
32 | dispatch({
33 | type: 'tahoe.tail.delete',
34 | meta: options,
35 | payload: {
36 | raw: prev
37 | }
38 | })
39 |
40 | export default handlers
41 |
--------------------------------------------------------------------------------
/src/lib/sendRequest.js:
--------------------------------------------------------------------------------
1 | import request from 'superagent'
2 | import createEventSource from './createEventSource'
3 | import qs from 'qs'
4 |
5 | const createResponseHandler = ({ options, dispatch, reject, resolve }) => {
6 | const debug = `${options.method.toUpperCase()} ${options.endpoint}`
7 | return (err, res) => {
8 | if (!res && !err) {
9 | err = new Error(`Connection failed: ${debug}`)
10 | }
11 | if (err) {
12 | err.res = res
13 | dispatch({
14 | type: 'tahoe.failure',
15 | meta: options,
16 | payload: err
17 | })
18 | if (options.onGlobalError) options.onGlobalError(err, res)
19 | if (options.onError) options.onError(err, res)
20 | return reject(err)
21 | }
22 |
23 | // handle json responses
24 | dispatch({
25 | type: 'tahoe.success',
26 | meta: options,
27 | payload: {
28 | raw: res.body,
29 | text: res.text
30 | }
31 | })
32 | if (options.onResponse) options.onResponse(res)
33 | resolve(res)
34 | }
35 | }
36 |
37 | export default async ({ options, dispatch }) => {
38 | dispatch({
39 | type: 'tahoe.request',
40 | payload: options
41 | })
42 |
43 | if (options.tail) {
44 | return createEventSource({ options, dispatch })
45 | }
46 |
47 | const req = request[options.method.toLowerCase()](options.endpoint)
48 | if (options.headers) {
49 | req.set(options.headers)
50 | }
51 | if (options.query) {
52 | req.query(typeof options.query === 'string'
53 | ? options.query
54 | : qs.stringify(options.query, { strictNullHandling: true }))
55 | }
56 | if (options.body) {
57 | req.send(options.body)
58 | }
59 | if (options.withCredentials) {
60 | req.withCredentials()
61 | }
62 |
63 | return new Promise((resolve, reject) => {
64 | req.end(createResponseHandler({
65 | options,
66 | dispatch,
67 | reject,
68 | resolve
69 | }))
70 | })
71 | }
72 |
--------------------------------------------------------------------------------
/src/reducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import { OrderedMap, List, fromJS, Iterable } from 'immutable'
3 |
4 | const toImmutable = (v) =>
5 | fromJS(v, (key, value) =>
6 | Iterable.isIndexed(value) ? value.toList() : value.toOrderedMap()
7 | )
8 |
9 | const initialState = OrderedMap({
10 | subsets: OrderedMap()
11 | })
12 |
13 | // subset state
14 | const createSubset = (state, { payload: { subset, fresh } }) => {
15 | if (!subset) return state
16 | const path = [ 'subsets', subset ]
17 | if (!fresh && state.hasIn(path)) return state
18 | const record = OrderedMap({
19 | id: subset,
20 | pending: true
21 | })
22 | return state.setIn(path, record)
23 | }
24 |
25 | const setSubsetData = (state, { meta: { subset }, payload: { raw, text } }) => {
26 | if (!subset) return state
27 | const path = [ 'subsets', subset ]
28 | if (!state.hasIn(path)) return state // subset doesnt exist
29 | return state.updateIn(path, (subset) =>
30 | subset
31 | .set('data', toImmutable(raw))
32 | .set('text', text)
33 | .set('pending', false)
34 | .set('error', null)
35 | )
36 | }
37 |
38 | const setSubsetError = (state, { meta: { subset }, payload }) => {
39 | if (!subset) return state
40 | const path = [ 'subsets', subset ]
41 | if (!state.hasIn(path)) return state // subset doesnt exist
42 | return state.updateIn(path, (subset) =>
43 | subset
44 | .delete('data')
45 | .delete('text')
46 | .set('error', payload)
47 | .set('pending', false)
48 | )
49 | }
50 |
51 | const setSubsetOpen = (state, { meta: { subset, collection } }) => {
52 | if (!subset) return state
53 | const path = [ 'subsets', subset ]
54 | if (!state.hasIn(path)) return state // subset doesnt exist
55 | return state.updateIn(path, (subset) =>
56 | subset
57 | .set('pending', false)
58 | .set('data', collection ? List() : OrderedMap())
59 | )
60 | }
61 |
62 | const insertSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
63 | if (!subset) return state
64 | const path = [ 'subsets', subset ]
65 | if (!state.hasIn(path)) return state // subset doesnt exist
66 | const newData = toImmutable(raw)
67 | return state.updateIn(path, (subset) =>
68 | subset
69 | .set('pending', false)
70 | .update('data', (data) => {
71 | // first event, initialize the value
72 | if (data == null && collection) return List([ newData ])
73 | // value exists, either push or replace
74 | return collection ? data.push(newData) : newData
75 | })
76 | )
77 | }
78 |
79 | const updateSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
80 | if (!subset) return state
81 | const path = [ 'subsets', subset ]
82 | if (!state.hasIn(path)) return state // subset doesnt exist
83 | const dataPath = [ ...path, 'data' ]
84 | if (!state.hasIn(dataPath)) return state // subset has no data to update
85 | const next = toImmutable(raw.next)
86 | return state.updateIn(dataPath, (data) => {
87 | // not a list item, replace with new value
88 | if (!collection) return next
89 |
90 | // list item, find the index and do the update
91 | const idx = data.findIndex((i) => i.get('id') === raw.prev.id)
92 | if (idx == null) return data // not our data?
93 | return data.set(idx, next)
94 | })
95 | }
96 | const deleteSubsetDataItem = (state, { meta: { subset, collection }, payload: { raw } }) => {
97 | if (!subset) return state
98 | const path = [ 'subsets', subset ]
99 | if (!state.hasIn(path)) return state // subset doesnt exist
100 | const dataPath = [ ...path, 'data' ]
101 | if (!state.hasIn(dataPath)) return state // subset has no data to update
102 |
103 | // not a list, just wipe the val
104 | if (!collection) {
105 | return state.removeIn(dataPath)
106 | }
107 | // item in a list, remove the specific item
108 | return state.updateIn(dataPath, (data) => {
109 | const idx = data.findIndex((i) => i.get('id') === raw.id)
110 | if (idx == null) return data // not our data?
111 | return data.delete(idx)
112 | })
113 | }
114 |
115 | // exported actions
116 | export const api = handleActions({
117 | 'tahoe.request': createSubset,
118 | 'tahoe.failure': setSubsetError,
119 | 'tahoe.success': setSubsetData,
120 | 'tahoe.tail.open': setSubsetOpen,
121 | 'tahoe.tail.insert': insertSubsetDataItem,
122 | 'tahoe.tail.update': updateSubsetDataItem,
123 | 'tahoe.tail.delete': deleteSubsetDataItem
124 | }, initialState)
125 |
--------------------------------------------------------------------------------
/test/createAction.js:
--------------------------------------------------------------------------------
1 | /*global it: true, describe: true, beforeEach: true */
2 | /*eslint no-console: 0*/
3 |
4 | import { fromJS, Map } from 'immutable'
5 | import should from 'should'
6 | import { createAction } from '../src'
7 | import { mergeOptions } from '../src/lib/createAction'
8 |
9 | describe('createAction', () => {
10 | it('should exist', (done) => {
11 | should.exist(createAction)
12 | done()
13 | })
14 | describe('mergeOptions', () => {
15 | const opt = {
16 | tail: true,
17 | onResponse: () => 'response',
18 | onError: () => 'error',
19 | method: 'GET',
20 | params: {
21 | string: '/other'
22 | },
23 | query: { testing: 'abc' }
24 | }
25 |
26 | const defaults = {
27 | tail: false,
28 | collection: false,
29 | endpoint: (params) => `${params.string}/test`,
30 | query: () => ({ test: 123 })
31 | }
32 |
33 | it('should exist', (done) => {
34 | should.exist(mergeOptions)
35 | done()
36 | })
37 | it('should apply defaults and convert non reserved functions to values', (done) => {
38 | const result = mergeOptions(opt, defaults)
39 | const expected = fromJS(opt).withMutations((updated) => {
40 | updated.set('endpoint', '/other/test')
41 | updated.set('collection', false)
42 | updated.set('query', Map({
43 | test: 123,
44 | testing: 'abc'
45 | }))
46 | })
47 | should(result).be.deepEqual(expected.toJS())
48 | done()
49 | })
50 | })
51 | })
52 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | /*global it: true, describe: true */
2 | /*eslint no-console: 0*/
3 |
4 | import should from 'should'
5 | import lib from '../src'
6 |
7 | describe('lib', () => {
8 | it('should exist', (done) => {
9 | should.exist(lib)
10 | done()
11 | })
12 | })
13 |
--------------------------------------------------------------------------------