From f52eb3512b086091e013a72b87a665660f669c14 Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Wed, 2 Nov 2022 14:25:09 +1100 Subject: [PATCH 001/289] feat: adds graphiql page --- package-lock.json | 1326 +++++++++++++----- studio/package.json | 2 + studio/pages/project/[ref]/graphql/index.tsx | 34 + 3 files changed, 1017 insertions(+), 345 deletions(-) create mode 100644 studio/pages/project/[ref]/graphql/index.tsx diff --git a/package-lock.json b/package-lock.json index faa6b32827d..c676116c2ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,7 @@ "jsrsasign": "^10.5.26", "lodash": "^4.17.21", "markdown-toc": "^1.2.0", - "next": "12.0.9", + "next": "12.1.0", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "^3.0.8", "next-themes": "0.0.15", @@ -177,176 +177,6 @@ "react": "^16.13.1 || ^17.0.0" } }, - "apps/temp-docs/node_modules/@next/env": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.0.9.tgz", - "integrity": "sha512-oBlkyDop0Stf7MPIzETGv5r0YT/G/weBrknoPOUTaa5qwOeGjuy6gsOVc/SBtrBkOoBmRpD+fFhQJPvmo1mS+g==" - }, - "apps/temp-docs/node_modules/@next/swc-android-arm64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.0.9.tgz", - "integrity": "sha512-aVqgsEn5plmUH2X58sjzhHsH/6majucWTMaaBEs7hHO2+GCwCZc7zaLH4XCBMKPES9Yaja8/pYUbvZQE9DqgFw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-darwin-arm64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.9.tgz", - "integrity": "sha512-uAgRKm4a2nVdyBiPPJokvmDD1saugOvxljz9ld2ih0CCg5S9vBhqaj3kPGCQBj9hSu3q+Lng2CHnQqG3ga1jzA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-darwin-x64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.9.tgz", - "integrity": "sha512-fDOs2lZIyrAdU18IxMA5orBPn9qLbOdu55gXSTNZOhyRJ8ugtbUAejsK7OL0boJy0CCHPAdVRXm01Mwk8tZ9RQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-linux-arm-gnueabihf": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.9.tgz", - "integrity": "sha512-/ni0p9DBvATUML9RQ1ycQuf05uOYKdzA6iI8+eRsARjpGbFVUFbge7XPzlj9g2Q9YWgoN8CSjFGnKRlyky5uHA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-linux-arm64-gnu": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.9.tgz", - "integrity": "sha512-AphxilJDf95rUxJDHgM9Ww1DaYXZWqTvoKwXeej/0SgSvICcRZrLaFDrkojdXz0Rxr4igX2OdYR1S4/Hj1jWOQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-linux-arm64-musl": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.9.tgz", - "integrity": "sha512-K5jbvNNzF3mRjWmPdxP5Bg87i7FHivfBj/L0KJlxpkLSC8sffBJDmB6jtMnI7wiPj9J6vmLkbGtSosln78xAlQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-linux-x64-gnu": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.9.tgz", - "integrity": "sha512-bJZ9bkMkQzsY+UyWezEZ77GWQ4TzwKeXdayX3U3+aEkL8k5C6eKBXlidWdrhu0teLmaUXIyWerWrLnJzwGXdfw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-linux-x64-musl": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.9.tgz", - "integrity": "sha512-SR9p0R+v1T32DTXPVAXZw31pmJAkSDotC6Afy+mfC0xrEL3pp95R8sGXYAAUCEPkQp0MEeUOVy2LrToe92X7hQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-win32-arm64-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.9.tgz", - "integrity": "sha512-mzQ1A8vfHhJrvEy5KJZGZWEByXthyKfWofvFaf+oo/5nJl/0Bz1ODP2ajSmbLG++77Eo2AROgbm9pkW1ucvG2A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-win32-ia32-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.9.tgz", - "integrity": "sha512-MpD2vj1zjo1u3J3wiz3pEKse19Etz+P0GL6XfQkB/9a84vJQ1JWMaWBjmIdivzZv718Il2pRSSx8hymwPfguYQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "apps/temp-docs/node_modules/@next/swc-win32-x64-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.9.tgz", - "integrity": "sha512-1c/sxp/4Qz4F6rCxiYqAnrmghCOFt5hHZ9Kd+rXFW5Mqev4C4XDOUMHdBH55HgnJZqngYhOE0r/XNkCtsIojig==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "apps/temp-docs/node_modules/@radix-ui/primitive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", @@ -812,55 +642,6 @@ "dev": true, "license": "MIT" }, - "apps/temp-docs/node_modules/next": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/next/-/next-12.0.9.tgz", - "integrity": "sha512-omfYqoR/DvbdOIJ6SS1unKJ4mGIxUPs0RPa7wr/Mft22OCKgJhuG+aI9KFYi5ZJBwoFQk1vqaMKpWz5qr+dN0Q==", - "dependencies": { - "@next/env": "12.0.9", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=12.22.0" - }, - "optionalDependencies": { - "@next/swc-android-arm64": "12.0.9", - "@next/swc-darwin-arm64": "12.0.9", - "@next/swc-darwin-x64": "12.0.9", - "@next/swc-linux-arm-gnueabihf": "12.0.9", - "@next/swc-linux-arm64-gnu": "12.0.9", - "@next/swc-linux-arm64-musl": "12.0.9", - "@next/swc-linux-x64-gnu": "12.0.9", - "@next/swc-linux-x64-musl": "12.0.9", - "@next/swc-win32-arm64-msvc": "12.0.9", - "@next/swc-win32-ia32-msvc": "12.0.9", - "@next/swc-win32-x64-msvc": "12.0.9" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0", - "react": "^17.0.2 || ^18.0.0-0", - "react-dom": "^17.0.2 || ^18.0.0-0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, "apps/temp-docs/node_modules/next-mdx-remote": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.8.tgz", @@ -897,23 +678,6 @@ "node": ">= 0.8.0" } }, - "apps/temp-docs/node_modules/postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", - "dependencies": { - "nanoid": "^3.1.30", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, "apps/temp-docs/node_modules/supports-color": { "version": "7.2.0", "dev": true, @@ -3574,6 +3338,37 @@ "node": ">=0.1.95" } }, + "node_modules/@codemirror/language": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.0.0.tgz", + "integrity": "sha512-rtjk5ifyMzOna1c7PBu7J1VCt0PvA5wy3o8eMVnxMKb7z8KA7JFecvD04dSn14vj/bBaAbqRsGed5OjtofEnLA==", + "peer": true, + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/state": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==", + "peer": true + }, + "node_modules/@codemirror/view": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.4.0.tgz", + "integrity": "sha512-Kv32b6Tn7QVwFbj/EDswTLSocjk5kgggF6zzBFAL4o4hZ/vmtFD155+EjH1pVlbfoDyVC2M6SedPsMrwYscgNg==", + "peer": true, + "dependencies": { + "@codemirror/state": "^6.0.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -3841,6 +3636,66 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, + "node_modules/@graphiql/react": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/@graphiql/react/-/react-0.13.7.tgz", + "integrity": "sha512-mI+6mXd9AJFDJy39VuZGxCiVLvmBe2XoNidbN3lXgTLe689RZKifPaUw41USitQOu20sASoYDfzJ8i98G4urow==", + "dependencies": { + "@graphiql/toolkit": "^0.8.0", + "@reach/combobox": "^0.17.0", + "@reach/dialog": "^0.17.0", + "@reach/listbox": "^0.17.0", + "@reach/menu-button": "^0.17.0", + "@reach/tooltip": "^0.17.0", + "@reach/visually-hidden": "^0.17.0", + "codemirror": "^5.65.3", + "codemirror-graphql": "^2.0.2", + "copy-to-clipboard": "^3.2.0", + "graphql-language-service": "^5.1.0", + "markdown-it": "^12.2.0", + "set-value": "^4.1.0" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@graphiql/react/node_modules/set-value": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-4.1.0.tgz", + "integrity": "sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==", + "funding": [ + "https://github.com/sponsors/jonschlinkert", + "https://paypal.me/jonathanschlinkert", + "https://jonschlinkert.dev/sponsor" + ], + "dependencies": { + "is-plain-object": "^2.0.4", + "is-primitive": "^3.0.1" + }, + "engines": { + "node": ">=11.0" + } + }, + "node_modules/@graphiql/toolkit": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.8.0.tgz", + "integrity": "sha512-DbMFhEKejpPzB6k8W3Mj+Rl8geXiw49USDF9Wdi06EEk1XLVh1iebDqveYY+4lViITsV4+BeGikxlqi8umfP4g==", + "dependencies": { + "@n1ru4l/push-pull-async-iterable-iterator": "^3.1.0", + "meros": "^1.1.4" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0", + "graphql-ws": ">= 4.5.0" + }, + "peerDependenciesMeta": { + "graphql-ws": { + "optional": true + } + } + }, "node_modules/@graphql-typed-document-node/core": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", @@ -5474,6 +5329,30 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@lezer/common": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz", + "integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==", + "peer": true + }, + "node_modules/@lezer/highlight": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.2.tgz", + "integrity": "sha512-CAun1WR1glxG9ZdOokTZwXbcwB7PXkIEyZRUMFBVwSrhTcogWq634/ByNImrkUnQhjju6xsIaOBIxvcRJtplXQ==", + "peer": true, + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz", + "integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==", + "peer": true, + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -5877,6 +5756,14 @@ "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", "dev": true }, + "node_modules/@n1ru4l/push-pull-async-iterable-iterator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz", + "integrity": "sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==", + "engines": { + "node": ">=12" + } + }, "node_modules/@next/bundle-analyzer": { "version": "12.3.1", "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-12.3.1.tgz", @@ -6781,6 +6668,229 @@ "@babel/runtime": "^7.13.10" } }, + "node_modules/@reach/auto-id": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/auto-id/-/auto-id-0.17.0.tgz", + "integrity": "sha512-ud8iPwF52RVzEmkHq1twuqGuPA+moreumUHdtgvU3sr3/15BNhwp3KyDLrKKSz0LP1r3V4pSdyF9MbYM8BoSjA==", + "dependencies": { + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/combobox": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/combobox/-/combobox-0.17.0.tgz", + "integrity": "sha512-2mYvU5agOBCQBMdlM4cri+P1BbNwp05P1OuDyc33xJSNiBG7BMy4+ZSHJ0X4fyle6rHwSgCAOCLOeWV1XUYjoQ==", + "dependencies": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/portal": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/descendants": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/descendants/-/descendants-0.17.0.tgz", + "integrity": "sha512-c7lUaBfjgcmKFZiAWqhG+VnXDMEhPkI4kAav/82XKZD6NVvFjsQOTH+v3tUkskrAPV44Yuch0mFW/u5Ntifr7Q==", + "dependencies": { + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/dialog": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/dialog/-/dialog-0.17.0.tgz", + "integrity": "sha512-AnfKXugqDTGbeG3c8xDcrQDE4h9b/vnc27Sa118oQSquz52fneUeX9MeFb5ZEiBJK8T5NJpv7QUTBIKnFCAH5A==", + "dependencies": { + "@reach/portal": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "react-focus-lock": "^2.5.2", + "react-remove-scroll": "^2.4.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/dropdown": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/dropdown/-/dropdown-0.17.0.tgz", + "integrity": "sha512-qBTIGInhxtPHtdj4Pl2XZgZMz3e37liydh0xR3qc48syu7g71sL4nqyKjOzThykyfhA3Pb3/wFgsFJKGTSdaig==", + "dependencies": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/listbox": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/listbox/-/listbox-0.17.0.tgz", + "integrity": "sha512-AMnH1P6/3VKy2V/nPb4Es441arYR+t4YRdh9jdcFVrCOD6y7CQrlmxsYjeg9Ocdz08XpdoEBHM3PKLJqNAUr7A==", + "dependencies": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/machine": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/machine": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/machine/-/machine-0.17.0.tgz", + "integrity": "sha512-9EHnuPgXzkbRENvRUzJvVvYt+C2jp7PGN0xon7ffmKoK8rTO6eA/bb7P0xgloyDDQtu88TBUXKzW0uASqhTXGA==", + "dependencies": { + "@reach/utils": "0.17.0", + "@xstate/fsm": "1.4.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/menu-button": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/menu-button/-/menu-button-0.17.0.tgz", + "integrity": "sha512-YyuYVyMZKamPtivoEI6D0UEILYH3qZtg4kJzEAuzPmoR/aHN66NZO75Fx0gtjG1S6fZfbiARaCOZJC0VEiDOtQ==", + "dependencies": { + "@reach/dropdown": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x", + "react-is": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/observe-rect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@reach/observe-rect/-/observe-rect-1.2.0.tgz", + "integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==" + }, + "node_modules/@reach/popover": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/popover/-/popover-0.17.0.tgz", + "integrity": "sha512-yYbBF4fMz4Ml4LB3agobZjcZ/oPtPsNv70ZAd7lEC2h7cvhF453pA+zOBGYTPGupKaeBvgAnrMjj7RnxDU5hoQ==", + "dependencies": { + "@reach/portal": "0.17.0", + "@reach/rect": "0.17.0", + "@reach/utils": "0.17.0", + "tabbable": "^4.0.0", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/portal": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/portal/-/portal-0.17.0.tgz", + "integrity": "sha512-+IxsgVycOj+WOeNPL2NdgooUdHPSY285wCtj/iWID6akyr4FgGUK7sMhRM9aGFyrGpx2vzr+eggbUmAVZwOz+A==", + "dependencies": { + "@reach/utils": "0.17.0", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/rect": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/rect/-/rect-0.17.0.tgz", + "integrity": "sha512-3YB7KA5cLjbLc20bmPkJ06DIfXSK06Cb5BbD2dHgKXjUkT9WjZaLYIbYCO8dVjwcyO3GCNfOmPxy62VsPmZwYA==", + "dependencies": { + "@reach/observe-rect": "1.2.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/tooltip": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/tooltip/-/tooltip-0.17.0.tgz", + "integrity": "sha512-HP8Blordzqb/Cxg+jnhGmWQfKgypamcYLBPlcx6jconyV5iLJ5m93qipr1giK7MqKT2wlsKWy44ZcOrJ+Wrf8w==", + "dependencies": { + "@reach/auto-id": "0.17.0", + "@reach/portal": "0.17.0", + "@reach/rect": "0.17.0", + "@reach/utils": "0.17.0", + "@reach/visually-hidden": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/utils": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.17.0.tgz", + "integrity": "sha512-M5y8fCBbrWeIsxedgcSw6oDlAMQDkl5uv3VnMVJ7guwpf4E48Xlh1v66z/1BgN/WYe2y8mB/ilFD2nysEfdGeA==", + "dependencies": { + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, + "node_modules/@reach/visually-hidden": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/visually-hidden/-/visually-hidden-0.17.0.tgz", + "integrity": "sha512-T6xF3Nv8vVnjVkGU6cm0+kWtvliLqPAo8PcZ+WxkKacZsaHTjaZb4v1PaCcyQHmuTNT/vtTVNOJLG0SjQOIb7g==", + "dependencies": { + "prop-types": "^15.7.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || 17.x", + "react-dom": "^16.8.0 || 17.x" + } + }, "node_modules/@react-dnd/asap": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", @@ -10925,6 +11035,11 @@ "node": ">=8" } }, + "node_modules/@xstate/fsm": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.4.0.tgz", + "integrity": "sha512-uTHDeu2xI5E1IFwf37JFQM31RrH7mY7877RqPBS4ZqSNUwoLDuct8AhBWaXGnVizBAYyimVwgCyGa9z/NiRhXA==" + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -13461,6 +13576,39 @@ "node": ">=0.10.0" } }, + "node_modules/codemirror": { + "version": "5.65.9", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz", + "integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==" + }, + "node_modules/codemirror-graphql": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-2.0.2.tgz", + "integrity": "sha512-9c1cItR+8lG7thmTnDDQ3zI8YesNKiFCp2BnLFkYWCtdhSSuCUHebU/Vurew6ayyUl8MBCldNx3Ev66QAWM5Kw==", + "dependencies": { + "graphql-language-service": "5.0.6" + }, + "peerDependencies": { + "@codemirror/language": "6.0.0", + "codemirror": "^5.65.3", + "graphql": "^15.5.0 || ^16.0.0" + } + }, + "node_modules/codemirror-graphql/node_modules/graphql-language-service": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.0.6.tgz", + "integrity": "sha512-FjE23aTy45Lr5metxCv3ZgSKEZOzN7ERR+OFC1isV5mHxI0Ob8XxayLTYjQKrs8b3kOpvgTYmSmu6AyXOzYslg==", + "dependencies": { + "nullthrows": "^1.0.0", + "vscode-languageserver-types": "^3.15.1" + }, + "bin": { + "graphql": "dist/temp-bin.js" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0" + } + }, "node_modules/coffee-script": { "version": "1.12.7", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", @@ -15426,7 +15574,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -18006,6 +18153,23 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphiql": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-2.0.13.tgz", + "integrity": "sha512-hfqcd40aO2V44Z/rey6lGXYnEsbwseeokeeZGQbFfSImciGtyP0SS8MyE5s5yno6z/M0ymJccpaNaUlC6imSwA==", + "dependencies": { + "@graphiql/react": "^0.13.7", + "@graphiql/toolkit": "^0.8.0", + "entities": "^2.0.0", + "graphql-language-service": "^5.1.0", + "markdown-it": "^12.2.0" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/graphql": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", @@ -18014,6 +18178,21 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, + "node_modules/graphql-language-service": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.1.0.tgz", + "integrity": "sha512-APffigZ/l2me6soek+Yq5Us3HBwmfw4vns4QoqsTePXkK3knVO8rn0uAC6PmTyglb1pmFFPbYaRIzW4wmcnnGQ==", + "dependencies": { + "nullthrows": "^1.0.0", + "vscode-languageserver-types": "^3.17.1" + }, + "bin": { + "graphql": "dist/temp-bin.js" + }, + "peerDependencies": { + "graphql": "^15.5.0 || ^16.0.0" + } + }, "node_modules/graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", @@ -19668,6 +19847,14 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, + "node_modules/is-primitive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", + "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-reference": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz", @@ -23473,6 +23660,14 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/list-item": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", @@ -23845,6 +24040,34 @@ "node": ">=0.10.0" } }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/markdown-link": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", @@ -24598,6 +24821,22 @@ "node": ">= 8" } }, + "node_modules/meros": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.2.1.tgz", + "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==", + "engines": { + "node": ">=13" + }, + "peerDependencies": { + "@types/node": ">=13" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -26155,6 +26394,11 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, "node_modules/num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -29240,6 +29484,17 @@ "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-clientside-effect": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", + "integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==", + "dependencies": { + "@babel/runtime": "^7.12.13" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-contexify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-contexify/-/react-contexify-5.0.0.tgz", @@ -29465,6 +29720,39 @@ "react": ">=16.8.6" } }, + "node_modules/react-focus-lock": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.1.tgz", + "integrity": "sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "focus-lock": "^0.11.2", + "prop-types": "^15.6.2", + "react-clientside-effect": "^1.2.6", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-focus-lock/node_modules/focus-lock": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.3.tgz", + "integrity": "sha512-4n0pYcPTa/uI7Q66BZna61nRT7lDhnuJ9PJr6wiDjx4uStg491ks41y7uOG+s0umaaa+hulNKSldU9aTg9/yVg==", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/react-from-dom": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.6.2.tgz", @@ -32919,6 +33207,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", + "peer": true + }, "node_modules/style-to-object": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", @@ -33077,6 +33371,11 @@ "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", "dev": true }, + "node_modules/tabbable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz", + "integrity": "sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==" + }, "node_modules/table": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", @@ -34342,6 +34641,11 @@ "node": ">=4.2.0" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -35255,6 +35559,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "devOptional": true }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -35264,6 +35573,12 @@ "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", + "peer": true + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", @@ -36830,6 +37145,8 @@ "dayjs": "^1.11.0", "file-saver": "^2.0.5", "generate-password": "^1.7.0", + "graphiql": "^2.0.13", + "graphql": "^16.6.0", "html-to-image": "^1.10.8", "immutability-helper": "^3.1.1", "json-logic-js": "^2.0.2", @@ -39084,6 +39401,37 @@ "minimist": "^1.2.0" } }, + "@codemirror/language": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.0.0.tgz", + "integrity": "sha512-rtjk5ifyMzOna1c7PBu7J1VCt0PvA5wy3o8eMVnxMKb7z8KA7JFecvD04dSn14vj/bBaAbqRsGed5OjtofEnLA==", + "peer": true, + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "@codemirror/state": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==", + "peer": true + }, + "@codemirror/view": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.4.0.tgz", + "integrity": "sha512-Kv32b6Tn7QVwFbj/EDswTLSocjk5kgggF6zzBFAL4o4hZ/vmtFD155+EjH1pVlbfoDyVC2M6SedPsMrwYscgNg==", + "peer": true, + "requires": { + "@codemirror/state": "^6.0.0", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -39315,6 +39663,46 @@ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, + "@graphiql/react": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/@graphiql/react/-/react-0.13.7.tgz", + "integrity": "sha512-mI+6mXd9AJFDJy39VuZGxCiVLvmBe2XoNidbN3lXgTLe689RZKifPaUw41USitQOu20sASoYDfzJ8i98G4urow==", + "requires": { + "@graphiql/toolkit": "^0.8.0", + "@reach/combobox": "^0.17.0", + "@reach/dialog": "^0.17.0", + "@reach/listbox": "^0.17.0", + "@reach/menu-button": "^0.17.0", + "@reach/tooltip": "^0.17.0", + "@reach/visually-hidden": "^0.17.0", + "codemirror": "^5.65.3", + "codemirror-graphql": "^2.0.2", + "copy-to-clipboard": "^3.2.0", + "graphql-language-service": "^5.1.0", + "markdown-it": "^12.2.0", + "set-value": "^4.1.0" + }, + "dependencies": { + "set-value": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-4.1.0.tgz", + "integrity": "sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==", + "requires": { + "is-plain-object": "^2.0.4", + "is-primitive": "^3.0.1" + } + } + } + }, + "@graphiql/toolkit": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.8.0.tgz", + "integrity": "sha512-DbMFhEKejpPzB6k8W3Mj+Rl8geXiw49USDF9Wdi06EEk1XLVh1iebDqveYY+4lViITsV4+BeGikxlqi8umfP4g==", + "requires": { + "@n1ru4l/push-pull-async-iterable-iterator": "^3.1.0", + "meros": "^1.1.4" + } + }, "@graphql-typed-document-node/core": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", @@ -40578,6 +40966,30 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@lezer/common": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz", + "integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==", + "peer": true + }, + "@lezer/highlight": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.2.tgz", + "integrity": "sha512-CAun1WR1glxG9ZdOokTZwXbcwB7PXkIEyZRUMFBVwSrhTcogWq634/ByNImrkUnQhjju6xsIaOBIxvcRJtplXQ==", + "peer": true, + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/lr": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz", + "integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==", + "peer": true, + "requires": { + "@lezer/common": "^1.0.0" + } + }, "@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -40860,6 +41272,11 @@ } } }, + "@n1ru4l/push-pull-async-iterable-iterator": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz", + "integrity": "sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q==" + }, "@next/bundle-analyzer": { "version": "12.3.1", "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-12.3.1.tgz", @@ -41494,6 +41911,172 @@ "@babel/runtime": "^7.13.10" } }, + "@reach/auto-id": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/auto-id/-/auto-id-0.17.0.tgz", + "integrity": "sha512-ud8iPwF52RVzEmkHq1twuqGuPA+moreumUHdtgvU3sr3/15BNhwp3KyDLrKKSz0LP1r3V4pSdyF9MbYM8BoSjA==", + "requires": { + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + } + }, + "@reach/combobox": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/combobox/-/combobox-0.17.0.tgz", + "integrity": "sha512-2mYvU5agOBCQBMdlM4cri+P1BbNwp05P1OuDyc33xJSNiBG7BMy4+ZSHJ0X4fyle6rHwSgCAOCLOeWV1XUYjoQ==", + "requires": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/portal": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/descendants": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/descendants/-/descendants-0.17.0.tgz", + "integrity": "sha512-c7lUaBfjgcmKFZiAWqhG+VnXDMEhPkI4kAav/82XKZD6NVvFjsQOTH+v3tUkskrAPV44Yuch0mFW/u5Ntifr7Q==", + "requires": { + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + } + }, + "@reach/dialog": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/dialog/-/dialog-0.17.0.tgz", + "integrity": "sha512-AnfKXugqDTGbeG3c8xDcrQDE4h9b/vnc27Sa118oQSquz52fneUeX9MeFb5ZEiBJK8T5NJpv7QUTBIKnFCAH5A==", + "requires": { + "@reach/portal": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "react-focus-lock": "^2.5.2", + "react-remove-scroll": "^2.4.3", + "tslib": "^2.3.0" + } + }, + "@reach/dropdown": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/dropdown/-/dropdown-0.17.0.tgz", + "integrity": "sha512-qBTIGInhxtPHtdj4Pl2XZgZMz3e37liydh0xR3qc48syu7g71sL4nqyKjOzThykyfhA3Pb3/wFgsFJKGTSdaig==", + "requires": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "tslib": "^2.3.0" + } + }, + "@reach/listbox": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/listbox/-/listbox-0.17.0.tgz", + "integrity": "sha512-AMnH1P6/3VKy2V/nPb4Es441arYR+t4YRdh9jdcFVrCOD6y7CQrlmxsYjeg9Ocdz08XpdoEBHM3PKLJqNAUr7A==", + "requires": { + "@reach/auto-id": "0.17.0", + "@reach/descendants": "0.17.0", + "@reach/machine": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2" + } + }, + "@reach/machine": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/machine/-/machine-0.17.0.tgz", + "integrity": "sha512-9EHnuPgXzkbRENvRUzJvVvYt+C2jp7PGN0xon7ffmKoK8rTO6eA/bb7P0xgloyDDQtu88TBUXKzW0uASqhTXGA==", + "requires": { + "@reach/utils": "0.17.0", + "@xstate/fsm": "1.4.0", + "tslib": "^2.3.0" + } + }, + "@reach/menu-button": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/menu-button/-/menu-button-0.17.0.tgz", + "integrity": "sha512-YyuYVyMZKamPtivoEI6D0UEILYH3qZtg4kJzEAuzPmoR/aHN66NZO75Fx0gtjG1S6fZfbiARaCOZJC0VEiDOtQ==", + "requires": { + "@reach/dropdown": "0.17.0", + "@reach/popover": "0.17.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/observe-rect": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@reach/observe-rect/-/observe-rect-1.2.0.tgz", + "integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ==" + }, + "@reach/popover": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/popover/-/popover-0.17.0.tgz", + "integrity": "sha512-yYbBF4fMz4Ml4LB3agobZjcZ/oPtPsNv70ZAd7lEC2h7cvhF453pA+zOBGYTPGupKaeBvgAnrMjj7RnxDU5hoQ==", + "requires": { + "@reach/portal": "0.17.0", + "@reach/rect": "0.17.0", + "@reach/utils": "0.17.0", + "tabbable": "^4.0.0", + "tslib": "^2.3.0" + } + }, + "@reach/portal": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/portal/-/portal-0.17.0.tgz", + "integrity": "sha512-+IxsgVycOj+WOeNPL2NdgooUdHPSY285wCtj/iWID6akyr4FgGUK7sMhRM9aGFyrGpx2vzr+eggbUmAVZwOz+A==", + "requires": { + "@reach/utils": "0.17.0", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/rect": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/rect/-/rect-0.17.0.tgz", + "integrity": "sha512-3YB7KA5cLjbLc20bmPkJ06DIfXSK06Cb5BbD2dHgKXjUkT9WjZaLYIbYCO8dVjwcyO3GCNfOmPxy62VsPmZwYA==", + "requires": { + "@reach/observe-rect": "1.2.0", + "@reach/utils": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/tooltip": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/tooltip/-/tooltip-0.17.0.tgz", + "integrity": "sha512-HP8Blordzqb/Cxg+jnhGmWQfKgypamcYLBPlcx6jconyV5iLJ5m93qipr1giK7MqKT2wlsKWy44ZcOrJ+Wrf8w==", + "requires": { + "@reach/auto-id": "0.17.0", + "@reach/portal": "0.17.0", + "@reach/rect": "0.17.0", + "@reach/utils": "0.17.0", + "@reach/visually-hidden": "0.17.0", + "prop-types": "^15.7.2", + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/utils": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/utils/-/utils-0.17.0.tgz", + "integrity": "sha512-M5y8fCBbrWeIsxedgcSw6oDlAMQDkl5uv3VnMVJ7guwpf4E48Xlh1v66z/1BgN/WYe2y8mB/ilFD2nysEfdGeA==", + "requires": { + "tiny-warning": "^1.0.3", + "tslib": "^2.3.0" + } + }, + "@reach/visually-hidden": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@reach/visually-hidden/-/visually-hidden-0.17.0.tgz", + "integrity": "sha512-T6xF3Nv8vVnjVkGU6cm0+kWtvliLqPAo8PcZ+WxkKacZsaHTjaZb4v1PaCcyQHmuTNT/vtTVNOJLG0SjQOIb7g==", + "requires": { + "prop-types": "^15.7.2", + "tslib": "^2.3.0" + } + }, "@react-dnd/asap": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-4.0.1.tgz", @@ -44682,6 +45265,11 @@ "tslib": "^2.3.0" } }, + "@xstate/fsm": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.4.0.tgz", + "integrity": "sha512-uTHDeu2xI5E1IFwf37JFQM31RrH7mY7877RqPBS4ZqSNUwoLDuct8AhBWaXGnVizBAYyimVwgCyGa9z/NiRhXA==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -46609,6 +47197,30 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" }, + "codemirror": { + "version": "5.65.9", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz", + "integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==" + }, + "codemirror-graphql": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-2.0.2.tgz", + "integrity": "sha512-9c1cItR+8lG7thmTnDDQ3zI8YesNKiFCp2BnLFkYWCtdhSSuCUHebU/Vurew6ayyUl8MBCldNx3Ev66QAWM5Kw==", + "requires": { + "graphql-language-service": "5.0.6" + }, + "dependencies": { + "graphql-language-service": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.0.6.tgz", + "integrity": "sha512-FjE23aTy45Lr5metxCv3ZgSKEZOzN7ERR+OFC1isV5mHxI0Ob8XxayLTYjQKrs8b3kOpvgTYmSmu6AyXOzYslg==", + "requires": { + "nullthrows": "^1.0.0", + "vscode-languageserver-types": "^3.15.1" + } + } + } + }, "coffee-script": { "version": "1.12.7", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", @@ -48245,8 +48857,7 @@ "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, "errno": { "version": "0.1.8", @@ -50235,11 +50846,32 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphiql": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/graphiql/-/graphiql-2.0.13.tgz", + "integrity": "sha512-hfqcd40aO2V44Z/rey6lGXYnEsbwseeokeeZGQbFfSImciGtyP0SS8MyE5s5yno6z/M0ymJccpaNaUlC6imSwA==", + "requires": { + "@graphiql/react": "^0.13.7", + "@graphiql/toolkit": "^0.8.0", + "entities": "^2.0.0", + "graphql-language-service": "^5.1.0", + "markdown-it": "^12.2.0" + } + }, "graphql": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==" }, + "graphql-language-service": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.1.0.tgz", + "integrity": "sha512-APffigZ/l2me6soek+Yq5Us3HBwmfw4vns4QoqsTePXkK3knVO8rn0uAC6PmTyglb1pmFFPbYaRIzW4wmcnnGQ==", + "requires": { + "nullthrows": "^1.0.0", + "vscode-languageserver-types": "^3.17.1" + } + }, "graphql-tag": { "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", @@ -51418,6 +52050,11 @@ "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" }, + "is-primitive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", + "integrity": "sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==" + }, "is-reference": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.0.tgz", @@ -54336,6 +54973,14 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "requires": { + "uc.micro": "^1.0.1" + } + }, "list-item": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/list-item/-/list-item-1.1.1.tgz", @@ -54639,6 +55284,30 @@ "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-1.1.1.tgz", "integrity": "sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==" }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + } + } + }, "markdown-link": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/markdown-link/-/markdown-link-0.1.1.tgz", @@ -55214,6 +55883,12 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, + "meros": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/meros/-/meros-1.2.1.tgz", + "integrity": "sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g==", + "requires": {} + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -56288,6 +56963,11 @@ "boolbase": "^1.0.0" } }, + "nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==" + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -58618,6 +59298,14 @@ "use-memo-one": "^1.1.1" } }, + "react-clientside-effect": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", + "integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==", + "requires": { + "@babel/runtime": "^7.12.13" + } + }, "react-contexify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-contexify/-/react-contexify-5.0.0.tgz", @@ -58784,6 +59472,29 @@ "prop-types": "^15.7.2" } }, + "react-focus-lock": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.1.tgz", + "integrity": "sha512-pSWOQrUmiKLkffPO6BpMXN7SNKXMsuOakl652IBuALAu1esk+IcpJyM+ALcYzPTTFz1rD0R54aB9A4HuP5t1Wg==", + "requires": { + "@babel/runtime": "^7.0.0", + "focus-lock": "^0.11.2", + "prop-types": "^15.6.2", + "react-clientside-effect": "^1.2.6", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "dependencies": { + "focus-lock": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.3.tgz", + "integrity": "sha512-4n0pYcPTa/uI7Q66BZna61nRT7lDhnuJ9PJr6wiDjx4uStg491ks41y7uOG+s0umaaa+hulNKSldU9aTg9/yVg==", + "requires": { + "tslib": "^2.0.3" + } + } + } + }, "react-from-dom": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.6.2.tgz", @@ -61415,6 +62126,8 @@ "dayjs": "^1.11.0", "file-saver": "^2.0.5", "generate-password": "^1.7.0", + "graphiql": "*", + "graphql": "*", "html-to-image": "^1.10.8", "immutability-helper": "^3.1.1", "jest": "^27.4.0", @@ -61658,6 +62371,12 @@ } } }, + "style-mod": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz", + "integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==", + "peer": true + }, "style-to-object": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", @@ -62018,6 +62737,11 @@ "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", "dev": true }, + "tabbable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-4.0.0.tgz", + "integrity": "sha512-H1XoH1URcBOa/rZZWxLxHCtOdVUEev+9vo5YdYhC9tCY4wnybX+VQrCYuy9ubkg69fCBxCONJOSLGfw0DWMffQ==" + }, "table": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", @@ -62159,7 +62883,7 @@ "lodash": "^4.17.21", "markdown-toc": "^1.2.0", "minimist": "^1.2.6", - "next": "12.0.9", + "next": "12.1.0", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "^3.0.8", "next-themes": "0.0.15", @@ -62235,77 +62959,6 @@ "version": "1.6.22", "requires": {} }, - "@next/env": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-12.0.9.tgz", - "integrity": "sha512-oBlkyDop0Stf7MPIzETGv5r0YT/G/weBrknoPOUTaa5qwOeGjuy6gsOVc/SBtrBkOoBmRpD+fFhQJPvmo1mS+g==" - }, - "@next/swc-android-arm64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.0.9.tgz", - "integrity": "sha512-aVqgsEn5plmUH2X58sjzhHsH/6majucWTMaaBEs7hHO2+GCwCZc7zaLH4XCBMKPES9Yaja8/pYUbvZQE9DqgFw==", - "optional": true - }, - "@next/swc-darwin-arm64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.9.tgz", - "integrity": "sha512-uAgRKm4a2nVdyBiPPJokvmDD1saugOvxljz9ld2ih0CCg5S9vBhqaj3kPGCQBj9hSu3q+Lng2CHnQqG3ga1jzA==", - "optional": true - }, - "@next/swc-darwin-x64": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.9.tgz", - "integrity": "sha512-fDOs2lZIyrAdU18IxMA5orBPn9qLbOdu55gXSTNZOhyRJ8ugtbUAejsK7OL0boJy0CCHPAdVRXm01Mwk8tZ9RQ==", - "optional": true - }, - "@next/swc-linux-arm-gnueabihf": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.9.tgz", - "integrity": "sha512-/ni0p9DBvATUML9RQ1ycQuf05uOYKdzA6iI8+eRsARjpGbFVUFbge7XPzlj9g2Q9YWgoN8CSjFGnKRlyky5uHA==", - "optional": true - }, - "@next/swc-linux-arm64-gnu": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.9.tgz", - "integrity": "sha512-AphxilJDf95rUxJDHgM9Ww1DaYXZWqTvoKwXeej/0SgSvICcRZrLaFDrkojdXz0Rxr4igX2OdYR1S4/Hj1jWOQ==", - "optional": true - }, - "@next/swc-linux-arm64-musl": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.9.tgz", - "integrity": "sha512-K5jbvNNzF3mRjWmPdxP5Bg87i7FHivfBj/L0KJlxpkLSC8sffBJDmB6jtMnI7wiPj9J6vmLkbGtSosln78xAlQ==", - "optional": true - }, - "@next/swc-linux-x64-gnu": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.9.tgz", - "integrity": "sha512-bJZ9bkMkQzsY+UyWezEZ77GWQ4TzwKeXdayX3U3+aEkL8k5C6eKBXlidWdrhu0teLmaUXIyWerWrLnJzwGXdfw==", - "optional": true - }, - "@next/swc-linux-x64-musl": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.9.tgz", - "integrity": "sha512-SR9p0R+v1T32DTXPVAXZw31pmJAkSDotC6Afy+mfC0xrEL3pp95R8sGXYAAUCEPkQp0MEeUOVy2LrToe92X7hQ==", - "optional": true - }, - "@next/swc-win32-arm64-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.9.tgz", - "integrity": "sha512-mzQ1A8vfHhJrvEy5KJZGZWEByXthyKfWofvFaf+oo/5nJl/0Bz1ODP2ajSmbLG++77Eo2AROgbm9pkW1ucvG2A==", - "optional": true - }, - "@next/swc-win32-ia32-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.9.tgz", - "integrity": "sha512-MpD2vj1zjo1u3J3wiz3pEKse19Etz+P0GL6XfQkB/9a84vJQ1JWMaWBjmIdivzZv718Il2pRSSx8hymwPfguYQ==", - "optional": true - }, - "@next/swc-win32-x64-msvc": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.9.tgz", - "integrity": "sha512-1c/sxp/4Qz4F6rCxiYqAnrmghCOFt5hHZ9Kd+rXFW5Mqev4C4XDOUMHdBH55HgnJZqngYhOE0r/XNkCtsIojig==", - "optional": true - }, "@radix-ui/primitive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", @@ -62642,29 +63295,6 @@ "version": "0.4.1", "dev": true }, - "next": { - "version": "12.0.9", - "resolved": "https://registry.npmjs.org/next/-/next-12.0.9.tgz", - "integrity": "sha512-omfYqoR/DvbdOIJ6SS1unKJ4mGIxUPs0RPa7wr/Mft22OCKgJhuG+aI9KFYi5ZJBwoFQk1vqaMKpWz5qr+dN0Q==", - "requires": { - "@next/env": "12.0.9", - "@next/swc-android-arm64": "12.0.9", - "@next/swc-darwin-arm64": "12.0.9", - "@next/swc-darwin-x64": "12.0.9", - "@next/swc-linux-arm-gnueabihf": "12.0.9", - "@next/swc-linux-arm64-gnu": "12.0.9", - "@next/swc-linux-arm64-musl": "12.0.9", - "@next/swc-linux-x64-gnu": "12.0.9", - "@next/swc-linux-x64-musl": "12.0.9", - "@next/swc-win32-arm64-msvc": "12.0.9", - "@next/swc-win32-ia32-msvc": "12.0.9", - "@next/swc-win32-x64-msvc": "12.0.9", - "caniuse-lite": "^1.0.30001283", - "postcss": "8.4.5", - "styled-jsx": "5.0.0", - "use-subscription": "1.5.1" - } - }, "next-mdx-remote": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/next-mdx-remote/-/next-mdx-remote-3.0.8.tgz", @@ -62692,16 +63322,6 @@ "word-wrap": "^1.2.3" } }, - "postcss": { - "version": "8.4.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", - "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", - "requires": { - "nanoid": "^3.1.30", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.1" - } - }, "supports-color": { "version": "7.2.0", "dev": true, @@ -63494,6 +64114,11 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==" }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -64175,6 +64800,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "devOptional": true }, + "vscode-languageserver-types": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.2.tgz", + "integrity": "sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==" + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -64183,6 +64813,12 @@ "browser-process-hrtime": "^1.0.0" } }, + "w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==", + "peer": true + }, "w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", diff --git a/studio/package.json b/studio/package.json index 1b9790d0711..03b6da52c66 100644 --- a/studio/package.json +++ b/studio/package.json @@ -39,6 +39,8 @@ "dayjs": "^1.11.0", "file-saver": "^2.0.5", "generate-password": "^1.7.0", + "graphiql": "^2.0.13", + "graphql": "^16.6.0", "html-to-image": "^1.10.8", "immutability-helper": "^3.1.1", "json-logic-js": "^2.0.2", diff --git a/studio/pages/project/[ref]/graphql/index.tsx b/studio/pages/project/[ref]/graphql/index.tsx new file mode 100644 index 00000000000..01b89f9585e --- /dev/null +++ b/studio/pages/project/[ref]/graphql/index.tsx @@ -0,0 +1,34 @@ +import { createGraphiQLFetcher } from '@graphiql/toolkit' +import { GraphiQL } from 'graphiql' +import { observer } from 'mobx-react-lite' +import 'graphiql/graphiql.css' + +import { ProjectLayoutWithAuth } from 'components/layouts' +import { useStore } from 'hooks' +import { NextPageWithLayout } from 'types' + +const fetcher = createGraphiQLFetcher({ + url: 'https://yrjyofbjvjypdsexuvvu.supabase.red/graphql/v1', + fetch, + headers: { + apikey: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlyanlvZmJqdmp5cGRzZXh1dnZ1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjczNTg0OTIsImV4cCI6MTk4MjkzNDQ5Mn0.CMVzrM7R0ym8ukt5miDoNL0ELhsM9fxOx2Qpm0hsLFE', + }, +}) + +const GraphiQLPage: NextPageWithLayout = () => { + const { ui } = useStore() + + const project = ui.selectedProject + console.log('project:', project) + + return +} + +GraphiQLPage.getLayout = (page) => ( + +
{page}
+
+) + +export default observer(GraphiQLPage) From 6cfb9283d662b5b9f48171605c3bde255485880c Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Wed, 2 Nov 2022 16:31:57 +1100 Subject: [PATCH 002/289] adds graphiql menu item --- package-lock.json | 6 +- .../NavigationBar/NavigationBar.utils.tsx | 14 +++++ studio/package.json | 1 + studio/pages/project/[ref]/graphiql/index.tsx | 59 +++++++++++++++++++ studio/pages/project/[ref]/graphql/index.tsx | 34 ----------- studio/public/img/graphql.svg | 10 ++++ 6 files changed, 88 insertions(+), 36 deletions(-) create mode 100644 studio/pages/project/[ref]/graphiql/index.tsx delete mode 100644 studio/pages/project/[ref]/graphql/index.tsx create mode 100644 studio/public/img/graphql.svg diff --git a/package-lock.json b/package-lock.json index c676116c2ca..2d9b2c00154 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37120,6 +37120,7 @@ "studio": { "version": "0.0.9", "dependencies": { + "@graphiql/toolkit": "^0.8.0", "@headlessui/react": "^1.4.1", "@monaco-editor/react": "^4.3.1", "@next/bundle-analyzer": "^12.0.4", @@ -62070,6 +62071,7 @@ "version": "file:studio", "requires": { "@babel/core": "^7.17.5", + "@graphiql/toolkit": "*", "@headlessui/react": "^1.4.1", "@monaco-editor/react": "^4.3.1", "@next/bundle-analyzer": "^12.0.4", @@ -62126,8 +62128,8 @@ "dayjs": "^1.11.0", "file-saver": "^2.0.5", "generate-password": "^1.7.0", - "graphiql": "*", - "graphql": "*", + "graphiql": "^2.0.13", + "graphql": "^16.6.0", "html-to-image": "^1.10.8", "immutability-helper": "^3.1.1", "jest": "^27.4.0", diff --git a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx index c5b6ddb9036..6ef0458c2be 100644 --- a/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx +++ b/studio/components/layouts/ProjectLayout/NavigationBar/NavigationBar.utils.tsx @@ -50,6 +50,20 @@ export const generateToolRoutes = (ref?: string, project?: ProjectBase): Route[] ref && (isProjectPaused ? homeUrl : isProjectBuilding ? buildingUrl : `/project/${ref}/sql`), }, + { + key: 'graphiql', + label: 'GraphiQL', + icon: ( + code.replace(/svg/, 'svg class="m-auto text-color-inherit"')} + /> + ), + link: + ref && + (isProjectPaused ? homeUrl : isProjectBuilding ? buildingUrl : `/project/${ref}/graphiql`), + }, ] } export const generateProductRoutes = (ref?: string, project?: ProjectBase): Route[] => { diff --git a/studio/package.json b/studio/package.json index 03b6da52c66..62bd3fbd52a 100644 --- a/studio/package.json +++ b/studio/package.json @@ -14,6 +14,7 @@ "prettier:write": "prettier --write ." }, "dependencies": { + "@graphiql/toolkit": "^0.8.0", "@headlessui/react": "^1.4.1", "@monaco-editor/react": "^4.3.1", "@next/bundle-analyzer": "^12.0.4", diff --git a/studio/pages/project/[ref]/graphiql/index.tsx b/studio/pages/project/[ref]/graphiql/index.tsx new file mode 100644 index 00000000000..bbf6f911558 --- /dev/null +++ b/studio/pages/project/[ref]/graphiql/index.tsx @@ -0,0 +1,59 @@ +import { createGraphiQLFetcher } from '@graphiql/toolkit' +import { GraphiQL } from 'graphiql' +import 'graphiql/graphiql.css' + +import { ProjectLayoutWithAuth } from 'components/layouts' +import Connecting from 'components/ui/Loading/Loading' +import { useParams, useProjectSettings } from 'hooks' +import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' +import { useMemo } from 'react' +import { NextPageWithLayout } from 'types' +import { IconAlertCircle } from 'ui' + +const GraphiQLPage: NextPageWithLayout = () => { + const { ref } = useParams() + + const { + services, + isError: isProjectSettingsError, + isLoading: isProjectSettingsLoading, + } = useProjectSettings(ref) + + const apiService = (services ?? []).find((x: any) => x.app.id == DEFAULT_PROJECT_API_SERVICE_ID) + const apiConfig = apiService?.app_config ?? {} + const apiKeys = apiService?.service_api_keys ?? [] + + const graphqlUrl = `https://${apiConfig.endpoint}/graphql/v1` + const anonKey = apiKeys.find((key: any) => key.tags === 'anon')?.api_key + + const fetcher = useMemo(() => { + return createGraphiQLFetcher({ + url: graphqlUrl, + fetch, + headers: { + apikey: anonKey, + }, + }) + }, [graphqlUrl, anonKey]) + + if (isProjectSettingsLoading) { + return + } + + if (isProjectSettingsError) { + return ( +
+ +

Failed to retrieve API keys

+
+ ) + } + + return +} + +GraphiQLPage.getLayout = (page) => ( + {page} +) + +export default GraphiQLPage diff --git a/studio/pages/project/[ref]/graphql/index.tsx b/studio/pages/project/[ref]/graphql/index.tsx deleted file mode 100644 index 01b89f9585e..00000000000 --- a/studio/pages/project/[ref]/graphql/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { createGraphiQLFetcher } from '@graphiql/toolkit' -import { GraphiQL } from 'graphiql' -import { observer } from 'mobx-react-lite' -import 'graphiql/graphiql.css' - -import { ProjectLayoutWithAuth } from 'components/layouts' -import { useStore } from 'hooks' -import { NextPageWithLayout } from 'types' - -const fetcher = createGraphiQLFetcher({ - url: 'https://yrjyofbjvjypdsexuvvu.supabase.red/graphql/v1', - fetch, - headers: { - apikey: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlyanlvZmJqdmp5cGRzZXh1dnZ1Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjczNTg0OTIsImV4cCI6MTk4MjkzNDQ5Mn0.CMVzrM7R0ym8ukt5miDoNL0ELhsM9fxOx2Qpm0hsLFE', - }, -}) - -const GraphiQLPage: NextPageWithLayout = () => { - const { ui } = useStore() - - const project = ui.selectedProject - console.log('project:', project) - - return -} - -GraphiQLPage.getLayout = (page) => ( - -
{page}
-
-) - -export default observer(GraphiQLPage) diff --git a/studio/public/img/graphql.svg b/studio/public/img/graphql.svg new file mode 100644 index 00000000000..8060db470ea --- /dev/null +++ b/studio/public/img/graphql.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file From 3274074846295f74397370ecc29a281aec6067e3 Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Wed, 2 Nov 2022 17:10:02 +1100 Subject: [PATCH 003/289] only show graphiql interface if graphql extension is enabled --- studio/pages/project/[ref]/graphiql/index.tsx | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/studio/pages/project/[ref]/graphiql/index.tsx b/studio/pages/project/[ref]/graphiql/index.tsx index bbf6f911558..b7382665d15 100644 --- a/studio/pages/project/[ref]/graphiql/index.tsx +++ b/studio/pages/project/[ref]/graphiql/index.tsx @@ -1,17 +1,31 @@ +import { observer } from 'mobx-react-lite' import { createGraphiQLFetcher } from '@graphiql/toolkit' import { GraphiQL } from 'graphiql' import 'graphiql/graphiql.css' +import ExtensionCard from 'components/interfaces/Database/Extensions/ExtensionCard' import { ProjectLayoutWithAuth } from 'components/layouts' import Connecting from 'components/ui/Loading/Loading' -import { useParams, useProjectSettings } from 'hooks' +import { useParams, useProjectSettings, useStore } from 'hooks' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' -import { useMemo } from 'react' +import { useEffect, useMemo } from 'react' import { NextPageWithLayout } from 'types' import { IconAlertCircle } from 'ui' const GraphiQLPage: NextPageWithLayout = () => { const { ref } = useParams() + const { ui, meta } = useStore() + + const isExtensionsLoading = meta.extensions.isLoading + const pgGraphqlExtension = meta.extensions.byId('pg_graphql') + + useEffect(() => { + if (ui.selectedProject?.ref) { + // Schemas may be needed when enabling the GraphQL extension + meta.schemas.load() + meta.extensions.load() + } + }, [ui.selectedProject?.ref]) const { services, @@ -36,7 +50,7 @@ const GraphiQLPage: NextPageWithLayout = () => { }) }, [graphqlUrl, anonKey]) - if (isProjectSettingsLoading) { + if (isProjectSettingsLoading || (isExtensionsLoading && !pgGraphqlExtension)) { return } @@ -49,6 +63,24 @@ const GraphiQLPage: NextPageWithLayout = () => { ) } + if (pgGraphqlExtension?.installed_version === null) { + return ( +
+
+
+

Enable the GraphQL Extension

+

+ Toggle the switch below to enable the GraphQL extension. Then you can use the GraphQL + API with your Supabase Database. +

+
+ + +
+
+ ) + } + return } @@ -56,4 +88,4 @@ GraphiQLPage.getLayout = (page) => ( {page} ) -export default GraphiQLPage +export default observer(GraphiQLPage) From 8e069fd002c9cabedcfe4bc448a5d4fbcdc23f93 Mon Sep 17 00:00:00 2001 From: Tilman Vogel Date: Tue, 31 Jan 2023 15:11:37 +0100 Subject: [PATCH 004/289] Add section about testing row-level-security --- .../pages/guides/auth/row-level-security.mdx | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/apps/docs/pages/guides/auth/row-level-security.mdx b/apps/docs/pages/guides/auth/row-level-security.mdx index eca412cd214..a4d5b2a8226 100644 --- a/apps/docs/pages/guides/auth/row-level-security.mdx +++ b/apps/docs/pages/guides/auth/row-level-security.mdx @@ -328,6 +328,64 @@ Tip: Make sure to enable RLS for all your tables, so that your tables are inacce Supabase provides special "Service" keys, which can be used to bypass all RLS. These should never be used in the browser or exposed to customers, but they are useful for administrative tasks. +### Testing policies + +In order to test policies on the database itself, i.e. from the SQL editor or from `psql` without switching to your frontend and logging in as different users, you can utilize the following helper SQL procedures ([credits](https://github.com/supabase/supabase/issues/7311#issuecomment-1398648114)): + +```sql +GRANT anon, authenticated TO postgres; + +CREATE OR REPLACE PROCEDURE auth.login_as_user (user_email text) + LANGUAGE plpgsql + AS $$ +DECLARE + auth_user auth.users; +BEGIN + SELECT + * INTO auth_user + FROM + auth.users + WHERE + email = user_email; + EXECUTE format('SET request.jwt.claim.sub=%L', (auth_user).id::text); + EXECUTE format('SET request.jwt.claim.role=%I', (auth_user).ROLE); + EXECUTE format('SET request.jwt.claim.email=%L', (auth_user).email); + EXECUTE format('SET request.jwt.claims=%L', json_strip_nulls(json_build_object('app_metadata', (auth_user).raw_app_meta_data))::text); + + RAISE NOTICE '%', format( 'SET ROLE %I; -- Logging in as %L (%L)', (auth_user).ROLE, (auth_user).id, (auth_user).email); + EXECUTE format('SET ROLE %I', (auth_user).ROLE); +END; +$$; + +CREATE OR REPLACE PROCEDURE auth.login_as_anon () + LANGUAGE plpgsql + AS $$ +BEGIN + SET request.jwt.claim.sub=''; + SET request.jwt.claim.role=''; + SET request.jwt.claim.email=''; + SET request.jwt.claims=''; + SET ROLE anon; +END; +$$; + +CREATE OR REPLACE PROCEDURE auth.logout () + LANGUAGE plpgsql + AS $$ +BEGIN + SET request.jwt.claim.sub=''; + SET request.jwt.claim.role=''; + SET request.jwt.claim.email=''; + SET request.jwt.claims=''; + SET ROLE postgres; +END; +$$; +``` + +In order to switch to a given user (by email), use `CALL auth.login_as_user('my@email.com');`. You can also switch to the `anon` role using `CALL auth.login_as_anon();`. When you are done, use `CALL auth.logout();` which will return yourself to the powerful `postgres` role. + +These procedures are also very handy for writing [pgTAP](/docs/guides/database/extensions/pgtap) unit-tests for policies. + ## Deprecated features We have deprecate some functions to ensure better performance and extensibilty of RLS policies. From f4e05ec743e55aa33b4799dcd6e8eb8438706682 Mon Sep 17 00:00:00 2001 From: dng Date: Tue, 31 Jan 2023 17:03:50 -0800 Subject: [PATCH 005/289] Apply suggestions from code review --- apps/docs/pages/guides/auth/row-level-security.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/docs/pages/guides/auth/row-level-security.mdx b/apps/docs/pages/guides/auth/row-level-security.mdx index a4d5b2a8226..0700d4fdc0d 100644 --- a/apps/docs/pages/guides/auth/row-level-security.mdx +++ b/apps/docs/pages/guides/auth/row-level-security.mdx @@ -330,7 +330,7 @@ These should never be used in the browser or exposed to customers, but they are ### Testing policies -In order to test policies on the database itself, i.e. from the SQL editor or from `psql` without switching to your frontend and logging in as different users, you can utilize the following helper SQL procedures ([credits](https://github.com/supabase/supabase/issues/7311#issuecomment-1398648114)): +To test policies on the database itself (i.e., from the [SQL Editor](https://app.supabase.com/project/_/sql) or from `psql`) without switching to your frontend and logging in as different users, you can utilize the following helper SQL procedures ([credits](https://github.com/supabase/supabase/issues/7311#issuecomment-1398648114)): ```sql GRANT anon, authenticated TO postgres; @@ -382,9 +382,9 @@ END; $$; ``` -In order to switch to a given user (by email), use `CALL auth.login_as_user('my@email.com');`. You can also switch to the `anon` role using `CALL auth.login_as_anon();`. When you are done, use `CALL auth.logout();` which will return yourself to the powerful `postgres` role. +To switch to a given user (by email), use `CALL auth.login_as_user('my@email.com');`. You can also switch to the `anon` role using `CALL auth.login_as_anon();`. When you are done, use `CALL auth.logout();` to return yourself to the `postgres` role. -These procedures are also very handy for writing [pgTAP](/docs/guides/database/extensions/pgtap) unit-tests for policies. +These procedures can also be used for writing [pgTAP](/docs/guides/database/extensions/pgtap) unit tests for policies. ## Deprecated features From 99a9edf28cdb9d55b6bc2fef0ddea8c1ecc7864c Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Sun, 5 Feb 2023 17:50:56 -0330 Subject: [PATCH 006/289] Mock autodocs into table editor --- studio/components/grid/types/grid.ts | 5 + .../TableGridEditor/GridHeaderActions.tsx | 20 +++- .../TableGridEditor/TableGridEditor.tsx | 103 +++++++++++++++++- 3 files changed, 125 insertions(+), 3 deletions(-) diff --git a/studio/components/grid/types/grid.ts b/studio/components/grid/types/grid.ts index e05352cfdfc..68c3dc73220 100644 --- a/studio/components/grid/types/grid.ts +++ b/studio/components/grid/types/grid.ts @@ -69,6 +69,11 @@ export interface SupabaseGridProps { * error handler */ onError?: (error: any) => void + /** + * Toggle api preview panel open + */ + apiPreviewPanelOpen?: boolean + setApiPreviewPanelOpen?: () => void } export interface SupabaseGridRef { diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 198e9a2a964..c21c62febe1 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -1,21 +1,37 @@ import { FC } from 'react' import Link from 'next/link' -import { Button, IconAlertCircle, IconLock } from 'ui' +import { Button, IconAlertCircle, IconCode, IconLock } from 'ui' import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' import { useStore } from 'hooks' interface Props { table: PostgresTable + apiPreviewPanelOpen: boolean + setApiPreviewPanelOpen: (apiPreviewPanelOpen: boolean) => void } -const GridHeaderActions: FC = ({ table }) => { +const GridHeaderActions: FC = ({ table, apiPreviewPanelOpen, setApiPreviewPanelOpen }) => { const { ui, meta } = useStore() const projectRef = ui.selectedProject?.ref const policies = meta.policies.list((policy: PostgresPolicy) => policy.table_id === table.id) + const RenderAPIPreviewToggle = () => { + return ( + + ) + } + return (
+ + + {disabled && ( + + +
+ + You need additional permissions to update network restrictions + +
+
+ )} + +) + +const DisallowAllAccessButton: FC<{ disabled: boolean; onClick: (value: boolean) => void }> = ({ + disabled, + onClick, +}) => ( + + + + + {disabled && ( + + +
+ + You need additional permissions to update network restrictions + +
+
+ )} +
+) + const NetworkRestrictions = ({}) => { const { ref } = useParams() @@ -21,6 +79,8 @@ const NetworkRestrictions = ({}) => { const [selectedRestrictionToRemove, setSelectedRestrictionToRemove] = useState() const { data, isLoading } = useNetworkRestrictionsQuery({ projectRef: ref }) + const canUpdateNetworkRestrictions = checkPermissions(PermissionAction.UPDATE, 'projects') + const hasAccessToRestrictions = data?.entitlement === 'allowed' const restrictedIps = data?.config.dbAllowedCidrs ?? [] const restrictionStatus = data?.status ?? '' @@ -48,7 +108,31 @@ const NetworkRestrictions = ({}) => {
- + + + + + {!canUpdateNetworkRestrictions && ( + + +
+ + You need additional permissions to update network restrictions + +
+
+ )} +
{isLoading ? ( @@ -75,12 +159,14 @@ const NetworkRestrictions = ({}) => {

- - + +
@@ -101,9 +187,10 @@ const NetworkRestrictions = ({}) => {
- +
) : isDisallowedAll ? ( @@ -125,9 +212,10 @@ const NetworkRestrictions = ({}) => {
- +
) : ( @@ -146,12 +234,14 @@ const NetworkRestrictions = ({}) => {

- - + +
{restrictedIps.map((ip) => { diff --git a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx index d1709896cf1..989df6e60fe 100644 --- a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx +++ b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx @@ -1,8 +1,10 @@ import Link from 'next/link' import { useState, useEffect } from 'react' -import { useParams, useStore } from 'hooks' +import { checkPermissions, useParams, useStore } from 'hooks' import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconDownload, Toggle, IconExternalLink, IconLoader, Alert } from 'ui' +import { PermissionAction } from '@supabase/shared-types/out/constants' + import { FormHeader, FormPanel, @@ -25,6 +27,8 @@ const SSLConfiguration = () => { }) const { mutateAsync: updateSSLEnforcement } = useSSLEnforcementUpdateMutation() + const canUpdateSSLEnforcement = checkPermissions(PermissionAction.UPDATE, 'projects') + const hasAccessToSSLEnforcement = !sslEnforcementConfiguration?.isNotAllowed const env = process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' ? 'prod' : 'staging' const hasSSLCertificate = @@ -115,11 +119,30 @@ const SSLConfiguration = () => { {(isLoading || isSubmitting) && ( )} - + + + + + {!canUpdateSSLEnforcement && ( + + +
+ + You need additional permissions to update SSL configurations + +
+
+ )} +
diff --git a/studio/components/interfaces/Settings/ProjectUsageBars/ProjectUsageBars.tsx b/studio/components/interfaces/Settings/ProjectUsageBars/ProjectUsageBars.tsx index ede0524c0a3..cfe5c5ac2e2 100644 --- a/studio/components/interfaces/Settings/ProjectUsageBars/ProjectUsageBars.tsx +++ b/studio/components/interfaces/Settings/ProjectUsageBars/ProjectUsageBars.tsx @@ -1,7 +1,10 @@ import { FC, useEffect } from 'react' +import { useRouter } from 'next/router' import { Badge, Button, IconAlertCircle, IconInfo, Loading } from 'ui' +import * as Tooltip from '@radix-ui/react-tooltip' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' import { formatBytes } from 'lib/helpers' import { PRICING_TIER_PRODUCT_IDS, USAGE_APPROACHING_THRESHOLD } from 'lib/constants' import SparkBar from 'components/ui/SparkBar' @@ -9,8 +12,6 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import InformationBox from 'components/ui/InformationBox' import { USAGE_BASED_PRODUCTS } from 'components/interfaces/Billing/Billing.constants' import { ProjectUsageResponse, useProjectUsageQuery } from 'data/usage/project-usage-query' -import { useRouter } from 'next/router' -import * as Tooltip from '@radix-ui/react-tooltip' interface Props { projectRef?: string @@ -21,6 +22,11 @@ const ProjectUsage: FC = ({ projectRef }) => { const { data: usage, error, isLoading } = useProjectUsageQuery({ projectRef }) const router = useRouter() + const canUpdateSubscription = checkPermissions( + PermissionAction.BILLING_WRITE, + 'stripe.subscriptions' + ) + const subscriptionTier = ui.selectedProject?.subscription_tier const projectHasNoLimits = @@ -128,14 +134,16 @@ const ProjectUsage: FC = ({ projectRef }) => { usageElement = (
Not included in {planName} tier - + {canUpdateSubscription && ( + + )}
) } else if (showUsageExceedMessage) { diff --git a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx index 4e05953129a..65662c22665 100644 --- a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx @@ -1,12 +1,14 @@ import { useState } from 'react' +import * as Tooltip from '@radix-ui/react-tooltip' import { Button, Form, IconClock, Input, Listbox } from 'ui' -import { useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' import { useProjectStorageConfigQuery } from 'data/config/project-storage-config-query' import { useProjectStorageConfigUpdateUpdateMutation } from 'data/config/project-storage-config-update-mutation' import UpgradeToPro from 'components/ui/UpgradeToPro' import { convertFromBytes, convertToBytes } from './StorageSettings.utils' import { StorageSizeUnits, STORAGE_FILE_SIZE_LIMIT_MAX_BYTES } from './StorageSettings.constants' +import { PermissionAction } from '@supabase/shared-types/out/constants' export type StorageSettingsProps = { projectRef: string | undefined @@ -42,6 +44,8 @@ const StorageConfig = ({ config, projectRef }: any) => { const [selectedUnit, setSelectedUnit] = useState(unit) let initialValues = { fileSizeLimit: value, unformattedFileSizeLimit: fileSizeLimit } + const canUpdateStorageSettings = checkPermissions(PermissionAction.UPDATE, 'projects') + const formattedMaxSizeBytes = `${new Intl.NumberFormat('en-US').format( STORAGE_FILE_SIZE_LIMIT_MAX_BYTES )} bytes` @@ -184,13 +188,20 @@ const StorageConfig = ({ config, projectRef }: any) => { icon={} primaryText="Free Plan has a fixed upload file size limit of 50 MB." projectRef={projectRef} - secondaryText="Please upgrade to Pro plan for a configurable upload file size limit of up to 5 GB." + secondaryText="Upgrade to the Pro plan for a configurable upload file size limit of up to 5 GB." /> )}
-
+
+ {!canUpdateStorageSettings ? ( +

+ You need additional permissions to update storage settings +

+ ) : ( +
+ )}
diff --git a/studio/components/to-be-cleaned/forms/SchemaForm.js b/studio/components/to-be-cleaned/forms/SchemaForm.js index bc5e6ac20a0..fa65c7b1560 100644 --- a/studio/components/to-be-cleaned/forms/SchemaForm.js +++ b/studio/components/to-be-cleaned/forms/SchemaForm.js @@ -2,10 +2,19 @@ import { AutoForm } from 'uniforms-bootstrap4' import Ajv from 'ajv' import { JSONSchemaBridge } from 'uniforms-bridge-json-schema' -const SchemaForm = ({ schema, model, children, formRef, onSubmit, onChangeModel = () => {} }) => { +const SchemaForm = ({ + schema, + model, + disabled = false, + children, + formRef, + onSubmit, + onChangeModel = () => {}, +}) => { const validatedSchema = new JSONSchemaBridge(schema, createValidator(schema)) return (
{title || ''}
-
- - -
+ + +
+ )} {message}
{ setHasChanged(true) if (onChangeModel) onChangeModel(model) diff --git a/studio/components/ui/UpgradeToPro.tsx b/studio/components/ui/UpgradeToPro.tsx index ca7b1b549b6..ccee10b1295 100644 --- a/studio/components/ui/UpgradeToPro.tsx +++ b/studio/components/ui/UpgradeToPro.tsx @@ -2,8 +2,11 @@ import { Button } from 'ui' import { observer } from 'mobx-react-lite' import Link from 'next/link' import { FC, ReactNode } from 'react' -import { useStore } from 'hooks' +import * as Tooltip from '@radix-ui/react-tooltip' + +import { checkPermissions, useStore, useFlag, useParams } from 'hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' +import { PermissionAction } from '@supabase/shared-types/out/constants' interface Props { icon?: ReactNode @@ -14,8 +17,16 @@ interface Props { const UpgradeToPro: FC = ({ icon, primaryText, projectRef, secondaryText }) => { const { ui } = useStore() + const { ref } = useParams() const tier = ui.selectedProject?.subscription_tier + const canUpdateSubscription = checkPermissions( + PermissionAction.BILLING_WRITE, + 'stripe.subscriptions' + ) + const projectUpdateDisabled = useFlag('disableProjectCreationAndUpdate') + const isEnterprise = tier === PRICING_TIER_PRODUCT_IDS.ENTERPRISE + return (
= ({ icon, primaryText, projectRef, secondaryText

{secondaryText}

- - - - - + + {!canUpdateSubscription || projectUpdateDisabled ? ( + + +
+ + {projectUpdateDisabled ? ( + <> + Subscription changes are currently disabled. +
+ Our engineers are working on a fix. + + ) : !canUpdateSubscription ? ( + 'You need additional permissions to amend subscriptions' + ) : ( + '' + )} +
+
+
+ ) : ( + <> + )} +
diff --git a/studio/pages/project/[ref]/database/backups/pitr.tsx b/studio/pages/project/[ref]/database/backups/pitr.tsx index 5f3eb4aadad..694e62f97c7 100644 --- a/studio/pages/project/[ref]/database/backups/pitr.tsx +++ b/studio/pages/project/[ref]/database/backups/pitr.tsx @@ -65,7 +65,7 @@ const PITR = () => { primaryText="Point in time recovery is a Pro plan add-on." secondaryText={ tier === PRICING_TIER_PRODUCT_IDS.FREE - ? 'Please upgrade to the Pro plan with the PITR add-on selected to enable point in time recovery for your project.' + ? 'Upgrade to the Pro plan with the PITR add-on selected to enable point in time recovery for your project.' : 'Please enable the add-on to enable point in time recovery for your project.' } /> diff --git a/studio/pages/project/[ref]/settings/billing/subscription.tsx b/studio/pages/project/[ref]/settings/billing/subscription.tsx index 750af452736..a47a62ad90d 100644 --- a/studio/pages/project/[ref]/settings/billing/subscription.tsx +++ b/studio/pages/project/[ref]/settings/billing/subscription.tsx @@ -36,7 +36,6 @@ interface SettingsProps { const Settings: FC = ({ project }) => { const { ui } = useStore() - const projectTier = ui.selectedProject?.subscription_tier const { data: subscription, diff --git a/studio/sentry.client.config.js b/studio/sentry.client.config.js index 456f62c88a0..23e597a09cb 100644 --- a/studio/sentry.client.config.js +++ b/studio/sentry.client.config.js @@ -39,6 +39,9 @@ Sentry.init({ // Safe to ignore since it's not a user-facing issue + we've not received any user feedback/report about it // Ref: https://github.com/supabase/supabase/pull/9729 'The provided `href` (/org/[slug]/general) value is missing query values (slug)', + 'The provided `href` (/org/[slug]/team) value is missing query values (slug)', + 'The provided `href` (/org/[slug]/billing) value is missing query values (slug)', + 'The provided `href` (/org/[slug]/invoices) value is missing query values (slug)', ], beforeSend: (event) => filterConsoleErrors(event), }) From e6bc954a9defb8aa2827d656f6e56d2d26c2a71e Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Thu, 9 Feb 2023 09:53:28 -0330 Subject: [PATCH 008/289] Format api sections --- packages/ui/index.tsx | 1 + packages/ui/internals/icons.js | 5 ++- packages/ui/internals/icons.json | 4 ++ .../src/components/Icon/IconImportHandler.tsx | 1 + .../ui/src/components/Icon/icons/index.tsx | 1 + .../interfaces/Docs/ResourceContent.tsx | 40 ++++++++++++------- .../to-be-cleaned/Docs/Pages/Introduction.js | 2 +- studio/components/to-be-cleaned/Docs/Param.js | 35 ---------------- studio/styles/ui.scss | 10 ++++- 9 files changed, 44 insertions(+), 55 deletions(-) delete mode 100644 studio/components/to-be-cleaned/Docs/Param.js diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx index 772f434d345..3edb9ec62c3 100644 --- a/packages/ui/index.tsx +++ b/packages/ui/index.tsx @@ -305,6 +305,7 @@ export * from './src/components/Icon/icons/IconSun' export * from './src/components/Icon/icons/IconSunrise' export * from './src/components/Icon/icons/IconSunset' export * from './src/components/Icon/icons/IconTablet' +export * from './src/components/Icon/icons/IconTable' export * from './src/components/Icon/icons/IconTag' export * from './src/components/Icon/icons/IconTarget' export * from './src/components/Icon/icons/IconTerminal' diff --git a/packages/ui/internals/icons.js b/packages/ui/internals/icons.js index 07a7f0e5539..1cde50bfbd9 100644 --- a/packages/ui/internals/icons.js +++ b/packages/ui/internals/icons.js @@ -234,6 +234,7 @@ export default { IconSunrise: 'src/components/Icon/icons/IconSunrise/index.tsx', IconSunset: 'src/components/Icon/icons/IconSunset/index.tsx', IconTablet: 'src/components/Icon/icons/IconTablet/index.tsx', + IconTable: 'src/components/Icon/icons/IconTable/index.tsx', IconTag: 'src/components/Icon/icons/IconTag/index.tsx', IconTarget: 'src/components/Icon/icons/IconTarget/index.tsx', IconTerminal: 'src/components/Icon/icons/IconTerminal/index.tsx', @@ -284,5 +285,5 @@ export default { IconZapOff: 'src/components/Icon/icons/IconZapOff/index.tsx', IconZap: 'src/components/Icon/icons/IconZap/index.tsx', IconZoomIn: 'src/components/Icon/icons/IconZoomIn/index.tsx', - IconZoomOut: 'src/components/Icon/icons/IconZoomOut/index.tsx' -} \ No newline at end of file + IconZoomOut: 'src/components/Icon/icons/IconZoomOut/index.tsx', +} diff --git a/packages/ui/internals/icons.json b/packages/ui/internals/icons.json index 992be561d20..a348ede4cf5 100644 --- a/packages/ui/internals/icons.json +++ b/packages/ui/internals/icons.json @@ -939,6 +939,10 @@ "name": "Tablet", "path": "react-feather/dist/icons/tablet" }, + "Table": { + "name": "Table", + "path": "react-feather/dist/icons/table" + }, "Tag": { "name": "Tag", "path": "react-feather/dist/icons/tag" diff --git a/packages/ui/src/components/Icon/IconImportHandler.tsx b/packages/ui/src/components/Icon/IconImportHandler.tsx index 0d158b428c6..3863d419700 100644 --- a/packages/ui/src/components/Icon/IconImportHandler.tsx +++ b/packages/ui/src/components/Icon/IconImportHandler.tsx @@ -241,6 +241,7 @@ export const Sun: Icon = require(`react-feather/dist/icons/sun`) export const Sunrise: Icon = require(`react-feather/dist/icons/sunrise`) export const Sunset: Icon = require(`react-feather/dist/icons/sunset`) export const Tablet: Icon = require(`react-feather/dist/icons/tablet`) +export const Table: Icon = require(`react-feather/dist/icons/table`) export const Tag: Icon = require(`react-feather/dist/icons/tag`) export const Target: Icon = require(`react-feather/dist/icons/target`) export const Terminal: Icon = require(`react-feather/dist/icons/terminal`) diff --git a/packages/ui/src/components/Icon/icons/index.tsx b/packages/ui/src/components/Icon/icons/index.tsx index 9fc2134a5a7..5975707ac72 100644 --- a/packages/ui/src/components/Icon/icons/index.tsx +++ b/packages/ui/src/components/Icon/icons/index.tsx @@ -234,6 +234,7 @@ export * as IconSun from './IconSun' export * as IconSunrise from './IconSunrise' export * as IconSunset from './IconSunset' export * as IconTablet from './IconTablet' +export * as IconTable from './IconTable' export * as IconTag from './IconTag' export * as IconTarget from './IconTarget' export * as IconTerminal from './IconTerminal' diff --git a/studio/components/interfaces/Docs/ResourceContent.tsx b/studio/components/interfaces/Docs/ResourceContent.tsx index a37ed884081..784b5018793 100644 --- a/studio/components/interfaces/Docs/ResourceContent.tsx +++ b/studio/components/interfaces/Docs/ResourceContent.tsx @@ -2,6 +2,7 @@ import Snippets from 'components/to-be-cleaned/Docs/Snippets' import CodeSnippet from 'components/to-be-cleaned/Docs/CodeSnippet' import Param from 'components/to-be-cleaned/Docs/Param' import Description from 'components/to-be-cleaned/Docs/Description' +import { IconTable } from 'ui' const ResourceContent = ({ autoApiService, @@ -29,12 +30,18 @@ const ResourceContent = ({ return ( <> -

- {resourceId} +

+ + + + {resourceId}

- @@ -147,8 +157,8 @@ const ResourceContent = ({ insert will also return the replaced values for UPSERT.

- - Learn more. + + Learn more

@@ -183,8 +193,8 @@ const ResourceContent = ({ update will also return the replaced values for UPDATE.

- - Learn more. + + Learn more

@@ -207,8 +217,8 @@ const ResourceContent = ({ default, so remember to specify your filters!

- - Learn more. + + Learn more

@@ -230,8 +240,8 @@ const ResourceContent = ({ users depending on Row Level Security (RLS) policies.

- - Learn more. + + Learn more

diff --git a/studio/components/to-be-cleaned/Docs/Pages/Introduction.js b/studio/components/to-be-cleaned/Docs/Pages/Introduction.js index 30e24301034..ed3e73462c0 100644 --- a/studio/components/to-be-cleaned/Docs/Pages/Introduction.js +++ b/studio/components/to-be-cleaned/Docs/Pages/Introduction.js @@ -5,7 +5,7 @@ export default function Introduction({ autoApiService, selectedLang }) { return ( <>

Introduction

-
+

This API provides an easy way to integrate with your Postgres database. The API diff --git a/studio/components/to-be-cleaned/Docs/Param.js b/studio/components/to-be-cleaned/Docs/Param.js deleted file mode 100644 index 9abb36712f8..00000000000 --- a/studio/components/to-be-cleaned/Docs/Param.js +++ /dev/null @@ -1,35 +0,0 @@ -import { Badge } from 'ui' -import Description from './Description' - -const Param = ({ - name, - type, - format, - required, - description, - metadata = {}, - onDesciptionUpdated = () => {}, -}) => { - return ( - <> -

- {name} - {required ? 'Required' : 'Optional'} -
- {format && format != type && ( -
- - {format} - {type} -
- )} - {description !== false && ( - <> - - - - )} - - ) -} -export default Param diff --git a/studio/styles/ui.scss b/studio/styles/ui.scss index 16a1284fc6b..d4515a3f090 100644 --- a/studio/styles/ui.scss +++ b/studio/styles/ui.scss @@ -224,6 +224,12 @@ @apply border-b flex border-scale-500; } + .doc-section--introduction { + .text { + width: 85%; + } + } + .doc-section article:first-child { @apply prose prose-docs prose-sm max-w-none; } @@ -239,7 +245,7 @@ a { @apply transition; } - + a:hover { @apply text-brand-1000; } @@ -333,4 +339,4 @@ .pitr-listbox { @apply md:gap-x-2; -} \ No newline at end of file +} From 2e90f996570e07c90ccd2c35eefd0b3760544c29 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Thu, 9 Feb 2023 09:53:40 -0330 Subject: [PATCH 009/289] Add table icon --- .../components/Icon/icons/IconTable/IconTable.tsx | 13 +++++++++++++ .../src/components/Icon/icons/IconTable/index.tsx | 1 + 2 files changed, 14 insertions(+) create mode 100644 packages/ui/src/components/Icon/icons/IconTable/IconTable.tsx create mode 100644 packages/ui/src/components/Icon/icons/IconTable/index.tsx diff --git a/packages/ui/src/components/Icon/icons/IconTable/IconTable.tsx b/packages/ui/src/components/Icon/icons/IconTable/IconTable.tsx new file mode 100644 index 00000000000..c0e41b29099 --- /dev/null +++ b/packages/ui/src/components/Icon/icons/IconTable/IconTable.tsx @@ -0,0 +1,13 @@ +// DO NOT EDIT + // this file is generated by /internals/populate-icons script + import * as React from 'react' + // @ts-ignore + import { Table } from 'react-feather' + import IconBase from './../../IconBase' + + function IconTable(props: any) { + return + } + + export default IconTable + \ No newline at end of file diff --git a/packages/ui/src/components/Icon/icons/IconTable/index.tsx b/packages/ui/src/components/Icon/icons/IconTable/index.tsx new file mode 100644 index 00000000000..906c04de230 --- /dev/null +++ b/packages/ui/src/components/Icon/icons/IconTable/index.tsx @@ -0,0 +1 @@ +export { default as IconTable } from './IconTable' \ No newline at end of file From 3aab5590ccf3a6bd9dcf061ff35084ff4a1c1c84 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Thu, 9 Feb 2023 10:04:24 -0330 Subject: [PATCH 010/289] Add param file --- .../components/to-be-cleaned/Docs/Param.tsx | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 studio/components/to-be-cleaned/Docs/Param.tsx diff --git a/studio/components/to-be-cleaned/Docs/Param.tsx b/studio/components/to-be-cleaned/Docs/Param.tsx new file mode 100644 index 00000000000..3ff95984a62 --- /dev/null +++ b/studio/components/to-be-cleaned/Docs/Param.tsx @@ -0,0 +1,98 @@ +import { FC } from 'react' +import { Badge, IconCode, IconDatabase } from 'ui' +import Description from './Description' + +interface Props { + name: string + type: string + format: string + required: string + description: boolean + metadata: any + onDesciptionUpdated: () => void +} + +function getColumnType(type: string, format: string) { + // json and jsonb both have type=undefined, so check format instead + if (type === undefined && (format === 'jsonb' || format === 'json')) return 'json' + + switch (type) { + case 'string': + return 'string' + case 'integer': + return 'number' + case 'json': + return 'json' + case 'number': + return 'number' + case 'boolean': + return 'boolean' + default: + return '' + } +} + +const Param: FC = ({ + name, + type, + format, + required, + description, + metadata = {}, + onDesciptionUpdated = () => {}, +}) => { + return ( + <> +
+
+
+ + +
+ {name} +
+
+
+ + {required ? 'Required' : 'Optional'} +
+ {format && ( +
+
+ +
+ + + + {getColumnType(type, format)} + + +
+
+
+ +
+ + + + {format} + + +
+
+
+ )} + {description !== false && ( +
+ + +
+ )} + + ) +} +export default Param From d150f7def7071717d2f611bf754e5a2c4e598e82 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 10 Feb 2023 02:01:32 +0800 Subject: [PATCH 011/289] mid --- .../grid/components/header/Header.tsx | 147 +++++++++--------- .../grid/components/menu/ColumnMenu.tsx | 1 - .../Auth/EmailTemplates/EmailTemplates.tsx | 17 +- .../Functions/FunctionsList/FunctionsList.tsx | 2 + .../interfaces/Database/Tables/ColumnList.tsx | 103 +++++++++--- .../interfaces/Database/Tables/TableList.tsx | 95 ++++++++++- .../TableGridEditor/GridHeaderActions.tsx | 30 +++- .../TableGridEditor/TableGridEditor.tsx | 6 +- .../layouts/StorageLayout/StorageLayout.tsx | 19 +-- .../layouts/StorageLayout/StorageMenu.tsx | 56 +++++-- .../project/[ref]/storage/buckets/index.tsx | 15 +- 11 files changed, 350 insertions(+), 141 deletions(-) diff --git a/studio/components/grid/components/header/Header.tsx b/studio/components/grid/components/header/Header.tsx index d839ced0cfd..1b7c0d8fbce 100644 --- a/studio/components/grid/components/header/Header.tsx +++ b/studio/components/grid/components/header/Header.tsx @@ -1,17 +1,9 @@ -import { FC, useState, ReactNode } from 'react' -import { - Button, - IconDownload, - IconPlus, - IconX, - IconTrash, - Dropdown, - IconColumns, - IconChevronDown, -} from 'ui' import { saveAs } from 'file-saver' +import { FC, useState, ReactNode } from 'react' +import { Button, IconDownload, IconX, IconTrash, Dropdown, IconChevronDown } from 'ui' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' import FilterDropdown from './filter' import SortPopover from './sort' import RefreshButton from './RefreshButton' @@ -80,6 +72,9 @@ const DefaultHeader: FC = ({ }) => { const canAddNew = onAddRow !== undefined || onAddColumn !== undefined + // [Joshen] Using this logic to block both column and row creation/update/delete + const canCreateColumns = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + return (
@@ -91,71 +86,73 @@ const DefaultHeader: FC = ({ <>
- -
-
-
+ {canCreateColumns && ( + +
+
+
+
+ } + > +
+

Insert row

+

Insert a new row into {table.name}

- } - > -
-

Insert row

-

Insert a new row into {table.name}

-
- , - ] - : []), - ...(onAddColumn !== undefined - ? [ - -
-
-
+ , + ] + : []), + ...(onAddColumn !== undefined + ? [ + +
+
+
+
+ } + > +
+

Insert column

+

Insert a new column into {table.name}

- } - > -
-

Insert column

-

Insert a new column into {table.name}

-
- , - ] - : []), - ]} - > - - + , + ] + : []), + ]} + > + + + )}
)} diff --git a/studio/components/grid/components/menu/ColumnMenu.tsx b/studio/components/grid/components/menu/ColumnMenu.tsx index d252aa58289..27d5f59b57a 100644 --- a/studio/components/grid/components/menu/ColumnMenu.tsx +++ b/studio/components/grid/components/menu/ColumnMenu.tsx @@ -10,7 +10,6 @@ import { IconLock, IconUnlock, } from 'ui' -import * as React from 'react' import { useDispatch, useTrackedState } from '../../store' type ColumnMenuProps = { diff --git a/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx b/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx index a982880a845..85462a7e4be 100644 --- a/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx +++ b/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.tsx @@ -8,19 +8,18 @@ import TemplateEditor from './TemplateEditor' const EmailTemplates = observer(() => { return (
-
+ = ({ title="Functions" ctaButtonLabel="Create a new function" onClickCta={() => createFunction()} + disabled={!canCreateFunctions} + disabledMessage="You need additional permissions to create functions" >

diff --git a/studio/components/interfaces/Database/Tables/ColumnList.tsx b/studio/components/interfaces/Database/Tables/ColumnList.tsx index c5b668777fc..e53ed442863 100644 --- a/studio/components/interfaces/Database/Tables/ColumnList.tsx +++ b/studio/components/interfaces/Database/Tables/ColumnList.tsx @@ -1,11 +1,13 @@ import { FC, useState } from 'react' import { observer } from 'mobx-react-lite' +import * as Tooltip from '@radix-ui/react-tooltip' import { Input, Button, IconSearch, IconPlus, IconChevronLeft, IconEdit3, IconTrash } from 'ui' +import type { PostgresTable } from '@supabase/postgres-meta' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore } from 'hooks' +import { useStore, checkPermissions } from 'hooks' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' -import type { PostgresTable } from '@supabase/postgres-meta' interface Props { selectedTable: PostgresTable @@ -30,6 +32,7 @@ const ColumnList: FC = ({ : selectedTable.columns?.filter((column: any) => column.name.includes(filterString))) ?? [] const isLocked = meta.excludedSchemas.includes(selectedTable.schema ?? '') + const canUpdateColumns = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') return ( <> @@ -58,9 +61,32 @@ const ColumnList: FC = ({

{!isLocked && (
- + + + + + {!canUpdateColumns && ( + + +
+ + You need additional permissions to create columns + +
+
+ )} +
)}
@@ -103,20 +129,59 @@ const ColumnList: FC = ({
-
diff --git a/studio/components/interfaces/Database/Tables/TableList.tsx b/studio/components/interfaces/Database/Tables/TableList.tsx index de856582937..b058f9ce6f4 100644 --- a/studio/components/interfaces/Database/Tables/TableList.tsx +++ b/studio/components/interfaces/Database/Tables/TableList.tsx @@ -12,10 +12,11 @@ import { IconLock, IconCheck, } from 'ui' - import { partition } from 'lodash' +import * as Tooltip from '@radix-ui/react-tooltip' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore } from 'hooks' +import { useStore, checkPermissions } from 'hooks' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import type { PostgresTable, PostgresSchema } from '@supabase/postgres-meta' @@ -38,8 +39,8 @@ const TableList: FC = ({ onOpenTable = () => {}, }) => { const { meta } = useStore() - const [filterString, setFilterString] = useState('') + const canUpdateTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const schemas: PostgresSchema[] = meta.schemas.list() const [protectedSchemas, openSchemas] = partition(schemas, (schema) => @@ -120,9 +121,32 @@ const TableList: FC = ({
{!isLocked && (
- + + + + + {!canUpdateTables && ( + + +
+ + You need additional permissions to create tables + +
+
+ )} +
)}
@@ -183,7 +207,62 @@ const TableList: FC = ({ > {x.columns.length} columns -
diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index 198e9a2a964..2a8a757aaa5 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -1,9 +1,11 @@ import { FC } from 'react' import Link from 'next/link' +import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconAlertCircle, IconLock } from 'ui' import type { PostgresPolicy, PostgresTable } from '@supabase/postgres-meta' -import { useStore } from 'hooks' +import { useStore, checkPermissions } from 'hooks' +import { PermissionAction } from '@supabase/shared-types/out/constants' interface Props { table: PostgresTable @@ -14,8 +16,34 @@ const GridHeaderActions: FC = ({ table }) => { const projectRef = ui.selectedProject?.ref const policies = meta.policies.list((policy: PostgresPolicy) => policy.table_id === table.id) + const isReadOnly = + !checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') && + !checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + return (
+ {isReadOnly && ( + + +
+ Viewing as read-only +
+
+ + +
+ + You need additional permissions to manage your project's data + +
+
+
+ )}
- } - style={{ justifyContent: 'start' }} - onClick={openCreateBucketModal} - > - New bucket - + + +
+ } + disabled={!canAccessStorage} + style={{ justifyContent: 'start' }} + onClick={openCreateBucketModal} + > + New bucket + + + {!canAccessStorage && ( + + +
+ + You need additional permissions to create buckets + +
+
+ )} +
diff --git a/studio/pages/project/[ref]/storage/buckets/index.tsx b/studio/pages/project/[ref]/storage/buckets/index.tsx index 80ca79f9f03..396a914ba2a 100644 --- a/studio/pages/project/[ref]/storage/buckets/index.tsx +++ b/studio/pages/project/[ref]/storage/buckets/index.tsx @@ -3,21 +3,21 @@ import { useRouter } from 'next/router' import { observer } from 'mobx-react-lite' import { API_URL } from 'lib/constants' -import { useFlag, useStore } from 'hooks' +import { useFlag, useParams, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { PROJECT_STATUS } from 'lib/constants' import { StorageLayout } from 'components/layouts' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { NextPageWithLayout } from 'types' +import { useProjectApiQuery } from 'data/config/project-api-query' +import { find } from 'lodash' /** * PageLayout is used to setup layout - as usual it will requires inject global store */ const PageLayout: NextPageWithLayout = ({}) => { - const router = useRouter() - const { ref } = router.query - + const { ref } = useParams() const { ui } = useStore() const project = ui.selectedProject @@ -26,6 +26,11 @@ const PageLayout: NextPageWithLayout = ({}) => { const kpsEnabled = useFlag('initWithKps') + const { data: settings, isLoading } = useProjectApiQuery({ projectRef: ref }) + const apiService = settings?.autoApiService + const serviceKey = find(apiService?.service_api_keys ?? [], (key) => key.tags === 'service_role') + const canAccessStorage = !isLoading && apiService && serviceKey !== undefined + useEffect(() => { if (project && project.status === PROJECT_STATUS.INACTIVE) { post(`${API_URL}/projects/${ref}/restore`, { kps_enabled: kpsEnabled }) @@ -42,6 +47,8 @@ const PageLayout: NextPageWithLayout = ({}) => { infoButtonLabel="About storage" infoButtonUrl="https://supabase.com/docs/guides/storage" onClickCta={openCreateBucketModal} + disabled={!canAccessStorage} + disabledMessage="You need additional permissions to create buckets" >

Create buckets to store and serve any type of digital content. From 393955b5d00f382f7049f57da1050f0b15dcbaf1 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Thu, 9 Feb 2023 15:24:22 -0330 Subject: [PATCH 012/289] Extract language picker --- .../components/interfaces/Docs/Docs.types.ts | 4 + .../interfaces/Docs/ResourceContent.tsx | 10 +- .../TableGridEditor/TableGridEditor.tsx | 30 ++++- .../to-be-cleaned/Docs/CodeSnippet.js | 1 + .../to-be-cleaned/Docs/LangSelector.tsx | 110 ++++++++++++++++++ .../components/to-be-cleaned/Docs/Param.tsx | 2 +- studio/pages/project/[ref]/api/index.tsx | 15 ++- studio/styles/ui.scss | 4 + 8 files changed, 163 insertions(+), 13 deletions(-) create mode 100644 studio/components/interfaces/Docs/Docs.types.ts create mode 100644 studio/components/to-be-cleaned/Docs/LangSelector.tsx diff --git a/studio/components/interfaces/Docs/Docs.types.ts b/studio/components/interfaces/Docs/Docs.types.ts new file mode 100644 index 00000000000..e6f3e8cb322 --- /dev/null +++ b/studio/components/interfaces/Docs/Docs.types.ts @@ -0,0 +1,4 @@ +export type showApiKey = { + key: string + name: string +} \ No newline at end of file diff --git a/studio/components/interfaces/Docs/ResourceContent.tsx b/studio/components/interfaces/Docs/ResourceContent.tsx index 784b5018793..df8634208be 100644 --- a/studio/components/interfaces/Docs/ResourceContent.tsx +++ b/studio/components/interfaces/Docs/ResourceContent.tsx @@ -30,7 +30,7 @@ const ResourceContent = ({ return ( <> -

+

@@ -54,7 +54,7 @@ const ResourceContent = ({
{properties.map((x) => (
-
+
-
-
+
+
-

+
))}
diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 1512a0446ae..b58d6f3375f 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -11,13 +11,14 @@ import GridHeaderActions from './GridHeaderActions' import NotFoundState from './NotFoundState' import SidePanelEditor from './SidePanelEditor' import { Dictionary, parseSupaTable, SupabaseGrid, SupabaseGridRef } from 'components/grid' -import { SidePanel } from 'ui' +import { IconBookOpen, SidePanel } from 'ui' import ActionBar from './SidePanelEditor/ActionBar' import { GeneralContent, ResourceContent } from '../Docs' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { snakeToCamel } from 'lib/helpers' import useSWR from 'swr' import { get } from 'lib/common/fetch' +import LangSelector from 'components/to-be-cleaned/Docs/LangSelector' interface Props { /** Theme for the editor */ @@ -78,9 +79,14 @@ const TableGridEditor: FC = ({ settings?.autoApiService.endpoint ?? '-' }`, } - const [selectedLang, setSelectedLang] = useState('js') + const DEFAULT_KEY = { name: 'hide', key: 'SUPABASE_KEY' } + const [encryptedColumns, setEncryptedColumns] = useState([]) const [apiPreviewPanelOpen, setApiPreviewPanelOpen] = useState(false) + + const [selectedLang, setSelectedLang] = useState('js') + const [showApiKey, setShowApiKey] = useState(DEFAULT_KEY) + const isVaultEnabled = useFlag('vaultExtension') const getEncryptedColumns = async (table: any) => { @@ -263,7 +269,12 @@ const TableGridEditor: FC = ({ size="xlarge" visible={apiPreviewPanelOpen} onCancel={() => console.log('cancel')} - header={Connect to your table} + header={ + + + API + + } customFooter={ = ({ /> } > -
+
+
+ +
+ {jsonSchema?.definitions && ( { + console.log(snippet, 'snippet') if (!snippet[selectedLang]) return null return ( <> diff --git a/studio/components/to-be-cleaned/Docs/LangSelector.tsx b/studio/components/to-be-cleaned/Docs/LangSelector.tsx new file mode 100644 index 00000000000..2386ff91d3d --- /dev/null +++ b/studio/components/to-be-cleaned/Docs/LangSelector.tsx @@ -0,0 +1,110 @@ +import { FC } from 'react' +import { Button, Dropdown, IconKey } from 'ui' +import { checkPermissions } from 'hooks' +import { PermissionAction } from '@supabase/shared-types/out/constants' + +import { showApiKey } from 'components/interfaces/Docs/docs.types' + +const DEFAULT_KEY = { name: 'hide', key: 'SUPABASE_KEY' } + +interface Props { + selectedLang: string + setSelectedLang: (selectedLang: string) => void + showApiKey: showApiKey + setShowApiKey: (showApiKey: showApiKey) => void + apiKey: string | undefined + autoApiService: any +} + +const LangSelector: FC = ({ + selectedLang, + setSelectedLang, + showApiKey, + setShowApiKey, + apiKey, + autoApiService, +}) => { + const canReadServiceKey = checkPermissions( + PermissionAction.READ, + 'service_api_keys.service_role_key' + ) + + return ( +
+
+ + + {selectedLang == 'bash' && ( +
+
+ + Project API key : +
+ + setShowApiKey(DEFAULT_KEY)}> + hide + + {apiKey && ( + + setShowApiKey({ + key: apiKey, + name: 'anon (public)', + }) + } + > + anon (public) + + )} + {canReadServiceKey && ( + + setShowApiKey({ + key: autoApiService.serviceApiKey, + name: 'service_role (secret)', + }) + } + > + service_role (secret) + + )} + + } + > + + +
+ )} +
+
+ ) +} + +export default LangSelector diff --git a/studio/components/to-be-cleaned/Docs/Param.tsx b/studio/components/to-be-cleaned/Docs/Param.tsx index 3ff95984a62..247cfd9d4c9 100644 --- a/studio/components/to-be-cleaned/Docs/Param.tsx +++ b/studio/components/to-be-cleaned/Docs/Param.tsx @@ -51,7 +51,7 @@ const Param: FC = ({
- {name} + {name}
diff --git a/studio/pages/project/[ref]/api/index.tsx b/studio/pages/project/[ref]/api/index.tsx index 4a793b45190..1ad4f4968f6 100644 --- a/studio/pages/project/[ref]/api/index.tsx +++ b/studio/pages/project/[ref]/api/index.tsx @@ -12,6 +12,7 @@ import { DocsLayout } from 'components/layouts' import { GeneralContent, ResourceContent, RpcContent } from 'components/interfaces/Docs' import { PermissionAction } from '@supabase/shared-types/out/constants' import { useProjectSettingsQuery } from 'data/config/project-settings-query' +import LangSelector from 'components/to-be-cleaned/Docs/LangSelector' const PageContext = createContext(null) @@ -128,10 +129,18 @@ const DocView: FC = observer(({}) => { const PAGE_KEY: any = resource || rpc || page || 'index' return ( -
+
-
+ + {/*
)}
-
+
*/}
{resource ? ( diff --git a/studio/styles/ui.scss b/studio/styles/ui.scss index d4515a3f090..2fa8033d916 100644 --- a/studio/styles/ui.scss +++ b/studio/styles/ui.scss @@ -234,6 +234,10 @@ @apply prose prose-docs prose-sm max-w-none; } + &.Docs--table-editor .doc-section__table-name { + @apply mt-12; + } + .text { @apply p-4 px-6 w-1/2; max-width: 50%; From e9dd00e4cee8dfeb6e66a485076dbe172c98c442 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 10 Feb 2023 15:11:40 +0800 Subject: [PATCH 013/289] Add read only locks for storage and vault --- .../Vault/Keys/EncryptionKeysManagement.tsx | 68 +++++++++++++++--- .../Settings/Vault/Secrets/SecretRow.tsx | 69 ++++++++++++++++--- .../Vault/Secrets/SecretsManagement.tsx | 35 ++++++++-- .../layouts/StorageLayout/StorageLayout.tsx | 20 +++--- .../storageExplorer/StorageExplorerStore.js | 1 + 5 files changed, 157 insertions(+), 36 deletions(-) diff --git a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx index 876805da8a1..63cac0d9820 100644 --- a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx @@ -1,6 +1,7 @@ import dayjs from 'dayjs' import Link from 'next/link' import { observer } from 'mobx-react-lite' +import * as Tooltip from '@radix-ui/react-tooltip' import { FC, Fragment, useEffect, useState } from 'react' import { Alert, @@ -11,13 +12,13 @@ import { Modal, Form, IconTrash, - Badge, IconKey, IconLoader, IconX, IconExternalLink, } from 'ui' -import { useParams, useStore } from 'hooks' +import { PermissionAction } from '@supabase/shared-types/out/constants' +import { useParams, useStore, checkPermissions } from 'hooks' import Divider from 'components/ui/Divider' const DEFAULT_KEY_NAME = 'No description provided' @@ -34,6 +35,8 @@ const EncryptionKeysManagement: FC = ({}) => { const [selectedKeyToRemove, setSelectedKeyToRemove] = useState() const [isDeletingKey, setIsDeletingKey] = useState(false) + const canManageKeys = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + useEffect(() => { if (id !== undefined) setSearchValue(id) }, [id]) @@ -143,9 +146,32 @@ const EncryptionKeysManagement: FC = ({}) => { - + + + + + {!canManageKeys && ( + + +
+ + You need additional permissions to add keys + +
+
+ )} +
@@ -178,12 +204,32 @@ const EncryptionKeysManagement: FC = ({}) => {

Added on {dayjs(key.created).format('MMM D, YYYY')}

-
{idx !== keys.length - 1 && } diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx index 412435028c3..c3c08a02e92 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx @@ -1,3 +1,4 @@ +import Link from 'next/link' import dayjs from 'dayjs' import { FC, useState } from 'react' import { @@ -12,9 +13,10 @@ import { IconMoreVertical, IconLoader, } from 'ui' +import * as Tooltip from '@radix-ui/react-tooltip' +import { PermissionAction } from '@supabase/shared-types/out/constants' import { VaultSecret } from 'types' -import { useParams, useStore } from 'hooks' -import Link from 'next/link' +import { useParams, useStore, checkPermissions } from 'hooks' interface Props { secret: VaultSecret @@ -30,6 +32,8 @@ const SecretRow: FC = ({ secret, onSelectEdit, onSelectRemove }) => { const [revealedValue, setRevealedValue] = useState() const name = secret?.name ?? 'No name provided' + const canManageSecrets = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const revealSecret = async () => { setIsLoading(true) if (revealedValue === undefined) { @@ -106,15 +110,58 @@ const SecretRow: FC = ({ secret, onSelectEdit, onSelectRemove }) => { className="w-[120px]" overlay={ <> - } onClick={() => onSelectEdit(secret)}> - Edit - - } - onClick={() => onSelectRemove(secret)} - > - Delete - + + + } + disabled={!canManageSecrets} + onClick={() => onSelectEdit(secret)} + > + Edit + + + {!canManageSecrets && ( + + +
+ + You need additional permissions to edit secrets + +
+
+ )} +
+ + + } + onClick={() => onSelectRemove(secret)} + > + Delete + + + {!canManageSecrets && ( + + +
+ + You need additional permissions to delete secrets + +
+
+ )} +
} > diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx index 468773ef358..05ca9c5d11c 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx @@ -1,9 +1,11 @@ import Link from 'next/link' import { observer } from 'mobx-react-lite' +import * as Tooltip from '@radix-ui/react-tooltip' import { FC, Fragment, useState, useEffect } from 'react' import { IconSearch, Input, Button, Listbox, IconLoader, IconExternalLink, IconX } from 'ui' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, useParams } from 'hooks' +import { useStore, useParams, checkPermissions } from 'hooks' import SecretRow from './SecretRow' import EditSecretModal from './EditSecretModal' import DeleteSecretModal from './DeleteSecretModal' @@ -22,6 +24,8 @@ const SecretsManagement: FC = ({}) => { const [selectedSecretToEdit, setSelectedSecretToEdit] = useState() const [selectedSecretToRemove, setSelectedSecretToRemove] = useState() + const canManageSecrets = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + useEffect(() => { if (search !== undefined) setSearchValue(search) }, [search]) @@ -105,9 +109,32 @@ const SecretsManagement: FC = ({}) => { - + + + + + {!canManageSecrets && ( + + +
+ + You need additional permissions to add secrets + +
+
+ )} +
diff --git a/studio/components/layouts/StorageLayout/StorageLayout.tsx b/studio/components/layouts/StorageLayout/StorageLayout.tsx index 1a12f2e8c24..53432b6461c 100644 --- a/studio/components/layouts/StorageLayout/StorageLayout.tsx +++ b/studio/components/layouts/StorageLayout/StorageLayout.tsx @@ -40,6 +40,7 @@ const StorageLayout: FC = ({ title, children }) => { buckets, } = storageExplorerStore || {} + // [Joshen] At the moment, without the service key, we won't be able to pull any data from storage const { data: settings, isLoading } = useProjectApiQuery({ projectRef }) const apiService = settings?.autoApiService const serviceKey = find(apiService?.service_api_keys ?? [], (key) => key.tags === 'service_role') @@ -99,16 +100,15 @@ const StorageLayout: FC = ({ title, children }) => { } } - // [Joshen TODO] Revisit this - // if (!isLoading && !canAccessStorage) { - // return ( - // - //
- // - //
- //
- // ) - // } + if (!isLoading && !canAccessStorage) { + return ( + +
+ +
+
+ ) + } return ( }> diff --git a/studio/localStores/storageExplorer/StorageExplorerStore.js b/studio/localStores/storageExplorer/StorageExplorerStore.js index 77d26ceda79..6fee62250c0 100644 --- a/studio/localStores/storageExplorer/StorageExplorerStore.js +++ b/studio/localStores/storageExplorer/StorageExplorerStore.js @@ -44,6 +44,7 @@ const EMPTY_FOLDER_PLACEHOLDER_FILE_NAME = '.emptyFolderPlaceholder' const STORAGE_PROGRESS_INFO_TEXT = "Please do not close the browser until it's completed" class StorageExplorerStore { + isReadOnly = false projectRef = '' loaded = false view = STORAGE_VIEWS.COLUMNS From d2e28ca1667b568893249c5d439c468c422d5444 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 10 Feb 2023 16:12:06 +0800 Subject: [PATCH 014/289] Add read only locks for wrappers --- .../Database/Wrappers/CreateWrapper.tsx | 3 +- .../Database/Wrappers/EditWrapper.tsx | 9 ++- .../Database/Wrappers/WrapperRow.tsx | 78 +++++++++++++++---- .../interfaces/Database/Wrappers/Wrappers.tsx | 2 +- .../Database/Wrappers/WrappersDropdown.tsx | 30 ++++++- .../project/[ref]/database/wrappers/[id].tsx | 1 + .../project/[ref]/database/wrappers/index.tsx | 2 +- .../project/[ref]/database/wrappers/new.tsx | 6 +- 8 files changed, 107 insertions(+), 24 deletions(-) diff --git a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx index dbe8fe10c83..242345a01f7 100644 --- a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx @@ -36,7 +36,7 @@ const CreateWrapper = () => { const [selectedTableToEdit, setSelectedTableToEdit] = useState() const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) - const canCreateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions') + const canCreateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const wrapperMeta = WRAPPERS.find((wrapper) => wrapper.name === type) const initialValues = @@ -164,6 +164,7 @@ const CreateWrapper = () => { isSubmitting={isSubmitting} hasChanges={hasChanges} handleReset={handleReset} + disabled={!canCreateWrapper} helper={ !canCreateWrapper ? 'You need additional permissions to create a foreign data wrapper' diff --git a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx index 2286ec04c7f..fdcec1aa4b8 100644 --- a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx @@ -65,7 +65,7 @@ const EditWrapper = () => { const [selectedTableToEdit, setSelectedTableToEdit] = useState() const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) - const canCreateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions') + const canUpdateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const initialValues = wrapperMeta !== undefined @@ -248,7 +248,7 @@ const EditWrapper = () => { return ( { handleReset() setWrapperTables(initialTables) }} + disabled={!canUpdateWrapper} helper={ - !canCreateWrapper - ? 'You need additional permissions to create a foreign data wrapper' + !canUpdateWrapper + ? 'You need additional permissions to edit a foreign data wrapper' : undefined } /> diff --git a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx index 35b7efbed34..896cd11d45e 100644 --- a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx @@ -1,10 +1,12 @@ import Link from 'next/link' import Image from 'next/image' import { FC } from 'react' -import { Collapsible, IconChevronUp, Button, IconExternalLink, IconTrash, IconEdit } from 'ui' import { partition } from 'lodash' +import * as Tooltip from '@radix-ui/react-tooltip' +import { PermissionAction } from '@supabase/shared-types/out/constants' +import { Collapsible, IconChevronUp, Button, IconExternalLink, IconTrash, IconEdit } from 'ui' -import { useParams, useStore } from 'hooks' +import { useParams, useStore, checkPermissions } from 'hooks' import { WrapperMeta } from './Wrappers.types' import { FDW } from 'data/fdw/fdws-query' import { useFDWDeleteMutation } from 'data/fdw/fdw-delete-mutation' @@ -24,6 +26,8 @@ const WrapperRow: FC = ({ wrappers = [], wrapperMeta, isOpen, onOpen }) = const { project } = useProjectContext() const { mutateAsync: deleteFDW } = useFDWDeleteMutation() + const canManageWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') + const onDeleteWrapper = (wrapper: any) => { confirmAlert({ title: `Confirm to disable ${wrapper.name}`, @@ -156,21 +160,69 @@ const WrapperRow: FC = ({ wrappers = [], wrapperMeta, isOpen, onOpen }) =
- - + {canManageWrappers ? ( + + +
) diff --git a/studio/components/interfaces/Database/Wrappers/Wrappers.tsx b/studio/components/interfaces/Database/Wrappers/Wrappers.tsx index d05146b786d..ad5e35a095f 100644 --- a/studio/components/interfaces/Database/Wrappers/Wrappers.tsx +++ b/studio/components/interfaces/Database/Wrappers/Wrappers.tsx @@ -1,4 +1,5 @@ import Link from 'next/link' +import { groupBy } from 'lodash' import { useState } from 'react' import { Button, IconExternalLink } from 'ui' import { observer } from 'mobx-react-lite' @@ -11,7 +12,6 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader' import WrappersDropdown from './WrappersDropdown' import WrappersDisabledState from './WrappersDisabledState' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { groupBy } from 'lodash' const Wrappers = () => { const { meta } = useStore() diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx index b74c9a9fffb..affb01fb608 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx @@ -3,8 +3,10 @@ import Image from 'next/image' import { FC, Fragment } from 'react' import { observer } from 'mobx-react-lite' import { Button, Dropdown, IconPlus } from 'ui' +import * as Tooltip from '@radix-ui/react-tooltip' +import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useParams } from 'hooks' +import { useParams, checkPermissions } from 'hooks' import { WRAPPERS } from './Wrappers.constants' interface Props { @@ -14,6 +16,32 @@ interface Props { const WrapperDropdown: FC = ({ buttonText = 'Add wrapper', align = 'end' }) => { const { ref } = useParams() + const canManageWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + + if (!canManageWrappers) { + return ( + + + + + + +
+ + You need additional permissions to add wrappers + +
+
+
+ ) + } return ( { const canReadWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'wrappers') + if (!canReadWrappers) { return } diff --git a/studio/pages/project/[ref]/database/wrappers/index.tsx b/studio/pages/project/[ref]/database/wrappers/index.tsx index ead5fba1e25..d8df5feae34 100644 --- a/studio/pages/project/[ref]/database/wrappers/index.tsx +++ b/studio/pages/project/[ref]/database/wrappers/index.tsx @@ -9,7 +9,7 @@ import NoPermission from 'components/ui/NoPermission' import { FormsContainer } from 'components/ui/Forms' const DatabaseWrappers: NextPageWithLayout = () => { - const canReadWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'wrappers') + const canReadWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables') if (!canReadWrappers) { return } diff --git a/studio/pages/project/[ref]/database/wrappers/new.tsx b/studio/pages/project/[ref]/database/wrappers/new.tsx index 4db0245131f..225b4051123 100644 --- a/studio/pages/project/[ref]/database/wrappers/new.tsx +++ b/studio/pages/project/[ref]/database/wrappers/new.tsx @@ -8,9 +8,9 @@ import NoPermission from 'components/ui/NoPermission' import { CreateWrapper } from 'components/interfaces/Database' const DatabaseWrappersNew: NextPageWithLayout = () => { - const canReadWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'wrappers') - if (!canReadWrappers) { - return + const canCreateWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + if (!canCreateWrappers) { + return } return From 1469cb111e7a8fdd1468d88d02a5d16a8206d499 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 10 Feb 2023 16:16:49 +0800 Subject: [PATCH 015/289] read only lock storage settings --- .../to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx index 65662c22665..a604849edf0 100644 --- a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx @@ -142,7 +142,7 @@ const StorageConfig = ({ config, projectRef }: any) => { id="fileSizeLimit" name="fileSizeLimit" type="number" - disabled={isFreeTier} + disabled={isFreeTier || !canUpdateStorageSettings} step={1} onKeyPress={(event) => { if (event.charCode < 48 || event.charCode > 57) { From f5dade6b67dc35adcdb331df153c256de2f9d3d7 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Fri, 10 Feb 2023 17:21:55 +0800 Subject: [PATCH 016/289] read only lock pitr --- .../Database/Backups/PITR/PITRNotice.tsx | 38 +++++++++++++++---- .../Database/Backups/PITR/PITRStatus.tsx | 32 +++++++++++++++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx index cd43b19d452..daab4106406 100644 --- a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx +++ b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx @@ -1,15 +1,22 @@ import Link from 'next/link' import { Button, IconCalendar } from 'ui' import { FormPanel } from 'components/ui/Forms' -import { useParams } from 'hooks' +import * as Tooltip from '@radix-ui/react-tooltip' +import { checkPermissions, useParams } from 'hooks' import { useProjectSubscriptionQuery } from 'data/subscriptions/project-subscription-query' import { getPITRRetentionDuration } from './PITR.utils' +import { PermissionAction } from '@supabase/shared-types/out/constants' const PITRNotice = ({}) => { const { ref: projectRef } = useParams() const { data: subscription } = useProjectSubscriptionQuery({ projectRef }) const retentionPeriod = getPITRRetentionDuration(subscription?.addons ?? []) + const canUpdateSubscription = checkPermissions( + PermissionAction.BILLING_WRITE, + 'stripe.subscriptions' + ) + return ( { You can also increase your recovery retention period updating your PITR add-on - - - - - + + {!canUpdateSubscription && ( + + +
+ + You need additional permissions to amend subscriptions + +
+
+ )} + } > diff --git a/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx b/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx index 4b47575c1d4..b634e1365c7 100644 --- a/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx +++ b/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx @@ -2,11 +2,13 @@ import dayjs from 'dayjs' import { FC } from 'react' import { observer } from 'mobx-react-lite' import { Button, IconAlertCircle } from 'ui' +import * as Tooltip from '@radix-ui/react-tooltip' -import { useStore } from 'hooks' +import { checkPermissions, useStore } from 'hooks' import { Timezone } from './PITR.types' import { FormPanel } from 'components/ui/Forms' import TimezoneSelection from './TimezoneSelection' +import { PermissionAction } from '@supabase/shared-types/out/constants' interface Props { selectedTimezone: Timezone @@ -29,6 +31,11 @@ const PITRStatus: FC = ({ selectedTimezone, onUpdateTimezone, onSetConfig .tz(selectedTimezone?.utc[0]) .format('DD MMM YYYY, HH:mm:ss') + const canTriggerPhysicalBackup = checkPermissions( + PermissionAction.INFRA_EXECUTE, + 'queue_job.walg.prepare_restore' + ) + return ( <> = ({ selectedTimezone, onUpdateTimezone, onSetConfig You'll be able to pick the right date and time when you begin - + + + + + {!canTriggerPhysicalBackup && ( + + +
+ + You need additional permissions to trigger a PITR recovery + +
+
+ )} +
} > From fae9a272759051079f8270921757fe66ba6a0aea Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Fri, 10 Feb 2023 16:42:25 -0330 Subject: [PATCH 017/289] Update --- .../ui/src/components/SidePanel/SidePanel.tsx | 2 +- packages/ui/src/lib/theme/defaultTheme.ts | 327 +++++++++--------- .../TableGridEditor/TableGridEditor.tsx | 8 +- .../to-be-cleaned/Docs/CodeSnippet.js | 5 +- .../to-be-cleaned/Docs/LangSelector.tsx | 2 +- .../components/to-be-cleaned/Docs/Param.tsx | 10 +- studio/styles/ui.scss | 5 +- 7 files changed, 181 insertions(+), 178 deletions(-) diff --git a/packages/ui/src/components/SidePanel/SidePanel.tsx b/packages/ui/src/components/SidePanel/SidePanel.tsx index e105fe85d91..ba0ed494a53 100644 --- a/packages/ui/src/components/SidePanel/SidePanel.tsx +++ b/packages/ui/src/components/SidePanel/SidePanel.tsx @@ -22,7 +22,7 @@ interface CustomProps { children?: React.ReactNode header?: string | React.ReactNode visible: boolean - size?: 'medium' | 'large' | 'xlarge' + size?: 'medium' | 'large' | 'xlarge' | 'xxlarge' loading?: boolean align?: 'right' | 'left' hideFooter?: boolean diff --git a/packages/ui/src/lib/theme/defaultTheme.ts b/packages/ui/src/lib/theme/defaultTheme.ts index 1265d536a10..35de4089bd7 100644 --- a/packages/ui/src/lib/theme/defaultTheme.ts +++ b/packages/ui/src/lib/theme/defaultTheme.ts @@ -117,9 +117,9 @@ export default { flex flex-row gap-3 items-center - w-full - text-left - cursor-pointer + w-full + text-left + cursor-pointer outline-none focus-visible:ring-1 @@ -143,27 +143,27 @@ export default { group border border-scale-700 - + first:rounded-tl-md first:rounded-tr-md last:rounded-bl-md last:rounded-br-md `, trigger: ` flex flex-row items-center - px-6 py-4 - w-full - text-left - cursor-pointer - - font-medium - text-base - bg-transparent + px-6 py-4 + w-full + text-left + cursor-pointer + + font-medium + text-base + bg-transparent outline-none focus-visible:ring-1 focus-visible:z-50 ring-scale-1100 - + transition-colors hover:bg-scale-200 @@ -252,8 +252,8 @@ export default { alert: { base: ` - relative rounded border py-4 px-6 - flex space-x-4 items-start + relative rounded border py-4 px-6 + flex space-x-4 items-start `, header: 'block text-sm font-normal mb-1', description: `text-xs`, @@ -290,11 +290,11 @@ export default { }, }, close: ` - absolute - right-6 top-4 - p-0 m-0 + absolute + right-6 top-4 + p-0 m-0 text-scale-900 - cursor-pointer transition ease-in-out + cursor-pointer transition ease-in-out bg-transparent border-transparent focus:outline-none opacity-50 hover:opacity-100`, }, @@ -306,15 +306,15 @@ export default { card: { base: ` bg-white dark:bg-scaleDark-700 - - border - ${defaults.border.primary} - flex flex-col + border + ${defaults.border.primary} + + flex flex-col rounded-md shadow-lg overflow-hidden relative `, hoverable: 'transition hover:-translate-y-1 hover:shadow-2xl', - head: `px-8 py-6 flex justify-between + head: `px-8 py-6 flex justify-between border-b ${defaults.border.primary} `, content: 'p-8', @@ -328,20 +328,20 @@ export default { base: `w-full justify-between space-y-4`, underlined: { list: ` - flex items-center border-b + flex items-center border-b ${defaults.border.secondary} `, - base: ` - relative - cursor-pointer - text-scale-900 - flex - items-center + base: ` + relative + cursor-pointer + text-scale-900 + flex + items-center space-x-2 - text-center + text-center transition - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -355,18 +355,18 @@ export default { }, pills: { list: 'flex space-x-1', - base: ` - relative - cursor-pointer - flex - items-center + base: ` + relative + cursor-pointer + flex + items-center space-x-2 - text-center + text-center transition shadow-sm rounded - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -378,23 +378,23 @@ export default { active: ` bg-scale-1200 text-scale-200 - border-scale-1200 + border-scale-1200 `, }, 'rounded-pills': { list: 'flex flex-wrap gap-2', - base: ` - relative - cursor-pointer - flex - items-center + base: ` + relative + cursor-pointer + flex + items-center space-x-2 - text-center + text-center transition shadow-sm rounded-full - focus:outline-none - focus-visible:ring + focus:outline-none + focus-visible:ring focus-visible:ring-scale-700 focus-visible:border-scale-900 `, @@ -406,7 +406,7 @@ export default { active: ` bg-scale-1200 text-scale-200 - border-scale-1200 + border-scale-1200 `, }, block: 'w-full flex items-center justify-center', @@ -427,15 +427,15 @@ export default { button: { base: ` - relative - cursor-pointer - inline-flex items-center space-x-2 - text-center + relative + cursor-pointer + inline-flex items-center space-x-2 + text-center font-regular - transition ease-out duration-200 - rounded + transition ease-out duration-200 + rounded ${defaults['focus-visible']} - + `, label: `truncate`, container: 'inline-flex font-medium', @@ -449,7 +449,7 @@ export default { secondary: ` bg-scale-1200 text-scale-100 hover:text-scale-800 - focus-visible:text-scale-600 + focus-visible:text-scale-600 bordershadow-scale-1100 hover:bordershadow-scale-900 @@ -462,7 +462,7 @@ export default { dark:bordershadow-scale-700 hover:dark:bordershadow-scale-800 dark:bg-scale-500 dark:hover:bg-scale-600 focus-visible:outline-brand-600 - + `, alternative: ` text-brand-1100 @@ -473,14 +473,14 @@ export default { focus-visible:outline-brand-600 `, outline: ` - text-scale-1200 - bg-transparent + text-scale-1200 + bg-transparent bordershadow-scale-600 hover:bordershadow-scale-700 dark:bordershadow-scale-800 hover:dark:bordershadow-scale-900 focus-visible:outline-scale-700 `, dashed: ` - text-scale-1200 + text-scale-1200 border border-dashed border-scale-700 hover:border-scale-900 @@ -498,7 +498,7 @@ export default { focus-visible:outline-scale-700 `, text: ` - text-scale-1200 + text-scale-1200 hover:bg-scale-500 shadow-none focus-visible:outline-scale-700 @@ -538,13 +538,13 @@ export default { input: { base: ` - block - box-border - w-full - rounded-md - shadow-sm + block + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -559,7 +559,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -581,13 +581,13 @@ export default { select: { base: ` - block - box-border - w-full - rounded-md - shadow-sm + block + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -605,7 +605,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -628,12 +628,12 @@ export default { inputNumber: { base: ` block - box-border - w-full - rounded-md - shadow-sm + box-border + w-full + rounded-md + shadow-sm transition-all - text-scale-1200 + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -651,7 +651,7 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, @@ -668,9 +668,9 @@ export default { /* * Checkbox * - * + * * This Checkbox requires a plugin in your config: - + ``` // tailwind.config.js module.exports = { @@ -681,17 +681,17 @@ export default { ], } ``` - * - * + * + * */ checkbox: { base: ` - bg-transparent + bg-transparent ${defaults.focus} focus:ring-scale-400 - text-brand-900 - border-scale-700 + text-brand-900 + border-scale-700 shadow-sm rounded cursor-pointer @@ -727,9 +727,9 @@ export default { /* * Radio * - * + * * This Radio requires a plugin in your config: - + ``` // tailwind.config.js module.exports = { @@ -740,8 +740,8 @@ export default { ], } ``` - * - * + * + * */ radio: { @@ -750,7 +750,7 @@ export default { ${defaults.focus} focus:ring-brand-400 border-scale-700 - + text-brand-900 shadow-sm cursor-pointer @@ -797,7 +797,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -816,7 +816,7 @@ export default { transition rounded-md border - shadow-sm + shadow-sm `, size: { tiny: `px-5 py-3`, @@ -833,7 +833,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -849,9 +849,9 @@ export default { }, group: `flex flex-row gap-3`, base: ` - transition + transition border - rounded-lg + rounded-lg grow items-center flex-wrap @@ -888,10 +888,10 @@ export default { }, group: `flex flex-row gap-3`, base: ` - transition - border border-scale-700 hover:border-scale-900 + transition + border border-scale-700 hover:border-scale-900 shadow-sm - rounded-lg + rounded-lg grow `, size: { @@ -909,7 +909,7 @@ export default { `, active: ` bg-scale-300 dark:bg-scale-600 z-10 - border-scale-900 dark:border-scale-900 + border-scale-900 dark:border-scale-900 border-1 `, radio_offset: 'left-4', @@ -969,21 +969,21 @@ export default { sidepanel: { base: ` bg-scale-100 dark:bg-scale-300 - flex flex-col - fixed - inset-y-0 - max-w-full + flex flex-col + fixed + inset-y-0 + max-w-full h-screen border-l border-overlay-border shadow-xl `, header: ` - space-y-1 py-4 px-4 bg-overlay-bg sm:px-6 + space-y-1 py-4 px-4 bg-overlay-bg sm:px-6 border-b border-overlay-border `, contents: ` - relative - flex-1 + relative + flex-1 overflow-y-auto `, content: ` @@ -998,16 +998,17 @@ export default { medium: `w-screen max-w-md h-full`, large: `w-screen max-w-2xl h-full`, xlarge: `w-screen max-w-3xl h-full`, + xxlarge: `w-screen max-w-4xl h-full`, }, align: { left: ` left-0 - data-open:animate-panel-slide-left-out + data-open:animate-panel-slide-left-out data-closed:animate-panel-slide-left-in `, right: ` right-0 - data-open:animate-panel-slide-right-out + data-open:animate-panel-slide-right-out data-closed:animate-panel-slide-right-in `, }, @@ -1023,9 +1024,9 @@ export default { dark:bg-scale-100 h-full w-full left-0 - top-0 + top-0 opacity-75 - data-closed:animate-fade-out-overlay-bg + data-closed:animate-fade-out-overlay-bg data-open:animate-fade-in-overlay-bg `, // this is to reset the button @@ -1041,10 +1042,10 @@ export default { toggle: { base: ` - p-0 relative - inline-flex flex-shrink-0 - border-2 border-transparent - rounded-full + p-0 relative + inline-flex flex-shrink-0 + border-2 border-transparent + rounded-full cursor-pointer transition-colors ease-in-out duration-200 ${defaults.focus} @@ -1054,8 +1055,8 @@ export default { hover:bg-scale-700 `, active: ` - bg-brand-900 - hover:bg-brand-900 + bg-brand-900 + hover:bg-brand-900 `, handle_container: { tiny: 'h-4 w-7', @@ -1066,12 +1067,12 @@ export default { }, handle: { base: ` - inline-block h-5 w-5 - rounded-full + inline-block h-5 w-5 + rounded-full bg-scale-100 dark:bg-scale-900 - shadow ring-0 - transition + shadow ring-0 + transition ease-in-out duration-200 `, tiny: 'h-3 w-3', @@ -1159,7 +1160,7 @@ export default { }, error: { base: ` - text-red-900 + text-red-900 transition-all data-show:mt-2 data-show:animate-slide-down-normal @@ -1187,7 +1188,7 @@ export default { trigger: ` flex - border-none + border-none rounded bg-transparent p-0 outline-none @@ -1279,8 +1280,8 @@ export default { popover: { trigger: ` flex - border-none - + border-none + rounded bg-transparent p-0 @@ -1300,7 +1301,7 @@ export default { data-closed:animate-dropdown-content-hide min-w-fit - origin-popover + origin-popover data-open:animate-dropdown-content-show data-closed:animate-dropdown-content-hide `, @@ -1344,7 +1345,7 @@ export default { cursor-pointer flex space-x-3 items-center outline-none - focus-visible:ring-1 ring-scale-1200 focus-visible:z-10 + focus-visible:ring-1 ring-scale-1200 focus-visible:z-10 group `, content: { @@ -1415,7 +1416,7 @@ export default { }, group: { base: ` - flex space-x-3 + flex space-x-3 mb-2 font-normal `, @@ -1438,20 +1439,20 @@ export default { bg-scale-100 dark:bg-scale-300 my-4 border border-scale-300 dark:border-scale-500 - rounded-md - shadow-xl - data-open:animate-overlay-show - data-closed:animate-overlay-hide - + rounded-md + shadow-xl + data-open:animate-overlay-show + data-closed:animate-overlay-hide + `, header: ` bg-scale-200 dark:bg-scale-400 - space-y-1 py-3 px-4 sm:px-5 + space-y-1 py-3 px-4 sm:px-5 border-b border-scale-300 dark:border-scale-500 `, footer: ` flex justify-end gap-2 - py-3 px-5 + py-3 px-5 border-t border-scale-300 dark:border-scale-500 `, size: { @@ -1469,9 +1470,9 @@ export default { dark:bg-scale-100 h-full w-full left-0 - top-0 + top-0 opacity-75 - data-closed:animate-fade-out-overlay-bg + data-closed:animate-fade-out-overlay-bg data-open:animate-fade-in-overlay-bg `, scroll_overlay: ` @@ -1480,7 +1481,7 @@ export default { grid place-items-center overflow-y-auto - data-open:animate-overlay-show data-closed:animate-overlay-hide + data-open:animate-overlay-show data-closed:animate-overlay-hide `, separator: ` w-full @@ -1495,12 +1496,12 @@ export default { listbox: { base: ` - block - box-border - w-full - rounded-md - shadow-sm - text-scale-1200 + block + box-border + w-full + rounded-md + shadow-sm + text-scale-1200 border focus:shadow-md ${defaults.focus} @@ -1524,24 +1525,24 @@ export default { `, error: ` bg-red-100 - border border-red-700 + border border-red-700 focus:ring-red-500 placeholder:text-red-600 `, }, options_container_animate: ` transition - data-open:animate-slide-down + data-open:animate-slide-down data-open:opacity-1 data-closed:animate-slide-up data-closed:opacity-0 `, options_container: ` - bg-scale-100 dark:bg-scale-300 - shadow-lg - border border-solid - border-gray-100 dark:border-gray-600 max-h-60 - rounded-md py-1 text-base + bg-scale-100 dark:bg-scale-300 + shadow-lg + border border-solid + border-gray-100 dark:border-gray-600 max-h-60 + rounded-md py-1 text-base sm:text-sm z-10 overflow-hidden overflow-y-scroll origin-dropdown @@ -1561,7 +1562,7 @@ export default { chevron: 'h-5 w-5 text-scale-600', option: ` w-listbox - transition cursor-pointer select-none relative py-2 pl-3 pr-9 + transition cursor-pointer select-none relative py-2 pl-3 pr-9 text-scale-900 text-sm hover:bg-scale-300 dark:hover:bg-scale-500 @@ -1587,9 +1588,9 @@ export default { inputErrorIcon: { base: ` - flex items-center - right-3 pr-2 pl-2 - inset-y-0 + flex items-center + right-3 pr-2 pl-2 + inset-y-0 pointer-events-none text-red-900 `, @@ -1597,8 +1598,8 @@ export default { inputIconContainer: { base: ` - absolute inset-y-0 - left-0 pl-3 flex + absolute inset-y-0 + left-0 pl-3 flex items-center pointer-events-none text-scale-1100 `, diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index b58d6f3375f..9d7b7185c6f 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -266,9 +266,9 @@ const TableGridEditor: FC = ({ console.log('cancel')} + onCancel={() => setApiPreviewPanelOpen(false)} header={ @@ -277,7 +277,7 @@ const TableGridEditor: FC = ({ } customFooter={ setApiPreviewPanelOpen(false)} @@ -286,7 +286,7 @@ const TableGridEditor: FC = ({ >
-
+
{ - console.log(snippet, 'snippet') if (!snippet[selectedLang]) return null return ( - <> +

{snippet.title}

{snippet[selectedLang].code} - +
) } export default CodeSnippet diff --git a/studio/components/to-be-cleaned/Docs/LangSelector.tsx b/studio/components/to-be-cleaned/Docs/LangSelector.tsx index 2386ff91d3d..ce453e47fad 100644 --- a/studio/components/to-be-cleaned/Docs/LangSelector.tsx +++ b/studio/components/to-be-cleaned/Docs/LangSelector.tsx @@ -30,7 +30,7 @@ const LangSelector: FC = ({ ) return ( -
+
@@ -63,8 +63,8 @@ const Param: FC = ({
- - + + {getColumnType(type, format)} @@ -76,8 +76,8 @@ const Param: FC = ({ Format
- - + + {format} diff --git a/studio/styles/ui.scss b/studio/styles/ui.scss index 2fa8033d916..c824175ec2b 100644 --- a/studio/styles/ui.scss +++ b/studio/styles/ui.scss @@ -224,7 +224,7 @@ @apply border-b flex border-scale-500; } - .doc-section--introduction { + &.Docs--table-editor .doc-section--introduction { .text { width: 85%; } @@ -280,6 +280,9 @@ @apply text-brand-900; } } + .codeblock-container + .codeblock-container { + @apply mt-12; + } } ::-moz-selection { From d4c16fa923725d8e3aeae86eaf419f040356dcce Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Fri, 10 Feb 2023 16:57:34 -0330 Subject: [PATCH 018/289] Fix type --- .../components/to-be-cleaned/Docs/Param.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/studio/components/to-be-cleaned/Docs/Param.tsx b/studio/components/to-be-cleaned/Docs/Param.tsx index 88b1ede519a..3b962756d09 100644 --- a/studio/components/to-be-cleaned/Docs/Param.tsx +++ b/studio/components/to-be-cleaned/Docs/Param.tsx @@ -2,16 +2,6 @@ import { FC } from 'react' import { Badge, IconCode, IconDatabase } from 'ui' import Description from './Description' -interface Props { - name: string - type: string - format: string - required: string - description: boolean - metadata: any - onDesciptionUpdated: () => void -} - function getColumnType(type: string, format: string) { // json and jsonb both have type=undefined, so check format instead if (type === undefined && (format === 'jsonb' || format === 'json')) return 'json' @@ -32,6 +22,15 @@ function getColumnType(type: string, format: string) { } } +interface Props { + name: string + type: string + format: string + required: boolean + description: boolean + metadata?: any + onDesciptionUpdated?: () => void +} const Param: FC = ({ name, type, From 549617e4a9374013bb5c9e690a1f5e415737cc69 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Fri, 10 Feb 2023 17:02:19 -0330 Subject: [PATCH 019/289] Types --- studio/components/to-be-cleaned/Docs/LangSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studio/components/to-be-cleaned/Docs/LangSelector.tsx b/studio/components/to-be-cleaned/Docs/LangSelector.tsx index ce453e47fad..a0e05272874 100644 --- a/studio/components/to-be-cleaned/Docs/LangSelector.tsx +++ b/studio/components/to-be-cleaned/Docs/LangSelector.tsx @@ -3,7 +3,7 @@ import { Button, Dropdown, IconKey } from 'ui' import { checkPermissions } from 'hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { showApiKey } from 'components/interfaces/Docs/docs.types' +import { showApiKey } from 'components/interfaces/Docs/Docs.types' const DEFAULT_KEY = { name: 'hide', key: 'SUPABASE_KEY' } From 1e6da5179ff60accf531f687ed64dcab20135d4a Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Mon, 13 Feb 2023 17:25:16 -0330 Subject: [PATCH 020/289] Add icons for libs --- .../interfaces/Docs/ResourceContent.tsx | 15 ----- .../TableGridEditor/TableGridEditor.tsx | 2 +- .../{Introduction.js => Introduction.tsx} | 55 ++++++++++++++++++- .../public/img/icons/reference-auth-light.svg | 1 + .../img/icons/reference-csharp-light.svg | 1 + studio/public/img/icons/reference-csharp.svg | 9 +++ .../public/img/icons/reference-dart-light.svg | 9 +++ studio/public/img/icons/reference-dart.svg | 9 +++ .../img/icons/reference-javascript-light.svg | 9 +++ .../public/img/icons/reference-javascript.svg | 9 +++ .../img/icons/reference-python-light.svg | 9 +++ studio/public/img/icons/reference-python.svg | 9 +++ 12 files changed, 120 insertions(+), 17 deletions(-) rename studio/components/to-be-cleaned/Docs/Pages/{Introduction.js => Introduction.tsx} (56%) create mode 100644 studio/public/img/icons/reference-auth-light.svg create mode 100644 studio/public/img/icons/reference-csharp-light.svg create mode 100644 studio/public/img/icons/reference-csharp.svg create mode 100644 studio/public/img/icons/reference-dart-light.svg create mode 100644 studio/public/img/icons/reference-dart.svg create mode 100644 studio/public/img/icons/reference-javascript-light.svg create mode 100644 studio/public/img/icons/reference-javascript.svg create mode 100644 studio/public/img/icons/reference-python-light.svg create mode 100644 studio/public/img/icons/reference-python.svg diff --git a/studio/components/interfaces/Docs/ResourceContent.tsx b/studio/components/interfaces/Docs/ResourceContent.tsx index df8634208be..21e6a3dc5fb 100644 --- a/studio/components/interfaces/Docs/ResourceContent.tsx +++ b/studio/components/interfaces/Docs/ResourceContent.tsx @@ -274,21 +274,6 @@ const ResourceContent = ({
- <> -

Much more

-
-
-

- These docs are a work in progress! See our{' '} - - docs - {' '} - for the additional functionality Supabase has to offer. -

-
-
-
- ) } diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 9d7b7185c6f..6dbc33f3a41 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -286,7 +286,7 @@ const TableGridEditor: FC = ({ >
-
+

Introduction

@@ -21,6 +47,33 @@ export default function Introduction({ autoApiService, selectedLang }) { update your API implementation accordingly whenever you make changes to your Supabase schema from the graphical interface.

+ +
+

Read the reference documentation:

+
+ {libs.map((lib) => ( + + {lib.name} + {lib.name} + + ))} +
+
diff --git a/studio/public/img/icons/reference-auth-light.svg b/studio/public/img/icons/reference-auth-light.svg new file mode 100644 index 00000000000..3995c790842 --- /dev/null +++ b/studio/public/img/icons/reference-auth-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/studio/public/img/icons/reference-csharp-light.svg b/studio/public/img/icons/reference-csharp-light.svg new file mode 100644 index 00000000000..782f87bcc40 --- /dev/null +++ b/studio/public/img/icons/reference-csharp-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/studio/public/img/icons/reference-csharp.svg b/studio/public/img/icons/reference-csharp.svg new file mode 100644 index 00000000000..40d0375079d --- /dev/null +++ b/studio/public/img/icons/reference-csharp.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-dart-light.svg b/studio/public/img/icons/reference-dart-light.svg new file mode 100644 index 00000000000..178f51a5b88 --- /dev/null +++ b/studio/public/img/icons/reference-dart-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-dart.svg b/studio/public/img/icons/reference-dart.svg new file mode 100644 index 00000000000..33f9ad24a27 --- /dev/null +++ b/studio/public/img/icons/reference-dart.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-javascript-light.svg b/studio/public/img/icons/reference-javascript-light.svg new file mode 100644 index 00000000000..a11845dff91 --- /dev/null +++ b/studio/public/img/icons/reference-javascript-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-javascript.svg b/studio/public/img/icons/reference-javascript.svg new file mode 100644 index 00000000000..f8ce1de0403 --- /dev/null +++ b/studio/public/img/icons/reference-javascript.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-python-light.svg b/studio/public/img/icons/reference-python-light.svg new file mode 100644 index 00000000000..1ac57aae572 --- /dev/null +++ b/studio/public/img/icons/reference-python-light.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio/public/img/icons/reference-python.svg b/studio/public/img/icons/reference-python.svg new file mode 100644 index 00000000000..4ca064b0b73 --- /dev/null +++ b/studio/public/img/icons/reference-python.svg @@ -0,0 +1,9 @@ + + + + + + + + + From d1ee823b0ba50d934c77e6c1f11393b5521e3493 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Mon, 13 Feb 2023 21:22:23 -0330 Subject: [PATCH 021/289] Refresh docs --- studio/components/grid/types/grid.ts | 4 + .../TableGridEditor/GridHeaderActions.tsx | 15 +++- .../TableGridEditor/TableGridEditor.tsx | 85 ++++++++++++------- studio/pages/project/[ref]/api/index.tsx | 1 - 4 files changed, 73 insertions(+), 32 deletions(-) diff --git a/studio/components/grid/types/grid.ts b/studio/components/grid/types/grid.ts index 68c3dc73220..9650ea0b890 100644 --- a/studio/components/grid/types/grid.ts +++ b/studio/components/grid/types/grid.ts @@ -74,6 +74,10 @@ export interface SupabaseGridProps { */ apiPreviewPanelOpen?: boolean setApiPreviewPanelOpen?: () => void + /** + * Refresh the docs after a change is made to the table + */ + refreshDocs: () => void } export interface SupabaseGridRef { diff --git a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx index c21c62febe1..78712ab0f0a 100644 --- a/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx +++ b/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx @@ -9,20 +9,31 @@ interface Props { table: PostgresTable apiPreviewPanelOpen: boolean setApiPreviewPanelOpen: (apiPreviewPanelOpen: boolean) => void + refreshDocs: () => void } -const GridHeaderActions: FC = ({ table, apiPreviewPanelOpen, setApiPreviewPanelOpen }) => { +const GridHeaderActions: FC = ({ + table, + apiPreviewPanelOpen, + setApiPreviewPanelOpen, + refreshDocs, +}) => { const { ui, meta } = useStore() const projectRef = ui.selectedProject?.ref const policies = meta.policies.list((policy: PostgresPolicy) => policy.table_id === table.id) + function handlePreviewToggle() { + setApiPreviewPanelOpen(!apiPreviewPanelOpen) + refreshDocs() + } + const RenderAPIPreviewToggle = () => { return ( diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 6dbc33f3a41..e0cbb60d6f9 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -16,7 +16,7 @@ import ActionBar from './SidePanelEditor/ActionBar' import { GeneralContent, ResourceContent } from '../Docs' import { useProjectSettingsQuery } from 'data/config/project-settings-query' import { snakeToCamel } from 'lib/helpers' -import useSWR from 'swr' +import useSWR, { mutate } from 'swr' import { get } from 'lib/common/fetch' import LangSelector from 'components/to-be-cleaned/Docs/LangSelector' @@ -117,7 +117,7 @@ const TableGridEditor: FC = ({ : undefined const swaggerUrl = settings?.autoApiService.restUrl - console.log('swaggerUrl:', swaggerUrl) + const headers: any = { apikey: API_KEY } if (API_KEY) headers['Authorization'] = `Bearer ${API_KEY}` @@ -126,9 +126,15 @@ const TableGridEditor: FC = ({ () => swaggerUrl, (url: string) => get(url, { headers, credentials: 'omit' }).then((res) => res) ) + if (jsonSchemaError) console.log('jsonSchemaError', jsonSchemaError) + const resources = getResourcesFromJsonSchema(jsonSchema) + const refreshDocs = async () => { + mutate(swaggerUrl) + } + useEffect(() => { if (selectedTable !== undefined && selectedTable.id !== undefined && isVaultEnabled) { getEncryptedColumns(selectedTable) @@ -230,12 +236,14 @@ const TableGridEditor: FC = ({ editable={canUpdateTables && canEditViaTableEditor} schema={selectedTable.schema} table={gridTable} + refreshDocs={refreshDocs} headerActions={ canEditViaTableEditor && ( ) } @@ -286,34 +294,53 @@ const TableGridEditor: FC = ({ >
-
- -
- + {jsonSchemaError ? ( +
+
+

Error connecting to API

+

{`${jsonSchemaError}`}

+
+
+ ) : ( + <> + {jsonSchema ? ( + <> +
+ +
+ - {jsonSchema?.definitions && ( - table.id === Number(query.id))?.name} - resources={resources} - definitions={jsonSchema.definitions} - paths={jsonSchema.paths} - showApiKey={true} - // refreshDocs={refreshDocs} - /> + {jsonSchema?.definitions && ( + table.id === Number(query.id))?.name} + resources={resources} + definitions={jsonSchema.definitions} + paths={jsonSchema.paths} + showApiKey={true} + refreshDocs={refreshDocs} + /> + )} + + ) : ( +
+

Building docs ...

+
+ )} + )}
diff --git a/studio/pages/project/[ref]/api/index.tsx b/studio/pages/project/[ref]/api/index.tsx index 1ad4f4968f6..670a7b93323 100644 --- a/studio/pages/project/[ref]/api/index.tsx +++ b/studio/pages/project/[ref]/api/index.tsx @@ -1,6 +1,5 @@ import useSWR, { mutate } from 'swr' import { useRouter } from 'next/router' -import { Button, Dropdown, IconKey } from 'ui' import { FC, createContext, useContext, useEffect, useState } from 'react' import { observer, useLocalObservable } from 'mobx-react-lite' From 6174de96d96b24a040dfa53c07b1fd16c6cdf658 Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Mon, 13 Feb 2023 21:26:12 -0330 Subject: [PATCH 022/289] Add hover --- studio/components/to-be-cleaned/Docs/Pages/Introduction.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/studio/components/to-be-cleaned/Docs/Pages/Introduction.tsx b/studio/components/to-be-cleaned/Docs/Pages/Introduction.tsx index e32e174a11c..5b58b9d7348 100644 --- a/studio/components/to-be-cleaned/Docs/Pages/Introduction.tsx +++ b/studio/components/to-be-cleaned/Docs/Pages/Introduction.tsx @@ -59,7 +59,7 @@ export default function Introduction({ autoApiService, selectedLang }: Props) { className=" flex items-center gap-1 rounded-md px-3 py-1 bg-scale-300 dark:bg-scale-500 - hover:dark:bg-scale-700 transition-colors + hover:bg-scale-500 hover:dark:bg-scale-700 transition-colors !text-scale-1100 hover:text-scale-1100 " > From 28fb7d6171c4ffd521a7e2688fb9a72ecef48db4 Mon Sep 17 00:00:00 2001 From: Alaister Young Date: Tue, 14 Feb 2023 18:43:42 +1100 Subject: [PATCH 023/289] moves rows + rows count queries and create + update rows to react-query --- studio/components/grid/SupabaseGrid.tsx | 48 ++++--- .../footer/pagination/Pagination.tsx | 46 +++++-- .../SidePanelEditor/SidePanelEditor.tsx | 58 ++++++--- .../layouts/ProjectLayout/ProjectContext.tsx | 8 +- .../table-rows/table-row-create-mutation.ts | 63 +++++++++ .../table-rows/table-row-update-mutation.ts | 67 ++++++++++ .../data/table-rows/table-rows-count-query.ts | 99 +++++++++++++++ studio/data/table-rows/table-rows-query.ts | 120 ++++++++++++++++++ studio/data/utils/pagination.ts | 11 ++ studio/pages/project/[ref]/editor/[id].tsx | 14 +- studio/pages/project/[ref]/editor/index.tsx | 11 +- 11 files changed, 490 insertions(+), 55 deletions(-) create mode 100644 studio/data/table-rows/table-row-create-mutation.ts create mode 100644 studio/data/table-rows/table-row-update-mutation.ts create mode 100644 studio/data/table-rows/table-rows-count-query.ts create mode 100644 studio/data/table-rows/table-rows-query.ts create mode 100644 studio/data/utils/pagination.ts diff --git a/studio/components/grid/SupabaseGrid.tsx b/studio/components/grid/SupabaseGrid.tsx index 4e3e2d5ab0b..96d1f711307 100644 --- a/studio/components/grid/SupabaseGrid.tsx +++ b/studio/components/grid/SupabaseGrid.tsx @@ -6,7 +6,8 @@ import { useMonaco } from '@monaco-editor/react' import { DataGridHandle } from '@supabase/react-data-grid' import { useUrlState } from 'hooks' -import { Dictionary, SupabaseGridProps, SupabaseGridRef } from './types' +import { Dictionary, SupabaseGridProps, SupabaseGridRef, SupaTable } from './types' +import { useTableRowsQuery } from 'data/table-rows/table-rows-query' import { StoreProvider, useDispatch, useTrackedState } from './store' import { fetchCount, fetchPage, refreshPageDebounced } from './utils' import { REFRESH_PAGE_IMMEDIATELY, TOTAL_ROWS_RESET } from './constants' @@ -22,6 +23,7 @@ import { formatFilterURLParams, formatSortURLParams, } from './SupabaseGrid.utils' +import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' /** Supabase Grid: React component to render database table */ @@ -73,7 +75,22 @@ const SupabaseGridLayout = forwardRef((props // [Joshen] This is not a perfect fix, but the useEffect to initialize the data in the editor // was not getting retriggered for views, works fine for tables. - const table = typeof props.table === 'string' ? { name: props.table } : props.table + const table = (typeof props.table === 'string' ? { name: props.table } : props.table) as SupaTable // TODO(alaister): add support for views + + const { project } = useProjectContext() + const { data } = useTableRowsQuery( + { + queryKey: [table.schema, table.name], + projectRef: project?.ref, + connectionString: project?.connectionString, + table, + sorts, + filters, + page: state.page, + limit: state.rowsPerPage, + }, + { keepPreviousData: true } + ) useImperativeHandle(ref, () => ({ rowAdded(row: Dictionary) { @@ -94,19 +111,20 @@ const SupabaseGridLayout = forwardRef((props if (!mounted) setMounted(true) }, []) - useEffect(() => { - if (state.refreshPageFlag === REFRESH_PAGE_IMMEDIATELY) { - fetchPage(state, dispatch, sorts, filters) - } else if (state.refreshPageFlag !== 0) { - refreshPageDebounced(state, dispatch, sorts, filters) - } - }, [state.refreshPageFlag]) + // TODO(alaister): update this to react-query + // useEffect(() => { + // if (state.refreshPageFlag === REFRESH_PAGE_IMMEDIATELY) { + // fetchPage(state, dispatch, sorts, filters) + // } else if (state.refreshPageFlag !== 0) { + // refreshPageDebounced(state, dispatch, sorts, filters) + // } + // }, [state.refreshPageFlag]) - useEffect(() => { - if (state.totalRows === TOTAL_ROWS_RESET) { - fetchCount(state, dispatch, filters) - } - }, [state.totalRows]) + // useEffect(() => { + // if (state.totalRows === TOTAL_ROWS_RESET) { + // fetchCount(state, dispatch, filters) + // } + // }, [state.totalRows]) useEffect(() => { if (mounted) { @@ -191,7 +209,7 @@ const SupabaseGridLayout = forwardRef((props onAddColumn={editable ? props.onAddColumn : undefined} headerActions={headerActions} /> - +