UNPKG

@sterblue/sterblue-sdk

Version:

Sterblue Graph SDK for graphile.sterblue.com

136 lines (110 loc) 5.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.streamQueryNoCount = void 0; var _fp = require("lodash/fp"); var _getPaginationPath = require("./get-pagination-path"); var _util = require("util"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function* generateBatchVariables({ first, offset = 0, batchSize = 20 } = { offset: 0, batchSize: 20 }) { if ((0, _fp.isNumber)(first)) { const end = offset + first; for (let batchOffset = offset; batchOffset < end; batchOffset = batchOffset + batchSize) { const batchFirst = Math.min(batchSize, end - batchOffset); if (batchOffset + batchSize >= end) { yield { first: batchFirst, offset: batchOffset }; } else { yield { first: batchFirst, offset: batchOffset }; } } return; } else { for (let batchOffset = offset; true; batchOffset = batchOffset + batchSize) { const batchFirst = batchSize; yield { first: batchFirst, offset: batchOffset }; } } } /** * Stream a list query as an async iterable using batches. * Allow to perform huge queries, replace queryHugeData */ const streamQueryNoCount = (queryFunction, dataPath = []) => { return async function (_ref) { let { query, variables: { first, offset = 0, batchSize = 20 } = { offset: 0, batchSize: 20 } } = _ref, variables = _objectWithoutProperties(_ref.variables, ["first", "offset", "batchSize"]), options = _objectWithoutProperties(_ref, ["query", "variables"]); const paginationPath = (0, _getPaginationPath.getPaginationPath)(query); if (!(0, _util.isArray)(paginationPath)) { throw new Error("Error: The query must contain an element with the exact arguments (first: $first offset: $offset ...others)"); } const extractArray = (0, _fp.get)([...dataPath, ...paginationPath]); const iteratee = async batchVariables => { const queryResult = await queryFunction(_objectSpread(_objectSpread({}, options), {}, { query, variables: _objectSpread(_objectSpread({}, variables), batchVariables) })); const extractedArray = extractArray(queryResult); if ((0, _fp.isNil)(extractedArray)) { throw new Error(`Could not find data as expected in query result at path ${[...dataPath, ...paginationPath]}`); } else { return extractArray(queryResult); } }; const batchVariablesIterator = generateBatchVariables({ first, offset, batchSize }); async function* _result() { for (const batchVariables of batchVariablesIterator) { const lastBatch = await iteratee(batchVariables); if ((0, _fp.isNil)(lastBatch) || (0, _fp.isEmpty)(lastBatch)) { return; } else { for (const result of lastBatch) { yield result; } } } return; } return _result(); // // This would be cool, but has no way to stop when the query returns an empty result // return flatMap( // iteratee, // generateBatchVariables({ first, offset, batchSize }) // ); }; }; exports.streamQueryNoCount = streamQueryNoCount;