├── .env.local.example ├── .gitignore ├── .vscode └── settings.json ├── Dockerfile ├── README.md ├── bsconfig.json ├── k8s └── deploy.yaml ├── next.config.js ├── package.json ├── public ├── favicon.ico └── vercel.svg ├── relay.config.js ├── schema.graphql ├── src ├── __generated__ │ └── .gitignore ├── bindings │ └── Next.res ├── features │ └── pokemon │ │ ├── PokemonDetail.module.css │ │ ├── PokemonDetail.res │ │ ├── PokemonFeed.module.css │ │ ├── PokemonFeed.res │ │ ├── PokemonItem.module.css │ │ ├── PokemonItem.res │ │ └── PokemonUtils.res ├── pages │ ├── _app.tsx │ ├── api │ │ └── graphql.ts │ ├── index.res │ └── pokemon │ │ └── [pokemonId].res └── relay │ ├── RelayEnv.res │ ├── environment.ts │ └── hydrateRelayStore.ts ├── styles └── globals.css ├── tsconfig.json └── yarn.lock /.env.local.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_API_URL=http://localhost:3000/api 2 | NODE_TLS_REJECT_UNAUTHORIZED=0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | lib 39 | .bsb.lock 40 | *.bs.js -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Dockerfile 3 | # 4 | 5 | # Install dependencies only when needed 6 | FROM node:18-alpine AS deps 7 | # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. 8 | RUN apk add --no-cache libc6-compat 9 | WORKDIR /app 10 | 11 | # Install dependencies based on the preferred package manager 12 | COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ 13 | RUN \ 14 | if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ 15 | elif [ -f package-lock.json ]; then npm ci; \ 16 | elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \ 17 | else echo "Lockfile not found." && exit 1; \ 18 | fi 19 | 20 | 21 | # Rebuild the source code only when needed 22 | FROM node:18-alpine AS builder 23 | WORKDIR /app 24 | COPY --from=deps /app/node_modules ./node_modules 25 | COPY . . 26 | 27 | # Next.js collects completely anonymous telemetry data about general usage. 28 | # Learn more here: https://nextjs.org/telemetry 29 | # Uncomment the following line in case you want to disable telemetry during the build. 30 | # ENV NEXT_TELEMETRY_DISABLED 1 31 | 32 | RUN yarn build 33 | 34 | # If using npm comment out above and use below instead 35 | # RUN npm run build 36 | 37 | # Production image, copy all the files and run next 38 | FROM node:18-alpine AS runner 39 | WORKDIR /app 40 | 41 | ENV NODE_ENV production 42 | # Uncomment the following line in case you want to disable telemetry during runtime. 43 | # ENV NEXT_TELEMETRY_DISABLED 1 44 | 45 | RUN addgroup --system --gid 1001 nodejs 46 | RUN adduser --system --uid 1001 nextjs 47 | 48 | COPY --from=builder /app/public ./public 49 | 50 | # Automatically leverage output traces to reduce image size 51 | # https://nextjs.org/docs/advanced-features/output-file-tracing 52 | COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ 53 | COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static 54 | 55 | ### 56 | ### aws-lambda-adapter 57 | ### 58 | # COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.6.0 /lambda-adapter /opt/extensions/lambda-adapter 59 | ### 60 | ### 61 | ### 62 | 63 | USER nextjs 64 | 65 | EXPOSE 3000 66 | 67 | ENV PORT 3000 68 | 69 | CMD ["node", "server.js"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rescript + Relay + Next.js + SSR example! 2 | 3 | * using graphql example by [GraphQL-Pokemon](https://graphql-pokemon.vercel.app/) 4 | 5 | ## Concept 6 | 7 | 1. Make feature component by using relay fragment (like [PokemonDetail.res](./src/features/pokemon/PokemonDetail.res)) 8 | 2. Write page by rescript. (Warning; rescript file name should be unique by your project) ([/pages/pokemon/[pokemonEnum].res](./src/pages/pokemon/[pokemonEnum].res)) 9 | 3. In page, make query and connect using feature fragments 10 | 4. Make environment and execute query and return dehydrate store data at `getServerSideProps` (This process is configure by [RelayEnv.SSR.make](./src/relay/RelayEnv.res) function and [hydrateRelayStore.ts](./src/relay/hydrateRelayStore.ts)) 11 | 5. Execute query at page renderer, pass the `fragmentRefs` to feature component 12 | 6. complete! 13 | -------------------------------------------------------------------------------- /bsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-next-ssr-template", 3 | "uncurried": true, 4 | "jsx": { 5 | "version": 4, 6 | "mode": "automatic" 7 | }, 8 | "sources": { 9 | "dir": "src", 10 | "subdirs": true 11 | }, 12 | "package-specs": [ 13 | { 14 | "module": "es6", 15 | "in-source": true 16 | } 17 | ], 18 | "suffix": ".bs.js", 19 | "ppx-flags": ["rescript-relay/ppx"], 20 | "namespace": true, 21 | "bs-dependencies": [ 22 | "@rescript/react", 23 | "rescript-relay" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /k8s/deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: rescript-relay-next-ssr 6 | name: rescript-relay-next-ssr 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: rescript-relay-next-ssr 11 | template: 12 | metadata: 13 | labels: 14 | app: rescript-relay-next-ssr 15 | spec: 16 | containers: 17 | - name: app 18 | image: docker.io/minukang/rescript-relay-next-ssr 19 | imagePullPolicy: Always 20 | ports: 21 | - containerPort: 3000 22 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | const bsconfig = require("./bsconfig.json"); 2 | 3 | /** @type {import('next').NextConfig} */ 4 | const nextConfig = { 5 | output: 'standalone', 6 | reactStrictMode: true, 7 | swcMinify: true, 8 | pageExtensions: ["tsx", "ts", "bs.js"], 9 | experimental: { 10 | scrollRestoration: true, 11 | transpilePackages: ["rescript"] 12 | .concat( 13 | bsconfig["bs-dependencies"]?.filter( 14 | (dep) => !bsconfig["pinned-dependencies"]?.includes(dep) 15 | ) 16 | ) 17 | .concat(["react-relay-network-modern"]), 18 | }, 19 | }; 20 | 21 | module.exports = nextConfig; 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rescript-relay-next-ssr-template", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "yarn relay && yarn res && concurrently 'next dev' 'yarn relay:watch' 'yarn res:watch'", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint", 10 | "res": "rescript build -with-deps", 11 | "res:watch": "yarn res -w", 12 | "relay": "rescript-relay-compiler", 13 | "relay:watch": "rescript-relay-compiler --watch" 14 | }, 15 | "dependencies": { 16 | "@rescript/react": "0.12.0-alpha.3", 17 | "@types/node": "18.11.10", 18 | "@types/react": "18.0.26", 19 | "@types/react-dom": "18.0.9", 20 | "concurrently": "^7.6.0", 21 | "graphql": "^16.6.0", 22 | "next": "13.0.6", 23 | "react": "18.2.0", 24 | "react-dom": "18.2.0", 25 | "react-relay": "^15.0.0", 26 | "react-relay-network-modern": "^6.2.1", 27 | "relay-runtime": "^15.0.0", 28 | "rescript-relay": "2.0.2", 29 | "typescript": "4.9.3" 30 | }, 31 | "devDependencies": { 32 | "@types/react-relay": "^14.1.2", 33 | "@types/relay-runtime": "^14.1.5", 34 | "rescript": "11.0.0-beta.4" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minuukang/rescript-relay-next-ssr-template/84b96dcde2f9e40f2914e07f5ee22afbc5007670/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /relay.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | src: "./", 3 | schema: "./schema.graphql", 4 | artifactDirectory: "./src/__generated__", 5 | customScalars: { 6 | DateTime: "string" 7 | } 8 | }; -------------------------------------------------------------------------------- /schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | pokemons(limit: Int, skip: Int): [Pokemon!] 3 | pokemon(id: ID!): Pokemon 4 | } 5 | 6 | type Attack { 7 | name: String 8 | type: PokemonType 9 | damage: Int 10 | } 11 | 12 | enum PokemonType { 13 | Grass 14 | Poison 15 | Fire 16 | Flying 17 | Water 18 | Bug 19 | Normal 20 | Electric 21 | Ground 22 | Fairy 23 | Fighting 24 | Psychic 25 | Rock 26 | Steel 27 | Ice 28 | Ghost 29 | Dragon 30 | Dark 31 | } 32 | 33 | type EvolutionRequirement { 34 | amount: Int 35 | name: String 36 | } 37 | 38 | type PokemonDimension { 39 | minimum: String! 40 | maximum: String! 41 | } 42 | 43 | type AttacksConnection { 44 | fast: [Attack] 45 | special: [Attack] 46 | } 47 | 48 | type Pokemon { 49 | id: ID! 50 | name: String! 51 | classification: String 52 | types: [PokemonType!]! 53 | resistant: [PokemonType!]! 54 | weaknesses: [PokemonType!]! 55 | evolutionRequirements: [EvolutionRequirement] 56 | weight: PokemonDimension! 57 | height: PokemonDimension! 58 | attacks: AttacksConnection 59 | fleeRate: Float 60 | # Likelihood of an attempt to catch a Pokémon to fail. 61 | 62 | maxCP: Int 63 | # Maximum combat power a Pokémon may achieve at max level. 64 | 65 | maxHP: Int 66 | # Maximum health points a Pokémon may achieve at max level. 67 | 68 | evolutions: [Pokemon!] 69 | } 70 | -------------------------------------------------------------------------------- /src/__generated__/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /src/bindings/Next.res: -------------------------------------------------------------------------------- 1 | module Req = { 2 | type t 3 | 4 | @get 5 | external cookies: t => Js.Dict.t = "cookies" 6 | 7 | @get external method: t => string = "method" 8 | @get external url: t => string = "url" 9 | @get external port: t => int = "port" 10 | @get external headers: t => Js.Dict.t = "headers" 11 | @get 12 | external rawHeaders: t => array = "rawHeaders" 13 | @get 14 | external rawTrailers: t => array = "rawTrailers" 15 | @get external aborted: t => bool = "aborted" 16 | @get external complete: t => bool = "complete" 17 | @send external destroy: t => unit = "destroy" 18 | @send 19 | external destroyWithError: (t, Js.Exn.t) => bool = "destroy" 20 | @get external statusCode: t => int = "statusCode" 21 | @get 22 | external statusMessage: t => string = "statusMessage" 23 | @get 24 | external trailers: t => Js.Dict.t = "trailers" 25 | } 26 | 27 | module Res = { 28 | type t 29 | 30 | @get external statusCode: t => int = "statusCode" 31 | @get external statusMessage: t => string = "statusMessage" 32 | @set 33 | external setStatusCode: (t, int) => unit = "statusCode" 34 | @send 35 | external getHeader: (t, string) => option = "getHeader" 36 | @send 37 | external setHeader: (t, string, string) => unit = "setHeader" 38 | @send external end: (t, 'a) => unit = "end" 39 | } 40 | 41 | module GetServerSideProps = { 42 | type result = 43 | | Props({.}) 44 | | NotFound 45 | | Redirect(string) 46 | | RedirectPermanent(string) 47 | | RedirectStatusCode(string, int) 48 | 49 | type context<'params> = { 50 | req: Req.t, 51 | res: Res.t, 52 | params: 'params, 53 | query: Js.Dict.t, 54 | resolvedUrl: string, 55 | locale: string, 56 | locales: array, 57 | defaultLocale: string, 58 | } 59 | 60 | type t<'a, 'b> = context<'b> => Js.Promise.t 61 | 62 | let parseResult = result => 63 | switch result { 64 | | Props(result) => {"props": result}->Obj.magic 65 | | NotFound => {"notFound": true}->Obj.magic 66 | | Redirect(url) => {"redirect": {"destination": url, "permanent": false}}->Obj.magic 67 | | RedirectPermanent(url) => {"redirect": {"destination": url, "permanent": true}}->Obj.magic 68 | | RedirectStatusCode(url, statusCode) => 69 | { 70 | "redirect": {"destination": url, "statusCode": statusCode}, 71 | }->Obj.magic 72 | } 73 | 74 | let make = async (callback: t<'a, 'b>, context: context<'b>) => { 75 | (await callback(context))->parseResult 76 | } 77 | } 78 | 79 | module Link = { 80 | @module("next/link") @react.component 81 | external make: ( 82 | ~href: string, 83 | @as("as") ~_as: string=?, 84 | ~prefetch: bool=?, 85 | ~scroll: bool=?, 86 | ~replace: option=?, 87 | ~shallow: option=?, 88 | ~passHref: option=?, 89 | ~children: React.element, 90 | ~locale: string=?, 91 | ~ref: ReactDOM.domRef=?, 92 | ) => React.element = "default" 93 | } 94 | 95 | module Router = { 96 | module Events = { 97 | type t 98 | 99 | @send 100 | external on: ( 101 | t, 102 | @string 103 | [ 104 | | #routeChangeStart(string => unit) 105 | | #routeChangeComplete(string => unit) 106 | | #hashChangeComplete(string => unit) 107 | ], 108 | ) => unit = "on" 109 | 110 | @send 111 | external off: ( 112 | t, 113 | @string 114 | [ 115 | | #routeChangeStart(string => unit) 116 | | #routeChangeComplete(string => unit) 117 | | #hashChangeComplete(string => unit) 118 | ], 119 | ) => unit = "off" 120 | } 121 | 122 | type router = { 123 | route: string, 124 | asPath: string, 125 | events: Events.t, 126 | pathname: string, 127 | query: Js.Dict.t, 128 | } 129 | 130 | type pathObj = { 131 | pathname: string, 132 | query: Js.Dict.t, 133 | } 134 | 135 | @deriving(abstract) 136 | type options = { 137 | @optional 138 | scroll: bool, 139 | @optional 140 | prefetch: bool, 141 | @optional 142 | shallow: bool, 143 | } 144 | 145 | type state = { 146 | url: string, 147 | @as("as") _as: string, 148 | options: options, 149 | } 150 | 151 | @send external push: (router, string) => unit = "push" 152 | @send external pushObj: (router, pathObj) => unit = "push" 153 | @send external pushWithAs: (router, string, option, ~options: options=?) => unit = "push" 154 | 155 | @module("next/router") external useRouter: unit => router = "useRouter" 156 | 157 | @send external replace: (router, string) => unit = "replace" 158 | @send external replaceObj: (router, pathObj) => unit = "replace" 159 | @send 160 | external replaceWithAs: (router, string, option, ~options: options=?) => unit = "replace" 161 | 162 | @scope("options") @set external setScrollOption: (state, bool) => unit = "scroll" 163 | 164 | @send 165 | external beforePopState: (router, state => bool) => unit = "beforePopState" 166 | 167 | @send 168 | external clearBeforePopState: router => unit = "beforePopState" 169 | } 170 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonDetail.module.css: -------------------------------------------------------------------------------- 1 | .list { 2 | display: grid; 3 | grid-template-columns: repeat(10, 1fr); 4 | gap: 10px; 5 | list-style: none; 6 | } 7 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonDetail.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment PokemonDetail_Fragment on Pokemon { 3 | id 4 | name 5 | types 6 | weight { 7 | minimum 8 | maximum 9 | } 10 | height { 11 | minimum 12 | maximum 13 | } 14 | evolutions { 15 | id 16 | ...PokemonItem_Fragment 17 | } 18 | } 19 | `) 20 | 21 | @module("./PokemonDetail.module.css") 22 | external styles: {..} = "default" 23 | 24 | @react.component 25 | let make = (~fragmentRefs) => { 26 | let pokemon = Fragment.use(fragmentRefs) 27 |
28 |

