Socket
Socket
Sign inDemoInstall

apollo-cache-inmemory

Package Overview
Dependencies
Maintainers
4
Versions
149
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-cache-inmemory - npm Package Compare versions

Comparing version 1.3.9 to 1.4.0-alpha.1

370

lib/bundle.umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('apollo-utilities'), require('graphql/language/visitor'), require('graphql/language/printer'), require('apollo-cache')) :
typeof define === 'function' && define.amd ? define(['exports', 'apollo-utilities', 'graphql/language/visitor', 'graphql/language/printer', 'apollo-cache'], factory) :
(factory((global.apollo = global.apollo || {}, global.apollo.cache = global.apollo.cache || {}, global.apollo.cache.inmemory = {}),global.apollo.utilities,global.visitor,global.print,global.apolloCache.core));
}(this, (function (exports,apolloUtilities,visitor,printer,apolloCache) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('apollo-utilities'), require('graphql/language/printer'), require('apollo-cache')) :
typeof define === 'function' && define.amd ? define(['exports', 'apollo-utilities', 'graphql/language/printer', 'apollo-cache'], factory) :
(factory((global.apollo = global.apollo || {}, global.apollo.cache = global.apollo.cache || {}, global.apollo.cache.inmemory = {}),global.apollo.utilities,global.print,global.apolloCache.core));
}(this, (function (exports,apolloUtilities,printer,apolloCache) { 'use strict';
var testMap = new Map();
if (testMap.set(1, 2) !== testMap) {
var set_1 = testMap.set;
Map.prototype.set = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
set_1.apply(this, args);
return this;
};
}
var testSet = new Set();
if (testSet.add(3) !== testSet) {
var add_1 = testSet.add;
Set.prototype.add = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
add_1.apply(this, args);
return this;
};
}
var frozen = {};
if (typeof Object.freeze === 'function') {
Object.freeze(frozen);
}
try {
testMap.set(frozen, frozen).delete(frozen);
}
catch (_a) {
var wrap = function (method) {
return method && (function (obj) {
try {
testMap.set(obj, obj).delete(obj);
}
finally {
return method.call(Object, obj);
}
});
};
Object.freeze = wrap(Object.freeze);
Object.seal = wrap(Object.seal);
Object.preventExtensions = wrap(Object.preventExtensions);
}
var haveWarned = false;

@@ -139,3 +92,3 @@ var HeuristicFragmentMatcher = (function () {

var wrap$1 = require('optimism').wrap;
var wrap = require('optimism').wrap;
var CacheKeyNode = (function () {

@@ -161,8 +114,4 @@ function CacheKeyNode() {

CacheKeyNode.prototype.getOrCreate = function (value) {
var map = this.children || (this.children = new Map());
var node = map.get(value);
if (!node) {
map.set(value, node = new CacheKeyNode());
}
return node;
var map = this.children || (this.children = new Map);
return map.get(value) || map.set(value, new CacheKeyNode()).get(value);
};

@@ -178,3 +127,3 @@ return CacheKeyNode;

this.data = data;
this.depend = wrap$1(function (dataId) { return _this.data[dataId]; }, {
this.depend = wrap(function (dataId) { return _this.data[dataId]; }, {
disposable: true,

@@ -245,3 +194,2 @@ makeCacheKey: function (dataId) {

var CIRCULAR = Object.create(null);
var objToStr = Object.prototype.toString;
var QueryKeyMaker = (function () {

@@ -323,38 +271,16 @@ function QueryKeyMaker(cacheKeyRoot) {

var elements = array.map(this.lookupAny, this);
return this.cacheKeyRoot.lookup(objToStr.call(array), this.cacheKeyRoot.lookupArray(elements));
return this.cacheKeyRoot.lookup(Array.prototype, this.cacheKeyRoot.lookupArray(elements));
};
PerQueryKeyMaker.prototype.lookupObject = function (object) {
var _this = this;
var keys = safeSortedKeys(object);
var keys = Object.keys(object);
var locIndex = keys.indexOf("loc");
if (locIndex >= 0)
keys.splice(locIndex, 1);
keys.sort();
var values = keys.map(function (key) { return _this.lookupAny(object[key]); });
return this.cacheKeyRoot.lookup(objToStr.call(object), this.cacheKeyRoot.lookupArray(keys), this.cacheKeyRoot.lookupArray(values));
return this.cacheKeyRoot.lookup(Object.getPrototypeOf(object), this.cacheKeyRoot.lookupArray(keys), this.cacheKeyRoot.lookupArray(values));
};
return PerQueryKeyMaker;
}());
var queryKeyMap = Object.create(null);
Object.keys(visitor.QueryDocumentKeys).forEach(function (parentKind) {
var childKeys = queryKeyMap[parentKind] = Object.create(null);
visitor.QueryDocumentKeys[parentKind].forEach(function (childKey) {
childKeys[childKey] = true;
});
if (parentKind === "FragmentSpread") {
childKeys["fragment"] = true;
}
});
function safeSortedKeys(object) {
var keys = Object.keys(object);
var keyCount = keys.length;
var knownKeys = typeof object.kind === "string" && queryKeyMap[object.kind];
var target = 0;
for (var source = target; source < keyCount; ++source) {
var key = keys[source];
var value = object[key];
var isObjectOrArray = value !== null && typeof value === "object";
if (!isObjectOrArray || !knownKeys || knownKeys[key] === true) {
keys[target++] = key;
}
}
keys.length = target;
return keys.sort();
}

@@ -373,21 +299,21 @@ var __assign$1 = (undefined && undefined.__assign) || function () {

var StoreReader = (function () {
function StoreReader(cacheKeyRoot) {
if (cacheKeyRoot === void 0) { cacheKeyRoot = new CacheKeyNode; }
var _this = this;
this.cacheKeyRoot = cacheKeyRoot;
function StoreReader(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.addTypename, addTypename = _c === void 0 ? false : _c, _d = _b.cacheKeyRoot, cacheKeyRoot = _d === void 0 ? new CacheKeyNode : _d;
var reader = this;
var executeStoreQuery = reader.executeStoreQuery, executeSelectionSet = reader.executeSelectionSet;
reader.addTypename = addTypename;
reader.cacheKeyRoot = cacheKeyRoot;
reader.keyMaker = new QueryKeyMaker(cacheKeyRoot);
this.executeStoreQuery = wrap$1(function (options) {
return executeStoreQuery.call(_this, options);
this.executeStoreQuery = wrap(function (options) {
return executeStoreQuery.call(reader, options);
}, {
makeCacheKey: function (_a) {
var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, fragmentMatcher = _a.fragmentMatcher;
var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues;
if (contextValue.store instanceof DepTrackingCache) {
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(query).lookupQuery(query), contextValue.store, fragmentMatcher, JSON.stringify(variableValues), rootValue.id);
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(query).lookupQuery(query), contextValue.store, JSON.stringify(variableValues));
}
}
});
this.executeSelectionSet = wrap$1(function (options) {
return executeSelectionSet.call(_this, options);
this.executeSelectionSet = wrap(function (options) {
return executeSelectionSet.call(reader, options);
}, {

@@ -397,3 +323,3 @@ makeCacheKey: function (_a) {

if (execContext.contextValue.store instanceof DepTrackingCache) {
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(execContext.query).lookupSelectionSet(selectionSet), execContext.contextValue.store, execContext.fragmentMatcher, JSON.stringify(execContext.variableValues), rootValue.id);
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(execContext.query).lookupSelectionSet(selectionSet), execContext.contextValue.store, JSON.stringify(execContext.variableValues), rootValue.id);
}

@@ -433,3 +359,3 @@ }

return;
throw new Error("Can't find field " + info.fieldName + " on object " + JSON.stringify(info.object, null, 2) + ".");
throw new Error("Can't find field " + info.fieldName + " on object (" + info.objectId + ") " + JSON.stringify(store.get(info.objectId), null, 2) + ".");
});

@@ -448,3 +374,3 @@ }

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 query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, _b = _a.fragmentMatcher, fragmentMatcher = _b === void 0 ? function () { return true; } : _b;
var mainDefinition = apolloUtilities.getMainDefinition(query);

@@ -464,2 +390,3 @@ var fragments = apolloUtilities.getFragmentDefinitions(query);

execContext: execContext,
parentKind: mainDefinition.kind,
});

@@ -469,3 +396,3 @@ };

var _this = this;
var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext;
var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext, parentKind = _a.parentKind;
var fragmentMap = execContext.fragmentMap, contextValue = execContext.contextValue, variables = execContext.variableValues;

@@ -475,7 +402,3 @@ var finalResult = {

};
var objectsToMerge = [];
var object = contextValue.store.get(rootValue.id);
var typename = (object && object.__typename) ||
(rootValue.id === 'ROOT_QUERY' && 'Query') ||
void 0;
var didReadTypename = false;
function handleMissing(result) {

@@ -489,3 +412,3 @@ var _a;

}
selectionSet.selections.forEach(function (selection) {
var handleSelection = function (selection) {
var _a;

@@ -496,6 +419,10 @@ if (!apolloUtilities.shouldInclude(selection, variables)) {

if (apolloUtilities.isField(selection)) {
var fieldResult = handleMissing(_this.executeField(object, typename, selection, execContext));
var fieldResult = handleMissing(_this.executeField(selection, rootValue, execContext));
var keyName = apolloUtilities.resultKeyNameFromField(selection);
if (keyName === "__typename") {
didReadTypename = true;
}
if (typeof fieldResult !== 'undefined') {
objectsToMerge.push((_a = {},
_a[apolloUtilities.resultKeyNameFromField(selection)] = fieldResult,
merge(finalResult.result, (_a = {},
_a[keyName] = fieldResult,
_a));

@@ -522,2 +449,3 @@ }

execContext: execContext,
parentKind: fragment.kind,
});

@@ -529,10 +457,21 @@ if (match === 'heuristic' && fragmentExecResult.missing) {

}
objectsToMerge.push(handleMissing(fragmentExecResult));
merge(finalResult.result, handleMissing(fragmentExecResult));
}
}
});
merge(finalResult.result, objectsToMerge);
};
selectionSet.selections.forEach(handleSelection);
if (!didReadTypename &&
this.addTypename &&
parentKind !== "OperationDefinition") {
handleSelection({
kind: "Field",
name: {
kind: "Name",
value: "__typename",
},
});
}
return finalResult;
};
StoreReader.prototype.executeField = function (object, typename, field, execContext) {
StoreReader.prototype.executeField = function (field, rootValue, execContext) {
var variables = execContext.variableValues, contextValue = execContext.contextValue;

@@ -545,8 +484,4 @@ var fieldName = field.name.value;

};
var readStoreResult = readStoreResolver(object, typename, fieldName, args, contextValue, info);
if (Array.isArray(readStoreResult.result)) {
return this.combineExecResults(readStoreResult, this.executeSubSelectedArray(field, readStoreResult.result, execContext));
}
var readStoreResult = readStoreResolver(fieldName, rootValue, args, contextValue, info);
if (!field.selectionSet) {
assertSelectionSetForIdValue(field, readStoreResult.result);
return readStoreResult;

@@ -557,25 +492,27 @@ }

}
return this.combineExecResults(readStoreResult, this.executeSelectionSet({
function handleMissing(res) {
var missing = null;
if (readStoreResult.missing) {
missing = missing || [];
missing.push.apply(missing, readStoreResult.missing);
}
if (res.missing) {
missing = missing || [];
missing.push.apply(missing, res.missing);
}
return {
result: res.result,
missing: missing,
};
}
if (Array.isArray(readStoreResult.result)) {
return handleMissing(this.executeSubSelectedArray(field, readStoreResult.result, execContext));
}
return handleMissing(this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: readStoreResult.result,
execContext: execContext,
parentKind: field.kind,
}));
};
StoreReader.prototype.combineExecResults = function () {
var execResults = [];
for (var _i = 0; _i < arguments.length; _i++) {
execResults[_i] = arguments[_i];
}
var missing = null;
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 (field, result, execContext) {

@@ -598,11 +535,8 @@ var _this = this;

}
if (field.selectionSet) {
return handleMissing(_this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext: execContext,
}));
}
assertSelectionSetForIdValue(field, item);
return item;
return handleMissing(_this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext: execContext,
parentKind: field.kind,
}));
});

@@ -613,10 +547,2 @@ return { result: result, missing: missing };

}());
function assertSelectionSetForIdValue(field, value) {
if (!field.selectionSet && apolloUtilities.isIdValue(value)) {
throw new Error("Missing selection set for object of type " + value.typename + " returned for query field " + field.name.value);
}
}
function defaultFragmentMatcher() {
return true;
}
function assertIdValue(idValue) {

@@ -627,4 +553,7 @@ if (!apolloUtilities.isIdValue(idValue)) {

}
function readStoreResolver(object, typename, fieldName, args, context, _a) {
function readStoreResolver(fieldName, idValue, args, context, _a) {
var resultKey = _a.resultKey, directives = _a.directives;
assertIdValue(idValue);
var objId = idValue.id;
var obj = context.store.get(objId);
var storeKeyName = fieldName;

@@ -635,7 +564,8 @@ if (args || directives) {

var fieldValue = void 0;
if (object) {
fieldValue = object[storeKeyName];
if (obj) {
fieldValue = obj[storeKeyName];
if (typeof fieldValue === 'undefined' &&
context.cacheRedirects &&
typeof typename === 'string') {
(obj.__typename || objId === 'ROOT_QUERY')) {
var typename = obj.__typename || 'Query';
var type = context.cacheRedirects[typename];

@@ -645,3 +575,3 @@ if (type) {

if (resolver) {
fieldValue = resolver(object, args, {
fieldValue = resolver(obj, args, {
getCacheKey: function (storeObj) {

@@ -662,3 +592,3 @@ return apolloUtilities.toIdValue({

missing: [{
object: object,
objectId: objId,
fieldName: storeKeyName,

@@ -677,24 +607,15 @@ tolerable: false,

var hasOwn$1 = Object.prototype.hasOwnProperty;
function merge(target, sources) {
var pastCopies = [];
sources.forEach(function (source) {
mergeHelper(target, source, pastCopies);
});
return target;
}
function mergeHelper(target, source, pastCopies) {
if (source !== null && typeof source === 'object') {
function merge(target, source) {
if (source !== null && typeof source === 'object' &&
source !== target) {
if (Object.isExtensible && !Object.isExtensible(target)) {
target = shallowCopyForMerge(target, pastCopies);
target = __assign$1({}, target);
}
Object.keys(source).forEach(function (sourceKey) {
var sourceValue = source[sourceKey];
if (hasOwn$1.call(target, sourceKey)) {
var targetValue = target[sourceKey];
if (sourceValue !== targetValue) {
target[sourceKey] = mergeHelper(shallowCopyForMerge(targetValue, pastCopies), sourceValue, pastCopies);
}
var sourceVal = source[sourceKey];
if (!hasOwn$1.call(target, sourceKey)) {
target[sourceKey] = sourceVal;
}
else {
target[sourceKey] = sourceValue;
target[sourceKey] = merge(target[sourceKey], sourceVal);
}

@@ -705,16 +626,2 @@ });

}
function shallowCopyForMerge(value, pastCopies) {
if (value !== null &&
typeof value === 'object' &&
pastCopies.indexOf(value) < 0) {
if (Array.isArray(value)) {
value = value.slice(0);
}
else {
value = __assign$1({}, value);
}
pastCopies.push(value);
}
return value;
}

@@ -789,4 +696,13 @@ var ObjectCache = (function () {

}
var TYPENAME_FIELD = {
kind: 'Field',
name: {
kind: 'Name',
value: '__typename',
},
};
var StoreWriter = (function () {
function StoreWriter() {
function StoreWriter(_a) {
var _b = (_a === void 0 ? {} : _a).addTypename, addTypename = _b === void 0 ? false : _b;
this.addTypename = addTypename;
}

@@ -821,2 +737,3 @@ StoreWriter.prototype.writeQueryToStore = function (_a) {

},
parentKind: operationDefinition.kind,
});

@@ -830,4 +747,5 @@ }

var _this = this;
var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context, parentKind = _a.parentKind;
var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;
var didWriteTypename = false;
selectionSet.selections.forEach(function (selection) {

@@ -840,2 +758,5 @@ if (!apolloUtilities.shouldInclude(selection, variables)) {

var value = result[resultFieldKey];
if (resultFieldKey === "__typename") {
didWriteTypename = true;
}
if (typeof value !== 'undefined') {

@@ -890,2 +811,3 @@ _this.writeFieldToStore({

context: context,
parentKind: fragment.kind,
});

@@ -895,2 +817,13 @@ }

});
if (!didWriteTypename &&
this.addTypename &&
parentKind !== "OperationDefinition" &&
typeof result.__typename === "string") {
this.writeFieldToStore({
dataId: dataId,
value: result.__typename,
field: TYPENAME_FIELD,
context: context,
});
}
return store;

@@ -915,3 +848,3 @@ };

var generatedId = dataId + "." + storeFieldName;
storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context);
storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context, field.kind);
}

@@ -941,2 +874,3 @@ else {

context: context,
parentKind: field.kind,
});

@@ -981,3 +915,3 @@ }

};
StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context) {
StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context, parentKind) {
var _this = this;

@@ -990,3 +924,3 @@ return value.map(function (item, index) {

if (Array.isArray(item)) {
return _this.processArrayValue(item, itemDataId, selectionSet, context);
return _this.processArrayValue(item, itemDataId, selectionSet, context, parentKind);
}

@@ -1007,2 +941,3 @@ var generated = true;

context: context,
parentKind: parentKind,
});

@@ -1179,7 +1114,12 @@ }

_this.data = defaultNormalizedCacheFactory();
_this.storeReader = new StoreReader(_this.cacheKeyRoot);
_this.storeWriter = new StoreWriter();
_this.storeReader = new StoreReader({
addTypename: _this.config.addTypename,
cacheKeyRoot: _this.cacheKeyRoot,
});
_this.storeWriter = new StoreWriter({
addTypename: _this.config.addTypename,
});
var cache = _this;
var maybeBroadcastWatch = cache.maybeBroadcastWatch;
_this.maybeBroadcastWatch = wrap$1(function (c) {
_this.maybeBroadcastWatch = wrap(function (c) {
return maybeBroadcastWatch.call(_this, c);

@@ -1223,3 +1163,3 @@ }, {

store: store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -1237,3 +1177,3 @@ rootId: query.rootId,

variables: write.variables,
document: this.transformDocument(write.query),
document: write.query,
store: this.data,

@@ -1251,3 +1191,3 @@ dataIdFromObject: this.config.dataIdFromObject,

store: store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -1314,5 +1254,3 @@ returnPartialData: query.returnPartialData,

if (!result) {
result = apolloUtilities.addTypenameToDocument(document);
this.typenameDocumentCache.set(document, result);
this.typenameDocumentCache.set(result, result);
this.typenameDocumentCache.set(document, (result = apolloUtilities.addTypenameToDocument(document)));
}

@@ -1334,3 +1272,3 @@ return result;

return this.read({
query: this.transformDocument(apolloUtilities.getFragmentQueryDocument(options.fragment, options.fragmentName)),
query: apolloUtilities.getFragmentQueryDocument(options.fragment, options.fragmentName),
variables: options.variables,

@@ -1345,3 +1283,3 @@ rootId: options.id,

result: options.data,
query: this.transformDocument(options.query),
query: options.query,
variables: options.variables,

@@ -1354,3 +1292,3 @@ });

result: options.data,
query: this.transformDocument(apolloUtilities.getFragmentQueryDocument(options.fragment, options.fragmentName)),
query: apolloUtilities.getFragmentQueryDocument(options.fragment, options.fragmentName),
variables: options.variables,

@@ -1372,8 +1310,14 @@ });

InMemoryCache.prototype.maybeBroadcastWatch = function (c) {
c.callback(this.diff({
var previousResult = c.previousResult && c.previousResult();
var newData = this.diff({
query: c.query,
variables: c.variables,
previousResult: c.previousResult && c.previousResult(),
previousResult: previousResult,
optimistic: c.optimistic,
}));
});
if (previousResult &&
previousResult === newData.result) {
return;
}
c.callback(newData);
};

@@ -1380,0 +1324,0 @@ return InMemoryCache;

@@ -1,2 +0,1 @@

import './fixPolyfills';
import { DocumentNode } from 'graphql';

@@ -3,0 +2,0 @@ import { Cache, DataProxy, ApolloCache, Transaction } from 'apollo-cache';

@@ -25,3 +25,2 @@ var __extends = (this && this.__extends) || (function () {

};
import './fixPolyfills';
import { ApolloCache } from 'apollo-cache';

@@ -72,4 +71,9 @@ import { getFragmentQueryDocument, addTypenameToDocument, } from 'apollo-utilities';

_this.data = defaultNormalizedCacheFactory();
_this.storeReader = new StoreReader(_this.cacheKeyRoot);
_this.storeWriter = new StoreWriter();
_this.storeReader = new StoreReader({
addTypename: _this.config.addTypename,
cacheKeyRoot: _this.cacheKeyRoot,
});
_this.storeWriter = new StoreWriter({
addTypename: _this.config.addTypename,
});
var cache = _this;

@@ -116,3 +120,3 @@ var maybeBroadcastWatch = cache.maybeBroadcastWatch;

store: store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -130,3 +134,3 @@ rootId: query.rootId,

variables: write.variables,
document: this.transformDocument(write.query),
document: write.query,
store: this.data,

@@ -144,3 +148,3 @@ dataIdFromObject: this.config.dataIdFromObject,

store: store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -207,5 +211,3 @@ returnPartialData: query.returnPartialData,

if (!result) {
result = addTypenameToDocument(document);
this.typenameDocumentCache.set(document, result);
this.typenameDocumentCache.set(result, result);
this.typenameDocumentCache.set(document, (result = addTypenameToDocument(document)));
}

@@ -227,3 +229,3 @@ return result;

return this.read({
query: this.transformDocument(getFragmentQueryDocument(options.fragment, options.fragmentName)),
query: getFragmentQueryDocument(options.fragment, options.fragmentName),
variables: options.variables,

@@ -238,3 +240,3 @@ rootId: options.id,

result: options.data,
query: this.transformDocument(options.query),
query: options.query,
variables: options.variables,

@@ -247,3 +249,3 @@ });

result: options.data,
query: this.transformDocument(getFragmentQueryDocument(options.fragment, options.fragmentName)),
query: getFragmentQueryDocument(options.fragment, options.fragmentName),
variables: options.variables,

@@ -265,8 +267,14 @@ });

InMemoryCache.prototype.maybeBroadcastWatch = function (c) {
c.callback(this.diff({
var previousResult = c.previousResult && c.previousResult();
var newData = this.diff({
query: c.query,
variables: c.variables,
previousResult: c.previousResult && c.previousResult(),
previousResult: previousResult,
optimistic: c.optimistic,
}));
});
if (previousResult &&
previousResult === newData.result) {
return;
}
c.callback(newData);
};

@@ -273,0 +281,0 @@ return InMemoryCache;

@@ -23,8 +23,4 @@ var wrap = require('optimism').wrap;

CacheKeyNode.prototype.getOrCreate = function (value) {
var map = this.children || (this.children = new Map());
var node = map.get(value);
if (!node) {
map.set(value, node = new CacheKeyNode());
}
return node;
var map = this.children || (this.children = new Map);
return map.get(value) || map.set(value, new CacheKeyNode()).get(value);
};

@@ -31,0 +27,0 @@ return CacheKeyNode;

@@ -12,5 +12,3 @@ var __assign = (this && this.__assign) || function () {

};
import { QueryDocumentKeys } from "graphql/language/visitor";
var CIRCULAR = Object.create(null);
var objToStr = Object.prototype.toString;
var QueryKeyMaker = (function () {

@@ -93,38 +91,16 @@ function QueryKeyMaker(cacheKeyRoot) {

var elements = array.map(this.lookupAny, this);
return this.cacheKeyRoot.lookup(objToStr.call(array), this.cacheKeyRoot.lookupArray(elements));
return this.cacheKeyRoot.lookup(Array.prototype, this.cacheKeyRoot.lookupArray(elements));
};
PerQueryKeyMaker.prototype.lookupObject = function (object) {
var _this = this;
var keys = safeSortedKeys(object);
var keys = Object.keys(object);
var locIndex = keys.indexOf("loc");
if (locIndex >= 0)
keys.splice(locIndex, 1);
keys.sort();
var values = keys.map(function (key) { return _this.lookupAny(object[key]); });
return this.cacheKeyRoot.lookup(objToStr.call(object), this.cacheKeyRoot.lookupArray(keys), this.cacheKeyRoot.lookupArray(values));
return this.cacheKeyRoot.lookup(Object.getPrototypeOf(object), this.cacheKeyRoot.lookupArray(keys), this.cacheKeyRoot.lookupArray(values));
};
return PerQueryKeyMaker;
}());
var queryKeyMap = Object.create(null);
Object.keys(QueryDocumentKeys).forEach(function (parentKind) {
var childKeys = queryKeyMap[parentKind] = Object.create(null);
QueryDocumentKeys[parentKind].forEach(function (childKey) {
childKeys[childKey] = true;
});
if (parentKind === "FragmentSpread") {
childKeys["fragment"] = true;
}
});
function safeSortedKeys(object) {
var keys = Object.keys(object);
var keyCount = keys.length;
var knownKeys = typeof object.kind === "string" && queryKeyMap[object.kind];
var target = 0;
for (var source = target; source < keyCount; ++source) {
var key = keys[source];
var value = object[key];
var isObjectOrArray = value !== null && typeof value === "object";
if (!isObjectOrArray || !knownKeys || knownKeys[key] === true) {
keys[target++] = key;
}
}
keys.length = target;
return keys.sort();
}
//# sourceMappingURL=queryKeyMaker.js.map
import { IdValue } from 'apollo-utilities';
import { Cache } from 'apollo-cache';
import { ReadStoreContext, DiffQueryAgainstStoreOptions, ReadQueryOptions, StoreObject } from './types';
import { ReadStoreContext, DiffQueryAgainstStoreOptions, ReadQueryOptions } from './types';
import { CacheKeyNode } from './optimism';

@@ -11,3 +11,3 @@ export { OptimisticWrapperFunction } from './optimism';

export declare type ExecResultMissingField = {
object: StoreObject;
objectId: string;
fieldName: string;

@@ -20,6 +20,11 @@ tolerable: boolean;

};
declare type StoreReaderOptions = {
addTypename?: boolean;
cacheKeyRoot?: CacheKeyNode;
};
export declare class StoreReader {
private addTypename;
private cacheKeyRoot;
private keyMaker;
constructor(cacheKeyRoot?: CacheKeyNode<object>);
constructor({ addTypename, cacheKeyRoot, }?: StoreReaderOptions);
readQueryFromStore<QueryType>(options: ReadQueryOptions): QueryType;

@@ -30,3 +35,2 @@ diffQueryAgainstStore<T>({ store, query, variables, previousResult, returnPartialData, rootId, fragmentMatcherFunction, config, }: DiffQueryAgainstStoreOptions): Cache.DiffResult<T>;

private executeField;
private combineExecResults;
private executeSubSelectedArray;

@@ -33,0 +37,0 @@ }

@@ -17,16 +17,16 @@ var __assign = (this && this.__assign) || function () {

var StoreReader = (function () {
function StoreReader(cacheKeyRoot) {
if (cacheKeyRoot === void 0) { cacheKeyRoot = new CacheKeyNode; }
var _this = this;
this.cacheKeyRoot = cacheKeyRoot;
function StoreReader(_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.addTypename, addTypename = _c === void 0 ? false : _c, _d = _b.cacheKeyRoot, cacheKeyRoot = _d === void 0 ? new CacheKeyNode : _d;
var reader = this;
var executeStoreQuery = reader.executeStoreQuery, executeSelectionSet = reader.executeSelectionSet;
reader.addTypename = addTypename;
reader.cacheKeyRoot = cacheKeyRoot;
reader.keyMaker = new QueryKeyMaker(cacheKeyRoot);
this.executeStoreQuery = wrap(function (options) {
return executeStoreQuery.call(_this, options);
return executeStoreQuery.call(reader, options);
}, {
makeCacheKey: function (_a) {
var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, fragmentMatcher = _a.fragmentMatcher;
var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues;
if (contextValue.store instanceof DepTrackingCache) {
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(query).lookupQuery(query), contextValue.store, fragmentMatcher, JSON.stringify(variableValues), rootValue.id);
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(query).lookupQuery(query), contextValue.store, JSON.stringify(variableValues));
}

@@ -36,3 +36,3 @@ }

this.executeSelectionSet = wrap(function (options) {
return executeSelectionSet.call(_this, options);
return executeSelectionSet.call(reader, options);
}, {

@@ -42,3 +42,3 @@ makeCacheKey: function (_a) {

if (execContext.contextValue.store instanceof DepTrackingCache) {
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(execContext.query).lookupSelectionSet(selectionSet), execContext.contextValue.store, execContext.fragmentMatcher, JSON.stringify(execContext.variableValues), rootValue.id);
return reader.cacheKeyRoot.lookup(reader.keyMaker.forQuery(execContext.query).lookupSelectionSet(selectionSet), execContext.contextValue.store, JSON.stringify(execContext.variableValues), rootValue.id);
}

@@ -78,3 +78,3 @@ }

return;
throw new Error("Can't find field " + info.fieldName + " on object " + JSON.stringify(info.object, null, 2) + ".");
throw new Error("Can't find field " + info.fieldName + " on object (" + info.objectId + ") " + JSON.stringify(store.get(info.objectId), null, 2) + ".");
});

@@ -93,3 +93,3 @@ }

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 query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, _b = _a.fragmentMatcher, fragmentMatcher = _b === void 0 ? function () { return true; } : _b;
var mainDefinition = getMainDefinition(query);

@@ -109,2 +109,3 @@ var fragments = getFragmentDefinitions(query);

execContext: execContext,
parentKind: mainDefinition.kind,
});

@@ -114,3 +115,3 @@ };

var _this = this;
var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext;
var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext, parentKind = _a.parentKind;
var fragmentMap = execContext.fragmentMap, contextValue = execContext.contextValue, variables = execContext.variableValues;

@@ -120,7 +121,3 @@ var finalResult = {

};
var objectsToMerge = [];
var object = contextValue.store.get(rootValue.id);
var typename = (object && object.__typename) ||
(rootValue.id === 'ROOT_QUERY' && 'Query') ||
void 0;
var didReadTypename = false;
function handleMissing(result) {

@@ -134,3 +131,3 @@ var _a;

}
selectionSet.selections.forEach(function (selection) {
var handleSelection = function (selection) {
var _a;

@@ -141,6 +138,10 @@ if (!shouldInclude(selection, variables)) {

if (isField(selection)) {
var fieldResult = handleMissing(_this.executeField(object, typename, selection, execContext));
var fieldResult = handleMissing(_this.executeField(selection, rootValue, execContext));
var keyName = resultKeyNameFromField(selection);
if (keyName === "__typename") {
didReadTypename = true;
}
if (typeof fieldResult !== 'undefined') {
objectsToMerge.push((_a = {},
_a[resultKeyNameFromField(selection)] = fieldResult,
merge(finalResult.result, (_a = {},
_a[keyName] = fieldResult,
_a));

@@ -167,2 +168,3 @@ }

execContext: execContext,
parentKind: fragment.kind,
});

@@ -174,10 +176,21 @@ if (match === 'heuristic' && fragmentExecResult.missing) {

}
objectsToMerge.push(handleMissing(fragmentExecResult));
merge(finalResult.result, handleMissing(fragmentExecResult));
}
}
});
merge(finalResult.result, objectsToMerge);
};
selectionSet.selections.forEach(handleSelection);
if (!didReadTypename &&
this.addTypename &&
parentKind !== "OperationDefinition") {
handleSelection({
kind: "Field",
name: {
kind: "Name",
value: "__typename",
},
});
}
return finalResult;
};
StoreReader.prototype.executeField = function (object, typename, field, execContext) {
StoreReader.prototype.executeField = function (field, rootValue, execContext) {
var variables = execContext.variableValues, contextValue = execContext.contextValue;

@@ -190,8 +203,4 @@ var fieldName = field.name.value;

};
var readStoreResult = readStoreResolver(object, typename, fieldName, args, contextValue, info);
if (Array.isArray(readStoreResult.result)) {
return this.combineExecResults(readStoreResult, this.executeSubSelectedArray(field, readStoreResult.result, execContext));
}
var readStoreResult = readStoreResolver(fieldName, rootValue, args, contextValue, info);
if (!field.selectionSet) {
assertSelectionSetForIdValue(field, readStoreResult.result);
return readStoreResult;

@@ -202,25 +211,27 @@ }

}
return this.combineExecResults(readStoreResult, this.executeSelectionSet({
function handleMissing(res) {
var missing = null;
if (readStoreResult.missing) {
missing = missing || [];
missing.push.apply(missing, readStoreResult.missing);
}
if (res.missing) {
missing = missing || [];
missing.push.apply(missing, res.missing);
}
return {
result: res.result,
missing: missing,
};
}
if (Array.isArray(readStoreResult.result)) {
return handleMissing(this.executeSubSelectedArray(field, readStoreResult.result, execContext));
}
return handleMissing(this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: readStoreResult.result,
execContext: execContext,
parentKind: field.kind,
}));
};
StoreReader.prototype.combineExecResults = function () {
var execResults = [];
for (var _i = 0; _i < arguments.length; _i++) {
execResults[_i] = arguments[_i];
}
var missing = null;
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 (field, result, execContext) {

@@ -243,11 +254,8 @@ var _this = this;

}
if (field.selectionSet) {
return handleMissing(_this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext: execContext,
}));
}
assertSelectionSetForIdValue(field, item);
return item;
return handleMissing(_this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext: execContext,
parentKind: field.kind,
}));
});

@@ -259,10 +267,2 @@ return { result: result, missing: missing };

export { StoreReader };
function assertSelectionSetForIdValue(field, value) {
if (!field.selectionSet && isIdValue(value)) {
throw new Error("Missing selection set for object of type " + value.typename + " returned for query field " + field.name.value);
}
}
function defaultFragmentMatcher() {
return true;
}
export function assertIdValue(idValue) {

@@ -273,4 +273,7 @@ if (!isIdValue(idValue)) {

}
function readStoreResolver(object, typename, fieldName, args, context, _a) {
function readStoreResolver(fieldName, idValue, args, context, _a) {
var resultKey = _a.resultKey, directives = _a.directives;
assertIdValue(idValue);
var objId = idValue.id;
var obj = context.store.get(objId);
var storeKeyName = fieldName;

@@ -281,7 +284,8 @@ if (args || directives) {

var fieldValue = void 0;
if (object) {
fieldValue = object[storeKeyName];
if (obj) {
fieldValue = obj[storeKeyName];
if (typeof fieldValue === 'undefined' &&
context.cacheRedirects &&
typeof typename === 'string') {
(obj.__typename || objId === 'ROOT_QUERY')) {
var typename = obj.__typename || 'Query';
var type = context.cacheRedirects[typename];

@@ -291,3 +295,3 @@ if (type) {

if (resolver) {
fieldValue = resolver(object, args, {
fieldValue = resolver(obj, args, {
getCacheKey: function (storeObj) {

@@ -308,3 +312,3 @@ return toIdValue({

missing: [{
object: object,
objectId: objId,
fieldName: storeKeyName,

@@ -323,24 +327,15 @@ tolerable: false,

var hasOwn = Object.prototype.hasOwnProperty;
function merge(target, sources) {
var pastCopies = [];
sources.forEach(function (source) {
mergeHelper(target, source, pastCopies);
});
return target;
}
function mergeHelper(target, source, pastCopies) {
if (source !== null && typeof source === 'object') {
function merge(target, source) {
if (source !== null && typeof source === 'object' &&
source !== target) {
if (Object.isExtensible && !Object.isExtensible(target)) {
target = shallowCopyForMerge(target, pastCopies);
target = __assign({}, target);
}
Object.keys(source).forEach(function (sourceKey) {
var sourceValue = source[sourceKey];
if (hasOwn.call(target, sourceKey)) {
var targetValue = target[sourceKey];
if (sourceValue !== targetValue) {
target[sourceKey] = mergeHelper(shallowCopyForMerge(targetValue, pastCopies), sourceValue, pastCopies);
}
var sourceVal = source[sourceKey];
if (!hasOwn.call(target, sourceKey)) {
target[sourceKey] = sourceVal;
}
else {
target[sourceKey] = sourceValue;
target[sourceKey] = merge(target[sourceKey], sourceVal);
}

@@ -351,16 +346,2 @@ });

}
function shallowCopyForMerge(value, pastCopies) {
if (value !== null &&
typeof value === 'object' &&
pastCopies.indexOf(value) < 0) {
if (Array.isArray(value)) {
value = value.slice(0);
}
else {
value = __assign({}, value);
}
pastCopies.push(value);
}
return value;
}
//# sourceMappingURL=readFromStore.js.map

@@ -19,3 +19,8 @@ import { SelectionSetNode, FieldNode, DocumentNode } from 'graphql';

};
declare type StoreWriterOptions = {
addTypename?: boolean;
};
export declare class StoreWriter {
private addTypename;
constructor({ addTypename, }?: StoreWriterOptions);
writeQueryToStore({ query, result, store, variables, dataIdFromObject, fragmentMatcherFunction, }: {

@@ -38,3 +43,3 @@ query: DocumentNode;

}): NormalizedCache;
writeSelectionSetToStore({ result, dataId, selectionSet, context, }: {
writeSelectionSetToStore({ result, dataId, selectionSet, context, parentKind, }: {
dataId: string;

@@ -44,2 +49,3 @@ result: any;

context: WriteContext;
parentKind: string;
}): NormalizedCache;

@@ -49,2 +55,3 @@ private writeFieldToStore;

}
export {};
//# sourceMappingURL=writeToStore.d.ts.map

@@ -45,4 +45,13 @@ var __extends = (this && this.__extends) || (function () {

}
var TYPENAME_FIELD = {
kind: 'Field',
name: {
kind: 'Name',
value: '__typename',
},
};
var StoreWriter = (function () {
function StoreWriter() {
function StoreWriter(_a) {
var _b = (_a === void 0 ? {} : _a).addTypename, addTypename = _b === void 0 ? false : _b;
this.addTypename = addTypename;
}

@@ -77,2 +86,3 @@ StoreWriter.prototype.writeQueryToStore = function (_a) {

},
parentKind: operationDefinition.kind,
});

@@ -86,4 +96,5 @@ }

var _this = this;
var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context, parentKind = _a.parentKind;
var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;
var didWriteTypename = false;
selectionSet.selections.forEach(function (selection) {

@@ -96,2 +107,5 @@ if (!shouldInclude(selection, variables)) {

var value = result[resultFieldKey];
if (resultFieldKey === "__typename") {
didWriteTypename = true;
}
if (typeof value !== 'undefined') {

@@ -146,2 +160,3 @@ _this.writeFieldToStore({

context: context,
parentKind: fragment.kind,
});

@@ -151,2 +166,13 @@ }

});
if (!didWriteTypename &&
this.addTypename &&
parentKind !== "OperationDefinition" &&
typeof result.__typename === "string") {
this.writeFieldToStore({
dataId: dataId,
value: result.__typename,
field: TYPENAME_FIELD,
context: context,
});
}
return store;

@@ -171,3 +197,3 @@ };

var generatedId = dataId + "." + storeFieldName;
storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context);
storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context, field.kind);
}

@@ -197,2 +223,3 @@ else {

context: context,
parentKind: field.kind,
});

@@ -237,3 +264,3 @@ }

};
StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context) {
StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context, parentKind) {
var _this = this;

@@ -246,3 +273,3 @@ return value.map(function (item, index) {

if (Array.isArray(item)) {
return _this.processArrayValue(item, itemDataId, selectionSet, context);
return _this.processArrayValue(item, itemDataId, selectionSet, context, parentKind);
}

@@ -263,2 +290,3 @@ var generated = true;

context: context,
parentKind: parentKind,
});

@@ -265,0 +293,0 @@ }

{
"name": "apollo-cache-inmemory",
"version": "1.3.9",
"version": "1.4.0-alpha.1",
"description": "Core abstract of Caching layer for Apollo Client",

@@ -18,5 +18,3 @@ "author": "James Baxley <james@meteor.com>",

"typings": "./lib/index.d.ts",
"sideEffects": [
"./lib/fixPolyfills.js"
],
"sideEffects": false,
"repository": {

@@ -46,8 +44,8 @@ "type": "git",

"dependencies": {
"apollo-cache": "^1.1.20",
"apollo-utilities": "^1.0.25",
"apollo-cache": "^1.2.0-alpha.1",
"apollo-utilities": "^1.1.0-alpha.1",
"optimism": "^0.6.6"
},
"peerDependencies": {
"graphql": "0.11.7 || ^0.12.0 || ^0.13.0 || ^14.0.0"
"graphql": "0.11.7 || ^0.12.0 || ^0.13.0"
},

@@ -67,3 +65,3 @@ "jest": {

},
"gitHead": "9e7f06b856b133216bb639f787d8da81a6ab2df4"
"gitHead": "cc787f8f294943fe1f1b8de427ed9a70725744f6"
}
import { ApolloCache } from 'apollo-cache';
import gql, { disableFragmentWarnings } from 'graphql-tag';
import { stripSymbols } from 'apollo-utilities';
import { cloneDeep } from 'lodash';

@@ -204,3 +203,2 @@ import { InMemoryCache, ApolloReducerConfig, NormalizedCache } from '..';

});
it('will read some data from the store with null variables', () => {

@@ -235,34 +233,2 @@ const proxy = createCache({

});
it('should not mutate arguments passed in', () => {
const proxy = createCache({
initialState: {
apollo: {
data: {
ROOT_QUERY: {
'field({"literal":true,"value":42})': 1,
'field({"literal":false,"value":42})': 2,
},
},
},
},
});
const options = {
query: gql`
query($literal: Boolean, $value: Int) {
a: field(literal: true, value: 42)
b: field(literal: $literal, value: $value)
}
`,
variables: {
literal: false,
value: 42,
},
};
const preQueryCopy = cloneDeep(options);
expect(stripSymbols(proxy.readQuery(options))).toEqual({ a: 1, b: 2 });
expect(preQueryCopy).toEqual(options);
});
});

@@ -269,0 +235,0 @@

@@ -9,3 +9,2 @@ import gql, { disableFragmentWarnings } from 'graphql-tag';

import { defaultDataIdFromObject } from '../inMemoryCache';
import { NormalizedCache } from '../types';

@@ -975,157 +974,2 @@ const fragmentMatcherFunction = new HeuristicFragmentMatcher().match;

});
describe('malformed queries', () => {
it('throws for non-scalar query fields without selection sets', () => {
// Issue #4025, fixed by PR #4038.
const validQuery = gql`
query getMessageList {
messageList {
id
__typename
message
}
}
`;
const invalidQuery = gql`
query getMessageList {
# This field needs a selection set because its value is an array
# of non-scalar objects.
messageList
}
`;
const store = writer.writeQueryToStore({
query: validQuery,
result: {
messageList: [{
id: 1,
__typename: "Message",
message: "hi"
}, {
id: 2,
__typename: "Message",
message: "hello"
}, {
id: 3,
__typename: "Message",
message: "hey"
}]
}
});
try {
reader.diffQueryAgainstStore({
store,
query: invalidQuery,
});
throw new Error('should have thrown');
} catch (e) {
expect(e.message).toEqual(
'Missing selection set for object of type Message returned for query field messageList'
);
}
});
});
describe('issue #4081', () => {
it('should not return results containing cycles', () => {
const company = {
__typename: 'Company',
id: 1,
name: 'Apollo',
users: [],
};
company.users.push({
__typename: 'User',
id: 1,
name: 'Ben',
company,
}, {
__typename: 'User',
id: 2,
name: 'James',
company,
});
const query = gql`
query Query {
user {
...UserFragment
company {
users {
...UserFragment
}
}
}
}
fragment UserFragment on User {
id
name
company {
id
name
}
}
`;
function check(store: NormalizedCache) {
const { result } = reader.diffQueryAgainstStore({ store, query });
// This JSON.stringify call has the side benefit of verifying that the
// result does not have any cycles.
const json = JSON.stringify(result);
company.users.forEach(user => {
expect(json).toContain(JSON.stringify(user.name));
});
expect(result).toEqual({
user: {
id: 1,
name: 'Ben',
company: {
id: 1,
name: 'Apollo',
users: [{
id: 1,
name: 'Ben',
company: {
id: 1,
name: 'Apollo',
},
}, {
id: 2,
name: 'James',
company: {
id: 1,
name: 'Apollo',
},
}],
},
},
});
}
// Check first using generated IDs.
check(writer.writeQueryToStore({
query,
result: {
user: company.users[0],
},
}));
// Now check with __typename-specific IDs.
check(writer.writeQueryToStore({
dataIdFromObject: defaultDataIdFromObject,
query,
result: {
user: company.users[0],
},
}));
});
});
});

@@ -1,4 +0,1 @@

// Make builtins like Map and Set safe to use with non-extensible objects.
import './fixPolyfills';
import { DocumentNode } from 'graphql';

@@ -83,5 +80,11 @@

this.storeReader = new StoreReader(this.cacheKeyRoot);
this.storeWriter = new StoreWriter();
this.storeReader = new StoreReader({
addTypename: this.config.addTypename,
cacheKeyRoot: this.cacheKeyRoot,
});
this.storeWriter = new StoreWriter({
addTypename: this.config.addTypename,
});
const cache = this;

@@ -144,3 +147,3 @@ const { maybeBroadcastWatch } = cache;

store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -159,3 +162,3 @@ rootId: query.rootId,

variables: write.variables,
document: this.transformDocument(write.query),
document: write.query,
store: this.data,

@@ -176,3 +179,3 @@ dataIdFromObject: this.config.dataIdFromObject,

store: store,
query: this.transformDocument(query.query),
query: query.query,
variables: query.variables,

@@ -266,8 +269,6 @@ returnPartialData: query.returnPartialData,

if (!result) {
result = addTypenameToDocument(document);
this.typenameDocumentCache.set(document, result);
// If someone calls transformDocument and then mistakenly passes the
// result back into an API that also calls transformDocument, make sure
// we don't keep creating new query documents.
this.typenameDocumentCache.set(result, result);
this.typenameDocumentCache.set(
document,
(result = addTypenameToDocument(document)),
);
}

@@ -295,4 +296,5 @@ return result;

return this.read({
query: this.transformDocument(
getFragmentQueryDocument(options.fragment, options.fragmentName),
query: getFragmentQueryDocument(
options.fragment,
options.fragmentName,
),

@@ -311,3 +313,3 @@ variables: options.variables,

result: options.data,
query: this.transformDocument(options.query),
query: options.query,
variables: options.variables,

@@ -323,4 +325,5 @@ });

result: options.data,
query: this.transformDocument(
getFragmentQueryDocument(options.fragment, options.fragmentName),
query: getFragmentQueryDocument(
options.fragment,
options.fragmentName,
),

@@ -350,9 +353,18 @@ variables: options.variables,

private maybeBroadcastWatch(c: Cache.WatchOptions) {
c.callback(this.diff({
const previousResult = c.previousResult && c.previousResult();
const newData = this.diff({
query: c.query,
variables: c.variables,
previousResult: c.previousResult && c.previousResult(),
previousResult,
optimistic: c.optimistic,
}));
});
if (previousResult &&
previousResult === newData.result) {
return;
}
c.callback(newData);
}
}
declare function require(id: string): any;
export type OptimisticWrapperFunction<
T = (...args: any[]) => any
T = (...args: any[]) => any,
> = T & {

@@ -17,5 +17,3 @@ // The .dirty(...) method of an optimistic function takes exactly the same

const {
wrap,
}: {
const { wrap }: {
wrap<T>(

@@ -46,9 +44,5 @@ originalFunction: T,

getOrCreate(value: any): CacheKeyNode<KeyType> {
const map = this.children || (this.children = new Map());
let node = map.get(value);
if (!node) {
map.set(value, node = new CacheKeyNode<KeyType>());
}
return node;
const map = this.children || (this.children = new Map);
return map.get(value) || map.set(value, new CacheKeyNode<KeyType>()).get(value);
}
}
import { CacheKeyNode } from "./optimism";
import { DocumentNode, SelectionSetNode, FragmentSpreadNode, FragmentDefinitionNode } from "graphql";
import { QueryDocumentKeys } from "graphql/language/visitor";
const CIRCULAR = Object.create(null);
const objToStr = Object.prototype.toString;

@@ -103,3 +101,3 @@ export class QueryKeyMaker {

return this.cacheKeyRoot.lookup(
objToStr.call(array),
Array.prototype,
this.cacheKeyRoot.lookupArray(elements),

@@ -110,6 +108,9 @@ );

private lookupObject(object: { [key: string]: any }): object {
const keys = safeSortedKeys(object);
const keys = Object.keys(object);
const locIndex = keys.indexOf("loc");
if (locIndex >= 0) keys.splice(locIndex, 1);
keys.sort();
const values = keys.map(key => this.lookupAny(object[key]));
return this.cacheKeyRoot.lookup(
objToStr.call(object),
Object.getPrototypeOf(object),
this.cacheKeyRoot.lookupArray(keys),

@@ -120,41 +121,1 @@ this.cacheKeyRoot.lookupArray(values),

}
const queryKeyMap: {
[key: string]: { [key: string]: boolean }
} = Object.create(null);
Object.keys(QueryDocumentKeys).forEach(parentKind => {
const childKeys = queryKeyMap[parentKind] = Object.create(null);
(QueryDocumentKeys as {
[key: string]: any[]
})[parentKind].forEach(childKey => {
childKeys[childKey] = true;
});
if (parentKind === "FragmentSpread") {
// A custom key that we include when looking up FragmentSpread nodes.
childKeys["fragment"] = true;
}
});
function safeSortedKeys(object: { [key: string]: any }): string[] {
const keys = Object.keys(object);
const keyCount = keys.length;
const knownKeys = typeof object.kind === "string" && queryKeyMap[object.kind];
// Remove unknown object-valued keys from the array, but leave keys with
// non-object values untouched.
let target = 0;
for (let source = target; source < keyCount; ++source) {
const key = keys[source];
const value = object[key];
const isObjectOrArray = value !== null && typeof value === "object";
if (! isObjectOrArray || ! knownKeys || knownKeys[key] === true) {
keys[target++] = key;
}
}
keys.length = target;
return keys.sort();
}

@@ -40,2 +40,3 @@ import {

SelectionSetNode,
SelectionNode,
} from 'graphql';

@@ -71,3 +72,3 @@

export type ExecResultMissingField = {
object: StoreObject;
objectId: string;
fieldName: string;

@@ -96,10 +97,19 @@ tolerable: boolean;

execContext: ExecContext;
parentKind: string;
};
type StoreReaderOptions = {
addTypename?: boolean;
cacheKeyRoot?: CacheKeyNode;
};
export class StoreReader {
private addTypename: boolean;
private cacheKeyRoot: CacheKeyNode;
private keyMaker: QueryKeyMaker;
constructor(
private cacheKeyRoot = new CacheKeyNode,
) {
constructor({
addTypename = false,
cacheKeyRoot = new CacheKeyNode,
}: StoreReaderOptions = {}) {
const reader = this;

@@ -111,6 +121,8 @@ const {

reader.addTypename = addTypename;
reader.cacheKeyRoot = cacheKeyRoot;
reader.keyMaker = new QueryKeyMaker(cacheKeyRoot);
this.executeStoreQuery = wrap((options: ExecStoreQueryOptions) => {
return executeStoreQuery.call(this, options);
return executeStoreQuery.call(reader, options);
}, {

@@ -122,3 +134,2 @@ makeCacheKey({

variableValues,
fragmentMatcher,
}: ExecStoreQueryOptions) {

@@ -132,5 +143,3 @@ // The result of executeStoreQuery can be safely cached only if the

contextValue.store,
fragmentMatcher,
JSON.stringify(variableValues),
rootValue.id,
);

@@ -142,3 +151,3 @@ }

this.executeSelectionSet = wrap((options: ExecSelectionSetOptions) => {
return executeSelectionSet.call(this, options);
return executeSelectionSet.call(reader, options);
}, {

@@ -154,4 +163,6 @@ makeCacheKey({

execContext.contextValue.store,
execContext.fragmentMatcher,
JSON.stringify(execContext.variableValues),
// Unlike executeStoreQuery, executeSelectionSet can be called
// recursively on nested objects, so it's important to include the
// ID of the current parent object in the cache key.
rootValue.id,

@@ -240,7 +251,5 @@ );

throw new Error(
`Can't find field ${info.fieldName} on object ${JSON.stringify(
info.object,
null,
2,
)}.`,
`Can't find field ${info.fieldName} on object (${info.objectId}) ${
JSON.stringify(store.get(info.objectId), null, 2)
}.`
);

@@ -286,3 +295,3 @@ });

// Default matcher always matches all fragments
fragmentMatcher = defaultFragmentMatcher,
fragmentMatcher = () => true,
}: ExecStoreQueryOptions): ExecResult {

@@ -304,2 +313,3 @@ const mainDefinition = getMainDefinition(query);

execContext,
parentKind: mainDefinition.kind,
});

@@ -312,2 +322,3 @@ }

execContext,
parentKind,
}: ExecSelectionSetOptions): ExecResult {

@@ -319,11 +330,4 @@ const { fragmentMap, contextValue, variableValues: variables } = execContext;

const objectsToMerge: { [key: string]: any }[] = [];
let didReadTypename = false;
const object: StoreObject = contextValue.store.get(rootValue.id);
const typename =
(object && object.__typename) ||
(rootValue.id === 'ROOT_QUERY' && 'Query') ||
void 0;
function handleMissing<T>(result: ExecResult<T>): T {

@@ -337,3 +341,3 @@ if (result.missing) {

selectionSet.selections.forEach(selection => {
const handleSelection = (selection: SelectionNode) => {
if (!shouldInclude(selection, variables)) {

@@ -346,8 +350,13 @@ // Skip this entirely

const fieldResult = handleMissing(
this.executeField(object, typename, selection, execContext),
this.executeField(selection, rootValue, execContext)
);
const keyName = resultKeyNameFromField(selection);
if (keyName === "__typename") {
didReadTypename = true;
}
if (typeof fieldResult !== 'undefined') {
objectsToMerge.push({
[resultKeyNameFromField(selection)]: fieldResult,
merge(finalResult.result, {
[keyName]: fieldResult,
});

@@ -378,2 +387,3 @@ }

execContext,
parentKind: fragment.kind,
});

@@ -390,11 +400,24 @@

objectsToMerge.push(handleMissing(fragmentExecResult));
merge(finalResult.result, handleMissing(fragmentExecResult));
}
}
});
};
// Perform a single merge at the end so that we can avoid making more
// defensive shallow copies than necessary.
merge(finalResult.result, objectsToMerge);
selectionSet.selections.forEach(handleSelection);
if (! didReadTypename &&
this.addTypename &&
// Analogous to the isRoot parameter that addTypenameToDocument passes
// to addTypenameToSelectionSet to avoid adding __typename to the root
// query operation's selection set.
parentKind !== "OperationDefinition") {
handleSelection({
kind: "Field",
name: {
kind: "Name",
value: "__typename",
},
});
}
return finalResult;

@@ -404,5 +427,4 @@ }

private executeField(
object: StoreObject,
typename: string | void,
field: FieldNode,
rootValue: any,
execContext: ExecContext,

@@ -420,5 +442,4 @@ ): ExecResult {

const readStoreResult = readStoreResolver(
object,
typename,
fieldName,
rootValue,
args,

@@ -429,16 +450,4 @@ contextValue,

if (Array.isArray(readStoreResult.result)) {
return this.combineExecResults(
readStoreResult,
this.executeSubSelectedArray(
field,
readStoreResult.result,
execContext,
),
);
}
// Handle all scalar types here
if (!field.selectionSet) {
assertSelectionSetForIdValue(field, readStoreResult.result);
return readStoreResult;

@@ -454,27 +463,36 @@ }

// Returned value is an object, and the query has a sub-selection. Recurse.
return this.combineExecResults(
readStoreResult,
this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: readStoreResult.result,
execContext,
}),
);
}
function handleMissing<T>(res: ExecResult<T>): ExecResult<T> {
let missing: ExecResultMissingField[] = null;
private combineExecResults<T>(
...execResults: ExecResult<T>[]
): ExecResult<T> {
let missing: ExecResultMissingField[] = null;
execResults.forEach(execResult => {
if (execResult.missing) {
if (readStoreResult.missing) {
missing = missing || [];
missing.push(...execResult.missing);
missing.push(...readStoreResult.missing);
}
});
return {
result: execResults.pop().result,
missing,
};
if (res.missing) {
missing = missing || [];
missing.push(...res.missing);
}
return {
result: res.result,
missing,
};
}
if (Array.isArray(readStoreResult.result)) {
return handleMissing(this.executeSubSelectedArray(
field,
readStoreResult.result,
execContext,
));
}
// Returned value is an object, and the query has a sub-selection. Recurse.
return handleMissing(this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: readStoreResult.result,
execContext,
parentKind: field.kind,
}));
}

@@ -510,13 +528,8 @@

// This is an object, run the selection set on it
if (field.selectionSet) {
return handleMissing(this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext,
}));
}
assertSelectionSetForIdValue(field, item);
return item;
return handleMissing(this.executeSelectionSet({
selectionSet: field.selectionSet,
rootValue: item,
execContext,
parentKind: field.kind,
}));
});

@@ -528,19 +541,2 @@

function assertSelectionSetForIdValue(
field: FieldNode,
value: any,
) {
if (!field.selectionSet && isIdValue(value)) {
throw new Error(
`Missing selection set for object of type ${
value.typename
} returned for query field ${field.name.value}`
);
}
}
function defaultFragmentMatcher() {
return true;
}
export function assertIdValue(idValue: IdValue) {

@@ -555,5 +551,4 @@ if (!isIdValue(idValue)) {

function readStoreResolver(
object: StoreObject,
typename: string | void,
fieldName: string,
idValue: IdValue,
args: any,

@@ -563,2 +558,7 @@ context: ReadStoreContext,

): ExecResult<StoreValue> {
assertIdValue(idValue);
const objId = idValue.id;
const obj = context.store.get(objId);
let storeKeyName = fieldName;

@@ -575,4 +575,4 @@ if (args || directives) {

if (object) {
fieldValue = object[storeKeyName];
if (obj) {
fieldValue = obj[storeKeyName];

@@ -582,4 +582,6 @@ if (

context.cacheRedirects &&
typeof typename === 'string'
(obj.__typename || objId === 'ROOT_QUERY')
) {
const typename = obj.__typename || 'Query';
// Look for the type in the custom resolver map

@@ -591,3 +593,3 @@ const type = context.cacheRedirects[typename];

if (resolver) {
fieldValue = resolver(object, args, {
fieldValue = resolver(obj, args, {
getCacheKey(storeObj: StoreObject) {

@@ -609,3 +611,3 @@ return toIdValue({

missing: [{
object,
objectId: objId,
fieldName: storeKeyName,

@@ -630,43 +632,21 @@ tolerable: false,

target: { [key: string]: any },
sources: { [key: string]: any }[]
source: { [key: string]: any },
) {
const pastCopies: any[] = [];
sources.forEach(source => {
mergeHelper(target, source, pastCopies);
});
return target;
}
if (source !== null && typeof source === 'object' &&
// Due to result caching, it's possible that source and target will
// be === at some point in the tree, which means we can stop early.
source !== target) {
function mergeHelper(
target: { [key: string]: any },
source: { [key: string]: any },
pastCopies: any[],
) {
if (source !== null && typeof source === 'object') {
// In case the target has been frozen, make an extensible copy so that
// we can merge properties into the copy.
if (Object.isExtensible && !Object.isExtensible(target)) {
target = shallowCopyForMerge(target, pastCopies);
target = { ...target };
}
Object.keys(source).forEach(sourceKey => {
const sourceValue = source[sourceKey];
if (hasOwn.call(target, sourceKey)) {
const targetValue = target[sourceKey];
if (sourceValue !== targetValue) {
// When there is a key collision, we need to make a shallow copy of
// target[sourceKey] so the merge does not modify any source objects.
// To avoid making unnecessary copies, we use a simple array to track
// past copies, instead of a Map, since the number of copies should
// be relatively small, and some Map polyfills modify their keys.
target[sourceKey] = mergeHelper(
shallowCopyForMerge(targetValue, pastCopies),
sourceValue,
pastCopies,
);
}
const sourceVal = source[sourceKey];
if (!hasOwn.call(target, sourceKey)) {
target[sourceKey] = sourceVal;
} else {
// If there is no collision, the target can safely share memory with
// the source, and the recursion can terminate here.
target[sourceKey] = sourceValue;
target[sourceKey] = merge(target[sourceKey], sourceVal);
}

@@ -678,17 +658,1 @@ });

}
function shallowCopyForMerge<T>(value: T, pastCopies: any[]): T {
if (
value !== null &&
typeof value === 'object' &&
pastCopies.indexOf(value) < 0
) {
if (Array.isArray(value)) {
value = (value as any).slice(0);
} else {
value = { ...(value as any) };
}
pastCopies.push(value);
}
return value;
}

@@ -64,3 +64,23 @@ import {

type StoreWriterOptions = {
addTypename?: boolean;
};
const TYPENAME_FIELD: FieldNode = {
kind: 'Field',
name: {
kind: 'Name',
value: '__typename',
},
};
export class StoreWriter {
private addTypename: boolean;
constructor({
addTypename = false,
}: StoreWriterOptions = {}) {
this.addTypename = addTypename;
}
/**

@@ -146,2 +166,3 @@ * Writes the result of a query to the store.

},
parentKind: operationDefinition.kind,
});

@@ -158,2 +179,3 @@ } catch (e) {

context,
parentKind,
}: {

@@ -164,4 +186,6 @@ dataId: string;

context: WriteContext;
parentKind: string;
}): NormalizedCache {
const { variables, store, fragmentMap } = context;
let didWriteTypename = false;

@@ -177,2 +201,6 @@ selectionSet.selections.forEach(selection => {

if (resultFieldKey === "__typename") {
didWriteTypename = true;
}
if (typeof value !== 'undefined') {

@@ -253,2 +281,3 @@ this.writeFieldToStore({

context,
parentKind: fragment.kind,
});

@@ -259,2 +288,17 @@ }

if (! didWriteTypename &&
this.addTypename &&
// Analogous to the isRoot parameter that addTypenameToDocument passes
// to addTypenameToSelectionSet to avoid adding __typename to the root
// query operation's selection set.
parentKind !== "OperationDefinition" &&
typeof result.__typename === "string") {
this.writeFieldToStore({
dataId,
value: result.__typename,
field: TYPENAME_FIELD,
context,
});
}
return store;

@@ -298,2 +342,3 @@ }

context,
field.kind,
);

@@ -339,2 +384,3 @@ } else {

context,
parentKind: field.kind,
});

@@ -418,2 +464,3 @@ }

context: WriteContext,
parentKind: string,
): any[] {

@@ -428,3 +475,9 @@ return value.map((item: any, index: any) => {

if (Array.isArray(item)) {
return this.processArrayValue(item, itemDataId, selectionSet, context);
return this.processArrayValue(
item,
itemDataId,
selectionSet,
context,
parentKind,
);
}

@@ -449,2 +502,3 @@

context,
parentKind,
});

@@ -451,0 +505,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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