diff --git a/package-lock.json b/package-lock.json index f6620b8a6..a13fdae47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1517,6 +1517,51 @@ "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.2.tgz", "integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q==" }, + "@trpc/client": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@trpc/client/-/client-3.5.0.tgz", + "integrity": "sha512-wwoyWziaKZtP+EiYvafbtodXuqpz7jD4PaBoiiND+E2ddFvydaq6m9DZdWz6aAxMsgxAS+ha1wACEzYTtDc+hA==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "@trpc/react": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@trpc/react/-/react-3.5.0.tgz", + "integrity": "sha512-Hn2TvxfJRs4PC3Ap7+vf++Ko2Fr/Ac/mg00GdlD7G6C1FHahJ1qjA5UU1dvau98Xudwey+vdHi57zYgYcnGiZg==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, + "@trpc/server": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@trpc/server/-/server-3.5.0.tgz", + "integrity": "sha512-ADvD9sJk1VeQ3ixZ+CD3y/wibHtxPuS1XoLueL2X2Nl1OOoasaJTBN4rjWhYt2SrYYeZDGfWcizRZwwdKHbJug==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, "@types/d3-path": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz", @@ -1998,6 +2043,11 @@ "tweetnacl": "^0.14.3" } }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -2053,6 +2103,20 @@ "fill-range": "^7.0.1" } }, + "broadcast-channel": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.4.1.tgz", + "integrity": "sha512-VXYivSkuBeQY+pL5hNQQNvBdKKQINBAROm4G8lAbWQfOZ7Yn4TMcgLNlJyEqlkxy5G8JJBsI3VJ1u8FUTOROcg==", + "requires": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.0.4", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -3081,6 +3145,11 @@ "minimalistic-assert": "^1.0.0" } }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, "detect-node-es": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.0.0.tgz", @@ -4162,6 +4231,11 @@ "@panva/asn1.js": "^1.0.0" } }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4754,6 +4828,15 @@ "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" }, + "match-sorter": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.0.tgz", + "integrity": "sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ==", + "requires": { + "@babel/runtime": "^7.12.5", + "remove-accents": "0.4.2" + } + }, "mathjs": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-8.1.1.tgz", @@ -4812,6 +4895,11 @@ "picomatch": "^2.0.5" } }, + "microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -4902,6 +4990,14 @@ "thenify-all": "^1.0.0" } }, + "nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=", + "requires": { + "big-integer": "^1.6.16" + } + }, "nanoid": { "version": "3.1.20", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", @@ -5841,6 +5937,16 @@ "xtend": "^4.0.1" } }, + "react-query": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.12.0.tgz", + "integrity": "sha512-WJYECeZ6xT2oxIlgqXUjLNLWRvJbeelXscVnAFfyUFgO21OYEYHMWPG61V9W57EUUqrXioQsNPsU9XyddfEvXQ==", + "requires": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + } + }, "react-refresh": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", @@ -6055,6 +6161,11 @@ "xtend": "^4.0.1" } }, + "remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=" + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -6132,7 +6243,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -6824,6 +6934,15 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, + "unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "requires": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index 01e1bc121..73ce78f9d 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,9 @@ "@lingui/react": "^3.7.1", "@prisma/client": "^2.18.0", "@sendou/react-sketch": "^0.5.2", + "@trpc/client": "^3.5.0", + "@trpc/react": "^3.5.0", + "@trpc/server": "^3.5.0", "countries-list": "^2.6.1", "framer-motion": "^3.10.0", "next": "^10.0.8", @@ -46,6 +49,7 @@ "react-icons": "^4.2.0", "react-infinite-scroller": "^1.2.4", "react-markdown": "^4.3.1", + "react-query": "^3.12.0", "react-select": "^4.2.1", "react-string-replace": "^0.4.4", "recharts": "^2.0.8", diff --git a/pages/_app.tsx b/pages/_app.tsx index d8f2a94c1..81171241d 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -10,9 +10,12 @@ import Head from "next/head"; import { Router } from "next/router"; import NProgress from "nprogress"; import { useEffect } from "react"; +import { QueryClientProvider } from "react-query"; +import { Hydrate } from "react-query/hydration"; import { theme } from "theme"; import { activateLocale } from "utils/i18n"; import { locales } from "utils/lists/locales"; +import { trpc } from "utils/trpc"; import "./styles.css"; NProgress.configure({ showSpinner: false }); @@ -181,7 +184,13 @@ const MyApp = ({ Component, pageProps }: AppProps) => { // @ts-expect-error header={Component.header} > - + + + + + diff --git a/pages/api/trpc/[trpc].ts b/pages/api/trpc/[trpc].ts new file mode 100644 index 000000000..e0f0fcee5 --- /dev/null +++ b/pages/api/trpc/[trpc].ts @@ -0,0 +1,43 @@ +import * as trpc from "@trpc/server"; +import * as trpcNext from "@trpc/server/dist/adapters/next"; +import * as z from "zod"; + +// The app's context - is generated for each incoming request +export type Context = {}; +const createContext = ({ + req, + res, +}: trpcNext.CreateNextContextOptions): Context => { + return {}; +}; + +function createRouter() { + return trpc.router(); +} +// Important: only use this export with SSR/SSG +export const appRouter = createRouter() + // Create procedure at path 'hello' + .query("hello", { + // using zod schema to validate and infer input values + input: z + .object({ + text: z.string().optional(), + }) + .optional(), + resolve({ input }) { + // the `input` here is parsed by the parser passed in `input` the type inferred + return { + greeting: `hello ${input?.text ?? "world"}`, + }; + }, + }); + +// Exporting type _type_ AppRouter only exposes types that can be used for inference +// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export +export type AppRouter = typeof appRouter; + +// export API handler +export default trpcNext.createNextApiHandler({ + router: appRouter, + createContext, +}); diff --git a/utils/trpc.ts b/utils/trpc.ts new file mode 100644 index 000000000..f0e180348 --- /dev/null +++ b/utils/trpc.ts @@ -0,0 +1,14 @@ +import { createReactQueryHooks, createTRPCClient } from "@trpc/react"; +import { QueryClient } from "react-query"; +// Type-only import: +// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export +import type { AppRouter } from "../pages/api/trpc/[trpc]"; + +export const client = createTRPCClient({ + url: "/api/trpc", +}); + +export const trpc = createReactQueryHooks({ + client, + queryClient: new QueryClient(), +});