diff --git a/package.json b/package.json index 6b8718375d..fd3876d007 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "@testing-library/react": "^9.1.3", "@testing-library/react-hooks": "^2.0.1", "@types/enzyme": "3.10.3", - "@types/fast-json-stable-stringify": "^2.0.0", "@types/jest": "^24.0.18", "@types/react": "^16.9.2", "@types/react-test-renderer": "^16.9.0", @@ -134,7 +133,6 @@ "react-dom": ">= 16.8.0" }, "dependencies": { - "fast-json-stable-stringify": "^2.0.0", "wonka": "^3.2.1" } } diff --git a/src/index.ts b/src/index.ts index fb48863b26..d827ce4b6b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ export * from './types'; export { CombinedError, + stringifyVariables, createRequest, makeResult, makeErrorResult, diff --git a/src/utils/index.ts b/src/utils/index.ts index e17b2d560b..8c01fe9570 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,6 +3,7 @@ export * from './request'; export * from './result'; export * from './typenames'; export * from './toSuspenseSource'; +export * from './stringifyVariables'; export * from './withPromise'; export const noop = () => { diff --git a/src/utils/request.ts b/src/utils/request.ts index f5ab63c32e..5d33de1997 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -1,6 +1,6 @@ import { DocumentNode, parse, print } from 'graphql'; import { hash, phash } from './hash'; -import stringify from 'fast-json-stable-stringify'; +import { stringifyVariables } from './stringifyVariables'; import { GraphQLRequest, Operation, OperationContext } from '../types'; interface Documents { @@ -33,7 +33,7 @@ export const createRequest = ( (query as any)[keyProp] = key; return { - key: vars ? phash(key, stringify(vars)) >>> 0 : key, + key: vars ? phash(key, stringifyVariables(vars)) >>> 0 : key, query, variables: vars || {}, }; diff --git a/src/utils/stringifyVariables.ts b/src/utils/stringifyVariables.ts new file mode 100644 index 0000000000..7417fef543 --- /dev/null +++ b/src/utils/stringifyVariables.ts @@ -0,0 +1,46 @@ +const seen = new Set(); + +const stringify = (x: any): string => { + if (x === undefined) { + return ''; + } else if (typeof x == 'number') { + return isFinite(x) ? '' + x : 'null'; + } else if (typeof x !== 'object') { + return JSON.stringify(x); + } else if (x === null) { + return 'null'; + } + + let out = '['; + if (Array.isArray(x)) { + for (let i = 0, l = x.length; i < l; i++) { + if (i > 0) out += ','; + const value = stringify(x[i]); + out += value.length > 0 ? value : 'null'; + } + + return out + ']'; + } else if (seen.has(x)) { + throw new TypeError('Converting circular structure to JSON'); + } + + const keys = Object.keys(x).sort(); + + seen.add(x); + for (let i = 0, l = keys.length; i < l; i++) { + const key = stringify(keys[i]); + const value = stringify(x[key]); + if (value.length !== 0) { + if (out.length > 0) out += ','; + out += key + ':' + value; + } + } + + seen.delete(x); + return '{' + out + '}'; +}; + +export const stringifyVariables = (x: any): string => { + seen.clear(); + return stringify(x); +}; diff --git a/yarn.lock b/yarn.lock index 807a433b6c..898e5ad2d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -456,11 +456,6 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== -"@types/fast-json-stable-stringify@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#40363bb847cb86b2c2e1599f1398d11e8329c921" - integrity sha512-mky/O83TXmGY39P1H9YbUpjV6l6voRYlufqfFCvel8l1phuy8HRjdWc1rrPuN53ITBJlbyMSV6z3niOySO5pgQ== - "@types/glob@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"