{pokemon.name->React.string}

29 | 30 |
    31 |
  • {`weight: ${pokemon.weight.minimum} ~ ${pokemon.weight.maximum}`->React.string}
  • 32 |
  • {`height: ${pokemon.height.minimum} ~ ${pokemon.height.maximum}`->React.string}
  • 33 |
34 |

{`Types`->React.string}

35 |
    36 | {pokemon.types 37 | ->Belt.Array.map(type_ => 38 |
  • Fragment.pokemonType_toString}> 39 | {switch `풀` 44 | | #Poison => `독` 45 | | #Fire => `불꽃` 46 | | #Flying => `비행` 47 | | #Water => `물` 48 | | #Bug => `벌레` 49 | | #Normal => `노멀` 50 | | #Electric => `전기` 51 | | #Ground => `땅` 52 | | #Fairy => `페어리` 53 | | #Fighting => `격투` 54 | | #Psychic => `에스퍼` 55 | | #Rock => `바위` 56 | | #Steel => `강철` 57 | | #Ice => `얼음` 58 | | #Ghost => `고스트` 59 | | #Dragon => `드래곤` 60 | | #Dark => `악` 61 | }} 62 | /> 63 |
  • 64 | ) 65 | ->React.array} 66 |
67 | {switch pokemon.evolutions { 68 | | Some([]) => React.null 69 | | Some(evolutions) => 70 | <> 71 |

{`Evolutions`->React.string}

72 |
    73 | {evolutions 74 | ->Belt.Array.map(pokemon => 75 |
  • 76 | 77 |
  • 78 | ) 79 | ->React.array} 80 |
81 | 82 | | None => React.null 83 | }} 84 |
85 | } 86 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonFeed.module.css: -------------------------------------------------------------------------------- 1 | .list { 2 | display: grid; 3 | grid-template-columns: repeat(10, 1fr); 4 | gap: 10px; 5 | list-style: none; 6 | } 7 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonFeed.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment PokemonFeed_Fragment on Query { 3 | pokemons(limit: 1000) { 4 | id 5 | ...PokemonItem_Fragment 6 | } 7 | } 8 | `) 9 | 10 | @module("./PokemonFeed.module.css") 11 | external styles: {..} = "default" 12 | 13 | @react.component 14 | let make = (~fragmentRefs) => { 15 | let {pokemons} = Fragment.use(fragmentRefs) 16 |
17 |

{`Pokemons`->React.string}

18 |
    19 | {pokemons 20 | ->Belt.Option.getWithDefault([]) 21 | ->Belt.Array.map(pokemon => 22 |
  • 23 | 24 |
  • 25 | ) 26 | ->React.array} 27 |
28 |
29 | } 30 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonItem.module.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | padding: 10px; 3 | } 4 | 5 | .wrapper img { 6 | display: block; 7 | width: 100%; 8 | margin: 0 auto; 9 | aspect-ratio: 1/1; 10 | object-fit: contain; 11 | } 12 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonItem.res: -------------------------------------------------------------------------------- 1 | module Fragment = %relay(` 2 | fragment PokemonItem_Fragment on Pokemon { 3 | id 4 | name 5 | } 6 | `) 7 | 8 | @module("./PokemonItem.module.css") 9 | external styles: {..} = "default" 10 | 11 | @react.component 12 | let make = (~fragmentRefs) => { 13 | let pokemon = Fragment.use(fragmentRefs) 14 | 15 |
16 | 17 |
{`No.${pokemon.id}: ${pokemon.name}`->React.string}
18 |
19 |
20 | } 21 | -------------------------------------------------------------------------------- /src/features/pokemon/PokemonUtils.res: -------------------------------------------------------------------------------- 1 | let makeSpriteImage = name => { 2 | let name = name->Js.String2.toLowerCase 3 | let name = name->Js.String2.replaceByRe(%re("/[\s\']/g"), "") 4 | let name = name->Js.String2.replaceByRe(%re("/-/g"), "_") 5 | `https://projectpokemon.org/images/normal-sprite/${name}.gif` 6 | } 7 | 8 | let makeTypeImage = (type_: RelaySchemaAssets_graphql.enum_PokemonType) => { 9 | switch type_ { 10 | | #Grass => `https://archives.bulbagarden.net/media/upload/a/a8/Grass_icon_SwSh.png` 11 | | #Poison => `https://archives.bulbagarden.net/media/upload/8/8d/Poison_icon_SwSh.png` 12 | | #Fire => `https://archives.bulbagarden.net/media/upload/a/ab/Fire_icon_SwSh.png` 13 | | #Flying => `https://archives.bulbagarden.net/media/upload/b/b5/Flying_icon_SwSh.png` 14 | | #Water => `https://archives.bulbagarden.net/media/upload/8/80/Water_icon_SwSh.png` 15 | | #Bug => `https://archives.bulbagarden.net/media/upload/9/9c/Bug_icon_SwSh.png` 16 | | #Normal => `https://archives.bulbagarden.net/media/upload/9/95/Normal_icon_SwSh.png` 17 | | #Electric => `https://archives.bulbagarden.net/media/upload/7/7b/Electric_icon_SwSh.png` 18 | | #Ground => `https://archives.bulbagarden.net/media/upload/2/27/Ground_icon_SwSh.png` 19 | | #Fairy => `https://archives.bulbagarden.net/media/upload/c/c6/Fairy_icon_SwSh.png` 20 | | #Fighting => `https://archives.bulbagarden.net/media/upload/3/3b/Fighting_icon_SwSh.png` 21 | | #Psychic => `https://archives.bulbagarden.net/media/upload/7/73/Psychic_icon_SwSh.png` 22 | | #Rock => `https://archives.bulbagarden.net/media/upload/1/11/Rock_icon_SwSh.png` 23 | | #Steel => `https://archives.bulbagarden.net/media/upload/0/09/Steel_icon_SwSh.png` 24 | | #Ice => `https://archives.bulbagarden.net/media/upload/1/15/Ice_icon_SwSh.png` 25 | | #Ghost => `https://archives.bulbagarden.net/media/upload/0/01/Ghost_icon_SwSh.png` 26 | | #Dragon => `https://archives.bulbagarden.net/media/upload/7/70/Dragon_icon_SwSh.png` 27 | | #Dark => `https://archives.bulbagarden.net/media/upload/d/d5/Dark_icon_SwSh.png` 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo, useRef } from "react"; 2 | import type { AppProps } from "next/app"; 3 | import { RelayEnvironmentProvider } from "react-relay"; 4 | import { commitLocalUpdate, RecordSource } from "relay-runtime"; 5 | import { makeEnvironment } from "../relay/environment"; 6 | 7 | import "../../styles/globals.css"; 8 | 9 | interface PageProps { 10 | __relayStore__?: Record>; 11 | } 12 | 13 | function App({ Component, pageProps, router }: AppProps) { 14 | const { __relayStore__ } = pageProps as PageProps; 15 | const environment = useMemo(() => makeEnvironment(), []); 16 | const relayStoreRef = useRef>({}); 17 | useMemo(() => { 18 | const key = (router as unknown as { _key: string })._key; 19 | // NOTE: This flag expected that the store will not be reapplied in the same history 20 | // example) pagination of infinite loading connection 21 | if (!relayStoreRef.current[key]) { 22 | relayStoreRef.current[key] = __relayStore__; 23 | if (__relayStore__) { 24 | const recordStore = new RecordSource(__relayStore__); 25 | // NOTE: Bug of relay-runtime merging client connection and server connection 26 | // so, i will delete connection edges by updating from recordStore 27 | commitLocalUpdate(environment, (store) => { 28 | recordStore.getRecordIDs().forEach((dataID) => { 29 | store 30 | .get(dataID) 31 | ?.getLinkedRecords("edges") 32 | ?.forEach((edge) => { 33 | store.delete(edge.getDataID()); 34 | }); 35 | }); 36 | }); 37 | environment.getStore().publish(recordStore); 38 | } 39 | } 40 | }, [__relayStore__, environment, router]); 41 | 42 | return ( 43 | 44 | 45 | 46 | ); 47 | } 48 | 49 | export default App; 50 | -------------------------------------------------------------------------------- /src/pages/api/graphql.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from "next"; 3 | 4 | export default async function handler( 5 | req: NextApiRequest, 6 | res: NextApiResponse 7 | ) { 8 | const response = await fetch( 9 | `https://trygql.formidable.dev/graphql/basic-pokedex`, 10 | { 11 | method: "POST", 12 | headers: { 13 | "Content-Type": "application/json", 14 | }, 15 | body: JSON.stringify(req.body), 16 | } 17 | ); 18 | res.status(response.status); 19 | if (response.ok) { 20 | const json = await response.json(); 21 | res.send(json); 22 | } else { 23 | console.error(await response.text()); 24 | res.send(await response.text()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/pages/index.res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query pages_Index_Query { 3 | ...PokemonFeed_Fragment 4 | } 5 | `) 6 | 7 | type params 8 | 9 | let getServerSideProps = RelayEnv.SSR.make(async ( 10 | ~context as _: Next.GetServerSideProps.context, 11 | ~environment, 12 | ) => { 13 | let _ = await Query.fetchPromised(~environment, ~variables=(), ()) 14 | None 15 | }) 16 | 17 | let default = () => { 18 | let {fragmentRefs} = Query.use(~variables=(), ()) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/pokemon/[pokemonId].res: -------------------------------------------------------------------------------- 1 | module Query = %relay(` 2 | query PokemonId_Page_Query($pokemonId: ID!) { 3 | pokemon(id: $pokemonId) { 4 | ...PokemonDetail_Fragment 5 | } 6 | } 7 | `) 8 | 9 | type params = {pokemonId: string} 10 | 11 | let getServerSideProps = RelayEnv.SSR.make(async ( 12 | ~context: Next.GetServerSideProps.context, 13 | ~environment, 14 | ) => { 15 | let _ = await Query.fetchPromised( 16 | ~environment, 17 | ~variables={ 18 | pokemonId: context.params.pokemonId, 19 | }, 20 | (), 21 | ) 22 | None 23 | }) 24 | 25 | let default = () => { 26 | let router = Next.Router.useRouter() 27 | let pokemonId = router.query->Js.Dict.get("pokemonId")->Belt.Option.getExn 28 | let {pokemon} = Query.use(~variables={pokemonId: pokemonId}, ()) 29 | Belt.Option.getExn).fragmentRefs} /> 30 | } 31 | -------------------------------------------------------------------------------- /src/relay/RelayEnv.res: -------------------------------------------------------------------------------- 1 | @module("./environment.ts") 2 | external makeEnvironment: unit => RescriptRelay.Environment.t = "makeEnvironment" 3 | 4 | @module("./hydrateRelayStore.ts") 5 | external hydrateRelayStore: ( 6 | Next.GetServerSideProps.context<'a>, 7 | RescriptRelay.Environment.t => promise>, 8 | ) => promise<{..}> = "hydrateRelayStore" 9 | 10 | module SSR = { 11 | let make = ( 12 | handler: ( 13 | ~context: Next.GetServerSideProps.context<'params>, 14 | ~environment: RescriptRelay.Environment.t, 15 | ) => promise>, 16 | ) => { 17 | context => Next.GetServerSideProps.make(async context => { 18 | let result = ref(None) 19 | let propsResult = await hydrateRelayStore(context, async environment => { 20 | result.contents = await handler(~context, ~environment) 21 | None 22 | }) 23 | switch result.contents { 24 | | Some(Next.GetServerSideProps.Props(props')) => 25 | Next.GetServerSideProps.Props(Js.Obj.assign(propsResult, props')) 26 | | Some(other) => other 27 | | None => Next.GetServerSideProps.Props(propsResult) 28 | } 29 | }, context) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/relay/environment.ts: -------------------------------------------------------------------------------- 1 | import { Environment, Store, RecordSource } from "relay-runtime"; 2 | import { 3 | RelayNetworkLayer, 4 | urlMiddleware, 5 | retryMiddleware, 6 | errorMiddleware, 7 | loggerMiddleware, 8 | type Variables, 9 | } from "react-relay-network-modern/es"; 10 | 11 | export const makeEnvironment = () => { 12 | return new Environment({ 13 | store: new Store(new RecordSource(), { 14 | gcReleaseBufferSize: 10, 15 | }), 16 | network: new RelayNetworkLayer( 17 | [ 18 | urlMiddleware({ 19 | url: `${process.env.NEXT_PUBLIC_API_URL}/graphql`, 20 | }), 21 | retryMiddleware(), 22 | process.env.NODE_ENV !== "development" ? undefined : errorMiddleware(), 23 | process.env.NODE_ENV !== "development" 24 | ? undefined 25 | : loggerMiddleware({ 26 | logger: (name: string, req: { variables: Variables }) => { 27 | console.info( 28 | `[RELAY] ${name}\n\t* variables: ${JSON.stringify( 29 | req.variables 30 | )}` 31 | ); 32 | }, 33 | }), 34 | ].filter( 35 | (middleware): middleware is NonNullable => 36 | !!middleware 37 | ) 38 | ), 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /src/relay/hydrateRelayStore.ts: -------------------------------------------------------------------------------- 1 | import { GetServerSidePropsContext } from "next"; 2 | import RelayModernEnvironment from "relay-runtime/lib/store/RelayModernEnvironment"; 3 | import { makeEnvironment } from "./environment"; 4 | 5 | const storeName = "__relayStore__"; 6 | 7 | export async function hydrateRelayStore( 8 | context: GetServerSidePropsContext, 9 | callback: (env: RelayModernEnvironment) => Promise 10 | ) { 11 | const environment: RelayModernEnvironment = makeEnvironment(); 12 | const result = await callback(environment); 13 | return { 14 | ...(typeof result === "object" ? result : {}), 15 | [storeName]: environment.getStore().getSource().toJSON(), 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/runtime@^7.0.0": 6 | version "7.20.6" 7 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.6.tgz#facf4879bfed9b5326326273a64220f099b0fce3" 8 | integrity sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA== 9 | dependencies: 10 | regenerator-runtime "^0.13.11" 11 | 12 | "@next/env@13.0.6": 13 | version "13.0.6" 14 | resolved "https://registry.yarnpkg.com/@next/env/-/env-13.0.6.tgz#3fcab11ffbe95bff127827d9f7f3139bc5e6adff" 15 | integrity sha512-yceT6DCHKqPRS1cAm8DHvDvK74DLIkDQdm5iV+GnIts8h0QbdHvkUIkdOvQoOODgpr6018skbmSQp12z5OWIQQ== 16 | 17 | "@next/swc-android-arm-eabi@13.0.6": 18 | version "13.0.6" 19 | resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.0.6.tgz#c971e5a3f8aae875ac1d9fdb159b7e126d8d98d5" 20 | integrity sha512-FGFSj3v2Bluw8fD/X+1eXIEB0PhoJE0zfutsAauRhmNpjjZshLDgoXMWm1jTRL/04K/o9gwwO2+A8+sPVCH1uw== 21 | 22 | "@next/swc-android-arm64@13.0.6": 23 | version "13.0.6" 24 | resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.0.6.tgz#ecacae60f1410136cc31f9e1e09e78e624ca2d68" 25 | integrity sha512-7MgbtU7kimxuovVsd7jSJWMkIHBDBUsNLmmlkrBRHTvgzx5nDBXogP0hzZm7EImdOPwVMPpUHRQMBP9mbsiJYQ== 26 | 27 | "@next/swc-darwin-arm64@13.0.6": 28 | version "13.0.6" 29 | resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.0.6.tgz#266e9e0908024760eba0dfce17edc90ffcba5fdc" 30 | integrity sha512-AUVEpVTxbP/fxdFsjVI9d5a0CFn6NVV7A/RXOb0Y+pXKIIZ1V5rFjPwpYfIfyOo2lrqgehMNQcyMRoTrhq04xg== 31 | 32 | "@next/swc-darwin-x64@13.0.6": 33 | version "13.0.6" 34 | resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.0.6.tgz#4be4ca7bc37f9c93d2e38be5ff313873ad758c09" 35 | integrity sha512-SasCDJlshglsPnbzhWaIF6VEGkQy2NECcAOxPwaPr0cwbbt4aUlZ7QmskNzgolr5eAjFS/xTr7CEeKJtZpAAtQ== 36 | 37 | "@next/swc-freebsd-x64@13.0.6": 38 | version "13.0.6" 39 | resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.0.6.tgz#42eb9043ee65ea5927ba550f4b59827d7064c47b" 40 | integrity sha512-6Lbxd9gAdXneTkwHyYW/qtX1Tdw7ND9UbiGsGz/SP43ZInNWnW6q0au4hEVPZ9bOWWRKzcVoeTBdoMpQk9Hx9w== 41 | 42 | "@next/swc-linux-arm-gnueabihf@13.0.6": 43 | version "13.0.6" 44 | resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.0.6.tgz#aab663282b5f15d12bf9de1120175f438a44c924" 45 | integrity sha512-wNdi5A519e1P+ozEuYOhWPzzE6m1y7mkO6NFwn6watUwO0X9nZs7fT9THmnekvmFQpaZ6U+xf2MQ9poQoCh6jQ== 46 | 47 | "@next/swc-linux-arm64-gnu@13.0.6": 48 | version "13.0.6" 49 | resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.0.6.tgz#5e2b6df4636576a00befb7bd414820a12161a9af" 50 | integrity sha512-e8KTRnleQY1KLk5PwGV5hrmvKksCc74QRpHl5ffWnEEAtL2FE0ave5aIkXqErsPdXkiKuA/owp3LjQrP+/AH7Q== 51 | 52 | "@next/swc-linux-arm64-musl@13.0.6": 53 | version "13.0.6" 54 | resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.0.6.tgz#4a5e91a36cf140cad974df602d647e64b1b9473f" 55 | integrity sha512-/7RF03C3mhjYpHN+pqOolgME3guiHU5T3TsejuyteqyEyzdEyLHod+jcYH6ft7UZ71a6TdOewvmbLOtzHW2O8A== 56 | 57 | "@next/swc-linux-x64-gnu@13.0.6": 58 | version "13.0.6" 59 | resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.0.6.tgz#accb8a721a99e704565b936f16e96fa0c67e8db1" 60 | integrity sha512-kxyEXnYHpOEkFnmrlwB1QlzJtjC6sAJytKcceIyFUHbCaD3W/Qb5tnclcnHKTaFccizZRePXvV25Ok/eUSpKTw== 61 | 62 | "@next/swc-linux-x64-musl@13.0.6": 63 | version "13.0.6" 64 | resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.0.6.tgz#2affaa2f4f01bc190a539d895118a6ad1a477645" 65 | integrity sha512-N0c6gubS3WW1oYYgo02xzZnNatfVQP/CiJq2ax+DJ55ePV62IACbRCU99TZNXXg+Kos6vNW4k+/qgvkvpGDeyA== 66 | 67 | "@next/swc-win32-arm64-msvc@13.0.6": 68 | version "13.0.6" 69 | resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.0.6.tgz#28e5c042772865efd05197a8d1db5920156997fc" 70 | integrity sha512-QjeMB2EBqBFPb/ac0CYr7GytbhUkrG4EwFWbcE0vsRp4H8grt25kYpFQckL4Jak3SUrp7vKfDwZ/SwO7QdO8vw== 71 | 72 | "@next/swc-win32-ia32-msvc@13.0.6": 73 | version "13.0.6" 74 | resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.0.6.tgz#30d91a6d847fa8bce9f8a0f9d2b469d574270be5" 75 | integrity sha512-EQzXtdqRTcmhT/tCq81rIwE36Y3fNHPInaCuJzM/kftdXfa0F+64y7FAoMO13npX8EG1+SamXgp/emSusKrCXg== 76 | 77 | "@next/swc-win32-x64-msvc@13.0.6": 78 | version "13.0.6" 79 | resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.0.6.tgz#dfa28ddb335c16233d22cf39ec8cdf723e6587a1" 80 | integrity sha512-pSkqZ//UP/f2sS9T7IvHLfEWDPTX0vRyXJnAUNisKvO3eF3e1xdhDX7dix/X3Z3lnN4UjSwOzclAI87JFbOwmQ== 81 | 82 | "@rescript/react@0.12.0-alpha.3": 83 | version "0.12.0-alpha.3" 84 | resolved "https://registry.yarnpkg.com/@rescript/react/-/react-0.12.0-alpha.3.tgz#45b94e5b1f24776e74c2dfb7da38ed2c02a4651d" 85 | integrity sha512-/S1uj77RPDzuLg3Ofb8KKU3Vppqy97/vF6bBdBZ+saIO9bpHVlsmmJyJG8QXjGZKE+aMynrrR3Tj4+9+5OzLdw== 86 | 87 | "@swc/helpers@0.4.14": 88 | version "0.4.14" 89 | resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" 90 | integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw== 91 | dependencies: 92 | tslib "^2.4.0" 93 | 94 | "@types/node@18.11.10": 95 | version "18.11.10" 96 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.10.tgz#4c64759f3c2343b7e6c4b9caf761c7a3a05cee34" 97 | integrity sha512-juG3RWMBOqcOuXC643OAdSA525V44cVgGV6dUDuiFtss+8Fk5x1hI93Rsld43VeJVIeqlP9I7Fn9/qaVqoEAuQ== 98 | 99 | "@types/prop-types@*": 100 | version "15.7.5" 101 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" 102 | integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== 103 | 104 | "@types/react-dom@18.0.9": 105 | version "18.0.9" 106 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.9.tgz#ffee5e4bfc2a2f8774b15496474f8e7fe8d0b504" 107 | integrity sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg== 108 | dependencies: 109 | "@types/react" "*" 110 | 111 | "@types/react-relay@^14.1.2": 112 | version "14.1.2" 113 | resolved "https://registry.yarnpkg.com/@types/react-relay/-/react-relay-14.1.2.tgz#0fa08fc8a7e196a0acdc1186fd983cdf3c7d559c" 114 | integrity sha512-skFg+hBAi/two5qloHVF2GjX+wNK7mRwLev6YOl3Xo48YZhPt6akOYdpQHMioBx0WBDxXHByut9JpjAAH3HAHA== 115 | dependencies: 116 | "@types/react" "*" 117 | "@types/relay-runtime" "*" 118 | 119 | "@types/react@*", "@types/react@18.0.26": 120 | version "18.0.26" 121 | resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917" 122 | integrity sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug== 123 | dependencies: 124 | "@types/prop-types" "*" 125 | "@types/scheduler" "*" 126 | csstype "^3.0.2" 127 | 128 | "@types/relay-runtime@*", "@types/relay-runtime@^14.1.5": 129 | version "14.1.5" 130 | resolved "https://registry.yarnpkg.com/@types/relay-runtime/-/relay-runtime-14.1.5.tgz#9ce9e3a896f4d416171cdbf40e50c5ae97c56dde" 131 | integrity sha512-6g4/kX11381FWWxSoe7B96l/a+j+ePvfTE9HlCJbFoRz2qetC+pIecMrEmZWhJ6CprBq+m7MwhpGtTw/YyD87Q== 132 | 133 | "@types/scheduler@*": 134 | version "0.16.2" 135 | resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" 136 | integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== 137 | 138 | ansi-regex@^5.0.1: 139 | version "5.0.1" 140 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 141 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 142 | 143 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 144 | version "4.3.0" 145 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 146 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 147 | dependencies: 148 | color-convert "^2.0.1" 149 | 150 | asap@~2.0.3: 151 | version "2.0.6" 152 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" 153 | integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== 154 | 155 | caniuse-lite@^1.0.30001406: 156 | version "1.0.30001436" 157 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001436.tgz#22d7cbdbbbb60cdc4ca1030ccd6dea9f5de4848b" 158 | integrity sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg== 159 | 160 | chalk@^4.1.0: 161 | version "4.1.2" 162 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 163 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 164 | dependencies: 165 | ansi-styles "^4.1.0" 166 | supports-color "^7.1.0" 167 | 168 | client-only@0.0.1: 169 | version "0.0.1" 170 | resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" 171 | integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== 172 | 173 | cliui@^8.0.1: 174 | version "8.0.1" 175 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" 176 | integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== 177 | dependencies: 178 | string-width "^4.2.0" 179 | strip-ansi "^6.0.1" 180 | wrap-ansi "^7.0.0" 181 | 182 | color-convert@^2.0.1: 183 | version "2.0.1" 184 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 185 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 186 | dependencies: 187 | color-name "~1.1.4" 188 | 189 | color-name@~1.1.4: 190 | version "1.1.4" 191 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 192 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 193 | 194 | concurrently@^7.6.0: 195 | version "7.6.0" 196 | resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a" 197 | integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw== 198 | dependencies: 199 | chalk "^4.1.0" 200 | date-fns "^2.29.1" 201 | lodash "^4.17.21" 202 | rxjs "^7.0.0" 203 | shell-quote "^1.7.3" 204 | spawn-command "^0.0.2-1" 205 | supports-color "^8.1.0" 206 | tree-kill "^1.2.2" 207 | yargs "^17.3.1" 208 | 209 | core-js@^3.0.0: 210 | version "3.26.1" 211 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" 212 | integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== 213 | 214 | cross-fetch@^3.1.5: 215 | version "3.1.5" 216 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" 217 | integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== 218 | dependencies: 219 | node-fetch "2.6.7" 220 | 221 | csstype@^3.0.2: 222 | version "3.1.1" 223 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" 224 | integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== 225 | 226 | date-fns@^2.29.1: 227 | version "2.29.3" 228 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" 229 | integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== 230 | 231 | detect-libc@^2.0.1: 232 | version "2.0.1" 233 | resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" 234 | integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== 235 | 236 | emoji-regex@^8.0.0: 237 | version "8.0.0" 238 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 239 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 240 | 241 | escalade@^3.1.1: 242 | version "3.1.1" 243 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" 244 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 245 | 246 | extract-files@^9.0.0: 247 | version "9.0.0" 248 | resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" 249 | integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== 250 | 251 | fbjs-css-vars@^1.0.0: 252 | version "1.0.2" 253 | resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" 254 | integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== 255 | 256 | fbjs@^3.0.2: 257 | version "3.0.4" 258 | resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" 259 | integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== 260 | dependencies: 261 | cross-fetch "^3.1.5" 262 | fbjs-css-vars "^1.0.0" 263 | loose-envify "^1.0.0" 264 | object-assign "^4.1.0" 265 | promise "^7.1.1" 266 | setimmediate "^1.0.5" 267 | ua-parser-js "^0.7.30" 268 | 269 | get-caller-file@^2.0.5: 270 | version "2.0.5" 271 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 272 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 273 | 274 | graphql@^16.6.0: 275 | version "16.6.0" 276 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" 277 | integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== 278 | 279 | has-flag@^4.0.0: 280 | version "4.0.0" 281 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 282 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 283 | 284 | invariant@^2.2.4: 285 | version "2.2.4" 286 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" 287 | integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== 288 | dependencies: 289 | loose-envify "^1.0.0" 290 | 291 | is-fullwidth-code-point@^3.0.0: 292 | version "3.0.0" 293 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 294 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 295 | 296 | "js-tokens@^3.0.0 || ^4.0.0": 297 | version "4.0.0" 298 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 299 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 300 | 301 | lodash@^4.17.21: 302 | version "4.17.21" 303 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 304 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 305 | 306 | loose-envify@^1.0.0, loose-envify@^1.1.0: 307 | version "1.4.0" 308 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 309 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 310 | dependencies: 311 | js-tokens "^3.0.0 || ^4.0.0" 312 | 313 | nanoid@^3.3.4: 314 | version "3.3.4" 315 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" 316 | integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== 317 | 318 | next@13.0.6: 319 | version "13.0.6" 320 | resolved "https://registry.yarnpkg.com/next/-/next-13.0.6.tgz#f9a2e9e2df9ad60e1b6b716488c9ad501a383621" 321 | integrity sha512-COvigvms2LRt1rrzfBQcMQ2GZd86Mvk1z+LOLY5pniFtL4VrTmhZ9salrbKfSiXbhsD01TrDdD68ec3ABDyscA== 322 | dependencies: 323 | "@next/env" "13.0.6" 324 | "@swc/helpers" "0.4.14" 325 | caniuse-lite "^1.0.30001406" 326 | postcss "8.4.14" 327 | styled-jsx "5.1.0" 328 | optionalDependencies: 329 | "@next/swc-android-arm-eabi" "13.0.6" 330 | "@next/swc-android-arm64" "13.0.6" 331 | "@next/swc-darwin-arm64" "13.0.6" 332 | "@next/swc-darwin-x64" "13.0.6" 333 | "@next/swc-freebsd-x64" "13.0.6" 334 | "@next/swc-linux-arm-gnueabihf" "13.0.6" 335 | "@next/swc-linux-arm64-gnu" "13.0.6" 336 | "@next/swc-linux-arm64-musl" "13.0.6" 337 | "@next/swc-linux-x64-gnu" "13.0.6" 338 | "@next/swc-linux-x64-musl" "13.0.6" 339 | "@next/swc-win32-arm64-msvc" "13.0.6" 340 | "@next/swc-win32-ia32-msvc" "13.0.6" 341 | "@next/swc-win32-x64-msvc" "13.0.6" 342 | 343 | node-fetch@2.6.7: 344 | version "2.6.7" 345 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 346 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 347 | dependencies: 348 | whatwg-url "^5.0.0" 349 | 350 | nullthrows@^1.1.1: 351 | version "1.1.1" 352 | resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" 353 | integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== 354 | 355 | object-assign@^4.1.0: 356 | version "4.1.1" 357 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 358 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 359 | 360 | picocolors@^1.0.0: 361 | version "1.0.0" 362 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" 363 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 364 | 365 | postcss@8.4.14: 366 | version "8.4.14" 367 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" 368 | integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== 369 | dependencies: 370 | nanoid "^3.3.4" 371 | picocolors "^1.0.0" 372 | source-map-js "^1.0.2" 373 | 374 | promise@^7.1.1: 375 | version "7.3.1" 376 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" 377 | integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== 378 | dependencies: 379 | asap "~2.0.3" 380 | 381 | react-dom@18.2.0: 382 | version "18.2.0" 383 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" 384 | integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== 385 | dependencies: 386 | loose-envify "^1.1.0" 387 | scheduler "^0.23.0" 388 | 389 | react-relay-network-modern@^6.2.1: 390 | version "6.2.1" 391 | resolved "https://registry.yarnpkg.com/react-relay-network-modern/-/react-relay-network-modern-6.2.1.tgz#34e93110cf1bb0e666bffb00b513335c37950bc9" 392 | integrity sha512-O1kP9GkNrm4d+ibfuTY9yNbkXV6vAByJ4jYTZIXn8nh7jLWoe6PneF1VcBYvYvzWYsebpCLDQHDPoXI05S+rhQ== 393 | dependencies: 394 | core-js "^3.0.0" 395 | extract-files "^9.0.0" 396 | 397 | react-relay@^15.0.0: 398 | version "15.0.0" 399 | resolved "https://registry.yarnpkg.com/react-relay/-/react-relay-15.0.0.tgz#0014bea71611ae5cdbd3ef445aa13398fe3372d1" 400 | integrity sha512-KWdeMMKMJanOL9LsGZYkyAekayYIi+Y4mbDM8VYbHVPgTWJWAQP6yJKS+V4D17qIMo1L84QJQjGaQWEG139p9Q== 401 | dependencies: 402 | "@babel/runtime" "^7.0.0" 403 | fbjs "^3.0.2" 404 | invariant "^2.2.4" 405 | nullthrows "^1.1.1" 406 | relay-runtime "15.0.0" 407 | 408 | react@18.2.0: 409 | version "18.2.0" 410 | resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" 411 | integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== 412 | dependencies: 413 | loose-envify "^1.1.0" 414 | 415 | regenerator-runtime@^0.13.11: 416 | version "0.13.11" 417 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" 418 | integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== 419 | 420 | relay-runtime@15.0.0, relay-runtime@^15.0.0: 421 | version "15.0.0" 422 | resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-15.0.0.tgz#e83315ea23925fae8f3317f0091f28924441576f" 423 | integrity sha512-7AXkXLQo6gpJNBhk4Kii5b+Yat62HSDD1TgJBi021iSjT1muI8iYd4UZG4f/If209LmaVjkZt2HTNAlk6xtslw== 424 | dependencies: 425 | "@babel/runtime" "^7.0.0" 426 | fbjs "^3.0.2" 427 | invariant "^2.2.4" 428 | 429 | require-directory@^2.1.1: 430 | version "2.1.1" 431 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 432 | integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== 433 | 434 | rescript-relay@2.0.2: 435 | version "2.0.2" 436 | resolved "https://registry.yarnpkg.com/rescript-relay/-/rescript-relay-2.0.2.tgz#2ac666ca06c56bd40898fec8d3583709cc689045" 437 | integrity sha512-pFZyiwcY+nfGbgKlU0XnUbllDss4STMhgRUEXAd/1xg5snCSGG/rTrojLDdyzLsTIppEbF22+n9VgcXWiTJXzg== 438 | dependencies: 439 | detect-libc "^2.0.1" 440 | 441 | rescript@11.0.0-beta.4: 442 | version "11.0.0-beta.4" 443 | resolved "https://registry.yarnpkg.com/rescript/-/rescript-11.0.0-beta.4.tgz#07433d6d0d7118bec73954241d7a61a32c6e1dbf" 444 | integrity sha512-MqTyh9LhDmA++2nemZF+amEO3kOg6a5tR43DuLVocILOAvR17UZcVcS6czGaW6+zOxvPOXVv2i/xiiWCJIDmvw== 445 | 446 | rxjs@^7.0.0: 447 | version "7.5.7" 448 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" 449 | integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== 450 | dependencies: 451 | tslib "^2.1.0" 452 | 453 | scheduler@^0.23.0: 454 | version "0.23.0" 455 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" 456 | integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== 457 | dependencies: 458 | loose-envify "^1.1.0" 459 | 460 | setimmediate@^1.0.5: 461 | version "1.0.5" 462 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 463 | integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== 464 | 465 | shell-quote@^1.7.3: 466 | version "1.7.4" 467 | resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" 468 | integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== 469 | 470 | source-map-js@^1.0.2: 471 | version "1.0.2" 472 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" 473 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 474 | 475 | spawn-command@^0.0.2-1: 476 | version "0.0.2-1" 477 | resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" 478 | integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg== 479 | 480 | string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: 481 | version "4.2.3" 482 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 483 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 484 | dependencies: 485 | emoji-regex "^8.0.0" 486 | is-fullwidth-code-point "^3.0.0" 487 | strip-ansi "^6.0.1" 488 | 489 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 490 | version "6.0.1" 491 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 492 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 493 | dependencies: 494 | ansi-regex "^5.0.1" 495 | 496 | styled-jsx@5.1.0: 497 | version "5.1.0" 498 | resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.0.tgz#4a5622ab9714bd3fcfaeec292aa555871f057563" 499 | integrity sha512-/iHaRJt9U7T+5tp6TRelLnqBqiaIT0HsO0+vgyj8hK2KUk7aejFqRrumqPUlAqDwAj8IbS/1hk3IhBAAK/FCUQ== 500 | dependencies: 501 | client-only "0.0.1" 502 | 503 | supports-color@^7.1.0: 504 | version "7.2.0" 505 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 506 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 507 | dependencies: 508 | has-flag "^4.0.0" 509 | 510 | supports-color@^8.1.0: 511 | version "8.1.1" 512 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" 513 | integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== 514 | dependencies: 515 | has-flag "^4.0.0" 516 | 517 | tr46@~0.0.3: 518 | version "0.0.3" 519 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 520 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 521 | 522 | tree-kill@^1.2.2: 523 | version "1.2.2" 524 | resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" 525 | integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== 526 | 527 | tslib@^2.1.0, tslib@^2.4.0: 528 | version "2.4.1" 529 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" 530 | integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== 531 | 532 | typescript@4.9.3: 533 | version "4.9.3" 534 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" 535 | integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA== 536 | 537 | ua-parser-js@^0.7.30: 538 | version "0.7.32" 539 | resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" 540 | integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== 541 | 542 | webidl-conversions@^3.0.0: 543 | version "3.0.1" 544 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 545 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 546 | 547 | whatwg-url@^5.0.0: 548 | version "5.0.0" 549 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 550 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 551 | dependencies: 552 | tr46 "~0.0.3" 553 | webidl-conversions "^3.0.0" 554 | 555 | wrap-ansi@^7.0.0: 556 | version "7.0.0" 557 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 558 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 559 | dependencies: 560 | ansi-styles "^4.0.0" 561 | string-width "^4.1.0" 562 | strip-ansi "^6.0.0" 563 | 564 | y18n@^5.0.5: 565 | version "5.0.8" 566 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" 567 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== 568 | 569 | yargs-parser@^21.1.1: 570 | version "21.1.1" 571 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" 572 | integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== 573 | 574 | yargs@^17.3.1: 575 | version "17.6.2" 576 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" 577 | integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== 578 | dependencies: 579 | cliui "^8.0.1" 580 | escalade "^3.1.1" 581 | get-caller-file "^2.0.5" 582 | require-directory "^2.1.1" 583 | string-width "^4.2.3" 584 | y18n "^5.0.5" 585 | yargs-parser "^21.1.1" 586 | --------------------------------------------------------------------------------