New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

react-diode

Package Overview
Dependencies
Maintainers
1
Versions
55
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-diode - npm Package Compare versions

Comparing version 0.2.0-beta.1 to 0.2.0-beta.3

lib/query/createBatchQueryRequest.js

52

lib/container/DiodeContainer.js
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

@@ -21,4 +19,2 @@

function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -38,47 +34,11 @@

function DiodeContainer() {
var _Object$getPrototypeO;
_classCallCheck(this, DiodeContainer);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
var _this = _possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(DiodeContainer)).call.apply(_Object$getPrototypeO, [this].concat(args)));
_this.query = spec.query;
return _this;
return _possibleConstructorReturn(this, Object.getPrototypeOf(DiodeContainer).apply(this, arguments));
}
_createClass(DiodeContainer, [{
key: '_parseDiodeResponse',
value: function _parseDiodeResponse(diodeResponse) {
var query = this.query;
return Object.keys(query.map).reduce(function (props, key) {
props[key] = diodeResponse[query.map[key].type];
return props;
}, {});
}
}, {
key: 'render',
value: function render() {
/* eslint no-use-before-define: 0 */
// see https://github.com/babel/babel-eslint/issues/249
var _props = this.props;
var __diodeResponse = _props.__diodeResponse;
var prop = _objectWithoutProperties(_props, ['__diodeResponse']);
// Child container doesn't need to parse diodeResponse again
// as parent already know what query types the children need,
// so __diodeResponse will not be passed to child container
var diodeProps = undefined;
if (__diodeResponse) {
diodeProps = this._parseDiodeResponse(__diodeResponse);
}
return _react2.default.createElement(Component, _extends({}, prop, diodeProps));
return _react2.default.createElement(Component, this.props);
}

@@ -91,6 +51,2 @@ }]);

DiodeContainer.displayName = containerName;
DiodeContainer.propTypes = {
__diodeResponse: _react2.default.PropTypes.object
};
return DiodeContainer;

@@ -102,5 +58,5 @@ }

var containerName = 'Diode(' + componentName + ')';
var query = spec.query = new _DiodeContainerQuery2.default(spec.queries, spec.children);
var query = new _DiodeContainerQuery2.default(spec.queries, spec.children);
var Container = undefined;
var Container = void 0;
function ContainerConstructor(props, context) {

@@ -107,0 +63,0 @@ if (!Container) {

@@ -19,2 +19,6 @@ 'use strict';

var _DiodeQueryTypes = require('./query/DiodeQueryTypes');
var _DiodeQueryTypes2 = _interopRequireDefault(_DiodeQueryTypes);
var _createDiodeQuery = require('./query/createDiodeQuery');

@@ -29,2 +33,3 @@

DefaultNetworkLayer: _DiodeDefaultNetworkLayer2.default,
QueryTypes: _DiodeQueryTypes2.default,

@@ -36,2 +41,3 @@ createContainer: _DiodeContainer2.default.create,

waitForQuery: _DiodeQueryRequest.createPendingQueryRequest,
useBatchQueries: _DiodeStore2.default.useBatchQueries.bind(_DiodeStore2.default),
injectNetworkLayer: _DiodeStore2.default.injectNetworkLayer.bind(_DiodeStore2.default)

@@ -38,0 +44,0 @@ };

@@ -38,17 +38,5 @@ 'use strict';

value: function sendQueries(queryRequests, options) {
var requests = this._sendRequests(queryRequests, options);
return Promise.all(requests).then(function (responses) {
return responses.reduce(function (result, response) {
result[response.type] = response.data;
return result;
}, {});
});
}
}, {
key: '_sendRequests',
value: function _sendRequests(queryRequests, options) {
var _this = this;
return queryRequests.map(function (query) {
var requests = queryRequests.map(function (query) {
/* istanbul ignore next */

@@ -69,2 +57,4 @@ var headers = options.headers ? options.headers : _this._defaultHeaders;

fetchParams.body = JSON.stringify(payload);
} else if (typeof payload === 'string') {
fetchParams.body = payload;
}

@@ -74,12 +64,6 @@

return response.json();
}).then(function (response) {
// modify response with query type so in the end we can convert
// this query response into Map<queryType, responseData>
// which is exactly what Diode wants
return {
type: query.type,
data: query.resolve(response, query.fragment, options)
};
});
});
return Promise.all(requests);
}

@@ -86,0 +70,0 @@ }]);

@@ -15,2 +15,3 @@ 'use strict';

