├── .github └── test.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── example ├── .gitignore ├── db.types.ts ├── index.html ├── package.json ├── src │ ├── App.css │ ├── App.tsx │ ├── favicon.svg │ ├── index.css │ ├── logo.svg │ ├── main.tsx │ └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── yarn.lock ├── jest.config.js ├── package.json ├── src ├── index.tsx └── util.ts ├── tests ├── constants.ts ├── db.types.ts ├── testUtils.tsx ├── useQuery.test.tsx └── util.test.ts ├── tsconfig.json └── yarn.lock /.github/test.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | branches: [main] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [10.x, 12.x, 14.x, 15.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: yarn build 24 | - run: yarn test 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Run `yarn ; yarn dev` in root folder to watch src directory. 2 | Run `yarn ; yarn dev` in `example/` to link and see changes 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Herman Nygaard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # supabase-query 2 | 3 | Supercharge your development speed with Supabase and react-query, combined! 4 | 5 | ## Features 6 | 7 | - Caching – save database reads 8 | - No more manually writing loading states 9 | - Easily invalidate after mutations 10 | - Leverage all of react-query's powerful query- and mutation API 11 | - Build queries with the Supabase query builder 12 | - Type support with Supabase v2 types 13 | 14 | ## Installation 15 | 16 | `yarn add supabase-query @supabase/supabase-js react-query@^3` 17 | 18 | or with npm: 19 | 20 | `npm i supabase-query @supabase/supabase-js react-query@^3` 21 | 22 | ## Quick start 23 | 24 | ```tsx 25 | import { QueryClient, QueryClientProvider, useQueryClient } from "react-query"; 26 | import { createClient } from "@supabase/supabase-js"; 27 | import { 28 | SupabaseQueryProvider, 29 | useSupabaseMutation, 30 | useSupabaseQuery, 31 | } from "supabase-query"; 32 | 33 | const queryClient = new QueryClient(); 34 | const supabaseClient = createClient("https://foo.bar", "key"); 35 | 36 | function App() { 37 | return ( 38 | // Provide SupabaseQuery provider to your app 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | } 46 | 47 | function Todos() { 48 | // Use the provided supabase instance in the callback to build your query 49 | // The table name ("todos" here) will by default be used as the queryKey (see mutation) 50 | const { data, isLoading } = useSupabaseQuery((supabase) => 51 | supabase.from("todos").select() 52 | ); 53 | 54 | // Mutations 55 | // Access the client for invalidations 56 | const queryClient = useQueryClient(); 57 | const { mutate, isLoading: isPosting } = useSupabaseMutation({ 58 | onSuccess: () => queryClient.invalidateQueries("todos"), 59 | }); 60 | 61 | if (isLoading) return

Loading...

; 62 | 63 | return ( 64 |
65 | 70 | 81 |
82 | ); 83 | } 84 | export default App; 85 | ``` 86 | 87 | ## API 88 | 89 | ### useSupabaseQuery 90 | 91 | ```tsx 92 | const { data, isLoading } = useSupabaseQuery( 93 | (supabase) => supabase.from("todos").select(), 94 | { 95 | onSuccess: () => { 96 | alert("success"); 97 | }, 98 | queryKey: ["todos", page], 99 | } 100 | ); 101 | ``` 102 | 103 | useSupabaseQuery accepts two arguments: 104 | The first is a function that provides the supabase client as an argument, 105 | and it expects a built query in return. 106 | 107 | The table name will by default be used as the queryKey for react-query. 108 | 109 | The second argument: react-query options, see their docs for all options. The options object also takes in 110 | `queryKey` if you want to override the default key for a more dynamic one. 111 | 112 | ### useSupabaseMutation 113 | 114 | ```tsx 115 | import { useQueryClient } from "react-query"; 116 | 117 | const client = useQueryClient(); 118 | const { mutate, isLoading: isPosting } = useSupabaseMutation({ 119 | onSuccess: () => client.invalidateQueries("todos"), 120 | }); 121 | 122 | function handlePost() { 123 | mutate((supabase) => 124 | supabase.from("todos").insert([{ name: val, done: false }]) 125 | ); 126 | } 127 | 128 | ; 131 | ``` 132 | 133 | The `mutate` function is used the same way as the useSupabaseQuery callback argument 134 | with the supabase client provided. 135 | 136 | ## TypeScript 137 | 138 | To leverage Supabase's schema type export you have to pass the schema to 139 | supabase-query's hooks and export those hooks in your app for use: 140 | 141 | `hooks/supabase.ts` 142 | 143 | ```ts 144 | import { 145 | TypedUseSupabaseMutation, 146 | TypedUseSupabaseQuery, 147 | useSupabaseMutation, 148 | useSupabaseQuery, 149 | } from "supabase-query"; 150 | import { DatabaseSchema } from "./db.types.ts"; 151 | 152 | export const useTypedSupabaseQuery: TypedUseSupabaseQuery = 153 | useSupabaseQuery; 154 | export const useTypedSupabaseMutation: TypedUseSupabaseMutation = 155 | useSupabaseMutation; 156 | ``` 157 | 158 | Then use it in your app: 159 | 160 | ```tsx 161 | import { useTypedSupabaseQuery } from "hooks/supabase"; 162 | 163 | function Todos() { 164 | // Data will be typed correctly 165 | const { data, isLoading } = useTypedSupabaseQuery( 166 | (supabase) => 167 | // The Supabase client will be typed to give inference on all tables 168 | supabase.from("todos").select(), 169 | { 170 | // Data is typed in options 171 | onSuccess(data) { 172 | console.log(data[0].done); 173 | }, 174 | } 175 | ); 176 | } 177 | ``` 178 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .env -------------------------------------------------------------------------------- /example/db.types.ts: -------------------------------------------------------------------------------- 1 | export type Json = 2 | | string 3 | | number 4 | | boolean 5 | | null 6 | | { [key: string]: Json } 7 | | Json[]; 8 | 9 | export interface Database { 10 | public: { 11 | Tables: { 12 | test: { 13 | Row: { 14 | cool: number | null; 15 | created_at: string | null; 16 | id: number; 17 | }; 18 | Insert: { 19 | cool?: number | null; 20 | created_at?: string | null; 21 | id?: number; 22 | }; 23 | Update: { 24 | cool?: number | null; 25 | created_at?: string | null; 26 | id?: number; 27 | }; 28 | }; 29 | todos: { 30 | Row: { 31 | created_at: string | null; 32 | done: boolean | null; 33 | foo: string | null; 34 | id: number; 35 | name: string | null; 36 | }; 37 | Insert: { 38 | created_at?: string | null; 39 | done?: boolean | null; 40 | foo?: string | null; 41 | id?: number; 42 | name?: string | null; 43 | }; 44 | Update: { 45 | created_at?: string | null; 46 | done?: boolean | null; 47 | foo?: string | null; 48 | id?: number; 49 | name?: string | null; 50 | }; 51 | }; 52 | }; 53 | Views: { 54 | [_ in never]: never; 55 | }; 56 | Functions: { 57 | [_ in never]: never; 58 | }; 59 | Enums: { 60 | [_ in never]: never; 61 | }; 62 | CompositeTypes: { 63 | [_ in never]: never; 64 | }; 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "tsc && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "react": "^18.0.0", 12 | "react-dom": "^18.0.0", 13 | "react-query": "^3.34.20", 14 | "supabase-query": "link:.." 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^17.0.0", 18 | "@types/react-dom": "^17.0.0", 19 | "@vitejs/plugin-react": "^1.3.0", 20 | "typescript": "^4.6.3", 21 | "vite": "^2.9.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | button { 41 | font-size: calc(10px + 2vmin); 42 | } 43 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import "./App.css"; 3 | 4 | import { QueryClient, QueryClientProvider, useQueryClient } from "react-query"; 5 | 6 | import { createClient } from "@supabase/supabase-js"; 7 | import { 8 | SupabaseQueryProvider, 9 | TypedUseSupabaseMutation, 10 | TypedUseSupabaseQuery, 11 | useSupabaseMutation, 12 | useSupabaseQuery, 13 | } from "supabase-query"; 14 | import { Database } from "../db.types"; 15 | 16 | const queryClient = new QueryClient(); 17 | 18 | const supabaseClient = createClient( 19 | import.meta.env.VITE_url, 20 | import.meta.env.VITE_key 21 | ); 22 | 23 | export const useTypedSupabaseQuery: TypedUseSupabaseQuery = 24 | useSupabaseQuery; 25 | 26 | export const useTypedSupabaseMutation: TypedUseSupabaseMutation = 27 | useSupabaseMutation; 28 | 29 | function App() { 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | } 38 | 39 | function DeleteButton({ id }) { 40 | const client = useQueryClient(); 41 | const { mutate } = useSupabaseMutation({ 42 | onSuccess: () => client.invalidateQueries("todos"), 43 | }); 44 | 45 | return ( 46 | 53 | ); 54 | } 55 | 56 | export function Todos() { 57 | const client = useQueryClient(); 58 | const [limit, setLimit] = useState(7); 59 | const { data, isLoading, isError, error } = useTypedSupabaseQuery( 60 | (supabase) => supabase.from("todos").select() 61 | ); 62 | 63 | const { 64 | mutate, 65 | isLoading: isPosting, 66 | data: ok, 67 | } = useTypedSupabaseMutation({ 68 | onSuccess: (env) => { 69 | client.invalidateQueries("todos"); 70 | }, 71 | onError: () => alert("noo"), 72 | }); 73 | console.log({ ok }); 74 | 75 | const [val, setVal] = useState(""); 76 | if (isLoading) return
Loading...
; 77 | 78 | return ( 79 |
87 |
88 | {data?.map((t) => ( 89 |
90 | {t.name} 91 | 92 | 93 |
94 | ))} 95 |
96 | setLimit(target.value)} /> 97 | {JSON.stringify(error)} 98 | setVal(target.value)} /> 99 | 109 |
110 | ); 111 | } 112 | 113 | export default App; 114 | -------------------------------------------------------------------------------- /example/src/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /example/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import './index.css' 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | 10 | ) 11 | -------------------------------------------------------------------------------- /example/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /example/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /example/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ampproject/remapping@^2.1.0": 6 | version "2.1.2" 7 | resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" 8 | integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== 9 | dependencies: 10 | "@jridgewell/trace-mapping" "^0.3.0" 11 | 12 | "@babel/code-frame@^7.16.7": 13 | version "7.16.7" 14 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" 15 | integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== 16 | dependencies: 17 | "@babel/highlight" "^7.16.7" 18 | 19 | "@babel/compat-data@^7.17.7": 20 | version "7.17.7" 21 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2" 22 | integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ== 23 | 24 | "@babel/core@^7.17.9": 25 | version "7.17.9" 26 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.9.tgz#6bae81a06d95f4d0dec5bb9d74bbc1f58babdcfe" 27 | integrity sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw== 28 | dependencies: 29 | "@ampproject/remapping" "^2.1.0" 30 | "@babel/code-frame" "^7.16.7" 31 | "@babel/generator" "^7.17.9" 32 | "@babel/helper-compilation-targets" "^7.17.7" 33 | "@babel/helper-module-transforms" "^7.17.7" 34 | "@babel/helpers" "^7.17.9" 35 | "@babel/parser" "^7.17.9" 36 | "@babel/template" "^7.16.7" 37 | "@babel/traverse" "^7.17.9" 38 | "@babel/types" "^7.17.0" 39 | convert-source-map "^1.7.0" 40 | debug "^4.1.0" 41 | gensync "^1.0.0-beta.2" 42 | json5 "^2.2.1" 43 | semver "^6.3.0" 44 | 45 | "@babel/generator@^7.17.9": 46 | version "7.17.9" 47 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.9.tgz#f4af9fd38fa8de143c29fce3f71852406fc1e2fc" 48 | integrity sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ== 49 | dependencies: 50 | "@babel/types" "^7.17.0" 51 | jsesc "^2.5.1" 52 | source-map "^0.5.0" 53 | 54 | "@babel/helper-annotate-as-pure@^7.16.7": 55 | version "7.16.7" 56 | resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" 57 | integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== 58 | dependencies: 59 | "@babel/types" "^7.16.7" 60 | 61 | "@babel/helper-compilation-targets@^7.17.7": 62 | version "7.17.7" 63 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz#a3c2924f5e5f0379b356d4cfb313d1414dc30e46" 64 | integrity sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w== 65 | dependencies: 66 | "@babel/compat-data" "^7.17.7" 67 | "@babel/helper-validator-option" "^7.16.7" 68 | browserslist "^4.17.5" 69 | semver "^6.3.0" 70 | 71 | "@babel/helper-environment-visitor@^7.16.7": 72 | version "7.16.7" 73 | resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" 74 | integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== 75 | dependencies: 76 | "@babel/types" "^7.16.7" 77 | 78 | "@babel/helper-function-name@^7.17.9": 79 | version "7.17.9" 80 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" 81 | integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== 82 | dependencies: 83 | "@babel/template" "^7.16.7" 84 | "@babel/types" "^7.17.0" 85 | 86 | "@babel/helper-hoist-variables@^7.16.7": 87 | version "7.16.7" 88 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" 89 | integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== 90 | dependencies: 91 | "@babel/types" "^7.16.7" 92 | 93 | "@babel/helper-module-imports@^7.16.7": 94 | version "7.16.7" 95 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" 96 | integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== 97 | dependencies: 98 | "@babel/types" "^7.16.7" 99 | 100 | "@babel/helper-module-transforms@^7.17.7": 101 | version "7.17.7" 102 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz#3943c7f777139e7954a5355c815263741a9c1cbd" 103 | integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== 104 | dependencies: 105 | "@babel/helper-environment-visitor" "^7.16.7" 106 | "@babel/helper-module-imports" "^7.16.7" 107 | "@babel/helper-simple-access" "^7.17.7" 108 | "@babel/helper-split-export-declaration" "^7.16.7" 109 | "@babel/helper-validator-identifier" "^7.16.7" 110 | "@babel/template" "^7.16.7" 111 | "@babel/traverse" "^7.17.3" 112 | "@babel/types" "^7.17.0" 113 | 114 | "@babel/helper-plugin-utils@^7.16.7": 115 | version "7.16.7" 116 | resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" 117 | integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== 118 | 119 | "@babel/helper-simple-access@^7.17.7": 120 | version "7.17.7" 121 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz#aaa473de92b7987c6dfa7ce9a7d9674724823367" 122 | integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== 123 | dependencies: 124 | "@babel/types" "^7.17.0" 125 | 126 | "@babel/helper-split-export-declaration@^7.16.7": 127 | version "7.16.7" 128 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" 129 | integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== 130 | dependencies: 131 | "@babel/types" "^7.16.7" 132 | 133 | "@babel/helper-validator-identifier@^7.16.7": 134 | version "7.16.7" 135 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" 136 | integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== 137 | 138 | "@babel/helper-validator-option@^7.16.7": 139 | version "7.16.7" 140 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" 141 | integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== 142 | 143 | "@babel/helpers@^7.17.9": 144 | version "7.17.9" 145 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" 146 | integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== 147 | dependencies: 148 | "@babel/template" "^7.16.7" 149 | "@babel/traverse" "^7.17.9" 150 | "@babel/types" "^7.17.0" 151 | 152 | "@babel/highlight@^7.16.7": 153 | version "7.17.9" 154 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" 155 | integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== 156 | dependencies: 157 | "@babel/helper-validator-identifier" "^7.16.7" 158 | chalk "^2.0.0" 159 | js-tokens "^4.0.0" 160 | 161 | "@babel/parser@^7.16.7", "@babel/parser@^7.17.9": 162 | version "7.17.9" 163 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.9.tgz#9c94189a6062f0291418ca021077983058e171ef" 164 | integrity sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg== 165 | 166 | "@babel/plugin-syntax-jsx@^7.16.7": 167 | version "7.16.7" 168 | resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" 169 | integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== 170 | dependencies: 171 | "@babel/helper-plugin-utils" "^7.16.7" 172 | 173 | "@babel/plugin-transform-react-jsx-development@^7.16.7": 174 | version "7.16.7" 175 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" 176 | integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== 177 | dependencies: 178 | "@babel/plugin-transform-react-jsx" "^7.16.7" 179 | 180 | "@babel/plugin-transform-react-jsx-self@^7.16.7": 181 | version "7.16.7" 182 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.16.7.tgz#f432ad0cba14c4a1faf44f0076c69e42a4d4479e" 183 | integrity sha512-oe5VuWs7J9ilH3BCCApGoYjHoSO48vkjX2CbA5bFVhIuO2HKxA3vyF7rleA4o6/4rTDbk6r8hBW7Ul8E+UZrpA== 184 | dependencies: 185 | "@babel/helper-plugin-utils" "^7.16.7" 186 | 187 | "@babel/plugin-transform-react-jsx-source@^7.16.7": 188 | version "7.16.7" 189 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.16.7.tgz#1879c3f23629d287cc6186a6c683154509ec70c0" 190 | integrity sha512-rONFiQz9vgbsnaMtQlZCjIRwhJvlrPET8TabIUK2hzlXw9B9s2Ieaxte1SCOOXMbWRHodbKixNf3BLcWVOQ8Bw== 191 | dependencies: 192 | "@babel/helper-plugin-utils" "^7.16.7" 193 | 194 | "@babel/plugin-transform-react-jsx@^7.16.7", "@babel/plugin-transform-react-jsx@^7.17.3": 195 | version "7.17.3" 196 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1" 197 | integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ== 198 | dependencies: 199 | "@babel/helper-annotate-as-pure" "^7.16.7" 200 | "@babel/helper-module-imports" "^7.16.7" 201 | "@babel/helper-plugin-utils" "^7.16.7" 202 | "@babel/plugin-syntax-jsx" "^7.16.7" 203 | "@babel/types" "^7.17.0" 204 | 205 | "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": 206 | version "7.17.9" 207 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72" 208 | integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg== 209 | dependencies: 210 | regenerator-runtime "^0.13.4" 211 | 212 | "@babel/template@^7.16.7": 213 | version "7.16.7" 214 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" 215 | integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== 216 | dependencies: 217 | "@babel/code-frame" "^7.16.7" 218 | "@babel/parser" "^7.16.7" 219 | "@babel/types" "^7.16.7" 220 | 221 | "@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9": 222 | version "7.17.9" 223 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.9.tgz#1f9b207435d9ae4a8ed6998b2b82300d83c37a0d" 224 | integrity sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw== 225 | dependencies: 226 | "@babel/code-frame" "^7.16.7" 227 | "@babel/generator" "^7.17.9" 228 | "@babel/helper-environment-visitor" "^7.16.7" 229 | "@babel/helper-function-name" "^7.17.9" 230 | "@babel/helper-hoist-variables" "^7.16.7" 231 | "@babel/helper-split-export-declaration" "^7.16.7" 232 | "@babel/parser" "^7.17.9" 233 | "@babel/types" "^7.17.0" 234 | debug "^4.1.0" 235 | globals "^11.1.0" 236 | 237 | "@babel/types@^7.16.7", "@babel/types@^7.17.0": 238 | version "7.17.0" 239 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" 240 | integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== 241 | dependencies: 242 | "@babel/helper-validator-identifier" "^7.16.7" 243 | to-fast-properties "^2.0.0" 244 | 245 | "@jridgewell/resolve-uri@^3.0.3": 246 | version "3.0.5" 247 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" 248 | integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== 249 | 250 | "@jridgewell/sourcemap-codec@^1.4.10": 251 | version "1.4.11" 252 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" 253 | integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== 254 | 255 | "@jridgewell/trace-mapping@^0.3.0": 256 | version "0.3.4" 257 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" 258 | integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== 259 | dependencies: 260 | "@jridgewell/resolve-uri" "^3.0.3" 261 | "@jridgewell/sourcemap-codec" "^1.4.10" 262 | 263 | "@rollup/pluginutils@^4.2.0": 264 | version "4.2.1" 265 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" 266 | integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== 267 | dependencies: 268 | estree-walker "^2.0.1" 269 | picomatch "^2.2.2" 270 | 271 | "@types/prop-types@*": 272 | version "15.7.5" 273 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" 274 | integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== 275 | 276 | "@types/react-dom@^17.0.0": 277 | version "17.0.15" 278 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.15.tgz#f2c8efde11521a4b7991e076cb9c70ba3bb0d156" 279 | integrity sha512-Tr9VU9DvNoHDWlmecmcsE5ZZiUkYx+nKBzum4Oxe1K0yJVyBlfbq7H3eXjxXqJczBKqPGq3EgfTru4MgKb9+Yw== 280 | dependencies: 281 | "@types/react" "^17" 282 | 283 | "@types/react@^17", "@types/react@^17.0.0": 284 | version "17.0.44" 285 | resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.44.tgz#c3714bd34dd551ab20b8015d9d0dbec812a51ec7" 286 | integrity sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g== 287 | dependencies: 288 | "@types/prop-types" "*" 289 | "@types/scheduler" "*" 290 | csstype "^3.0.2" 291 | 292 | "@types/scheduler@*": 293 | version "0.16.2" 294 | resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" 295 | integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== 296 | 297 | "@vitejs/plugin-react@^1.3.0": 298 | version "1.3.1" 299 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.3.1.tgz#bf008adf33e713215cd4a6b94a75146dd6891975" 300 | integrity sha512-qQS8Y2fZCjo5YmDUplEXl3yn+aueiwxB7BaoQ4nWYJYR+Ai8NXPVLlkLobVMs5+DeyFyg9Lrz6zCzdX1opcvyw== 301 | dependencies: 302 | "@babel/core" "^7.17.9" 303 | "@babel/plugin-transform-react-jsx" "^7.17.3" 304 | "@babel/plugin-transform-react-jsx-development" "^7.16.7" 305 | "@babel/plugin-transform-react-jsx-self" "^7.16.7" 306 | "@babel/plugin-transform-react-jsx-source" "^7.16.7" 307 | "@rollup/pluginutils" "^4.2.0" 308 | react-refresh "^0.12.0" 309 | resolve "^1.22.0" 310 | 311 | ansi-styles@^3.2.1: 312 | version "3.2.1" 313 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 314 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 315 | dependencies: 316 | color-convert "^1.9.0" 317 | 318 | balanced-match@^1.0.0: 319 | version "1.0.2" 320 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 321 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 322 | 323 | big-integer@^1.6.16: 324 | version "1.6.51" 325 | resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" 326 | integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== 327 | 328 | brace-expansion@^1.1.7: 329 | version "1.1.11" 330 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 331 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 332 | dependencies: 333 | balanced-match "^1.0.0" 334 | concat-map "0.0.1" 335 | 336 | broadcast-channel@^3.4.1: 337 | version "3.7.0" 338 | resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" 339 | integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== 340 | dependencies: 341 | "@babel/runtime" "^7.7.2" 342 | detect-node "^2.1.0" 343 | js-sha3 "0.8.0" 344 | microseconds "0.2.0" 345 | nano-time "1.0.0" 346 | oblivious-set "1.0.0" 347 | rimraf "3.0.2" 348 | unload "2.2.0" 349 | 350 | browserslist@^4.17.5: 351 | version "4.20.2" 352 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88" 353 | integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA== 354 | dependencies: 355 | caniuse-lite "^1.0.30001317" 356 | electron-to-chromium "^1.4.84" 357 | escalade "^3.1.1" 358 | node-releases "^2.0.2" 359 | picocolors "^1.0.0" 360 | 361 | caniuse-lite@^1.0.30001317: 362 | version "1.0.30001332" 363 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz#39476d3aa8d83ea76359c70302eafdd4a1d727dd" 364 | integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== 365 | 366 | chalk@^2.0.0: 367 | version "2.4.2" 368 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 369 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 370 | dependencies: 371 | ansi-styles "^3.2.1" 372 | escape-string-regexp "^1.0.5" 373 | supports-color "^5.3.0" 374 | 375 | color-convert@^1.9.0: 376 | version "1.9.3" 377 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 378 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 379 | dependencies: 380 | color-name "1.1.3" 381 | 382 | color-name@1.1.3: 383 | version "1.1.3" 384 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 385 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 386 | 387 | concat-map@0.0.1: 388 | version "0.0.1" 389 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 390 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 391 | 392 | convert-source-map@^1.7.0: 393 | version "1.8.0" 394 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" 395 | integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== 396 | dependencies: 397 | safe-buffer "~5.1.1" 398 | 399 | csstype@^3.0.2: 400 | version "3.0.11" 401 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33" 402 | integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw== 403 | 404 | debug@^4.1.0: 405 | version "4.3.4" 406 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 407 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 408 | dependencies: 409 | ms "2.1.2" 410 | 411 | detect-node@^2.0.4, detect-node@^2.1.0: 412 | version "2.1.0" 413 | resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" 414 | integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== 415 | 416 | electron-to-chromium@^1.4.84: 417 | version "1.4.110" 418 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.110.tgz#269208d7cf7e32123b1d87bf4e6e1fd9ac7ff51d" 419 | integrity sha512-TvHZrkj9anfWkxgblHlNr4IMQdm2N6D0o8Wu1BDpSL/RKT4DHyUt/tvDFtApgZ+LGFL3U9EO4LRZ1eSlQ8xMYA== 420 | 421 | esbuild-android-64@0.14.36: 422 | version "0.14.36" 423 | resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.36.tgz#fc5f95ce78c8c3d790fa16bc71bd904f2bb42aa1" 424 | integrity sha512-jwpBhF1jmo0tVCYC/ORzVN+hyVcNZUWuozGcLHfod0RJCedTDTvR4nwlTXdx1gtncDqjk33itjO+27OZHbiavw== 425 | 426 | esbuild-android-arm64@0.14.36: 427 | version "0.14.36" 428 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.36.tgz#44356fbb9f8de82a5cdf11849e011dfb3ad0a8a8" 429 | integrity sha512-/hYkyFe7x7Yapmfv4X/tBmyKnggUmdQmlvZ8ZlBnV4+PjisrEhAvC3yWpURuD9XoB8Wa1d5dGkTsF53pIvpjsg== 430 | 431 | esbuild-darwin-64@0.14.36: 432 | version "0.14.36" 433 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.36.tgz#3d9324b21489c70141665c2e740d6e84f16f725d" 434 | integrity sha512-kkl6qmV0dTpyIMKagluzYqlc1vO0ecgpviK/7jwPbRDEv5fejRTaBBEE2KxEQbTHcLhiiDbhG7d5UybZWo/1zQ== 435 | 436 | esbuild-darwin-arm64@0.14.36: 437 | version "0.14.36" 438 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.36.tgz#2a8040c2e465131e5281034f3c72405e643cb7b2" 439 | integrity sha512-q8fY4r2Sx6P0Pr3VUm//eFYKVk07C5MHcEinU1BjyFnuYz4IxR/03uBbDwluR6ILIHnZTE7AkTUWIdidRi1Jjw== 440 | 441 | esbuild-freebsd-64@0.14.36: 442 | version "0.14.36" 443 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.36.tgz#d82c387b4d01fe9e8631f97d41eb54f2dbeb68a3" 444 | integrity sha512-Hn8AYuxXXRptybPqoMkga4HRFE7/XmhtlQjXFHoAIhKUPPMeJH35GYEUWGbjteai9FLFvBAjEAlwEtSGxnqWww== 445 | 446 | esbuild-freebsd-arm64@0.14.36: 447 | version "0.14.36" 448 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.36.tgz#e8ce2e6c697da6c7ecd0cc0ac821d47c5ab68529" 449 | integrity sha512-S3C0attylLLRiCcHiJd036eDEMOY32+h8P+jJ3kTcfhJANNjP0TNBNL30TZmEdOSx/820HJFgRrqpNAvTbjnDA== 450 | 451 | esbuild-linux-32@0.14.36: 452 | version "0.14.36" 453 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.36.tgz#a4a261e2af91986ea62451f2db712a556cb38a15" 454 | integrity sha512-Eh9OkyTrEZn9WGO4xkI3OPPpUX7p/3QYvdG0lL4rfr73Ap2HAr6D9lP59VMF64Ex01LhHSXwIsFG/8AQjh6eNw== 455 | 456 | esbuild-linux-64@0.14.36: 457 | version "0.14.36" 458 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.36.tgz#4a9500f9197e2c8fcb884a511d2c9d4c2debde72" 459 | integrity sha512-vFVFS5ve7PuwlfgoWNyRccGDi2QTNkQo/2k5U5ttVD0jRFaMlc8UQee708fOZA6zTCDy5RWsT5MJw3sl2X6KDg== 460 | 461 | esbuild-linux-arm64@0.14.36: 462 | version "0.14.36" 463 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.36.tgz#c91c21e25b315464bd7da867365dd1dae14ca176" 464 | integrity sha512-24Vq1M7FdpSmaTYuu1w0Hdhiqkbto1I5Pjyi+4Cdw5fJKGlwQuw+hWynTcRI/cOZxBcBpP21gND7W27gHAiftw== 465 | 466 | esbuild-linux-arm@0.14.36: 467 | version "0.14.36" 468 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.36.tgz#90e23bca2e6e549affbbe994f80ba3bb6c4d934a" 469 | integrity sha512-NhgU4n+NCsYgt7Hy61PCquEz5aevI6VjQvxwBxtxrooXsxt5b2xtOUXYZe04JxqQo+XZk3d1gcr7pbV9MAQ/Lg== 470 | 471 | esbuild-linux-mips64le@0.14.36: 472 | version "0.14.36" 473 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.36.tgz#40e11afb08353ff24709fc89e4db0f866bc131d2" 474 | integrity sha512-hZUeTXvppJN+5rEz2EjsOFM9F1bZt7/d2FUM1lmQo//rXh1RTFYzhC0txn7WV0/jCC7SvrGRaRz0NMsRPf8SIA== 475 | 476 | esbuild-linux-ppc64le@0.14.36: 477 | version "0.14.36" 478 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.36.tgz#9e8a588c513d06cc3859f9dcc52e5fdfce8a1a5e" 479 | integrity sha512-1Bg3QgzZjO+QtPhP9VeIBhAduHEc2kzU43MzBnMwpLSZ890azr4/A9Dganun8nsqD/1TBcqhId0z4mFDO8FAvg== 480 | 481 | esbuild-linux-riscv64@0.14.36: 482 | version "0.14.36" 483 | resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.36.tgz#e578c09b23b3b97652e60e3692bfda628b541f06" 484 | integrity sha512-dOE5pt3cOdqEhaufDRzNCHf5BSwxgygVak9UR7PH7KPVHwSTDAZHDoEjblxLqjJYpc5XaU9+gKJ9F8mp9r5I4A== 485 | 486 | esbuild-linux-s390x@0.14.36: 487 | version "0.14.36" 488 | resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.36.tgz#3c9dab40d0d69932ffded0fd7317bb403626c9bc" 489 | integrity sha512-g4FMdh//BBGTfVHjF6MO7Cz8gqRoDPzXWxRvWkJoGroKA18G9m0wddvPbEqcQf5Tbt2vSc1CIgag7cXwTmoTXg== 490 | 491 | esbuild-netbsd-64@0.14.36: 492 | version "0.14.36" 493 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.36.tgz#e27847f6d506218291619b8c1e121ecd97628494" 494 | integrity sha512-UB2bVImxkWk4vjnP62ehFNZ73lQY1xcnL5ZNYF3x0AG+j8HgdkNF05v67YJdCIuUJpBuTyCK8LORCYo9onSW+A== 495 | 496 | esbuild-openbsd-64@0.14.36: 497 | version "0.14.36" 498 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.36.tgz#c94c04c557fae516872a586eae67423da6d2fabb" 499 | integrity sha512-NvGB2Chf8GxuleXRGk8e9zD3aSdRO5kLt9coTQbCg7WMGXeX471sBgh4kSg8pjx0yTXRt0MlrUDnjVYnetyivg== 500 | 501 | esbuild-sunos-64@0.14.36: 502 | version "0.14.36" 503 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.36.tgz#9b79febc0df65a30f1c9bd63047d1675511bf99d" 504 | integrity sha512-VkUZS5ftTSjhRjuRLp+v78auMO3PZBXu6xl4ajomGenEm2/rGuWlhFSjB7YbBNErOchj51Jb2OK8lKAo8qdmsQ== 505 | 506 | esbuild-windows-32@0.14.36: 507 | version "0.14.36" 508 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.36.tgz#910d11936c8d2122ffdd3275e5b28d8a4e1240ec" 509 | integrity sha512-bIar+A6hdytJjZrDxfMBUSEHHLfx3ynoEZXx/39nxy86pX/w249WZm8Bm0dtOAByAf4Z6qV0LsnTIJHiIqbw0w== 510 | 511 | esbuild-windows-64@0.14.36: 512 | version "0.14.36" 513 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.36.tgz#21b4ce8b42a4efc63f4b58ec617f1302448aad26" 514 | integrity sha512-+p4MuRZekVChAeueT1Y9LGkxrT5x7YYJxYE8ZOTcEfeUUN43vktSn6hUNsvxzzATrSgq5QqRdllkVBxWZg7KqQ== 515 | 516 | esbuild-windows-arm64@0.14.36: 517 | version "0.14.36" 518 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.36.tgz#ba21546fecb7297667d0052d00150de22c044b24" 519 | integrity sha512-fBB4WlDqV1m18EF/aheGYQkQZHfPHiHJSBYzXIo8yKehek+0BtBwo/4PNwKGJ5T0YK0oc8pBKjgwPbzSrPLb+Q== 520 | 521 | esbuild@^0.14.27: 522 | version "0.14.36" 523 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.36.tgz#0023a73eab57886ac5605df16ee421e471a971b3" 524 | integrity sha512-HhFHPiRXGYOCRlrhpiVDYKcFJRdO0sBElZ668M4lh2ER0YgnkLxECuFe7uWCf23FrcLc59Pqr7dHkTqmRPDHmw== 525 | optionalDependencies: 526 | esbuild-android-64 "0.14.36" 527 | esbuild-android-arm64 "0.14.36" 528 | esbuild-darwin-64 "0.14.36" 529 | esbuild-darwin-arm64 "0.14.36" 530 | esbuild-freebsd-64 "0.14.36" 531 | esbuild-freebsd-arm64 "0.14.36" 532 | esbuild-linux-32 "0.14.36" 533 | esbuild-linux-64 "0.14.36" 534 | esbuild-linux-arm "0.14.36" 535 | esbuild-linux-arm64 "0.14.36" 536 | esbuild-linux-mips64le "0.14.36" 537 | esbuild-linux-ppc64le "0.14.36" 538 | esbuild-linux-riscv64 "0.14.36" 539 | esbuild-linux-s390x "0.14.36" 540 | esbuild-netbsd-64 "0.14.36" 541 | esbuild-openbsd-64 "0.14.36" 542 | esbuild-sunos-64 "0.14.36" 543 | esbuild-windows-32 "0.14.36" 544 | esbuild-windows-64 "0.14.36" 545 | esbuild-windows-arm64 "0.14.36" 546 | 547 | escalade@^3.1.1: 548 | version "3.1.1" 549 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 550 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 551 | 552 | escape-string-regexp@^1.0.5: 553 | version "1.0.5" 554 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 555 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 556 | 557 | estree-walker@^2.0.1: 558 | version "2.0.2" 559 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" 560 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 561 | 562 | fs.realpath@^1.0.0: 563 | version "1.0.0" 564 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 565 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 566 | 567 | fsevents@~2.3.2: 568 | version "2.3.2" 569 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 570 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 571 | 572 | function-bind@^1.1.1: 573 | version "1.1.1" 574 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 575 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 576 | 577 | gensync@^1.0.0-beta.2: 578 | version "1.0.0-beta.2" 579 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" 580 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 581 | 582 | glob@^7.1.3: 583 | version "7.2.0" 584 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" 585 | integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== 586 | dependencies: 587 | fs.realpath "^1.0.0" 588 | inflight "^1.0.4" 589 | inherits "2" 590 | minimatch "^3.0.4" 591 | once "^1.3.0" 592 | path-is-absolute "^1.0.0" 593 | 594 | globals@^11.1.0: 595 | version "11.12.0" 596 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 597 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 598 | 599 | has-flag@^3.0.0: 600 | version "3.0.0" 601 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 602 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 603 | 604 | has@^1.0.3: 605 | version "1.0.3" 606 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 607 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 608 | dependencies: 609 | function-bind "^1.1.1" 610 | 611 | inflight@^1.0.4: 612 | version "1.0.6" 613 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 614 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 615 | dependencies: 616 | once "^1.3.0" 617 | wrappy "1" 618 | 619 | inherits@2: 620 | version "2.0.4" 621 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 622 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 623 | 624 | is-core-module@^2.8.1: 625 | version "2.8.1" 626 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" 627 | integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== 628 | dependencies: 629 | has "^1.0.3" 630 | 631 | js-sha3@0.8.0: 632 | version "0.8.0" 633 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" 634 | integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== 635 | 636 | "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: 637 | version "4.0.0" 638 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 639 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 640 | 641 | jsesc@^2.5.1: 642 | version "2.5.2" 643 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" 644 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== 645 | 646 | json5@^2.2.1: 647 | version "2.2.1" 648 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" 649 | integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== 650 | 651 | loose-envify@^1.1.0: 652 | version "1.4.0" 653 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 654 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 655 | dependencies: 656 | js-tokens "^3.0.0 || ^4.0.0" 657 | 658 | match-sorter@^6.0.2: 659 | version "6.3.1" 660 | resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" 661 | integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== 662 | dependencies: 663 | "@babel/runtime" "^7.12.5" 664 | remove-accents "0.4.2" 665 | 666 | microseconds@0.2.0: 667 | version "0.2.0" 668 | resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" 669 | integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== 670 | 671 | minimatch@^3.0.4: 672 | version "3.1.2" 673 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 674 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 675 | dependencies: 676 | brace-expansion "^1.1.7" 677 | 678 | ms@2.1.2: 679 | version "2.1.2" 680 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 681 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 682 | 683 | nano-time@1.0.0: 684 | version "1.0.0" 685 | resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" 686 | integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= 687 | dependencies: 688 | big-integer "^1.6.16" 689 | 690 | nanoid@^3.3.1: 691 | version "3.3.2" 692 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" 693 | integrity sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA== 694 | 695 | node-releases@^2.0.2: 696 | version "2.0.3" 697 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.3.tgz#225ee7488e4a5e636da8da52854844f9d716ca96" 698 | integrity sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw== 699 | 700 | oblivious-set@1.0.0: 701 | version "1.0.0" 702 | resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" 703 | integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== 704 | 705 | once@^1.3.0: 706 | version "1.4.0" 707 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 708 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 709 | dependencies: 710 | wrappy "1" 711 | 712 | path-is-absolute@^1.0.0: 713 | version "1.0.1" 714 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 715 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 716 | 717 | path-parse@^1.0.7: 718 | version "1.0.7" 719 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 720 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 721 | 722 | picocolors@^1.0.0: 723 | version "1.0.0" 724 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 725 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 726 | 727 | picomatch@^2.2.2: 728 | version "2.3.1" 729 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 730 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 731 | 732 | postcss@^8.4.12: 733 | version "8.4.12" 734 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" 735 | integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== 736 | dependencies: 737 | nanoid "^3.3.1" 738 | picocolors "^1.0.0" 739 | source-map-js "^1.0.2" 740 | 741 | react-dom@^18.0.0: 742 | version "18.0.0" 743 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.0.0.tgz#26b88534f8f1dbb80853e1eabe752f24100d8023" 744 | integrity sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw== 745 | dependencies: 746 | loose-envify "^1.1.0" 747 | scheduler "^0.21.0" 748 | 749 | react-query@^3.34.20: 750 | version "3.34.20" 751 | resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.34.20.tgz#649e83073b7e3350cd3fc78f8b2370e9252c4a64" 752 | integrity sha512-I0nGBu/4bebKodwwHSFmdMCjgx4bAjn2p5OQRFIlGX7GhVAyTWGRWEWAP3+KG06bb062HPOMqcy9jw086snfQg== 753 | dependencies: 754 | "@babel/runtime" "^7.5.5" 755 | broadcast-channel "^3.4.1" 756 | match-sorter "^6.0.2" 757 | 758 | react-refresh@^0.12.0: 759 | version "0.12.0" 760 | resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.12.0.tgz#28ac0a2c30ef2bb3433d5fd0621e69a6d774c3a4" 761 | integrity sha512-suLIhrU2IHKL5JEKR/fAwJv7bbeq4kJ+pJopf77jHwuR+HmJS/HbrPIGsTBUVfw7tXPOmYv7UJ7PCaN49e8x4A== 762 | 763 | react@^18.0.0: 764 | version "18.0.0" 765 | resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96" 766 | integrity sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A== 767 | dependencies: 768 | loose-envify "^1.1.0" 769 | 770 | regenerator-runtime@^0.13.4: 771 | version "0.13.9" 772 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" 773 | integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== 774 | 775 | remove-accents@0.4.2: 776 | version "0.4.2" 777 | resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" 778 | integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= 779 | 780 | resolve@^1.22.0: 781 | version "1.22.0" 782 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" 783 | integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== 784 | dependencies: 785 | is-core-module "^2.8.1" 786 | path-parse "^1.0.7" 787 | supports-preserve-symlinks-flag "^1.0.0" 788 | 789 | rimraf@3.0.2: 790 | version "3.0.2" 791 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" 792 | integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== 793 | dependencies: 794 | glob "^7.1.3" 795 | 796 | rollup@^2.59.0: 797 | version "2.70.2" 798 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.70.2.tgz#808d206a8851628a065097b7ba2053bd83ba0c0d" 799 | integrity sha512-EitogNZnfku65I1DD5Mxe8JYRUCy0hkK5X84IlDtUs+O6JRMpRciXTzyCUuX11b5L5pvjH+OmFXiQ3XjabcXgg== 800 | optionalDependencies: 801 | fsevents "~2.3.2" 802 | 803 | safe-buffer@~5.1.1: 804 | version "5.1.2" 805 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 806 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 807 | 808 | scheduler@^0.21.0: 809 | version "0.21.0" 810 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820" 811 | integrity sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ== 812 | dependencies: 813 | loose-envify "^1.1.0" 814 | 815 | semver@^6.3.0: 816 | version "6.3.0" 817 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" 818 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 819 | 820 | source-map-js@^1.0.2: 821 | version "1.0.2" 822 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 823 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 824 | 825 | source-map@^0.5.0: 826 | version "0.5.7" 827 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 828 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= 829 | 830 | "supabase-query@link:..": 831 | version "0.0.0" 832 | uid "" 833 | 834 | supports-color@^5.3.0: 835 | version "5.5.0" 836 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 837 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 838 | dependencies: 839 | has-flag "^3.0.0" 840 | 841 | supports-preserve-symlinks-flag@^1.0.0: 842 | version "1.0.0" 843 | resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" 844 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 845 | 846 | to-fast-properties@^2.0.0: 847 | version "2.0.0" 848 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" 849 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= 850 | 851 | typescript@^4.6.3: 852 | version "4.6.3" 853 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" 854 | integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== 855 | 856 | unload@2.2.0: 857 | version "2.2.0" 858 | resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" 859 | integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== 860 | dependencies: 861 | "@babel/runtime" "^7.6.2" 862 | detect-node "^2.0.4" 863 | 864 | vite@^2.9.2: 865 | version "2.9.5" 866 | resolved "https://registry.yarnpkg.com/vite/-/vite-2.9.5.tgz#08ef37ac7a6d879c96f328b791732c9a00ea25ea" 867 | integrity sha512-dvMN64X2YEQgSXF1lYabKXw3BbN6e+BL67+P3Vy4MacnY+UzT1AfkHiioFSi9+uiDUiaDy7Ax/LQqivk6orilg== 868 | dependencies: 869 | esbuild "^0.14.27" 870 | postcss "^8.4.12" 871 | resolve "^1.22.0" 872 | rollup "^2.59.0" 873 | optionalDependencies: 874 | fsevents "~2.3.2" 875 | 876 | wrappy@1: 877 | version "1.0.2" 878 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 879 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 880 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [""], 3 | transform: { 4 | "^.+\\.tsx?$": "ts-jest", 5 | }, 6 | preset: "ts-jest", 7 | testEnvironment: "jsdom", 8 | testMatch: ["**/?(*.)+(test).ts*"], 9 | moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"], 10 | }; 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supabase-query", 3 | "version": "1.0.1", 4 | "description": "", 5 | "main": "dist/cjs/index.js", 6 | "module": "dist/esm/index.js", 7 | "types": "dist/esm/index.d.ts", 8 | "scripts": { 9 | "test": "jest", 10 | "build": "rm -rf dist ; yarn build:esm && yarn build:cjs", 11 | "build:esm": "tsc", 12 | "build:cjs": "tsc --module commonjs --outDir dist/cjs", 13 | "dev": "tsc -w" 14 | }, 15 | "peerDependencies": { 16 | "@supabase/supabase-js": "^2.7.1", 17 | "react": "18", 18 | "react-query": "^3.34.19" 19 | }, 20 | "keywords": [], 21 | "files": [ 22 | "dist" 23 | ], 24 | "author": "", 25 | "license": "ISC", 26 | "devDependencies": { 27 | "@supabase/supabase-js": "^2.7.1", 28 | "@testing-library/jest-dom": "^5.16.5", 29 | "@testing-library/react": "^12.1.5", 30 | "@types/jest": "^29.4.0", 31 | "@types/react": "^17.0.5", 32 | "jest": "^29.4.1", 33 | "jest-environment-jsdom": "^29.4.1", 34 | "msw": "^1.0.0", 35 | "react": "17", 36 | "react-dom": "17.0.0", 37 | "react-query": "^3.34.19", 38 | "ts-jest": "^29.0.5", 39 | "typescript": "4.9.5" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import type { 2 | PostgrestSingleResponse, 3 | PostgrestBuilder, 4 | } from "@supabase/postgrest-js"; 5 | import { SupabaseClient } from "@supabase/supabase-js"; 6 | import React, { useContext } from "react"; 7 | import { 8 | useMutation, 9 | UseMutationOptions, 10 | UseMutationResult, 11 | useQuery, 12 | UseQueryOptions, 13 | UseQueryResult, 14 | } from "react-query"; 15 | import { getTableName } from "./util"; 16 | 17 | type Provider = { 18 | children: React.ReactNode; 19 | client: SupabaseClient; 20 | }; 21 | 22 | export function SupabaseQueryProvider({ children, client }: Provider) { 23 | return {children}; 24 | } 25 | 26 | async function execute(query: any) { 27 | const { data, error } = await query; 28 | if (error) { 29 | throw error; 30 | } 31 | return data; 32 | } 33 | 34 | type QueryCreator = ( 35 | client: SupabaseClient 36 | ) => PostgrestBuilder; 37 | 38 | const context = React.createContext(undefined); 39 | 40 | function useClient() { 41 | const client = useContext(context); 42 | if (!client) { 43 | throw new Error("Must be used inside SupabaseQueryProvider"); 44 | } 45 | return client; 46 | } 47 | 48 | type Query = (client: SupabaseClient) => PostgrestBuilder; 49 | 50 | export type TypedUseSupabaseQuery = ( 51 | queryCreator: QueryCreator, 52 | options?: UseQueryOptions 53 | ) => UseQueryResult["data"]>; 54 | 55 | export function useSupabaseQuery( 56 | queryCreator: Query, 57 | options?: UseQueryOptions 58 | ) { 59 | const client = useClient(); 60 | const query = queryCreator(client); 61 | 62 | return useQuery( 63 | // @ts-ignore 64 | // query.url is protected in Class 65 | options?.queryKey ?? [getTableName(query.url)], 66 | () => execute(query), 67 | options as any 68 | ); 69 | } 70 | 71 | export type TypedUseSupabaseMutation = ( 72 | options?: UseMutationOptions 73 | ) => UseMutationResult< 74 | PostgrestSingleResponse["data"], 75 | unknown, 76 | QueryCreator, 77 | unknown 78 | >; 79 | 80 | export function useSupabaseMutation(options?: UseMutationOptions) { 81 | const c = useClient(); 82 | 83 | async function mutate( 84 | queryCreator: Query 85 | ): Promise["data"]> { 86 | const query = queryCreator(c); 87 | return execute(query); 88 | } 89 | return useMutation< 90 | PostgrestSingleResponse["data"], 91 | unknown, 92 | Query, 93 | unknown 94 | >(mutate, options as any); 95 | } 96 | 97 | export { getTableName as getTable }; 98 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | export const getTableName = (url: URL) => { 2 | const str = url.toString(); 3 | return /.*\/([^?]+)/.exec(str)?.[1]; 4 | }; 5 | -------------------------------------------------------------------------------- /tests/constants.ts: -------------------------------------------------------------------------------- 1 | export const url = "http://test.com" as const; 2 | export const tableName = "todos" as const; 3 | export const supabaseUrl = `${url}/rest/v1/${tableName}` as const; 4 | -------------------------------------------------------------------------------- /tests/db.types.ts: -------------------------------------------------------------------------------- 1 | export type Json = 2 | | string 3 | | number 4 | | boolean 5 | | null 6 | | { [key: string]: Json } 7 | | Json[] 8 | 9 | export interface Database { 10 | public: { 11 | Tables: { 12 | test: { 13 | Row: { 14 | cool: number | null 15 | created_at: string | null 16 | id: number 17 | } 18 | Insert: { 19 | cool?: number | null 20 | created_at?: string | null 21 | id?: number 22 | } 23 | Update: { 24 | cool?: number | null 25 | created_at?: string | null 26 | id?: number 27 | } 28 | } 29 | todos: { 30 | Row: { 31 | created_at: string | null 32 | done: boolean | null 33 | foo: string | null 34 | id: number 35 | name: string | null 36 | } 37 | Insert: { 38 | created_at?: string | null 39 | done?: boolean | null 40 | foo?: string | null 41 | id?: number 42 | name?: string | null 43 | } 44 | Update: { 45 | created_at?: string | null 46 | done?: boolean | null 47 | foo?: string | null 48 | id?: number 49 | name?: string | null 50 | } 51 | } 52 | } 53 | Views: { 54 | [_ in never]: never 55 | } 56 | Functions: { 57 | [_ in never]: never 58 | } 59 | Enums: { 60 | [_ in never]: never 61 | } 62 | CompositeTypes: { 63 | [_ in never]: never 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/testUtils.tsx: -------------------------------------------------------------------------------- 1 | import { createClient } from "@supabase/supabase-js"; 2 | import { render } from "@testing-library/react"; 3 | import { 4 | SupabaseQueryProvider, 5 | TypedUseSupabaseMutation, 6 | TypedUseSupabaseQuery, 7 | useSupabaseMutation, 8 | useSupabaseQuery, 9 | } from "../src"; 10 | import React from "react"; 11 | import { QueryClient, QueryClientProvider } from "react-query"; 12 | export * from "@testing-library/react"; 13 | import "@testing-library/jest-dom"; 14 | import { Database } from "./db.types"; 15 | 16 | const supabaseClient = createClient("http://test.com", "key"); 17 | const queryClient = new QueryClient(); 18 | 19 | export const useTypedSupabaseQuery: TypedUseSupabaseQuery = 20 | useSupabaseQuery; 21 | 22 | export const useTypedSupabaseMutation: TypedUseSupabaseMutation = 23 | useSupabaseMutation; 24 | 25 | function Provider({ children }: { children: React.ReactNode }) { 26 | return ( 27 | 28 | {children} 29 | 30 | ); 31 | } 32 | 33 | export function customRender(children: any) { 34 | return render(children, { wrapper: Provider }); 35 | } 36 | 37 | export async function sleep(ms = 100) { 38 | await new Promise((res) => setTimeout(res, ms)); 39 | } 40 | -------------------------------------------------------------------------------- /tests/useQuery.test.tsx: -------------------------------------------------------------------------------- 1 | import { useSupabaseMutation, useSupabaseQuery } from "../src/index"; 2 | import React, { useEffect } from "react"; 3 | import { 4 | customRender, 5 | screen, 6 | render, 7 | waitFor, 8 | sleep, 9 | useTypedSupabaseQuery, 10 | } from "./testUtils"; 11 | import { setupServer } from "msw/node"; 12 | import { rest } from "msw"; 13 | 14 | import { supabaseUrl, url } from "./constants"; 15 | import { useQueryClient } from "react-query"; 16 | 17 | const database = [ 18 | { 19 | name: "hi", 20 | }, 21 | ]; 22 | 23 | const [{ name: firstTodoName }] = database; 24 | const server = setupServer( 25 | rest.all(`${supabaseUrl}`, async (req, res, ctx) => { 26 | if (req.method === "POST") { 27 | await sleep(); 28 | const body = await req.json(); 29 | database.push(body); 30 | return res(ctx.json(body)); 31 | } 32 | return res(ctx.json(database)); 33 | }), 34 | rest.all(`${url}/rest/v1/error`, (_, res, ctx) => { 35 | return res( 36 | ctx.status(403), 37 | ctx.json({ 38 | message: `An error occurred`, 39 | }) 40 | ); 41 | }) 42 | ); 43 | 44 | beforeAll(() => server.listen()); 45 | afterEach(() => server.resetHandlers()); 46 | afterAll(() => server.close()); 47 | 48 | function Component() { 49 | const { data, isLoading } = useTypedSupabaseQuery((client) => 50 | client.from("todos").select() 51 | ); 52 | 53 | if (isLoading) return

