UNPKG

@graffy/common

Version:

Common libraries that used by various Graffy modules.

290 lines (237 loc) 8.96 kB
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } import { isRange, isBranch, isLink, findFirst, findLast } from '../../node'; import { isEmpty } from '../../util.js'; import { keyAfter, keyBefore } from '../../ops'; import { decodeArgs, encodeQuery } from '../index.js'; var LINK_PLACEHOLDER = Symbol(); function descend(tree, path) { var node = tree; for (var _iterator = _createForOfIteratorHelperLoose(path), _step; !(_step = _iterator()).done;) { var key = _step.value; if (!node) return; if (Array.isArray(node)) node = node.props; if (!(key in node)) return undefined; node = node[key]; } return node; } export default function decodeGraph(graph, query, links) { if (links === void 0) { links = []; } var result = graph && decodeChildren(graph, query, links); var link; while (link = links.shift()) { var _link = link, from = _link[0], key = _link[1], path = _link[2], args = _link[3]; var node = descend(result, path); // console.log('resolving link', link, 'found', node, 'in', result); if (node === LINK_PLACEHOLDER) { // Try this link again later. This is to resolve multi-hop links. // TODO: Cycle detection. links.push(link); } else { // console.log('Replacing placeholder at', key, 'with', node); from[key] = node; if (typeof node === 'object' && node) { node.$ref = path; if (args) node.$key = args; } } } return result; } function decodeChildren(graph, query, links) { var resObj = {}; var hasEncoded = false; var hasRanges = false; // First, we construct the result object for (var _iterator2 = _createForOfIteratorHelperLoose(graph), _step2; !(_step2 = _iterator2()).done;) { var node = _step2.value; var _key = node.key; if (_key[0] === '\0') hasEncoded = true; if (isRange(node)) { if (_key === node.end) { resObj[_key] = null; } else { hasRanges = true; } continue; } if (isLink(node)) { links.push([resObj, _key, node.path]); resObj[_key] = LINK_PLACEHOLDER; continue; } if (isBranch(node)) { resObj[_key] = decodeChildren(node.children, query == null ? void 0 : query[_key], links); continue; } if (typeof node.value === 'object' && node.value) { // The API must appear to return the value directly, but when // JSON-stringified it returned object should be wrapped in a $val. var child = Object.create(node.value); child.$val = node.value; resObj[_key] = child; } else { resObj[_key] = node.value; } } if (hasRanges) { var putRanges = []; var last = null; for (var _iterator3 = _createForOfIteratorHelperLoose(graph), _step3; !(_step3 = _iterator3()).done;) { var _step3$value = _step3.value, key = _step3$value.key, end = _step3$value.end; if (last) { if (last.end) { if (key === keyAfter(last.end)) { last.end = end || key; continue; } } else { if (key === keyAfter(last.key)) key = last.key; } } if (end && key !== end) { last = { key: key, end: end }; putRanges.push(last); } else { last = { key: key }; } } if (putRanges.length === 1 && putRanges[0].key === '' && putRanges[0].end === "\uFFFF") { resObj.$put = true; } else { resObj.$put = putRanges.map(function (rNode) { return decodeArgs(rNode); }); } } /* We return an array, not an object, as the decoded value in three situations: 1. The query had pagination parameters 2. The result had ranges of unknown 3. The result has encoded values, which must be decoded into an $key */ if (query) { if (Array.isArray(query)) { if (query.length !== 1) throw Error('decodeGraph.multi_page'); return makeArray(graph, query[0], links, resObj); } else if (isPaginated(query)) { return makeArray(graph, query, links, resObj); } } if (hasEncoded) { return makeArray(graph, null, links, resObj); } return resObj; } function isPaginated(_temp) { var _ref = _temp === void 0 ? {} : _temp, key = _ref.$key; return key && (key.$first || key.$last || key.$after || key.$before || key.$since || key.$until || key.all); } function isMinKey(key) { return key === '' || key[0] === '\0' && key[key.length - 1] === '.'; } function isMaxKey(key) { return key === "\uFFFF" || key[0] === '\0' && key[key.length - 2] === '.' && key[key.length - 1] === "\uFFFF"; } function prefix(key) { if (key[0] === '\0') { var parts = key.split('.'); return parts[parts.length - 2] ? parts[parts.length - 2] + '.' : ''; } return ''; } function makeArray(graph, query, links, object) { var _query$$key, _query$$key2; var resArr = []; if (query && isPaginated(query)) { var queryNode = encodeQuery(query)[0]; graph = getRangeNodes(graph, queryNode); } for (var _iterator4 = _createForOfIteratorHelperLoose(graph), _step4; !(_step4 = _iterator4()).done;) { var node = _step4.value; // console.log('node', node); var key = node.key; var child = object[key]; if (typeof child === 'undefined' || child === null) continue; var args = decodeArgs(node); var _args = args, cursor = _args.cursor, rest = _objectWithoutPropertiesLoose(_args, ["cursor"]); if (isEmpty(rest) && Array.isArray(cursor)) args = cursor; if (child === LINK_PLACEHOLDER) { links.push([resArr, resArr.length, node.path, args]); resArr.push(LINK_PLACEHOLDER); // Placeholder that will be replaced. continue; } if (typeof child === 'object' && child) child.$key = args; resArr.push(child); } // Add next and previous page links var firstNode = graph[0]; var lastNode = graph[graph.length - 1]; var firstKey = firstNode.key; var lastKey = lastNode.end || lastNode.key; var limit = (query == null ? void 0 : (_query$$key = query.$key) == null ? void 0 : _query$$key.$first) || (query == null ? void 0 : (_query$$key2 = query.$key) == null ? void 0 : _query$$key2.$last) || resArr.length || 1; if (!isMinKey(firstKey)) { Object.defineProperty(resArr, 'prevPage', { value: decodeArgs({ key: keyBefore(firstKey), end: prefix(firstKey), limit: limit }) }); } if (!isMaxKey(lastKey)) { Object.defineProperty(resArr, 'nextPage', { value: decodeArgs({ key: keyAfter(lastKey), end: prefix(lastKey) + "\uFFFF", limit: limit }) }); } // Object.defineProperty(resArr, 'pageInfo', { value: pageInfo(graph) }); Object.defineProperty(resArr, 'props', { value: object }); return resArr; } export function getRangeNodes(graph, _ref2) { var key = _ref2.key, end = _ref2.end, _ref2$limit = _ref2.limit, limit = _ref2$limit === void 0 ? Infinity : _ref2$limit; var result = []; if (key < end) { for (var i = findFirst(graph, key); key <= end && limit > 0; i++) { var node = graph[i]; if (!node || key < node.key) break; result.push(node); if (!isRange(node)) limit--; key = keyAfter(node.end || node.key); } } else { for (var _i = findLast(graph, key) - 1; key >= end && limit > 0; _i--) { var _node = graph[_i]; if (!_node || key > (_node.end || _node.key)) break; result.unshift(_node); if (!isRange(_node)) limit--; key = keyBefore(_node.key); } } return result; }