Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
// The result of executeStoreQuery can be safely cached only if the
// underlying store is capable of tracking dependencies and invalidating
// the cache when relevant data have changed.
if (contextValue.store instanceof DepTrackingCache) {
return cacheKeyRoot.lookup(
contextValue.store,
query,
fragmentMatcher,
JSON.stringify(variableValues),
rootValue.id,
);
}
}
});
this.executeSelectionSet = wrap((options: ExecSelectionSetOptions) => {
return executeSelectionSet.call(this, options);
}, {
makeCacheKey({
selectionSet,
rootValue,
execContext,
}: ExecSelectionSetOptions) {
if (execContext.contextValue.store instanceof DepTrackingCache) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
selectionSet,
execContext.fragmentMatcher,
JSON.stringify(execContext.variableValues),
rootValue.id,
);
}
constructor({
cacheKeyRoot = new KeyTrie(canUseWeakMap),
freezeResults = false,
}: StoreReaderConfig = {}) {
const {
executeStoreQuery,
executeSelectionSet,
executeSubSelectedArray,
} = this;
this.freezeResults = freezeResults;
this.executeStoreQuery = wrap((options: ExecStoreQueryOptions) => {
return executeStoreQuery.call(this, options);
}, {
makeCacheKey({
query,
rootValue,
contextValue,
variableValues,
fragmentMatcher,
}: ExecStoreQueryOptions) {
// The result of executeStoreQuery can be safely cached only if the
// underlying store is capable of tracking dependencies and invalidating
// the cache when relevant data have changed.
if (contextValue.store instanceof DepTrackingCache) {
return cacheKeyRoot.lookup(
contextValue.store,
query,
// When no optimistic writes are currently active, cache.optimisticData ===
// cache.data, so there are no additional layers on top of the actual data.
// When an optimistic update happens, this.optimisticData will become a
// linked list of OptimisticCacheLayer objects that terminates with the
// original this.data cache object.
this.optimisticData = this.data;
this.storeWriter = new StoreWriter();
this.storeReader = new StoreReader({
cacheKeyRoot: this.cacheKeyRoot,
freezeResults: config.freezeResults,
});
const cache = this;
const { maybeBroadcastWatch } = cache;
this.maybeBroadcastWatch = wrap((c: Cache.WatchOptions) => {
return maybeBroadcastWatch.call(this, c);
}, {
makeCacheKey(c: Cache.WatchOptions) {
if (c.optimistic) {
// If we're reading optimistic data, it doesn't matter if this.data
// is a DepTrackingCache, since it will be ignored.
return;
}
if (c.previousResult) {
// If a previousResult was provided, assume the caller would prefer
// to compare the previous data to the new data to determine whether
// to broadcast, so we should disable caching by returning here, to
// give maybeBroadcastWatch a chance to do that comparison.
return;
}
}
}
if (storeFieldName === void 0) {
storeFieldName = storeKeyNameFromField(field, variables);
}
// Make sure custom field names start with the actual field.name.value
// of the field, so we can always figure out which properties of a
// StoreObject correspond to which original field names.
return fieldName === fieldNameFromStoreName(storeFieldName)
? storeFieldName
: fieldName + ":" + storeFieldName;
}
private storageTrie = new KeyTrie(true);
private fieldDep = dep();
public readField(
objectOrReference: StoreObject | Reference,
nameOrField: string | FieldNode,
getFieldValue: FieldValueGetter,
variables?: Record,
typename = getFieldValue(objectOrReference, "__typename"),
): Readonly {
const policies = this;
const storeFieldName = typeof nameOrField === "string" ? nameOrField
: policies.getStoreFieldName(typename, nameOrField, variables);
const fieldName = fieldNameFromStoreName(storeFieldName);
const existing = getFieldValue(objectOrReference, storeFieldName);
const policy = policies.getFieldPolicy(typename, fieldName, false);
const read = policy && policy.read;
? this.data[dataId]
: this.parent.get(dataId);
}
}
export class InMemoryCache extends ApolloCache {
private data: NormalizedCache;
private optimisticData: NormalizedCache;
protected config: InMemoryCacheConfig;
private watches = new Set();
private addTypename: boolean;
private typenameDocumentCache = new Map();
private storeReader: StoreReader;
private storeWriter: StoreWriter;
private cacheKeyRoot = new KeyTrie(canUseWeakMap);
// Set this while in a transaction to prevent broadcasts...
// don't forget to turn it back on!
private silenceBroadcast: boolean = false;
constructor(config: InMemoryCacheConfig = {}) {
super();
this.config = { ...defaultConfig, ...config };
// backwards compat
if ((this.config as any).customResolvers) {
invariant.warn(
'customResolvers have been renamed to cacheRedirects. Please update your config as we will be deprecating customResolvers in the next major version.',
);
this.config.cacheRedirects = (this.config as any).customResolvers;
}
rootValue,
execContext,
}: ExecSelectionSetOptions) {
if (execContext.contextValue.store instanceof DepTrackingCache) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
selectionSet,
execContext.fragmentMatcher,
JSON.stringify(execContext.variableValues),
rootValue.id,
);
}
}
});
this.executeSubSelectedArray = wrap((options: ExecSubSelectedArrayOptions) => {
return executeSubSelectedArray.call(this, options);
}, {
makeCacheKey({ field, array, execContext }) {
if (execContext.contextValue.store instanceof DepTrackingCache) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
field,
array,
JSON.stringify(execContext.variableValues),
);
}
}
});
}
const cacheKeyRoot =
config && config.cacheKeyRoot || new KeyTrie(canUseWeakMap);
this.config = {
addTypename: true,
cacheKeyRoot,
...config,
};
const {
executeStoreQuery,
executeSelectionSet,
executeSubSelectedArray,
} = this;
this.executeStoreQuery = wrap((options: ExecStoreQueryOptions) => {
return executeStoreQuery.call(this, options);
}, {
makeCacheKey({
query,
objectOrReference,
contextValue,
variableValues,
}: ExecStoreQueryOptions) {
if (supportsResultCaching(contextValue.store)) {
return cacheKeyRoot.lookup(
contextValue.store,
query,
JSON.stringify(variableValues),
isReference(objectOrReference) ? objectOrReference.__ref : objectOrReference,
);
}
constructor(private data: NormalizedCacheObject = Object.create(null)) {
this.depend = wrap((dataId: string) => this.data[dataId], {
disposable: true,
makeCacheKey(dataId: string) {
return dataId;
},
});
}
objectOrReference,
contextValue,
variableValues,
}: ExecStoreQueryOptions) {
if (supportsResultCaching(contextValue.store)) {
return cacheKeyRoot.lookup(
contextValue.store,
query,
JSON.stringify(variableValues),
isReference(objectOrReference) ? objectOrReference.__ref : objectOrReference,
);
}
}
});
this.executeSelectionSet = wrap((options: ExecSelectionSetOptions) => {
return executeSelectionSet.call(this, options);
}, {
makeCacheKey({
selectionSet,
objectOrReference,
execContext,
}: ExecSelectionSetOptions) {
if (supportsResultCaching(execContext.contextValue.store)) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
selectionSet,
JSON.stringify(execContext.variableValues),
isReference(objectOrReference) ? objectOrReference.__ref : objectOrReference,
);
}
}
selectionSet,
objectOrReference,
execContext,
}: ExecSelectionSetOptions) {
if (supportsResultCaching(execContext.contextValue.store)) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
selectionSet,
JSON.stringify(execContext.variableValues),
isReference(objectOrReference) ? objectOrReference.__ref : objectOrReference,
);
}
}
});
this.executeSubSelectedArray = wrap((options: ExecSubSelectedArrayOptions) => {
return executeSubSelectedArray.call(this, options);
}, {
makeCacheKey({ field, array, execContext }) {
if (supportsResultCaching(execContext.contextValue.store)) {
return cacheKeyRoot.lookup(
execContext.contextValue.store,
field,
array,
JSON.stringify(execContext.variableValues),
);
}
}
});
}