UNPKG

apollo-cache-inmemory

Version:

Core abstract of Caching layer for Apollo Client

318 lines 14.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var apollo_utilities_1 = require("apollo-utilities"); var optimism_1 = require("optimism"); var depTrackingCache_1 = require("./depTrackingCache"); var ts_invariant_1 = require("ts-invariant"); var StoreReader = (function () { function StoreReader(_a) { var _this = this; var _b = _a === void 0 ? {} : _a, _c = _b.cacheKeyRoot, cacheKeyRoot = _c === void 0 ? new optimism_1.KeyTrie(apollo_utilities_1.canUseWeakMap) : _c, _d = _b.freezeResults, freezeResults = _d === void 0 ? false : _d; var _e = this, executeStoreQuery = _e.executeStoreQuery, executeSelectionSet = _e.executeSelectionSet, executeSubSelectedArray = _e.executeSubSelectedArray; this.freezeResults = freezeResults; this.executeStoreQuery = optimism_1.wrap(function (options) { return executeStoreQuery.call(_this, options); }, { makeCacheKey: function (_a) { var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, fragmentMatcher = _a.fragmentMatcher; if (contextValue.store instanceof depTrackingCache_1.DepTrackingCache) { return cacheKeyRoot.lookup(contextValue.store, query, fragmentMatcher, JSON.stringify(variableValues), rootValue.id); } } }); this.executeSelectionSet = optimism_1.wrap(function (options) { return executeSelectionSet.call(_this, options); }, { makeCacheKey: function (_a) { var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext; if (execContext.contextValue.store instanceof depTrackingCache_1.DepTrackingCache) { return cacheKeyRoot.lookup(execContext.contextValue.store, selectionSet, execContext.fragmentMatcher, JSON.stringify(execContext.variableValues), rootValue.id); } } }); this.executeSubSelectedArray = optimism_1.wrap(function (options) { return executeSubSelectedArray.call(_this, options); }, { makeCacheKey: function (_a) { var field = _a.field, array = _a.array, execContext = _a.execContext; if (execContext.contextValue.store instanceof depTrackingCache_1.DepTrackingCache) { return cacheKeyRoot.lookup(execContext.contextValue.store, field, array, JSON.stringify(execContext.variableValues)); } } }); } StoreReader.prototype.readQueryFromStore = function (options) { return this.diffQueryAgainstStore(tslib_1.__assign(tslib_1.__assign({}, options), { returnPartialData: false })).result; }; StoreReader.prototype.diffQueryAgainstStore = function (_a) { var store = _a.store, query = _a.query, variables = _a.variables, previousResult = _a.previousResult, _b = _a.returnPartialData, returnPartialData = _b === void 0 ? true : _b, _c = _a.rootId, rootId = _c === void 0 ? 'ROOT_QUERY' : _c, fragmentMatcherFunction = _a.fragmentMatcherFunction, config = _a.config; var queryDefinition = apollo_utilities_1.getQueryDefinition(query); variables = apollo_utilities_1.assign({}, apollo_utilities_1.getDefaultValues(queryDefinition), variables); var context = { store: store, dataIdFromObject: config && config.dataIdFromObject, cacheRedirects: (config && config.cacheRedirects) || {}, }; var execResult = this.executeStoreQuery({ query: query, rootValue: { type: 'id', id: rootId, generated: true, typename: 'Query', }, contextValue: context, variableValues: variables, fragmentMatcher: fragmentMatcherFunction, }); var hasMissingFields = execResult.missing && execResult.missing.length > 0; if (hasMissingFields && !returnPartialData) { execResult.missing.forEach(function (info) { if (info.tolerable) return; throw new ts_invariant_1.InvariantError("Can't find field " + info.fieldName + " on object " + JSON.stringify(info.object, null, 2) + "."); }); } if (previousResult) { if (apollo_utilities_1.isEqual(previousResult, execResult.result)) { execResult.result = previousResult; } } return { result: execResult.result, complete: !hasMissingFields, }; }; StoreReader.prototype.executeStoreQuery = function (_a) { var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, _b = _a.fragmentMatcher, fragmentMatcher = _b === void 0 ? defaultFragmentMatcher : _b; var mainDefinition = apollo_utilities_1.getMainDefinition(query); var fragments = apollo_utilities_1.getFragmentDefinitions(query); var fragmentMap = apollo_utilities_1.createFragmentMap(fragments); var execContext = { query: query, fragmentMap: fragmentMap, contextValue: contextValue, variableValues: variableValues, fragmentMatcher: fragmentMatcher, }; return this.executeSelectionSet({ selectionSet: mainDefinition.selectionSet, rootValue: rootValue, execContext: execContext, }); }; StoreReader.prototype.executeSelectionSet = function (_a) { var _this = this; var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext; var fragmentMap = execContext.fragmentMap, contextValue = execContext.contextValue, variables = execContext.variableValues; var finalResult = { result: null }; var objectsToMerge = []; var object = contextValue.store.get(rootValue.id); var typename = (object && object.__typename) || (rootValue.id === 'ROOT_QUERY' && 'Query') || void 0; function handleMissing(result) { var _a; if (result.missing) { finalResult.missing = finalResult.missing || []; (_a = finalResult.missing).push.apply(_a, result.missing); } return result.result; } selectionSet.selections.forEach(function (selection) { var _a; if (!apollo_utilities_1.shouldInclude(selection, variables)) { return; } if (apollo_utilities_1.isField(selection)) { var fieldResult = handleMissing(_this.executeField(object, typename, selection, execContext)); if (typeof fieldResult !== 'undefined') { objectsToMerge.push((_a = {}, _a[apollo_utilities_1.resultKeyNameFromField(selection)] = fieldResult, _a)); } } else { var fragment = void 0; if (apollo_utilities_1.isInlineFragment(selection)) { fragment = selection; } else { fragment = fragmentMap[selection.name.value]; if (!fragment) { throw new ts_invariant_1.InvariantError("No fragment named " + selection.name.value); } } var typeCondition = fragment.typeCondition && fragment.typeCondition.name.value; var match = !typeCondition || execContext.fragmentMatcher(rootValue, typeCondition, contextValue); if (match) { var fragmentExecResult = _this.executeSelectionSet({ selectionSet: fragment.selectionSet, rootValue: rootValue, execContext: execContext, }); if (match === 'heuristic' && fragmentExecResult.missing) { fragmentExecResult = tslib_1.__assign(tslib_1.__assign({}, fragmentExecResult), { missing: fragmentExecResult.missing.map(function (info) { return tslib_1.__assign(tslib_1.__assign({}, info), { tolerable: true }); }) }); } objectsToMerge.push(handleMissing(fragmentExecResult)); } } }); finalResult.result = apollo_utilities_1.mergeDeepArray(objectsToMerge); if (this.freezeResults && process.env.NODE_ENV !== 'production') { Object.freeze(finalResult.result); } return finalResult; }; StoreReader.prototype.executeField = function (object, typename, field, execContext) { var variables = execContext.variableValues, contextValue = execContext.contextValue; var fieldName = field.name.value; var args = apollo_utilities_1.argumentsObjectFromField(field, variables); var info = { resultKey: apollo_utilities_1.resultKeyNameFromField(field), directives: apollo_utilities_1.getDirectiveInfoFromField(field, variables), }; var readStoreResult = readStoreResolver(object, typename, fieldName, args, contextValue, info); if (Array.isArray(readStoreResult.result)) { return this.combineExecResults(readStoreResult, this.executeSubSelectedArray({ field: field, array: readStoreResult.result, execContext: execContext, })); } if (!field.selectionSet) { assertSelectionSetForIdValue(field, readStoreResult.result); if (this.freezeResults && process.env.NODE_ENV !== 'production') { apollo_utilities_1.maybeDeepFreeze(readStoreResult); } return readStoreResult; } if (readStoreResult.result == null) { return readStoreResult; } return this.combineExecResults(readStoreResult, this.executeSelectionSet({ selectionSet: field.selectionSet, rootValue: readStoreResult.result, execContext: execContext, })); }; StoreReader.prototype.combineExecResults = function () { var execResults = []; for (var _i = 0; _i < arguments.length; _i++) { execResults[_i] = arguments[_i]; } var missing; execResults.forEach(function (execResult) { if (execResult.missing) { missing = missing || []; missing.push.apply(missing, execResult.missing); } }); return { result: execResults.pop().result, missing: missing, }; }; StoreReader.prototype.executeSubSelectedArray = function (_a) { var _this = this; var field = _a.field, array = _a.array, execContext = _a.execContext; var missing; function handleMissing(childResult) { if (childResult.missing) { missing = missing || []; missing.push.apply(missing, childResult.missing); } return childResult.result; } array = array.map(function (item) { if (item === null) { return null; } if (Array.isArray(item)) { return handleMissing(_this.executeSubSelectedArray({ field: field, array: item, execContext: execContext, })); } if (field.selectionSet) { return handleMissing(_this.executeSelectionSet({ selectionSet: field.selectionSet, rootValue: item, execContext: execContext, })); } assertSelectionSetForIdValue(field, item); return item; }); if (this.freezeResults && process.env.NODE_ENV !== 'production') { Object.freeze(array); } return { result: array, missing: missing }; }; return StoreReader; }()); exports.StoreReader = StoreReader; function assertSelectionSetForIdValue(field, value) { if (!field.selectionSet && apollo_utilities_1.isIdValue(value)) { throw new ts_invariant_1.InvariantError("Missing selection set for object of type " + value.typename + " returned for query field " + field.name.value); } } function defaultFragmentMatcher() { return true; } function assertIdValue(idValue) { ts_invariant_1.invariant(apollo_utilities_1.isIdValue(idValue), "Encountered a sub-selection on the query, but the store doesn't have an object reference. This should never happen during normal use unless you have custom code that is directly manipulating the store; please file an issue."); } exports.assertIdValue = assertIdValue; function readStoreResolver(object, typename, fieldName, args, context, _a) { var resultKey = _a.resultKey, directives = _a.directives; var storeKeyName = fieldName; if (args || directives) { storeKeyName = apollo_utilities_1.getStoreKeyName(storeKeyName, args, directives); } var fieldValue = void 0; if (object) { fieldValue = object[storeKeyName]; if (typeof fieldValue === 'undefined' && context.cacheRedirects && typeof typename === 'string') { var type = context.cacheRedirects[typename]; if (type) { var resolver = type[fieldName]; if (resolver) { fieldValue = resolver(object, args, { getCacheKey: function (storeObj) { var id = context.dataIdFromObject(storeObj); return id && apollo_utilities_1.toIdValue({ id: id, typename: storeObj.__typename, }); }, }); } } } } if (typeof fieldValue === 'undefined') { return { result: fieldValue, missing: [{ object: object, fieldName: storeKeyName, tolerable: false, }], }; } if (apollo_utilities_1.isJsonValue(fieldValue)) { fieldValue = fieldValue.json; } return { result: fieldValue, }; } //# sourceMappingURL=readFromStore.js.map