diff --git a/.gitignore b/.gitignore
index 03a3194..efe2f49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
node_modules/
dist/
-extension.zip
\ No newline at end of file
+extension.zip
+*.tsbuildinfo
diff --git a/examples/swr-devtools-demo/package.json b/examples/swr-devtools-demo/package.json
index a388c35..9ef8f02 100644
--- a/examples/swr-devtools-demo/package.json
+++ b/examples/swr-devtools-demo/package.json
@@ -14,7 +14,7 @@
"react-dom": "17.0.2",
"styled-components": "^5.3.0",
"sugar-high": "^0.4.2",
- "swr": "^1.1.0"
+ "swr": "^2.0.0-beta.2"
},
"devDependencies": {
"@types/node": "^14.14.27",
diff --git a/examples/swr-devtools-demo/tsconfig.json b/examples/swr-devtools-demo/tsconfig.json
index 5bee8c4..37588c0 100644
--- a/examples/swr-devtools-demo/tsconfig.json
+++ b/examples/swr-devtools-demo/tsconfig.json
@@ -17,7 +17,6 @@
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
- "incremental": true
},
"include": [
"next-env.d.ts",
diff --git a/examples/swr-v1-devtools-demo/.babelrc b/examples/swr-v1-devtools-demo/.babelrc
new file mode 100644
index 0000000..01c31d1
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["next/babel"],
+ "plugins": [["styled-components", { "ssr": true }]]
+ }
\ No newline at end of file
diff --git a/examples/swr-v1-devtools-demo/.gitignore b/examples/swr-v1-devtools-demo/.gitignore
new file mode 100644
index 0000000..8c495ad
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+.tsbuildinfo
\ No newline at end of file
diff --git a/examples/swr-v1-devtools-demo/LICENSE b/examples/swr-v1-devtools-demo/LICENSE
new file mode 100644
index 0000000..6c23b9c
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Toru Kobayashi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/examples/swr-v1-devtools-demo/README.md b/examples/swr-v1-devtools-demo/README.md
new file mode 100644
index 0000000..b12f3e3
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/README.md
@@ -0,0 +1,34 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
+
+[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
+
+The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/examples/swr-v1-devtools-demo/components/DevToolsView.tsx b/examples/swr-v1-devtools-demo/components/DevToolsView.tsx
new file mode 100644
index 0000000..57316a7
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/components/DevToolsView.tsx
@@ -0,0 +1,17 @@
+import { useSWRConfig } from "swr";
+import { SWRDevToolPanel } from "swr-devtools-panel";
+
+// The way to use SWR DevTools as a React Component
+export const DevToolsView = () => {
+ const { cache } = useSWRConfig();
+ return (
+
+
+
+ );
+};
diff --git a/examples/swr-v1-devtools-demo/next-env.d.ts b/examples/swr-v1-devtools-demo/next-env.d.ts
new file mode 100644
index 0000000..4f11a03
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/swr-v1-devtools-demo/package.json b/examples/swr-v1-devtools-demo/package.json
new file mode 100644
index 0000000..0742918
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "swr-v1-devtools-demo",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "tsc --noEmit"
+ },
+ "dependencies": {
+ "next": "^12.0.7",
+ "react": "17.0.2",
+ "react-dom": "17.0.2",
+ "styled-components": "^5.3.0",
+ "sugar-high": "^0.4.2",
+ "swr": "^1.3.0"
+ },
+ "devDependencies": {
+ "@types/node": "^14.14.27",
+ "babel-plugin-styled-components": "^1.13.2"
+ }
+}
diff --git a/examples/swr-v1-devtools-demo/pages/_app.tsx b/examples/swr-v1-devtools-demo/pages/_app.tsx
new file mode 100644
index 0000000..0632f1f
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/_app.tsx
@@ -0,0 +1,24 @@
+import "../styles/globals.css";
+import { SWRConfig } from "swr";
+import { SWRDevTools } from "swr-devtools";
+
+const fetcher = async (url) => {
+ const res = await fetch(url);
+ const json = await res.json();
+ if (res.ok) {
+ return json;
+ }
+ throw new Error(json.message);
+};
+
+function MyApp({ Component, pageProps }) {
+ return (
+
+
+
+
+
+ );
+}
+
+export default MyApp;
diff --git a/examples/swr-v1-devtools-demo/pages/_document.tsx b/examples/swr-v1-devtools-demo/pages/_document.tsx
new file mode 100644
index 0000000..96d1213
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/_document.tsx
@@ -0,0 +1,30 @@
+import Document, { DocumentContext } from "next/document";
+import { ServerStyleSheet } from "styled-components";
+
+export default class MyDocument extends Document {
+ static async getInitialProps(ctx: DocumentContext) {
+ const sheet = new ServerStyleSheet();
+ const originalRenderPage = ctx.renderPage;
+
+ try {
+ ctx.renderPage = () =>
+ originalRenderPage({
+ enhanceApp: (App) => (props) =>
+ sheet.collectStyles( ),
+ });
+
+ const initialProps = await Document.getInitialProps(ctx);
+ return {
+ ...initialProps,
+ styles: (
+ <>
+ {initialProps.styles}
+ {sheet.getStyleElement()}
+ >
+ ),
+ };
+ } finally {
+ sheet.seal();
+ }
+ }
+}
diff --git a/examples/swr-v1-devtools-demo/pages/api/hello.ts b/examples/swr-v1-devtools-demo/pages/api/hello.ts
new file mode 100644
index 0000000..3ad7b18
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/api/hello.ts
@@ -0,0 +1,12 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+let counter = 1;
+
+export default (req, res) => {
+ ++counter;
+ if (req.query.error) {
+ res.status(500).json({ message: "this is an error message" });
+ } else {
+ res.status(200).json({ name: `Hello World ${counter}` });
+ }
+};
diff --git a/examples/swr-v1-devtools-demo/pages/api/list.ts b/examples/swr-v1-devtools-demo/pages/api/list.ts
new file mode 100644
index 0000000..6728134
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/api/list.ts
@@ -0,0 +1,74 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+const pages = {
+ 1: [
+ {
+ name: "Array.prototype.at()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at",
+ },
+ {
+ name: "Array.prototype.concat()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat",
+ },
+ {
+ name: "Array.prototype.copyWithin()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin",
+ },
+ {
+ name: "Array.prototype.entries()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries",
+ },
+ {
+ name: "Array.prototype.every()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every",
+ },
+ ],
+ 2: [
+ {
+ name: "HTMLElement.accessKey",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/accessKey",
+ },
+ {
+ name: "HTMLElement.contentEditable",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/contentEditable",
+ },
+ {
+ name: "HTMLElement.inert",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert",
+ },
+ {
+ name: "HTMLElement.nonce",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/nonce",
+ },
+ {
+ name: "HTMLElement.tabIndex",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/tabIndex",
+ },
+ ],
+ 3: [
+ {
+ name: "animation",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/animation",
+ },
+ {
+ name: "background",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/background",
+ },
+ {
+ name: "border",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/border",
+ },
+ {
+ name: "display",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/display",
+ },
+ {
+ name: "env()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/env()",
+ },
+ ],
+};
+
+export default (req, res) => {
+ res.status(200).json(pages[req.query.page] || null);
+};
diff --git a/examples/swr-v1-devtools-demo/pages/index.tsx b/examples/swr-v1-devtools-demo/pages/index.tsx
new file mode 100644
index 0000000..a89a3e0
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/index.tsx
@@ -0,0 +1,135 @@
+import Head from "next/head";
+import Link from "next/link";
+import { highlight } from "sugar-high";
+import styles from "../styles/Home.module.css";
+import useSWR from "swr";
+import { useEffect } from "react";
+import { DevToolsView } from "../components/DevToolsView";
+
+export default function Home() {
+ // const { data, mutate } = useSWR("/api/hello?error=true");
+ const { data, mutate, error } = useSWR(
+ `/api/hello${typeof window !== "undefined" ? location.search : ""}`
+ );
+ const { data: data2 } = useSWR("/api/hello?foo");
+
+ useEffect(() => {
+ const timerId = setInterval(() => {
+ mutate();
+ }, 5000);
+ return () => clearInterval(timerId);
+ }, [mutate]);
+
+ return (
+
+
+
SWR DevTools
+
+
+
+
+
+
+ Download
+
+ You can download SWRDevTools extensions at the following.
+
+
+
+
+ How to use
+
+ First, you can install swr-devtools
and wrap your app
+ with the SWRDevTools
component
+
+
+
+
+ ,
+ document.getElementById("app")
+);
+ `),
+ }}
+ />
+
+
+ Then, open the SWR Devtools from the browser's developer tools
+
+
+
+ Online Demo
+
+
App
+
+
+ /api/hello
+ {!data && !error && ...loading }
+ {data && {data.name} }
+ {error && Error: {error.message} }
+
+ (auto increment in 5 seconds)
+
+
+
+ /api/hello?foo
+ {data2 ? data2.name : "...loading"}
+
+
+
+
+
+
+ You can check{" "}
+ an example with useSWRInfinte.
+
+
+
+
+ );
+}
diff --git a/examples/swr-v1-devtools-demo/pages/infinite.tsx b/examples/swr-v1-devtools-demo/pages/infinite.tsx
new file mode 100644
index 0000000..86941da
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/pages/infinite.tsx
@@ -0,0 +1,53 @@
+import Head from "next/head";
+import Link from "next/link";
+import useSWRInfinite from "swr/infinite";
+import { DevToolsView } from "../components/DevToolsView";
+
+import styles from "../styles/infinite.module.css";
+
+export default function Home() {
+ const { data, setSize } = useSWRInfinite(
+ (index) => `/api/list?page=${index + 1}`
+ );
+
+ const pages = data ? data.reduce((acc, page) => acc.concat(page), []) : [];
+
+ return (
+
+
+
SWR DevTools Demo (useSWRInfinite)
+
+
+
+
+ SWR DevTools Demo (useSWRInfinite)
+
+
+
+ setSize((size) => size + 1)}
+ >
+ Load more
+
+
+
+
+ Top
+
+
+
+
+
+ );
+}
diff --git a/examples/swr-v1-devtools-demo/public/favicon.ico b/examples/swr-v1-devtools-demo/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/examples/swr-v1-devtools-demo/public/favicon.ico differ
diff --git a/examples/swr-v1-devtools-demo/public/vercel.svg b/examples/swr-v1-devtools-demo/public/vercel.svg
new file mode 100644
index 0000000..fbf0e25
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/public/vercel.svg
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/examples/swr-v1-devtools-demo/styles/Home.module.css b/examples/swr-v1-devtools-demo/styles/Home.module.css
new file mode 100644
index 0000000..f9eb297
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/styles/Home.module.css
@@ -0,0 +1,83 @@
+.container {
+ min-height: 100vh;
+ padding: 0;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.main {
+ width: 80%;
+ margin: 0 auto;
+ padding: 0;
+}
+
+.header {
+ text-align: center;
+
+}
+
+.header > h1 {
+ width: 100%;
+ margin: 0.2rem 0.5rem;
+}
+
+.row {
+ display: grid;
+ grid-template-columns: 1fr 1fr 2fr;
+ gap: 0.4rem;
+ padding-bottom: 0.2rem;
+ border-bottom: solid 1px #ccc;
+}
+
+.cacheKey {
+ font-weight: bold;
+}
+
+.subTitle {
+ font-size: 1.8rem;
+ margin: 1rem 0;
+ border-bottom: solid 1px rgba(128 128 128 / 20%)
+}
+
+.paragraph {
+ margin: 0.2rem 0;
+}
+
+.title {
+ display: inline-block;
+ padding-inline-end: 1rem;
+ line-height: 1.15;
+ font-size: 3rem;
+ font-weight: bold;
+ text-align: center;
+}
+
+.list {
+ margin: 0.5rem 0 0 1.2rem;
+ line-height: 1.5;
+}
+
+.section {
+ margin: 2rem 0;
+}
+
+.demo {
+ box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ background-color: #fff;
+ width: 100%;
+}
+
+.demo > h3 {
+ margin: 0.3rem;
+ padding-top: 0.3rem;
+}
+
+.demoApp {
+ padding: 0.3rem;
+}
+
+.footer {
+ text-align: center;;
+}
\ No newline at end of file
diff --git a/examples/swr-v1-devtools-demo/styles/globals.css b/examples/swr-v1-devtools-demo/styles/globals.css
new file mode 100644
index 0000000..67d8e7f
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/styles/globals.css
@@ -0,0 +1,32 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ background-color: #fafafa;
+}
+ul {
+ padding: 0;
+}
+
+/**
+ * Types that sugar-high have:
+ *
+ * identifier
+ * keyword
+ * string
+ * Class, number and null
+ * sign
+ * comment
+ * jsxliterals
+ */
+ :root {
+ --sh-class: #2d5e9d;
+ --sh-identifier: #354150;
+ --sh-sign: #8996a3;
+ --sh-string: #00a99a;
+ --sh-keyword: #f47067;
+ --sh-comment: #a19595;
+ --sh-jsxliterals: #6266d1;
+}
\ No newline at end of file
diff --git a/examples/swr-v1-devtools-demo/styles/infinite.module.css b/examples/swr-v1-devtools-demo/styles/infinite.module.css
new file mode 100644
index 0000000..dd083cf
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/styles/infinite.module.css
@@ -0,0 +1,55 @@
+.container {
+ min-height: 100vh;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.main {
+ padding: 0;
+ flex: 1;
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+}
+
+.list {
+ margin: 0 auto;
+ max-width: 80%;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ list-style: none;
+}
+
+.listItem {
+ font-size: 1.2rem;
+}
+
+.buttonArea {
+ display: flex;
+ justify-content: center;
+ padding: 1rem;
+}
+.button {
+ font-size: 1rem;
+ padding: 0.3rem 0.5rem;
+ border-radius: 5px;
+ border: solid 2px #ccc;
+}
+
+.nav {
+ font-size: 1.2rem;
+ text-align: center;
+}
+
+.title {
+ line-height: 1.15;
+ font-size: 3rem;
+ text-align: center;
+}
+
diff --git a/examples/swr-v1-devtools-demo/tsconfig.json b/examples/swr-v1-devtools-demo/tsconfig.json
new file mode 100644
index 0000000..37588c0
--- /dev/null
+++ b/examples/swr-v1-devtools-demo/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/examples/swr-v1-legacy-devtools-demo/.babelrc b/examples/swr-v1-legacy-devtools-demo/.babelrc
new file mode 100644
index 0000000..01c31d1
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["next/babel"],
+ "plugins": [["styled-components", { "ssr": true }]]
+ }
\ No newline at end of file
diff --git a/examples/swr-v1-legacy-devtools-demo/.gitignore b/examples/swr-v1-legacy-devtools-demo/.gitignore
new file mode 100644
index 0000000..8c495ad
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+.tsbuildinfo
\ No newline at end of file
diff --git a/examples/swr-v1-legacy-devtools-demo/LICENSE b/examples/swr-v1-legacy-devtools-demo/LICENSE
new file mode 100644
index 0000000..6c23b9c
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Toru Kobayashi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/examples/swr-v1-legacy-devtools-demo/README.md b/examples/swr-v1-legacy-devtools-demo/README.md
new file mode 100644
index 0000000..b12f3e3
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/README.md
@@ -0,0 +1,34 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
+
+[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`.
+
+The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/examples/swr-v1-legacy-devtools-demo/components/DevToolsView.tsx b/examples/swr-v1-legacy-devtools-demo/components/DevToolsView.tsx
new file mode 100644
index 0000000..57316a7
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/components/DevToolsView.tsx
@@ -0,0 +1,17 @@
+import { useSWRConfig } from "swr";
+import { SWRDevToolPanel } from "swr-devtools-panel";
+
+// The way to use SWR DevTools as a React Component
+export const DevToolsView = () => {
+ const { cache } = useSWRConfig();
+ return (
+
+
+
+ );
+};
diff --git a/examples/swr-v1-legacy-devtools-demo/next-env.d.ts b/examples/swr-v1-legacy-devtools-demo/next-env.d.ts
new file mode 100644
index 0000000..4f11a03
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/examples/swr-v1-legacy-devtools-demo/package.json b/examples/swr-v1-legacy-devtools-demo/package.json
new file mode 100644
index 0000000..ba7ba25
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "swr-v1-legacy-devtools-demo",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "tsc --noEmit"
+ },
+ "dependencies": {
+ "next": "^12.0.7",
+ "react": "17.0.2",
+ "react-dom": "17.0.2",
+ "styled-components": "^5.3.0",
+ "sugar-high": "^0.4.2",
+ "swr": "1.1.x"
+ },
+ "devDependencies": {
+ "@types/node": "^14.14.27",
+ "babel-plugin-styled-components": "^1.13.2"
+ }
+}
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/_app.tsx b/examples/swr-v1-legacy-devtools-demo/pages/_app.tsx
new file mode 100644
index 0000000..0632f1f
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/_app.tsx
@@ -0,0 +1,24 @@
+import "../styles/globals.css";
+import { SWRConfig } from "swr";
+import { SWRDevTools } from "swr-devtools";
+
+const fetcher = async (url) => {
+ const res = await fetch(url);
+ const json = await res.json();
+ if (res.ok) {
+ return json;
+ }
+ throw new Error(json.message);
+};
+
+function MyApp({ Component, pageProps }) {
+ return (
+
+
+
+
+
+ );
+}
+
+export default MyApp;
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/_document.tsx b/examples/swr-v1-legacy-devtools-demo/pages/_document.tsx
new file mode 100644
index 0000000..96d1213
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/_document.tsx
@@ -0,0 +1,30 @@
+import Document, { DocumentContext } from "next/document";
+import { ServerStyleSheet } from "styled-components";
+
+export default class MyDocument extends Document {
+ static async getInitialProps(ctx: DocumentContext) {
+ const sheet = new ServerStyleSheet();
+ const originalRenderPage = ctx.renderPage;
+
+ try {
+ ctx.renderPage = () =>
+ originalRenderPage({
+ enhanceApp: (App) => (props) =>
+ sheet.collectStyles( ),
+ });
+
+ const initialProps = await Document.getInitialProps(ctx);
+ return {
+ ...initialProps,
+ styles: (
+ <>
+ {initialProps.styles}
+ {sheet.getStyleElement()}
+ >
+ ),
+ };
+ } finally {
+ sheet.seal();
+ }
+ }
+}
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/api/hello.ts b/examples/swr-v1-legacy-devtools-demo/pages/api/hello.ts
new file mode 100644
index 0000000..3ad7b18
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/api/hello.ts
@@ -0,0 +1,12 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+let counter = 1;
+
+export default (req, res) => {
+ ++counter;
+ if (req.query.error) {
+ res.status(500).json({ message: "this is an error message" });
+ } else {
+ res.status(200).json({ name: `Hello World ${counter}` });
+ }
+};
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/api/list.ts b/examples/swr-v1-legacy-devtools-demo/pages/api/list.ts
new file mode 100644
index 0000000..6728134
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/api/list.ts
@@ -0,0 +1,74 @@
+// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
+
+const pages = {
+ 1: [
+ {
+ name: "Array.prototype.at()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at",
+ },
+ {
+ name: "Array.prototype.concat()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat",
+ },
+ {
+ name: "Array.prototype.copyWithin()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/copyWithin",
+ },
+ {
+ name: "Array.prototype.entries()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries",
+ },
+ {
+ name: "Array.prototype.every()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every",
+ },
+ ],
+ 2: [
+ {
+ name: "HTMLElement.accessKey",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/accessKey",
+ },
+ {
+ name: "HTMLElement.contentEditable",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/contentEditable",
+ },
+ {
+ name: "HTMLElement.inert",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert",
+ },
+ {
+ name: "HTMLElement.nonce",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/nonce",
+ },
+ {
+ name: "HTMLElement.tabIndex",
+ url: "https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/tabIndex",
+ },
+ ],
+ 3: [
+ {
+ name: "animation",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/animation",
+ },
+ {
+ name: "background",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/background",
+ },
+ {
+ name: "border",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/border",
+ },
+ {
+ name: "display",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/display",
+ },
+ {
+ name: "env()",
+ url: "https://developer.mozilla.org/en-US/docs/Web/CSS/env()",
+ },
+ ],
+};
+
+export default (req, res) => {
+ res.status(200).json(pages[req.query.page] || null);
+};
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/index.tsx b/examples/swr-v1-legacy-devtools-demo/pages/index.tsx
new file mode 100644
index 0000000..a89a3e0
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/index.tsx
@@ -0,0 +1,135 @@
+import Head from "next/head";
+import Link from "next/link";
+import { highlight } from "sugar-high";
+import styles from "../styles/Home.module.css";
+import useSWR from "swr";
+import { useEffect } from "react";
+import { DevToolsView } from "../components/DevToolsView";
+
+export default function Home() {
+ // const { data, mutate } = useSWR("/api/hello?error=true");
+ const { data, mutate, error } = useSWR(
+ `/api/hello${typeof window !== "undefined" ? location.search : ""}`
+ );
+ const { data: data2 } = useSWR("/api/hello?foo");
+
+ useEffect(() => {
+ const timerId = setInterval(() => {
+ mutate();
+ }, 5000);
+ return () => clearInterval(timerId);
+ }, [mutate]);
+
+ return (
+
+
+
SWR DevTools
+
+
+
+
+
+
+ Download
+
+ You can download SWRDevTools extensions at the following.
+
+
+
+
+ How to use
+
+ First, you can install swr-devtools
and wrap your app
+ with the SWRDevTools
component
+
+
+
+
+ ,
+ document.getElementById("app")
+);
+ `),
+ }}
+ />
+
+
+ Then, open the SWR Devtools from the browser's developer tools
+
+
+
+ Online Demo
+
+
App
+
+
+ /api/hello
+ {!data && !error && ...loading }
+ {data && {data.name} }
+ {error && Error: {error.message} }
+
+ (auto increment in 5 seconds)
+
+
+
+ /api/hello?foo
+ {data2 ? data2.name : "...loading"}
+
+
+
+
+
+
+ You can check{" "}
+ an example with useSWRInfinte.
+
+
+
+
+ );
+}
diff --git a/examples/swr-v1-legacy-devtools-demo/pages/infinite.tsx b/examples/swr-v1-legacy-devtools-demo/pages/infinite.tsx
new file mode 100644
index 0000000..86941da
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/pages/infinite.tsx
@@ -0,0 +1,53 @@
+import Head from "next/head";
+import Link from "next/link";
+import useSWRInfinite from "swr/infinite";
+import { DevToolsView } from "../components/DevToolsView";
+
+import styles from "../styles/infinite.module.css";
+
+export default function Home() {
+ const { data, setSize } = useSWRInfinite(
+ (index) => `/api/list?page=${index + 1}`
+ );
+
+ const pages = data ? data.reduce((acc, page) => acc.concat(page), []) : [];
+
+ return (
+
+
+
SWR DevTools Demo (useSWRInfinite)
+
+
+
+
+ SWR DevTools Demo (useSWRInfinite)
+
+
+
+ setSize((size) => size + 1)}
+ >
+ Load more
+
+
+
+
+ Top
+
+
+
+
+
+ );
+}
diff --git a/examples/swr-v1-legacy-devtools-demo/public/favicon.ico b/examples/swr-v1-legacy-devtools-demo/public/favicon.ico
new file mode 100644
index 0000000..4965832
Binary files /dev/null and b/examples/swr-v1-legacy-devtools-demo/public/favicon.ico differ
diff --git a/examples/swr-v1-legacy-devtools-demo/public/vercel.svg b/examples/swr-v1-legacy-devtools-demo/public/vercel.svg
new file mode 100644
index 0000000..fbf0e25
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/public/vercel.svg
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/examples/swr-v1-legacy-devtools-demo/styles/Home.module.css b/examples/swr-v1-legacy-devtools-demo/styles/Home.module.css
new file mode 100644
index 0000000..f9eb297
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/styles/Home.module.css
@@ -0,0 +1,83 @@
+.container {
+ min-height: 100vh;
+ padding: 0;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.main {
+ width: 80%;
+ margin: 0 auto;
+ padding: 0;
+}
+
+.header {
+ text-align: center;
+
+}
+
+.header > h1 {
+ width: 100%;
+ margin: 0.2rem 0.5rem;
+}
+
+.row {
+ display: grid;
+ grid-template-columns: 1fr 1fr 2fr;
+ gap: 0.4rem;
+ padding-bottom: 0.2rem;
+ border-bottom: solid 1px #ccc;
+}
+
+.cacheKey {
+ font-weight: bold;
+}
+
+.subTitle {
+ font-size: 1.8rem;
+ margin: 1rem 0;
+ border-bottom: solid 1px rgba(128 128 128 / 20%)
+}
+
+.paragraph {
+ margin: 0.2rem 0;
+}
+
+.title {
+ display: inline-block;
+ padding-inline-end: 1rem;
+ line-height: 1.15;
+ font-size: 3rem;
+ font-weight: bold;
+ text-align: center;
+}
+
+.list {
+ margin: 0.5rem 0 0 1.2rem;
+ line-height: 1.5;
+}
+
+.section {
+ margin: 2rem 0;
+}
+
+.demo {
+ box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.1);
+ border-radius: 8px;
+ background-color: #fff;
+ width: 100%;
+}
+
+.demo > h3 {
+ margin: 0.3rem;
+ padding-top: 0.3rem;
+}
+
+.demoApp {
+ padding: 0.3rem;
+}
+
+.footer {
+ text-align: center;;
+}
\ No newline at end of file
diff --git a/examples/swr-v1-legacy-devtools-demo/styles/globals.css b/examples/swr-v1-legacy-devtools-demo/styles/globals.css
new file mode 100644
index 0000000..67d8e7f
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/styles/globals.css
@@ -0,0 +1,32 @@
+html,
+body {
+ padding: 0;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+ background-color: #fafafa;
+}
+ul {
+ padding: 0;
+}
+
+/**
+ * Types that sugar-high have:
+ *
+ * identifier
+ * keyword
+ * string
+ * Class, number and null
+ * sign
+ * comment
+ * jsxliterals
+ */
+ :root {
+ --sh-class: #2d5e9d;
+ --sh-identifier: #354150;
+ --sh-sign: #8996a3;
+ --sh-string: #00a99a;
+ --sh-keyword: #f47067;
+ --sh-comment: #a19595;
+ --sh-jsxliterals: #6266d1;
+}
\ No newline at end of file
diff --git a/examples/swr-v1-legacy-devtools-demo/styles/infinite.module.css b/examples/swr-v1-legacy-devtools-demo/styles/infinite.module.css
new file mode 100644
index 0000000..dd083cf
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/styles/infinite.module.css
@@ -0,0 +1,55 @@
+.container {
+ min-height: 100vh;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+
+.main {
+ padding: 0;
+ flex: 1;
+}
+
+.content {
+ display: flex;
+ flex-direction: column;
+}
+
+.list {
+ margin: 0 auto;
+ max-width: 80%;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ list-style: none;
+}
+
+.listItem {
+ font-size: 1.2rem;
+}
+
+.buttonArea {
+ display: flex;
+ justify-content: center;
+ padding: 1rem;
+}
+.button {
+ font-size: 1rem;
+ padding: 0.3rem 0.5rem;
+ border-radius: 5px;
+ border: solid 2px #ccc;
+}
+
+.nav {
+ font-size: 1.2rem;
+ text-align: center;
+}
+
+.title {
+ line-height: 1.15;
+ font-size: 3rem;
+ text-align: center;
+}
+
diff --git a/examples/swr-v1-legacy-devtools-demo/tsconfig.json b/examples/swr-v1-legacy-devtools-demo/tsconfig.json
new file mode 100644
index 0000000..37588c0
--- /dev/null
+++ b/examples/swr-v1-legacy-devtools-demo/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/package.json b/package.json
index 55ceffc..0f7c07d 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,8 @@
"start:extensions": "yarn workspace swr-devtools-extensions start",
"start:panel": "yarn workspace swr-devtools-panel start",
"start": "run-p -l start:*",
+ "v1": "yarn workspace swr-v1-devtools-demo dev",
+ "v1-legacy": "yarn workspace swr-v1-legacy-devtools-demo dev",
"lint:eslint": "eslint '**/pages/**/*' '**/src/**/*'",
"lint:tsc": "yarn workspaces run lint",
"lint": "run-p -l lint:*"
diff --git a/packages/swr-devtools-extensions/package.json b/packages/swr-devtools-extensions/package.json
index 09c920e..7d2d7ca 100644
--- a/packages/swr-devtools-extensions/package.json
+++ b/packages/swr-devtools-extensions/package.json
@@ -20,6 +20,7 @@
"@types/react-dom": "^17.0.9",
"@types/webextension-polyfill": "^0.8.0",
"copy-webpack-plugin": "^9.0.1",
+ "swr": "^2.0.0-beta.2",
"ts-loader": "^9.2.3",
"typescript": "^4.3.5",
"web-ext": "^6.5.0",
diff --git a/packages/swr-devtools-panel/package.json b/packages/swr-devtools-panel/package.json
index 4fe8358..18af023 100644
--- a/packages/swr-devtools-panel/package.json
+++ b/packages/swr-devtools-panel/package.json
@@ -33,14 +33,14 @@
"peerDependencies": {
"react": "^17.0.2",
"styled-components": "^5.3.0",
- "swr": "^1.0.0"
+ "swr": ">=1.0.0"
},
"devDependencies": {
"@types/react": "^17.0.16",
"@types/styled-components": "^5.1.12",
"react": "^17.0.2",
"styled-components": "^5.3.0",
- "swr": "^1.0.0",
+ "swr": "^2.0.0-beta.2",
"typescript": "^4.1.3"
},
"dependencies": {
diff --git a/packages/swr-devtools-panel/src/components/CacheData.tsx b/packages/swr-devtools-panel/src/components/CacheData.tsx
index bec754f..428c837 100644
--- a/packages/swr-devtools-panel/src/components/CacheData.tsx
+++ b/packages/swr-devtools-panel/src/components/CacheData.tsx
@@ -6,23 +6,32 @@ import { CacheKey } from "./CacheKey";
import { ErrorLabel } from "./ErrorLabel";
type Props = {
- data: SWRCacheData;
+ cache: SWRCacheData;
};
-export const CacheData = React.memo(({ data }: Props) => (
-
-
- {data.error && }
-
-
- {data.timestampString}
-
-
- {data.data && }
- {data.error && }
-
-
-));
+export const CacheData = React.memo(
+ ({
+ cache: {
+ // @ts-ignore
+ cache: { data, error },
+ key,
+ timestampString,
+ },
+ }: Props) => (
+
+
+ {error && }
+
+
+ {timestampString}
+
+
+ {data && }
+ {error && }
+
+
+ )
+);
CacheData.displayName = "CacheData";
const ErrorData = ({ error }: { error: string | ReactJsonViewProps }) => (
diff --git a/packages/swr-devtools-panel/src/components/Panel.tsx b/packages/swr-devtools-panel/src/components/Panel.tsx
index bc007a2..40b8efc 100644
--- a/packages/swr-devtools-panel/src/components/Panel.tsx
+++ b/packages/swr-devtools-panel/src/components/Panel.tsx
@@ -23,7 +23,6 @@ export const Panel = ({
const [currentCache, historyCache] = useDevToolsCache(cache);
const [filterText, setFilterText] = useState("");
const cacheData = type === "history" ? historyCache : currentCache;
-
const currentData =
selectedItemKey &&
cacheData.find(
@@ -41,7 +40,8 @@ export const Panel = ({
{cacheData
.filter(({ key }) => filterText === "" || key.includes(filterText))
- .map(({ key, error, timestampString, timestamp }) => (
+ // @ts-ignore
+ .map(({ key, cache: { error }, timestampString, timestamp }) => (
- {currentData && }
+ {currentData && }
);
};
diff --git a/packages/swr-devtools-panel/src/devtools-cache.ts b/packages/swr-devtools-panel/src/devtools-cache.ts
index 3d41d41..dec526c 100644
--- a/packages/swr-devtools-panel/src/devtools-cache.ts
+++ b/packages/swr-devtools-panel/src/devtools-cache.ts
@@ -4,37 +4,19 @@ import { Cache } from "swr";
import {
injectSWRCache,
isMetaCache,
- isErrorCache,
- getErrorCacheKey,
SWRCacheData,
+ convertCacheData,
} from "swr-devtools/lib/swr-cache";
-type DevToolsCache = {
- get(key: string): Value;
- set(key: string, value: Value): void;
- delete(key: string): void;
- // TODO: should support a delete method
- subscribe(fn: (key: string, value: Value) => void): () => void;
-};
+type Subscribe = (fn: (key: string, value: any) => void) => () => void;
-const createDevToolsCache = (cache: Cache): DevToolsCache => {
+const createDevToolsCache = (cache: Cache) => {
let listeners: Array<(key: string, value: any) => void> = [];
- const store: DevToolsCache = {
- get(key) {
- return cache.get(key);
- },
- set(key, value) {
- cache.set(key, value);
- },
- delete(key) {
- cache.delete(key);
- },
- subscribe(callback) {
- listeners.push(callback);
- return () => {
- listeners = [];
- };
- },
+ const subscribe: Subscribe = (callback) => {
+ listeners.push(callback);
+ return () => {
+ listeners = [];
+ };
};
injectSWRCache(cache, (key: string, value: any) => {
if (isMetaCache(key)) {
@@ -44,7 +26,7 @@ const createDevToolsCache = (cache: Cache): DevToolsCache => {
listener(key, value);
});
});
- return store;
+ return subscribe;
};
const formatTime = (date: Date) =>
@@ -70,19 +52,20 @@ const toJSON = (value: any) => {
};
const retrieveCache = (
- key_: string,
+ key: string,
value: any
): [SWRCacheData[], SWRCacheData[]] => {
const date = new Date();
- const data = toJSON(value);
-
- const isErrorCache_ = isErrorCache(key_);
- const key = isErrorCache_ ? getErrorCacheKey(key_) : key_;
-
- const payload = isErrorCache_ ? { key, error: data } : { key, data };
currentCacheData.set(key, {
- ...payload,
+ key,
+ cache: Object.keys(value).reduce(
+ (acc, cacheKey) => ({
+ ...acc,
+ [cacheKey]: toJSON(value[cacheKey]),
+ }),
+ {}
+ ),
timestamp: date,
timestampString: formatTime(date),
});
@@ -105,8 +88,9 @@ export const useDevToolsCache = (
]);
useEffect(() => {
- const devToolsCache = createDevToolsCache(cache);
- const unsubscribe = devToolsCache.subscribe((key: string, value: any) => {
+ const subscribe = createDevToolsCache(cache);
+ const unsubscribe = subscribe((key_: string, value_: any) => {
+ const { key, value } = convertCacheData(key_, value_, cache);
setCacheData(retrieveCache(key, value));
});
return () => {
diff --git a/packages/swr-devtools/package.json b/packages/swr-devtools/package.json
index 0ddb686..4e64a25 100644
--- a/packages/swr-devtools/package.json
+++ b/packages/swr-devtools/package.json
@@ -46,12 +46,12 @@
},
"peerDependencies": {
"react": "^17.0.2",
- "swr": "^1.0.0"
+ "swr": ">=1.0.0"
},
"devDependencies": {
"@types/react": "^17.0.16",
"react": "^17.0.2",
- "swr": "^1.0.0",
+ "swr": "^2.0.0-beta.2",
"typescript": "^4.1.3"
}
}
diff --git a/packages/swr-devtools/src/SWRDevTools.tsx b/packages/swr-devtools/src/SWRDevTools.tsx
index eb38960..35b096a 100644
--- a/packages/swr-devtools/src/SWRDevTools.tsx
+++ b/packages/swr-devtools/src/SWRDevTools.tsx
@@ -1,7 +1,7 @@
import React, { useLayoutEffect } from "react";
import { useSWRConfig, SWRConfig, Middleware, Cache } from "swr";
-import { injectSWRCache, isMetaCache, isErrorCache } from "./swr-cache";
+import { injectSWRCache, isMetaCache } from "./swr-cache";
const injected = new WeakSet();
@@ -32,7 +32,13 @@ const inject = (cache: Cache) =>
type: "updated_swr_cache",
payload: {
key,
- value: convertToSerializableObject(value),
+ value: Object.keys(value).reduce(
+ (acc, cacheKey) => ({
+ ...acc,
+ [cacheKey]: convertToSerializableObject(value[cacheKey]),
+ }),
+ {}
+ ),
},
},
"*"
diff --git a/packages/swr-devtools/src/swr-cache.ts b/packages/swr-devtools/src/swr-cache.ts
index 13ceb08..9d13451 100644
--- a/packages/swr-devtools/src/swr-cache.ts
+++ b/packages/swr-devtools/src/swr-cache.ts
@@ -1,9 +1,8 @@
import { Cache } from "swr";
export type SWRCacheData = {
- id: number;
key: string;
- data: any;
+ cache: any;
isValidating: boolean;
error: string;
timestamp: Date;
@@ -35,11 +34,6 @@ export const isErrorCache = (key: string) => {
return /^\$err\$/.test(key);
};
-export const getErrorCacheKey = (key: string) => {
- const match = key.match(/^\$err\$(?.*)?/);
- return match?.groups?.cacheKey ?? key;
-};
-
export const isInfiniteCache = (key: string) => {
return /^\$inf\$/.test(key);
};
@@ -48,3 +42,48 @@ export const getInfiniteCacheKey = (key: string) => {
const match = key.match(/^\$inf\$(?.*)?/);
return match?.groups?.cacheKey ?? key;
};
+
+const getErrorCacheKey = (key: string) => {
+ const match = key.match(/^\$err\$(?.*)?/);
+ return match?.groups?.cacheKey ?? key;
+};
+
+const isV2CacheData = (data: any) => {
+ return "isValidating" in data && "isLoading" in data;
+};
+
+const isV1MetaCache = (key: string) => {
+ return /^\$swr\$/.test(key);
+};
+
+export const convertCacheData = (key: string, value: any, cache: Cache) => {
+ if (value !== undefined && isV2CacheData(value)) {
+ // SWR v2
+ return {
+ key,
+ value,
+ };
+ } else if (value !== undefined && isV1MetaCache(key)) {
+ // SWR ^1.3.0 ($swr$ cache key)
+ const v1CacheKey = key.replace(/^\$swr\$/, "");
+ return {
+ key: v1CacheKey,
+ value: {
+ data: cache.get(v1CacheKey),
+ error: value.error,
+ },
+ };
+ } else if (isErrorCache(key)) {
+ // SWR <1.3.0
+ return {
+ key: getErrorCacheKey(key),
+ value: {
+ error: value,
+ },
+ };
+ }
+ return {
+ key,
+ value: { data: value },
+ };
+};
diff --git a/yarn.lock b/yarn.lock
index 9580497..dc2d13f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8086,11 +8086,26 @@ supports-color@^8.0.0:
dependencies:
has-flag "^4.0.0"
-swr@^1.0.0, swr@^1.1.0:
+swr@1.1.x:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/swr/-/swr-1.1.2.tgz#9f3de2541931fccf03c48f322f1fc935a7551612"
+ integrity sha512-UsM0eo5T+kRPyWFZtWRx2XR5qzohs/LS4lDC0GCyLpCYFmsfTk28UCVDbOE9+KtoXY4FnwHYiF+ZYEU3hnJ1lQ==
+
+swr@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/swr/-/swr-1.1.0.tgz#7710cdbc5ff664c13e41fba6a1fa4734f82aba35"
integrity sha512-MFL3mkl752Uap81nLA1tEu7vQmikPamSziW+6dBidYKAo4oLOlUx/x5GZy4ZCkCwfZe2uedylkz1UMGnatUX4g==
+swr@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
+ integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
+
+swr@^2.0.0-beta.2:
+ version "2.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/swr/-/swr-2.0.0-beta.2.tgz#70c7feb0ac96ea81acf5004307b83013de42345d"
+ integrity sha512-lHFbeoN/kdFhcl/gs1urD3ynAnj6l9NOBqYADqY4oron4kDZvGDf1ZSEhUmlGII87DuSWjaKprB8QTeIKe0Feg==
+
table@^6.0.9:
version "6.7.5"
resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238"