Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

fix(core): ensure operationKey is different when dealing with files (#3601)

Changed files
+19 -10
.changeset
packages
core
src
utils
+8
.changeset/shaggy-wasps-bow.md
···
+
---
+
'@urql/core': patch
+
---
+
+
Change how we calculate the `OperationKey` to take files into account, before we
+
would encode them to `null` resulting in every mutation with the same variables
+
(excluding the files) to have the same key. This resulted in mutations that upload
+
different files at the same time to share a result in GraphCache.
+11 -10
packages/core/src/utils/variables.ts
···
const seen: Set<any> = new Set();
const cache: WeakMap<any, any> = new WeakMap();
-
const stringify = (x: any): string => {
+
const stringify = (x: any, includeFiles: boolean): string => {
if (x === null || seen.has(x)) {
return 'null';
} else if (typeof x !== 'object') {
return JSON.stringify(x) || '';
} else if (x.toJSON) {
-
return stringify(x.toJSON());
+
return stringify(x.toJSON(), includeFiles);
} else if (Array.isArray(x)) {
let out = '[';
for (const value of x) {
if (out.length > 1) out += ',';
-
out += stringify(value) || 'null';
+
out += stringify(value, includeFiles) || 'null';
}
out += ']';
return out;
} else if (
-
(FileConstructor !== NoopConstructor && x instanceof FileConstructor) ||
-
(BlobConstructor !== NoopConstructor && x instanceof BlobConstructor)
+
!includeFiles &&
+
((FileConstructor !== NoopConstructor && x instanceof FileConstructor) ||
+
(BlobConstructor !== NoopConstructor && x instanceof BlobConstructor))
) {
return 'null';
}
···
) {
const key = cache.get(x) || Math.random().toString(36).slice(2);
cache.set(x, key);
-
return stringify({ __key: key });
+
return stringify({ __key: key }, includeFiles);
}
seen.add(x);
let out = '{';
for (const key of keys) {
-
const value = stringify(x[key]);
+
const value = stringify(x[key], includeFiles);
if (value) {
if (out.length > 1) out += ',';
-
out += stringify(key) + ':' + value;
+
out += stringify(key, includeFiles) + ':' + value;
}
}
···
* replacing their values, which remain stable for the objects’
* instance.
*/
-
export const stringifyVariables = (x: any): string => {
+
export const stringifyVariables = (x: any, includeFiles?: boolean): string => {
seen.clear();
-
return stringify(x);
+
return stringify(x, includeFiles || false);
};
class NoopConstructor {}