diff --git a/package.json b/package.json index 4f31f50a..a21c074b 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dev:codegen": "graphql-codegen --config codegen.yml" }, "dependencies": { - "@urql/core": "^2.3.6", + "@apollo/client": "^3.5.6", "autoprefixer": "^10.4.0", "body-parser": "^1.19.1", "cookie-session": "^2.0.0", @@ -48,14 +48,12 @@ "postcss-nested": "^5.0.6", "react": "^18.0.0-rc.0-next-20212349a-20211223", "react-dom": "^18.0.0-rc.0-next-20212349a-20211223", - "react-ssr-prepass": "^1.4.0", "regenerator-runtime": "^0.13.9", "serialize-javascript": "^6.0.0", "source-map-loader": "^3.0.0", "style-loader": "^3.3.1", "ts-loader": "^9.2.6", "typescript": "^4.5.4", - "urql": "^2.0.6", "webpack": "^5.64.4", "webpack-cli": "^4.9.1" }, diff --git a/src/components/header.tsx b/src/components/header.tsx index ead97b88..72199f43 100644 --- a/src/components/header.tsx +++ b/src/components/header.tsx @@ -1,16 +1,15 @@ -import { useAppState } from "store" - +import useAuthToken from "store/use-auth-token" import Balance from "./balance" import Link from "./link" import Logout from "./logout" const Header = ({ balance }: { balance: number }) => { - const { authToken } = useAppState() + const { hasToken } = useAuthToken() return (
- {authToken ? : Login} + {hasToken ? : Login}
) } diff --git a/src/components/home.tsx b/src/components/home.tsx index d8fbc1b9..368a9571 100644 --- a/src/components/home.tsx +++ b/src/components/home.tsx @@ -1,19 +1,18 @@ -import { useQuery } from "urql" +import { useQuery } from "@apollo/client" -import { useAppState } from "store" import QUERY_ME from "store/graphql/query.me" +import useAuthToken from "store/use-auth-token" import Header from "./header" const Home = () => { - const { authToken } = useAppState() + const { hasToken } = useAuthToken() - const [result] = useQuery({ - query: QUERY_ME, - variables: { hasToken: Boolean(authToken) }, + const { data } = useQuery(QUERY_ME, { + variables: { hasToken }, }) - const me = result?.data?.me + const me = data?.me const balance = me?.defaultAccount?.wallets?.[0]?.balance ?? 0 return ( diff --git a/src/components/login.tsx b/src/components/login.tsx index 72db7d24..b2e18855 100644 --- a/src/components/login.tsx +++ b/src/components/login.tsx @@ -1,8 +1,10 @@ +import { useApolloClient } from "@apollo/client" import intlTelInput from "intl-tel-input" import React, { useCallback, useRef, useState } from "react" import config from "server/config" import { history, useRequest } from "store" +import { setCachedAuthToken } from "store/use-auth-token" const PhoneNumber = ({ onSuccess }: { onSuccess: (arg: string) => void }) => { const iti = useRef(null) @@ -55,6 +57,7 @@ const PhoneNumber = ({ onSuccess }: { onSuccess: (arg: string) => void }) => { } const AuthCode = ({ phoneNumber }: { phoneNumber: string }) => { + const client = useApolloClient() const request = useRequest() const [errorMessage, setErrorMessage] = useState("") @@ -73,7 +76,7 @@ const AuthCode = ({ phoneNumber }: { phoneNumber: string }) => { setErrorMessage(data.message) return } - + setCachedAuthToken(client)(data?.authToken) history.push("/", { authToken: data?.authToken }) } diff --git a/src/components/logout.tsx b/src/components/logout.tsx index 3beb567d..8c044dbc 100644 --- a/src/components/logout.tsx +++ b/src/components/logout.tsx @@ -1,12 +1,15 @@ +import { useApolloClient } from "@apollo/client" import { useAppDispatcher, useRequest } from "store" const Logout = () => { + const client = useApolloClient() const request = useRequest() const dispatch = useAppDispatcher() const handleLogout: React.MouseEventHandler = async (event) => { event.preventDefault() await request.post("/api/logout") + client.clearStore() dispatch({ type: "logout" }) } diff --git a/src/components/root-component.tsx b/src/components/root-component.tsx index d02a72e4..7746d029 100644 --- a/src/components/root-component.tsx +++ b/src/components/root-component.tsx @@ -2,14 +2,9 @@ import { Suspense } from "react" import appRoutes, { SupportedRoutes } from "server/routes" const RootComponent = ({ path }: { path: RoutePath }) => { - if (!path) { - throw new Error("MISSING_ROOT_PATH") - } - const checkedRoutePath = SupportedRoutes.find( (supportedRoute) => supportedRoute === path, ) - if (!checkedRoutePath) { throw new Error("INVALID_ROOT_PATH") } diff --git a/src/components/root-provider.tsx b/src/components/root-provider.tsx deleted file mode 100644 index 2ed000a7..00000000 --- a/src/components/root-provider.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { createClient, Provider, dedupExchange, cacheExchange, fetchExchange } from "urql" - -import config from "server/config" -import { ssr, useAppState } from "store" - -import RootComponent from "./root-component" -import { useMemo } from "react" - -const RootProvider = () => { - const { path, authToken } = useAppState() - const client = useMemo(() => { - return createClient({ - url: config.graphqlUri, - suspense: !config.isBrowser, - exchanges: [dedupExchange, cacheExchange, ssr, fetchExchange], - fetchOptions: () => { - return { - headers: { authorization: authToken ? `Bearer ${authToken}` : "" }, - } - }, - }) - }, [authToken]) - - return ( - - - - ) -} - -export default RootProvider diff --git a/src/components/root.test.tsx b/src/components/root.test.tsx index f10fcd2d..b4f3bdbe 100644 --- a/src/components/root.test.tsx +++ b/src/components/root.test.tsx @@ -1,16 +1,25 @@ import "@testing-library/jest-dom/extend-expect" import { render } from "@testing-library/react" +import { MockedProvider } from "@apollo/client/testing" import Root from "./root" describe("Root", () => { it("renders Home and matches snapshot", () => { - const { asFragment } = render() + const { asFragment } = render( + + + , + ) expect(asFragment()).toMatchSnapshot() }) it("renders Login and matches snapshot", () => { - const { asFragment } = render() + const { asFragment } = render( + + + , + ) expect(asFragment()).toMatchSnapshot() }) }) diff --git a/src/components/root.tsx b/src/components/root.tsx index c9e56230..8d4911dd 100644 --- a/src/components/root.tsx +++ b/src/components/root.tsx @@ -2,8 +2,7 @@ import { useEffect, useReducer } from "react" import { GwwContext, history } from "store" import mainReducer from "store/reducer" - -import RootProvider from "./root-provider" +import RootComponent from "./root-component" const Root = ({ initialState }: { initialState: InitialState }) => { const [state, dispatch] = useReducer(mainReducer, initialState) @@ -11,7 +10,7 @@ const Root = ({ initialState }: { initialState: InitialState }) => { useEffect(() => { const unlisten = history.listen(({ location }) => { dispatch({ - type: "state", + type: "navigate", path: location.pathname, ...(location.state as Record | null), }) @@ -21,7 +20,7 @@ const Root = ({ initialState }: { initialState: InitialState }) => { return ( - + ) } diff --git a/src/renderers/dom.tsx b/src/renderers/dom.tsx index 0d0bf641..7cf79337 100644 --- a/src/renderers/dom.tsx +++ b/src/renderers/dom.tsx @@ -1,9 +1,10 @@ import * as ReactDOM from "react-dom" - -import Root from "components/root" +import { ApolloProvider } from "@apollo/client" import "../styles/index.css" -import { ssr } from "store" + +import Root from "components/root" +import client from "store/client" const container = document.getElementById("root") @@ -11,6 +12,9 @@ if (!container) { throw new Error("HTML_ROOT_ELEMENT_IS_MISSING") } -ssr.restoreData(window.__G_DATA.ssrData) - -ReactDOM.hydrateRoot(container, ) +ReactDOM.hydrateRoot( + container, + + + , +) diff --git a/src/renderers/server.tsx b/src/renderers/server.tsx index 6fec823d..06e53d4b 100644 --- a/src/renderers/server.tsx +++ b/src/renderers/server.tsx @@ -1,10 +1,15 @@ -import * as ReactDOMServer from "react-dom/server" +import { + ApolloClient, + InMemoryCache, + ApolloProvider, + createHttpLink, +} from "@apollo/client" import { Request } from "express" -import prepass from "react-ssr-prepass" +import config from "server/config" import appRoutes from "server/routes" import Root from "components/root" -import { ssr } from "store" +import { renderToStringWithData } from "@apollo/client/react/ssr" export const serverRenderer = (req: Request) => @@ -16,18 +21,31 @@ export const serverRenderer = authToken, } - const element = - - await prepass(element) + const cache = new InMemoryCache() + const client = new ApolloClient({ + ssrMode: true, + link: createHttpLink({ + uri: config.graphqlUri, + headers: { + authorization: authToken ? `Bearer ${authToken}` : "", + }, + }), + cache, + }) - const initialMarkup = ReactDOMServer.renderToString(element) + const App = ( + + + + ) - const ssrData = ssr.extractData() + const initialMarkup = await renderToStringWithData(App) + const ssrData = client.extract() return Promise.resolve({ initialState, - ssrData, initialMarkup, + ssrData, pageData: appRoutes[path], }) } diff --git a/src/server/api-router.ts b/src/server/api-router.ts index f004b35a..8a1b27a9 100644 --- a/src/server/api-router.ts +++ b/src/server/api-router.ts @@ -1,4 +1,4 @@ -import "cross-fetch/polyfill" // The URQL client depends on fetch +import "cross-fetch/polyfill" // The Apollo client depends on fetch import express from "express" import MUTATION_USER_LOGIN from "store/graphql/mutation.user-login" import client from "./graphql" @@ -13,13 +13,12 @@ apiRouter.post("/login", async (req, res) => { throw new Error("INVALID_LOGIN_REQUEST") } - const { error, data } = await client(req) - .mutation(MUTATION_USER_LOGIN, { - input: { phone: phoneNumber, code: authCode }, - }) - .toPromise() + const { data } = await client(req).mutate({ + mutation: MUTATION_USER_LOGIN, + variables: { input: { phone: phoneNumber, code: authCode } }, + }) - if (error || data?.userLogin?.errors?.length > 0 || !data?.userLogin?.authToken) { + if (data?.userLogin?.errors?.length > 0 || !data?.userLogin?.authToken) { throw new Error(data?.userLogin?.errors?.[0].message || "SOMETHING_WENT_WRONG") } diff --git a/src/server/graphql.ts b/src/server/graphql.ts index c80bf40d..447cf9a1 100644 --- a/src/server/graphql.ts +++ b/src/server/graphql.ts @@ -1,17 +1,20 @@ -import { createClient } from "@urql/core" import { Request } from "express" +import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client" import config from "./config" -const client = (req: Request) => - createClient({ - url: config.graphqlUri, - fetchOptions: () => { - const token = req.session?.authToken - return { - headers: { authorization: token ? `Bearer ${token}` : "" }, - } - }, +const client = (req: Request) => { + const authToken = req.session?.authToken + return new ApolloClient({ + ssrMode: true, + link: createHttpLink({ + uri: config.graphqlUri, + headers: { + authorization: authToken ? `Bearer ${authToken}` : "", + }, + }), + cache: new InMemoryCache(), }) +} export default client diff --git a/src/store/client.ts b/src/store/client.ts new file mode 100644 index 00000000..7b30767a --- /dev/null +++ b/src/store/client.ts @@ -0,0 +1,30 @@ +import { ApolloClient, InMemoryCache, ApolloLink, from, HttpLink } from "@apollo/client" + +import config from "server/config" +import { getCachedAuthToken, setCachedAuthToken } from "./use-auth-token" + +export const cache = new InMemoryCache().restore(window.__G_DATA.ssrData) + +const authLink = new ApolloLink((operation, forward) => { + const user = getCachedAuthToken(cache) + operation.setContext(({ headers }: { headers: Record }) => ({ + headers: { + authorization: user ? `Bearer ${user.authToken}` : "", + ...headers, + }, + })) + return forward(operation) +}) + +const httpLink = new HttpLink({ uri: config.graphqlUri }) + +const client = new ApolloClient({ + cache, + link: from([authLink, httpLink]), +}) + +if (window.__G_DATA.initialState.authToken) { + setCachedAuthToken(client)(window.__G_DATA.initialState.authToken) +} + +export default client diff --git a/src/store/graphql/mutation.user-login.ts b/src/store/graphql/mutation.user-login.ts index 8a7100d4..5913cbb5 100644 --- a/src/store/graphql/mutation.user-login.ts +++ b/src/store/graphql/mutation.user-login.ts @@ -1,4 +1,4 @@ -import { gql } from "urql" +import { gql } from "@apollo/client" const MUTATION_USER_LOGIN = gql` mutation userLogin($input: UserLoginInput!) { diff --git a/src/store/graphql/query.cached-data.ts b/src/store/graphql/query.cached-data.ts new file mode 100644 index 00000000..bf30ec3c --- /dev/null +++ b/src/store/graphql/query.cached-data.ts @@ -0,0 +1,9 @@ +import { gql } from "@apollo/client" + +export const CACHED_DATA = gql` + query localAppState { + authToken @client + } +` + +export default CACHED_DATA diff --git a/src/store/graphql/query.me.ts b/src/store/graphql/query.me.ts index ffeb2266..31f46ed4 100644 --- a/src/store/graphql/query.me.ts +++ b/src/store/graphql/query.me.ts @@ -1,4 +1,4 @@ -import { gql } from "urql" +import { gql } from "@apollo/client" const QUERY_ME = gql` query me($hasToken: Boolean!) { diff --git a/src/store/index.ts b/src/store/index.ts index 200d97cf..b9ce859d 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,7 +1,7 @@ import fetch from "cross-fetch" import { createContext, useContext } from "react" -import config from "server/config" -import { ssrExchange } from "urql" + +import useAuthToken from "./use-auth-token" export const GwwContext = createContext({ state: { path: "/" }, @@ -12,11 +12,6 @@ export const GwwContext = createContext({ export * from "./history" -export const ssr = ssrExchange({ - isClient: config.isBrowser, - initialState: config.isBrowser ? window.__G_DATA.ssrData : undefined, -}) - export const useAppState = () => { const { state } = useContext(GwwContext) return state @@ -28,7 +23,7 @@ export const useAppDispatcher = () => { } export const useRequest = () => { - const { authToken } = useAppState() + const { authToken } = useAuthToken() const request = { post: async ( diff --git a/src/store/reducer.ts b/src/store/reducer.ts index 6497da5b..93015064 100644 --- a/src/store/reducer.ts +++ b/src/store/reducer.ts @@ -2,7 +2,7 @@ const mainReducer = (state: GwwState, action: GwwAction): GwwState => { const { type, ...newState } = action switch (type) { - case "state": + case "navigate": return { ...state, ...newState } case "logout": return { ...state, authToken: undefined } diff --git a/src/store/use-auth-token.ts b/src/store/use-auth-token.ts new file mode 100644 index 00000000..10034be0 --- /dev/null +++ b/src/store/use-auth-token.ts @@ -0,0 +1,21 @@ +import { ApolloClient, InMemoryCache } from "@apollo/client" +import { useAppState } from "store" +import CACHED_DATA from "./graphql/query.cached-data" + +export const getCachedAuthToken = (cache: InMemoryCache) => + cache.readQuery<{ authToken: string }>({ query: CACHED_DATA }) + +export const setCachedAuthToken = + (client: ApolloClient) => (newAuthToken: string | undefined) => + client.writeQuery({ query: CACHED_DATA, data: { authToken: newAuthToken } }) + +const useAuthToken: UseAuthTokenFunction = () => { + const { authToken } = useAppState() + + return { + authToken, + hasToken: Boolean(authToken), + } +} + +export default useAuthToken diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 16d89e77..1220d2a8 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,4 +1,4 @@ -type SSRData = import("@urql/core/dist/types/exchanges/ssr").SSRData +type NormalizedCacheObject = import("@apollo/client").NormalizedCacheObject type RoutePath = typeof import("../server/routes").SupportedRoutes[number] type RouteInfo = Record JSX.Element)> @@ -12,7 +12,7 @@ type InitialState = { declare interface Window { __G_DATA: { initialState: InitialState - ssrData: SSRData + ssrData: NormalizedCacheObject } } @@ -28,8 +28,8 @@ type GwwState = { } type GwwAction = { - type: "state" | "logout" - [payloadKey: string]: string + type: "navigate" | "logout" + [payloadKey: string]: string | undefined } type GwwContextType = { @@ -56,3 +56,8 @@ type GeetestCaptchaReturn = { resetError: () => void resetValidationData: () => void } + +type UseAuthTokenFunction = () => { + authToken: string | undefined + hasToken: boolean +} diff --git a/yarn.lock b/yarn.lock index 71f7182f..3a07f898 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,24 @@ # yarn lockfile v1 +"@apollo/client@^3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.5.6.tgz#911929df073280689efd98e5603047b79e0c39a2" + integrity sha512-XHoouuEJ4L37mtfftcHHO1caCRrKKAofAwqRoq28UQIPMJk+e7n3X9OtRRNXKk/9tmhNkwelSary+EilfPwI7A== + dependencies: + "@graphql-typed-document-node/core" "^3.0.0" + "@wry/context" "^0.6.0" + "@wry/equality" "^0.5.0" + "@wry/trie" "^0.3.0" + graphql-tag "^2.12.3" + hoist-non-react-statics "^3.3.2" + optimism "^0.16.1" + prop-types "^15.7.2" + symbol-observable "^4.0.0" + ts-invariant "^0.9.4" + tslib "^2.3.0" + zen-observable-ts "^1.2.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" @@ -1004,7 +1022,7 @@ tslib "~2.3.0" value-or-promise "1.0.11" -"@graphql-typed-document-node/core@^3.1.0": +"@graphql-typed-document-node/core@^3.0.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg== @@ -1824,14 +1842,6 @@ "@typescript-eslint/types" "5.8.0" eslint-visitor-keys "^3.0.0" -"@urql/core@^2.3.6": - version "2.3.6" - resolved "https://registry.yarnpkg.com/@urql/core/-/core-2.3.6.tgz#ee0a6f8fde02251e9560c5f17dce5cd90f948552" - integrity sha512-PUxhtBh7/8167HJK6WqBv6Z0piuiaZHQGYbhwpNL9aIQmLROPEdaUYkY4wh45wPQXcTpnd11l0q3Pw+TI11pdw== - dependencies: - "@graphql-typed-document-node/core" "^3.1.0" - wonka "^4.0.14" - "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -1970,6 +1980,27 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.0.tgz#2c275aa05c895eccebbfc34cfb223c6e8bd591a2" integrity sha512-ZkVeqEmRpBV2GHvjjUZqEai2PpUbuq8Bqd//vEYsp63J8WyexI8ppCqVS3Zs0QADf6aWuPdU+0XsPI647PVlQA== +"@wry/context@^0.6.0": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.6.1.tgz#c3c29c0ad622adb00f6a53303c4f965ee06ebeb2" + integrity sha512-LOmVnY1iTU2D8tv4Xf6MVMZZ+juIJ87Kt/plMijjN20NMAXGmH4u8bS1t0uT74cZ5gwpocYueV58YwyI8y+GKw== + dependencies: + tslib "^2.3.0" + +"@wry/equality@^0.5.0": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.2.tgz#72c8a7a7d884dff30b612f4f8464eba26c080e73" + integrity sha512-oVMxbUXL48EV/C0/M7gLVsoK6qRHPS85x8zECofEZOVvxGmIPLA9o5Z27cc2PoAyZz1S2VoM2A7FLAnpfGlneA== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.3.1.tgz#2279b790f15032f8bcea7fc944d27988e5b3b139" + integrity sha512-WwB53ikYudh9pIorgxrkHKrQZcCqNM/Q/bDzZBffEaGUKGuHrRb3zZUT9Sh2qw9yogC7SsdRmQ1ER0pqvd3bfw== + dependencies: + tslib "^2.3.0" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -4238,7 +4269,7 @@ graphql-sse@^1.0.1: resolved "https://registry.yarnpkg.com/graphql-sse/-/graphql-sse-1.0.6.tgz#4f98e0a06f2020542ed054399116108491263224" integrity sha512-y2mVBN2KwNrzxX2KBncQ6kzc6JWvecxuBernrl0j65hsr6MAS3+Yn8PTFSOgRmtolxugepxveyZVQEuaNEbw3w== -graphql-tag@^2.11.0: +graphql-tag@^2.11.0, graphql-tag@^2.12.3: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== @@ -4316,6 +4347,13 @@ history@^5.2.0: dependencies: "@babel/runtime" "^7.7.6" +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" @@ -6122,6 +6160,14 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +optimism@^0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.1.tgz#7c8efc1f3179f18307b887e18c15c5b7133f6e7d" + integrity sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg== + dependencies: + "@wry/context" "^0.6.0" + "@wry/trie" "^0.3.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -6746,7 +6792,7 @@ react-dom@^18.0.0-rc.0-next-20212349a-20211223: object-assign "^4.1.1" scheduler "0.21.0-rc.0-next-20212349a-20211223" -react-is@^16.8.1: +react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -6756,11 +6802,6 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-ssr-prepass@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/react-ssr-prepass/-/react-ssr-prepass-1.4.0.tgz#33a3db19414f0f8f9f3f781c88f760ae366b4f51" - integrity sha512-0SzdmiQUtHvhxCabHg9BI/pkJfijGkQ0jQL6fC4YFy7idaDOuaiQLsajIkkNxffFXtJFHIWFITlve2WB88e0Jw== - react@^18.0.0-rc.0-next-20212349a-20211223: version "18.0.0-rc.0-next-20212349a-20211223" resolved "https://registry.yarnpkg.com/react/-/react-18.0.0-rc.0-next-20212349a-20211223.tgz#b2d6a182bae4c993c664904a970ce76502b5461d" @@ -7590,6 +7631,11 @@ symbol-observable@^1.0.4, symbol-observable@^1.1.0: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== +symbol-observable@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" + integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== + symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -7740,6 +7786,13 @@ tree-kill@^1.2.2: resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +ts-invariant@^0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.9.4.tgz#42ac6c791aade267dd9dc65276549df5c5d71cac" + integrity sha512-63jtX/ZSwnUNi/WhXjnK8kz4cHHpYS60AnmA6ixz17l7E12a5puCWFlNpkne5Rl0J8TBPVHpGjsj4fxs8ObVLQ== + dependencies: + tslib "^2.1.0" + ts-jest@^27.1.2: version "27.1.2" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-27.1.2.tgz#5991d6eb3fd8e1a8d4b8f6de3ec0a3cc567f3151" @@ -7994,14 +8047,6 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -urql@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/urql/-/urql-2.0.6.tgz#e67f09c83780f13d07d462a669977b3d5b36d964" - integrity sha512-ovK9mx7YxD/CKUwVZGbEDBzZjbCcNsr1990nIhDCKe3Ij/0gNcIa+0EIyXKceOPuYDYKavIoaNQV2kOZjQxFcw== - dependencies: - "@urql/core" "^2.3.6" - wonka "^4.0.14" - util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -8247,11 +8292,6 @@ wildcard@^2.0.0: resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== -wonka@^4.0.14: - version "4.0.15" - resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.15.tgz#9aa42046efa424565ab8f8f451fcca955bf80b89" - integrity sha512-U0IUQHKXXn6PFo9nqsHphVCE5m3IntqZNB9Jjn7EB1lrR7YTDY3YWgFvEvwniTzXSvOH/XMzAZaIfJF/LvHYXg== - word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -8441,3 +8481,15 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zen-observable-ts@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.3.tgz#c2f5ccebe812faf0cfcde547e6004f65b1a6d769" + integrity sha512-hc/TGiPkAWpByykMwDcem3SdUgA4We+0Qb36bItSuJC9xD0XVBZoFHYoadAomDSNf64CG8Ydj0Qb8Od8BUWz5g== + dependencies: + zen-observable "0.8.15" + +zen-observable@0.8.15: + version "0.8.15" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==