loading

; 54 | 55 | return

{data?.[0].name}

; 56 | } 57 | 58 | test("useQuery throws if used outside of provider", () => { 59 | // suppress annoying logs 60 | const spy = jest.spyOn(console, "error"); 61 | spy.mockImplementation(() => {}); 62 | 63 | expect(() => render()).toThrow( 64 | "Must be used inside SupabaseQueryProvider" 65 | ); 66 | 67 | spy.mockRestore(); 68 | }); 69 | 70 | test("useQuery loads and shows data", async () => { 71 | customRender(); 72 | expect(screen.getByText("loading")).toBeInTheDocument(); 73 | expect(screen.queryByText(firstTodoName)).toBeNull(); 74 | await waitFor(() => { 75 | expect(screen.getByText(firstTodoName)).toBeInTheDocument(); 76 | }); 77 | expect(screen.queryByText("loading")).toBeNull(); 78 | }); 79 | 80 | test.todo("CUSTOM QUERY KEY!!"); 81 | 82 | test("useQuery returns error state", async () => { 83 | function Component(): any { 84 | const { isLoading, isError, error } = useTypedSupabaseQuery( 85 | (client) => client.from("error").select(), 86 | { retry: false } 87 | ); 88 | if (isLoading) return "loading"; 89 | if (isError) return (error as Error).message; 90 | return ""; 91 | } 92 | customRender(); 93 | expect(screen.getByText("loading")).toBeInTheDocument(); 94 | await waitFor(() => { 95 | expect(screen.getByText("An error occurred")).toBeInTheDocument(); 96 | }); 97 | }); 98 | 99 | test("mutation and invalidation, inferred query key", async () => { 100 | const newTodo = { name: "bar" }; 101 | const { name: newTodoName } = newTodo; 102 | function Component(): any { 103 | const { mutate } = useSupabaseMutation(); 104 | const { data } = useTypedSupabaseQuery( 105 | (client) => client.from("todos").select(), 106 | { 107 | onSuccess(data) { 108 | data[0].done; 109 | }, 110 | } 111 | ); 112 | const queryClient = useQueryClient(); 113 | 114 | useEffect(() => { 115 | mutate((client) => client.from("todos").insert(newTodo), { 116 | onSuccess: () => queryClient.invalidateQueries("todos"), 117 | }); 118 | }, []); 119 | if (!data) return "loading"; 120 | return data.map((d) =>

{d.name}

); 121 | } 122 | customRender(); 123 | 124 | await waitFor(() => { 125 | expect(screen.getByText(firstTodoName)).toBeInTheDocument(); 126 | }); 127 | expect(screen.queryByText(newTodoName)).toBeNull(); 128 | 129 | await waitFor(() => { 130 | expect(screen.getByText(newTodoName)).toBeInTheDocument(); 131 | }); 132 | }); 133 | 134 | test.todo("custom query key"); 135 | test.todo("pagination, query key pagination "); 136 | test.todo("mutation data and callback value, { data } same as useQuery"); 137 | 138 | test.skip("NON TYPED QUERY + MUTATION, old API", () => { 139 | function Component() { 140 | const { data } = useSupabaseQuery((c) => c.from("todos").select()); 141 | const { mutate } = useSupabaseMutation(); 142 | mutate((c) => c.from("todos").insert({ done: false })); 143 | return data; 144 | } 145 | ; 146 | }); 147 | 148 | test("mutation error state", async () => { 149 | function Component(): any { 150 | const { isLoading, isError, error, mutate } = useSupabaseMutation(); 151 | useEffect(() => { 152 | mutate((client) => client.from("error").insert({})); 153 | }, []); 154 | 155 | if (isLoading) return "loading"; 156 | if (isError) return (error as Error).message; 157 | return ""; 158 | } 159 | customRender(); 160 | await waitFor(() => { 161 | expect(screen.getByText("An error occurred")).toBeInTheDocument(); 162 | }); 163 | }); 164 | -------------------------------------------------------------------------------- /tests/util.test.ts: -------------------------------------------------------------------------------- 1 | import { getTable } from "../src"; 2 | 3 | test("getTable", () => { 4 | expect(getTable(new URL("http://test.com/rest/v1/todo?select=*"))).toEqual( 5 | "todo" 6 | ); 7 | expect(getTable(new URL("http://test.com/rest/v1/todo?"))).toEqual("todo"); 8 | expect(getTable(new URL("http://test.com/rest/v1/todo"))).toEqual("todo"); 9 | }); 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist/esm", 4 | "module": "esnext", 5 | "target": "es5", 6 | "lib": ["es6", "dom", "es2016", "es2017"], 7 | "jsx": "react", 8 | "declaration": true, 9 | "moduleResolution": "node", 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "esModuleInterop": true, 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noImplicitAny": true, 16 | "strictNullChecks": true, 17 | "skipLibCheck": true, 18 | "suppressImplicitAnyIndexErrors": true, 19 | "allowSyntheticDefaultImports": true 20 | }, 21 | "include": ["src"], 22 | "exclude": ["node_modules", "dist", "test"] 23 | } 24 | --------------------------------------------------------------------------------