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 + + + +
+
+

SWR DevTools

+

+ A devtools for{" "} + + SWR + +  to enable you to inspect your SWR cache data. +

+
+
+

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"} +

+
+ +
+
+ +
+ +
+ ); +} 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)

+
+ +
+ +
+
+ +
+
+

SWR DevTools

+
+ +
+ ); +} 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 + + + +
+
+

SWR DevTools

+

+ A devtools for{" "} + + SWR + +  to enable you to inspect your SWR cache data. +

+
+
+

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"} +

+
+ +
+
+ +
+ +
+ ); +} 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)

+
+ +
+ +
+
+ +
+
+

SWR DevTools

+
+ +
+ ); +} 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 && <ErrorLabel />} - <CacheKey cacheKey={data.key} /> -   - <TimestampText>{data.timestampString}</TimestampText> - - - {data.data && } - {data.error && } - - -)); +export const CacheData = React.memo( + ({ + cache: { + // @ts-ignore + cache: { data, error }, + key, + timestampString, + }, + }: Props) => ( + + + {error && <ErrorLabel />} + <CacheKey cacheKey={key} /> +   + <TimestampText>{timestampString}</TimestampText> + + + {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"