diff --git a/.changeset/small-timers-shake.md b/.changeset/small-timers-shake.md
new file mode 100644
index 00000000000..f37c10ca874
--- /dev/null
+++ b/.changeset/small-timers-shake.md
@@ -0,0 +1,5 @@
+---
+'@apollo/client': minor
+---
+
+Add support for React suspense with a new `useSuspenseQuery` hook.
diff --git a/.prettierignore b/.prettierignore
index 7fc13da26e3..9f4a4cfdcca 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,6 +1,41 @@
+##### DISCLAIMER ######
+# We have disabled the use of prettier in this project for a variety of reasons.
+# Because much of this project has not been formatted, we don't want to want to
+# apply formatting to everything and skew `git blame` stats. Instead, we should
+# only format newly created files that we can guarantee have no existing git
+# history. For this reason, we have disabled prettier project-wide except for
+# a handful of files.
+#
+# ONLY ADD NEWLY CREATED FILES/PATHS TO THE LIST BELOW. DO NOT ADD EXISTING
+# PROJECT FILES.
+
# ignores all files in /docs directory
/docs/**
# Ignore all mdx & md files:
*.mdx
*.md
+
+# Do not format anything automatically except files listed below
+/*
+
+##### PATHS TO BE FORMATTED #####
+!src/
+src/*
+!src/react/
+src/react/*
+
+# Allow src/react/cache
+!src/react/cache/
+
+## Allowed React Hooks
+!src/react/hooks/
+src/react/hooks/*
+!src/react/hooks/internal
+!src/react/hooks/useSuspenseCache.ts
+!src/react/hooks/useSuspenseQuery.ts
+
+## Allowed React hook tests
+!src/react/hooks/__tests__/
+src/react/hooks/__tests__/*
+!src/react/hooks/__tests__/useSuspenseQuery.test.tsx
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0fad22ff6aa..5ad783aaf99 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## Apollo Client 3.8.0
+
+### Bug fixes
+
+- Avoid calling `useQuery` `onCompleted` callback after cache writes, only after the originating query's network request(s) complete.
+ [@alessbell](https://github.com/alessbell) in [#10229](https://github.com/apollographql/apollo-client/pull/10229)
+
## Apollo Client 3.7.2 (2022-12-06)
### Improvements
diff --git a/config/bundlesize.ts b/config/bundlesize.ts
index b628fb88013..4a738d0ff20 100644
--- a/config/bundlesize.ts
+++ b/config/bundlesize.ts
@@ -3,7 +3,7 @@ import { join } from "path";
import { gzipSync } from "zlib";
import bytes from "bytes";
-const gzipBundleByteLengthLimit = bytes("31.87KB");
+const gzipBundleByteLengthLimit = bytes("32.79KB");
const minFile = join("dist", "apollo-client.min.cjs");
const minPath = join(__dirname, "..", minFile);
const gzipByteLen = gzipSync(readFileSync(minPath)).byteLength;
diff --git a/config/jest.config.js b/config/jest.config.js
index 9862ff2c9aa..3c45812e17d 100644
--- a/config/jest.config.js
+++ b/config/jest.config.js
@@ -2,7 +2,7 @@ const defaults = {
rootDir: "src",
preset: "ts-jest",
testEnvironment: "jsdom",
- setupFiles: ["/config/jest/setup.ts"],
+ setupFilesAfterEnv: ["/config/jest/setup.ts"],
testEnvironmentOptions: {
url: "http://localhost",
},
@@ -25,6 +25,13 @@ const defaults = {
const ignoreTSFiles = '.ts$';
const ignoreTSXFiles = '.tsx$';
+const react17TestFileIgnoreList = [
+ ignoreTSFiles,
+ // For now, we only support useSuspenseQuery with React 18, so no need to test
+ // it with React 17
+ 'src/react/hooks/__tests__/useSuspenseQuery.test.tsx'
+]
+
const react18TestFileIgnoreList = [
// ignore core tests (.ts files) as they are run separately
// to avoid running them twice with both react versions
@@ -68,7 +75,7 @@ const standardReact18Config = {
const standardReact17Config = {
...defaults,
displayName: "ReactDOM 17",
- testPathIgnorePatterns: [ignoreTSFiles],
+ testPathIgnorePatterns: react17TestFileIgnoreList,
moduleNameMapper: {
"^react$": "react-17",
"^react-dom$": "react-dom-17",
diff --git a/package-lock.json b/package-lock.json
index 14ad167c4f1..7359c111fa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,6 +7,7 @@
"": {
"name": "@apollo/client",
"version": "3.7.2",
+ "hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
@@ -29,6 +30,7 @@
"@changesets/cli": "2.25.2",
"@graphql-tools/schema": "9.0.10",
"@rollup/plugin-node-resolve": "11.2.1",
+ "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "13.4.0",
"@testing-library/react-12": "npm:@testing-library/react@^12",
"@testing-library/react-hooks": "8.0.1",
@@ -57,10 +59,13 @@
"jest-environment-jsdom": "29.3.1",
"jest-junit": "15.0.0",
"lodash": "4.17.21",
+ "patch-package": "6.5.0",
+ "prettier": "2.7.1",
"react": "18.2.0",
"react-17": "npm:react@^17",
"react-dom": "18.2.0",
"react-dom-17": "npm:react-dom@^17",
+ "react-error-boundary": "^3.1.4",
"recast": "0.21.5",
"resolve": "1.22.1",
"rimraf": "3.0.2",
@@ -102,6 +107,12 @@
}
}
},
+ "node_modules/@adobe/css-tools": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz",
+ "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==",
+ "dev": true
+ },
"node_modules/@babel/code-frame": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
@@ -1773,6 +1784,74 @@
"node": ">=12"
}
},
+ "node_modules/@testing-library/jest-dom": {
+ "version": "5.16.5",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz",
+ "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==",
+ "dev": true,
+ "dependencies": {
+ "@adobe/css-tools": "^4.0.1",
+ "@babel/runtime": "^7.9.2",
+ "@types/testing-library__jest-dom": "^5.9.1",
+ "aria-query": "^5.0.0",
+ "chalk": "^3.0.0",
+ "css.escape": "^1.5.1",
+ "dom-accessibility-api": "^0.5.6",
+ "lodash": "^4.17.15",
+ "redent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
"node_modules/@testing-library/react": {
"version": "13.4.0",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz",
@@ -2199,6 +2278,15 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
+ "node_modules/@types/testing-library__jest-dom": {
+ "version": "5.14.5",
+ "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz",
+ "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/jest": "*"
+ }
+ },
"node_modules/@types/tough-cookie": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
@@ -2259,6 +2347,12 @@
"node": ">=8"
}
},
+ "node_modules/@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true
+ },
"node_modules/abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -2943,6 +3037,12 @@
"node": ">= 8"
}
},
+ "node_modules/css.escape": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
+ "dev": true
+ },
"node_modules/cssom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
@@ -3653,6 +3753,15 @@
"node": ">=8"
}
},
+ "node_modules/find-yarn-workspace-root": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+ "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+ "dev": true,
+ "dependencies": {
+ "micromatch": "^4.0.2"
+ }
+ },
"node_modules/find-yarn-workspace-root2": {
"version": "1.2.16",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz",
@@ -4272,6 +4381,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -4477,6 +4601,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -5726,6 +5862,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -6050,6 +6195,15 @@
"node": "*"
}
},
+ "node_modules/minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/minimist-options": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
@@ -6091,6 +6245,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -6261,6 +6421,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optimism": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.1.tgz",
@@ -6400,6 +6576,161 @@
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
+ "node_modules/patch-package": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.0.tgz",
+ "integrity": "sha512-tC3EqJmo74yKqfsMzELaFwxOAu6FH6t+FzFOsnWAuARm7/n2xB5AOeOueE221eM9gtMuIKMKpF9tBy/X2mNP0Q==",
+ "dev": true,
+ "dependencies": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "cross-spawn": "^6.0.5",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^7.0.1",
+ "is-ci": "^2.0.0",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "rimraf": "^2.6.3",
+ "semver": "^5.6.0",
+ "slash": "^2.0.0",
+ "tmp": "^0.0.33",
+ "yaml": "^1.10.2"
+ },
+ "bin": {
+ "patch-package": "index.js"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">5"
+ }
+ },
+ "node_modules/patch-package/node_modules/ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "node_modules/patch-package/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/patch-package/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/patch-package/node_modules/is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^2.0.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/patch-package/node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/patch-package/node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/patch-package/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/patch-package/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/patch-package/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/patch-package/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/patch-package/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -6582,9 +6913,9 @@
}
},
"node_modules/prettier": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
- "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
@@ -6785,9 +7116,9 @@
}
},
"node_modules/react-error-boundary": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.3.tgz",
- "integrity": "sha512-A+F9HHy9fvt9t8SNDlonq01prnU8AmkjvGKV4kk8seB9kU3xMEO8J/PQlLVmoOIDODl5U2kufSBs4vrWIqhsAA==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
+ "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.12.5"
@@ -8473,6 +8804,15 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/yargs": {
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
@@ -8536,6 +8876,12 @@
}
},
"dependencies": {
+ "@adobe/css-tools": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz",
+ "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==",
+ "dev": true
+ },
"@babel/code-frame": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
@@ -9910,6 +10256,59 @@
"pretty-format": "^27.0.2"
}
},
+ "@testing-library/jest-dom": {
+ "version": "5.16.5",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz",
+ "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==",
+ "dev": true,
+ "requires": {
+ "@adobe/css-tools": "^4.0.1",
+ "@babel/runtime": "^7.9.2",
+ "@types/testing-library__jest-dom": "^5.9.1",
+ "aria-query": "^5.0.0",
+ "chalk": "^3.0.0",
+ "css.escape": "^1.5.1",
+ "dom-accessibility-api": "^0.5.6",
+ "lodash": "^4.17.15",
+ "redent": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ }
+ }
+ },
"@testing-library/react": {
"version": "13.4.0",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz",
@@ -10285,6 +10684,15 @@
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
"dev": true
},
+ "@types/testing-library__jest-dom": {
+ "version": "5.14.5",
+ "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz",
+ "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==",
+ "dev": true,
+ "requires": {
+ "@types/jest": "*"
+ }
+ },
"@types/tough-cookie": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz",
@@ -10336,6 +10744,12 @@
"tslib": "^2.1.0"
}
},
+ "@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true
+ },
"abab": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
@@ -10866,6 +11280,12 @@
"which": "^2.0.1"
}
},
+ "css.escape": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
+ "dev": true
+ },
"cssom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
@@ -11414,6 +11834,15 @@
"path-exists": "^4.0.0"
}
},
+ "find-yarn-workspace-root": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+ "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^4.0.2"
+ }
+ },
"find-yarn-workspace-root2": {
"version": "1.2.16",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz",
@@ -11863,6 +12292,12 @@
"has-tostringtag": "^1.0.0"
}
},
+ "is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true
+ },
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -12002,6 +12437,15 @@
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
+ "is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0"
+ }
+ },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -12946,6 +13390,15 @@
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
+ "klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
"kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -13193,6 +13646,12 @@
"brace-expansion": "^1.1.7"
}
},
+ "minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "dev": true
+ },
"minimist-options": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
@@ -13222,6 +13681,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -13355,6 +13820,16 @@
"mimic-fn": "^2.1.0"
}
},
+ "open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dev": true,
+ "requires": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ }
+ },
"optimism": {
"version": "0.16.1",
"resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.1.tgz",
@@ -13460,6 +13935,123 @@
"entities": "^4.4.0"
}
},
+ "patch-package": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.0.tgz",
+ "integrity": "sha512-tC3EqJmo74yKqfsMzELaFwxOAu6FH6t+FzFOsnWAuARm7/n2xB5AOeOueE221eM9gtMuIKMKpF9tBy/X2mNP0Q==",
+ "dev": true,
+ "requires": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "cross-spawn": "^6.0.5",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^7.0.1",
+ "is-ci": "^2.0.0",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "rimraf": "^2.6.3",
+ "semver": "^5.6.0",
+ "slash": "^2.0.0",
+ "tmp": "^0.0.33",
+ "yaml": "^1.10.2"
+ },
+ "dependencies": {
+ "ci-info": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "is-ci": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
+ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^2.0.0"
+ }
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "dev": true
+ },
+ "slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
+ },
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -13587,9 +14179,9 @@
"dev": true
},
"prettier": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz",
- "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true
},
"pretty-format": {
@@ -13735,9 +14327,9 @@
}
},
"react-error-boundary": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.3.tgz",
- "integrity": "sha512-A+F9HHy9fvt9t8SNDlonq01prnU8AmkjvGKV4kk8seB9kU3xMEO8J/PQlLVmoOIDODl5U2kufSBs4vrWIqhsAA==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
+ "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.12.5"
@@ -15025,6 +15617,12 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
+ "yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "dev": true
+ },
"yargs": {
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
diff --git a/package.json b/package.json
index 856626daa0b..52f5920a5e4 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"prebuild": "npm run clean",
"build": "tsc",
"postbuild": "npm run update-version && npm run invariants && npm run sourcemaps && npm run rollup && npm run prepdist && npm run postprocess-dist && npm run verify-version",
+ "postinstall": "patch-package",
"update-version": "node config/version.js update",
"verify-version": "node config/version.js verify",
"invariants": "ts-node-script config/processInvariants.ts",
@@ -102,6 +103,7 @@
"@changesets/cli": "2.25.2",
"@graphql-tools/schema": "9.0.10",
"@rollup/plugin-node-resolve": "11.2.1",
+ "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "13.4.0",
"@testing-library/react-12": "npm:@testing-library/react@^12",
"@testing-library/react-hooks": "8.0.1",
@@ -130,10 +132,13 @@
"jest-environment-jsdom": "29.3.1",
"jest-junit": "15.0.0",
"lodash": "4.17.21",
+ "patch-package": "6.5.0",
+ "prettier": "2.7.1",
"react": "18.2.0",
"react-17": "npm:react@^17",
"react-dom": "18.2.0",
"react-dom-17": "npm:react-dom@^17",
+ "react-error-boundary": "^3.1.4",
"recast": "0.21.5",
"resolve": "1.22.1",
"rimraf": "3.0.2",
@@ -152,5 +157,13 @@
},
"publishConfig": {
"access": "public"
+ },
+ "prettier": {
+ "bracketSpacing": true,
+ "printWidth": 80,
+ "semi": true,
+ "singleQuote": true,
+ "tabWidth": 2,
+ "trailingComma": "es5"
}
}
diff --git a/patches/@testing-library+react-12+12.1.5.patch b/patches/@testing-library+react-12+12.1.5.patch
new file mode 100644
index 00000000000..818d1cd989f
--- /dev/null
+++ b/patches/@testing-library+react-12+12.1.5.patch
@@ -0,0 +1,63 @@
+diff --git a/node_modules/@testing-library/react-12/dist/pure.js b/node_modules/@testing-library/react-12/dist/pure.js
+index 72287ac..f0d2c59 100644
+--- a/node_modules/@testing-library/react-12/dist/pure.js
++++ b/node_modules/@testing-library/react-12/dist/pure.js
+@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
+ });
+ var _exportNames = {
+ render: true,
++ renderHook: true,
+ cleanup: true,
+ act: true,
+ fireEvent: true
+@@ -25,6 +26,7 @@ Object.defineProperty(exports, "fireEvent", {
+ }
+ });
+ exports.render = render;
++exports.renderHook = renderHook;
+
+ var React = _interopRequireWildcard(require("react"));
+
+@@ -138,6 +140,42 @@ function cleanup() {
+ } // maybe one day we'll expose this (perhaps even as a utility returned by render).
+ // but let's wait until someone asks for it.
+
++function renderHook(renderCallback, options = {}) {
++ const {
++ initialProps,
++ ...renderOptions
++ } = options;
++ const result = /*#__PURE__*/React.createRef();
++
++ function TestComponent({
++ renderCallbackProps
++ }) {
++ const pendingResult = renderCallback(renderCallbackProps);
++ React.useEffect(() => {
++ result.current = pendingResult;
++ });
++ return null;
++ }
++
++ const {
++ rerender: baseRerender,
++ unmount
++ } = render( /*#__PURE__*/React.createElement(TestComponent, {
++ renderCallbackProps: initialProps
++ }), renderOptions);
++
++ function rerender(rerenderCallbackProps) {
++ return baseRerender( /*#__PURE__*/React.createElement(TestComponent, {
++ renderCallbackProps: rerenderCallbackProps
++ }));
++ }
++
++ return {
++ result,
++ rerender,
++ unmount
++ };
++} // just re-export everything from dom-testing-library
+
+ function cleanupAtContainer(container) {
+ (0, _actCompat.default)(() => {
diff --git a/src/__tests__/__snapshots__/exports.ts.snap b/src/__tests__/__snapshots__/exports.ts.snap
index b16e03c1870..ae513d67051 100644
--- a/src/__tests__/__snapshots__/exports.ts.snap
+++ b/src/__tests__/__snapshots__/exports.ts.snap
@@ -16,6 +16,7 @@ Array [
"NetworkStatus",
"Observable",
"ObservableQuery",
+ "SuspenseCache",
"checkFetcher",
"concat",
"createHttpLink",
@@ -59,6 +60,7 @@ Array [
"useQuery",
"useReactiveVar",
"useSubscription",
+ "useSuspenseQuery_experimental",
]
`;
@@ -239,6 +241,7 @@ Array [
"ApolloConsumer",
"ApolloProvider",
"DocumentType",
+ "SuspenseCache",
"getApolloContext",
"operationName",
"parser",
@@ -250,6 +253,7 @@ Array [
"useQuery",
"useReactiveVar",
"useSubscription",
+ "useSuspenseQuery_experimental",
]
`;
@@ -289,6 +293,7 @@ Array [
"useQuery",
"useReactiveVar",
"useSubscription",
+ "useSuspenseQuery_experimental",
]
`;
diff --git a/src/config/jest/setup.ts b/src/config/jest/setup.ts
index 911b1835cdc..49369785472 100644
--- a/src/config/jest/setup.ts
+++ b/src/config/jest/setup.ts
@@ -1,4 +1,5 @@
import gql from 'graphql-tag';
+import '@testing-library/jest-dom';
// Turn off warnings for repeated fragment names
gql.disableFragmentWarnings();
diff --git a/src/core/ObservableQuery.ts b/src/core/ObservableQuery.ts
index 1bc872da4c6..3fa3c6be091 100644
--- a/src/core/ObservableQuery.ts
+++ b/src/core/ObservableQuery.ts
@@ -110,6 +110,8 @@ export class ObservableQuery<
options: WatchQueryOptions;
}) {
super((observer: Observer>) => {
+ const { fetchOnFirstSubscribe = true } = options
+
// Zen Observable has its own error function, so in order to log correctly
// we need to provide a custom error callback.
try {
@@ -132,7 +134,7 @@ export class ObservableQuery<
// Initiate observation of this query if it hasn't been reported to
// the QueryManager yet.
- if (first) {
+ if (first && fetchOnFirstSubscribe) {
// Blindly catching here prevents unhandled promise rejections,
// and is safe because the ObservableQuery handles this error with
// this.observer.error, so we're not just swallowing the error by
diff --git a/src/core/watchQueryOptions.ts b/src/core/watchQueryOptions.ts
index 676dc7253de..4053fbe236a 100644
--- a/src/core/watchQueryOptions.ts
+++ b/src/core/watchQueryOptions.ts
@@ -145,6 +145,12 @@ export interface WatchQueryOptions
* behavior, for backwards compatibility with Apollo Client 3.x.
*/
refetchWritePolicy?: RefetchWritePolicy;
+
+ /**
+ * Determines whether the observable should execute a request when the first
+ * observer subscribes to it.
+ */
+ fetchOnFirstSubscribe?: boolean
}
export interface NextFetchPolicyContext {
diff --git a/src/react/cache/SuspenseCache.ts b/src/react/cache/SuspenseCache.ts
new file mode 100644
index 00000000000..b1cd168a94f
--- /dev/null
+++ b/src/react/cache/SuspenseCache.ts
@@ -0,0 +1,87 @@
+import {
+ ApolloQueryResult,
+ DocumentNode,
+ ObservableQuery,
+ OperationVariables,
+ TypedDocumentNode,
+} from '../../core';
+import { canonicalStringify } from '../../cache';
+
+interface CacheEntry {
+ observable: ObservableQuery;
+ fulfilled: boolean;
+ promise: Promise>;
+}
+
+export class SuspenseCache {
+ private queries = new Map<
+ DocumentNode,
+ Map>
+ >();
+
+ add(
+ query: DocumentNode | TypedDocumentNode,
+ variables: TVariables | undefined,
+ {
+ promise,
+ observable,
+ }: { promise: Promise; observable: ObservableQuery }
+ ) {
+ const variablesKey = this.getVariablesKey(variables);
+ const map = this.queries.get(query) || new Map();
+
+ const entry: CacheEntry = {
+ observable,
+ fulfilled: false,
+ promise: promise
+ .catch(() => {
+ // Throw away the error as we only care to track when the promise has
+ // been fulfilled
+ })
+ .finally(() => {
+ entry.fulfilled = true;
+ }),
+ };
+
+ map.set(variablesKey, entry);
+
+ this.queries.set(query, map);
+
+ return entry;
+ }
+
+ lookup<
+ TData = any,
+ TVariables extends OperationVariables = OperationVariables
+ >(
+ query: DocumentNode | TypedDocumentNode,
+ variables: TVariables | undefined
+ ): CacheEntry | undefined {
+ return this.queries
+ .get(query)
+ ?.get(this.getVariablesKey(variables)) as CacheEntry;
+ }
+
+ remove(query: DocumentNode, variables: OperationVariables | undefined) {
+ const map = this.queries.get(query);
+
+ if (!map) {
+ return;
+ }
+
+ const key = this.getVariablesKey(variables);
+ const entry = map.get(key);
+
+ if (entry && !entry.observable.hasObservers()) {
+ map.delete(key);
+ }
+
+ if (map.size === 0) {
+ this.queries.delete(query);
+ }
+ }
+
+ private getVariablesKey(variables: OperationVariables | undefined) {
+ return canonicalStringify(variables || Object.create(null));
+ }
+}
diff --git a/src/react/cache/index.ts b/src/react/cache/index.ts
new file mode 100644
index 00000000000..534c51cda6e
--- /dev/null
+++ b/src/react/cache/index.ts
@@ -0,0 +1 @@
+export { SuspenseCache } from './SuspenseCache';
diff --git a/src/react/context/ApolloContext.ts b/src/react/context/ApolloContext.ts
index d64f0c3e39f..2453a6356de 100644
--- a/src/react/context/ApolloContext.ts
+++ b/src/react/context/ApolloContext.ts
@@ -1,11 +1,13 @@
import * as React from 'react';
import { ApolloClient } from '../../core';
import { canUseSymbol } from '../../utilities';
+import { SuspenseCache } from '../cache';
import type { RenderPromises } from '../ssr';
export interface ApolloContextValue {
client?: ApolloClient