feat(frontend/api): i18n support

pull/96/head
sct 4 years ago
parent 04252f88bb
commit 9131254f33

@ -29,6 +29,7 @@ module.exports = {
'react-hooks/exhaustive-deps': 'warn',
'@typescript-eslint/explicit-function-return-type': 'off',
'prettier/prettier': ['error', { endOfLine: 'auto' }],
'formatjs/no-offset': 'error',
},
overrides: [
{
@ -38,7 +39,7 @@ module.exports = {
},
},
],
plugins: ['jsx-a11y', 'prettier', 'react-hooks'],
plugins: ['jsx-a11y', 'prettier', 'react-hooks', 'formatjs'],
settings: {
react: {
pragma: 'React',

@ -0,0 +1,25 @@
module.exports = function (api) {
api.cache(true);
return {
presets: [
[
'next/babel',
{
'preset-env': {
useBuiltIns: 'entry',
corejs: '3',
},
},
],
],
plugins: [
[
'react-intl-auto',
{
removePrefix: 'src/',
},
],
],
};
};

@ -2,7 +2,7 @@ const devConfig = {
type: 'sqlite',
database: 'config/db/db.sqlite3',
synchronize: true,
logging: true,
logging: false,
entities: ['server/entity/**/*.ts'],
migrations: ['server/migration/**/*.ts'],
cli: {

@ -8,7 +8,8 @@
"build:next": "next build",
"build": "yarn build:next && yarn build:server",
"lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\"",
"start": "NODE_ENV=production node dist/index.js"
"start": "NODE_ENV=production node dist/index.js",
"i18n:extract": "extract-messages -l=en,ja -o src/i18n/locale -d en --flat true './src/**/!(*.test).{ts,tsx}'"
},
"dependencies": {
"@svgr/webpack": "^5.4.0",
@ -21,10 +22,13 @@
"express": "^4.17.1",
"express-openapi-validator": "^3.16.15",
"express-session": "^1.17.1",
"intl": "^1.2.5",
"lodash": "^4.17.20",
"next": "9.5.3",
"nookies": "^2.4.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-intl": "^5.8.1",
"react-spring": "^8.0.27",
"react-toast-notifications": "^2.4.0",
"react-transition-group": "^4.4.1",
@ -36,6 +40,7 @@
"yamljs": "^0.3.0"
},
"devDependencies": {
"@babel/cli": "^7.11.6",
"@commitlint/cli": "^9.1.2",
"@commitlint/config-conventional": "^9.1.2",
"@types/body-parser": "^1.19.0",
@ -52,14 +57,18 @@
"@types/yamljs": "^0.2.31",
"@typescript-eslint/eslint-plugin": "^4.0.0",
"@typescript-eslint/parser": "^3.10.1",
"babel-plugin-react-intl": "^8.2.2",
"babel-plugin-react-intl-auto": "^3.3.0",
"commitizen": "^4.2.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^7.8.1",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-formatjs": "^2.7.10",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.0",
"extract-react-intl-messages": "^4.1.1",
"husky": "^4.3.0",
"lint-staged": "^10.3.0",
"nodemon": "^2.0.4",

@ -4,6 +4,7 @@ interface SearchOptions {
query: string;
page?: number;
includeAdult?: boolean;
language?: string;
}
interface DiscoverMovieOptions {
@ -260,10 +261,11 @@ class TheMovieDb {
query,
page = 1,
includeAdult = false,
language = 'en-US',
}: SearchOptions): Promise<TmdbSearchMultiResponse> => {
try {
const response = await this.axios.get('/search/multi', {
params: { query, page, include_adult: includeAdult },
params: { query, page, include_adult: includeAdult, language },
});
return response.data;

@ -1060,6 +1060,11 @@ paths:
type: number
example: 1
default: 1
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Results
@ -1097,6 +1102,11 @@ paths:
type: number
example: 1
default: 1
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Results
@ -1131,6 +1141,11 @@ paths:
type: number
example: 1
default: 1
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Results
@ -1282,6 +1297,11 @@ paths:
schema:
type: number
example: 337401
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: Movie details
@ -1308,6 +1328,11 @@ paths:
type: number
example: 1
default: 1
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: List of movies
@ -1348,6 +1373,11 @@ paths:
type: number
example: 1
default: 1
- in: query
name: language
schema:
type: string
example: en
responses:
'200':
description: List of movies

@ -8,7 +8,10 @@ const discoverRoutes = Router();
discoverRoutes.get('/movies', async (req, res) => {
const tmdb = new TheMovieDb();
const data = await tmdb.getDiscoverMovies({ page: Number(req.query.page) });
const data = await tmdb.getDiscoverMovies({
page: Number(req.query.page),
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
data.results.map((result) => result.id)
@ -30,7 +33,10 @@ discoverRoutes.get('/movies', async (req, res) => {
discoverRoutes.get('/tv', async (req, res) => {
const tmdb = new TheMovieDb();
const data = await tmdb.getDiscoverTv({ page: Number(req.query.page) });
const data = await tmdb.getDiscoverTv({
page: Number(req.query.page),
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
data.results.map((result) => result.id)

@ -9,7 +9,10 @@ const movieRoutes = Router();
movieRoutes.get('/:id', async (req, res) => {
const tmdb = new TheMovieDb();
const movie = await tmdb.getMovie({ movieId: Number(req.params.id) });
const movie = await tmdb.getMovie({
movieId: Number(req.params.id),
language: req.query.language as string,
});
const request = await MediaRequest.getRequest(movie.id);
@ -22,6 +25,7 @@ movieRoutes.get('/:id/recommendations', async (req, res) => {
const results = await tmdb.getMovieRecommendations({
movieId: Number(req.params.id),
page: Number(req.query.page),
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(
@ -47,6 +51,7 @@ movieRoutes.get('/:id/similar', async (req, res) => {
const results = await tmdb.getMovieSimilar({
movieId: Number(req.params.id),
page: Number(req.query.page),
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(

@ -11,6 +11,7 @@ searchRoutes.get('/', async (req, res) => {
const results = await tmdb.searchMulti({
query: req.query.query as string,
page: Number(req.query.page),
language: req.query.language as string,
});
const requests = await MediaRequest.getRelatedRequests(

@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import useSWR from 'swr';
import type { MovieResult, TvResult } from '../../../server/models/Search';
import TitleCard from '../TitleCard';
@ -6,6 +6,14 @@ import { MediaRequest } from '../../../server/entity/MediaRequest';
import RequestCard from '../TitleCard/RequestCard';
import Slider from '../Slider';
import Link from 'next/link';
import { defineMessages, FormattedMessage } from 'react-intl';
import { LanguageContext } from '../../context/LanguageContext';
const messages = defineMessages({
recentrequests: 'Recent Requests',
popularmovies: 'Popular Movies',
populartv: 'Popular Series',
});
interface MovieDiscoverResult {
page: number;
@ -22,11 +30,12 @@ interface TvDiscoverResult {
}
const Discover: React.FC = () => {
const { locale } = useContext(LanguageContext);
const { data: movieData, error: movieError } = useSWR<MovieDiscoverResult>(
'/api/v1/discover/movies'
`/api/v1/discover/movies?language=${locale}`
);
const { data: tvData, error: tvError } = useSWR<TvDiscoverResult>(
'/api/v1/discover/tv'
`/api/v1/discover/tv?language=${locale}`
);
const { data: requests, error: requestError } = useSWR<MediaRequest[]>(
@ -39,7 +48,9 @@ const Discover: React.FC = () => {
<div className="flex-1 min-w-0">
<Link href="/requests">
<a className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>Recent Requests</span>
<span>
<FormattedMessage {...messages.recentrequests} />
</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
@ -74,7 +85,9 @@ const Discover: React.FC = () => {
<div className="flex-1 min-w-0">
<Link href="/discover/movies">
<a className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>Popular Movies</span>
<span>
<FormattedMessage {...messages.popularmovies} />
</span>
<svg
className="w-6 h-6 ml-2"
fill="none"
@ -116,7 +129,9 @@ const Discover: React.FC = () => {
<div className="flex-1 min-w-0">
<Link href="/discover/tv">
<a className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>Popular TV Shows</span>
<span>
<FormattedMessage {...messages.populartv} />
</span>
<svg
className="w-6 h-6 ml-2"
fill="none"

@ -0,0 +1,109 @@
import React, { useState, useRef, useContext } from 'react';
import Transition from '../../Transition';
import useClickOutside from '../../../hooks/useClickOutside';
import {
LanguageContext,
AvailableLocales,
} from '../../../context/LanguageContext';
import { FormattedMessage, defineMessages } from 'react-intl';
const messages = defineMessages({
changelanguage: 'Change Language',
});
type AvailableLanguageObject = Record<
string,
{ code: AvailableLocales; display: string }
>;
const availableLanguages: AvailableLanguageObject = {
en: {
code: 'en',
display: 'English',
},
ja: {
code: 'ja',
display: '日本語',
},
};
const LanguagePicker: React.FC = () => {
const dropdownRef = useRef<HTMLDivElement>(null);
const { locale, setLocale } = useContext(LanguageContext);
const [isDropdownOpen, setDropdownOpen] = useState(false);
useClickOutside(dropdownRef, () => setDropdownOpen(false));
return (
<div className="ml-3 relative">
<div>
<button
className="p-1 text-gray-400 rounded-full hover:bg-cool-gray-500 hover:text-white focus:outline-none focus:shadow-outline focus:text-white"
aria-label="Language Picker"
onClick={() => setDropdownOpen(true)}
>
<svg
className="w-6 h-6"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M7 2a1 1 0 011 1v1h3a1 1 0 110 2H9.578a18.87 18.87 0 01-1.724 4.78c.29.354.596.696.914 1.026a1 1 0 11-1.44 1.389c-.188-.196-.373-.396-.554-.6a19.098 19.098 0 01-3.107 3.567 1 1 0 01-1.334-1.49 17.087 17.087 0 003.13-3.733 18.992 18.992 0 01-1.487-2.494 1 1 0 111.79-.89c.234.47.489.928.764 1.372.417-.934.752-1.913.997-2.927H3a1 1 0 110-2h3V3a1 1 0 011-1zm6 6a1 1 0 01.894.553l2.991 5.982a.869.869 0 01.02.037l.99 1.98a1 1 0 11-1.79.895L15.383 16h-4.764l-.724 1.447a1 1 0 11-1.788-.894l.99-1.98.019-.038 2.99-5.982A1 1 0 0113 8zm-1.382 6h2.764L13 11.236 11.618 14z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
<Transition
show={isDropdownOpen}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<div
className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg"
ref={dropdownRef}
>
<div className="py-2 px-2 rounded-md bg-cool-gray-700 shadow-xs">
<div>
<label
htmlFor="language"
className="block text-sm leading-5 font-medium text-cool-gray-300 pb-2"
>
<FormattedMessage {...messages.changelanguage} />
</label>
<select
id="language"
className="mt-1 form-select block w-full pl-3 pr-10 py-2 text-base leading-6 text-white bg-cool-gray-700 border-cool-gray-600 focus:outline-none focus:shadow-outline-indigo focus:border-blue-800 sm:text-sm sm:leading-5"
onChange={(e) =>
setLocale && setLocale(e.target.value as AvailableLocales)
}
onBlur={(e) =>
setLocale && setLocale(e.target.value as AvailableLocales)
}
>
{(Object.keys(
availableLanguages
) as (keyof typeof availableLanguages)[]).map((key) => (
<option
key={key}
value={availableLanguages[key].code}
selected={locale === availableLanguages[key].code}
>
{availableLanguages[key].display}
</option>
))}
</select>
</div>
</div>
</div>
</Transition>
</div>
);
};
export default LanguagePicker;

@ -3,6 +3,7 @@ import SearchInput from './SearchInput';
import UserDropdown from './UserDropdown';
import Sidebar from './Sidebar';
import Notifications from './Notifications';
import LanguagePicker from './LanguagePicker';
const Layout: React.FC = ({ children }) => {
const [isSidebarOpen, setSidebarOpen] = useState(false);
@ -35,6 +36,7 @@ const Layout: React.FC = ({ children }) => {
<div className="flex-1 px-4 flex justify-between">
<SearchInput />
<div className="ml-4 flex items-center md:ml-6">
<LanguagePicker />
<Notifications />
<UserDropdown />
</div>

@ -1,4 +1,10 @@
import React, { useState } from 'react';
import React, { useState, useContext } from 'react';
import {
FormattedMessage,
defineMessages,
FormattedNumber,
FormattedDate,
} from 'react-intl';
import type { MovieDetails as MovieDetailsType } from '../../../server/models/Movie';
import useSWR from 'swr';
import { useRouter } from 'next/router';
@ -12,6 +18,19 @@ import Link from 'next/link';
import Slider from '../Slider';
import TitleCard from '../TitleCard';
import PersonCard from '../PersonCard';
import { LanguageContext } from '../../context/LanguageContext';
const messages = defineMessages({
releasedate: 'Release Date',
userrating: 'User Rating',
status: 'Status',
revenue: 'Revenue',
budget: 'Budget',
originallanguage: 'Original Language',
overview: 'Overview',
runtime: '{minutes} minutes',
cast: 'Cast',
});
interface MovieDetailsProps {
movie?: MovieDetailsType;
@ -33,20 +52,21 @@ enum MediaRequestStatus {
const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
const router = useRouter();
const { locale } = useContext(LanguageContext);
const { addToast } = useToasts();
const [showRequestModal, setShowRequestModal] = useState(false);
const [showCancelModal, setShowCancelModal] = useState(false);
const { data, error, revalidate } = useSWR<MovieDetailsType>(
`/api/v1/movie/${router.query.movieId}`,
`/api/v1/movie/${router.query.movieId}?language=${locale}`,
{
initialData: movie,
}
);
const { data: recommended, error: recommendedError } = useSWR<SearchResult>(
`/api/v1/movie/${router.query.movieId}/recommendations`
`/api/v1/movie/${router.query.movieId}/recommendations?language=${locale}`
);
const { data: similar, error: similarError } = useSWR<SearchResult>(
`/api/v1/movie/${router.query.movieId}/similar`
`/api/v1/movie/${router.query.movieId}/similar?language=${locale}`
);
const request = async () => {
@ -110,7 +130,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<img
src={`//image.tmdb.org/t/p/w600_and_h900_bestv2${data.posterPath}`}
alt=""
className="rounded shadow md:shadow-2xl w-32 md:w-52"
className="rounded md:rounded-lg shadow md:shadow-2xl w-32 md:w-52"
/>
</div>
<div className="text-white flex flex-col mr-4 mt-4 md:mt-0 text-center md:text-left">
@ -119,7 +139,11 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</span>
<h1 className="text-2xl md:text-4xl">{data.title}</h1>
<span className="text-xs md:text-base mt-1 md:mt-0">
{data.runtime} minutes | {data.genres.map((g) => g.name).join(', ')}
<FormattedMessage
{...messages.runtime}
values={{ minutes: data.runtime }}
/>{' '}
| {data.genres.map((g) => g.name).join(', ')}
</span>
</div>
<div className="flex-1 flex justify-end mt-4 md:mt-0">
@ -249,31 +273,70 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</div>
<div className="flex pt-8 text-white flex-col md:flex-row pb-4">
<div className="flex-1 md:mr-8">
<h2 className="text-xl md:text-2xl">Overview</h2>
<h2 className="text-xl md:text-2xl">
<FormattedMessage {...messages.overview} />
</h2>
<p className="pt-2 text-sm md:text-base">{data.overview}</p>
</div>
<div className="w-full md:w-80 mt-8 md:mt-0">
<div className="bg-cool-gray-900 rounded-lg shadow border border-cool-gray-800">
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">Status</span>
<span className="text-sm">
<FormattedMessage {...messages.userrating} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
{data.voteAverage}/10
</span>
</div>
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">
<FormattedMessage {...messages.releasedate} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
<FormattedDate
value={new Date(data.releaseDate)}
year="numeric"
month="long"
day="numeric"
/>
</span>
</div>
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">
<FormattedMessage {...messages.status} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
{data.status}
</span>
</div>
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">Revenue</span>
<span className="text-sm">
<FormattedMessage {...messages.revenue} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
{data.revenue}
<FormattedNumber
currency="USD"
style="currency"
value={data.revenue}
/>
</span>
</div>
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">Budget</span>
<span className="text-sm">
<FormattedMessage {...messages.budget} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
{data.budget}
<FormattedNumber
currency="USD"
style="currency"
value={data.budget}
/>
</span>
</div>
<div className="flex px-4 py-2 border-b border-cool-gray-800 last:border-b-0">
<span className="text-sm">Original Language</span>
<span className="text-sm">
<FormattedMessage {...messages.originallanguage} />
</span>
<span className="flex-1 text-right text-cool-gray-400 text-sm">
{data.originalLanguage}
</span>
@ -285,7 +348,9 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
<div className="flex-1 min-w-0">
<Link href="/movie/[movieId]/cast" as={`/movie/${data.id}/cast`}>
<a className="inline-flex text-xl leading-7 text-cool-gray-300 hover:text-white sm:text-2xl sm:leading-9 sm:truncate items-center">
<span>Cast</span>
<span>
<FormattedMessage {...messages.cast} />
</span>
<svg
className="w-6 h-6 ml-2"
fill="none"

@ -1,8 +1,9 @@
import React from 'react';
import React, { useContext } from 'react';
import useSWR from 'swr';
import type { MovieDetails } from '../../../server/models/Movie';
import type { TvDetails } from '../../../server/models/Tv';
import TitleCard from '.';
import { LanguageContext } from '../../context/LanguageContext';
interface TmdbTitleCardProps {
tmdbId: number;
@ -14,9 +15,12 @@ const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
};
const RequestCard: React.FC<TmdbTitleCardProps> = ({ tmdbId, type }) => {
const { locale } = useContext(LanguageContext);
const url =
type === 'movie' ? `/api/v1/movie/${tmdbId}` : `/api/v1/tv/${tmdbId}`;
const { data: title, error } = useSWR<MovieDetails | TvDetails>(url);
const { data: title, error } = useSWR<MovieDetails | TvDetails>(
`${url}?language=${locale}`
);
if (!title && !error) {
return <TitleCard.Placeholder />;

@ -0,0 +1,15 @@
import React, { ReactNode } from 'react';
export type AvailableLocales = 'en' | 'ja';
interface LanguageContextProps {
locale: AvailableLocales;
children: (locale: string) => ReactNode;
setLocale?: React.Dispatch<React.SetStateAction<AvailableLocales>>;
}
export const LanguageContext = React.createContext<
Omit<LanguageContextProps, 'children'>
>({
locale: 'en',
});

@ -0,0 +1,15 @@
{
"components.Discover.popularmovies": "Popular Movies",
"components.Discover.populartv": "Popular Series",
"components.Discover.recentrequests": "Recent Requests",
"components.Layout.LanguagePicker.changelanguage": "Change Language",
"components.MovieDetails.budget": "Budget",
"components.MovieDetails.cast": "Cast",
"components.MovieDetails.originallanguage": "Original Language",
"components.MovieDetails.overview": "Overview",
"components.MovieDetails.releasedate": "Release Date",
"components.MovieDetails.revenue": "Revenue",
"components.MovieDetails.runtime": "{minutes} minutes",
"components.MovieDetails.status": "Status",
"components.MovieDetails.userrating": "User Rating"
}

@ -0,0 +1,15 @@
{
"components.Discover.popularmovies": "人気映画",
"components.Discover.populartv": "人気テレビ番組",
"components.Discover.recentrequests": "最近のリクエスト",
"components.Layout.LanguagePicker.changelanguage": "言語",
"components.MovieDetails.budget": "興行収入",
"components.MovieDetails.cast": "キャスト",
"components.MovieDetails.originallanguage": "言語",
"components.MovieDetails.overview": "ストーリー",
"components.MovieDetails.releasedate": "公開日",
"components.MovieDetails.revenue": "製作費",
"components.MovieDetails.runtime": "{minutes}分",
"components.MovieDetails.status": "状態",
"components.MovieDetails.userrating": "ユーザー評価"
}

@ -1,82 +1,136 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import '../styles/globals.css';
import App, { AppInitialProps } from 'next/app';
import App, { AppInitialProps, AppProps } from 'next/app';
import { SWRConfig } from 'swr';
import { ToastProvider } from 'react-toast-notifications';
import { parseCookies, setCookie } from 'nookies';
import Layout from '../components/Layout';
import { UserContext } from '../context/UserContext';
import axios from 'axios';
import { User } from '../hooks/useUser';
import { IntlProvider } from 'react-intl';
import { LanguageContext, AvailableLocales } from '../context/LanguageContext';
const loadLocaleData = (locale: string) => {
switch (locale) {
case 'ja':
return import('../i18n/locale/ja.json');
default:
return import('../i18n/locale/en.json');
}
};
// Custom types so we can correctly type our GetInitialProps function
// with our combined user prop
// This is specific to _app.tsx. Other pages will not need to do this!
type NextAppComponentType = typeof App;
type GetInitialPropsFn = NextAppComponentType['getInitialProps'];
type MessagesType = Record<string, any>;
interface AppProps {
interface ExtendedAppProps extends AppProps {
user: User;
messages: MessagesType;
locale: AvailableLocales;
}
class CoreApp extends App<AppProps> {
public static getInitialProps: GetInitialPropsFn = async (initialProps) => {
// Run the default getInitialProps for the main nextjs initialProps
const appInitialProps: AppInitialProps = await App.getInitialProps(
initialProps
if (typeof window === 'undefined') {
global.Intl = require('intl');
}
const CoreApp: Omit<NextAppComponentType, 'origGetInitialProps'> = ({
Component,
pageProps,
router,
user,
messages,
locale,
}: ExtendedAppProps) => {
let component: React.ReactNode;
const [loadedMessages, setMessages] = useState<MessagesType>(messages);
const [currentLocale, setLocale] = useState<AvailableLocales>(locale);
useEffect(() => {
loadLocaleData(currentLocale).then(setMessages);
setCookie(null, 'locale', currentLocale, { path: '/' });
}, [currentLocale]);
if (router.asPath === '/login') {
component = <Component {...pageProps} />;
} else {
component = (
<Layout>
<Component {...pageProps} />
</Layout>
);
const { ctx, router } = initialProps;
let user = undefined;
if (ctx.res) {
try {
// Attempt to get the user by running a request to the local api
const response = await axios.get<User>(
`http://localhost:${process.env.PORT || 3000}/api/v1/auth/me`,
{ headers: ctx.req ? { cookie: ctx.req.headers.cookie } : undefined }
);
user = response.data;
} catch (e) {
// If there is no user, and ctx.res is set (to check if we are on the server side)
// _AND_ we are not already on the login or setup route, redirect to /login with a 307
// before anything actually renders
if (!router.pathname.match(/(login|setup)/)) {
ctx.res.writeHead(307, {
Location: '/login',
});
ctx.res.end();
}
}
}
}
return { ...appInitialProps, user };
};
return (
<SWRConfig
value={{
fetcher: (url) => axios.get(url).then((res) => res.data),
}}
>
<LanguageContext.Provider value={{ locale: currentLocale, setLocale }}>
<IntlProvider
locale={currentLocale}
defaultLocale="en"
messages={loadedMessages}
>
<ToastProvider>
<UserContext initialUser={user}>{component}</UserContext>
</ToastProvider>
</IntlProvider>
</LanguageContext.Provider>
</SWRConfig>
);
};
public render(): JSX.Element {
const { Component, pageProps, router, user } = this.props;
CoreApp.getInitialProps = async (initialProps) => {
// Run the default getInitialProps for the main nextjs initialProps
const appInitialProps: AppInitialProps = await App.getInitialProps(
initialProps
);
const { ctx, router } = initialProps;
let user = undefined;
let component: React.ReactNode;
let locale = 'en';
if (router.asPath === '/login') {
component = <Component {...pageProps} />;
} else {
component = (
<Layout>
<Component {...pageProps} />
</Layout>
);
if (ctx.res) {
const cookies = parseCookies(ctx);
if (cookies.locale) {
locale = cookies.locale;
}
return (
<SWRConfig
value={{
fetcher: (url) => axios.get(url).then((res) => res.data),
}}
>
<ToastProvider>
<UserContext initialUser={user}>{component}</UserContext>
</ToastProvider>
</SWRConfig>
);
try {
// Attempt to get the user by running a request to the local api
const response = await axios.get<User>(
`http://localhost:${process.env.PORT || 3000}/api/v1/auth/me`,
{ headers: ctx.req ? { cookie: ctx.req.headers.cookie } : undefined }
);
user = response.data;
if (router.pathname.match(/login/)) {
ctx.res.writeHead(307, {
Location: '/',
});
ctx.res.end();
}
} catch (e) {
// If there is no user, and ctx.res is set (to check if we are on the server side)
// _AND_ we are not already on the login or setup route, redirect to /login with a 307
// before anything actually renders
if (!router.pathname.match(/(login|setup)/)) {
ctx.res.writeHead(307, {
Location: '/login',
});
ctx.res.end();
}
}
}
}
const messages = await loadLocaleData(locale);
return { ...appInitialProps, user, messages, locale };
};
export default CoreApp;

@ -3,6 +3,7 @@ import { NextPage } from 'next';
import type { MovieDetails as MovieDetailsType } from '../../../../server/models/Movie';
import MovieDetails from '../../../components/MovieDetails';
import axios from 'axios';
import { parseCookies } from 'nookies';
interface MoviePageProps {
movie?: MovieDetailsType;
@ -14,10 +15,11 @@ const MoviePage: NextPage<MoviePageProps> = ({ movie }) => {
MoviePage.getInitialProps = async (ctx) => {
if (ctx.req) {
const cookies = parseCookies(ctx);
const response = await axios.get<MovieDetailsType>(
`http://localhost:${process.env.PORT || 3000}/api/v1/movie/${
ctx.query.movieId
}`,
}?language=${cookies.locale}`,
{ headers: ctx.req ? { cookie: ctx.req.headers.cookie } : undefined }
);

@ -1,13 +0,0 @@
import React from 'react';
import { NextPage } from 'next';
import PersonCard from '../components/PersonCard';
const PlexText: NextPage = () => {
return (
<div>
<PersonCard />
</div>
);
};
export default PlexText;

@ -0,0 +1,11 @@
import { MessageDescriptor } from 'react-intl';
declare module 'react-intl' {
interface ExtractableMessage {
[key: string]: string;
}
export function defineMessages<T extends ExtractableMessage>(
messages: T
): { [K in keyof T]: MessageDescriptor };
}

@ -62,6 +62,22 @@
call-me-maybe "^1.0.1"
js-yaml "^3.13.1"
"@babel/cli@^7.11.6":
version "7.11.6"
resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.11.6.tgz#1fcbe61c2a6900c3539c06ee58901141f3558482"
integrity sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg==
dependencies:
commander "^4.0.1"
convert-source-map "^1.1.0"
fs-readdir-recursive "^1.1.0"
glob "^7.0.0"
lodash "^4.17.19"
make-dir "^2.1.0"
slash "^2.0.0"
source-map "^0.5.0"
optionalDependencies:
chokidar "^2.1.8"
"@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
@ -373,16 +389,16 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
"@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.7.7":
version "7.11.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9"
integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==
"@babel/parser@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
"@babel/plugin-proposal-async-generator-functions@^7.10.4":
version "7.10.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558"
@ -1067,7 +1083,7 @@
globals "^11.1.0"
lodash "^4.17.19"
"@babel/traverse@^7.11.5":
"@babel/traverse@^7.11.5", "@babel/traverse@^7.9.0":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
@ -1082,7 +1098,7 @@
globals "^11.1.0"
lodash "^4.17.19"
"@babel/types@7.11.5", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.4.4", "@babel/types@^7.7.4", "@babel/types@^7.9.5":
"@babel/types@7.11.5", "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.7.4", "@babel/types@^7.9.0", "@babel/types@^7.9.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
@ -1334,6 +1350,60 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@formatjs/ecma402-abstract@^1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.2.1.tgz#ad966998d7f0e96fca4bdc5de0ca28d02f371279"
integrity sha512-LvbwgHxprafjceDfOC7yMl4sP5al71rAWahXk3qug5bV020aCq64WjqAo+zNnkIJk8hqK2pFKnNdDsT58HZJQw==
"@formatjs/intl-displaynames@^3.3.7":
version "3.3.7"
resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-3.3.7.tgz#7d8cc73d0a67a7c51b182233121eaa2c85f9f751"
integrity sha512-sMdV3QaFy2RMOZ6YaRYInDzThEEIiD8vZjue20/CYvxgNKw3ZIZROvpEaKHvHr197Si3RFaxhAGUWk/lI7NAeA==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl-listformat@^4.2.6":
version "4.2.6"
resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-4.2.6.tgz#31638a6cb3e33047d81161b139c1d68fb377d3c2"
integrity sha512-4JGDYVwZyEMGpwhUKXIcSXjRVuSrz5ox1rQCQVzj0CzgEoojrQoaUkcuW+Vj89JlpCtRS8NS46d3CWLUSDC+2g==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl-numberformat@^5.5.2":
version "5.6.1"
resolved "https://registry.yarnpkg.com/@formatjs/intl-numberformat/-/intl-numberformat-5.6.1.tgz#eaa16b68be6a8c7dddbb2495a9271046c51293c5"
integrity sha512-ENtX07hT/GJD/GZIvk1jf/nYHg8Hq3twZ4fOGAZIVhwd6ZqlAm6dgqqRxpNXw3ul8UCwx9tOeptF1gT42HwjKA==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl-relativetimeformat@^7.2.6":
version "7.2.6"
resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-7.2.6.tgz#7452e0feaa433f341b306e308166058e8126e934"
integrity sha512-SHwrzk9HuAUwl3/qfupU3ZnW4ZgVOpI2+3gwGmvoPOmAlKFlo7liSCszA5hcRpsnhjS66BqUzfx6BWOwzYvmKQ==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl@^1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-1.3.1.tgz#8604b1bcef60572a2ecd22db91c0599760ceebf6"
integrity sha512-W1m8vLAQHjrox3ZrJRD6ArMp2AOvUCBeeID7NNhcezZ2fWXtzIKi8k9jeptkO54HZbueLcpshWb2gbUSR5Xy0Q==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl-displaynames" "^3.3.7"
"@formatjs/intl-listformat" "^4.2.6"
"@formatjs/intl-relativetimeformat" "^7.2.6"
fast-memoize "^2.5.2"
intl-messageformat "^9.3.7"
intl-messageformat-parser "^6.0.6"
"@formatjs/ts-transformer@^2.10.0", "@formatjs/ts-transformer@^2.6.0":
version "2.10.0"
resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-2.10.0.tgz#06f292b6cbcea661e2cecf7b8945ac59f21b7c93"
integrity sha512-ff+gIzsbd5WEm6mLn1x0A1gD4oJomst8pF7NEjrI0Egn+82v8PEEZeYrsGjUzRt3jyOaRguQUYJGHiw+5d84dQ==
dependencies:
intl-messageformat-parser "^6.0.6"
typescript "^4.0"
"@fullhuman/postcss-purgecss@^2.1.2":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.3.0.tgz#50a954757ec78696615d3e118e3fee2d9291882e"
@ -1528,6 +1598,39 @@
hex-rgb "^4.1.0"
postcss-selector-parser "^6.0.2"
"@types/babel__core@^7.1.7":
version "7.1.9"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d"
integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
"@types/babel__generator" "*"
"@types/babel__template" "*"
"@types/babel__traverse" "*"
"@types/babel__generator@*":
version "7.6.1"
resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04"
integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==
dependencies:
"@babel/types" "^7.0.0"
"@types/babel__template@*":
version "7.0.2"
resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307"
integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==
dependencies:
"@babel/parser" "^7.1.0"
"@babel/types" "^7.0.0"
"@types/babel__traverse@*":
version "7.0.14"
resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.14.tgz#e99da8c075d4fb098c774ba65dabf7dc9954bd13"
integrity sha512-8w9szzKs14ZtBVuP6Wn7nMLRJ0D6dfB0VEBEyRgxrZ/Ln49aNMykrghM2FaNn4FJRzNppCSa0Rv9pBRM5Xc3wg==
dependencies:
"@babel/types" "^7.3.0"
"@types/body-parser@*", "@types/body-parser@^1.19.0":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
@ -1560,11 +1663,29 @@
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-0.0.31.tgz#bac8d8aab6a823e91deb7f79083b2a35fa638f33"
integrity sha512-LS1MCPaQKqspg7FvexuhmDbWUhE2yIJ+4AgVIyObfc06/UKZ8REgxGNjZc82wPLWmbeOm7S+gSsLgo75TanG4A==
"@types/emoji-regex@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@types/emoji-regex/-/emoji-regex-8.0.0.tgz#df215c9ff818e071087fb8e7e6e74c4cb42a1303"
integrity sha512-iacbaYN9IWWrGWTwlYLVOeUtN/e4cjN9Uh6v7Yo1Qa/vJzeSQeh10L/erBBSl53BTmbnQ07vsWp8mmNHGI4WbQ==
"@types/eslint-visitor-keys@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
"@types/eslint@^7.2.0":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.2.tgz#c88426b896efeb0b2732a92431ce8aa7ec0dee61"
integrity sha512-psWuwNXuKR2e6vMU5d2qH0Kqzrb2Zxwk+uBCF2LsyEph+Nex3lFIPMJXwxfGesdtJM2qtjKoCYsyh76K3x9wLg==
dependencies:
"@types/estree" "*"
"@types/json-schema" "*"
"@types/estree@*", "@types/estree@^0.0.45":
version "0.0.45"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
"@types/express-serve-static-core@*":
version "4.17.9"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz#2d7b34dcfd25ec663c25c85d76608f8b249667f1"
@ -1592,6 +1713,26 @@
"@types/qs" "*"
"@types/serve-static" "*"
"@types/fs-extra@^9.0.1":
version "9.0.1"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.1.tgz#91c8fc4c51f6d5dbe44c2ca9ab09310bd00c7918"
integrity sha512-B42Sxuaz09MhC3DDeW5kubRcQ5by4iuVQ0cRRWM2lggLzAa/KVom0Aft/208NgMvNQQZ86s5rVcqDdn/SH0/mg==
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/json-schema@*", "@types/json-schema@^7.0.5":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
"@types/json-schema@^7.0.3", "@types/json-schema@^7.0.4":
version "7.0.5"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
@ -1676,6 +1817,13 @@
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/schema-utils@^2.4.0":
version "2.4.0"
resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-2.4.0.tgz#9983012045d541dcee053e685a27c9c87c840fcd"
integrity sha512-454hrj5gz/FXcUE20ygfEiN4DxZ1sprUo0V1gqIqkNZ/CzoEzAZEll2uxMsuyz6BYjiQan4Aa65xbTemfzW9hQ==
dependencies:
schema-utils "*"
"@types/serve-static@*":
version "1.13.5"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53"
@ -1762,7 +1910,7 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.0.0.tgz#ec1f9fc06b8558a1d5afa6e337182d08beece7f5"
integrity sha512-bK+c2VLzznX2fUWLK6pFDv3cXGTp7nHIuBMq1B9klA+QCsqLHOOqe5TQReAQDl7DN2RfH+neweo0oC5hYlG7Rg==
"@typescript-eslint/typescript-estree@3.10.1":
"@typescript-eslint/typescript-estree@3.10.1", "@typescript-eslint/typescript-estree@^3.6.0":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853"
integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==
@ -2048,7 +2196,7 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
@ -2339,6 +2487,11 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
at-least-node@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
atob@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
@ -2416,6 +2569,46 @@ babel-plugin-macros@^2.0.0:
cosmiconfig "^6.0.0"
resolve "^1.12.0"
babel-plugin-react-intl-auto@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/babel-plugin-react-intl-auto/-/babel-plugin-react-intl-auto-3.3.0.tgz#75c6ba8a1eb442f43c2ab85f1a75f4cc1e0d7857"
integrity sha512-08ZyGWtKrQY/rMNfdvrWPBsjqx+8CirqV4/JUM46FAS2aU98Mi/uWM60K6Wg6Zapdyqs3fCbQ8S4OfqMPsBiqQ==
dependencies:
"@babel/core" "^7.9.0"
"@babel/traverse" "^7.9.0"
"@babel/types" "^7.9.0"
murmurhash3js "^3.0.1"
babel-plugin-react-intl@^7.0.0:
version "7.9.4"
resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-7.9.4.tgz#1fc9ab50470d41b934df50d8f436578ee1732cb0"
integrity sha512-cMKrHEXrw43yT4M89Wbgq8A8N8lffSquj1Piwov/HVukR7jwOw8gf9btXNsQhT27ccyqEwy+M286JQYy0jby2g==
dependencies:
"@babel/core" "^7.9.0"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/types" "^7.9.5"
"@formatjs/ts-transformer" "^2.6.0"
"@types/babel__core" "^7.1.7"
"@types/fs-extra" "^9.0.1"
"@types/schema-utils" "^2.4.0"
fs-extra "^9.0.0"
intl-messageformat-parser "^5.3.7"
schema-utils "^2.6.6"
babel-plugin-react-intl@^8.2.2:
version "8.2.2"
resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-8.2.2.tgz#fcaab15a4f481f64405795a915cce7fab520dc6d"
integrity sha512-lFq03ZdEX8ggSCKAxVCJKwFE+m9VhpGEK/Q0P7lAPfdYUTNlT5abirDOV3kolrZ9keqlYY00B+4hPUQoHpPVrw==
dependencies:
"@babel/core" "^7.9.0"
"@babel/helper-plugin-utils" "^7.8.3"
"@babel/types" "^7.9.5"
"@formatjs/ts-transformer" "^2.10.0"
"@types/babel__core" "^7.1.7"
"@types/schema-utils" "^2.4.0"
intl-messageformat-parser "^6.0.6"
schema-utils "^2.6.6"
babel-plugin-syntax-jsx@6.18.0, babel-plugin-syntax-jsx@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
@ -3133,6 +3326,11 @@ commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
@ -3300,7 +3498,7 @@ conventional-commits-parser@^3.0.0:
through2 "^3.0.0"
trim-off-newlines "^1.0.0"
convert-source-map@1.7.0, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
convert-source-map@1.7.0, convert-source-map@^1.1.0, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
@ -3330,6 +3528,11 @@ 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.0:
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"
@ -3832,7 +4035,7 @@ detect-file@^1.0.0:
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
detect-indent@6.0.0:
detect-indent@6.0.0, detect-indent@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
@ -4174,6 +4377,19 @@ eslint-config-prettier@^6.11.0:
dependencies:
get-stdin "^6.0.0"
eslint-plugin-formatjs@^2.7.10:
version "2.7.10"
resolved "https://registry.yarnpkg.com/eslint-plugin-formatjs/-/eslint-plugin-formatjs-2.7.10.tgz#436bfe8283d5108c3e93617c8bea929cbbc8e35b"
integrity sha512-rqhw+AgicCWDD38jluqwLKqAEuVEBI3/XcUu/AWoWrhsyg692KmBdNl0hiKaN9bv+U837q0PYXcdcFwv5TuBeQ==
dependencies:
"@formatjs/ts-transformer" "^2.10.0"
"@types/emoji-regex" "^8.0.0"
"@types/eslint" "^7.2.0"
"@types/estree" "^0.0.45"
"@typescript-eslint/typescript-estree" "^3.6.0"
emoji-regex "^9.0.0"
intl-messageformat-parser "^6.0.6"
eslint-plugin-jsx-a11y@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660"
@ -4516,6 +4732,27 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
extract-react-intl-messages@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/extract-react-intl-messages/-/extract-react-intl-messages-4.1.1.tgz#cd01d99053bb053ecc8410ccdccb9ac56daae91c"
integrity sha512-dPogci5X7HVtV7VbUxajH/1YgfNRaW2VtEiVidZ/31Tq8314uzOtzVMNo0IrAPD2E+H1wHoPiu/j565TZsyIZg==
dependencies:
"@babel/core" "^7.9.0"
babel-plugin-react-intl "^7.0.0"
flat "^5.0.0"
glob "^7.1.6"
js-yaml "^3.13.1"
load-json-file "^6.2.0"
lodash.merge "^4.6.2"
lodash.mergewith "^4.6.2"
lodash.pick "^4.4.0"
meow "^6.1.0"
mkdirp "^1.0.3"
pify "^5.0.0"
read-babelrc-up "^1.1.0"
sort-keys "^4.0.0"
write-json-file "^4.3.0"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@ -4563,6 +4800,11 @@ fast-levenshtein@^2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fast-memoize@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/fast-memoize/-/fast-memoize-2.5.2.tgz#79e3bb6a4ec867ea40ba0e7146816f6cdce9b57e"
integrity sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==
fastq@^1.6.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481"
@ -4708,6 +4950,11 @@ flat-cache@^2.0.1:
rimraf "2.6.3"
write "1.0.3"
flat@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
flatted@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
@ -4796,6 +5043,16 @@ fs-extra@8.1.0, fs-extra@^8.0.0, fs-extra@^8.1.0:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-extra@^9.0.0:
version "9.0.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc"
integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==
dependencies:
at-least-node "^1.0.0"
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^1.0.0"
fs-minipass@^1.2.5:
version "1.2.7"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
@ -4810,6 +5067,11 @@ fs-minipass@^2.0.0:
dependencies:
minipass "^3.0.0"
fs-readdir-recursive@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27"
integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==
fs-write-stream-atomic@^1.0.8:
version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@ -5187,6 +5449,13 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
homedir-polyfill@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
@ -5419,6 +5688,33 @@ internal-slot@^1.0.2:
has "^1.0.3"
side-channel "^1.0.2"
intl-messageformat-parser@^5.3.7:
version "5.5.1"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-5.5.1.tgz#f09a692755813e6220081e3374df3fb1698bd0c6"
integrity sha512-TvB3LqF2VtP6yI6HXlRT5TxX98HKha6hCcrg9dwlPwNaedVNuQA9KgBdtWKgiyakyCTYHQ+KJeFEstNKfZr64w==
dependencies:
"@formatjs/intl-numberformat" "^5.5.2"
intl-messageformat-parser@^6.0.6:
version "6.0.6"
resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-6.0.6.tgz#c06c79c534612808e1f3c39288a3c009fb1ff7cd"
integrity sha512-XPAgYvCTSwgr92zzy5sfaglUu4uKjIWXHNTenEQRTo5t3o2TGxuPYPruxZqnvSLgnlAegiT/hBemmPcnFPNjAg==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
intl-messageformat@^9.3.7:
version "9.3.7"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-9.3.7.tgz#d40e61dc20ded8952fef00d97237880ff380550a"
integrity sha512-DUc+BJ6QN/IyT05gyKTuSJuauuYheV/5IhP+KEwmLhaJzONu0U/nnL5P6L5Ck9DXAx8iy7HM0CwFUctD7CmqZw==
dependencies:
fast-memoize "^2.5.2"
intl-messageformat-parser "^6.0.6"
intl@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/intl/-/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde"
integrity sha1-giRKIZDE5Bn4Nx9ao02qNCDiq94=
invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@ -5616,6 +5912,11 @@ is-plain-obj@^1.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
is-plain-obj@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -5810,6 +6111,15 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"
integrity sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==
dependencies:
universalify "^1.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
jsonparse@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@ -5960,6 +6270,16 @@ listr2@^2.6.0:
rxjs "^6.6.2"
through "^2.3.8"
load-json-file@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1"
integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ==
dependencies:
graceful-fs "^4.1.15"
parse-json "^5.0.0"
strip-bom "^4.0.0"
type-fest "^0.6.0"
loader-runner@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
@ -6022,6 +6342,16 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash.mergewith@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
lodash.pick@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
@ -6115,7 +6445,7 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
make-dir@^2.0.0:
make-dir@^2.0.0, make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@ -6202,6 +6532,23 @@ memory-fs@^0.5.0:
errno "^0.1.3"
readable-stream "^2.0.1"
meow@^6.1.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467"
integrity sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==
dependencies:
"@types/minimist" "^1.2.0"
camelcase-keys "^6.2.2"
decamelize-keys "^1.1.0"
hard-rejection "^2.1.0"
minimist-options "^4.0.2"
normalize-package-data "^2.5.0"
read-pkg-up "^7.0.1"
redent "^3.0.0"
trim-newlines "^3.0.0"
type-fest "^0.13.1"
yargs-parser "^18.1.3"
meow@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.0.tgz#50ecbcdafa16f8b58fb7eb9675b933f6473b3a59"
@ -6347,7 +6694,7 @@ minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
minimist-options@4.1.0:
minimist-options@4.1.0, minimist-options@^4.0.2:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==
@ -6496,6 +6843,11 @@ multer@^1.4.2:
type-is "^1.6.4"
xtend "^4.0.0"
murmurhash3js@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/murmurhash3js/-/murmurhash3js-3.0.1.tgz#3e983e5b47c2a06f43a713174e7e435ca044b998"
integrity sha1-Ppg+W0fCoG9DpxMXTn5DXKBEuZg=
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
@ -6751,6 +7103,14 @@ nodemon@^2.0.4:
undefsafe "^2.0.2"
update-notifier "^4.0.0"
nookies@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/nookies/-/nookies-2.4.0.tgz#1bd4eb244f54d6e622e8ff1c7aeca692892d292d"
integrity sha512-QC1+Ih9/BedZOIUVXneHBQgp8n9NzvsqyfmzAoUTrwOdwJOjB+phWzeLXuLqcxgxztTq3t3PeHtuosFKclL+Hw==
dependencies:
cookie "^0.4.0"
set-cookie-parser "^2.4.3"
"nopt@2 || 3":
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
@ -7260,6 +7620,11 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
pify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
pkg-dir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@ -7928,7 +8293,24 @@ react-dom@16.13.1:
prop-types "^15.6.2"
scheduler "^0.19.1"
react-is@16.13.1, react-is@^16.8.1:
react-intl@^5.8.1:
version "5.8.1"
resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.8.1.tgz#2974499d438bcde58437100b0c19043ca0ffcc3b"
integrity sha512-NGwtadXCoPUYHqQFNYR0Rbwv08QkCLECeBPUUFndhJIudvgmVqNrX3x6A3LMEYY76vLOovmoy+xiTAx7yWGkBg==
dependencies:
"@formatjs/ecma402-abstract" "^1.2.1"
"@formatjs/intl" "^1.3.1"
"@formatjs/intl-displaynames" "^3.3.7"
"@formatjs/intl-listformat" "^4.2.6"
"@formatjs/intl-relativetimeformat" "^7.2.6"
"@types/hoist-non-react-statics" "^3.3.1"
fast-memoize "^2.5.2"
hoist-non-react-statics "^3.3.2"
intl-messageformat "^9.3.7"
intl-messageformat-parser "^6.0.6"
shallow-equal "^1.2.1"
react-is@16.13.1, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -7973,6 +8355,14 @@ react@16.13.1:
object-assign "^4.1.1"
prop-types "^15.6.2"
read-babelrc-up@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/read-babelrc-up/-/read-babelrc-up-1.1.0.tgz#10fd5baaf6ca03eaba6748fa65ddae25bca61e70"
integrity sha512-fcl0JeI85Ss3//kfC3z2rsG2VxSiHl1bJgpjQWrne2YuQEewZpAgAjb17A6q/Q3ozWeZsUSroiIBVsnjmOU8vw==
dependencies:
find-up "^4.1.0"
json5 "^2.1.2"
read-pkg-up@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
@ -8396,6 +8786,15 @@ scheduler@^0.19.1:
loose-envify "^1.1.0"
object-assign "^4.1.1"
schema-utils@*:
version "2.7.1"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
dependencies:
"@types/json-schema" "^7.0.5"
ajv "^6.12.4"
ajv-keywords "^3.5.2"
schema-utils@2.6.6:
version "2.6.6"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c"
@ -8505,6 +8904,11 @@ 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.3:
version "2.4.6"
resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.6.tgz#43bdea028b9e6f176474ee5298e758b4a44799c3"
integrity sha512-mNCnTUF0OYPwYzSHbdRdCfNNHqrne+HS5tS5xNb6yJbdP9wInV0q5xPLE0EyfV/Q3tImo3y/OXpD8Jn0Jtnjrg==
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@ -8550,6 +8954,11 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
shallow-equal@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
@ -8587,6 +8996,11 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
slash@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
slash@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
@ -8649,6 +9063,13 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
sort-keys@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.0.0.tgz#56dc5e256637bfe3fec8db0dc57c08b1a2be22d6"
integrity sha512-hlJLzrn/VN49uyNkZ8+9b+0q9DjmmYcYOnbMQtpkLrYpPwRApDPZfmqbUfJnAA3sb/nRib+nDot7Zi/1ER1fuA==
dependencies:
is-plain-obj "^2.0.0"
source-list-map@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
@ -8984,7 +9405,7 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
dependencies:
ansi-regex "^4.1.0"
strip-bom@4.0.0:
strip-bom@4.0.0, strip-bom@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
@ -9487,7 +9908,7 @@ typeorm@^0.2.26:
yargonaut "^1.1.2"
yargs "^13.2.1"
typescript@^4.0.2:
typescript@^4.0, typescript@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2"
integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==
@ -9570,6 +9991,11 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@ -9887,6 +10313,18 @@ write-file-atomic@^3.0.0:
signal-exit "^3.0.2"
typedarray-to-buffer "^3.1.5"
write-json-file@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d"
integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==
dependencies:
detect-indent "^6.0.0"
graceful-fs "^4.1.15"
is-plain-obj "^2.0.0"
make-dir "^3.0.0"
sort-keys "^4.0.0"
write-file-atomic "^3.0.0"
write@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3"

Loading…
Cancel
Save