@apollo/client
Version:
A fully-featured caching GraphQL client.
1,232 lines (1,220 loc) • 102 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var globals = require('../utilities/globals');
var tslib = require('tslib');
var optimism = require('optimism');
var utilities = require('../utilities');
var equality = require('@wry/equality');
var trie = require('@wry/trie');
var graphql = require('graphql');
var context = require('@wry/context');
var ApolloCache = (function () {
function ApolloCache() {
this.getFragmentDoc = optimism.wrap(utilities.getFragmentQueryDocument);
}
ApolloCache.prototype.batch = function (options) {
var _this = this;
var optimisticId = typeof options.optimistic === "string" ? options.optimistic :
options.optimistic === false ? null : void 0;
var updateResult;
this.performTransaction(function () { return updateResult = options.update(_this); }, optimisticId);
return updateResult;
};
ApolloCache.prototype.recordOptimisticTransaction = function (transaction, optimisticId) {
this.performTransaction(transaction, optimisticId);
};
ApolloCache.prototype.transformDocument = function (document) {
return document;
};
ApolloCache.prototype.transformForLink = function (document) {
return document;
};
ApolloCache.prototype.identify = function (object) {
return;
};
ApolloCache.prototype.gc = function () {
return [];
};
ApolloCache.prototype.modify = function (options) {
return false;
};
ApolloCache.prototype.readQuery = function (options, optimistic) {
if (optimistic === void 0) { optimistic = !!options.optimistic; }
return this.read(tslib.__assign(tslib.__assign({}, options), { rootId: options.id || 'ROOT_QUERY', optimistic: optimistic }));
};
ApolloCache.prototype.readFragment = function (options, optimistic) {
if (optimistic === void 0) { optimistic = !!options.optimistic; }
return this.read(tslib.__assign(tslib.__assign({}, options), { query: this.getFragmentDoc(options.fragment, options.fragmentName), rootId: options.id, optimistic: optimistic }));
};
ApolloCache.prototype.writeQuery = function (_a) {
var id = _a.id, data = _a.data, options = tslib.__rest(_a, ["id", "data"]);
return this.write(Object.assign(options, {
dataId: id || 'ROOT_QUERY',
result: data,
}));
};
ApolloCache.prototype.writeFragment = function (_a) {
var id = _a.id, data = _a.data, fragment = _a.fragment, fragmentName = _a.fragmentName, options = tslib.__rest(_a, ["id", "data", "fragment", "fragmentName"]);
return this.write(Object.assign(options, {
query: this.getFragmentDoc(fragment, fragmentName),
dataId: id,
result: data,
}));
};
ApolloCache.prototype.updateQuery = function (options, update) {
return this.batch({
update: function (cache) {
var value = cache.readQuery(options);
var data = update(value);
if (data === void 0 || data === null)
return value;
cache.writeQuery(tslib.__assign(tslib.__assign({}, options), { data: data }));
return data;
},
});
};
ApolloCache.prototype.updateFragment = function (options, update) {
return this.batch({
update: function (cache) {
var value = cache.readFragment(options);
var data = update(value);
if (data === void 0 || data === null)
return value;
cache.writeFragment(tslib.__assign(tslib.__assign({}, options), { data: data }));
return data;
},
});
};
return ApolloCache;
}());
exports.Cache = void 0;
(function (Cache) {
})(exports.Cache || (exports.Cache = {}));
var MissingFieldError = (function (_super) {
tslib.__extends(MissingFieldError, _super);
function MissingFieldError(message, path, query, variables) {
var _a;
var _this = _super.call(this, message) || this;
_this.message = message;
_this.path = path;
_this.query = query;
_this.variables = variables;
if (Array.isArray(_this.path)) {
_this.missing = _this.message;
for (var i = _this.path.length - 1; i >= 0; --i) {
_this.missing = (_a = {}, _a[_this.path[i]] = _this.missing, _a);
}
}
else {
_this.missing = _this.path;
}
_this.__proto__ = MissingFieldError.prototype;
return _this;
}
return MissingFieldError;
}(Error));
var hasOwn = Object.prototype.hasOwnProperty;
function isNullish(value) {
return value === null || value === void 0;
}
function defaultDataIdFromObject(_a, context) {
var __typename = _a.__typename, id = _a.id, _id = _a._id;
if (typeof __typename === "string") {
if (context) {
context.keyObject =
!isNullish(id) ? { id: id } :
!isNullish(_id) ? { _id: _id } :
void 0;
}
if (isNullish(id) && !isNullish(_id)) {
id = _id;
}
if (!isNullish(id)) {
return "".concat(__typename, ":").concat((typeof id === "number" ||
typeof id === "string") ? id : JSON.stringify(id));
}
}
}
var defaultConfig = {
dataIdFromObject: defaultDataIdFromObject,
addTypename: true,
resultCaching: true,
canonizeResults: false,
};
function normalizeConfig(config) {
return utilities.compact(defaultConfig, config);
}
function shouldCanonizeResults(config) {
var value = config.canonizeResults;
return value === void 0 ? defaultConfig.canonizeResults : value;
}
function getTypenameFromStoreObject(store, objectOrReference) {
return utilities.isReference(objectOrReference)
? store.get(objectOrReference.__ref, "__typename")
: objectOrReference && objectOrReference.__typename;
}
var TypeOrFieldNameRegExp = /^[_a-z][_0-9a-z]*/i;
function fieldNameFromStoreName(storeFieldName) {
var match = storeFieldName.match(TypeOrFieldNameRegExp);
return match ? match[0] : storeFieldName;
}
function selectionSetMatchesResult(selectionSet, result, variables) {
if (utilities.isNonNullObject(result)) {
return utilities.isArray(result)
? result.every(function (item) { return selectionSetMatchesResult(selectionSet, item, variables); })
: selectionSet.selections.every(function (field) {
if (utilities.isField(field) && utilities.shouldInclude(field, variables)) {
var key = utilities.resultKeyNameFromField(field);
return hasOwn.call(result, key) &&
(!field.selectionSet ||
selectionSetMatchesResult(field.selectionSet, result[key], variables));
}
return true;
});
}
return false;
}
function storeValueIsStoreObject(value) {
return utilities.isNonNullObject(value) &&
!utilities.isReference(value) &&
!utilities.isArray(value);
}
function makeProcessedFieldsMerger() {
return new utilities.DeepMerger;
}
function extractFragmentContext(document, fragments) {
var fragmentMap = utilities.createFragmentMap(utilities.getFragmentDefinitions(document));
return {
fragmentMap: fragmentMap,
lookupFragment: function (name) {
var def = fragmentMap[name];
if (!def && fragments) {
def = fragments.lookup(name);
}
return def || null;
},
};
}
var DELETE = Object.create(null);
var delModifier = function () { return DELETE; };
var INVALIDATE = Object.create(null);
exports.EntityStore = (function () {
function EntityStore(policies, group) {
var _this = this;
this.policies = policies;
this.group = group;
this.data = Object.create(null);
this.rootIds = Object.create(null);
this.refs = Object.create(null);
this.getFieldValue = function (objectOrReference, storeFieldName) { return utilities.maybeDeepFreeze(utilities.isReference(objectOrReference)
? _this.get(objectOrReference.__ref, storeFieldName)
: objectOrReference && objectOrReference[storeFieldName]); };
this.canRead = function (objOrRef) {
return utilities.isReference(objOrRef)
? _this.has(objOrRef.__ref)
: typeof objOrRef === "object";
};
this.toReference = function (objOrIdOrRef, mergeIntoStore) {
if (typeof objOrIdOrRef === "string") {
return utilities.makeReference(objOrIdOrRef);
}
if (utilities.isReference(objOrIdOrRef)) {
return objOrIdOrRef;
}
var id = _this.policies.identify(objOrIdOrRef)[0];
if (id) {
var ref = utilities.makeReference(id);
if (mergeIntoStore) {
_this.merge(id, objOrIdOrRef);
}
return ref;
}
};
}
EntityStore.prototype.toObject = function () {
return tslib.__assign({}, this.data);
};
EntityStore.prototype.has = function (dataId) {
return this.lookup(dataId, true) !== void 0;
};
EntityStore.prototype.get = function (dataId, fieldName) {
this.group.depend(dataId, fieldName);
if (hasOwn.call(this.data, dataId)) {
var storeObject = this.data[dataId];
if (storeObject && hasOwn.call(storeObject, fieldName)) {
return storeObject[fieldName];
}
}
if (fieldName === "__typename" &&
hasOwn.call(this.policies.rootTypenamesById, dataId)) {
return this.policies.rootTypenamesById[dataId];
}
if (this instanceof Layer) {
return this.parent.get(dataId, fieldName);
}
};
EntityStore.prototype.lookup = function (dataId, dependOnExistence) {
if (dependOnExistence)
this.group.depend(dataId, "__exists");
if (hasOwn.call(this.data, dataId)) {
return this.data[dataId];
}
if (this instanceof Layer) {
return this.parent.lookup(dataId, dependOnExistence);
}
if (this.policies.rootTypenamesById[dataId]) {
return Object.create(null);
}
};
EntityStore.prototype.merge = function (older, newer) {
var _this = this;
var dataId;
if (utilities.isReference(older))
older = older.__ref;
if (utilities.isReference(newer))
newer = newer.__ref;
var existing = typeof older === "string"
? this.lookup(dataId = older)
: older;
var incoming = typeof newer === "string"
? this.lookup(dataId = newer)
: newer;
if (!incoming)
return;
__DEV__ ? globals.invariant(typeof dataId === "string", "store.merge expects a string ID") : globals.invariant(typeof dataId === "string", 1);
var merged = new utilities.DeepMerger(storeObjectReconciler).merge(existing, incoming);
this.data[dataId] = merged;
if (merged !== existing) {
delete this.refs[dataId];
if (this.group.caching) {
var fieldsToDirty_1 = Object.create(null);
if (!existing)
fieldsToDirty_1.__exists = 1;
Object.keys(incoming).forEach(function (storeFieldName) {
if (!existing || existing[storeFieldName] !== merged[storeFieldName]) {
fieldsToDirty_1[storeFieldName] = 1;
var fieldName = fieldNameFromStoreName(storeFieldName);
if (fieldName !== storeFieldName &&
!_this.policies.hasKeyArgs(merged.__typename, fieldName)) {
fieldsToDirty_1[fieldName] = 1;
}
if (merged[storeFieldName] === void 0 && !(_this instanceof Layer)) {
delete merged[storeFieldName];
}
}
});
if (fieldsToDirty_1.__typename &&
!(existing && existing.__typename) &&
this.policies.rootTypenamesById[dataId] === merged.__typename) {
delete fieldsToDirty_1.__typename;
}
Object.keys(fieldsToDirty_1).forEach(function (fieldName) { return _this.group.dirty(dataId, fieldName); });
}
}
};
EntityStore.prototype.modify = function (dataId, fields) {
var _this = this;
var storeObject = this.lookup(dataId);
if (storeObject) {
var changedFields_1 = Object.create(null);
var needToMerge_1 = false;
var allDeleted_1 = true;
var sharedDetails_1 = {
DELETE: DELETE,
INVALIDATE: INVALIDATE,
isReference: utilities.isReference,
toReference: this.toReference,
canRead: this.canRead,
readField: function (fieldNameOrOptions, from) { return _this.policies.readField(typeof fieldNameOrOptions === "string" ? {
fieldName: fieldNameOrOptions,
from: from || utilities.makeReference(dataId),
} : fieldNameOrOptions, { store: _this }); },
};
Object.keys(storeObject).forEach(function (storeFieldName) {
var fieldName = fieldNameFromStoreName(storeFieldName);
var fieldValue = storeObject[storeFieldName];
if (fieldValue === void 0)
return;
var modify = typeof fields === "function"
? fields
: fields[storeFieldName] || fields[fieldName];
if (modify) {
var newValue = modify === delModifier ? DELETE :
modify(utilities.maybeDeepFreeze(fieldValue), tslib.__assign(tslib.__assign({}, sharedDetails_1), { fieldName: fieldName, storeFieldName: storeFieldName, storage: _this.getStorage(dataId, storeFieldName) }));
if (newValue === INVALIDATE) {
_this.group.dirty(dataId, storeFieldName);
}
else {
if (newValue === DELETE)
newValue = void 0;
if (newValue !== fieldValue) {
changedFields_1[storeFieldName] = newValue;
needToMerge_1 = true;
fieldValue = newValue;
}
}
}
if (fieldValue !== void 0) {
allDeleted_1 = false;
}
});
if (needToMerge_1) {
this.merge(dataId, changedFields_1);
if (allDeleted_1) {
if (this instanceof Layer) {
this.data[dataId] = void 0;
}
else {
delete this.data[dataId];
}
this.group.dirty(dataId, "__exists");
}
return true;
}
}
return false;
};
EntityStore.prototype.delete = function (dataId, fieldName, args) {
var _a;
var storeObject = this.lookup(dataId);
if (storeObject) {
var typename = this.getFieldValue(storeObject, "__typename");
var storeFieldName = fieldName && args
? this.policies.getStoreFieldName({ typename: typename, fieldName: fieldName, args: args })
: fieldName;
return this.modify(dataId, storeFieldName ? (_a = {},
_a[storeFieldName] = delModifier,
_a) : delModifier);
}
return false;
};
EntityStore.prototype.evict = function (options, limit) {
var evicted = false;
if (options.id) {
if (hasOwn.call(this.data, options.id)) {
evicted = this.delete(options.id, options.fieldName, options.args);
}
if (this instanceof Layer && this !== limit) {
evicted = this.parent.evict(options, limit) || evicted;
}
if (options.fieldName || evicted) {
this.group.dirty(options.id, options.fieldName || "__exists");
}
}
return evicted;
};
EntityStore.prototype.clear = function () {
this.replace(null);
};
EntityStore.prototype.extract = function () {
var _this = this;
var obj = this.toObject();
var extraRootIds = [];
this.getRootIdSet().forEach(function (id) {
if (!hasOwn.call(_this.policies.rootTypenamesById, id)) {
extraRootIds.push(id);
}
});
if (extraRootIds.length) {
obj.__META = { extraRootIds: extraRootIds.sort() };
}
return obj;
};
EntityStore.prototype.replace = function (newData) {
var _this = this;
Object.keys(this.data).forEach(function (dataId) {
if (!(newData && hasOwn.call(newData, dataId))) {
_this.delete(dataId);
}
});
if (newData) {
var __META = newData.__META, rest_1 = tslib.__rest(newData, ["__META"]);
Object.keys(rest_1).forEach(function (dataId) {
_this.merge(dataId, rest_1[dataId]);
});
if (__META) {
__META.extraRootIds.forEach(this.retain, this);
}
}
};
EntityStore.prototype.retain = function (rootId) {
return this.rootIds[rootId] = (this.rootIds[rootId] || 0) + 1;
};
EntityStore.prototype.release = function (rootId) {
if (this.rootIds[rootId] > 0) {
var count = --this.rootIds[rootId];
if (!count)
delete this.rootIds[rootId];
return count;
}
return 0;
};
EntityStore.prototype.getRootIdSet = function (ids) {
if (ids === void 0) { ids = new Set(); }
Object.keys(this.rootIds).forEach(ids.add, ids);
if (this instanceof Layer) {
this.parent.getRootIdSet(ids);
}
else {
Object.keys(this.policies.rootTypenamesById).forEach(ids.add, ids);
}
return ids;
};
EntityStore.prototype.gc = function () {
var _this = this;
var ids = this.getRootIdSet();
var snapshot = this.toObject();
ids.forEach(function (id) {
if (hasOwn.call(snapshot, id)) {
Object.keys(_this.findChildRefIds(id)).forEach(ids.add, ids);
delete snapshot[id];
}
});
var idsToRemove = Object.keys(snapshot);
if (idsToRemove.length) {
var root_1 = this;
while (root_1 instanceof Layer)
root_1 = root_1.parent;
idsToRemove.forEach(function (id) { return root_1.delete(id); });
}
return idsToRemove;
};
EntityStore.prototype.findChildRefIds = function (dataId) {
if (!hasOwn.call(this.refs, dataId)) {
var found_1 = this.refs[dataId] = Object.create(null);
var root = this.data[dataId];
if (!root)
return found_1;
var workSet_1 = new Set([root]);
workSet_1.forEach(function (obj) {
if (utilities.isReference(obj)) {
found_1[obj.__ref] = true;
}
if (utilities.isNonNullObject(obj)) {
Object.keys(obj).forEach(function (key) {
var child = obj[key];
if (utilities.isNonNullObject(child)) {
workSet_1.add(child);
}
});
}
});
}
return this.refs[dataId];
};
EntityStore.prototype.makeCacheKey = function () {
return this.group.keyMaker.lookupArray(arguments);
};
return EntityStore;
}());
var CacheGroup = (function () {
function CacheGroup(caching, parent) {
if (parent === void 0) { parent = null; }
this.caching = caching;
this.parent = parent;
this.d = null;
this.resetCaching();
}
CacheGroup.prototype.resetCaching = function () {
this.d = this.caching ? optimism.dep() : null;
this.keyMaker = new trie.Trie(utilities.canUseWeakMap);
};
CacheGroup.prototype.depend = function (dataId, storeFieldName) {
if (this.d) {
this.d(makeDepKey(dataId, storeFieldName));
var fieldName = fieldNameFromStoreName(storeFieldName);
if (fieldName !== storeFieldName) {
this.d(makeDepKey(dataId, fieldName));
}
if (this.parent) {
this.parent.depend(dataId, storeFieldName);
}
}
};
CacheGroup.prototype.dirty = function (dataId, storeFieldName) {
if (this.d) {
this.d.dirty(makeDepKey(dataId, storeFieldName), storeFieldName === "__exists" ? "forget" : "setDirty");
}
};
return CacheGroup;
}());
function makeDepKey(dataId, storeFieldName) {
return storeFieldName + '#' + dataId;
}
function maybeDependOnExistenceOfEntity(store, entityId) {
if (supportsResultCaching(store)) {
store.group.depend(entityId, "__exists");
}
}
(function (EntityStore) {
var Root = (function (_super) {
tslib.__extends(Root, _super);
function Root(_a) {
var policies = _a.policies, _b = _a.resultCaching, resultCaching = _b === void 0 ? true : _b, seed = _a.seed;
var _this = _super.call(this, policies, new CacheGroup(resultCaching)) || this;
_this.stump = new Stump(_this);
_this.storageTrie = new trie.Trie(utilities.canUseWeakMap);
if (seed)
_this.replace(seed);
return _this;
}
Root.prototype.addLayer = function (layerId, replay) {
return this.stump.addLayer(layerId, replay);
};
Root.prototype.removeLayer = function () {
return this;
};
Root.prototype.getStorage = function () {
return this.storageTrie.lookupArray(arguments);
};
return Root;
}(EntityStore));
EntityStore.Root = Root;
})(exports.EntityStore || (exports.EntityStore = {}));
var Layer = (function (_super) {
tslib.__extends(Layer, _super);
function Layer(id, parent, replay, group) {
var _this = _super.call(this, parent.policies, group) || this;
_this.id = id;
_this.parent = parent;
_this.replay = replay;
_this.group = group;
replay(_this);
return _this;
}
Layer.prototype.addLayer = function (layerId, replay) {
return new Layer(layerId, this, replay, this.group);
};
Layer.prototype.removeLayer = function (layerId) {
var _this = this;
var parent = this.parent.removeLayer(layerId);
if (layerId === this.id) {
if (this.group.caching) {
Object.keys(this.data).forEach(function (dataId) {
var ownStoreObject = _this.data[dataId];
var parentStoreObject = parent["lookup"](dataId);
if (!parentStoreObject) {
_this.delete(dataId);
}
else if (!ownStoreObject) {
_this.group.dirty(dataId, "__exists");
Object.keys(parentStoreObject).forEach(function (storeFieldName) {
_this.group.dirty(dataId, storeFieldName);
});
}
else if (ownStoreObject !== parentStoreObject) {
Object.keys(ownStoreObject).forEach(function (storeFieldName) {
if (!equality.equal(ownStoreObject[storeFieldName], parentStoreObject[storeFieldName])) {
_this.group.dirty(dataId, storeFieldName);
}
});
}
});
}
return parent;
}
if (parent === this.parent)
return this;
return parent.addLayer(this.id, this.replay);
};
Layer.prototype.toObject = function () {
return tslib.__assign(tslib.__assign({}, this.parent.toObject()), this.data);
};
Layer.prototype.findChildRefIds = function (dataId) {
var fromParent = this.parent.findChildRefIds(dataId);
return hasOwn.call(this.data, dataId) ? tslib.__assign(tslib.__assign({}, fromParent), _super.prototype.findChildRefIds.call(this, dataId)) : fromParent;
};
Layer.prototype.getStorage = function () {
var p = this.parent;
while (p.parent)
p = p.parent;
return p.getStorage.apply(p, arguments);
};
return Layer;
}(exports.EntityStore));
var Stump = (function (_super) {
tslib.__extends(Stump, _super);
function Stump(root) {
return _super.call(this, "EntityStore.Stump", root, function () { }, new CacheGroup(root.group.caching, root.group)) || this;
}
Stump.prototype.removeLayer = function () {
return this;
};
Stump.prototype.merge = function () {
return this.parent.merge.apply(this.parent, arguments);
};
return Stump;
}(Layer));
function storeObjectReconciler(existingObject, incomingObject, property) {
var existingValue = existingObject[property];
var incomingValue = incomingObject[property];
return equality.equal(existingValue, incomingValue) ? existingValue : incomingValue;
}
function supportsResultCaching(store) {
return !!(store instanceof exports.EntityStore && store.group.caching);
}
function shallowCopy(value) {
if (utilities.isNonNullObject(value)) {
return utilities.isArray(value)
? value.slice(0)
: tslib.__assign({ __proto__: Object.getPrototypeOf(value) }, value);
}
return value;
}
var ObjectCanon = (function () {
function ObjectCanon() {
this.known = new (utilities.canUseWeakSet ? WeakSet : Set)();
this.pool = new trie.Trie(utilities.canUseWeakMap);
this.passes = new WeakMap();
this.keysByJSON = new Map();
this.empty = this.admit({});
}
ObjectCanon.prototype.isKnown = function (value) {
return utilities.isNonNullObject(value) && this.known.has(value);
};
ObjectCanon.prototype.pass = function (value) {
if (utilities.isNonNullObject(value)) {
var copy = shallowCopy(value);
this.passes.set(copy, value);
return copy;
}
return value;
};
ObjectCanon.prototype.admit = function (value) {
var _this = this;
if (utilities.isNonNullObject(value)) {
var original = this.passes.get(value);
if (original)
return original;
var proto = Object.getPrototypeOf(value);
switch (proto) {
case Array.prototype: {
if (this.known.has(value))
return value;
var array = value.map(this.admit, this);
var node = this.pool.lookupArray(array);
if (!node.array) {
this.known.add(node.array = array);
if (__DEV__) {
Object.freeze(array);
}
}
return node.array;
}
case null:
case Object.prototype: {
if (this.known.has(value))
return value;
var proto_1 = Object.getPrototypeOf(value);
var array_1 = [proto_1];
var keys = this.sortedKeys(value);
array_1.push(keys.json);
var firstValueIndex_1 = array_1.length;
keys.sorted.forEach(function (key) {
array_1.push(_this.admit(value[key]));
});
var node = this.pool.lookupArray(array_1);
if (!node.object) {
var obj_1 = node.object = Object.create(proto_1);
this.known.add(obj_1);
keys.sorted.forEach(function (key, i) {
obj_1[key] = array_1[firstValueIndex_1 + i];
});
if (__DEV__) {
Object.freeze(obj_1);
}
}
return node.object;
}
}
}
return value;
};
ObjectCanon.prototype.sortedKeys = function (obj) {
var keys = Object.keys(obj);
var node = this.pool.lookupArray(keys);
if (!node.keys) {
keys.sort();
var json = JSON.stringify(keys);
if (!(node.keys = this.keysByJSON.get(json))) {
this.keysByJSON.set(json, node.keys = { sorted: keys, json: json });
}
}
return node.keys;
};
return ObjectCanon;
}());
var canonicalStringify = Object.assign(function (value) {
if (utilities.isNonNullObject(value)) {
if (stringifyCanon === void 0) {
resetCanonicalStringify();
}
var canonical = stringifyCanon.admit(value);
var json = stringifyCache.get(canonical);
if (json === void 0) {
stringifyCache.set(canonical, json = JSON.stringify(canonical));
}
return json;
}
return JSON.stringify(value);
}, {
reset: resetCanonicalStringify,
});
var stringifyCanon;
var stringifyCache;
function resetCanonicalStringify() {
stringifyCanon = new ObjectCanon;
stringifyCache = new (utilities.canUseWeakMap ? WeakMap : Map)();
}
function execSelectionSetKeyArgs(options) {
return [
options.selectionSet,
options.objectOrReference,
options.context,
options.context.canonizeResults,
];
}
var StoreReader = (function () {
function StoreReader(config) {
var _this = this;
this.knownResults = new (utilities.canUseWeakMap ? WeakMap : Map)();
this.config = utilities.compact(config, {
addTypename: config.addTypename !== false,
canonizeResults: shouldCanonizeResults(config),
});
this.canon = config.canon || new ObjectCanon;
this.executeSelectionSet = optimism.wrap(function (options) {
var _a;
var canonizeResults = options.context.canonizeResults;
var peekArgs = execSelectionSetKeyArgs(options);
peekArgs[3] = !canonizeResults;
var other = (_a = _this.executeSelectionSet).peek.apply(_a, peekArgs);
if (other) {
if (canonizeResults) {
return tslib.__assign(tslib.__assign({}, other), { result: _this.canon.admit(other.result) });
}
return other;
}
maybeDependOnExistenceOfEntity(options.context.store, options.enclosingRef.__ref);
return _this.execSelectionSetImpl(options);
}, {
max: this.config.resultCacheMaxSize,
keyArgs: execSelectionSetKeyArgs,
makeCacheKey: function (selectionSet, parent, context, canonizeResults) {
if (supportsResultCaching(context.store)) {
return context.store.makeCacheKey(selectionSet, utilities.isReference(parent) ? parent.__ref : parent, context.varString, canonizeResults);
}
}
});
this.executeSubSelectedArray = optimism.wrap(function (options) {
maybeDependOnExistenceOfEntity(options.context.store, options.enclosingRef.__ref);
return _this.execSubSelectedArrayImpl(options);
}, {
max: this.config.resultCacheMaxSize,
makeCacheKey: function (_a) {
var field = _a.field, array = _a.array, context = _a.context;
if (supportsResultCaching(context.store)) {
return context.store.makeCacheKey(field, array, context.varString);
}
}
});
}
StoreReader.prototype.resetCanon = function () {
this.canon = new ObjectCanon;
};
StoreReader.prototype.diffQueryAgainstStore = function (_a) {
var store = _a.store, query = _a.query, _b = _a.rootId, rootId = _b === void 0 ? 'ROOT_QUERY' : _b, variables = _a.variables, _c = _a.returnPartialData, returnPartialData = _c === void 0 ? true : _c, _d = _a.canonizeResults, canonizeResults = _d === void 0 ? this.config.canonizeResults : _d;
var policies = this.config.cache.policies;
variables = tslib.__assign(tslib.__assign({}, utilities.getDefaultValues(utilities.getQueryDefinition(query))), variables);
var rootRef = utilities.makeReference(rootId);
var execResult = this.executeSelectionSet({
selectionSet: utilities.getMainDefinition(query).selectionSet,
objectOrReference: rootRef,
enclosingRef: rootRef,
context: tslib.__assign({ store: store, query: query, policies: policies, variables: variables, varString: canonicalStringify(variables), canonizeResults: canonizeResults }, extractFragmentContext(query, this.config.fragments)),
});
var missing;
if (execResult.missing) {
missing = [new MissingFieldError(firstMissing(execResult.missing), execResult.missing, query, variables)];
if (!returnPartialData) {
throw missing[0];
}
}
return {
result: execResult.result,
complete: !missing,
missing: missing,
};
};
StoreReader.prototype.isFresh = function (result, parent, selectionSet, context) {
if (supportsResultCaching(context.store) &&
this.knownResults.get(result) === selectionSet) {
var latest = this.executeSelectionSet.peek(selectionSet, parent, context, this.canon.isKnown(result));
if (latest && result === latest.result) {
return true;
}
}
return false;
};
StoreReader.prototype.execSelectionSetImpl = function (_a) {
var _this = this;
var selectionSet = _a.selectionSet, objectOrReference = _a.objectOrReference, enclosingRef = _a.enclosingRef, context = _a.context;
if (utilities.isReference(objectOrReference) &&
!context.policies.rootTypenamesById[objectOrReference.__ref] &&
!context.store.has(objectOrReference.__ref)) {
return {
result: this.canon.empty,
missing: "Dangling reference to missing ".concat(objectOrReference.__ref, " object"),
};
}
var variables = context.variables, policies = context.policies, store = context.store;
var typename = store.getFieldValue(objectOrReference, "__typename");
var objectsToMerge = [];
var missing;
var missingMerger = new utilities.DeepMerger();
if (this.config.addTypename &&
typeof typename === "string" &&
!policies.rootIdsByTypename[typename]) {
objectsToMerge.push({ __typename: typename });
}
function handleMissing(result, resultName) {
var _a;
if (result.missing) {
missing = missingMerger.merge(missing, (_a = {}, _a[resultName] = result.missing, _a));
}
return result.result;
}
var workSet = new Set(selectionSet.selections);
workSet.forEach(function (selection) {
var _a, _b;
if (!utilities.shouldInclude(selection, variables))
return;
if (utilities.isField(selection)) {
var fieldValue = policies.readField({
fieldName: selection.name.value,
field: selection,
variables: context.variables,
from: objectOrReference,
}, context);
var resultName = utilities.resultKeyNameFromField(selection);
if (fieldValue === void 0) {
if (!utilities.addTypenameToDocument.added(selection)) {
missing = missingMerger.merge(missing, (_a = {},
_a[resultName] = "Can't find field '".concat(selection.name.value, "' on ").concat(utilities.isReference(objectOrReference)
? objectOrReference.__ref + " object"
: "object " + JSON.stringify(objectOrReference, null, 2)),
_a));
}
}
else if (utilities.isArray(fieldValue)) {
fieldValue = handleMissing(_this.executeSubSelectedArray({
field: selection,
array: fieldValue,
enclosingRef: enclosingRef,
context: context,
}), resultName);
}
else if (!selection.selectionSet) {
if (context.canonizeResults) {
fieldValue = _this.canon.pass(fieldValue);
}
}
else if (fieldValue != null) {
fieldValue = handleMissing(_this.executeSelectionSet({
selectionSet: selection.selectionSet,
objectOrReference: fieldValue,
enclosingRef: utilities.isReference(fieldValue) ? fieldValue : enclosingRef,
context: context,
}), resultName);
}
if (fieldValue !== void 0) {
objectsToMerge.push((_b = {}, _b[resultName] = fieldValue, _b));
}
}
else {
var fragment = utilities.getFragmentFromSelection(selection, context.lookupFragment);
if (!fragment && selection.kind === graphql.Kind.FRAGMENT_SPREAD) {
throw __DEV__ ? new globals.InvariantError("No fragment named ".concat(selection.name.value)) : new globals.InvariantError(5);
}
if (fragment && policies.fragmentMatches(fragment, typename)) {
fragment.selectionSet.selections.forEach(workSet.add, workSet);
}
}
});
var result = utilities.mergeDeepArray(objectsToMerge);
var finalResult = { result: result, missing: missing };
var frozen = context.canonizeResults
? this.canon.admit(finalResult)
: utilities.maybeDeepFreeze(finalResult);
if (frozen.result) {
this.knownResults.set(frozen.result, selectionSet);
}
return frozen;
};
StoreReader.prototype.execSubSelectedArrayImpl = function (_a) {
var _this = this;
var field = _a.field, array = _a.array, enclosingRef = _a.enclosingRef, context = _a.context;
var missing;
var missingMerger = new utilities.DeepMerger();
function handleMissing(childResult, i) {
var _a;
if (childResult.missing) {
missing = missingMerger.merge(missing, (_a = {}, _a[i] = childResult.missing, _a));
}
return childResult.result;
}
if (field.selectionSet) {
array = array.filter(context.store.canRead);
}
array = array.map(function (item, i) {
if (item === null) {
return null;
}
if (utilities.isArray(item)) {
return handleMissing(_this.executeSubSelectedArray({
field: field,
array: item,
enclosingRef: enclosingRef,
context: context,
}), i);
}
if (field.selectionSet) {
return handleMissing(_this.executeSelectionSet({
selectionSet: field.selectionSet,
objectOrReference: item,
enclosingRef: utilities.isReference(item) ? item : enclosingRef,
context: context,
}), i);
}
if (__DEV__) {
assertSelectionSetForIdValue(context.store, field, item);
}
return item;
});
return {
result: context.canonizeResults ? this.canon.admit(array) : array,
missing: missing,
};
};
return StoreReader;
}());
function firstMissing(tree) {
try {
JSON.stringify(tree, function (_, value) {
if (typeof value === "string")
throw value;
return value;
});
}
catch (result) {
return result;
}
}
function assertSelectionSetForIdValue(store, field, fieldValue) {
if (!field.selectionSet) {
var workSet_1 = new Set([fieldValue]);
workSet_1.forEach(function (value) {
if (utilities.isNonNullObject(value)) {
__DEV__ ? globals.invariant(!utilities.isReference(value), "Missing selection set for object of type ".concat(getTypenameFromStoreObject(store, value), " returned for query field ").concat(field.name.value)) : globals.invariant(!utilities.isReference(value), 6);
Object.values(value).forEach(workSet_1.add, workSet_1);
}
});
}
}
var cacheSlot = new context.Slot();
var cacheInfoMap = new WeakMap();
function getCacheInfo(cache) {
var info = cacheInfoMap.get(cache);
if (!info) {
cacheInfoMap.set(cache, info = {
vars: new Set,
dep: optimism.dep(),
});
}
return info;
}
function forgetCache(cache) {
getCacheInfo(cache).vars.forEach(function (rv) { return rv.forgetCache(cache); });
}
function recallCache(cache) {
getCacheInfo(cache).vars.forEach(function (rv) { return rv.attachCache(cache); });
}
function makeVar(value) {
var caches = new Set();
var listeners = new Set();
var rv = function (newValue) {
if (arguments.length > 0) {
if (value !== newValue) {
value = newValue;
caches.forEach(function (cache) {
getCacheInfo(cache).dep.dirty(rv);
broadcast(cache);
});
var oldListeners = Array.from(listeners);
listeners.clear();
oldListeners.forEach(function (listener) { return listener(value); });
}
}
else {
var cache = cacheSlot.getValue();
if (cache) {
attach(cache);
getCacheInfo(cache).dep(rv);
}
}
return value;
};
rv.onNextChange = function (listener) {
listeners.add(listener);
return function () {
listeners.delete(listener);
};
};
var attach = rv.attachCache = function (cache) {
caches.add(cache);
getCacheInfo(cache).vars.add(rv);
return rv;
};
rv.forgetCache = function (cache) { return caches.delete(cache); };
return rv;
}
function broadcast(cache) {
if (cache.broadcastWatches) {
cache.broadcastWatches();
}
}
var specifierInfoCache = Object.create(null);
function lookupSpecifierInfo(spec) {
var cacheKey = JSON.stringify(spec);
return specifierInfoCache[cacheKey] ||
(specifierInfoCache[cacheKey] = Object.create(null));
}
function keyFieldsFnFromSpecifier(specifier) {
var info = lookupSpecifierInfo(specifier);
return info.keyFieldsFn || (info.keyFieldsFn = function (object, context) {
var extract = function (from, key) { return context.readField(key, from); };
var keyObject = context.keyObject = collectSpecifierPaths(specifier, function (schemaKeyPath) {
var extracted = extractKeyPath(context.storeObject, schemaKeyPath, extract);
if (extracted === void 0 &&
object !== context.storeObject &&
hasOwn.call(object, schemaKeyPath[0])) {
extracted = extractKeyPath(object, schemaKeyPath, extractKey);
}
__DEV__ ? globals.invariant(extracted !== void 0, "Missing field '".concat(schemaKeyPath.join('.'), "' while extracting keyFields from ").concat(JSON.stringify(object))) : globals.invariant(extracted !== void 0, 2);
return extracted;
});
return "".concat(context.typename, ":").concat(JSON.stringify(keyObject));
});
}
function keyArgsFnFromSpecifier(specifier) {
var info = lookupSpecifierInfo(specifier);
return info.keyArgsFn || (info.keyArgsFn = function (args, _a) {
var field = _a.field, variables = _a.variables, fieldName = _a.fieldName;
var collected = collectSpecifierPaths(specifier, function (keyPath) {
var firstKey = keyPath[0];
var firstChar = firstKey.charAt(0);
if (firstChar === "@") {
if (field && utilities.isNonEmptyArray(field.directives)) {
var directiveName_1 = firstKey.slice(1);
var d = field.directives.find(function (d) { return d.name.value === directiveName_1; });
var directiveArgs = d && utilities.argumentsObjectFromField(d, variables);
return directiveArgs && extractKeyPath(directiveArgs, keyPath.slice(1));
}
return;
}
if (firstChar === "$") {
var variableName = firstKey.slice(1);
if (variables && hasOwn.call(variables, variableName)) {
var varKeyPath = keyPath.slice(0);
varKeyPath[0] = variableName;
return extractKeyPath(variables, varKeyPath);
}
return;
}
if (args) {
return extractKeyPath(args, keyPath);
}
});
var suffix = JSON.stringify(collected);
if (args || suffix !== "{}") {
fieldName += ":" + suffix;
}
return fieldName;
});
}
function collectSpecifierPaths(specifier, extractor) {
var merger = new utilities.DeepMerger;
return getSpecifierPaths(specifier).reduce(function (collected, path) {
var _a;
var toMerge = extractor(path);
if (toMerge !== void 0) {
for (var i = path.length - 1; i >= 0; --i) {
toMerge = (_a = {}, _a[path[i]] = toMerge, _a);
}
collected = merger.merge(collected, toMerge);
}
return collected;
}, Object.create(null));
}
function getSpecifierPaths(spec) {
var info = lookupSpecifierInfo(spec);
if (!info.paths) {
var paths_1 = info.paths = [];
var currentPath_1 = [];
spec.forEach(function (s, i) {
if (utilities.isArray(s)) {
getSpecifierPaths(s).forEach(function (p) { return paths_1.push(currentPath_1.concat(p)); });
currentPath_1.length = 0;
}
else {
currentPath_1.push(s);
if (!utilities.isArray(spec[i + 1])) {
paths_1.push(currentPath_1.slice(0));
currentPath_1.length = 0;
}
}
});
}
return info.paths;
}
function extractKey(object, key) {
return object[key];
}
function extractKeyPath(object, path, extract) {
extract = extract || extractKey;
return normalize(path.reduce(function reducer(obj, key) {
return utilities.isArray(obj)
? obj.map(function (child) { return reducer(child, key); })
: obj && extract(obj, key);
}, object));
}
function normalize(value) {
if (utilities.isNonNullObject(value)) {
if (utilities.isArray(value)) {
return value.map(normalize);
}
return collectSpecifierPaths(Object.keys(value).sort(), function (path) { return extractKeyPath(value, path); });
}
return value;
}
utilities.getStoreKeyName.setStringify(canonicalStringify);
function argsFromFieldSpecifier(spec) {
return spec.args !== void 0 ? spec.args :
spec.field ? utilities.argumentsObjectFromField(spec.field, spec.variables) : null;
}
var nullKeyFieldsFn = function () { return void 0; };
var simpleKeyArgsFn = function (_args, context) { return context.fieldName; };
var mergeTrueFn = function (existing, incoming, _a) {
var mergeObjects = _a.mergeObjects;
return mergeObjects(existing, incoming);
};
var mergeFalseFn = function (_, incoming) { return incoming; };
var Policies = (function () {
function Policies(config) {
this.config = config;
this.typePolicies = Object.create(null);
this.toBeAdded = Object.create(null);
this.supertypeMap = new Map();
this.fuzzySubtypes = new Map();
this.rootIdsByTypename = Object.create(null);
this.rootTypenamesById = Object.cre