diff --git a/.env.example b/.env.example index 7059c54..1cd7b67 100644 --- a/.env.example +++ b/.env.example @@ -1,16 +1,13 @@ PORT=3000 -SESSION_NAME="bo2kshelf.sid" +WEBSITE_DOMAIN="http://localhost:${PORT}" +API_DOMAIN="http://localhost:4000" -# Auth Server -AUTH_SERVER_ENDPOINT="http://localhost:8000" +# GraphQL API Endpoint +API_GRAPHQL_ENDPOINT="${API_DOMAIN}/graphql" -# Imageproxy -IMAGE_PROXY_HOST="localhost" - -# Public API -PUBLIC_API_ENDPOINT="http://localhost:8080/graphql" -PUBLIC_API_ACCESS_TOKEN= +# Supertokens +SUPERTOKENS_APP_NAME="bo2kshelf" -# Authenticated API -AUTHENTICATED_API_ENDPOINT="http://localhost:8081/graphql" +# Imageproxy +IMAGEPROXY_HOST="localhost" diff --git a/.storybook/TemplateDecolator.tsx b/.storybook/TemplateDecolator.tsx index 9e5d566..187150b 100644 --- a/.storybook/TemplateDecolator.tsx +++ b/.storybook/TemplateDecolator.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx'; import React from 'react'; -import {PageLayout} from '~/components/layout/PageLayout'; +import {PageLayout} from '~/layouts/PageLayout'; export const TemplateDecolator: React.FC = ({children}) => ( <> diff --git a/codegen.yml b/codegen.yml index af4a534..e62920e 100644 --- a/codegen.yml +++ b/codegen.yml @@ -1,31 +1,24 @@ generates: - ./src/graphql/api-public/schema.graphql: - schema: ${PUBLIC_API_ENDPOINT:./src/graphql/api-public/schema.graphql} + ./src/graphql/schema.graphql: + schema: ${API_GRAPHQL_ENDPOINT:./src/graphql/schema.graphql} plugins: - 'schema-ast' config: includeDirectives: true - ./src/graphql/api-public/codegen/graphql-request.ts: - schema: ${PUBLIC_API_ENDPOINT:./src/graphql/api-public/schema.graphql} + ./src/graphql/codegen/graphql-request.ts: + schema: ${API_GRAPHQL_ENDPOINT:./src/graphql/schema.graphql} documents: - - 'src/graphql/api-public/graphql-request/*.graphql' + - 'src/graphql/graphql-request/*.graphql' plugins: - 'typescript' - 'typescript-operations' - 'typescript-graphql-request' - ./src/graphql/api-authenticated/schema.graphql: - schema: ${AUTHENTICATED_API_ENDPOINT:./src/graphql/api-authenticated/schema.graphql} - plugins: - - 'schema-ast' - config: - includeDirectives: true - - ./src/graphql/api-authenticated/codegen/apollo.ts: - schema: ${AUTHENTICATED_API_ENDPOINT:./src/graphql/api-authenticated/schema.graphql} + ./src/graphql/codegen/apollo.ts: + schema: ${API_GRAPHQL_ENDPOINT:./src/graphql/schema.graphql} documents: - - 'src/graphql/api-authenticated/apollo/*.graphql' + - 'src/graphql/apollo/*.graphql' plugins: - 'typescript' - 'typescript-operations' diff --git a/next.config.js b/next.config.js index 181b5e2..c31fdbc 100644 --- a/next.config.js +++ b/next.config.js @@ -4,13 +4,12 @@ module.exports = { ignoreBuildErrors: true, }, env: { - SESSION_NAME: process.env.SESSION_NAME, - AUTH_SERVER_ENDPOINT: process.env.AUTH_SERVER_ENDPOINT, - GRAPHQL_API_ENDPOINT: process.env.GRAPHQL_API_ENDPOINT, - GRAPHQL_API_SERVER_ACCESS_TOKEN: - process.env.GRAPHQL_API_SERVER_ACCESS_TOKEN, + API_GRAPHQL_ENDPOINT: process.env.API_GRAPHQL_ENDPOINT, + SUPERTOKENS_APP_NAME: process.env.SUPERTOKENS_APP_NAME, + WEBSITE_DOMAIN: process.env.WEBSITE_DOMAIN, + API_DOMAIN: process.env.API_DOMAIN, }, images: { - domains: [process.env.IMAGE_PROXY_HOST], + domains: [process.env.IMAGEPROXY_HOST], }, }; diff --git a/package.json b/package.json index b0f3e71..0f1478f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dev": "run-p -n dev:*", "dev:codegen": "yarn codegen -ws", "dev:next": "next dev -p $PORT", - "start": "next start -p $PORT", + "start": "next start", "test": "jest", "test:watch": "jest --watch", "clean": "run-p -n clean:*", @@ -36,17 +36,13 @@ "@fortawesome/free-solid-svg-icons": "5.15.2", "@fortawesome/react-fontawesome": "0.1.14", "clsx": "1.1.1", - "cookie": "^0.4.1", "dayjs": "^1.10.4", "graphql": "15.4.0", "graphql-request": "3.4.0", "graphql-tag": "2.11.0", "i18next": "19.8.4", "i18next-browser-languagedetector": "6.0.1", - "isomorphic-unfetch": "3.1.0", - "jsonwebtoken": "^8.5.1", "next": "10.0.5", - "nookies": "^2.5.2", "ramda": "^0.27.1", "react": "17.0.1", "react-dom": "17.0.1", @@ -55,8 +51,8 @@ "react-is": "17.0.1", "react-use": "15.3.8", "recoil": "^0.1.2", - "request": "^2.88.2", "styled-components": "5.2.1", + "supertokens-auth-react": "^0.12.1", "tailwindcss": "2.0.2", "type-fest": "0.20.2" }, @@ -82,13 +78,10 @@ "@testing-library/dom": "^7.29.4", "@testing-library/jest-dom": "^5.11.8", "@testing-library/react": "^11.2.3", - "@types/cookie": "^0.4.0", - "@types/express": "^4.17.11", "@types/jest": "26.0.20", "@types/node": "14.14.22", "@types/ramda": "^0.27.35", "@types/react": "17.0.0", - "@types/request": "^2.48.5", "@types/styled-components": "5.1.7", "autoprefixer": "10.2.3", "babel-loader": "^8.2.2", diff --git a/src/components/atoms/Link/Component.tsx b/src/components/atoms/Link/Component.tsx index 8529fe9..09d58a3 100644 --- a/src/components/atoms/Link/Component.tsx +++ b/src/components/atoms/Link/Component.tsx @@ -186,7 +186,7 @@ export const LinkSeriesBooksPage: React.FC<{ export const LinkLoginPage: React.FC<{ className?: string; -}> = ({...props}) => ; +}> = ({...props}) => ; export const LinkLogoutPage: React.FC<{ className?: string; }> = ({...props}) => ; diff --git a/src/components/layout/AppLayout/index.ts b/src/components/layout/AppLayout/index.ts deleted file mode 100644 index dd54451..0000000 --- a/src/components/layout/AppLayout/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {Component as AppLayout} from './Layout'; -export type {ComponentProps as AppLayoutProps} from './Layout'; diff --git a/src/components/layout/PageLayout/index.ts b/src/components/layout/PageLayout/index.ts deleted file mode 100644 index 56aa45b..0000000 --- a/src/components/layout/PageLayout/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {Layout as PageLayout} from './Layout'; -export type {LayoutProps as PageLayoutProps} from './Layout'; diff --git a/src/components/organisms/HeaderNav/Component.stories.tsx b/src/components/organisms/HeaderNav/Component.stories.tsx index 03c70e5..093b715 100644 --- a/src/components/organisms/HeaderNav/Component.stories.tsx +++ b/src/components/organisms/HeaderNav/Component.stories.tsx @@ -28,7 +28,7 @@ export const UnloggedIn: Story = (args) => ( ); UnloggedIn.args = { userLoading: false, - userLoggedIn: false, + signedIn: false, }; UnloggedIn.storyName = '未ログイン'; @@ -37,7 +37,7 @@ export const LoggedIn: Story = (args) => ( ); LoggedIn.args = { userLoading: false, - userLoggedIn: true, + signedIn: true, currentUser: { userName: 'INTERNET_EXPLORER', displayName: 'IAMTHEKIDYOUKNOWWHATIMEAN', diff --git a/src/components/organisms/HeaderNav/Component.tsx b/src/components/organisms/HeaderNav/Component.tsx index e132a43..885833d 100644 --- a/src/components/organisms/HeaderNav/Component.tsx +++ b/src/components/organisms/HeaderNav/Component.tsx @@ -1,27 +1,12 @@ import clsx from 'clsx'; import React from 'react'; -import {Popup} from './atoms/Popup'; -import {LoginButton} from './molecules/LoginButton'; -import {PopupMenu} from './molecules/PopupMenu'; -import {PopupSummary} from './molecules/PopupSummary'; +import {Profile} from './molecules/Profile'; export type ComponentProps = { className?: string; -} & ( - | { - userLoading: true; - } - | { - userLoading: false; - userLoggedIn: false; - } - | { - userLoading: false; - userLoggedIn: true; - currentUser: {userName: string; displayName: string; picture: string}; - } -); -export const Component: React.FC = ({className, ...props}) => ( + signedIn: boolean; +}; +export const Component: React.FC = ({className, signedIn}) => ( ); diff --git a/src/components/organisms/HeaderNav/Container.tsx b/src/components/organisms/HeaderNav/Container.tsx index 9cfd1b3..92d335d 100644 --- a/src/components/organisms/HeaderNav/Container.tsx +++ b/src/components/organisms/HeaderNav/Container.tsx @@ -1,22 +1,10 @@ import React from 'react'; -import {useCurrentUser} from '~/lib/useCurrentUser'; +import {useAuth} from '~/hooks/useAuth'; import {Component} from './Component'; export type ContainerProps = {className?: string}; export const Container: React.FC = ({...props}) => { - const {currentUser, isLoading} = useCurrentUser(); - - if (isLoading) return ; - - return currentUser ? ( - - ) : ( - - ); + const {signedIn} = useAuth(); + return ; }; Container.displayName = 'HeaderNav'; diff --git a/src/components/organisms/HeaderNav/molecules/PopupMenu/Component.tsx b/src/components/organisms/HeaderNav/molecules/PopupMenu/Component.tsx index 81a96d6..7b865de 100644 --- a/src/components/organisms/HeaderNav/molecules/PopupMenu/Component.tsx +++ b/src/components/organisms/HeaderNav/molecules/PopupMenu/Component.tsx @@ -4,7 +4,6 @@ import styled from 'styled-components'; import { MenuItemHaveBooks, MenuItemLikedBooks, - MenuItemLogout, MenuItemReadBooks, MenuItemReadingBooks, MenuItemReadRecords, @@ -13,6 +12,7 @@ import { MenuItemWishBooks, } from '../PopupMenuItem'; import {PopupMenuProfile} from '../PopupMenuProfile'; +import {LogoutButton} from '../SignOut'; export type ComponentProps = { className?: string; @@ -48,7 +48,7 @@ const UnstyledComponent: React.VFC = ({ - + ); diff --git a/src/components/organisms/HeaderNav/molecules/Profile/Container.tsx b/src/components/organisms/HeaderNav/molecules/Profile/Container.tsx new file mode 100644 index 0000000..0424643 --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/Profile/Container.tsx @@ -0,0 +1,20 @@ +import clsx from 'clsx'; +import React from 'react'; +import {withComponentAuthenticated} from '~/hoc/withComponentAuthenticated'; +import {useAuth} from '~/hooks/useAuth'; +import {LoginButton} from '../LoginButton'; +import {UserPopup} from '../UserPopup'; + +export type ContainerProps = {className?: string}; +export const UnwrappedContainer: React.VFC = ({className}) => { + const {signedIn} = useAuth(); + + return ( +
+ {!signedIn && } + {signedIn && } +
+ ); +}; + +export const Container = withComponentAuthenticated(UnwrappedContainer); diff --git a/src/components/organisms/HeaderNav/molecules/Profile/index.ts b/src/components/organisms/HeaderNav/molecules/Profile/index.ts new file mode 100644 index 0000000..7b7abcc --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/Profile/index.ts @@ -0,0 +1,2 @@ +export {Container as Profile} from './Container'; +export type {ContainerProps as ProfileProps} from './Container'; diff --git a/src/components/organisms/HeaderNav/molecules/SignOut/Container.tsx b/src/components/organisms/HeaderNav/molecules/SignOut/Container.tsx new file mode 100644 index 0000000..941ae2f --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/SignOut/Container.tsx @@ -0,0 +1,55 @@ +import clsx from 'clsx'; +import React from 'react'; +import {useTranslation} from 'react-i18next'; +import {IconLogout} from '~/components/atoms/Icon'; +import {useSignOut} from '~/hooks/useSignOut'; + +export type BaseComponentProps = { + className?: string; +}; +export const BaseComponent: React.FC = ({className}) => { + const {t} = useTranslation(); + + const signOut = useSignOut(); + + const onClick = async () => { + signOut(); + }; + + return ( +
+ + + {t('common:logout')} + +
+ ); +}; diff --git a/src/components/organisms/HeaderNav/molecules/SignOut/index.ts b/src/components/organisms/HeaderNav/molecules/SignOut/index.ts new file mode 100644 index 0000000..c24cd4f --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/SignOut/index.ts @@ -0,0 +1,2 @@ +export {BaseComponent as LogoutButton} from './Container'; +export type {BaseComponentProps as LogoutButtonProps} from './Container'; diff --git a/src/components/organisms/HeaderNav/molecules/UserPopup/Container.tsx b/src/components/organisms/HeaderNav/molecules/UserPopup/Container.tsx new file mode 100644 index 0000000..36615e8 --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/UserPopup/Container.tsx @@ -0,0 +1,41 @@ +import clsx from 'clsx'; +import React from 'react'; +import {useAuth} from '~/hooks/useAuth'; +import {Popup} from '../../atoms/Popup'; +import {PopupMenu} from '../PopupMenu'; +import {PopupSummary} from '../PopupSummary'; + +export type ContainerProps = { + className?: string; +}; +export const Container: React.VFC = () => { + const auth = useAuth(); + + if ('currentUser' in auth) + return ( + ( + + )} + Content={({className}) => ( + + )} + /> + ); + + return ( +
+

Loading

+
+ ); +}; diff --git a/src/components/organisms/HeaderNav/molecules/UserPopup/index.ts b/src/components/organisms/HeaderNav/molecules/UserPopup/index.ts new file mode 100644 index 0000000..207dd2a --- /dev/null +++ b/src/components/organisms/HeaderNav/molecules/UserPopup/index.ts @@ -0,0 +1,2 @@ +export {Container as UserPopup} from './Container'; +export type {ContainerProps as UserPopupProps} from './Container'; diff --git a/src/components/organisms/LoginInputForm/Component.stories.tsx b/src/components/organisms/LoginInputForm/Component.stories.tsx deleted file mode 100644 index cf7ebae..0000000 --- a/src/components/organisms/LoginInputForm/Component.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import {Meta, Story} from '@storybook/react/types-6-0'; -import clsx from 'clsx'; -import React from 'react'; -import {Component, ComponentProps} from './Component'; - -export default { - title: 'organisms/LoginForm', - component: Component, - argTypes: { - className: {table: {disable: true}}, - }, -} as Meta; - -export const Primary: Story = (args) => ( - -); diff --git a/src/components/organisms/LoginInputForm/Component.tsx b/src/components/organisms/LoginInputForm/Component.tsx deleted file mode 100644 index 5d208f6..0000000 --- a/src/components/organisms/LoginInputForm/Component.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import clsx from 'clsx'; -import React from 'react'; -import {PasswordInput, UsernameInput} from './molecules/Input'; -import {LoginButton} from './molecules/LoginButton'; -import {StatusText} from './molecules/StatusText'; - -export type ComponentProps = { - className?: string; - - handleUserName: React.ChangeEventHandler; - handlePassword: React.ChangeEventHandler; - handleSubmit: React.MouseEventHandler; - - loginDisabled: boolean; - - status?: 400 | 401 | 404 | 500; -}; -export const Component: React.FC = ({ - className, - loginDisabled, - - handleUserName, - handlePassword, - handleSubmit, - status, -}) => ( -
- - - - {status && ( - - )} - -); diff --git a/src/components/organisms/LoginInputForm/Container.tsx b/src/components/organisms/LoginInputForm/Container.tsx deleted file mode 100644 index 6d9bcb8..0000000 --- a/src/components/organisms/LoginInputForm/Container.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import fetch from 'isomorphic-unfetch'; -import {useRouter} from 'next/router'; -import React, {useState} from 'react'; -import {Component} from './Component'; - -export type ContainerProps = { - className?: string; -}; -export const Container: React.FC = ({...props}) => { - const router = useRouter(); - const [username, setUserName] = useState(''); - const [password, setPassword] = useState(''); - const [status, setStatus] = useState<400 | 401 | 404 | 500 | undefined>(); - - return ( - { - setStatus(undefined); // eslint-disable-line unicorn/no-useless-undefined - setUserName(event.target.value); - }} - handlePassword={(event) => { - setStatus(undefined); // eslint-disable-line unicorn/no-useless-undefined - setPassword(event.target.value); - }} - handleSubmit={async (event) => { - event.preventDefault(); - if (!username || !password) return; - - const result = await fetch('/api/auth/login', { - method: 'POST', - body: JSON.stringify({username, password}), - }); - if (result.status === 401 || result.status === 404) { - setStatus(result.status); - return; - } - if (result.status >= 500) { - setStatus(500); - return; - } - if (result.status >= 400) { - setStatus(400); - return; - } - router.push('/'); - }} - /> - ); -}; -Container.displayName = 'LoginInputForm'; diff --git a/src/components/organisms/LoginInputForm/atoms/Input/Component.tsx b/src/components/organisms/LoginInputForm/atoms/Input/Component.tsx deleted file mode 100644 index 56fb85f..0000000 --- a/src/components/organisms/LoginInputForm/atoms/Input/Component.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import clsx from 'clsx'; -import React from 'react'; - -export type ComponentProps = { - className?: string; - - i18n: Record<'label', string>; - - type?: React.InputHTMLAttributes['type']; - placeholder?: string; - - onChange: React.ChangeEventHandler; -}; -export const Component: React.FC = ({ - className, - i18n, - onChange, - type = 'text', - placeholder, -}) => ( - -); diff --git a/src/components/organisms/LoginInputForm/atoms/Input/index.ts b/src/components/organisms/LoginInputForm/atoms/Input/index.ts deleted file mode 100644 index 99a8f15..0000000 --- a/src/components/organisms/LoginInputForm/atoms/Input/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {Component as Input} from './Component'; -export type {ComponentProps as InputProps} from './Component'; diff --git a/src/components/organisms/LoginInputForm/index.ts b/src/components/organisms/LoginInputForm/index.ts deleted file mode 100644 index 4ee4c9f..0000000 --- a/src/components/organisms/LoginInputForm/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export {Component} from './Component'; -export type {ComponentProps} from './Component'; -export {Container as LoginInputForm} from './Container'; -export type {ContainerProps as LoginInputFormProps} from './Container'; diff --git a/src/components/organisms/LoginInputForm/molecules/Input/Component.stories.tsx b/src/components/organisms/LoginInputForm/molecules/Input/Component.stories.tsx deleted file mode 100644 index 155218b..0000000 --- a/src/components/organisms/LoginInputForm/molecules/Input/Component.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import {Meta, Story} from '@storybook/react/types-6-0'; -import clsx from 'clsx'; -import React from 'react'; -import {ComponentProps, PasswordInput, UsernameInput} from './Component'; - -export default { - title: 'organisms/LoginForm/molecules/Input', - argTypes: { - className: {table: {disable: true}}, - }, -} as Meta; - -export const Username: Story = (args) => ( - -); - -export const Password: Story = (args) => ( - -); diff --git a/src/components/organisms/LoginInputForm/molecules/Input/Component.tsx b/src/components/organisms/LoginInputForm/molecules/Input/Component.tsx deleted file mode 100644 index 7f97def..0000000 --- a/src/components/organisms/LoginInputForm/molecules/Input/Component.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import {useTranslation} from 'react-i18next'; -import {Input} from '../../atoms/Input'; - -export type ComponentProps = { - className?: string; - onChange: React.ChangeEventHandler; -}; -export const UsernameInput: React.FC = ({...props}) => { - const {t} = useTranslation(); - return ( - - ); -}; - -export const PasswordInput: React.FC = ({...props}) => { - const {t} = useTranslation(); - return ( - - ); -}; diff --git a/src/components/organisms/LoginInputForm/molecules/Input/index.ts b/src/components/organisms/LoginInputForm/molecules/Input/index.ts deleted file mode 100644 index d5196c1..0000000 --- a/src/components/organisms/LoginInputForm/molecules/Input/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {PasswordInput, UsernameInput} from './Component'; -export type {ComponentProps as LoginInputProps} from './Component'; diff --git a/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.stories.tsx b/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.stories.tsx deleted file mode 100644 index 9f29803..0000000 --- a/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import {Meta, Story} from '@storybook/react/types-6-0'; -import React from 'react'; -import {Component, ComponentProps} from './Component'; - -export default { - title: 'organisms/LoginForm/molecules/LoginButton', - component: Component, - argTypes: { - className: {table: {disable: true}}, - disabled: {table: {disable: true}}, - }, -} as Meta; - -export const Active: Story = (args) => ; -Active.args = { - disabled: false, -}; - -export const Disabled: Story = (args) => ( - -); -Disabled.args = { - disabled: true, -}; diff --git a/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.tsx b/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.tsx deleted file mode 100644 index f7b9736..0000000 --- a/src/components/organisms/LoginInputForm/molecules/LoginButton/Component.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import {useTranslation} from 'react-i18next'; -import {NormalButtonBlue} from '~/components/atoms/Button'; -import {IconLogin, IconWarning} from '~/components/atoms/Icon/Component'; - -export type ComponentProps = { - className?: string; - disabled: boolean; - onClick: React.MouseEventHandler; -}; -export const Component: React.FC = ({disabled, ...props}) => { - const {t} = useTranslation(); - - const text = disabled ? t('必要な情報を入力してください') : t('common:login'); - const Icon = disabled ? IconWarning : IconLogin; - return ( - - ); -}; diff --git a/src/components/organisms/LoginInputForm/molecules/LoginButton/index.ts b/src/components/organisms/LoginInputForm/molecules/LoginButton/index.ts deleted file mode 100644 index 7dd737a..0000000 --- a/src/components/organisms/LoginInputForm/molecules/LoginButton/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {Component as LoginButton} from './Component'; -export type {ComponentProps as LoginButtonProps} from './Component'; diff --git a/src/components/organisms/LoginInputForm/molecules/StatusText/Component.tsx b/src/components/organisms/LoginInputForm/molecules/StatusText/Component.tsx deleted file mode 100644 index 94bde78..0000000 --- a/src/components/organisms/LoginInputForm/molecules/StatusText/Component.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import clsx from 'clsx'; -import React from 'react'; -import {useTranslation} from 'react-i18next'; - -export type ComponentProps = { - className?: string; - status?: 400 | 401 | 404 | 500; -}; -export const Component: React.VFC = ({className, status}) => { - const {t} = useTranslation(); - - return ( -

- {status === 400 && t('クライアント側で何らかのエラーが発生しています')} - {status === 401 && t('パスワードが間違っています')} - {status === 404 && t('存在しないユーザーです')} - {status === 500 && t('サーバー側で何らかのエラーが発生しています')} -

- ); -}; diff --git a/src/components/organisms/LoginInputForm/molecules/StatusText/index.ts b/src/components/organisms/LoginInputForm/molecules/StatusText/index.ts deleted file mode 100644 index 30458ac..0000000 --- a/src/components/organisms/LoginInputForm/molecules/StatusText/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {Component as StatusText} from './Component'; -export type {ComponentProps as StatusTextProps} from './Component'; diff --git a/src/configs/api.ts b/src/configs/api.ts new file mode 100644 index 0000000..30f08e2 --- /dev/null +++ b/src/configs/api.ts @@ -0,0 +1,2 @@ +/* eslint-disable no-process-env */ +export const API_GRAPHQL_ENDPOINT = process.env.API_GRAPHQL_ENDPOINT!; diff --git a/src/configs/supertokens.ts b/src/configs/supertokens.ts new file mode 100644 index 0000000..ed6b8d7 --- /dev/null +++ b/src/configs/supertokens.ts @@ -0,0 +1,19 @@ +/* eslint-disable no-process-env */ +import SessionReact from 'supertokens-auth-react/recipe/session'; +import ThirdParty, {Github} from 'supertokens-auth-react/recipe/thirdparty'; + +export const supertokensFrontendConfig = { + appInfo: { + appName: process.env.SUPERTOKENS_APP_NAME!, + websiteDomain: process.env.WEBSITE_DOMAIN!, + apiDomain: process.env.API_DOMAIN!, + }, + recipeList: [ + SessionReact.init(), + ThirdParty.init({ + signInAndUpFeature: { + providers: [Github.init()], + }, + }), + ], +}; diff --git a/src/graphql/.eslintrc b/src/graphql/.eslintrc index 498711c..35f66a1 100644 --- a/src/graphql/.eslintrc +++ b/src/graphql/.eslintrc @@ -1,19 +1,11 @@ { "overrides": [ { - "files": ["./api-authenticated/**/*.graphql"], + "files": ["./**/*.graphql"], "parser": "@graphql-eslint/eslint-plugin", "plugins": ["@graphql-eslint"], "parserOptions": { - "schema": "./src/graphql/api-authenticated/schema.graphql" - } - }, - { - "files": ["./api-public/**/*.graphql"], - "parser": "@graphql-eslint/eslint-plugin", - "plugins": ["@graphql-eslint"], - "parserOptions": { - "schema": "./src/graphql/api-public/schema.graphql" + "schema": "./src/graphql/schema.graphql" } } ] diff --git a/src/graphql/api-authenticated/apollo/PersonalUserPage.graphql b/src/graphql/api-authenticated/apollo/PersonalUserPage.graphql deleted file mode 100644 index d22acb9..0000000 --- a/src/graphql/api-authenticated/apollo/PersonalUserPage.graphql +++ /dev/null @@ -1,144 +0,0 @@ -query PersonalUserPage { - currentUser { - id - userName: uniqueName - displayName - picture - readBooks(limit: 12) { - hasNext - nodes { - id - title - cover - } - } - readingBooks(limit: 12) { - hasNext - nodes { - book { - id - title - cover - } - } - } - hasBooks(limit: 12) { - hasNext - nodes { - book { - id - title - cover - } - } - } - stackedBooks(limit: 12) { - hasNext - nodes { - book { - id - title - cover - } - } - } - } -} - -query PersonalUserReadBooksPage($skip: Int!, $limit: Int!) { - currentUser { - userName: uniqueName - displayName - picture - books: readBooks(limit: $limit, skip: $skip) { - count - hasNext - hasPrevious - nodes { - id - title - cover - } - } - } -} - -query PersonalUserReadingBooksPage($skip: Int!, $limit: Int!) { - currentUser { - userName: uniqueName - displayName - picture - books: readingBooks(limit: $limit, skip: $skip) { - count - hasNext - hasPrevious - nodes { - book { - id - title - cover - } - } - } - } -} - -query PersonalUserStackedBooksPage($skip: Int!, $limit: Int!) { - currentUser { - userName: uniqueName - displayName - picture - books: stackedBooks(limit: $limit, skip: $skip) { - count - hasNext - hasPrevious - nodes { - book { - id - title - cover - } - } - } - } -} - -query PersonalUserWishReadBooksPage($skip: Int!, $limit: Int!) { - currentUser { - userName: uniqueName - displayName - picture - books: wishesReadBooks(limit: $limit, skip: $skip) { - count - hasNext - hasPrevious - nodes { - book { - id - title - cover - } - } - } - } -} - -query PersonalUserhasBooksPage($skip: Int!, $limit: Int!) { - currentUser { - userName: uniqueName - displayName - picture - books: hasBooks(limit: $limit, skip: $skip) { - count - hasNext - hasPrevious - nodes { - book { - id - title - cover - } - } - } - } -} diff --git a/src/graphql/api-authenticated/apollo/UserPage.graphql b/src/graphql/api-authenticated/apollo/UserPage.graphql deleted file mode 100644 index 1e94da7..0000000 --- a/src/graphql/api-authenticated/apollo/UserPage.graphql +++ /dev/null @@ -1,23 +0,0 @@ -query MoreRecordsInUserPage($userName: String!, $limit: Int!, $skip: Int!) { - user(uniqueName: $userName) { - records(skip: $skip, limit: $limit, orderBy: {readAt: DESC}) { - count - hasNext - nodes { - id - readAt - user { - displayName - userName: uniqueName - picture - } - book { - id - title - subtitle - cover - } - } - } - } -} diff --git a/src/graphql/api-authenticated/schema.graphql b/src/graphql/api-authenticated/schema.graphql deleted file mode 100644 index ae0c12d..0000000 --- a/src/graphql/api-authenticated/schema.graphql +++ /dev/null @@ -1,405 +0,0 @@ -schema { - query: Query - mutation: Mutation -} -type Author { - id: ID! - name: String! - writed(skip: Int = 0, limit: Int = 0, except: [ID!] = [], orderBy: AuthorWritesArgsOrderBy = {title: ASC}): AuthorWritesReturn! - relatedSeries(skip: Int = 0, limit: Int = 0, orderBy: AuthorsRelatedSeriesArgsOrderBy = {title: ASC}): AuthorsRelatedSeriesReturn! -} -enum AuthorRole { - AUTHOR - ORIGINAL_AUTHOR - SUPERVISOR - PARTICIPANT - EDITOR - ILLUSTRATOR - COMIC_ARTIST - TRANSLATOR - TRANSLATE_SUPERVISOR -} -type AuthorSeriesRelation { - author: Author! - series: Series! - relatedBooks(skip: Int = 0, limit: Int = 0, orderBy: AuthorSeriesRelationRelatedBooksArgsOrderBy = {order: ASC, title: ASC}): [Book!]! -} -input AuthorSeriesRelationRelatedBooksArgsOrderBy { - order: OrderBy - title: OrderBy -} -input AuthorsRelatedSeriesArgsOrderBy { - title: OrderBy -} -type AuthorsRelatedSeriesReturn { - nodes: [AuthorSeriesRelation!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input AuthorWritesArgsOrderBy { - title: OrderBy -} -type AuthorWritesReturn { - nodes: [Writing!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -type Book { - id: ID! - title: String! - subtitle: String - isbn(dehyphenize: Boolean = true): String - writedBy(orderBy: BookWritedByArgsOrderBy = {name: ASC}): [Writing!]! - seriesOf: [SeriesPart!]! - previousBooks(skip: Int = 0, limit: Int = 1): BooksPreviousReturn! - nextBooks(skip: Int = 0, limit: Int = 1): BooksNextReturn! - publishedBy: Publisher - label: Label - cover: String -} -type BooksNextReturn { - nodes: [NextBookConnection!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -type BooksPreviousReturn { - nodes: [NextBookConnection!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input BookWritedByArgsOrderBy { - name: OrderBy -} -"""A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.""" -scalar DateTime -type HaveBookRecord { - have: Boolean! - updatedAt: DateTime! - user: User! - book: Book! -} -type Label { - id: ID! - name: String! - books(skip: Int = 0, limit: Int = 0, except: [ID!] = [], orderBy: LabelsBooksArgsOrderBy = {title: ASC}): LabelsBooksReturn! - belongsTo: PublisherLabelRelation! -} -type Labeling { - book: Book! - label: Label! -} -input LabelsBooksArgsOrderBy { - title: OrderBy -} -type LabelsBooksReturn { - nodes: [Labeling!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -"""A local date string (i.e., with no associated timezone) in `YYYY-MM-DD` format, e.g. `2020-01-01`.""" -scalar LocalDate -type NextBookConnection { - previous: Book! - next: Book! -} -enum OrderBy { - ASC - DESC -} -type Publication { - book: Book! - publisher: Publisher! -} -type Publisher { - id: ID! - name: String! - publications(skip: Int = 0, limit: Int = 0, except: [ID!] = [], orderBy: PublishersPublicationsArgsOrderBy = {title: ASC}): PublishersPublicationsReturn! - labels(skip: Int = 0, limit: Int = 0, except: [ID!] = [], orderBy: PublishersLabelsArgsOrderBy = {name: ASC}): PublishersLabelsReturn! -} -type PublisherLabelRelation { - publisher: Publisher! - label: Label! -} -input PublishersLabelsArgsOrderBy { - name: OrderBy -} -type PublishersLabelsReturn { - nodes: [PublisherLabelRelation!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input PublishersPublicationsArgsOrderBy { - title: OrderBy -} -type PublishersPublicationsReturn { - nodes: [Publication!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -type ReadingBookRecord { - reading: Boolean! - updatedAt: DateTime! - user: User! - book: Book! -} -type Record { - id: ID! - readAt: LocalDate - user: User! - book: Book! -} -type Series { - id: ID! - title: String! - head: SeriesPart! - parts(skip: Int = 0, limit: Int = 0, orderBy: OrderBy = ASC): SeriesPartsReturn! - subParts(skip: Int = 0, limit: Int = 0, orderBy: SeriesSubSubPartsArgsOrderBy = {order: ASC}): SeriesPartsReturn! - relatedAuthors(skip: Int = 0, limit: Int = 0, orderBy: SeriesRelatedAuthorsArgsOrderBy = {name: ASC}): SeriesRelatedAuthorsReturn! -} -type SeriesPart { - numberingAs: String - book: Book! - series: Series! -} -type SeriesPartsReturn { - nodes: [SeriesPart!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input SeriesRelatedAuthorsArgsOrderBy { - name: OrderBy -} -type SeriesRelatedAuthorsReturn { - nodes: [AuthorSeriesRelation!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input SeriesSubSubPartsArgsOrderBy { - order: OrderBy -} -type StackedBookRecord { - user: User! - book: Book! -} -input UsersHasBooksArgsOrderBy { - updatedAt: OrderBy -} -type UsersHasBooksReturn { - nodes: [HaveBookRecord!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input UsersReadBooksArgsOrderBy { - title: OrderBy -} -type UsersReadBooksReturn { - nodes: [Book!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input UsersReadingBooksArgsOrderBy { - updatedAt: OrderBy -} -type UsersReadingBooksReturn { - nodes: [ReadingBookRecord!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input UsersRecordsArgsOrderBy { - readAt: OrderBy -} -type UsersRecordsReturn { - nodes: [Record!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input UsersStackedBooksArgsOrderBy { - updatedAt: OrderBy -} -type UsersStackedBooksReturn { - nodes: [StackedBookRecord!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -input UsersWishesReadBooksArgsOrderBy { - updatedAt: OrderBy -} -type UsersWishReadBooksReturn { - nodes: [WishReadBookRecord!]! - count: Int! - hasPrevious: Boolean! - hasNext: Boolean! -} -type WishReadBookRecord { - wish: Boolean! - updatedAt: DateTime! - user: User! - book: Book! -} -type Writing { - roles: [AuthorRole!]! - book: Book! - author: Author! -} -input SearchAuthorsQuery { - name: String! -} -type SearchAuthorsResult { - aggregate: SearchAuthorsResultAggregate! - pageInfo: SearchAuthorsResultPageInfo! - edges: [SearchAuthorsResultEdgeType!]! -} -type SearchAuthorsResultAggregate { - count: Int! -} -type SearchAuthorsResultEdgeType { - node: Author! - cursor: String! -} -type SearchAuthorsResultPageInfo { - hasNextPage: Boolean - hasPreviousPage: Boolean - startCursor: String - endCursor: String - query: SearchAuthorsResultPageInfoQuery! -} -type SearchAuthorsResultPageInfoQuery { - name: String! -} -input SearchBooksQuery { - title: String! -} -type SearchBooksResult { - aggregate: SearchBooksResultAggregate! - pageInfo: SearchBooksResultPageInfo! - edges: [SearchBooksResultEdgeType!]! -} -type SearchBooksResultAggregate { - count: Int! -} -type SearchBooksResultEdgeType { - node: Book! - cursor: String! -} -type SearchBooksResultPageInfo { - hasNextPage: Boolean - hasPreviousPage: Boolean - startCursor: String - endCursor: String - query: SearchBooksResultPageInfoQuery! -} -type SearchBooksResultPageInfoQuery { - title: String! -} -input SearchMixedQuery { - query: String -} -type SearchMixedResult { - aggregate: SearchMixedResultAggregate! - pageInfo: SearchMixedResultPageInfo! - edges: [SearchMixedResultEdgeType!]! -} -type SearchMixedResultAggregate { - count: Int! -} -type SearchMixedResultEdgeType { - node: SearchMixedUnion! - cursor: String! -} -type SearchMixedResultPageInfo { - hasNextPage: Boolean - hasPreviousPage: Boolean - startCursor: String - endCursor: String - query: SearchMixedResultPageInfoQuery! -} -type SearchMixedResultPageInfoQuery { - query: String -} -union SearchMixedUnion = Book | Author | Series -input SearchSeriesQuery { - title: String! -} -type SearchSeriesResult { - aggregate: SearchSeriesResultAggregate! - pageInfo: SearchSeriesResultPageInfo! - edges: [SearchSeriesResultEdgeType!]! -} -type SearchSeriesResultAggregate { - count: Int! -} -type SearchSeriesResultEdgeType { - node: Series! - cursor: String! -} -type SearchSeriesResultPageInfo { - hasNextPage: Boolean - hasPreviousPage: Boolean - startCursor: String - endCursor: String - query: SearchSeriesResultPageInfoQuery! -} -type SearchSeriesResultPageInfoQuery { - title: String! -} -type User { - id: ID! - uniqueName: String! - displayName: String! - picture: String! - readingBooks(skip: Int = 0, limit: Int = 0, orderBy: UsersReadingBooksArgsOrderBy = {updatedAt: DESC}): UsersReadingBooksReturn! - hasBooks(skip: Int = 0, limit: Int = 0, orderBy: UsersHasBooksArgsOrderBy = {updatedAt: DESC}): UsersHasBooksReturn! - wishesReadBooks(skip: Int = 0, limit: Int = 0, orderBy: UsersWishesReadBooksArgsOrderBy = {updatedAt: DESC}): UsersWishReadBooksReturn! - stackedBooks(skip: Int = 0, limit: Int = 0, orderBy: UsersStackedBooksArgsOrderBy = {updatedAt: DESC}): UsersStackedBooksReturn! - records(skip: Int = 0, limit: Int = 0, orderBy: UsersRecordsArgsOrderBy = {readAt: DESC}): UsersRecordsReturn! - readBooks(skip: Int = 0, limit: Int = 0, orderBy: UsersReadBooksArgsOrderBy = {title: ASC}): UsersReadBooksReturn! -} -type Query { - book(id: ID!): Book! - allBooks: [Book!]! - author(id: ID!): Author! - allAuthors: [Author!]! - series(id: ID!): Series! - allSeries: [Series!]! - publisher(id: ID!): Publisher! - allPublishers: [Publisher!]! - label(id: ID!): Label! - allLabels: [Label!]! - recordById(id: ID!): Record! - searchBooks(after: String, first: Int, before: String, last: Int, query: SearchBooksQuery!): SearchBooksResult! - searchAuthors(after: String, first: Int, before: String, last: Int, query: SearchAuthorsQuery!): SearchAuthorsResult! - searchSeries(after: String, first: Int, before: String, last: Int, query: SearchSeriesQuery!): SearchSeriesResult! - searchMixed(after: String, first: Int, before: String, last: Int, query: SearchMixedQuery!): SearchMixedResult! - user(id: String, uniqueName: String): User! - allUsers: [User!]! - currentUser: User! -} -type Mutation { - createBook(title: String!, subtitle: String, isbn: String): Book! - createAuthor(name: String!): Author! - writedBook(bookId: ID!, authorId: ID!, roles: [AuthorRole!]): Writing! - connectNextBook(previousId: ID!, nextId: ID!): NextBookConnection! - createSeries(bookId: ID!, title: String!): SeriesPart! - createPublisher(name: String!): Publisher! - publishedBook(bookId: ID!, publisherId: ID!): Publication! - createLabel(publisherId: ID!, name: String!): Label! - labeledBook(bookId: ID!, labelId: ID!): Labeling! - setReadingBook(userId: ID!, bookId: ID!, reading: Boolean!): ReadingBookRecord! - setHaveBook(userId: ID!, bookId: ID!, have: Boolean!): HaveBookRecord! - setWishReadBook(userId: ID!, bookId: ID!, wish: Boolean!): WishReadBookRecord! - createUser(uniqueName: String!, displayName: String!, picture: String!): User! -} \ No newline at end of file diff --git a/src/graphql/api-public/graphql-request.ts b/src/graphql/api-public/graphql-request.ts deleted file mode 100644 index d9124e2..0000000 --- a/src/graphql/api-public/graphql-request.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {GraphQLClient} from 'graphql-request'; -import {getSdk} from '~/graphql/api-public/codegen/graphql-request'; -import {PUBLIC_API_ACCESS_TOKEN, PUBLIC_API_ENDPOINT} from '~/lib/env'; - -export const graphqlSdk = getSdk( - new GraphQLClient(PUBLIC_API_ENDPOINT, { - headers: {Authorization: `Bearer ${PUBLIC_API_ACCESS_TOKEN}`}, - }), -); diff --git a/src/graphql/apollo.tsx b/src/graphql/apollo.tsx new file mode 100644 index 0000000..66f394b --- /dev/null +++ b/src/graphql/apollo.tsx @@ -0,0 +1,26 @@ +import { + ApolloClient, + ApolloLink, + createHttpLink, + InMemoryCache, +} from '@apollo/client'; +import {ApolloProvider} from '@apollo/react-hooks'; +import React from 'react'; +import {API_GRAPHQL_ENDPOINT} from '~/configs/api'; + +export const ConfiguredApolloProvider: React.FC = ({children}) => { + const httpLink = createHttpLink({ + uri: API_GRAPHQL_ENDPOINT, + credentials: 'include', + }); + + const client = new ApolloClient({ + connectToDevTools: process.browser, + ssrMode: !process.browser, + link: ApolloLink.from([httpLink]), + cache: new InMemoryCache(), + }); + + return {children}; +}; +export * from './codegen/apollo'; diff --git a/src/graphql/apollo/CurrentUserPage.graphql b/src/graphql/apollo/CurrentUserPage.graphql new file mode 100644 index 0000000..c5750c2 --- /dev/null +++ b/src/graphql/apollo/CurrentUserPage.graphql @@ -0,0 +1,57 @@ +query CurrentUserPage { + currentUser { + userName: uniqueName + displayName + picture + readBooks { + count: totalCount + } + records(first: 5) { + count: totalCount + pageInfo { + hasNextPage + } + edges { + node { + id + readAt + user { + displayName + userName: uniqueName + picture + } + book { + id + title + subtitle + cover + } + } + } + } + readingBooks(first: 5) { + count: totalCount + pageInfo { + hasNextPage + } + edges { + node { + book { + id + title + cover + } + } + } + } + wishBooks { + count: totalCount + } + haveBooks { + count: totalCount + } + stackedBooks { + count: totalCount + } + } +} diff --git a/src/graphql/api-authenticated/apollo/GetCurrentUser.graphql b/src/graphql/apollo/GetCurrentUser.graphql similarity index 85% rename from src/graphql/api-authenticated/apollo/GetCurrentUser.graphql rename to src/graphql/apollo/GetCurrentUser.graphql index 2e4f2c9..739ecda 100644 --- a/src/graphql/api-authenticated/apollo/GetCurrentUser.graphql +++ b/src/graphql/apollo/GetCurrentUser.graphql @@ -1,8 +1,8 @@ query GetCurrentUser { currentUser { - id userName: uniqueName displayName picture + initialized } } diff --git a/src/graphql/graphql-request.ts b/src/graphql/graphql-request.ts new file mode 100644 index 0000000..8846ddc --- /dev/null +++ b/src/graphql/graphql-request.ts @@ -0,0 +1,6 @@ +import {GraphQLClient} from 'graphql-request'; +import {API_GRAPHQL_ENDPOINT} from '~/configs/api'; +import {getSdk} from '~/graphql/codegen/graphql-request'; + +export const graphqlSdk = getSdk(new GraphQLClient(API_GRAPHQL_ENDPOINT)); +export * from './codegen/graphql-request'; diff --git a/src/graphql/api-public/graphql-request/AuthorPage.graphql b/src/graphql/graphql-request/AuthorPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/AuthorPage.graphql rename to src/graphql/graphql-request/AuthorPage.graphql diff --git a/src/graphql/api-public/graphql-request/BookPage.graphql b/src/graphql/graphql-request/BookPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/BookPage.graphql rename to src/graphql/graphql-request/BookPage.graphql diff --git a/src/graphql/api-public/graphql-request/PublisherPage.graphql b/src/graphql/graphql-request/PublisherPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/PublisherPage.graphql rename to src/graphql/graphql-request/PublisherPage.graphql diff --git a/src/graphql/api-public/graphql-request/RecordPage.graphql b/src/graphql/graphql-request/RecordPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/RecordPage.graphql rename to src/graphql/graphql-request/RecordPage.graphql diff --git a/src/graphql/api-public/graphql-request/SeriesPage.graphql b/src/graphql/graphql-request/SeriesPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/SeriesPage.graphql rename to src/graphql/graphql-request/SeriesPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserHaveBooksPage.graphql b/src/graphql/graphql-request/UserHaveBooksPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserHaveBooksPage.graphql rename to src/graphql/graphql-request/UserHaveBooksPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserPage.graphql b/src/graphql/graphql-request/UserPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserPage.graphql rename to src/graphql/graphql-request/UserPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserReadBooksPage.graphql b/src/graphql/graphql-request/UserReadBooksPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserReadBooksPage.graphql rename to src/graphql/graphql-request/UserReadBooksPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserReadingBooksPage.graphql b/src/graphql/graphql-request/UserReadingBooksPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserReadingBooksPage.graphql rename to src/graphql/graphql-request/UserReadingBooksPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserStackedBooksPage.graphql b/src/graphql/graphql-request/UserStackedBooksPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserStackedBooksPage.graphql rename to src/graphql/graphql-request/UserStackedBooksPage.graphql diff --git a/src/graphql/api-public/graphql-request/UserWishBooksPage.graphql b/src/graphql/graphql-request/UserWishBooksPage.graphql similarity index 100% rename from src/graphql/api-public/graphql-request/UserWishBooksPage.graphql rename to src/graphql/graphql-request/UserWishBooksPage.graphql diff --git a/src/graphql/api-public/schema.graphql b/src/graphql/schema.graphql similarity index 99% rename from src/graphql/api-public/schema.graphql rename to src/graphql/schema.graphql index 6ff46a2..c01b96b 100644 --- a/src/graphql/api-public/schema.graphql +++ b/src/graphql/schema.graphql @@ -1,18 +1,6 @@ schema { query: Query } -type User { - id: ID! - uniqueName: String! - displayName: String! - picture: String! - records(after: String, first: Int, before: String, last: Int, orderBy: UserRecordsArgsOrderBy = {readAt: DESC}): UserRecordConnection! - haveBooks(after: String, first: Int, before: String, last: Int, orderBy: UserHaveBooksArgsOrderBy = {updatedAt: DESC}): UserHaveBookConnection! - readBooks(after: String, first: Int, before: String, last: Int, orderBy: UserReadBooksArgsOrderBy = {title: ASC}): UserReadBookConnection! - readingBooks(after: String, first: Int, before: String, last: Int, orderBy: UserReadingBooksArgsOrderBy = {updatedAt: DESC}): UserReadingBookConnection! - stackedBooks(after: String, first: Int, before: String, last: Int, orderBy: UserStackedBooksArgsOrderBy = {updatedAt: DESC}): UserStackedBookConnection! - wishBooks(after: String, first: Int, before: String, last: Int, orderBy: UserWishBooksArgsOrderBy = {updatedAt: DESC}): UserWishBooksConnection! -} type Author { id: ID! name: String! @@ -85,6 +73,8 @@ type BookPreviousBooksReturnType { input BookWrittenByArgsOrderBy { name: OrderBy } +"""A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.""" +scalar DateTime type Label { id: ID! name: String! @@ -104,6 +94,8 @@ type LabelLabeledBooksReturnType { hasPrevious: Boolean! hasNext: Boolean! } +"""A local date string (i.e., with no associated timezone) in `YYYY-MM-DD` format, e.g. `2020-01-01`.""" +scalar LocalDate type NextBookConnection { previous: Book! next: Book! @@ -112,6 +104,12 @@ enum OrderBy { ASC DESC } +type PageInfo { + startCursor: String + endCursor: String + hasPreviousPage: Boolean + hasNextPage: Boolean +} type Publication { book: Book! publisher: Publisher! @@ -144,6 +142,23 @@ type PublisherPublishedBooksReturnType { hasPrevious: Boolean! hasNext: Boolean! } +type Query { + user(uniqueName: String!): User! + allUsers: [User!]! + book(id: ID!): Book! + allBooks: [Book!]! + author(id: ID!): Author! + allAuthors: [Author!]! + series(id: ID!): Series! + allSeries: [Series!]! + publisher(id: ID!): Publisher! + allPublishers: [Publisher!]! + label(id: ID!): Label! + allLabels: [Label!]! + record(id: ID!): UserRecord! + allRecords: [UserRecord!]! + currentUser: User! +} type Series { id: ID! title: String! @@ -178,20 +193,18 @@ type SeriesSeriesBooksReturnType { hasPrevious: Boolean! hasNext: Boolean! } -type Writing { - roles: [AuthorRole!]! - book: Book! - author: Author! -} -"""A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.""" -scalar DateTime -"""A local date string (i.e., with no associated timezone) in `YYYY-MM-DD` format, e.g. `2020-01-01`.""" -scalar LocalDate -type PageInfo { - startCursor: String - endCursor: String - hasPreviousPage: Boolean - hasNextPage: Boolean +type User { + id: ID! + uniqueName: String! + displayName: String! + initialized: Boolean! + picture: String! + records(after: String, first: Int, before: String, last: Int, orderBy: UserRecordsArgsOrderBy = {readAt: DESC}): UserRecordConnection! + haveBooks(after: String, first: Int, before: String, last: Int, orderBy: UserHaveBooksArgsOrderBy = {updatedAt: DESC}): UserHaveBookConnection! + readBooks(after: String, first: Int, before: String, last: Int, orderBy: UserReadBooksArgsOrderBy = {title: ASC}): UserReadBookConnection! + readingBooks(after: String, first: Int, before: String, last: Int, orderBy: UserReadingBooksArgsOrderBy = {updatedAt: DESC}): UserReadingBookConnection! + stackedBooks(after: String, first: Int, before: String, last: Int, orderBy: UserStackedBooksArgsOrderBy = {updatedAt: DESC}): UserStackedBookConnection! + wishBooks(after: String, first: Int, before: String, last: Int, orderBy: UserWishBooksArgsOrderBy = {updatedAt: DESC}): UserWishBooksConnection! } type UserHaveBook { updatedAt: DateTime! @@ -294,19 +307,8 @@ type UserWishBooksConnection { pageInfo: PageInfo! totalCount: Int! } -type Query { - user(uniqueName: String!): User! - allUsers: [User!]! - book(id: ID!): Book! - allBooks: [Book!]! - author(id: ID!): Author! - allAuthors: [Author!]! - series(id: ID!): Series! - allSeries: [Series!]! - publisher(id: ID!): Publisher! - allPublishers: [Publisher!]! - label(id: ID!): Label! - allLabels: [Label!]! - record(id: ID!): UserRecord! - allRecords: [UserRecord!]! +type Writing { + roles: [AuthorRole!]! + book: Book! + author: Author! } \ No newline at end of file diff --git a/src/hoc/withComponentAuthenticated.tsx b/src/hoc/withComponentAuthenticated.tsx new file mode 100644 index 0000000..feea305 --- /dev/null +++ b/src/hoc/withComponentAuthenticated.tsx @@ -0,0 +1,12 @@ +import dynamic from 'next/dynamic'; +import React from 'react'; +import {ThirdPartyAuth} from 'supertokens-auth-react/recipe/thirdparty'; + +export function withComponentAuthenticated

(Component: React.FC

) { + const WithComponentAuthenticated = (props: P) => ( + + + + ); + return dynamic(async () => WithComponentAuthenticated, {ssr: false}); +} diff --git a/src/hoc/withComponentRegistered.tsx b/src/hoc/withComponentRegistered.tsx new file mode 100644 index 0000000..490f375 --- /dev/null +++ b/src/hoc/withComponentRegistered.tsx @@ -0,0 +1,12 @@ +import dynamic from 'next/dynamic'; +import React from 'react'; +import {useAuth} from '~/hooks/useAuth'; + +export function withComponentRegistered

(Component: React.FC

) { + const WithComponentRegistered = (props: P) => { + const auth = useAuth(); + if ('currentUser' in auth) return ; + return <>; + }; + return dynamic(async () => WithComponentRegistered, {ssr: false}); +} diff --git a/src/hoc/withPageAuthenticated.tsx b/src/hoc/withPageAuthenticated.tsx new file mode 100644 index 0000000..460571d --- /dev/null +++ b/src/hoc/withPageAuthenticated.tsx @@ -0,0 +1,15 @@ +import {NextPage} from 'next'; +import dynamic from 'next/dynamic'; +import React from 'react'; +import {ThirdPartyAuth} from 'supertokens-auth-react/recipe/thirdparty'; + +export function withPageAuthenticated

(Page: NextPage

) { + const WithProtectedPage = (props: P) => { + return ( + + + + ); + }; + return dynamic(async () => WithProtectedPage, {ssr: false}); +} diff --git a/src/hoc/withPageRegistered.tsx b/src/hoc/withPageRegistered.tsx new file mode 100644 index 0000000..015508e --- /dev/null +++ b/src/hoc/withPageRegistered.tsx @@ -0,0 +1,17 @@ +import {NextPage} from 'next'; +import dynamic from 'next/dynamic'; +import {useRouter} from 'next/router'; +import React from 'react'; +import {useAuth} from '~/hooks/useAuth'; + +export function withPageRegistered

(Page: NextPage

) { + const WithPageRegistered = (props: P) => { + const auth = useAuth(); + const router = useRouter(); + if ('registered' in auth && !auth.registered) + router.push('/settings/profile'); + if ('currentUser' in auth) return ; + return <>; + }; + return dynamic(async () => WithPageRegistered, {ssr: false}); +} diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx new file mode 100644 index 0000000..499f1c7 --- /dev/null +++ b/src/hooks/useAuth.tsx @@ -0,0 +1,80 @@ +import {useEffect} from 'react'; +import {useEffectOnce} from 'react-use'; +import {useRecoilValue, useSetRecoilState} from 'recoil'; +import {useSessionContext} from 'supertokens-auth-react/recipe/session'; +import {useGetCurrentUserLazyQuery} from '~/graphql/apollo'; +import { + CurrentUser, + stateCurrentUser, + stateCurrentUserRegistered, +} from '~/states/CurrentUser'; + +export type AuthState = + | { + signedIn: false; + } + | { + signedIn: true; + loading: true; + } + | { + signedIn: true; + loading: false; + registered: false; + } + | { + signedIn: true; + loading: false; + registered: true; + currentUser: CurrentUser; + }; + +export const useAuth = (): AuthState => { + const {doesSessionExist: signedIn} = useSessionContext(); + const [loadCurrentUser, {data, loading}] = useGetCurrentUserLazyQuery(); + + const currentUser = useRecoilValue(stateCurrentUser); + const setCurrentUser = useSetRecoilState(stateCurrentUser); + + const registered = useRecoilValue(stateCurrentUserRegistered); + const setRegistered = useSetRecoilState(stateCurrentUserRegistered); + + useEffectOnce(() => { + if (!currentUser && signedIn) loadCurrentUser(); + }); + + useEffect(() => { + if (data?.currentUser && !data.currentUser.initialized) { + setRegistered(false); + } else if (data?.currentUser && data.currentUser.initialized) { + setRegistered(true); + setCurrentUser({ + userName: data.currentUser.userName, + displayName: data.currentUser.displayName, + picture: data.currentUser.picture, + }); + } + }, [data, setCurrentUser, setRegistered]); + + if (signedIn && !loading && registered && currentUser) + return { + signedIn: true, + loading: false, + registered, + currentUser, + }; + if (signedIn && !loading && !registered) + return { + signedIn: true, + loading: false, + registered: false, + }; + if (signedIn && loading) + return { + signedIn: true, + loading: true, + }; + return { + signedIn: false, + }; +}; diff --git a/src/hooks/useSignOut.ts b/src/hooks/useSignOut.ts new file mode 100644 index 0000000..3c27368 --- /dev/null +++ b/src/hooks/useSignOut.ts @@ -0,0 +1,19 @@ +import {useRouter} from 'next/router'; +import {useSetRecoilState} from 'recoil'; +import {signOut} from 'supertokens-auth-react/recipe/thirdparty'; +import {stateCurrentUser} from '~/states/CurrentUser'; + +export const useSignOut = (): (() => Promise) => { + const router = useRouter(); + const setCurrentUser = useSetRecoilState(stateCurrentUser); + + return async () => { + await signOut(); + + // eslint-disable-next-line unicorn/no-useless-undefined + setCurrentUser(undefined); + + router.push('/'); + router.reload(); + }; +}; diff --git a/src/components/layout/AppLayout/Layout.tsx b/src/layouts/AppLayout/Component.tsx similarity index 100% rename from src/components/layout/AppLayout/Layout.tsx rename to src/layouts/AppLayout/Component.tsx diff --git a/src/layouts/AppLayout/index.ts b/src/layouts/AppLayout/index.ts new file mode 100644 index 0000000..9d12344 --- /dev/null +++ b/src/layouts/AppLayout/index.ts @@ -0,0 +1,2 @@ +export {Component as AppLayout} from './Component'; +export type {ComponentProps as AppLayoutProps} from './Component'; diff --git a/src/components/layout/PageLayout/Layout.tsx b/src/layouts/PageLayout/Component.tsx similarity index 51% rename from src/components/layout/PageLayout/Layout.tsx rename to src/layouts/PageLayout/Component.tsx index 07842e1..04a23c0 100644 --- a/src/components/layout/PageLayout/Layout.tsx +++ b/src/layouts/PageLayout/Component.tsx @@ -1,11 +1,11 @@ import clsx from 'clsx'; import React from 'react'; -export type LayoutProps = { +export type ComponentProps = { className?: string; }; -export const Layout: React.FC = ({className, children}) => { +export const Component: React.FC = ({className, children}) => { return

{children}
; }; -Layout.displayName = 'PageLayout'; +Component.displayName = 'PageLayout'; diff --git a/src/layouts/PageLayout/index.ts b/src/layouts/PageLayout/index.ts new file mode 100644 index 0000000..b622ab5 --- /dev/null +++ b/src/layouts/PageLayout/index.ts @@ -0,0 +1,2 @@ +export {Component as PageLayout} from './Component'; +export type {ComponentProps as PageLayoutProps} from './Component'; diff --git a/src/lib/ApolloProvider.tsx b/src/lib/ApolloProvider.tsx deleted file mode 100644 index 01795c9..0000000 --- a/src/lib/ApolloProvider.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { - ApolloClient, - ApolloLink, - createHttpLink, - InMemoryCache, -} from '@apollo/client'; -import {setContext} from '@apollo/client/link/context'; -import {ApolloProvider} from '@apollo/react-hooks'; -import React from 'react'; -import { - AUTHENTICATED_API_ENDPOINT, - AUTH_SERVER_TOKEN_ENDPOINT, -} from '~/lib/env'; - -export const getToken = async (): Promise => { - return fetch(AUTH_SERVER_TOKEN_ENDPOINT, { - credentials: 'include', - }) - .then((res) => { - return res.status >= 400 ? undefined : res.text(); - }) - .catch(() => {}); -}; - -export const ConfiguredApolloProvider: React.FC = ({children}) => { - const httpLink = createHttpLink({ - uri: AUTHENTICATED_API_ENDPOINT, - }); - - const authLink = setContext(async (_, {headers}) => { - const token = await getToken(); - return { - headers: { - ...headers, - authorization: token ? `Bearer ${token}` : '', - }, - }; - }); - - const client = new ApolloClient({ - connectToDevTools: process.browser, - ssrMode: !process.browser, - link: ApolloLink.from([authLink, httpLink]), - cache: new InMemoryCache(), - }); - - return {children}; -}; diff --git a/src/lib/AuthorRole.ts b/src/lib/AuthorRole.ts index 8f9eb61..3a846d6 100644 --- a/src/lib/AuthorRole.ts +++ b/src/lib/AuthorRole.ts @@ -1,6 +1,6 @@ -import {AuthorRole} from '~/graphql/api-public/codegen/graphql-request'; +import {AuthorRole} from '~/graphql/codegen/graphql-request'; -export {AuthorRole} from '~/graphql/api-public/codegen/graphql-request'; +export {AuthorRole} from '~/graphql/codegen/graphql-request'; export const rolesPriorities: Record = { [AuthorRole.Author]: 0, diff --git a/src/lib/CurrentUser.tsx b/src/lib/CurrentUser.tsx deleted file mode 100644 index 967eb7f..0000000 --- a/src/lib/CurrentUser.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React, {useEffect} from 'react'; -import {useEffectOnce} from 'react-use'; -import {useRecoilValue, useSetRecoilState} from 'recoil'; -import {useGetCurrentUserLazyQuery} from '~/graphql/api-authenticated/codegen/apollo'; -import {currentUserLoadingState, currentUserState} from '~/states/CurrentUser'; - -export const CurrentUser: React.FC = () => { - const [getCurrentUser, {data, loading}] = useGetCurrentUserLazyQuery(); - const currentUser = useRecoilValue(currentUserState); - const setCurrentUser = useSetRecoilState(currentUserState); - const setCurrentUserLoading = useSetRecoilState(currentUserLoadingState); - - useEffect(() => { - if (!loading) setCurrentUserLoading(loading); - }); - - useEffect(() => { - if (data?.currentUser) setCurrentUser(data.currentUser); - }); - - useEffectOnce(() => { - if (!currentUser) { - setCurrentUserLoading(true); - setCurrentUser(undefined); // eslint-disable-line unicorn/no-useless-undefined - getCurrentUser(); - } - }); - - return <>; -}; diff --git a/src/lib/Links.ts b/src/lib/Links.ts deleted file mode 100644 index 68fd3b9..0000000 --- a/src/lib/Links.ts +++ /dev/null @@ -1,95 +0,0 @@ -export type Links = { - '/users/[username]/have': { - pathname: '/users/[username]/have'; - query: {username: string}; - }; - '/users/[username]/have/[number]': { - pathname: '/users/[username]/have/[number]'; - query: {username: string; number: string}; - }; - - '/users/[username]/read': { - pathname: '/users/[username]/read'; - query: {username: string}; - }; - '/users/[username]/read/[number]': { - pathname: '/users/[username]/read/[number]'; - query: {username: string; number: string}; - }; - - '/users/[username]/reading': { - pathname: '/users/[username]/reading'; - query: {username: string}; - }; - '/users/[username]/reading/[number]': { - pathname: '/users/[username]/reading/[number]'; - query: {username: string; number: string}; - }; - - '/users/[username]/wish': { - pathname: '/users/[username]/wish'; - query: {username: string}; - }; - '/users/[username]/wish/[number]': { - pathname: '/users/[username]/wish/[number]'; - query: {username: string; number: string}; - }; - - '/users/[username]/stacked': { - pathname: '/users/[username]/stacked'; - query: {username: string}; - }; - '/users/[username]/stacked/[number]': { - pathname: '/users/[username]/stacked/[number]'; - query: {username: string; number: string}; - }; -}; - -export const linkFactories: { - [key in keyof Links]: (query: Links[key]['query']) => Links[key]; -} = { - '/users/[username]/have': (query) => ({ - pathname: '/users/[username]/have' as const, - query, - }), - '/users/[username]/have/[number]': (query) => ({ - pathname: '/users/[username]/have/[number]' as const, - query, - }), - - '/users/[username]/read': (query) => ({ - pathname: '/users/[username]/read' as const, - query, - }), - '/users/[username]/read/[number]': (query) => ({ - pathname: '/users/[username]/read/[number]' as const, - query, - }), - - '/users/[username]/reading': (query) => ({ - pathname: '/users/[username]/reading' as const, - query, - }), - '/users/[username]/reading/[number]': (query) => ({ - pathname: '/users/[username]/reading/[number]' as const, - query, - }), - - '/users/[username]/wish': (query) => ({ - pathname: '/users/[username]/wish' as const, - query, - }), - '/users/[username]/wish/[number]': (query) => ({ - pathname: '/users/[username]/wish/[number]' as const, - query, - }), - - '/users/[username]/stacked': (query) => ({ - pathname: '/users/[username]/stacked' as const, - query, - }), - '/users/[username]/stacked/[number]': (query) => ({ - pathname: '/users/[username]/stacked/[number]' as const, - query, - }), -}; diff --git a/src/lib/env.ts b/src/lib/env.ts deleted file mode 100644 index dd578e1..0000000 --- a/src/lib/env.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* eslint-disable no-process-env */ - -export const SESSION_NAME = process.env.SESSION_NAME!; - -export const PUBLIC_API_ENDPOINT = process.env.PUBLIC_API_ENDPOINT!; -export const PUBLIC_API_ACCESS_TOKEN = process.env.PUBLIC_API_ACCESS_TOKEN!; - -export const AUTHENTICATED_API_ENDPOINT = process.env - .AUTHENTICATED_API_ENDPOINT!; - -export const AUTH_SERVER_ENDPOINT = process.env.AUTH_SERVER_ENDPOINT!; -export const AUTH_SERVER_TOKEN_ENDPOINT = new URL( - '/token', - AUTH_SERVER_ENDPOINT, -).toString(); -export const AUTH_SERVER_LOGIN_ENDPOINT = new URL( - '/login', - AUTH_SERVER_ENDPOINT, -).toString(); diff --git a/src/lib/useCurrentUser.ts b/src/lib/useCurrentUser.ts deleted file mode 100644 index 1d9bb93..0000000 --- a/src/lib/useCurrentUser.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {useRecoilValue} from 'recoil'; -import {currentUserLoadingState, currentUserState} from '~/states/CurrentUser'; - -export function useCurrentUser() { - const currentUser = useRecoilValue(currentUserState); - const isLoading = useRecoilValue(currentUserLoadingState); - - return { - currentUser, - isLoading, - }; -} diff --git a/src/lib/withPageLoggedIn.tsx b/src/lib/withPageLoggedIn.tsx deleted file mode 100644 index 372046e..0000000 --- a/src/lib/withPageLoggedIn.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import {NextPage} from 'next'; -import {useRouter} from 'next/router'; -import React from 'react'; -import {LoadingPage} from '~/templates/Loading'; -import {useCurrentUser} from './useCurrentUser'; - -export function withPageLoggedIn( - PageComponent: NextPage, - LoadingPageComponent: React.FC = LoadingPage, -) { - const WithPageLoggedIn = () => { - const {currentUser, isLoading} = useCurrentUser(); - const router = useRouter(); - - if (!isLoading && !currentUser) router.push('/login'); - if (currentUser) return ; - return ; - }; - - return WithPageLoggedIn; -} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index d57755d..05b4851 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,13 +1,17 @@ import {AppProps} from 'next/dist/next-server/lib/router/router'; import React from 'react'; import {RecoilRoot} from 'recoil'; +import SuperTokensReact from 'supertokens-auth-react'; import 'tailwindcss/tailwind.css'; -import {AppLayout} from '~/components/layout/AppLayout'; +import {supertokensFrontendConfig} from '~/configs/supertokens'; +import {ConfiguredApolloProvider} from '~/graphql/apollo'; import {Configured18nextProvider} from '~/i18n'; -import {ConfiguredApolloProvider} from '~/lib/ApolloProvider'; -import {CurrentUser} from '~/lib/CurrentUser'; +import {AppLayout} from '~/layouts/AppLayout'; import '~/styles/index.css'; +if (typeof window !== 'undefined') { + SuperTokensReact.init(supertokensFrontendConfig); +} export const App: React.FC = ({ Component: PageComponent, pageProps, @@ -16,7 +20,6 @@ export const App: React.FC = ({ - diff --git a/src/pages/api/auth/login.ts b/src/pages/api/auth/login.ts deleted file mode 100644 index 8626b82..0000000 --- a/src/pages/api/auth/login.ts +++ /dev/null @@ -1,20 +0,0 @@ -import fetch from 'isomorphic-unfetch'; -import {NextApiHandler} from 'next'; -import {AUTH_SERVER_LOGIN_ENDPOINT} from '~/lib/env'; - -const ApiHandler: NextApiHandler = async (req, res) => { - const result = await fetch(AUTH_SERVER_LOGIN_ENDPOINT, { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: req.body, - }); - if (result.status >= 400) { - res.status(result.status); - res.end(); - } else { - const setCookie = result.headers.get('set-cookie'); - if (setCookie) res.setHeader('set-cookie', setCookie); - res.redirect('/'); - } -}; -export default ApiHandler; diff --git a/src/pages/api/auth/logout.ts b/src/pages/api/auth/logout.ts deleted file mode 100644 index f4d2e1b..0000000 --- a/src/pages/api/auth/logout.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {NextApiHandler} from 'next'; -import {destroyCookie} from 'nookies'; -import {SESSION_NAME} from '~/lib/env'; - -const ApiHandler: NextApiHandler = async (req, res) => { - destroyCookie({res}, SESSION_NAME, {path: '/'}); - res.redirect('/'); -}; -export default ApiHandler; diff --git a/src/pages/auth/[[...path]].tsx b/src/pages/auth/[[...path]].tsx new file mode 100644 index 0000000..525f00e --- /dev/null +++ b/src/pages/auth/[[...path]].tsx @@ -0,0 +1,17 @@ +import dynamic from 'next/dynamic'; +import React, {useEffect} from 'react'; +import SuperTokens from 'supertokens-auth-react'; +import {redirectToAuth} from 'supertokens-auth-react/recipe/thirdparty'; + +const SuperTokensComponentNoSSR = dynamic( + async () => SuperTokens.getRoutingComponent as () => JSX.Element, + {ssr: false}, +); + +export default function Auth() { + useEffect(() => { + if (!SuperTokens.canHandleRoute()) redirectToAuth(); + }, []); + + return ; +} diff --git a/src/pages/authors/[id]/index.tsx b/src/pages/authors/[id]/index.tsx index 77ed96b..8ae8cfb 100644 --- a/src/pages/authors/[id]/index.tsx +++ b/src/pages/authors/[id]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {AuthorPage, AuthorPageProps, transform} from '~/templates/Author'; import {LoadingPage} from '~/templates/Loading'; diff --git a/src/pages/books/[id]/index.tsx b/src/pages/books/[id]/index.tsx index d6f6f3b..a09d55b 100644 --- a/src/pages/books/[id]/index.tsx +++ b/src/pages/books/[id]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {BookPage, BookPageProps, transform} from '~/templates/Book'; import {LoadingPage} from '~/templates/Loading'; diff --git a/src/pages/home.tsx b/src/pages/home.tsx new file mode 100644 index 0000000..9bb116f --- /dev/null +++ b/src/pages/home.tsx @@ -0,0 +1,16 @@ +import clsx from 'clsx'; +import React from 'react'; +import {useCurrentUserPageQuery} from '~/graphql/codegen/apollo'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; + +export function Page() { + const {data} = useCurrentUserPageQuery(); + + return ( +
+

Index

+
+ ); +} + +export default withPageAuthenticated(Page); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 38d8397..2867a7c 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,6 +1,12 @@ -import {NextPage} from 'next'; +import clsx from 'clsx'; import React from 'react'; -import {IndexPage} from '~/templates/Index'; -export const Page: NextPage = (props) => ; +export function Page() { + return ( +
+

Index

+
+ ); +} + export default Page; diff --git a/src/pages/login.tsx b/src/pages/login.tsx deleted file mode 100644 index 3774a5e..0000000 --- a/src/pages/login.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import {NextPage} from 'next'; -import {useRouter} from 'next/router'; -import React from 'react'; -import {useCurrentUser} from '~/lib/useCurrentUser'; -import {LoginPage} from '~/templates/Login'; - -export type UrlQuery = Record; - -export const Page: NextPage = (props) => { - const router = useRouter(); - const {currentUser} = useCurrentUser(); - - if (currentUser) router.push('/me'); - return ; -}; -export default Page; diff --git a/src/pages/me/have/index.tsx b/src/pages/me/have/index.tsx index 3300789..bc3825a 100644 --- a/src/pages/me/have/index.tsx +++ b/src/pages/me/have/index.tsx @@ -1,7 +1,10 @@ import {NextPage} from 'next'; import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; export const Page: NextPage = (props) => { return
; }; -export default Page; + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/me/index.tsx b/src/pages/me/index.tsx index 50c80e6..a664ef2 100644 --- a/src/pages/me/index.tsx +++ b/src/pages/me/index.tsx @@ -1,14 +1,20 @@ import {NextPage} from 'next'; import React from 'react'; -import {usePersonalUserPageQuery} from '~/graphql/api-authenticated/codegen/apollo'; -import {withPageLoggedIn} from '~/lib/withPageLoggedIn'; +import {useCurrentUserPageQuery} from '~/graphql/codegen/apollo'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; import {LoadingPage} from '~/templates/Loading'; import {PersonalUserPage, transform} from '~/templates/PersonalUser'; -export const Page: NextPage = (props) => { - const {data, loading, error} = usePersonalUserPageQuery(); - if (data) return ; +export const Page: NextPage = () => { + const {data, loading, error} = useCurrentUserPageQuery(); + + if (data) + return ( + + ); if (loading) return ; return
; }; -export default withPageLoggedIn(Page); + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/me/read/index.tsx b/src/pages/me/read/index.tsx index 3300789..bc3825a 100644 --- a/src/pages/me/read/index.tsx +++ b/src/pages/me/read/index.tsx @@ -1,7 +1,10 @@ import {NextPage} from 'next'; import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; export const Page: NextPage = (props) => { return
; }; -export default Page; + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/me/reading/index.tsx b/src/pages/me/reading/index.tsx index 3300789..bc3825a 100644 --- a/src/pages/me/reading/index.tsx +++ b/src/pages/me/reading/index.tsx @@ -1,7 +1,10 @@ import {NextPage} from 'next'; import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; export const Page: NextPage = (props) => { return
; }; -export default Page; + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/me/stacked/index.tsx b/src/pages/me/stacked/index.tsx index 3300789..bc3825a 100644 --- a/src/pages/me/stacked/index.tsx +++ b/src/pages/me/stacked/index.tsx @@ -1,7 +1,10 @@ import {NextPage} from 'next'; import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; export const Page: NextPage = (props) => { return
; }; -export default Page; + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/me/wish/index.tsx b/src/pages/me/wish/index.tsx index 3300789..bc3825a 100644 --- a/src/pages/me/wish/index.tsx +++ b/src/pages/me/wish/index.tsx @@ -1,7 +1,10 @@ import {NextPage} from 'next'; import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; +import {withPageRegistered} from '~/hoc/withPageRegistered'; export const Page: NextPage = (props) => { return
; }; -export default Page; + +export default withPageAuthenticated(withPageRegistered(Page)); diff --git a/src/pages/publishers/[id]/index.tsx b/src/pages/publishers/[id]/index.tsx index 7c862c0..22a4152 100644 --- a/src/pages/publishers/[id]/index.tsx +++ b/src/pages/publishers/[id]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { PublisherPage, diff --git a/src/pages/records/[id]/index.tsx b/src/pages/records/[id]/index.tsx index d115f2a..c4d237f 100644 --- a/src/pages/records/[id]/index.tsx +++ b/src/pages/records/[id]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { TemplateRecord, diff --git a/src/pages/settings.tsx b/src/pages/register.tsx similarity index 52% rename from src/pages/settings.tsx rename to src/pages/register.tsx index a6170cc..61a9ee1 100644 --- a/src/pages/settings.tsx +++ b/src/pages/register.tsx @@ -1,6 +1,6 @@ import {NextPage} from 'next'; import React from 'react'; -import {withPageLoggedIn} from '~/lib/withPageLoggedIn'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; export const Page: NextPage = (props) =>
; -export default withPageLoggedIn(Page); +export default withPageAuthenticated(Page); diff --git a/src/pages/series/[id]/index.tsx b/src/pages/series/[id]/index.tsx index c5489ae..5d5d9aa 100644 --- a/src/pages/series/[id]/index.tsx +++ b/src/pages/series/[id]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import {SeriesPage, SeriesPageProps, transform} from '~/templates/Series'; diff --git a/src/pages/settings/profile.tsx b/src/pages/settings/profile.tsx new file mode 100644 index 0000000..61a9ee1 --- /dev/null +++ b/src/pages/settings/profile.tsx @@ -0,0 +1,6 @@ +import {NextPage} from 'next'; +import React from 'react'; +import {withPageAuthenticated} from '~/hoc/withPageAuthenticated'; + +export const Page: NextPage = (props) =>
; +export default withPageAuthenticated(Page); diff --git a/src/pages/users/[username]/have/[number].tsx b/src/pages/users/[username]/have/[number].tsx index 95618b4..0858680 100644 --- a/src/pages/users/[username]/have/[number].tsx +++ b/src/pages/users/[username]/have/[number].tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { getPathsForNumbered, diff --git a/src/pages/users/[username]/have/index.tsx b/src/pages/users/[username]/have/index.tsx index d3dcb69..8713d76 100644 --- a/src/pages/users/[username]/have/index.tsx +++ b/src/pages/users/[username]/have/index.tsx @@ -1,5 +1,5 @@ import {GetStaticPaths} from 'next'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {getPathsForIndex, UrlQueryForIndexPage} from '~/templates/UserBooks'; import * as General from './[number]'; diff --git a/src/pages/users/[username]/index.tsx b/src/pages/users/[username]/index.tsx index e073329..edf385e 100644 --- a/src/pages/users/[username]/index.tsx +++ b/src/pages/users/[username]/index.tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import {transform, UserPage, UserPageProps} from '~/templates/User'; diff --git a/src/pages/users/[username]/read/[number].tsx b/src/pages/users/[username]/read/[number].tsx index b4cf2ef..5d5cbd1 100644 --- a/src/pages/users/[username]/read/[number].tsx +++ b/src/pages/users/[username]/read/[number].tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { getPathsForNumbered, diff --git a/src/pages/users/[username]/read/index.tsx b/src/pages/users/[username]/read/index.tsx index e97a6fa..04fa3d8 100644 --- a/src/pages/users/[username]/read/index.tsx +++ b/src/pages/users/[username]/read/index.tsx @@ -1,4 +1,4 @@ -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {getPathsForIndex, UrlQueryForIndexPage} from '~/templates/UserBooks'; import * as General from './[number]'; diff --git a/src/pages/users/[username]/reading/[number].tsx b/src/pages/users/[username]/reading/[number].tsx index 007bdc9..7b21171 100644 --- a/src/pages/users/[username]/reading/[number].tsx +++ b/src/pages/users/[username]/reading/[number].tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { getPathsForNumbered, diff --git a/src/pages/users/[username]/reading/index.tsx b/src/pages/users/[username]/reading/index.tsx index 2decc57..569e963 100644 --- a/src/pages/users/[username]/reading/index.tsx +++ b/src/pages/users/[username]/reading/index.tsx @@ -1,4 +1,4 @@ -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {getPathsForIndex, UrlQueryForIndexPage} from '~/templates/UserBooks'; import * as General from './[number]'; diff --git a/src/pages/users/[username]/stacked/[number].tsx b/src/pages/users/[username]/stacked/[number].tsx index 09e520c..958ae37 100644 --- a/src/pages/users/[username]/stacked/[number].tsx +++ b/src/pages/users/[username]/stacked/[number].tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { getPathsForNumbered, diff --git a/src/pages/users/[username]/stacked/index.tsx b/src/pages/users/[username]/stacked/index.tsx index 145a979..2018e53 100644 --- a/src/pages/users/[username]/stacked/index.tsx +++ b/src/pages/users/[username]/stacked/index.tsx @@ -1,4 +1,4 @@ -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {getPathsForIndex, UrlQueryForIndexPage} from '~/templates/UserBooks'; import * as General from './[number]'; diff --git a/src/pages/users/[username]/wish/[number].tsx b/src/pages/users/[username]/wish/[number].tsx index be85441..9f9b47e 100644 --- a/src/pages/users/[username]/wish/[number].tsx +++ b/src/pages/users/[username]/wish/[number].tsx @@ -6,7 +6,7 @@ import { } from 'next'; import {useRouter} from 'next/router'; import React from 'react'; -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {LoadingPage} from '~/templates/Loading'; import { getPathsForNumbered, diff --git a/src/pages/users/[username]/wish/index.tsx b/src/pages/users/[username]/wish/index.tsx index 4d2291a..0917284 100644 --- a/src/pages/users/[username]/wish/index.tsx +++ b/src/pages/users/[username]/wish/index.tsx @@ -1,4 +1,4 @@ -import {graphqlSdk} from '~/graphql/api-public/graphql-request'; +import {graphqlSdk} from '~/graphql/graphql-request'; import {getPathsForIndex, UrlQueryForIndexPage} from '~/templates/UserBooks'; import * as General from './[number]'; diff --git a/src/states/CurrentUser.tsx b/src/states/CurrentUser.tsx index 75fb956..97e9976 100644 --- a/src/states/CurrentUser.tsx +++ b/src/states/CurrentUser.tsx @@ -1,18 +1,17 @@ import {atom} from 'recoil'; export type CurrentUser = { - id: string; userName: string; displayName: string; picture: string; }; -export const currentUserState = atom({ +export const stateCurrentUser = atom({ key: 'CurrentUser', default: undefined, }); -export const currentUserLoadingState = atom({ - key: 'CurrentUserLoading', - default: true, +export const stateCurrentUserRegistered = atom({ + key: 'CurrentUserRegistered', + default: undefined, }); diff --git a/src/templates/Author/transform.ts b/src/templates/Author/transform.ts index 9a73d9d..d5d33b5 100644 --- a/src/templates/Author/transform.ts +++ b/src/templates/Author/transform.ts @@ -1,4 +1,4 @@ -import {AuthorPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {AuthorPageQuery} from '~/graphql/codegen/graphql-request'; import {avoidUndefined} from '~/lib/utils'; export type TransformedProps = { diff --git a/src/templates/Book/transform.ts b/src/templates/Book/transform.ts index 5fa5128..e45991e 100644 --- a/src/templates/Book/transform.ts +++ b/src/templates/Book/transform.ts @@ -1,4 +1,4 @@ -import {BookPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {BookPageQuery} from '~/graphql/codegen/graphql-request'; import { AuthorRole, authorsComparerByRoles, diff --git a/src/templates/Login/Container.tsx b/src/templates/Login/Container.tsx deleted file mode 100644 index c1dbc8d..0000000 --- a/src/templates/Login/Container.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import clsx from 'clsx'; -import Head from 'next/head'; -import React from 'react'; -import {useTranslation} from 'react-i18next'; -import {LoginInputForm} from '~/components/organisms/LoginInputForm'; - -export type ContainerProps = Record; -export const Container: React.FC = ({...props}) => { - const {t} = useTranslation(); - return ( -
- - {t('head:login_page')} - -
- -
-
- ); -}; -Container.displayName = 'LoginPage'; diff --git a/src/templates/Login/index.ts b/src/templates/Login/index.ts deleted file mode 100644 index ddb2ff0..0000000 --- a/src/templates/Login/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -// export {Component} from './Component'; -// export type {ComponentProps} from './Component'; -export {Container as LoginPage} from './Container'; -export type {ContainerProps as LoginPageProps} from './Container'; diff --git a/src/templates/PersonalUser/transform.ts b/src/templates/PersonalUser/transform.ts index cc4a129..fc50590 100644 --- a/src/templates/PersonalUser/transform.ts +++ b/src/templates/PersonalUser/transform.ts @@ -1,59 +1,60 @@ -import {PersonalUserPageQuery} from '~/graphql/api-authenticated/codegen/apollo'; +import {CurrentUserPageQuery} from '~/graphql/codegen/apollo'; import {avoidUndefined} from '~/lib/utils'; import {TransformedProps as UserPageTransformedProps} from '~/templates/User'; export type TransformedProps = UserPageTransformedProps; -export const transform = ({ - currentUser: { - userName, - displayName, - picture, - hasBooks, - readBooks, - readingBooks, - stackedBooks, - }, -}: PersonalUserPageQuery): TransformedProps => + +export const transform: ( + result: CurrentUserPageQuery, + variables: {recordSkip: number; recordLimit: number}, +) => TransformedProps = ({currentUser}, {recordLimit, recordSkip}) => avoidUndefined({ - userName, - displayName, - picture, - likedBooks: {count: 0, hasNext: false, books: []}, - records: {count: 0, hasNext: false, limit: 0, skip: 0, nodes: []}, - readBooks: { - count: 0, - hasNext: readBooks.hasNext, - books: readBooks.nodes.map(({id, title, cover}) => ({ - id, - title, - cover: cover || undefined, - })), + userName: currentUser.userName, + displayName: currentUser.displayName, + picture: currentUser.picture, + records: { + count: currentUser.records.count, + hasNext: Boolean(currentUser.records.pageInfo.hasNextPage), + limit: recordLimit, + skip: recordSkip, + nodes: currentUser.records.edges.map( + ({node: {id, readAt, book: recordBook, user: recordUser}}) => ({ + id, + readAt: readAt || undefined, + user: { + userName: recordUser.userName, + displayName: recordUser.displayName, + picture: recordUser.picture, + }, + book: { + id: recordBook.id, + title: recordBook.title, + subtitle: recordBook.subtitle || undefined, + cover: recordBook.cover || undefined, + }, + }), + ), }, readingBooks: { - count: 0, - hasNext: readingBooks.hasNext, - books: readingBooks.nodes.map(({book}) => ({ - ...book, + count: currentUser.readingBooks.count, + hasNext: Boolean(currentUser.readingBooks.pageInfo.hasNextPage), + books: currentUser.readingBooks.edges.map(({node: {book}}) => ({ + id: book.id, + title: book.title, cover: book.cover || undefined, })), }, + likedBooks: {count: 0, hasNext: false, books: []}, haveBooks: { - count: 0, - hasNext: hasBooks.hasNext, - books: hasBooks.nodes.map(({book}) => ({ - ...book, - cover: book.cover || undefined, - })), + count: currentUser.haveBooks.count, }, stackedBooks: { - count: 0, - hasNext: stackedBooks.hasNext, - books: stackedBooks.nodes.map(({book}) => ({ - ...book, - cover: book.cover || undefined, - })), + count: currentUser.stackedBooks.count, + }, + readBooks: { + count: currentUser.readBooks.count, }, wishBooks: { - count: 0, + count: currentUser.wishBooks.count, }, }); diff --git a/src/templates/Publisher/transform.ts b/src/templates/Publisher/transform.ts index d31c934..8139b83 100644 --- a/src/templates/Publisher/transform.ts +++ b/src/templates/Publisher/transform.ts @@ -1,4 +1,4 @@ -import {PublisherPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {PublisherPageQuery} from '~/graphql/codegen/graphql-request'; import {avoidUndefined} from '~/lib/utils'; export type TransformedProps = { diff --git a/src/templates/Record/transform.ts b/src/templates/Record/transform.ts index 5cb9dea..6dc6d79 100644 --- a/src/templates/Record/transform.ts +++ b/src/templates/Record/transform.ts @@ -1,4 +1,4 @@ -import {RecordPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {RecordPageQuery} from '~/graphql/codegen/graphql-request'; import {AuthorRole} from '~/lib/AuthorRole'; import {avoidUndefined} from '~/lib/utils'; diff --git a/src/templates/Series/transform.ts b/src/templates/Series/transform.ts index b8493d1..354770c 100644 --- a/src/templates/Series/transform.ts +++ b/src/templates/Series/transform.ts @@ -1,4 +1,4 @@ -import {SeriesPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {SeriesPageQuery} from '~/graphql/codegen/graphql-request'; import {avoidUndefined} from '~/lib/utils'; export type TransformedProps = { diff --git a/src/templates/User/transform.ts b/src/templates/User/transform.ts index 2ab5a87..d4507b0 100644 --- a/src/templates/User/transform.ts +++ b/src/templates/User/transform.ts @@ -1,4 +1,4 @@ -import {UserPageQuery} from '~/graphql/api-public/codegen/graphql-request'; +import {UserPageQuery} from '~/graphql/codegen/graphql-request'; import {avoidUndefined} from '~/lib/utils'; export type TransformedProps = { diff --git a/src/templates/UserBooks/transform.ts b/src/templates/UserBooks/transform.ts index 7aacdc8..6b81053 100644 --- a/src/templates/UserBooks/transform.ts +++ b/src/templates/UserBooks/transform.ts @@ -4,7 +4,7 @@ import { UserReadingBooksPageQuery, UserStackedBooksPageQuery, UserWishBooksPageQuery, -} from '~/graphql/api-public/codegen/graphql-request'; +} from '~/graphql/codegen/graphql-request'; import {avoidUndefined} from '~/lib/utils'; import {countPages} from './transform-pages'; diff --git a/yarn.lock b/yarn.lock index b686d23..d3346d3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -343,7 +343,7 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-imports@^7.13.12": +"@babel/helper-module-imports@^7.13.12", "@babel/helper-module-imports@^7.7.0": version "7.13.12" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== @@ -1555,6 +1555,35 @@ debug "^3.1.0" lodash.once "^4.1.1" +"@emotion/babel-plugin@11.1.2": + version "11.1.2" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.1.2.tgz#68fe1aa3130099161036858c64ee92056c6730b7" + integrity sha512-Nz1k7b11dWw8Nw4Z1R99A9mlB6C6rRsCtZnwNUOj4NsoZdrO2f2A/83ST7htJORD5zpOiLKY59aJN23092949w== + dependencies: + "@babel/helper-module-imports" "^7.7.0" + "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/runtime" "^7.7.2" + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.5" + "@emotion/serialize" "^1.0.0" + babel-plugin-macros "^2.6.1" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "^4.0.3" + +"@emotion/cache@11.1.3": + version "11.1.3" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.1.3.tgz#c7683a9484bcd38d5562f2b9947873cf66829afd" + integrity sha512-n4OWinUPJVaP6fXxWZD9OUeQ0lY7DvtmtSuqtRWT0Ofo/sBLCVSgb4/Oa0Q5eFxcwablRKjUXqXtNZVyEwCAuA== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.0.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "^4.0.3" + "@emotion/cache@^10.0.27": version "10.0.29" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.29.tgz#87e7e64f412c060102d589fe7c6dc042e6f9d1e0" @@ -1565,6 +1594,17 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" +"@emotion/cache@^11.1.3": + version "11.4.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.4.0.tgz#293fc9d9a7a38b9aad8e9337e5014366c3b09ac0" + integrity sha512-Zx70bjE7LErRO9OaZrhf22Qye1y4F7iDl+ITjet0J+i+B88PrAOBkKvaAWhxsZf72tDLajwCgfCjJ2dvH77C3g== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.0.0" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "^4.0.3" + "@emotion/core@^10.1.1": version "10.1.1" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.1.1.tgz#c956c1365f2f2481960064bcb8c4732e5fb612c3" @@ -1586,7 +1626,7 @@ "@emotion/utils" "0.11.3" babel-plugin-emotion "^10.0.27" -"@emotion/hash@0.8.0": +"@emotion/hash@0.8.0", "@emotion/hash@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== @@ -1603,6 +1643,24 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== +"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@11.1.4": + version "11.1.4" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.1.4.tgz#ddee4247627ff7dd7d0c6ae52f1cfd6b420357d2" + integrity sha512-9gkhrW8UjV4IGRnEe4/aGPkUxoGS23aD9Vu6JCGfEDyBYL+nGkkRBoMFGAzCT9qFdyUvQp4UUtErbKWxq/JS4A== + dependencies: + "@babel/runtime" "^7.7.2" + "@emotion/cache" "^11.1.3" + "@emotion/serialize" "^1.0.0" + "@emotion/sheet" "^1.0.1" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + "@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": version "0.11.16" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" @@ -1614,11 +1672,37 @@ "@emotion/utils" "0.11.3" csstype "^2.5.7" +"@emotion/serialize@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" + integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/server@11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@emotion/server/-/server-11.0.0.tgz#bec7fbaa139f42ce7bb3c8dc7f96c96e2fa02f77" + integrity sha512-2iyQf841Ir//9EmXk4L35gZJxl4T8q9pmKPQIj9JmM9mkaHpIu1P2ZrWuQ7cxFZc7HU230vNvnY9pAk17nRDKA== + dependencies: + "@emotion/utils" "^1.0.0" + html-tokenize "^2.0.0" + multipipe "^1.0.2" + through "^2.3.8" + "@emotion/sheet@0.9.4": version "0.9.4" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== +"@emotion/sheet@^1.0.0", "@emotion/sheet@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.1.tgz#245f54abb02dfd82326e28689f34c27aa9b2a698" + integrity sha512-GbIvVMe4U+Zc+929N1V7nW6YYJtidj31lidSmdYcWozwoBIObXBnaJkKNDjZrLm9Nc0BR+ZyHNaRZxqNZbof5g== + "@emotion/styled-base@^10.0.27": version "10.0.31" resolved "https://registry.yarnpkg.com/@emotion/styled-base/-/styled-base-10.0.31.tgz#940957ee0aa15c6974adc7d494ff19765a2f742a" @@ -1642,7 +1726,7 @@ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4": +"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4", "@emotion/unitless@^0.7.5": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== @@ -1652,7 +1736,12 @@ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== -"@emotion/weak-memoize@0.2.5": +"@emotion/utils@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" + integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== + +"@emotion/weak-memoize@0.2.5", "@emotion/weak-memoize@^0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== @@ -3340,55 +3429,11 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*": - version "1.19.0" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" - integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== - dependencies: - "@types/connect" "*" - "@types/node" "*" - "@types/braces@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.0.tgz#7da1c0d44ff1c7eb660a36ec078ea61ba7eb42cb" integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== -"@types/caseless@*": - version "0.12.2" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" - integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== - -"@types/connect@*": - version "3.4.34" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" - integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ== - dependencies: - "@types/node" "*" - -"@types/cookie@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108" - integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg== - -"@types/express-serve-static-core@^4.17.18": - version "4.17.18" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" - integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express@^4.17.11": - version "4.17.11" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.11.tgz#debe3caa6f8e5fcda96b47bd54e2f40c4ee59545" - integrity sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" - "@types/qs" "*" - "@types/serve-static" "*" - "@types/glob-base@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@types/glob-base/-/glob-base-0.3.0.tgz#a581d688347e10e50dd7c17d6f2880a10354319d" @@ -3526,11 +3571,6 @@ dependencies: "@types/braces" "*" -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -3589,7 +3629,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== -"@types/qs@*", "@types/qs@^6.9.0": +"@types/qs@^6.9.0": version "6.9.5" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== @@ -3601,11 +3641,6 @@ dependencies: ts-toolbelt "^6.15.1" -"@types/range-parser@*": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" - integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== - "@types/reach__router@^1.3.5": version "1.3.6" resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709" @@ -3644,24 +3679,6 @@ dependencies: "@types/react" "*" -"@types/request@^2.48.5": - version "2.48.5" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.5.tgz#019b8536b402069f6d11bee1b2c03e7f232937a0" - integrity sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ== - dependencies: - "@types/caseless" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - -"@types/serve-static@*": - version "1.13.9" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" - integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - "@types/sinonjs__fake-timers@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae" @@ -3703,11 +3720,6 @@ dependencies: "@types/jest" "*" -"@types/tough-cookie@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.0.tgz#fef1904e4668b6e5ecee60c52cc6a078ffa6697d" - integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== - "@types/uglify-js@*": version "3.11.1" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.11.1.tgz#97ff30e61a0aa6876c270b5f538737e2d6ab8ceb" @@ -4804,7 +4816,7 @@ babel-plugin-jest-hoist@^26.6.2: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.8.0: +babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.6.1, babel-plugin-macros@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -5257,6 +5269,13 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== +browser-tabs-lock@^1.2.14: + version "1.2.14" + resolved "https://registry.yarnpkg.com/browser-tabs-lock/-/browser-tabs-lock-1.2.14.tgz#f4ba30810d20199a1858c102da1f91e339250728" + integrity sha512-ssSpCRcvFe4vc098LDnrJOQDfZiG35KhQGB9hthTbwJk5mmUkePwhcMlW61NH3YuIE2Y9uGLqf9yxEBKbaDlaw== + dependencies: + lodash ">=4.17.21" + browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -5378,6 +5397,11 @@ buffer-from@1.x, buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-from@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" + integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg== + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -5803,6 +5827,13 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chroma-js@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.1.0.tgz#c0be48a21fe797ef8965608c1c4f911ef2da49d5" + integrity sha512-uiRdh4ZZy+UTPSrAdp8hqEdVb1EllLtTHOt5TMaOjJUvi+O54/83Fc5K2ld1P+TJX+dw5B+8/sCgzI6eaur/lg== + dependencies: + cross-env "^6.0.3" + chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" @@ -6239,11 +6270,6 @@ cookie@0.4.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -cookie@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -6399,6 +6425,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-env@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941" + integrity sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag== + dependencies: + cross-spawn "^7.0.0" + cross-fetch@3.0.6, cross-fetch@^3.0.4, cross-fetch@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c" @@ -7188,6 +7221,13 @@ downshift@^6.0.6: prop-types "^15.7.2" react-is "^17.0.1" +duplexer2@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -7309,6 +7349,11 @@ emotion-theming@^10.0.19: "@emotion/weak-memoize" "0.2.5" hoist-non-react-statics "^3.3.0" +emotion@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/emotion/-/emotion-11.0.0.tgz#e33353668e72f0adea1f6fba790dc6c5b05b45d9" + integrity sha512-QW3CRqic3aRw1OBOcnvxaHEpCmxtlGwZ5tM9dV5rY3Rn+F41E8EgTPOqJ5VfsqQ5ZXHDs2zSDyUwGI0ZfC2+5A== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -7520,6 +7565,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + escodegen@^1.12.0, escodegen@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -8420,7 +8470,7 @@ form-data@4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@^2.3.2, form-data@^2.5.0: +form-data@^2.3.2: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== @@ -9238,7 +9288,7 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, 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== @@ -9299,6 +9349,17 @@ html-tags@^3.1.0: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== +html-tokenize@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-tokenize/-/html-tokenize-2.0.1.tgz#c3b2ea6e2837d4f8c06693393e9d2a12c960be5f" + integrity sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w== + dependencies: + buffer-from "~0.1.1" + inherits "~2.0.1" + minimist "~1.2.5" + readable-stream "~1.0.27-1" + through2 "~0.4.1" + html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" @@ -9415,6 +9476,11 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== +humps@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa" + integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao= + hygen@6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/hygen/-/hygen-6.0.4.tgz#89d494c34c4160484e2057e649045e2e466b31de" @@ -10200,6 +10266,11 @@ is-wsl@^2.1.1, is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -10247,14 +10318,6 @@ isomorphic-form-data@2.0.0: dependencies: form-data "^2.3.2" -isomorphic-unfetch@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" - integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== - dependencies: - node-fetch "^2.6.1" - unfetch "^4.2.0" - isomorphic-ws@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" @@ -11296,7 +11359,7 @@ lodash.without@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4.x: +lodash@4.x, lodash@>=4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -11808,7 +11871,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@~1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -11942,6 +12005,14 @@ multimap@^1.1.0: resolved "https://registry.yarnpkg.com/multimap/-/multimap-1.1.0.tgz#5263febc085a1791c33b59bb3afc6a76a2a10ca8" integrity sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw== +multipipe@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-1.0.2.tgz#cc13efd833c9cda99f224f868461b8e1a3fd939d" + integrity sha1-zBPv2DPJzamfIk+GhGG44aP9k50= + dependencies: + duplexer2 "^0.1.2" + object-assign "^4.1.0" + mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -12200,14 +12271,6 @@ node-releases@^1.1.52, node-releases@^1.1.65, node-releases@^1.1.69: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== -nookies@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/nookies/-/nookies-2.5.2.tgz#cc55547efa982d013a21475bd0db0c02c1b35b27" - integrity sha512-x0TRSaosAEonNKyCrShoUaJ5rrT5KHRNZ5DwPCuizjgrnkpE5DRf3VL7AyyQin4htict92X1EQ7ejDbaHDVdYA== - dependencies: - cookie "^0.4.1" - set-cookie-parser "^2.4.6" - noop-logger@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" @@ -12365,6 +12428,11 @@ object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + object-path@^0.11.4: version "0.11.5" resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a" @@ -13840,6 +13908,14 @@ react-refresh@0.8.3, react-refresh@^0.8.3: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== +react-shadow@19.0.1: + version "19.0.1" + resolved "https://registry.yarnpkg.com/react-shadow/-/react-shadow-19.0.1.tgz#f59b17fcc22dcf0106849e6783101508ab866ea4" + integrity sha512-UOZ8j/SW6+m6QQaI7b6E5jR01r0YITbDMgX/xhl7kmeDQzg6DJ1ZKGnQEivgtjr5qrHrCQnBmNQAYPtc7Jpv4g== + dependencies: + humps "^2.0.1" + react-use "^15.3.3" + react-sizeme@^2.6.7: version "2.6.12" resolved "https://registry.yarnpkg.com/react-sizeme/-/react-sizeme-2.6.12.tgz#ed207be5476f4a85bf364e92042520499455453e" @@ -13875,7 +13951,7 @@ react-universal-interface@^0.6.2: resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw== -react-use@15.3.8: +react-use@15.3.8, react-use@^15.3.3: version "15.3.8" resolved "https://registry.yarnpkg.com/react-use/-/react-use-15.3.8.tgz#ca839ac7fb3d696e5ccbeabbc8dadc2698969d30" integrity sha512-GeGcrmGuUvZrY5wER3Lnph9DSYhZt5nEjped4eKDq8BRGr2CnLf9bDQWG9RFc7oCPphnscUUdOovzq0E5F2c6Q== @@ -13977,6 +14053,16 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stre string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@~1.0.17, readable-stream@~1.0.27-1: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -14796,11 +14882,6 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-cookie-parser@^2.4.6: - version "2.4.8" - resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" - integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== - set-harmonic-interval@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" @@ -15458,6 +15539,11 @@ string_decoder@^1.0.0, string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -15689,6 +15775,11 @@ stylis@3.5.4: resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== +stylis@^4.0.3: + version "4.0.10" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240" + integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg== + stylis@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.6.tgz#0d8b97b6bc4748bea46f68602b6df27641b3c548" @@ -15701,6 +15792,27 @@ sugarss@^2.0.0: dependencies: postcss "^7.0.2" +supertokens-auth-react@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/supertokens-auth-react/-/supertokens-auth-react-0.12.1.tgz#e7cc45f0830cfb7fcd5b09c3bb0e87e561750693" + integrity sha512-rJevRUpgeJPShyGXHPZI5VYcaIHpeSkHeTlZZpd6hby6CZbBg65KbqPVD1TsYlqR+1cUrg3lLbw1r3SnB4rlCQ== + dependencies: + "@emotion/babel-plugin" "11.1.2" + "@emotion/cache" "11.1.3" + "@emotion/react" "11.1.4" + "@emotion/server" "11.0.0" + chroma-js "2.1.0" + emotion "11.0.0" + react-shadow "19.0.1" + supertokens-website "^7.0.1" + +supertokens-website@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/supertokens-website/-/supertokens-website-7.0.1.tgz#e0d0d52766df37d4ee6a44ce7d643c3cc56b4a9c" + integrity sha512-R2hJ1AYX0UC4d/xPyWrnFmwFsz8lMdK82Q6KWVHFHECk5V38o3T9Y0AUUpjYG7iw92C9w6l5msbPXKgiX1WrJA== + dependencies: + browser-tabs-lock "^1.2.14" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -15979,7 +16091,15 @@ through2@^4.0.0: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.6: +through2@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.4.2.tgz#dbf5866031151ec8352bb6c4db64a2292a840b9b" + integrity sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s= + dependencies: + readable-stream "~1.0.17" + xtend "~2.1.1" + +"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -16385,7 +16505,7 @@ unc-path-regex@^0.1.2: resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= -unfetch@^4.1.0, unfetch@^4.2.0: +unfetch@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== @@ -17151,6 +17271,13 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + y18n@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"