/**

@@ -17,0 +18,0 @@ * @internal

@@ -51,2 +51,6 @@ 'use strict';

if (queries === null || queries === undefined) {
return;
}
Object.keys(queries).forEach(function (key) {

@@ -85,2 +89,6 @@ var query = queries[key];

if (childQueryMap === null || childQueryMap === undefined) {
return;
}
Object.keys(childQueryMap).forEach(function (key) {

@@ -112,10 +120,12 @@ var childQuery = childQueryMap[key];

// Create initial query map from parent container via query type map.
// For the most part, this is enough as we already compile the complete
// fragment and usually parent and child use same query key
this.map = Object.keys(queries).reduce(function (queryMap, key) {
var query = queries[key];
queryMap[key] = _this3._queryTypeMap[query.type];
return queryMap;
}, {});
if (queries) {
// Create initial query map from parent container via query type map.
// For the most part, this is enough as we already compile the complete
// fragment and usually parent and child use same query key
this.map = Object.keys(queries).reduce(function (queryMap, key) {
var query = queries[key];
queryMap[key] = _this3._queryTypeMap[query.type];
return queryMap;
}, {});
}

@@ -134,3 +144,4 @@ if (!children || !children.length) {

if (existingQuery && existingQuery.type !== childQuery.type) {
return console.warn('Found same query key (%s) with different type (%s and %s)', key, existingQuery.type, childQuery.type);
return console.warn( // eslint-disable-line no-console
'Found same query key (%s) with different type (%s and %s)', key, existingQuery.type, childQuery.type);
}

@@ -137,0 +148,0 @@

@@ -19,9 +19,10 @@ 'use strict';

*/
function createPendingQueryRequest(QueryDependencies, callback) {
if (!(QueryDependencies instanceof Array)) {
QueryDependencies = [QueryDependencies];
}
// TODO find a way to merge this type without writing twice
function createPendingQueryRequest(Query, callback) {
return {
pending: true,
dependency: Query,
dependencies: QueryDependencies,
callback: callback

@@ -37,2 +38,3 @@ };

return {
pending: false,
url: url,

@@ -65,6 +67,6 @@ method: method,

*/
function generateQueryRequest(QueryShape, queryRequestInfo) {
var type = QueryShape.type;
var fragment = QueryShape.fragment;
var resolve = QueryShape.resolve;
function generateQueryRequest(query, queryRequestInfo) {
var type = query.type;
var fragment = query.fragment;
var resolve = query.resolve;

@@ -71,0 +73,0 @@

@@ -30,3 +30,3 @@ 'use strict';

/**
* @public
* @internal
*

@@ -37,2 +37,13 @@ */

_createClass(DiodeRootQuery, [{
key: 'getContainerQuery',
value: function getContainerQuery() {
return this._containerQuery;
}
/**
* @public
*
*/
}, {
key: 'setVariables',

@@ -39,0 +50,0 @@ value: function setVariables(variables) {

@@ -13,2 +13,18 @@ 'use strict';

var _DiodeQueryTypes = require('../query/DiodeQueryTypes');
var _DiodeQueryTypes2 = _interopRequireDefault(_DiodeQueryTypes);
var _resolvePendingQueries = require('../query/resolvePendingQueries');
var _resolvePendingQueries2 = _interopRequireDefault(_resolvePendingQueries);
var _filterBatchQueries = require('../query/filterBatchQueries');
var _filterBatchQueries2 = _interopRequireDefault(_filterBatchQueries);
var _resolveBatchQuery = require('../query/resolveBatchQuery');
var _resolveBatchQuery2 = _interopRequireDefault(_resolveBatchQuery);
var _DiodeQueryRequest = require('../query/DiodeQueryRequest');

@@ -24,2 +40,3 @@

this._batchQueriesEnabled = false;
this._networkLayer = new _DiodeNetworkLayer2.default();

@@ -41,5 +58,20 @@ }

* @public
*/
}, {
key: 'useBatchQueries',
value: function useBatchQueries(batchQueries) {
/* istanbul ignore else */
if (batchQueries && batchQueries.length) {
this._batchQueriesEnabled = true;
this._batchQueries = batchQueries;
}
}
/**
* @public
*
* Send queries via network layer bypassing internal cache. Note that the
* server may respond with 304 status but it's not actually a cached response
* server may respond with 304 status but it's not actually an internal
* cached response
*/

@@ -50,5 +82,15 @@

value: function forceFetch(RootContainer, options) {
var allQueries = (0, _DiodeQueryRequest.getQueryRequests)(RootContainer);
return this._fetchQueries(allQueries, options).then(function (__diodeResponse) {
return { __diodeResponse: __diodeResponse };
var queries = (0, _DiodeQueryRequest.getQueryRequests)(RootContainer);
return this._fetchQueries(queries, options).then(function (response) {
// Convert diode response as root container props
var _RootContainer$query$ = RootContainer.query.getContainerQuery();
var queryMap = _RootContainer$query$.map;
return Object.keys(queryMap).reduce(function (props, key) {
props[key] = response[queryMap[key].type];
return props;
}, {});
});

@@ -59,3 +101,8 @@ }

* Recursively fetch over query dependency, starting with query with no
* dependency, and build up response moving up
* dependency, and build response moving up
*
* TODO:
* - All DiodeQueryRequest should contain pending property for filtering
* instead of using query.dependencies which is not available in normal
* QueryRequest
*/

@@ -70,36 +117,46 @@

// We need to store unmodified initial queries before filtered
// into batch query so we can use their resolve function when resolving
// response from batch query
var pendingQueries = allQueries.filter(function (query) {
return query.pending;
return query.dependencies;
});
var queries = allQueries.filter(function (query) {
return !query.pending;
var initialQueries = allQueries.filter(function (query) {
return !query.dependencies;
});
var queries = initialQueries;
return this._networkLayer.sendQueries(queries, options).then(function (response) {
if (pendingQueries.length > 0) {
var _queries = _this._resolvePendingQueries(pendingQueries, response);
return _this._fetchQueries(_queries, options).then(function (pendingResponse) {
return (0, _objectAssign2.default)(response, pendingResponse);
});
}
if (this._batchQueriesEnabled) {
queries = (0, _filterBatchQueries2.default)(queries, this._batchQueries);
}
return response;
});
}
}, {
key: '_resolvePendingQueries',
value: function _resolvePendingQueries(pendingQueries, response) {
return pendingQueries.map(function (pendingQuery) {
var callback = pendingQuery.callback;
var dependency = pendingQuery.dependency;
return this._networkLayer.sendQueries(queries, options).then(function (responses) {
// Convert array of response into Map<QueryType, QueryResponse>
var responseMap = responses.reduce(function (responseMap, response, id) {
var query = queries[id];
var type = query.type;
var fragment = query.fragment;
/* istanbul ignore else */
if (response[dependency.type]) {
var queryRequestInfo = callback(response[dependency.type]);
return (0, _DiodeQueryRequest.generateQueryRequest)(pendingQuery, queryRequestInfo);
if (type === _DiodeQueryTypes2.default.BATCH) {
// BatchQuery returns multiple response at once as single object,
// we need to merge initial response with response generated by
// batch query response resolution
var batchQueryResponseMap = (0, _resolveBatchQuery2.default)(query.resolve(response, options), initialQueries, options);
(0, _objectAssign2.default)(responseMap, batchQueryResponseMap);
} else {
responseMap[type] = query.resolve(response, fragment, options);
}
return responseMap;
}, {});
if (pendingQueries.length > 0) {
var nextQueries = (0, _resolvePendingQueries2.default)(pendingQueries, responseMap);
return _this._fetchQueries(nextQueries, options).then(function (nextResponseMap) {
return (0, _objectAssign2.default)(responseMap, nextResponseMap);
});
}
/* istanbul ignore next */
return pendingQuery;
return responseMap;
});

@@ -106,0 +163,0 @@ }

{
"name": "react-diode",
"version": "0.2.0-beta.1",
"version": "0.2.0-beta.3",
"description": "Endpoint agnostic, unidirectional data fetching for React applications",

@@ -13,3 +13,3 @@ "main": "lib/DiodePublic.js",

"scripts": {
"typecheck": "flow",
"typecheck": "flow check",
"lint": "marlint",

@@ -43,6 +43,5 @@ "unit": "mocha --compilers js:babel-core/register",

"dependencies": {
"deep-extend": "^0.4.0",
"deep-extend": "^0.4.1",
"isomorphic-fetch": "^2.2.1",
"object-assign": "^4.0.1",
"superagent": "^1.4.0"
"object-assign": "^4.0.1"
},

@@ -53,3 +52,3 @@ "peerDependencies": {

"devDependencies": {
"babel-cli": "^6.6.4",
"babel-cli": "^6.6.5",
"babel-core": "^6.7.2",

@@ -60,7 +59,8 @@ "babel-preset-es2015": "^6.6.0",

"chai": "^3.5.0",
"codecov": "^1.0.1",
"flow-bin": "^0.22.1",
"marlint": "^1.5.3",
"mocha": "^2.4.5",
"nock": "^7.2.2",
"nyc": "^6.0.0",
"nock": "^7.4.0",
"nyc": "^6.1.1",
"react": "^0.14.7",

@@ -67,0 +67,0 @@ "sinon": "^1.17.3",

# Diode
[![Build Status](https://travis-ci.org/traveloka/react-diode.svg?branch=master)](https://travis-ci.org/traveloka/react-diode) [![codecov.io](https://codecov.io/github/traveloka/react-diode/coverage.svg?branch=master)](https://codecov.io/github/traveloka/react-diode?branch=master)
> Endpoint agnostic, unidirectional data fetching for React application

@@ -16,21 +18,18 @@

- **Unidirectional**
Data requirement flows one direction from child component to parent component so root component will know all data the child need. No more confusion where the data comes from (or what component should fetch what data) as root component data is the only source of truth.
- **Declarative**
Declare your data requirements declaratively, no need to manually call API in `componentDidMount`
and use `this.state` to store data from server. All your data will be available as props.
Declare your data requirements declaratively, no need to manually call API in `componentDidMount` and use `this.state` to store data from server. All your data in component will be available as props.
- **Colocation**
Query next to views that rely on them. See your data requirement in the same place
that your view resides.
Query next to views that rely on them. See your data requirement in the same place that your view resides.
- **Endpoint agnostic**
Every query will have its own endpoint and configuration on how to call them. You can use any
HTTP-based endpoint, including REST and yes, GraphQL.
Every query will have its own endpoint and configuration on how to call them. You can use any HTTP-based endpoint, including REST and yes, GraphQL.
- **Batched query**
For some reason you may want for some queries to be sent as one payload, while still declaring data in your component using single query.
## Install

@@ -37,0 +36,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc