diff --git a/.alexrc.js b/.alexrc.js index 71913eb..bd676be 100644 --- a/.alexrc.js +++ b/.alexrc.js @@ -1,4 +1,13 @@ // Use a "maybe" level of profanity instead of the default "unlikely". exports.profanitySureness = 1 -exports.allow = ["simple", "special", "invalid", "he-she", "her-him", "herself-himself", "obvious"] +exports.allow = [ + "simple", + "special", + "invalid", + "he-she", + "her-him", + "herself-himself", + "obvious", + "easy", +] diff --git a/.prettierrc b/.prettierrc index 77b066d..abe4813 100644 --- a/.prettierrc +++ b/.prettierrc @@ -8,7 +8,9 @@ "files": "*.mdx", "options": { "printWidth": 74, - "proseWrap": "always" + "proseWrap": "always", + "bracketSpacing": true, + "trailingComma": "es5" } } ] diff --git a/README.md b/README.md index ee04909..f7d345a 100644 --- a/README.md +++ b/README.md @@ -70,3 +70,24 @@ Example: ``` If you aren't totally sure how the slug should look like, or just want to automate the process, run `yarn english-slugify` + +## Cards + +You can use cards, like the one at the start of [_API Routes_](https://blitzjs.com/docs/api-routes) like this: + +```md + + +Unlike Next.js, your `api/` folder should be a sibling of `pages/` instead +of being nested inside. But `pages/api` is still supported for +compatibility with Next.js. + + +``` + +Properties: + +- `type`: `'caution' | 'info' | 'note'` +- `title`: `string` (optional) + +**Remember to leave an empty line** between the component tag and the content as shown in the example above. diff --git a/app/core/components/DarkModeToggle.js b/app/core/components/DarkModeToggle.js index 4ea7f87..3fe4169 100644 --- a/app/core/components/DarkModeToggle.js +++ b/app/core/components/DarkModeToggle.js @@ -18,7 +18,7 @@ const DarkModeToggle = ({className}) => { return ( ) diff --git a/app/core/components/SponsorPack.js b/app/core/components/SponsorPack.js index 61c9fb9..cc91e93 100644 --- a/app/core/components/SponsorPack.js +++ b/app/core/components/SponsorPack.js @@ -20,6 +20,14 @@ const sponsors = [ tier: 3, cost: 250, }, + { + name: "RIT", + href: + "https://rit-inc.co.jp/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021", + imageUrl: "https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/rit_logo.png", + tier: 3, + cost: 250, + }, { name: "Andreas", href: "https://andreas.fyi/", @@ -53,7 +61,7 @@ const sponsors = [ { name: "userTrack", href: "https://www.usertrack.net/?ref=blitzjs_web", - imageUrl: "https://i.imgur.com/UDBeazC.png", + imageUrl: "https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/usertrack.png", tier: 4, cost: 100, }, diff --git a/app/core/components/docs/Card.js b/app/core/components/docs/Card.js new file mode 100644 index 0000000..c09bc6a --- /dev/null +++ b/app/core/components/docs/Card.js @@ -0,0 +1,44 @@ +import clsx from "clsx" + +import styles from "./Card.module.css" + +/** + * @param {{type: 'caution' | 'info' | 'note', title: string, children: any}} + * @returns + */ +export function Card({type, title, children}) { + const defaultTitle = type[0].toUpperCase() + type.substr(1) + + return ( +
+
+ + + + {title || defaultTitle} +
+
{children}
+
+ ) +} + +const InfoIcon = () => ( + + + + +) diff --git a/app/core/components/docs/Card.module.css b/app/core/components/docs/Card.module.css new file mode 100644 index 0000000..61bd0ff --- /dev/null +++ b/app/core/components/docs/Card.module.css @@ -0,0 +1,30 @@ +.container { + @apply p-5 mb-4 rounded-xl; + + a { + /* Remember to change this if you update the a (anchor, link) styles */ + @apply text-purple-light font-medium no-underline hover:underline; + } +} + +.heading { + @apply mt-0 mb-4 capitalize font-bold flex items-center text-black; +} + +.icon { + @apply inline-block align-middle mr-2; + + svg { + @apply block w-4 h-4 stroke-0; + } +} + +.content { + * { + @apply text-black; + } + + strong { + color: inherit !important; + } +} diff --git a/app/core/components/home/HeroCode.js b/app/core/components/home/HeroCode.js index cc6dd7c..39eb781 100644 --- a/app/core/components/home/HeroCode.js +++ b/app/core/components/home/HeroCode.js @@ -7,11 +7,11 @@ import tokenize from "../../macros/tokenize.macro.js" const pageTokenized = tokenize.jsx( `// app/pages/projects/new.tsx -import { Link, useRouter, useMutation, BlitzPage } from "blitz" +import { Link, Routes, useRouter, useMutation, BlitzPage } from "blitz" import Layout from "app/core/layouts/Layout" // Merk op hoe we de server functie rechtstreeks importeren import createProject, {CreateProject} from "app/projects/mutations/createProject" -import { ProjectForm, FORM_ERROR } from "app/projects/components/ProjectForm" +import { ProjectForm } from "app/projects/components/ProjectForm" const NewProjectPage: BlitzPage = () => { const router = useRouter() @@ -25,6 +25,7 @@ const NewProjectPage: BlitzPage = () => { submitText="Project aanmaken" schema={CreateProject} onSubmit={async (values) => { +<<<<<<< HEAD try { // Dit is hetzelfde als de server functie rechtstreeks te callen const project = await createProjectMutation(values) @@ -32,6 +33,12 @@ const NewProjectPage: BlitzPage = () => { } catch (error) { return { [FORM_ERROR]: error.toString() } } +======= + // This is equivalent to calling the server function directly + const project = await createProjectMutation(values) + // Notice the 'Routes' object Blitz provides for routing + router.push(Routes.ProjectsPage({projectId: project.id}})) +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa }} /> diff --git a/app/core/components/home/VideoPlayer.js b/app/core/components/home/VideoPlayer.js index 9606cb2..a5e31d2 100644 --- a/app/core/components/home/VideoPlayer.js +++ b/app/core/components/home/VideoPlayer.js @@ -1,4 +1,4 @@ -import ReactPlayer from "react-player" +import ReactPlayer from "react-player/lazy" const VideoPlayer = ({url, className = ""}) => { return ( @@ -9,6 +9,7 @@ const VideoPlayer = ({url, className = ""}) => { width="100%" height="100%" controls={true} + light={true} /> ) diff --git a/app/core/layouts/ContentsLayout.js b/app/core/layouts/ContentsLayout.js index a2f3eae..cfa85ec 100644 --- a/app/core/layouts/ContentsLayout.js +++ b/app/core/layouts/ContentsLayout.js @@ -176,7 +176,7 @@ export function ContentsLayout({children, meta, tableOfContents: toc}) { *:first-child { - @apply mt-2; -} - -.admonition.admonition-caution { - @apply bg-supplementary-yellow; -} - -.admonition.admonition-info { - @apply bg-supplementary-blue; -} - -.admonition.admonition-note { - @apply bg-blue-primary; -} - -.admonition .admonition-heading { - @apply capitalize font-bold; -} - -.admonition .admonition-heading > * { - @apply flex items-center; - margin-top: 0; -} - -.admonition .admonition-icon { - @apply mr-2; -} - -.admonition .admonition-icon { - @apply mr-2; -} - -.dark .admonition .admonition-heading h5 { - @apply text-black; -} - -.dark .admonition .admonition-content.admonition-content { - @apply text-black; -} - -.dark .admonition .admonition-content.admonition-content strong { - color: inherit; -} - .topic-select .topic-select__placeholder, .topic-select .topic-select__menu-list, .topic-select .topic-select__single-value { diff --git a/app/pages/_app.js b/app/pages/_app.js index 44c65e5..a969109 100644 --- a/app/pages/_app.js +++ b/app/pages/_app.js @@ -71,7 +71,7 @@ export default function App({Component, pageProps, router}) { - + diff --git a/app/pages/docs/api-routes.mdx b/app/pages/docs/api-routes.mdx index d141d7c..ff15244 100644 --- a/app/pages/docs/api-routes.mdx +++ b/app/pages/docs/api-routes.mdx @@ -3,13 +3,13 @@ title: API Routes sidebar_label: API Routes --- - -:::info -Unlike Next.js, your `api/` folder should be a sibling of `pages/` -instead of being nested inside. But `pages/api` is still supported for + + +Unlike Next.js, your `api/` folder should be a sibling of `pages/` instead +of being nested inside. But `pages/api` is still supported for compatibility with Next.js. -::: - + + Any file inside an `api/` folder are accessible at a URL corresponding to its path inside `api/`. So `app/projects/api/webhook.ts` will be at @@ -19,11 +19,12 @@ For example, the following API route `app/api/hello.js` handles a `json` response: ```ts -export default (req: BlitzApiRequest, res: BlitzApiResponse) => { +const handler = (req: BlitzApiRequest, res: BlitzApiResponse) => { res.statusCode = 200 res.setHeader("Content-Type", "application/json") - res.end(JSON.stringify({name: "John Doe"})) + res.end(JSON.stringify({ name: "John Doe" })) } +export default handler ``` For an API route to work, you need to export as default a function (a.k.a @@ -36,17 +37,30 @@ For an API route to work, you need to export as default a function (a.k.a [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse), plus some helper functions you can see [here](#response-helpers) +If you want to avoid writting the types `BlitzApiRequest` and +`BlitzApiResponse` everywhere, you can use `BlitzApiHandler`: + +```ts +const handler: BlitzApiHandler = (req, res) => { + res.statusCode = 200 + res.setHeader("Content-Type", "application/json") + res.end(JSON.stringify({ name: "John Doe" })) +} +export default handler +``` + To handle different HTTP methods in an API route, you can use `req.method` in your request handler, like so: ```ts -export default (req: BlitzApiRequest, res: BlitzApiResponse) => { +const handler: BlitzApiHandler = (req, res) => { if (req.method === "POST") { // Process a POST request } else { // Handle any other HTTP method } } +export default handler ``` To fetch API endpoints, take a look into any of the examples at the start @@ -67,25 +81,25 @@ You can use the `getSession` function to get the session of the user. Here is an example using session in a API route `app/api/customRoute.tsx`: ```ts -import {getSession, BlitzApiRequest, BlitzApiResponse} from "blitz" +import { getSession, BlitzApiRequest, BlitzApiResponse } from "blitz" export default async function customRoute( req: BlitzApiRequest, - res: BlitzApiResponse, + res: BlitzApiResponse ) { const session = await getSession(req, res) console.log("User ID:", session.userId) res.statusCode = 200 res.setHeader("Content-Type", "application/json") - res.end(JSON.stringify({userId: session.userId})) + res.end(JSON.stringify({ userId: session.userId })) } ``` This is called in the frontend like this: ```ts -import {getAntiCSRFToken} from "blitz" +import { getAntiCSRFToken } from "blitz" const antiCSRFToken = getAntiCSRFToken() const response = await window.fetch("/api/customRoute", { @@ -105,13 +119,14 @@ Dynamic API routes follow the same file naming rules used for `pages`. For example, the API route `app/api/post/[pid].js` has the following code: ```ts -export default (req: BlitzApiRequest, res: BlitzApiResponse) => { +const handler: BlitzApiHandler = (req, res) => { const { - query: {pid}, + query: { pid }, } = req res.end(`Post: ${pid}`) } +export default handler ``` Now, a request to `/api/post/abc` will respond with the text: `Post: abc`. @@ -150,26 +165,27 @@ example) to the api handler, and it will always be an array, so, the path `/api/post/a` will have the following `query` object: ```json -{"slug": ["a"]} +{ "slug": ["a"] } ``` And in the case of `/api/post/a/b`, and any other matching path, new parameters will be added to the array, like so: ```json -{"slug": ["a", "b"]} +{ "slug": ["a", "b"] } ``` An API route for `app/api/post/[...slug].js` could look like this: ```ts -export default (req: BlitzApiRequest, res: BlitzApiResponse) => { +const handler: BlitzApiHandler = (req, res) => { const { - query: {slug}, + query: { slug }, } = req res.end(`Post: ${slug.join(", ")}`) } +export default handler ``` Now, a request to `/api/post/a/b/c` will respond with the text: @@ -209,9 +225,10 @@ the developer experience and increase the speed of creating new API endpoints, take a look at the following example: ```ts -export default (req: BlitzApiRequest, res: BlitzApiResponse) => { - res.status(200).json({name: "Blitz.js"}) +const handler: BlitzApiHandler = (req, res) => { + res.status(200).json({ name: "Blitz.js" }) } +export default handler ``` The included helpers are: @@ -338,7 +355,7 @@ async function handler(req: BlitzApiRequest, res: BlitzApiResponse) { await runMiddleware(req, res, cors) // Rest of the API logic - res.json({message: "Hello Everyone!"}) + res.json({ message: "Hello Everyone!" }) } export default handler diff --git a/app/pages/docs/app-component.mdx b/app/pages/docs/app-component.mdx index a5bf723..eff4ea3 100644 --- a/app/pages/docs/app-component.mdx +++ b/app/pages/docs/app-component.mdx @@ -16,7 +16,7 @@ Het standaard `_app.tsx` bestand ziet er als volgt uit: ```tsx // app/pages/_app.tsx -export default function App({Component, pageProps}) { +export default function App({ Component, pageProps }) { return } ``` @@ -25,7 +25,27 @@ De `Component` prop is de actieve pagina, dus wanneer je tussen routes navigeert, zal `Component` veranderen naar de nieuwe pagina. Daarom zullen alle props die je naar `Component` stuurt door de pagina worden ontvangen. +<<<<<<< HEAD `pageProps` is een object met de initiële props die vooraf zijn geladen voor jouw pagina door één van onze methodes om data op te vragen zoals [`getStaticProps`](./get-static-props) of [`getServerSideProps`](./get-server-side-props) +======= +`pageProps` is an object with the initial props that were preloaded for +your page by one of our data fetching methods like +[`getStaticProps`](./get-static-props) or +[`getServerSideProps`](./get-server-side-props), otherwise it's an empty +object. + +### Caveats {#caveats} + +- Adding a custom `getInitialProps` in your `App` will disable + [Automatic Static Optimization](./pages#automatic-static-optimization) + in pages without [Static Generation](./get-static-props). +- When you add `getInitialProps` in your custom app, you must + `import App from "blitz"`, call `App.getInitialProps(appContext)` inside + `getInitialProps` and merge the returned object into the return value. +- `App` currently does not support page data fetching methods like + [`getStaticProps`](./get-static-props) or + [`getServerSideProps`](./get-server-side-props). +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa diff --git a/app/pages/docs/auth-utils.mdx b/app/pages/docs/auth-utils.mdx index 3c3780b..a88abb8 100644 --- a/app/pages/docs/auth-utils.mdx +++ b/app/pages/docs/auth-utils.mdx @@ -10,7 +10,7 @@ sidebar_label: Hooks & Utilities ### Example {#example} ```ts -import {useSession} from "blitz" +import { useSession } from "blitz" const session = useSession() ``` @@ -36,7 +36,7 @@ This will throw `AuthenticationError` if the user is not logged in ### Example {#example-1} ```ts -import {useAuthenticatedSession} from "blitz" +import { useAuthenticatedSession } from "blitz" const session = useAuthenticatedSession() ``` @@ -62,7 +62,7 @@ This will throw `AuthenticationError` if the user is not logged in ### Example {#example-2} ```ts -import {useAuthorize} from "blitz" +import { useAuthorize } from "blitz" useAuthorize() ``` @@ -85,7 +85,7 @@ for logged out users. ### Example {#example-3} ```ts -import {useRedirectAuthenticated} from "blitz" +import { useRedirectAuthenticated } from "blitz" useRedirectAuthenticated("/dashboard") ``` @@ -111,7 +111,7 @@ like password resets. #### Example Usage ```ts -import {generateToken} from "blitz" +import { generateToken } from "blitz" const token = generateToken() ``` @@ -128,7 +128,7 @@ tokens before saving them in the database. #### Example Usage ```ts -import {hash256} from "blitz" +import { hash256 } from "blitz" const hashedToken = hash256(token) ``` @@ -140,7 +140,7 @@ const hashedToken = hash256(token) a nice way to hash passwords and verify password hashes. ```ts -import {SecurePassword} from "blitz" +import { SecurePassword } from "blitz" await SecurePassword.hash(password) await SecurePassword.verify(passwordHash, password) @@ -180,31 +180,31 @@ Size of the `hash` Buffer returned by `hash` and `hashSync` and used by #### Example Usage ```ts -import {SecurePassword, AuthenticationError} from "blitz" +import { SecurePassword, AuthenticationError } from "blitz" import db from "db" export const authenticateUser = async ( email: string, - password: string, + password: string ) => { - const user = await db.user.findFirst({where: {email}}) + const user = await db.user.findFirst({ where: { email } }) if (!user) throw new AuthenticationError() const result = await SecurePassword.verify( user.hashedPassword, - password, + password ) if (result === SecurePassword.VALID_NEEDS_REHASH) { // Upgrade hashed password with a more secure hash const improvedHash = await SecurePassword.hash(password) await db.user.update({ - where: {id: user.id}, - data: {hashedPassword: improvedHash}, + where: { id: user.id }, + data: { hashedPassword: improvedHash }, }) } - const {hashedPassword, ...rest} = user + const { hashedPassword, ...rest } = user return rest } ``` diff --git a/app/pages/docs/authorization.mdx b/app/pages/docs/authorization.mdx index 3e3c562..0b92563 100644 --- a/app/pages/docs/authorization.mdx +++ b/app/pages/docs/authorization.mdx @@ -78,7 +78,7 @@ which we include in all our code generation templates. Without this, users may be able to access data or perform actions that are forbidden. ```ts -import {resolver} from "blitz" +import { resolver } from "blitz" import db from "db" import * as z from "zod" @@ -97,9 +97,9 @@ export default resolver.pipe( resolver.authorize(), async (input, ctx) => { // TODO: in multi-tenant app, you must add validation to ensure correct tenant - const projects = await db.projects.create({data: input}) + const projects = await db.projects.create({ data: input }) return projects - }, + } ) ``` @@ -132,12 +132,17 @@ pages, set `Page.redirectAuthenticatedTo = '/'` to automatically redirect logged in users to another page. ```tsx +import { Routes } from "blitz" + const Page: BlitzPage = () => { return
{/* ... */}
} // highlight-start +// using full path Page.redirectAuthenticatedTo = "/" +// using route manifest +Page.redirectAuthenticatedTo = Routes.Home() // highlight-end export default Page @@ -221,7 +226,7 @@ on first load. You can fix that by setting [`Page.suppressFirstRenderFlicker = true`](./pages##automatic-static-optimization) ```tsx -import {useSession} from "blitz" +import { useSession } from "blitz" const session = useSession() @@ -238,7 +243,7 @@ New Blitz apps by default have a `useCurrentUser()` hook and a corresponding `getCurrentUser` query. ```tsx -import {useCurrentUser} from "app/hooks/useCurrentUser" +import { useCurrentUser } from "app/core/hooks/useCurrentUser" const user = useCurrentUser() @@ -265,15 +270,15 @@ Always returns a boolean indicating if user is authorized commonly use to secure your queries and mutations. ```ts -import {Ctx} from "blitz" -import {GetUserInput} from "./somewhere" +import { Ctx } from "blitz" +import { GetUserInput } from "./somewhere" -export default async function getUser({where}: GetUserInput, ctx: Ctx) { +export default async function getUser({ where }: GetUserInput, ctx: Ctx) { // highlight-start ctx.session.$authorize("admin") // highlight-end - return await db.user.findOne({where}) + return await db.user.findOne({ where }) } ``` @@ -286,7 +291,7 @@ set up by default in new apps). ```js // blitz.config.js -const {sessionMiddleware, simpleRolesIsAuthorized} = require("blitz") +const { sessionMiddleware, simpleRolesIsAuthorized } = require("blitz") module.exports = { middleware: [ @@ -302,7 +307,7 @@ module.exports = { And if using Typescript, set the type in `types.ts` like this: ```ts -import {SimpleRolesIsAuthorized} from "blitz" +import { SimpleRolesIsAuthorized } from "blitz" type Role = "ADMIN" | "USER" @@ -354,7 +359,10 @@ type CustomIsAuthorizedArgs = { ctx: any args: [/* args that you want for session.$authorize(...args) */] } -export function customIsAuthorized({ctx, args}: CustomIsAuthorizedArgs) { +export function customIsAuthorized({ + ctx, + args, +}: CustomIsAuthorizedArgs) { // can access ctx.session, ctx.session.userId, etc } ``` diff --git a/app/pages/docs/background-processing-with-quirrel.mdx b/app/pages/docs/background-processing-with-quirrel.mdx index 7b4bd08..4a84534 100644 --- a/app/pages/docs/background-processing-with-quirrel.mdx +++ b/app/pages/docs/background-processing-with-quirrel.mdx @@ -57,7 +57,7 @@ First, you define your ```ts // app/api/booking-reminder import db from "db" -import {Queue} from "quirrel/blitz" +import { Queue } from "quirrel/blitz" import sms from "some-sms-provider" // it's important to export it as default @@ -65,15 +65,15 @@ export default Queue( "api/booking-reminder", // 👈 the route that it's reachable on async (bookingId: number) => { const booking = await db.booking.findUnique({ - where: {id: bookingId}, - include: {user: true, event: true}, + where: { id: bookingId }, + include: { user: true, event: true }, }) await sms.send({ to: booking.user.phoneNumber, content: `Put on your dancing shoes for ${booking.event.title} 🕺`, }) - }, + } ) ``` @@ -137,7 +137,7 @@ the perfect fit. ```ts // app/api/monthly-invoice import db from "db" -import {CronJob} from "quirrel/blitz" +import { CronJob } from "quirrel/blitz" import stripe from "stripe" export default CronJob( @@ -148,9 +148,9 @@ export default CronJob( await Promise.all( customers.map(async (customer) => { await stripe.finalizeInvoice(customer.stripeId) - }), + }) ) - }, + } ) ``` @@ -161,8 +161,8 @@ Again, [`CronJob`](https://docs.quirrel.dev/api/cronjob) is a great fit. ```ts // app/api/remove-old-data import db from "db" -import {CronJob} from "quirrel/blitz" -import {subDays} from "date-fns" +import { CronJob } from "quirrel/blitz" +import { subDays } from "date-fns" export default CronJob( "api/remove-old-data", // 👈 the route that it's reachable on @@ -178,7 +178,7 @@ export default CronJob( }, }, }) - }, + } ) ``` @@ -204,7 +204,7 @@ import csvProcessingQueue from "app/api/process-csv" export default async function uploadCsvForProcessing(data: string) { const record = await db.uploadedCsv.create({ - data: {data}, + data: { data }, }) await csvProcessingQueue.enqueue(record.id) @@ -221,16 +221,16 @@ set it to true). ```ts // app/api/process-csv import db from "db" -import {Queue} from "quirrel/blitz" +import { Queue } from "quirrel/blitz" export default Queue("api/process-csv", async (uploadId: number) => { const upload = await db.uplodadedCsv.findUnique({ - where: {id: uploadId}, + where: { id: uploadId }, }) await doYourProcessing(upload.data) - await db.uplodadedCsv.delete({where: {id: uploadId}}) + await db.uplodadedCsv.delete({ where: { id: uploadId } }) }) ``` @@ -242,7 +242,7 @@ can look it up in your own database: import db from "db" export default async function hasFinishedProcessing(uploadId: number) { - const count = await db.uploadedCsv.count({where: {uploadId}}) + const count = await db.uploadedCsv.count({ where: { uploadId } }) return count === 0 } ``` diff --git a/app/pages/docs/blitz-config.mdx b/app/pages/docs/blitz-config.mdx index 12f99d6..2d162fb 100644 --- a/app/pages/docs/blitz-config.mdx +++ b/app/pages/docs/blitz-config.mdx @@ -3,11 +3,8 @@ title: blitz.config.js sidebar_label: blitz.config.js --- -You can customize advanced behavior of Blitz with `blitz.config.js`. - -`blitz.config.js` is a regular Node.js module, not a JSON file. It gets -used by the Blitz server and build phases, and it's not included in the -browser build. +You can customize advanced behavior of Blitz with `blitz.config.js` or +`blitz.config.ts`. Take a look at the following `blitz.config.js` example: @@ -20,7 +17,7 @@ module.exports = { You can also use a function: ```js -module.exports = (phase, {defaultConfig}) => { +module.exports = (phase, { defaultConfig }) => { return { /* config options here */ } @@ -33,9 +30,9 @@ can see the available phases Phases can be imported from `next/constants`: ```js -const {PHASE_DEVELOPMENT_SERVER} = require("next/constants") +import { PHASE_DEVELOPMENT_SERVER } from "next/constants" -module.exports = (phase, {defaultConfig}) => { +module.exports = (phase, { defaultConfig }) => { if (phase === PHASE_DEVELOPMENT_SERVER) { return { /* development only config options here */ @@ -57,10 +54,6 @@ understand what each config does, instead, search for the features you need to enable or modify in this section and they will show you what to do. -> Avoid using new JavaScript features not available in your target Node.js -> version. `blitz.config.js` will not be parsed by Webpack, Babel or -> TypeScript. - ## Webpack Config {#webpack-config} You can customize the Blitz webpack config. See @@ -93,9 +86,6 @@ module.exports = { } ``` -> Deployments to [Vercel](https://vercel.com) will automatically enable -> this target. You should not opt-into it yourself. - ## Middleware {#middleware} HTTP middleware can be added queries and mutations. @@ -129,6 +119,8 @@ module.exports = { ## CLI {#cli} +### Clear Console On Blitz Dev {#clear-console-on-blitz-dev} + When you run `blitz dev`, the console gets cleared. You can disable it by setting the `cli.clearConsoleOnBlitzDev` to `false`: @@ -140,6 +132,25 @@ module.exports = { } ``` +### Proxy support {#proxy-support} + +Proxy support is enabled automatically for recipe install if either +`http_proxy` or `https_proxy` environment variable is present. You can +also set proxy using: + +```js +module.exports = { + cli: { + httpProxy: "http://127.0.0.1:8080", + httpsProxy: "http://127.0.0.1:8080", + noProxy: "localhost", + }, +} +``` + +Please note that proxy configuration in `blitz.config.js` will override +environment proxy configuration. + ## CDN Support with Asset Prefix {#cdn-support-with-asset-prefix} To set up a [CDN](https://en.wikipedia.org/wiki/Content_delivery_network), @@ -304,8 +315,8 @@ re-building as the value is inlined in the client-side bundles. ### Links {#links} -When linking to other pages using `blitz/link` and `blitz/router` the -`basePath` will be automatically applied. +When linking to other pages using `Link` and `Router` the `basePath` will +be automatically applied. For example using `/about` will automatically become `/docs/about` when `basePath` is set to `/docs`. @@ -314,7 +325,7 @@ For example using `/about` will automatically become `/docs/about` when export default function HomePage() { return ( <> - +
About Page @@ -331,732 +342,6 @@ Output html: This makes sure that you don't have to change all links in your application when changing the `basePath` value. -## Rewrites {#rewrites} - -Rewrites allow you to map an incoming request path to a different -destination path. - -Rewrites are only available on the Node.js environment and do not affect -client-side routing. - -Rewrites are not able to override public files or routes in the pages -directory as these have higher priority than rewrites. For example, if you -have `pages/index.js` you are not able to rewrite `/` to another location -unless you rename the `pages/index.js` file. - -To use rewrites you can use the `rewrites` key in `blitz.config.js`: - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/about", - destination: "/", - }, - ] - }, -} -``` - -`rewrites` is an async function that expects an array to be returned -holding objects with `source` and `destination` properties: - -- `source` is the incoming request path pattern. -- `destination` is the path you want to route to. - -### Rewrite parameters {#rewrite-parameters} - -When using parameters in a rewrite the parameters will be passed in the -query by default when none of the parameters are used in the -`destination`. - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/old-about/:path*", - destination: "/about", // The :path parameter isn't used here so will be automatically passed in the query - }, - ] - }, -} -``` - -If a parameter is used in the destination none of the parameters will be -automatically passed in the query. - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/docs/:path*", - destination: "/:path*", // The :path parameter is used here so will not be automatically passed in the query - }, - ] - }, -} -``` - -You can still pass the parameters manually in the query if one is already -used in the destination by specifying the query in the `destination`. - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/:first/:second", - destination: "/:first?second=:second", - // Since the :first parameter is used in the destination the :second parameter - // will not automatically be added in the query although we can manually add it - // as shown above - }, - ] - }, -} -``` - -### Path Matching {#path-matching} - -Path matches are allowed, for example `/blog/:slug` will match -`/blog/hello-world` (no nested paths): - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/blog/:slug", - destination: "/news/:slug", // Matched parameters can be used in the destination - }, - ] - }, -} -``` - -#### Wildcard Path Matching - -To match a wildcard path you can use `*` after a parameter, for example -`/blog/:slug*` will match `/blog/a/b/c/d/hello-world`: - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/blog/:slug*", - destination: "/news/:slug*", // Matched parameters can be used in the destination - }, - ] - }, -} -``` - -#### Regex Path Matching - -To match a regex path you can wrap the regex in parenthesis after a -parameter, for example `/blog/:slug(\\d{1,})` will match `/blog/123` but -not `/blog/abc`: - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/old-blog/:post(\\d{1,})", - destination: "/blog/:post", // Matched parameters can be used in the destination - }, - ] - }, -} -``` - -### Rewriting to an external URL {#rewriting-to-an-external-url} - -Rewrites allow you to rewrite to an external url. This is especially -useful for incrementally adopting Next.js. - -```js -module.exports = { - async rewrites() { - return [ - { - source: "/blog/:slug", - destination: "https://example.com/blog/:slug", // Matched parameters can be used in the destination - }, - ] - }, -} -``` - -#### Incremental adoption of Blitz - -You can also make Blitz check the application routes before falling back -to proxying to the previous website. - -This way you don't have to change the rewrites configuration when -migrating more pages to Blitz - -```js -module.exports = { - async rewrites() { - return [ - // we need to define a no-op rewrite to trigger checking - // all pages/static files before we attempt proxying - { - source: "/:path*", - destination: "/:path*", - }, - { - source: "/:path*", - destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`, - }, - ] - }, -} -``` - -#### Rewrites with basePath support - -When leveraging [`basePath` support](#base-path) with rewrites each -`source` and `destination` is automatically prefixed with the `basePath` -unless you add `basePath: false` to the rewrite: - -```js -module.exports = { - basePath: "/docs", - - async rewrites() { - return [ - { - source: "/with-basePath", // automatically becomes /docs/with-basePath - destination: "/another", // automatically becomes /docs/another - }, - { - // does not add /docs to /without-basePath since basePath: false is set - // Note: this can not be used for internal rewrites e.g. `destination: '/another'` - source: "/without-basePath", - destination: "https://example.com", - basePath: false, - }, - ] - }, -} -``` - -#### Rewrites with i18n support - -When leveraging [`i18n` support](/docs/i18n-routing) with rewrites each -`source` and `destination` is automatically prefixed to handle the -configured `locales` unless you add `locale: false` to the rewrite. If -`locale: false` is used you must prefix the `source` and `destination` -with a locale for it to be matched correctly. - -```js -module.exports = { - i18n: { - locales: ["en", "fr", "de"], - defaultLocale: "en", - }, - - async rewrites() { - return [ - { - source: "/with-locale", // automatically handles all locales - destination: "/another", // automatically passes the locale on - }, - { - // does not handle locales automatically since locale: false is set - source: "/nl/with-locale-manual", - destination: "/nl/another", - locale: false, - }, - { - // this matches '/' since `en` is the defaultLocale - source: "/en", - destination: "/en/another", - locale: false, - }, - ] - }, -} -``` - -## Redirects {#redirects} - -Redirects allow you to redirect an incoming request path to a different -destination path. - -Redirects are only available on the Node.js environment and do not affect -client-side routing. - -To use Redirects you can use the `redirects` key in `blitz.config.js`: - -```js -module.exports = { - async redirects() { - return [ - { - source: "/about", - destination: "/", - permanent: true, - }, - ] - }, -} -``` - -`redirects` is an async function that expects an array to be returned -holding objects with `source`, `destination`, and `permanent` properties: - -- `source` is the incoming request path pattern. -- `destination` is the path you want to route to. -- `permanent` if the redirect is permanent or not. - -### Path Matching {#path-matching-1} - -Path matches are allowed, for example `/old-blog/:slug` will match -`/old-blog/hello-world` (no nested paths): - -```js -module.exports = { - async redirects() { - return [ - { - source: "/old-blog/:slug", - destination: "/news/:slug", // Matched parameters can be used in the destination - permanent: true, - }, - ] - }, -} -``` - -#### Wildcard Path Matching - -To match a wildcard path you can use `*` after a parameter, for example -`/blog/:slug*` will match `/blog/a/b/c/d/hello-world`: - -```js -module.exports = { - async redirects() { - return [ - { - source: "/blog/:slug*", - destination: "/news/:slug*", // Matched parameters can be used in the destination - permanent: true, - }, - ] - }, -} -``` - -#### Regex Path Matching - -To match a regex path you can wrap the regex in parenthesis after a -parameter, for example `/post/:slug(\\d{1,})` will match `/post/123` but -not `/post/abc`: - -```js -module.exports = { - async redirects() { - return [ - { - source: "/post/:slug(\\d{1,})", - destination: "/news/:slug", // Matched parameters can be used in the destination - permanent: false, - }, - ] - }, -} -``` - -#### Redirects with basePath support - -When leveraging [`basePath` support](#base-path) with redirects each -`source` and `destination` is automatically prefixed with the `basePath` -unless you add `basePath: false` to the redirect: - -```js -module.exports = { - basePath: "/docs", - - async redirects() { - return [ - { - source: "/with-basePath", // automatically becomes /docs/with-basePath - destination: "/another", // automatically becomes /docs/another - permanent: false, - }, - { - // does not add /docs since basePath: false is set - source: "/without-basePath", - destination: "/another", - basePath: false, - permanent: false, - }, - ] - }, -} -``` - -#### Redirects with i18n support - -When leveraging [`i18n` support](/docs/i18n-routing) with redirects each -`source` and `destination` is automatically prefixed to handle the -configured `locales` unless you add `locale: false` to the redirect. If -`locale: false` is used you must prefix the `source` and `destination` -with a locale for it to be matched correctly. - -```js -module.exports = { - i18n: { - locales: ["en", "fr", "de"], - defaultLocale: "en", - }, - - async redirects() { - return [ - { - source: "/with-locale", // automatically handles all locales - destination: "/another", // automatically passes the locale on - permanent: false, - }, - { - // does not handle locales automatically since locale: false is set - source: "/nl/with-locale-manual", - destination: "/nl/another", - locale: false, - permanent: false, - }, - { - // this matches '/' since `en` is the defaultLocale - source: "/en", - destination: "/en/another", - locale: false, - permanent: false, - }, - ] - }, -} -``` - -In some rare cases, you might need to assign a custom status code for -older HTTP Clients to properly redirect. In these cases, you can use the -`statusCode` property instead of the `permanent` property, but not both. -Note: to ensure IE11 compatibility a `Refresh` header is automatically -added for the 308 status code. - -## Headers {#headers} - -Headers allow you to set custom HTTP headers for an incoming request path. - -To set custom HTTP headers you can use the `headers` key in -`blitz.config.js`: - -```js -module.exports = { - async headers() { - return [ - { - source: "/about", - headers: [ - { - key: "x-custom-header", - value: "my custom header value", - }, - { - key: "x-another-custom-header", - value: "my other custom header value", - }, - ], - }, - ] - }, -} -``` - -`headers` is an async function that expects an array to be returned -holding objects with `source` and `headers` properties: - -- `source` is the incoming request path pattern. -- `headers` is an array of header objects with the `key` and `value` - properties. - -### Header Overriding Behavior {#header-overriding-behavior} - -If two headers match the same path and set the same header key, the last -header key will override the first. Using the below headers, the path -`/hello` will result in the header `x-hello` being `world` due to the last -header value set being `world`. - -```js -module.exports = { - async headers() { - return [ - { - source: '/:path*', - headers: [ - { - key: 'x-hello', - value: 'there', - }, - ], - }, - { - source: '/hello', - headers: [ - { - key: 'x-hello', - value: 'world', - }, - ], - }, - ], - }, -} -``` - -### Path Matching {#path-matching-2} - -Path matches are allowed, for example `/blog/:slug` will match -`/blog/hello-world` (no nested paths): - -```js -module.exports = { - async headers() { - return [ - { - source: '/blog/:slug', - headers: [ - { - key: 'x-slug', - value: ':slug', // Matched parameters can be used in the value - }, - { - key: 'x-slug-:slug', // Matched parameters can be used in the key - value: 'my other custom header value', - }, - ], - }, - ], - }, -} -``` - -#### Wildcard Path Matching - -To match a wildcard path you can use `*` after a parameter, for example -`/blog/:slug*` will match `/blog/a/b/c/d/hello-world`: - -```js -module.exports = { - async headers() { - return [ - { - source: '/blog/:slug*', - headers: [ - { - key: 'x-slug', - value: ':slug*', // Matched parameters can be used in the value - }, - { - key: 'x-slug-:slug*', // Matched parameters can be used in the key - value: 'my other custom header value', - }, - ], - }, - ], - }, -} -``` - -#### Regex Path Matching - -To match a regex path you can wrap the regex in parenthesis after a -parameter, for example `/blog/:slug(\\d{1,})` will match `/blog/123` but -not `/blog/abc`: - -```js -module.exports = { - async headers() { - return [ - { - source: '/blog/:post(\\d{1,})', - headers: [ - { - key: 'x-post', - value: ':post', - }, - ], - }, - ], - }, -} -``` - -#### Headers with basePath support - -When leveraging [`basePath` support](#base-path) with headers each -`source` is automatically prefixed with the `basePath` unless you add -`basePath: false` to the header: - -```js -module.exports = { - basePath: "/docs", - - async headers() { - return [ - { - source: "/with-basePath", // becomes /docs/with-basePath - headers: [ - { - key: "x-hello", - value: "world", - }, - ], - }, - { - source: "/without-basePath", // is not modified since basePath: false is set - headers: [ - { - key: "x-hello", - value: "world", - }, - ], - basePath: false, - }, - ] - }, -} -``` - -#### Headers with i18n support - -When leveraging [`i18n` support](/docs/i18n-routing) with headers each -`source` is automatically prefixed to handle the configured `locales` -unless you add `locale: false` to the header. If `locale: false` is used -you must prefix the `source` with a locale for it to be matched correctly. - -```js -module.exports = { - i18n: { - locales: ["en", "fr", "de"], - defaultLocale: "en", - }, - - async headers() { - return [ - { - source: "/with-locale", // automatically handles all locales - headers: [ - { - key: "x-hello", - value: "world", - }, - ], - }, - { - // does not handle locales automatically since locale: false is set - source: "/nl/with-locale-manual", - locale: false, - headers: [ - { - key: "x-hello", - value: "world", - }, - ], - }, - { - // this matches '/' since `en` is the defaultLocale - source: "/en", - locale: false, - headers: [ - { - key: "x-hello", - value: "world", - }, - ], - }, - ] - }, -} -``` - -#### Cache-Control - -Cache-Control headers set in blitz.config.js will be overwritten in -production to ensure that static assets can be cached effectively. If you -need to revalidate the cache of a page that has been -[statically generated](/docs/get-static-props#when-should-i-use-getstaticprops), -you can do so by setting `revalidate` in the page's -[`getStaticProps`](/docs/get-static-props) function. - -## Export Path Map {#export-path-map} - -`exportPathMap` allows you to specify a mapping of request paths to page -destinations, to be used during [export](static-html-export). Paths -defined in `exportPathMap` will also be available when using `blitz dev`. - -`exportPathMap` is an async function that receives 2 arguments: the first -one is `defaultPathMap`, which is the default map used by Blitz. The -second argument is an object with: - -- `dev` - `true` when `exportPathMap` is being called in development. - `false` when running `blitz export`. In development `exportPathMap` is - used to define routes. -- `dir` - Absolute path to the project directory -- `outDir` - Absolute path to the `out/` directory - ([configurable with `-o`](cli-export)). When `dev` is `true` the value - of `outDir` will be `null`. -- `distDir` - Absolute path to the `.next/` directory (configurable with - the [`distDir` config](#setting-a-custom-build-directory)) -- `buildId` - The generated build id - -The returned object is a map of pages where the `key` is the `pathname` -and the `value` is an object that accepts the following fields: - -- `page`: `String` - the page inside the pages directory to render -- `query`: `Object` - the query object passed to `getStaticProps` when - prerendering. Defaults to `{}` - -> The exported `pathname` can also be a filename (for example, -> `/readme.md`), but you may need to set the `Content-Type` header to -> `text/html` when serving its content if it is different than `.html`. - -#### Example - -Original pages: - -- `pages/index.js` -- `pages/about.js` -- `pages/post.js` - -`blitz.config.js`: - -```js -module.exports = { - exportPathMap: async function ( - defaultPathMap, - {dev, dir, outDir, distDir, buildId}, - ) { - return { - "/": {page: "/"}, - "/about": {page: "/about"}, - "/p/hello-nextjs": {page: "/post", query: {title: "hello-nextjs"}}, - "/p/learn-nextjs": {page: "/post", query: {title: "learn-nextjs"}}, - "/p/deploy-nextjs": { - page: "/post", - query: {title: "deploy-nextjs"}, - }, - } - }, -} -``` - ## Trailing Slash {#trailing-slash} By default Blitz will redirect urls with trailing slashes to their @@ -1095,19 +380,18 @@ module.exports = { } ``` -### React Mode {#react-mode} +### React Root Mode {#react-mode} By default Blitz uses [React Concurrent Mode](https://reactjs.org/docs/concurrent-mode-intro.html). -You can disable it by changing `experimental.reactMode` to `legacy`. +You can disable it by changing `experimental.reactRoot` to `false`. -- Default: `concurrent` -- Options: `concurrent` | `legacy` +- Default: `true` ```js module.exports = { experimental: { - reactMode: "legacy", + reactRoot: false, }, } ``` diff --git a/app/pages/docs/cli-codegen.mdx b/app/pages/docs/cli-codegen.mdx new file mode 100644 index 0000000..36f03d5 --- /dev/null +++ b/app/pages/docs/cli-codegen.mdx @@ -0,0 +1,20 @@ +--- +title: blitz codegen +sidebar_label: blitz codegen +--- + +**Alias: `blitz cg`** + +Use this command to generate the [Route Manifest](./route-manifest). + +#### Options + +None + +#### Example + +``` +> blitz codegen + +✔ Compiled +``` diff --git a/app/pages/docs/cli-db.mdx b/app/pages/docs/cli-db.mdx index 643c3c6..b2cb5d8 100644 --- a/app/pages/docs/cli-db.mdx +++ b/app/pages/docs/cli-db.mdx @@ -3,13 +3,13 @@ title: blitz db sidebar_label: blitz db --- - -:::caution -This command is now deprecated in favor of using the -`blitz prisma` command. The `blitz db seed` command still works until -Prisma finishes adding their native seeding functionatily. -::: - + + +This command is now deprecated in favor of using the `blitz prisma` +command. The `blitz db seed` command still works until Prisma finishes +adding their native seeding functionatily. + + ### `blitz db seed` {#blitz-db-seed} diff --git a/app/pages/docs/cli-dev.mdx b/app/pages/docs/cli-dev.mdx index 3b80c3e..260407b 100644 --- a/app/pages/docs/cli-dev.mdx +++ b/app/pages/docs/cli-dev.mdx @@ -14,6 +14,7 @@ Starts the Blitz development server. | `--hostname` | `-H` | Set the hostname to use for the server. | `"localhost"` | | `--port` | `-p` | Set the port you'd like the server to listen on. | `3000` | | `--no-incremental-build` | | Disable incremental build and start from a fresh cache | `false` | +| `--inspect` | | Enable the Node.js inspector | `false` | #### Examples diff --git a/app/pages/docs/cli-start.mdx b/app/pages/docs/cli-start.mdx index 3abdee1..6010aae 100644 --- a/app/pages/docs/cli-start.mdx +++ b/app/pages/docs/cli-start.mdx @@ -13,14 +13,15 @@ Starts the Blitz production server. | ------------ | --------- | ------------------------------------------------ | ------------- | | `--hostname` | `-H` | Set the hostname to use for the server. | `"localhost"` | | `--port` | `-p` | Set the port you'd like the server to listen on. | `3000` | +| `--inspect` | | Enable the Node.js inspector | `false` | #### Examples - -:::note + + Make sure to run `blitz build` before running `blitz start` -::: - + + ```bash blitz start diff --git a/app/pages/docs/code-splitting.mdx b/app/pages/docs/code-splitting.mdx index e5dea78..ebeb9c8 100644 --- a/app/pages/docs/code-splitting.mdx +++ b/app/pages/docs/code-splitting.mdx @@ -34,7 +34,7 @@ In the following example, the module `../components/hello` will be dynamically loaded by the page: ```jsx -import {dynamic} from "blitz" +import { dynamic } from "blitz" const DynamicComponent = dynamic(() => import("../components/hello")) @@ -55,6 +55,14 @@ export default Home `../components/hello`. It works like a regular React Component, and you can pass props to it as you normally would. +> **Note**: In `import('path/to/component')`, the path must be explicitly +> written. It can't be a template string nor a variable. Furthermore the +> `import()` has to be inside the `dynamic()` call for Next.js to be able +> to match webpack bundles / module ids to the specific `dynamic()` call +> and preload them before rendering. `dynamic()` can't be used inside of +> React rendering as it needs to be marked in the top level of the module +> for preloading to work, similar to `React.lazy`. + ## With named exports {#with-named-exports} If the dynamic component is not the default export, you can use a named @@ -74,10 +82,10 @@ returned by like so: ```jsx -import {dynamic} from "blitz" +import { dynamic } from "blitz" const DynamicComponent = dynamic(() => - import("../components/hello").then((mod) => mod.Hello), + import("../components/hello").then((mod) => mod.Hello) ) function Home() { @@ -99,13 +107,13 @@ An optional `loading` component can be added to render a loading state while the dynamic component is being loaded. For example: ```jsx -import {dynamic} from "blitz" +import { dynamic } from "blitz" const DynamicComponentWithCustomLoading = dynamic( () => import("../components/hello"), { loading: () =>

...

, - }, + } ) function Home() { @@ -129,13 +137,13 @@ when the module includes a library that only works in the browser. Take a look at the following example: ```jsx -import {dynamic} from "blitz" +import { dynamic } from "blitz" const DynamicComponentWithNoSSR = dynamic( () => import("../components/hello3"), { ssr: false, - }, + } ) function Home() { diff --git a/app/pages/docs/contributing.mdx b/app/pages/docs/contributing.mdx index 6449a50..56184d6 100644 --- a/app/pages/docs/contributing.mdx +++ b/app/pages/docs/contributing.mdx @@ -149,6 +149,17 @@ Most Blitz packages in `packages/` have jest unit tests. Blitz integration tests are inside the root `test/` folder. +Make sure you have `chromedriver` installed for your Chrome version. You +can install it with + +- `brew install --cask chromedriver` on Mac OS X +- `chocolatey install chromedriver` on Windows +- Or manually download the version that matches your installed chrome + version (if there's no match, download a version under it, but not + above) from the + [chromedriver repo](https://chromedriver.storage.googleapis.com/index.html) + and add the binary to `/node_modules/.bin` + You can run all integration tests by running `yarn test:integration` from the repo root. Or you can run `yarn testheadles` to run them in headless mode (so it doesn't open a web browser window). @@ -191,18 +202,18 @@ The typical workflow will be only run next.js integation tests related to your change. Then push to CI and see if any other intergration tests fail. If they do, then locally run the one that fails and fix the issue. -### Testing Development Version of Blitz Inside and App {#testing-development-version-of-blitz} +### Testing Development Version of Blitz Inside an App {#testing-development-version-of-blitz} + + - -:::info -Currently, to test the local dev version of Blitz, you can -**only** test an app inside the `blitz/examples/` folder. In there, the -blitz dependency will automatically use the local dev version. We mainly -use the `auth` and `store` example apps. We use them for development -testing and for blitz integration tests. You must also make sure you are -running `yarn dev` in the `blitz` folder at the same time. -::: - +Currently, to test the local dev version of Blitz, you can **only** test +an app inside the `blitz/examples/` folder. In there, the blitz dependency +will automatically use the local dev version. We mainly use the `auth` and +`store` example apps. We use them for development testing and for blitz +integration tests. You must also make sure you are running `yarn dev` in +the `blitz` folder at the same time. + + For using in apps outside the repo, [yalc](https://github.com/whitecolor/yalc) should work, but hasn't been @@ -269,3 +280,9 @@ If you run into symlink and EPERM errors when trying to run Preconstruct on Windows, you may need to enable [Windows Developer Mode](https://www.howtogeek.com/292914/what-is-developer-mode-in-windows-10/) so that Preconstruct can create symlinks. + +#### Missing files in Windows + +If you have errors about missing files even after you run `yarn build`, +try cloning again your repository with the configuration `core.symlinks` +set to `true` like this: `git clone -c core.symlinks=true `. diff --git a/app/pages/docs/css.mdx b/app/pages/docs/css.mdx index a943398..e13fd76 100644 --- a/app/pages/docs/css.mdx +++ b/app/pages/docs/css.mdx @@ -27,7 +27,7 @@ Then, import the `styles.css` file. ```jsx import "../styles.css" -export default function App({Component, pageProps}) { +export default function App({ Component, pageProps }) { return } ``` diff --git a/app/pages/docs/custom-server.mdx b/app/pages/docs/custom-server.mdx index 77a8e1a..d47d1ed 100644 --- a/app/pages/docs/custom-server.mdx +++ b/app/pages/docs/custom-server.mdx @@ -8,7 +8,9 @@ some other direct control over the web server itself. ### How {#how} -1. Add a `server.js` file in your project root. See below for an example. +1. Add a `server.ts` or `server.js` file in your project root. Or you can + use `server/index.js` or `server/index.ts`. See below for an example + server. 2. Now `blitz dev` and `blitz start` will automatically detect and use your custom server. @@ -16,48 +18,52 @@ some other direct control over the web server itself. Here's an example custom server: -```js -// server.js -const {createServer} = require("http") -const {parse} = require("url") -const blitz = require("blitz/custom-server") +```ts +// server.ts +import blitz from "blitz/custom-server" +import { createServer } from "http" +import { parse } from "url" +import { log } from "@blitzjs/display" +const { PORT = "3000" } = process.env const dev = process.env.NODE_ENV !== "production" -const app = blitz({dev}) +const app = blitz({ dev }) const handle = app.getRequestHandler() app.prepare().then(() => { createServer((req, res) => { // Be sure to pass `true` as the second argument to `url.parse`. // This tells it to parse the query portion of the URL. - const parsedUrl = parse(req.url, true) - const {pathname, query} = parsedUrl + const parsedUrl = parse(req.url!, true) + const { pathname } = parsedUrl + + if (pathname === "/hello") { + res.writeHead(200).end("world") + return + } - if (pathname === "/a") { + if (pathname === "/hello") { + res.writeHead(200).end("world") + return + } else if (pathname === "/a") { app.render(req, res, "/a", query) } else if (pathname === "/b") { app.render(req, res, "/b", query) } else { handle(req, res, parsedUrl) } - }).listen(3000, (err) => { - if (err) throw err - console.log("> Ready on http://localhost:3000") + + handle(req, res, parsedUrl) + }).listen(PORT, () => { + log.success(`Ready on http://localhost:${PORT}`) }) }) ``` -> `server.js` doesn't go through babel or webpack. Make sure the syntax -> and sources this file requires are compatible with the current node -> version you are running. - --- -The custom server uses the following import to connect the server with the -Blitz application: - -The above `blitz` import is a function that receives an object with the -following options: +The above `blitz/custom-server` import is a function that receives an +object with the following options: - `dev`: `Boolean` - Whether or not to launch Blitz in dev mode. Defaults to `false` @@ -72,10 +78,10 @@ required. ## Disabling file-system routing {#disabling-file-system-routing} -By default, `blitz` will serve each file in the `pages` folder under a -pathname matching the filename. If your project uses a custom server, this -behavior may result in the same content being served from multiple paths, -which can present problems with SEO and UX. +By default, `blitz` will serve each file `pages` folders under a pathname +matching the filename. If your project uses a custom server, this behavior +may result in the same content being served from multiple paths, which can +present problems with SEO and UX. To disable this behavior and prevent routing based on files in `pages`, open `blitz.config.js` and disable the `useFileSystemPublicRoutes` config: diff --git a/app/pages/docs/database-overview.mdx b/app/pages/docs/database-overview.mdx index 4f601d3..b5f670b 100644 --- a/app/pages/docs/database-overview.mdx +++ b/app/pages/docs/database-overview.mdx @@ -3,13 +3,13 @@ title: Database Overview sidebar_label: Overview --- - -:::info + + If you are totally new to Databases, check out [Prisma's Data Guide](https://www.prisma.io/dataguide/) which covers the very large majority of everything you might want to know. -::: - + + By default, Blitz uses Prisma 2 which is a strongly typed database client. @@ -40,8 +40,8 @@ model Task { > If you need, > [reference the Prisma Schema documentation](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model) -2. Then run `blitz prisma migrate dev --preview-feature` in your terminal - to apply the changes +2. Then run `blitz prisma migrate dev` in your terminal to apply the + changes 3. Now you can import `db` from `db/index.ts` and create a model like this: - `db.project.create({data: {name: 'Hello'}})` @@ -67,6 +67,5 @@ datasource db { your setup, you may need to modify the URL. 3. Update `.env.test.local` as well to use PostgreSQL in your test runs. 4. Delete the `db/migrations` folder -5. Run `blitz prisma migrate dev --preview-feature`. This command will - create the database (if it does not already exist) and tables based on - your schema. +5. Run `blitz prisma migrate dev`. This command will create the database + (if it does not already exist) and tables based on your schema. diff --git a/app/pages/docs/database-seeds.mdx b/app/pages/docs/database-seeds.mdx index 1b689ef..6cb9974 100644 --- a/app/pages/docs/database-seeds.mdx +++ b/app/pages/docs/database-seeds.mdx @@ -40,7 +40,7 @@ model Task { import db from "./index" const seed = async () => { - const project = await db.project.create({data: {name: "FooBar"}}) + const project = await db.project.create({ data: { name: "FooBar" } }) for (let i = 0; i < 5; i++) { await db.task.create({ diff --git a/app/pages/docs/deploy-heroku.mdx b/app/pages/docs/deploy-heroku.mdx index 3e5936e..8375a24 100644 --- a/app/pages/docs/deploy-heroku.mdx +++ b/app/pages/docs/deploy-heroku.mdx @@ -3,8 +3,7 @@ title: Deploy to a Server on Heroku sidebar_label: To Heroku --- - -:::info + This guide assumes the following: @@ -16,8 +15,7 @@ This guide assumes the following: 4. That deployments will be made with git and the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). -::: - + **In Heroku:** @@ -62,7 +60,7 @@ heroku git:remote --app following content. ``` -release: npx blitz prisma migrate deploy --preview-feature +release: npx blitz prisma migrate deploy web: npm run start:production ``` @@ -94,4 +92,8 @@ heroku config:set SESSION_SECRET_KEY= #### SSL Certificates -On the free tier, Heroku does not supply you with SSL certificates. These are crucial for secure authentication, though - and Blitz' built-in authentication won't work without. You can use [Cloudflare SSL](https://support.cloudflare.com/hc/en-us/articles/205893698-Configure-Cloudflare-and-Heroku-over-HTTPS) to get free SSL certificates. +On the free tier, Heroku does not supply you with SSL certificates. These +are crucial for secure authentication, though - and Blitz' built-in +authentication won't work without. You can use +[Cloudflare SSL](https://support.cloudflare.com/hc/en-us/articles/205893698-Configure-Cloudflare-and-Heroku-over-HTTPS) +to get free SSL certificates. diff --git a/app/pages/docs/deploy-railway.mdx b/app/pages/docs/deploy-railway.mdx new file mode 100644 index 0000000..80126de --- /dev/null +++ b/app/pages/docs/deploy-railway.mdx @@ -0,0 +1,121 @@ +--- +title: Deploy to a Server on Railway +sidebar_label: To Railway +--- + +## If you don't have a Railway account {#signup} + +Sign up for an account on [Railway](https://railway.app) - they have a +free tier that is sufficient for small applications. + +![Screen Shot 2021-05-04 at 6 11 09 PM](https://user-images.githubusercontent.com/19371989/117007314-13ee3580-ad1c-11eb-9705-2ca9b5f545bd.png) + +## Set up a new project {#setup} + +1. Create a new project (via your + [Dashboard](https://railway.app/dashboard) or `⌘ + /` shortcut) + +![Screen Shot 2021-05-04 at 5 19 28 PM](https://user-images.githubusercontent.com/19371989/117007376-28323280-ad1c-11eb-90a5-9fa5c165f5df.png) + +2. If a database is required, select **Provision PostgreSQL** (or + MongoDB/MySQL/Redis - whichever flavour your app requires). Once the + database is provisioned, you will see the Project Setup page. + +![Screen Shot 2021-05-04 at 6 01 16 PM](https://user-images.githubusercontent.com/19371989/117007600-6deefb00-ad1c-11eb-876c-22a374c1f535.png) + +If a database is not required, select **Deploy From Repo**. + +There are two ways to set up your project on Railway: + +1. [Via the command line interface (CLI)](#cli) +2. [Via Railway's user interface (GUI)](#gui) + +### Via CLI {#cli} + +1. Install Railway + +```bash +npm i -g @railway/cli +# or +yarn global add @railway/cli +``` + +2. Login to Railway + +``` +railway login +``` + +3. Go to your project folder and link to Railway + +``` +cd /path/to/project +railway link your-project-id +``` + +The project ID is taken from the **Project Setup** page. + +4. Enter your required environment variables + +Blitz requires the `SESSION_SECRET_KEY` variable to be set. Go to your +project on the GUI, select the Variables link and enter +`SESSION_SECRET_KEY` as the name of the variables a random 32-key secret +as its value. Click **Add** to add the variable. + +Enter other environment variables that you require. The `DATABASE_URL` +variable will be automatically set by Railway if you provision a +PostgreSQL database. + +Verify that the variables are set correctly via your linked project: + +``` +railway variables +``` + +5. Deploy your project + +``` +railway up +``` + +Once the build is successful and deployment is completed, you will receive +the URL for your application that is now accessible via the internet. To +get the URL, go to the **Deployments** section in the project's dashboard +and the URL will be listed under a successful deployment. + +![Screen Shot 2021-05-04 at 8 49 57 PM](https://user-images.githubusercontent.com/19371989/117007722-8e1eba00-ad1c-11eb-9a9e-91908e4c281c.png) + +You may also view your app logs by running + +``` +railway logs +``` + +In order to set Railway to build + deploy automatically when you push to a +branch on your GitHub repository, connect your GitHub repository by +following the [GUI](#gui) steps below from Step 2 onward. + +### Via GUI {#gui} + +1. Enter your required environment variables + +Blitz requires the `SESSION_SECRET_KEY` variable to be set. Go to your +project on the GUI, select the **Variables** link and enter +`SESSION_SECRET_KEY` as the name of the variable and a random 32-key +secret as its value. Click **Add** to add the variable. + +Enter other environment variables that you require. The `DATABASE_URL` +variable will be automatically set by Railway if you provision a database. + +2. Go to the **Deployments** section. If your project is on GitHub, you + can click on **Connect GitHub** to deploy and connect directly to your + repositories on GitHub. Otherwise, you will have to use the [CLI](#cli) + to deploy your application. + +3. Select the repository and the branch to deploy from and click + **Connect + Deploy** + +![Screen Shot 2021-05-04 at 8 55 36 PM](https://user-images.githubusercontent.com/19371989/117007814-a5f63e00-ad1c-11eb-84d6-d75019930ea1.png) + +4. Railway will now build and deploy your app on every push to this branch + on your selected repository. diff --git a/app/pages/docs/deploy-render.mdx b/app/pages/docs/deploy-render.mdx index cceda9a..ca439f4 100644 --- a/app/pages/docs/deploy-render.mdx +++ b/app/pages/docs/deploy-render.mdx @@ -46,7 +46,7 @@ services: buildCommand: yarn --frozen-lockfile --prod=false && blitz build && - blitz prisma migrate deploy --preview-feature + blitz prisma migrate deploy startCommand: blitz start envVars: - key: NODE_ENV diff --git a/app/pages/docs/deploy-vercel.mdx b/app/pages/docs/deploy-vercel.mdx index d48d6b0..0c71e29 100644 --- a/app/pages/docs/deploy-vercel.mdx +++ b/app/pages/docs/deploy-vercel.mdx @@ -3,19 +3,19 @@ title: Deploy Serverless to Vercel sidebar_label: To Vercel --- - -:::caution + + We do not recommend deploying Blitz to Vercel. Vercel is a platform optimized for frontend deployments, not fullstack. While you can deploy to Vercel, most people run into too many issues and give up. Direct SQL database connections are one of the biggest issues. You have to pay for a very expensive database to support any amount of scale. -::: - + + ## Serverless Peculiarities for SQL Databases {#peculiarities} -There are two main issues when it comes to using SQL databases in a +There are three main issues when it comes to using SQL databases in a serverless environment: ### Problem 1: Separate Locations for App and Database {#locations} @@ -35,35 +35,34 @@ outside your API handler (this is the default setup in Blitz apps). This optimizes performance because subsequent requests to the same lambda already have an active database connection. -However, this can result in a large number of idle connections. A larger -number than what your database can support. For reference, the lowest -database tier on Digital Ocean has a limit of 22 connections. +However, this can result in a large number of idle connections, larger +than what your database can support. For reference, the lowest database +tier on Digital Ocean has a limit of 22 connections. -**Solution:** The solution to this problem is to use a connection pool in -front of your database. Pgbouncer is the most popular connection pool for -postgres. Both Digital Ocean and Heroku have a feature to simply add -pgbouncer. +**Solution:** Use a connection pool in front of your database. PgBouncer +is the most popular connection pool for PostgreSQL. Both Digital Ocean and +Heroku have a feature to simply add PgBouncer. ### Problem 3: Database Throughput {#database-throughput} -Pgbouncer for PostgreSQL is advertised as allowing you to have +PgBouncer for PostgreSQL is advertised as allowing you to have 5,000-10,000 active database connections, but **it's critical to -understand that those are idle connections.** **Pgbouncer does not +understand that those are idle connections.** **PgBouncer does not increase your core database capacity.** If your database has a max of 22 connections, then you can only have 22 simultaneous transactions, -regardless of whether you have pgbouncer in front of it or not. +regardless of whether you have PgBouncer in front of it or not. **Solution:** Increase your database size to meet the traffic needs for your app. But be aware this can become very expensive. -Note: slow database transactions will greatly decrease your throughput. If -it seems you are running out of connections before you should based on +Note: Slow database transactions will greatly decrease your throughput. If +it seems you are running out of connections before you should, based on your app traffic, then turn on logging for your database queries and look for long transactions. ## Databases to Consider {#databases} -1. PostgreSQL + Pgbouncer +1. PostgreSQL + PgBouncer 2. [PlanetScaleDB](https://www.planetscale.com) - This is MySQL but seems to have solved the connection limit issue for serverless environments @@ -90,12 +89,12 @@ This also assumes you already have a [Vercel](https://vercel.com) account. [read the Prisma docs on this](https://www.prisma.io/docs/reference/database-connectors/postgresql#connection-details). 1. Make sure you get the connection string to your connection pool, not directly to the DB. - 2. If using pgBouncer (default connection pool on Digital Ocean), you + 2. If using PgBouncer (default connection pool on Digital Ocean), you must add `&pgbouncer=true` to the end of your connection string for Prisma to work correctly. 4. Change your build script in package.json to be - `NODE_ENV=production blitz build && blitz prisma migrate deploy --preview-feature` - so that the production DB will be migrated on each deploy + `NODE_ENV=production blitz build && blitz prisma migrate deploy` so + that the production DB will be migrated on each deploy 5. Add your DB url as a secret environment variable [using the UI](https://vercel.com/blog/environment-variables-ui) or by running `vercel env add DATABASE_URL` diff --git a/app/pages/docs/document-component.mdx b/app/pages/docs/document-component.mdx index 22fe218..e5068e9 100644 --- a/app/pages/docs/document-component.mdx +++ b/app/pages/docs/document-component.mdx @@ -92,7 +92,7 @@ The `ctx` parameter is an object containing the following keys: It takes as argument an options object for further customization: ```jsx -import {Document} from "blitz" +import { Document } from "blitz" class MyDocument extends Document { static async getInitialProps(ctx) { diff --git a/app/pages/docs/error-handling.mdx b/app/pages/docs/error-handling.mdx index 5e2a813..c8453ca 100644 --- a/app/pages/docs/error-handling.mdx +++ b/app/pages/docs/error-handling.mdx @@ -30,7 +30,7 @@ curious, you can [see the source code for these](https://github.com/blitz-js/blitz/blob/canary/packages/core/src/errors.ts). ```ts -import {AuthenticationError} from "blitz" +import { AuthenticationError } from "blitz" try { throw new AuthenticationError() @@ -57,27 +57,27 @@ It looks something like this: ```tsx // app/pages/_app.tsx -import {AppProps, ErrorComponent} from "blitz" -import {ErrorBoundary} from "react-error-boundary" -import {queryCache} from "react-query" +import { + AppProps, + ErrorComponent, + useQueryErrorResetBoundary, +} from "blitz" +import { ErrorBoundary } from "react-error-boundary" import LoginForm from "app/auth/components/LoginForm" -export default function App({Component, pageProps}: AppProps) { +export default function App({ Component, pageProps }: AppProps) { + // This ensures the Blitz useQuery hooks will automatically refetch + // data any time you reset the error boundary + const { reset } = useQueryErrorResetBoundary() + return ( - { - // This ensures the Blitz useQuery hooks will automatically refetch - // data any time you reset the error boundary - queryCache.resetErrorBoundaries() - }} - > + ) } -function RootErrorFallback({error, resetErrorBoundary}) { +function RootErrorFallback({ error, resetErrorBoundary }) { if (error.name === "AuthenticationError") { return } else if (error.name === "AuthorizationError") { @@ -100,7 +100,9 @@ function RootErrorFallback({error, resetErrorBoundary}) { That means all errors will at least be caught at the root level. However, you can also add `` anywhere else in your app for more -localized error handiling. If an error is caught by an `` +localized error handling. To do this, declare a separate +`useQueryErrorResetBoundary` in your component and pass it along to the +local ErrorBoundary. If an error is caught by an `` somewhere down inside your app tree, then it will not reach the root ErrorBoundary unless you re-throw it. @@ -129,7 +131,7 @@ import SuperJson from "superjson" export class UsernameTakenError extends Error { name = "UsernameTakenError" - constructor({suggestedUserName}) { + constructor({ suggestedUserName }) { super() this.suggestedUserName = suggestedUserName } @@ -138,7 +140,7 @@ export class UsernameTakenError extends Error { SuperJson.registerClass(UsernameTakenError) SuperJson.allowErrorProps("suggestedUserName") -throw new UsernameTakenError({suggestedUserName: "second_best"}) +throw new UsernameTakenError({ suggestedUserName: "second_best" }) ``` Note that you **must register it with SuperJson** as shown above in order diff --git a/app/pages/docs/error-pages.mdx b/app/pages/docs/error-pages.mdx index 15d3d81..2429d2d 100644 --- a/app/pages/docs/error-pages.mdx +++ b/app/pages/docs/error-pages.mdx @@ -34,7 +34,7 @@ component. If you wish to override it, define the file `app/pages/_error.js` and add the following code: ```jsx -function Error({statusCode}) { +function Error({ statusCode }) { return (

{statusCode @@ -44,9 +44,9 @@ function Error({statusCode}) { ) } -Error.getInitialProps = ({res, err}) => { +Error.getInitialProps = ({ res, err }) => { const statusCode = res ? res.statusCode : err ? err.statusCode : 404 - return {statusCode} + return { statusCode } } export default Error @@ -159,7 +159,7 @@ It accepts two props: - `title` - a string to display as the error message ```jsx -import {ErrorComponent} from "blitz" +import { ErrorComponent } from "blitz" export default function Page() { return @@ -167,7 +167,7 @@ export default function Page() { ``` ```jsx -import {ErrorComponent} from "blitz" +import { ErrorComponent } from "blitz" export default function Page() { return diff --git a/app/pages/docs/eslint-config.mdx b/app/pages/docs/eslint-config.mdx new file mode 100644 index 0000000..53ac31c --- /dev/null +++ b/app/pages/docs/eslint-config.mdx @@ -0,0 +1,43 @@ +--- +title: Custom ESLint Config +sidebar_label: ESLint Config +--- + +Blitz extends the +[create-react-app](https://create-react-app.dev/docs/setting-up-your-editor/#experimental-extending-the-eslint-config) +eslint config. + +Our configuration contains a few modifications, and the full preset can be +found on github +[here](https://github.com/blitz-js/blitz/blob/canary/packages/eslint-config/index.js), + +This configuration is found in .eslintrc.js, and by default is + +```js +module.exports = { + extends: ["blitz"], +} +``` + +## Extending or replacing the default Blitz ESLint config {#extending} + +You can extend the base Blitz ESLint config, or replace it completely if you need. + +There are a few things to remember: + +1. We highly recommend extending the base config, as removing it could introduce hard-to-find issues. +2. It's important to note that any rules that are set to "error" will stop the project from building. + +In the below example: + + - the base config has been extended by a shared ESLint config, + - a new rule has been set that applies to all JavaScript and TypeScript files + +```js +module.exports = { + extends: ["blitz", "shared-config"], + rules: { + "additional-rule": "warn" + }, +} +``` \ No newline at end of file diff --git a/app/pages/docs/get-server-side-props.mdx b/app/pages/docs/get-server-side-props.mdx index 199c139..853170d 100644 --- a/app/pages/docs/get-server-side-props.mdx +++ b/app/pages/docs/get-server-side-props.mdx @@ -3,9 +3,9 @@ title: getServerSideProps API sidebar_label: getServerSideProps API --- -If you export an `async` function called `getServerSideProps` from a page, -Blitz will pre-render this page on each request using the data returned by -`getServerSideProps`. +If you export an `async` function called `getServerSideProps` from a +[page](./pages), Blitz will pre-render this page on each request using the +data returned by `getServerSideProps`. ```js export async function getServerSideProps(context) { @@ -134,7 +134,7 @@ fetching data on the client side. For TypeScript, you can use the `GetServerSideProps` type from `blitz`: ```ts -import {GetServerSideProps} from "blitz" +import { GetServerSideProps } from "blitz" export const getServerSideProps: GetServerSideProps = async (context) => { // ... @@ -189,9 +189,20 @@ what Blitz eliminates from the client-side bundle. #### Only allowed in a page -`getServerSideProps` can only be exported from a **page**. You can’t -export it from non-page files. +`getServerSideProps` can only be exported from a [page](./pages). You +can’t export it from non-page files. Also, you must use `export async function getServerSideProps() {}` — it will **not** work if you add `getServerSideProps` as a property of the page component. + +#### First Render UX + +Even though a page with `getServerSideProps` will be pre-rendered on the +server, it may fallback to the page's loading state if your page contains +queries that request data missing from the initial page props. This can +create a flickering effect where the contents of the page rapidly changes +when the query data gets loaded into the app. + +[Click here](./pages#first-render-ux) to discover ways you can improve the +first render User Experience (UX) of your pages. diff --git a/app/pages/docs/get-started.mdx b/app/pages/docs/get-started.mdx index bfec852..f8de382 100644 --- a/app/pages/docs/get-started.mdx +++ b/app/pages/docs/get-started.mdx @@ -5,11 +5,21 @@ sidebar_label: Aan de slag ### Bereid je computer voor {#set-up-your-computer} +<<<<<<< HEAD Je hebt Node.js 12 of nieuwer nodig. +======= +You need Node.js 12 or newer. You can verify this by running `node -v` in +your terminal. If you don't have Node or need a newer version, we +recommend using a node version manager like +[fnm](https://github.com/Schniz/fnm). That will allow you to easily change +node versions and even have different versions for each project. +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa ### Installeer Blitz {#install-blitz} -Run `npm install -g blitz` +Run `yarn global add blitz` or `npm install -g blitz --legacy-peer-deps` +(legacy-peer-deps is needed because npm totally change behavior of peer +deps and some dependencies haven't caught up) ### Maak een nieuwe applicatie {#create-a-new-app} diff --git a/app/pages/docs/get-static-paths.mdx b/app/pages/docs/get-static-paths.mdx index 1297a11..ea77fec 100644 --- a/app/pages/docs/get-static-paths.mdx +++ b/app/pages/docs/get-static-paths.mdx @@ -239,7 +239,7 @@ that use dynamic routes. For TypeScript, you can use the `GetStaticPaths` type from `blitz`: ```ts -import {GetStaticPaths} from "blitz" +import { GetStaticPaths } from "blitz" export const getStaticPaths: GetStaticPaths = async () => { // ... diff --git a/app/pages/docs/get-static-props.mdx b/app/pages/docs/get-static-props.mdx index 9f4f34b..ee4413b 100644 --- a/app/pages/docs/get-static-props.mdx +++ b/app/pages/docs/get-static-props.mdx @@ -3,8 +3,8 @@ title: getStaticProps API sidebar_label: getStaticProps API --- - -:::info + + `getStaticProps` should only be used for pages that do not require authentication. The statically generated pages will be publicly available via your server and via a CDN if you have one. Therefore they cannot @@ -13,12 +13,12 @@ contain any personal or sensitive data. Also, this is why there is no `req` and `res` objects for `getStaticProps`, because the pages are generated at build time, not at runtime. And at build time, there is no user http request to handle. -::: - -If you export an `async` function called `getStaticProps` from a page, -Blitz will pre-render this page at build time using the props returned by -`getStaticProps`. + + +If you export an `async` function called `getStaticProps` from a +[page](./pages), Blitz will pre-render this page at build time using the +props returned by `getStaticProps`. ```jsx export async function getStaticProps(context) { @@ -170,7 +170,7 @@ You should use `getStaticProps` if: For TypeScript, you can use the `GetStaticProps` type from `blitz`: ```ts -import {GetStaticProps} from "blitz" +import { GetStaticProps } from "blitz" export const getStaticProps: GetStaticProps = async (context) => { // ... @@ -181,7 +181,7 @@ If you want to get inferred typings for your props, you can use `InferGetStaticPropsType`, like this: ```tsx -import {InferGetStaticPropsType} from "blitz" +import { InferGetStaticPropsType } from "blitz" type Post = { author: string @@ -199,7 +199,7 @@ export const getStaticProps = async () => { } } -function Blog({posts}: InferGetStaticPropsType) { +function Blog({ posts }: InferGetStaticPropsType) { // will resolve posts to type Post[] } @@ -222,7 +222,7 @@ Consider our previous [`getStaticProps` example](#simple-example), but now with regeneration enabled: ```jsx -function Blog({posts}) { +function Blog({ posts }) { return (

    {posts.map((post) => ( @@ -297,7 +297,7 @@ import fs from "fs" import path from "path" // posts will be populated at build time by getStaticProps() -function Blog({posts}) { +function Blog({ posts }) { return (
      {posts.map((post) => ( @@ -376,8 +376,8 @@ the exported JSON is used. #### Only allowed in a page -`getStaticProps` can only be exported from a **page**. You can’t export it -from non-page files. +`getStaticProps` can only be exported from a [page](./pages). You can’t +export it from non-page files. One of the reasons for this restriction is that React needs to have all the required data before the page is rendered. @@ -391,6 +391,17 @@ component. In development (`blitz dev`), `getStaticProps` will be called on every request. +#### First Render UX + +Even though a page with `getStaticProps` will be pre-rendered on the +server, it may fallback to the page's loading state if your page contains +queries that request data missing from the initial page props. This can +create a flickering effect where the contents of the page rapidly changes +when the query data gets loaded into the app. + +[Click here](./pages#first-render-ux) to discover ways you can improve the +first render User Experience (UX) of your pages. + #### Preview Mode In some cases, you might want to temporarily bypass Static Generation and diff --git a/app/pages/docs/head-component.mdx b/app/pages/docs/head-component.mdx index e82b78b..e1da3a6 100644 --- a/app/pages/docs/head-component.mdx +++ b/app/pages/docs/head-component.mdx @@ -7,7 +7,7 @@ We expose a built-in component for appending elements to the `head` of the page: ```jsx -import {Head} from "blitz" +import { Head } from "blitz" function IndexPage() { return ( @@ -32,7 +32,7 @@ which will make sure the tag is only rendered once, as in the following example: ```jsx -import {Head} from "blitz" +import { Head } from "blitz" function IndexPage() { return ( diff --git a/app/pages/docs/headers.mdx b/app/pages/docs/headers.mdx new file mode 100644 index 0000000..c9812ab --- /dev/null +++ b/app/pages/docs/headers.mdx @@ -0,0 +1,390 @@ +--- +title: HTTP Headers +sidebar_label: HTTP Headers +--- + +Headers allow you to set custom HTTP headers for an incoming request path. + +To set custom HTTP headers you can use the `headers` key in +`blitz.config.js`: + +```js +module.exports = { + async headers() { + return [ + { + source: "/about", + headers: [ + { + key: "x-custom-header", + value: "my custom header value", + }, + { + key: "x-another-custom-header", + value: "my other custom header value", + }, + ], + }, + ] + }, +} +``` + +`headers` is an async function that expects an array to be returned +holding objects with `source` and `headers` properties: + +- `source` is the incoming request path pattern. +- `headers` is an array of header objects with the `key` and `value` + properties. +- `basePath`: `false` or `undefined` - if false the basePath won't be + included when matching, can be used for external rewrites only. +- `locale`: `false` or `undefined` - whether the locale should not be + included when matching. +- `has` is an array of [has objects](#header-cookie-and-query-matching) + with the `type`, `key` and `value` properties. + +Headers are checked before the filesystem which includes pages and +`/public` files. + +## Header Overriding Behavior {#overriding} + +If two headers match the same path and set the same header key, the last +header key will override the first. Using the below headers, the path +`/hello` will result in the header `x-hello` being `world` due to the last +header value set being `world`. + +```js +module.exports = { + async headers() { + return [ + { + source: '/:path*', + headers: [ + { + key: 'x-hello', + value: 'there', + }, + ], + }, + { + source: '/hello', + headers: [ + { + key: 'x-hello', + value: 'world', + }, + ], + }, + ], + }, +} +``` + +## Path Matching {#path-matching} + +Path matches are allowed, for example `/blog/:slug` will match +`/blog/hello-world` (no nested paths): + +```js +module.exports = { + async headers() { + return [ + { + source: '/blog/:slug', + headers: [ + { + key: 'x-slug', + value: ':slug', // Matched parameters can be used in the value + }, + { + key: 'x-slug-:slug', // Matched parameters can be used in the key + value: 'my other custom header value', + }, + ], + }, + ], + }, +} +``` + +### Wildcard Path Matching {#wildcard} + +To match a wildcard path you can use `*` after a parameter, for example +`/blog/:slug*` will match `/blog/a/b/c/d/hello-world`: + +```js +module.exports = { + async headers() { + return [ + { + source: '/blog/:slug*', + headers: [ + { + key: 'x-slug', + value: ':slug*', // Matched parameters can be used in the value + }, + { + key: 'x-slug-:slug*', // Matched parameters can be used in the key + value: 'my other custom header value', + }, + ], + }, + ], + }, +} +``` + +### Regex Path Matching {#regex} + +To match a regex path you can wrap the regex in parenthesis after a +parameter, for example `/blog/:slug(\\d{1,})` will match `/blog/123` but +not `/blog/abc`: + +```js +module.exports = { + async headers() { + return [ + { + source: '/blog/:post(\\d{1,})', + headers: [ + { + key: 'x-post', + value: ':post', + }, + ], + }, + ], + }, +} +``` + +The following characters `(`, `)`, `{`, `}`, `:`, `*`, `+`, `?` are used +for regex path matching, so when used in the `source` as non-special +values they must be escaped by adding `\\` before them: + +```js +module.exports = { + async redirects() { + return [ + { + // this will match `/english(default)/something` being requested + source: "/english\\(default\\)/:slug", + destination: "/en-us/:slug", + permanent: false, + }, + ] + }, +} +``` + +## Header, Cookie, and Query Matching {#header-cookie-matching} + +To only apply a header when either header, cookie, or query values also +match the `has` field can be used. Both the `source` and all `has` items +must match for the header to be applied. + +`has` items have the following fields: + +- `type`: `String` - must be either `header`, `cookie`, `host`, or + `query`. +- `key`: `String` - the key from the selected type to match against. +- `value`: `String` or `undefined` - the value to check for, if undefined + any value will match. A regex like string can be used to capture a + specific part of the value, e.g. if the value `first-(?.*)` + is used for `first-second` then `second` will be usable in the + destination with `:paramName`. + +```js +module.exports = { + async headers() { + return [ + // if the header `x-add-header` is present, + // the `x-another-header` header will be applied + { + source: "/:path*", + has: [ + { + type: "header", + key: "x-add-header", + }, + ], + headers: [ + { + key: "x-another-header", + value: "hello", + }, + ], + }, + // if the source, query, and cookie are matched, + // the `x-authorized` header will be applied + { + source: "/specific/:path*", + has: [ + { + type: "query", + key: "page", + // the page value will not be available in the + // header key/values since value is provided and + // doesn't use a named capture group e.g. (?home) + value: "home", + }, + { + type: "cookie", + key: "authorized", + value: "true", + }, + ], + headers: [ + { + key: "x-authorized", + value: ":authorized", + }, + ], + }, + // if the header `x-authorized` is present and + // contains a matching value, the `x-another-header` will be applied + { + source: "/:path*", + has: [ + { + type: "header", + key: "x-authorized", + value: "(?yes|true)", + }, + ], + headers: [ + { + key: "x-another-header", + value: ":authorized", + }, + ], + }, + // if the host is `example.com`, + // this header will be applied + { + source: "/:path*", + has: [ + { + type: "host", + value: "example.com", + }, + ], + headers: [ + { + key: "x-another-header", + value: ":authorized", + }, + ], + }, + ] + }, +} +``` + +### Headers with basePath support {#basepath} + +When leveraging [`basePath` support](./blitz-config#base-path) with +headers each `source` is automatically prefixed with the `basePath` unless +you add `basePath: false` to the header: + +```js +module.exports = { + basePath: "/docs", + + async headers() { + return [ + { + source: "/with-basePath", // becomes /docs/with-basePath + headers: [ + { + key: "x-hello", + value: "world", + }, + ], + }, + { + source: "/without-basePath", // is not modified since basePath: false is set + headers: [ + { + key: "x-hello", + value: "world", + }, + ], + basePath: false, + }, + ] + }, +} +``` + +### Headers with i18n support {#i18n} + +When leveraging [`i18n` support](./i18n-routing) with headers each +`source` is automatically prefixed to handle the configured `locales` +unless you add `locale: false` to the header. If `locale: false` is used +you must prefix the `source` with a locale for it to be matched correctly. + +```js +module.exports = { + i18n: { + locales: ["en", "fr", "de"], + defaultLocale: "en", + }, + + async headers() { + return [ + { + source: "/with-locale", // automatically handles all locales + headers: [ + { + key: "x-hello", + value: "world", + }, + ], + }, + { + // does not handle locales automatically since locale: false is set + source: "/nl/with-locale-manual", + locale: false, + headers: [ + { + key: "x-hello", + value: "world", + }, + ], + }, + { + // this matches '/' since `en` is the defaultLocale + source: "/en", + locale: false, + headers: [ + { + key: "x-hello", + value: "world", + }, + ], + }, + { + // this gets converted to /(en|fr|de)/(.*) so will not match the top-level + // `/` or `/fr` routes like /:path* would + source: "/(.*)", + headers: [ + { + key: "x-hello", + value: "worlld", + }, + ], + }, + ] + }, +} +``` + +### Cache-Control {#cache-control} + +Cache-Control headers set in blitz.config.js will be overwritten in +production to ensure that static assets can be cached effectively. If you +need to revalidate the cache of a page that has been +[statically generated](./pages#automatic-static-optimization), you can do +so by setting `revalidate` in the page's +[`getStaticProps`](./get-static-props) function. diff --git a/app/pages/docs/how-the-community-operates.mdx b/app/pages/docs/how-the-community-operates.mdx index a16edef..60aa7e4 100644 --- a/app/pages/docs/how-the-community-operates.mdx +++ b/app/pages/docs/how-the-community-operates.mdx @@ -167,20 +167,6 @@ For more details, see [Being an L2 Maintainer](./maintainers) - - - - - + + diff --git a/app/pages/docs/i18n-routing.mdx b/app/pages/docs/i18n-routing.mdx index 4af6f30..921ddc8 100644 --- a/app/pages/docs/i18n-routing.mdx +++ b/app/pages/docs/i18n-routing.mdx @@ -9,8 +9,13 @@ routing. You can provide a list of locales, the default locale, and domain-specific locales and Blitz will automatically handle the routing. The i18n routing support is currently meant to complement existing i18n -library solutions like `react-intl`, `react-i18next`, `lingui`, `rosetta`, -and others by streamlining the routes and locale parsing. +library solutions like +[`react-intl`](https://formatjs.io/docs/getting-started/installation), +[`react-i18next`](https://react.i18next.com/), +[`lingui`](https://lingui.js.org/), +[`rosetta`](https://github.com/lukeed/rosetta), +[`next-intl`](https://github.com/amannn/next-intl) and others by +streamlining the routes and locale parsing. ## Getting started {#getting-started} @@ -194,7 +199,7 @@ locale from the currently active one. If no `locale` prop is provided, the currently active `locale` is used during client-transitions. For example: ```jsx -import {Link} from "blitz" +import { Link } from "blitz" export default function IndexPage(props) { return ( @@ -209,7 +214,7 @@ When using the `Router` methods directly, you can specify the `locale` that should be used via the transition options. For example: ```jsx -import {useRouter} from "blitz" +import { useRouter } from "blitz" export default function IndexPage(props) { const router = useRouter() @@ -217,7 +222,7 @@ export default function IndexPage(props) { return (
      { - router.push("/another", "/another", {locale: "fr"}) + router.push("/another", "/another", { locale: "fr" }) }} > to /fr/another @@ -230,7 +235,7 @@ If you have a `href` that already includes the locale you can opt-out of automatically handling the locale prefixing: ```jsx -import {Link} from "blitz" +import { Link } from "blitz" export default function IndexPage(props) { return ( @@ -279,7 +284,7 @@ being pre-rendered, you can return `notFound: true` from `getStaticProps` and this variant of the page will not be generated. ```js -export async function getStaticProps({locale}) { +export async function getStaticProps({ locale }) { // Call an external API endpoint to get posts. // You can use any data fetching library const res = await fetch(`https://.../posts?locale=${locale}`) @@ -311,11 +316,11 @@ specifying which locale you want to render. For example: ```js // pages/blog/[slug].js -export const getStaticPaths = ({locales}) => { +export const getStaticPaths = ({ locales }) => { return { paths: [ - {params: {slug: "post-1"}, locale: "en-US"}, - {params: {slug: "post-1"}, locale: "fr"}, + { params: { slug: "post-1" }, locale: "en-US" }, + { params: { slug: "post-1" }, locale: "fr" }, ], fallback: true, } diff --git a/app/pages/docs/image-optimization.mdx b/app/pages/docs/image-optimization.mdx index c78f95a..ea7da78 100644 --- a/app/pages/docs/image-optimization.mdx +++ b/app/pages/docs/image-optimization.mdx @@ -43,7 +43,7 @@ Om een afbeelding aan je applicatie toe te voegen, importeer je de `Image` component: ```jsx -import {Image} from "blitz" +import { Image } from "blitz" function Home() { return ( @@ -196,7 +196,7 @@ Neem als voorbeeld een project met volgende bestanden: We kunnen op deze manier een geoptimaliseerde afbeelding tonen: ```jsx -import {Image} from "blitz" +import { Image } from "blitz" function Home() { return ( @@ -285,9 +285,9 @@ aanneemt: - `quality` ```js -import {Image} from "blitz" +import { Image } from "blitz" -const myLoader = ({src, width, quality}) => { +const myLoader = ({ src, width, quality }) => { return `https://example.com/${src}?w=${width}&q=${quality || 75}` } @@ -347,6 +347,7 @@ De afbeeldingspositie wanneer `layout="fill"` wordt gebruikt. #### loading +<<<<<<< HEAD :::caution Deze property is enkel bedoeld voor geavanceerd gebruik. Een @@ -357,6 +358,17 @@ We raden aan om in de plaats daarvan de `priority` property te gebruiken, die de afbeelding in bijna alle gevallen eager zal laden. ::: +======= + + +This property is only meant for advanced usage. Switching an image to load +with `eager` will normally **hurt performance**. + +We recommend using the `priority` property instead, which properly loads +the image eagerly for nearly all use cases. + + +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa Het laadgedrag van de afbeelding. Standaard is dit `lazy`. diff --git a/app/pages/docs/impersonation.mdx b/app/pages/docs/impersonation.mdx index 753ee9e..3f6ed84 100644 --- a/app/pages/docs/impersonation.mdx +++ b/app/pages/docs/impersonation.mdx @@ -15,8 +15,8 @@ First, add a `impersonatingFromUserId` type to your ```ts // types.ts -import {DefaultCtx, SessionContext, DefaultPublicData} from "blitz" -import {User} from "db" +import { DefaultCtx, SessionContext, DefaultPublicData } from "blitz" +import { User } from "db" declare module "blitz" { export interface Ctx extends DefaultCtx { @@ -36,7 +36,7 @@ start the impersonation as well as stopping it. ```ts // app/auth/mutations/impersonateUser.ts -import {resolver} from "blitz" +import { resolver } from "blitz" import db from "db" import * as z from "zod" @@ -47,25 +47,25 @@ export const ImpersonateUserInput = z.object({ export default resolver.pipe( resolver.zod(ImpersonateUserInput), resolver.authorize(), - async ({userId}, ctx) => { - const user = await db.user.findFirst({where: {id: userId}}) + async ({ userId }, ctx) => { + const user = await db.user.findFirst({ where: { id: userId } }) if (!user) throw new Error("Could not find user id " + userId) await ctx.session.$create({ userId: user.id, - role: "admin", + role: user.role, orgId: user.organizationId, impersonatingFromUserId: ctx.session.userId, }) return user - }, + } ) ``` ```ts // app/auth/mutations/stopImpersonating.ts -import {resolver} from "blitz" +import { resolver } from "blitz" import db from "db" export default resolver.pipe(resolver.authorize(), async (_, ctx) => { @@ -76,7 +76,7 @@ export default resolver.pipe(resolver.authorize(), async (_, ctx) => { } const user = await db.user.findFirst({ - where: {id: userId}, + where: { id: userId }, }) if (!user) throw new Error("Could not find user id " + userId) @@ -94,12 +94,11 @@ export default resolver.pipe(resolver.authorize(), async (_, ctx) => { Add a form similar to this in order to switch users. ```tsx -import {useMutation} from "blitz" -import {queryCache} from "react-query" +import { useMutation, queryClient } from "blitz" import impersonateUser, { ImpersonateUserInput, } from "app/auth/mutations/impersonateUser" -import Form from "app/core/components/Form" +import { Form, FORM_ERROR } from "app/core/components/Form" import LabeledTextField from "app/core/components/LabeledTextField" export const ImpersonateUserForm = () => { @@ -112,7 +111,7 @@ export const ImpersonateUserForm = () => { onSubmit={async (values) => { try { await impersonateUserMutation(values) - queryCache.clear() + queryClient.clear() } catch (error) { return { [FORM_ERROR]: @@ -132,8 +131,7 @@ Lastly, add the following component at the top of your Layout(s). ```tsx // app/core/components/ImpersonatingUserNotice.tsx -import {invoke, useSession} from "blitz" -import {queryCache} from "react-query" +import { invoke, useSession, queryClient } from "blitz" import stopImpersonating from "app/auth/mutations/stopImpersonating" export const ImpersonatingUserNotice = () => { @@ -147,7 +145,7 @@ export const ImpersonatingUserNotice = () => { className="appearance-none bg-transparent text-black uppercase" onClick={async () => { await invoke(stopImpersonating, {}) - queryCache.clear() + queryClient.clear() }} > Exit diff --git a/app/pages/docs/link.mdx b/app/pages/docs/link.mdx index 83511be..13ab628 100644 --- a/app/pages/docs/link.mdx +++ b/app/pages/docs/link.mdx @@ -5,21 +5,23 @@ sidebar_label: `` is used to navigate between pages -An example of linking to `/` and `/about`: +An example of linking to `Home` and `About`: ```jsx -import {Link} from "blitz" +import {Link, Routes} from "blitz" function Home() { return (
      • - + // Option 1: use Route manifest + // Option 2: use string or location object Home
      • - + // Option 1: use Route manifest + // Option 2: use string or location object About Us
      • @@ -30,10 +32,15 @@ function Home() { export default Home ``` +The `Routes` object imported from `blitz` is automatically generated based +on the pages in your app. If your page component is named `About`, then +you can link to it with `Routes.About`. For more information, see the +[Route Manifest documentation](./route-manifest). + `Link` accepts the following props: - `href` - The path inside `pages` directory. This is the only required - prop + prop. - `as` - The path that will be rendered in the browser URL bar. Used for dynamic routes - [`passHref`](#if-the-child-is-a-custom-component-that-wraps-an-a-tag) - @@ -41,8 +48,12 @@ export default Home `false` - `prefetch` - Prefetch the page in the background. Defaults to `true`. Any `` that is in the viewport (initially or through scroll) - will be preloaded. Pages using [Static Generation](./get-static-props) - will preload `JSON` files with the data for faster page transitions. + will be preloaded. Prefetch can be disabled by passing + `prefetch={false}`. When `prefetch` is set to `false`, prefetching will + still occur on hover. Pages using + [Static Generation](./get-static-props.mdx) will preload `JSON` files + with the data for faster page transitions. Prefetching is only enabled + in production. - [`replace`](#replace-the-url-instead-of-push) - Replace the current `history` state instead of adding a new url into the stack. Defaults to `false` @@ -62,7 +73,7 @@ A `Link` to a dynamic route works like the other links. A link to the page `pages/post/[pid].js` will look like this: ```jsx - + First Post ``` @@ -73,7 +84,8 @@ Here's an example of how to create a list of links: const pids = ["id1", "id2", "id3"] { pids.map((pid) => ( - + // using Routes Manifest + // using location Post {pid} )) @@ -89,7 +101,7 @@ the `` tag will not have the `href` attribute, which might hurt your site’s SEO. ```jsx -import {Link} from "blitz" +import { Link } from "blitz" import styled from "styled-components" // This creates a custom component that wraps an tag @@ -97,7 +109,7 @@ const RedLink = styled.a` color: red; ` -function NavLink({href, name}) { +function NavLink({ href, name }) { // Must add passHref to Link return ( @@ -120,11 +132,11 @@ If the child of `Link` is a function component, in addition to using [`React.forwardRef`](https://reactjs.org/docs/react-api.html#reactforwardref): ```jsx -import {Link} from "blitz" +import { Link, Routes } from "blitz" // `onClick`, `href`, and `ref` need to be passed to the DOM element // for proper handling -const MyButton = React.forwardRef(({onClick, href}, ref) => { +const MyButton = React.forwardRef(({ onClick, href }, ref) => { return ( Click Me @@ -134,7 +146,7 @@ const MyButton = React.forwardRef(({onClick, href}, ref) => { function Home() { return ( - + ) @@ -149,12 +161,12 @@ export default Home to create the URL string. Here's how to do it: ```jsx -import {Link} from "blitz" +import { Link } from "blitz" function Home() { return ( @@ -175,7 +187,7 @@ the `history` stack. You can use the `replace` prop to prevent adding a new entry, as in the following example: ```jsx - + About us ``` @@ -186,7 +198,7 @@ new entry, as in the following example: case you don't provide an `` tag, consider the following example: ```jsx - + image ``` diff --git a/app/pages/docs/measuring-performance.mdx b/app/pages/docs/measuring-performance.mdx index dc3ac1b..2c17aeb 100644 --- a/app/pages/docs/measuring-performance.mdx +++ b/app/pages/docs/measuring-performance.mdx @@ -15,7 +15,7 @@ export function reportWebVitals(metric) { console.log(metric) } -function MyApp({Component, pageProps}) { +function MyApp({ Component, pageProps }) { return } @@ -161,7 +161,7 @@ export function reportWebVitals(metric) { if (navigator.sendBeacon) { navigator.sendBeacon(url, body) } else { - fetch(url, {body, method: "POST", keepalive: true}) + fetch(url, { body, method: "POST", keepalive: true }) } } ``` @@ -172,7 +172,7 @@ export function reportWebVitals(metric) { > (to calculate percentiles, etc...). > > ```js -> export function reportWebVitals({id, name, label, value}) { +> export function reportWebVitals({ id, name, label, value }) { > ga("send", "event", { > eventCategory: > label === "web-vital" ? "Web Vitals" : "Blitz custom metric", diff --git a/app/pages/docs/middleware.mdx b/app/pages/docs/middleware.mdx index b76fe68..72a9b1d 100644 --- a/app/pages/docs/middleware.mdx +++ b/app/pages/docs/middleware.mdx @@ -43,7 +43,7 @@ project (this is included in new apps by default). ```ts // types.ts -import {DefaultCtx, SessionContext} from "blitz" +import { DefaultCtx, SessionContext } from "blitz" declare module "blitz" { export interface Ctx extends DefaultCtx { @@ -56,7 +56,7 @@ Whatever types you add to `Ctx` add will be automatically available in your queries and mutations as shown here. ```ts -import {Ctx} from "blitz" +import { Ctx } from "blitz" export default async function getThing(input, ctx: Ctx) { // Properly typed @@ -71,8 +71,8 @@ by exporting a `middleware` array from a query or mutation. ```ts // app/products/queries/getProduct.tsx -import {Middleware} from "blitz" -import db, {FindOneProjectArgs} from "db" +import { Middleware } from "blitz" +import db, { FindOneProjectArgs } from "db" type GetProjectInput = { where: FindOneProjectArgs["where"] @@ -89,11 +89,11 @@ export const middleware: Middleware[] = [ ] export default async function getProject( - {where}: GetProjectInput, - ctx: Record = {}, + { where }: GetProjectInput, + ctx: Record = {} ) { console.log("Referer:", ctx.referer) - return await db.project.findOne({where}) + return await db.project.findOne({ where }) } ``` @@ -106,7 +106,7 @@ middleware by doing `return next()` or `await next()`. See below for the `connectMiddleware()` adapter for existing connect middleware. ```js -import {Middleware} from "blitz" +import { Middleware } from "blitz" const middleware: Middleware = async (req, res, next) => { res.blitzCtx.referer = req.headers.referer @@ -213,7 +213,7 @@ middleware to Blitz middleware. ```ts // blitz.config.js -const {connectMiddleware} = require("blitz") +const { connectMiddleware } = require("blitz") const Cors = require("cors") const cors = Cors({ diff --git a/app/pages/docs/multitenancy.mdx b/app/pages/docs/multitenancy.mdx new file mode 100644 index 0000000..8d676ce --- /dev/null +++ b/app/pages/docs/multitenancy.mdx @@ -0,0 +1,389 @@ +--- +title: Multitenancy +sidebar_label: Multitenancy +--- + +Multitenancy is a software architecture where a single app can server +multiple different users or organizations whose data is kept private from +the other users of the system. One way to do this is have a totally +separate database for each user, but that has a high operations overhead. +The most common way is to store all user data in a single database and use +foreign keys to keep data private. + +This guide shows you a good way to implement a multitenant Blitz app. + +## Data Model {#data-model} + +We recommend implementing the data model +[as described by Andrew Culver of Bullet Train](https://blog.bullettrain.co/teams-should-be-an-mvp-feature/). + +- The `Organization` is the "God" model which owns everything for an + account +- An `Organization` **has many** `User`s **through** `Membership` +- Every other model in the system has an `organizationId` to indicate who + owns it. +- A `User` can have access to multiple `Organization`s +- When assigning an entity to a user, like a task, assign the task to the + user's `Membership` instead of directly to the user. See the Bullet + Train blog post linked above for more explanation on this. + +The prisma schema looks like this: + +```prisma +model Organization { + id Int @id @default(autoincrement()) + name String + role GlobalRole + + membership Membership[] +} + +// The owners of the SaaS (you) can have a SUPERADMIN role to access all data +enum GlobalRole { + SUPERADMIN + CUSTOMER +} + +model Membership { + id Int @id @default(autoincrement()) + role MembershipRole + + organization Organization @relation(fields: [organizationId], references: [id]) + organizationId Int + + user User? @relation(fields: [userId], references: [id]) + userId Int? + + // When the user joins, we will clear out the name and email and set the user. + invitedName String? + invitedEmail String? + + @@unique([organizationId, invitedEmail]) +} + +enum MembershipRole { + OWNER + ADMIN + USER +} + +model User { + id Int @id @default(autoincrement()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + name String? + email String @unique + + memberships Membership[] +} +``` + +Then you will need to update your `signup` mutation to also create an +organization and membership at the same time as you create the user. Like +this: + +```ts +const user = await db.user.create({ + data: { + // ... + memberships: { + create: { + role: "OWNER", + organization: { + create: { + name: organizationName, + }, + }, + }, + }, + }, +}) +``` + +## User Sessions {#sessions} + +The above data model allows a single user to be in multiple organizations. +So how can we track which organization a user is currently accessing or +modifying? + +The best way is to only let a user access one organization at a time. And +then provide a menu in the UI that let's them switch which organization +they are accessing. + +To do that, first add an `orgId` field to the +[session `PublicData`](./session-management#change-session-public-data-of-current-user). + +Update `types.ts` like this: + +```diff ++import { GlobalRole, MembershipRole, Organization } from "db" + +declare module "blitz" { + export interface Ctx extends DefaultCtx { + session: SessionContext + } + export interface Session { + isAuthorized: SimpleRolesIsAuthorized + PublicData: { + userId: User["id"] ++ roles: Array ++ orgId: Organization["id"] + } + } +} +``` + +and then update all places where you call `ctx.session.$create()`. You +will need to add `orgId` and update `roles`. + +It will look something like this: + +```ts +await session.$create({ + userId: user.id, + roles: [user.role, user.memberships[0].role], + orgId: user.memberships[0].organizationId, +}) +``` + +Then you can use `ctx.session.orgId` in queries and mutations to filter +your queries based on the current organization. + +## Queries {#queries} + +You must filter all your queries by `organizationId` to ensure one user +cannot see another user's private data. + +```ts +import db from "db" + +// If you accept only the `id` as input +const project = await db.project.findFirst({ + where: { + id: input.id, + organizationId: ctx.session.orgId, + }, +}) + +// If you accept `where` as input +const projects = await db.project.findMany({ + where: { + ...input.where, + organizationId: ctx.session.orgId, + }, +}) +``` + +## Mutations {#mutations} + +When creating new entities, make sure you attach them to the current +organization. Here's an example of how to do that: + +```ts +import { resolver } from "blitz" +import db from "db" +import * as z from "zod" + +const CreateProject = z + .object({ + name: z.string(), + }) + .nonstrict() + +export default resolver.pipe( + resolver.zod(CreateProject), + resolver.authorize(), + async (input, ctx) => { + const project = await db.project.create({ + data: { + ...input, + organizationId: ctx.session.orgId, + }, + }) + + return project + } +) +``` + +You must also filter update and delete mutations by `organizationId` to +ensure another user's data can't be changed. + +Here's an example where a mutation accepts `id` that could be the id of an +entity belonging to a different organization. You could first make a +`db.project.findFirst()` query for that id and then manually verify that +`organizationId` is correct. But the easier way shown here is by adding +`organizationId` to the `db.update` `where` input. This update call will +fail if the organizationId doesn't match. + +```ts +import { resolver } from "blitz" +import db from "db" +import * as z from "zod" + +const UpdateProject = z + .object({ + id: z.number(), + name: z.string(), + }) + .nonstrict() + +export default resolver.pipe( + resolver.zod(UpdateProject), + resolver.authorize(), + async ({ id, ...data }, ctx) => { + const project = await db.project.update({ + where: { + id, + // Filter by organizationId + organizationId: ctx.session.orgId, + }, + data, + }) + + return project + } +) +``` + +## Advanced Authorization {#authorization} + +You can do more advanced things like calling `ctx.session.$authorize()` +inside an if/else + +```ts +import { resolver } from "blitz" +import db, { GlobalRole, MembershipRole } from "db" +import * as z from "zod" + +const UpdateProject = z + .object({ + id: z.number(), + organizationId: z.number(), + name: z.string(), + }) + .nonstrict() + +export default resolver.pipe( + resolver.zod(UpdateProject), + // Ensure all users are logged in + resolver.authorize(), + async ({ id, organizationId, ...data }, ctx) => { + // if organizationId doesn't match current organization + if (organizationId !== ctx.session.orgId) { + // Require SUPERADMIN role + ctx.session.$authorize(GlobalRole.SUPERADMIN) + } else if (!ctx.session.accessibleProjects.includes(id)) { + // If user doesn't have specific access to this project, + // require them to be a project manager + ctx.session.$authorize(MembershipRole.PROJECT_MANAGER) + } + + const project = await db.project.update({ + where: { + id, + organizationId, + }, + data, + }) + + return project + } +) +``` + +#### Utilities + +Here's some advanced utilities that allow you to do authorization in a way +that allows SUPERADMINs to access all organizations but only permits +regular users to access the organization they are currently logged in to. + +```ts +// app/orders/queries/getOrder.ts +import { NotFoundError, resolver } from "blitz" +import db from "db" +import * as z from "zod" +import { + enforceAdminOrProctorIfNotCurrentOrganization, + setDefaultOrganizationId, +} from "app/core/utils" + +const GetOrder = z.object({ + id: z.number(), + organizationId: z.number().optional(), +}) + +export default resolver.pipe( + resolver.zod(GetOrder), + // Ensure user is logged in + resolver.authorize(), //highlight-line + // Set input.organizationId to the current organization if one is not set + // This allows SUPERADMINs to pass in a specific organizationId + setDefaultOrganizationId, //highlight-line + // But now we need to enforce input.organizationId matches + // session.orgId unless user is a SUPERADMIN + enforceSuperAdminIfNotCurrentOrganization, //highlight-line + async ({ id, organizationId }) => { + const order = await db.getOrder({ + where: { + id, + // Now we can safely use organizationId to filter queries + organizationId, + }, + }) + if (!order) throw new NotFoundError() + return order + } +) +``` + +```ts +// app/core/utils.ts +import { Ctx } from "blitz" +import { Prisma, GloblRole } from "db" + +export default function assert( + condition: any, + message: string +): asserts condition { + if (!condition) throw new Error(message) +} + +export const setDefaultOrganizationId = >( + input: T, + { session }: Ctx +): T & { organizationId: Prisma.IntNullableFilter | number } => { + assert( + session.orgId, + "Missing session.orgId in setDefaultOrganizationId" + ) + if (input.organizationId) { + // Pass through the input + return input as T & { organizationId: number } + } else if (session.roles?.includes(GloblRole.SUPERADMIN)) { + // Allow viewing any organization + return { ...input, organizationId: { not: 0 } } + } else { + // Set organizationId to session.orgId + return { ...input, organizationId: session.orgId } + } +} + +export const enforceSuperAdminIfNotCurrentOrganization = < + T extends Record +>( + input: T, + ctx: Ctx +): T => { + assert(ctx.session.orgId, "missing session.orgId") + assert(input.organizationId, "missing input.organizationId") + + if (input.organizationId !== ctx.session.orgId) { + ctx.session.$authorize(GloblRole.SUPERADMIN) + } + return input +} +``` + +If you want to do more advanced authorization, check out +[Blitz Guard](https://github.com/ntgussoni/blitz-guard). diff --git a/app/pages/docs/mutation-resolvers.mdx b/app/pages/docs/mutation-resolvers.mdx index 24cbd94..5ab7018 100644 --- a/app/pages/docs/mutation-resolvers.mdx +++ b/app/pages/docs/mutation-resolvers.mdx @@ -34,20 +34,29 @@ fetching from third-party APIs. ```ts // app/products/mutations/createProduct.tsx -import {Ctx} from "blitz" -import db, {ProjectCreateArgs} from "db" +import { Ctx } from "blitz" +import db from "db" +import * as z from "zod" -type CreateProjectInput = { - data: ProjectCreateArgs["data"] -} +const CreateProject = z + .object({ + name: z.string(), + }) + .nonstrict() export default async function createProject( - {data}: CreateProjectInput, - ctx: Ctx, + input: z.infer, + ctx: Ctx ) { - // Can do any processing, fetching from other APIs, etc + // Validate input - very importnant for security + const data = CreateProject.parse(input) + + // Require user to be logged in + ctx.session.$authorize() - const project = await db.project.create({data}) + const project = await db.project.create({ data }) + + // Can do any processing, fetching from other APIs, etc return project } diff --git a/app/pages/docs/mutation-usage.mdx b/app/pages/docs/mutation-usage.mdx index 855f3ae..7b58e4a 100644 --- a/app/pages/docs/mutation-usage.mdx +++ b/app/pages/docs/mutation-usage.mdx @@ -40,14 +40,14 @@ function (props) { For complete details, see the [`useMutation` documentation](./use-mutation). - -:::info 🤔 -You may be wondering how that can work since it's importing -server code into your component: At build time, the direct function import -is swapped out with a network call. So the query function code is never -included in your client code. -::: - + + +You may be wondering how that can work since it's importing server code +into your component: At build time, the direct function import is swapped +out with a network call. So the query function code is never included in +your client code. + + ## Error Handling {#error-handling} @@ -66,9 +66,9 @@ exactly like you'd expect. So you can wrap the `invoke` in passing an options object `{refetch: false}` as the second argument. ```tsx -export default function (props: {query: {id: number}}) { - const [product, {setQueryData}] = useQuery(getProduct, { - where: {id: props.query.id}, +export default function (props: { query: { id: number } }) { + const [product, { setQueryData }] = useQuery(getProduct, { + where: { id: props.query.id }, }) const [updateProjectMutation] = useMutation(updateProject) @@ -97,8 +97,8 @@ trigger a query reload. ```tsx export default function (props) { - const [product, {refetch}] = useQuery(getProduct, { - where: {id: props.id}, + const [product, { refetch }] = useQuery(getProduct, { + where: { id: props.id }, }) const [updateProjectMutation] = useMutation(updateProject) @@ -131,10 +131,10 @@ function provided by `blitz`. ##### Example ```tsx -import {invalidateQuery} from "blitz" // highlight-line +import { invalidateQuery } from "blitz" // highlight-line import getProducts from "app/products/queries/getProducts" -const Page = function ({products}) { +const Page = function ({ products }) { return (
        -
        @@ -446,14 +509,21 @@ gemaakt hebben geen `name` veld bevat. Om dit op te lossen, vervang je export const QuestionsList = () => { const router = useRouter() const page = Number(router.query.page) || 0 - const [{questions, hasMore}] = usePaginatedQuery(getQuestions, { - orderBy: {id: "asc"}, - skip: ITEMS_PER_PAGE * page, - take: ITEMS_PER_PAGE, - }) + const [{questions, hasMore}, {isPreviousData}] = usePaginatedQuery( + getQuestions, { + orderBy: {id: "asc"}, + skip: ITEMS_PER_PAGE * page, + take: ITEMS_PER_PAGE, + }, + ) const goToPreviousPage = () => router.push({query: {page: page - 1}}) - const goToNextPage = () => router.push({query: {page: page + 1}}) + + const goToNextPage = () => { + if (!isPreviousData && hasMore) { + router.push({query: {page: page + 1}}) + } + } return (
        @@ -471,7 +541,7 @@ export const QuestionsList = () => { -
        @@ -545,7 +615,7 @@ de `Question` wordt verwijderd. We moeten tijdelijk de gegenereerde volgende toe bovenin de body van de functie: ```ts -await db.choice.deleteMany({where: {questionId: id}}) +await db.choice.deleteMany({ where: { questionId: id } }) ``` Het eindresultaat zou er zo moeten uitzien: @@ -788,8 +858,13 @@ uitzien! #### Nu is het tijd om stemmen toe te voegen! +<<<<<<< HEAD Eerst openen we `app/choices/mutations/updateChoice.ts`, updaten het zod schema en voegen een verhoger voor het aantal stemmen toe. +======= +First we need to open `app/choices/mutations/updateChoice.ts`, update the +zod schema, and add a vote increment. +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa ```diff const UpdateChoice = z @@ -879,12 +954,14 @@ export const Question = () => { const router = useRouter() const questionId = useParam("questionId", "number") const [deleteQuestionMutation] = useMutation(deleteQuestion) - const [question, {refetch}] = useQuery(getQuestion, {id: questionId}) + const [question, { refetch }] = useQuery(getQuestion, { + id: questionId, + }) const [updateChoiceMutation] = useMutation(updateChoice) const handleVote = async (id: number) => { try { - await updateChoiceMutation({id}) + await updateChoiceMutation({ id }) refetch() } catch (error) { alert( @@ -919,11 +996,11 @@ export const Question = () => { type="button" onClick={async () => { if (window.confirm("This will be deleted")) { - await deleteQuestionMutation({id: question.id}) + await deleteQuestionMutation({ id: question.id }) router.push("/questions") } }} - style={{marginLeft: "0.5rem"}} + style={{ marginLeft: "0.5rem" }} > Delete @@ -975,6 +1052,9 @@ export default resolver.pipe( + })), + }, + }, ++ include: { ++ choices: true, ++ }, + }) return question @@ -989,7 +1069,17 @@ want we hebben de gebruiker niet verplicht om drie keuzes toe voegen bij het maken van de vraag. Dus als de gebruiker later nog een keuze toevoegt door de vraag te bewerken, zal het die hier worden aangemaakt. +<<<<<<< HEAD ## Conclusie {#conclusion} +======= +## Cleanup {#cleanup} + +In order for `yarn tsc` or `git push` to succeed, you'll need to delete +`app/choices/mutations/createChoice.ts` (unused) or update the +CreateChoice zod schema to include the required fields. + +## Conclusion {#conclusion} +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa 🥳 Proficiat! Je hebt je eigen Blitz app gemaakt! Speel er gerust wat mee, of deel het met je vrienden. Nu je deze tutorial hebt afgewerkt, waarom diff --git a/app/pages/docs/use-infinite-query.mdx b/app/pages/docs/use-infinite-query.mdx index 9c08030..4b80e95 100644 --- a/app/pages/docs/use-infinite-query.mdx +++ b/app/pages/docs/use-infinite-query.mdx @@ -3,45 +3,53 @@ title: useInfiniteQuery sidebar_label: useInfiniteQuery --- +Use `useInfiniteQuery` instead of `useQuery`, if you want to show large +data gradually more. For instance, you have many numbered pages, and you +want to show the first ten pages initially. After clicking on +`Show more pages`, the user should see three pages more than before. For +this case, you can `useInfiniteQuery` as shown in the following example. + ### Example {#example} ```ts -import {useInfiniteQuery} from "blitz" -import getProjectsInfinite from "app/projects/queries/getProjectsInfinite" +import { useInfiniteQuery } from "blitz" +import getProjects from "app/projects/queries/getProjects" function Projects(props) { const [ - groupedProjects, - {isFetching, isFetchingMore, fetchMore, canFetchMore}, + projectPages, + { isFetching, isFetchingNextPage, fetchNextPage, hasNextPage }, ] = useInfiniteQuery( - getProjectsInfinite, - (page = {take: 3, skip: 0}) => page, + getProjects, + (page = { take: 3, skip: 0 }) => page, { - getFetchMore: (lastGroup) => lastGroup.nextPage, - }, + getNextPageParam: (lastPage) => lastPage.nextPage, + } ) return ( <> - {groupedProjects.map((group, i) => ( + {projectPages.map((page, i) => ( - {group.projects.map((project) => ( + {page.projects.map((project) => (

        {project.name}

        ))}
        ))}
        -
        {isFetching && !isFetchingMore ? "Fetching..." : null}
        +
        + {isFetching && !isFetchingNextPage ? "Fetching..." : null} +
        ) } @@ -50,28 +58,34 @@ function Projects(props) { And here's the query to work with that: ```ts -export default async function getProjectsInfinite({ - where, - orderBy, - take, - skip, -}: GetProjectsInfiniteInput) { - const projects = await db.project.findMany({ - where, - orderBy, - take, - skip, - }) - - const count = await db.project.count() - const hasMore = skip! + take! < count - const nextPage = hasMore ? {take, skip: skip! + take!} : null - - return { - projects, - nextPage, +import { paginate, resolver } from "blitz" +import db, { Prisma } from "db" + +interface GetProjectsInput + extends Pick< + Prisma.ProjectFindManyArgs, + "where" | "orderBy" | "skip" | "take" + > {} + +export default resolver.pipe( + resolver.authorize(), + async ({ where, orderBy, skip = 0, take = 100 }: GetProjectsInput) => { + const { items: projects, hasMore, nextPage, count } = await paginate({ + skip, + take, + count: () => db.project.count({ where }), + query: (paginateArgs) => + db.project.findMany({ ...paginateArgs, where, orderBy }), + }) + + return { + projects, + nextPage, + hasMore, + count, + } } -} +) ``` ## API {#api} @@ -79,18 +93,21 @@ export default async function getProjectsInfinite({ ```js const [ - groupedQueryFunctionResults, + pagesOfQueryResults, { - isFetching, - failureCount, - refetch, - fetchMore, - canFetchMore, - setQueryData, + pageParams, + fetchNextPage, + fetchPreviousPage, + hasNextPage, + hasPreviousPage, + isFetchingNextPage, + isFetchingPreviousPage, + ...extras } -] = useQuery(queryResolver, getQueryInputArguments, { - getFetchMore: (lastPage, allPages) => fetchMoreVariable - ...queryOptions, +] = useInfiniteQuery(queryResolver, getQueryInputArguments, { + ...options, + getNextPageParam: (lastPage, allPages) => lastPage.nextPage, + getPreviousPageParam: (firstPage, allPages) => firstPage.nextPage, }) ``` @@ -98,64 +115,71 @@ const [ - `queryResolver:` A [Blitz query resolver](./query-resolvers) - **Required** -- `getQueryInputArguments: (fetchMoreVariable) => queryInputArguments` +- `getQueryInputArguments: (fetchNextPageVariable) => queryInputArguments` - **Required** - A function that accepts the current page options and returns the `queryInputArguments` - - On the first page load, `fetchMoreVariable` is `undefined`. - - For subsequent pages, `fetchMoreVariable` is whatever is returned from - `getFetchMore()` + - On the first page load, `fetchNextPageVariable` is `undefined`. + - For subsequent pages, `fetchNextPageVariable` is whatever is returned + from `getNextPageParam()` - `options` - Optional ### Options {#options} The options are identical to the options for the -[useQuery hook](./use-query) with the addition of the following: +[useQuery hook](./use-query#options) with the addition of the following: -- `getFetchMore: Function(lastPage, allPages) => fetchMoreVariable | Boolean` +- `getNextPageParam: (lastPage, allPages) => unknown | undefined` - When new data is received for this query, this function receives both the last page of the infinite list of data and the full array of all pages. - It should return a **single variable** that will be passed as the - argument to `getQueryInputArguments()` + argument to `getQueryInputArguments()`. + - Return `undefined` to indicate there is no next page available. +- `getPreviousPageParam: (firstPage, allPages) => unknown | undefined` + - When new data is received for this query, this function receives both + the first page of the infinite list of data and the full array of all + pages. + - It should return a **single variable** that will be passed as the + argument to your `getQueryInputArguments()`. + - Return `undefined` to indicate there is no previous page available. ### Returns {#returns} -`[groupedQueryFunctionResults, queryExtras]` +`[pagesOfQueryResults, queryExtras]` -##### `groupedQueryFunctionResults: Array` +##### `pagesOfQueryResults: TData[]` -- Defaults to `[]`. -- The array will contain each "page" of data that has been requested +- Array containing all pages. ##### `queryExtras: Object` -- `isFetching: Boolean` - - Will be `true` if the query is currently fetching, including - background fetching. -- `failureCount: Integer` - - The failure count for the query. - - Incremented every time the query fails. - - Reset to `0` when the query succeeds. -- `refetch()` - `Function({ force, throwOnError }) => void` - - A function to manually refetch the query if it is stale. - - To bypass the stale check, you can pass the `force: true` option and - refetch it regardless of it's freshness - - If the query errors, the error will only be logged. If you want an - error to be thrown, pass the `throwOnError: true` option -- `fetchMore()` - - `Function(fetchMoreVariableOverride, { previous }) => Promise` +The query extras for `useInfiniteQuery` are identical to the query extas +for the [useQuery hook](./use-query#returns) with the addition of the +following: + +- `pageParams: unknown[]` + - Array containing all page params. +- `isFetchingNextPage: boolean` + - Will be `true` while fetching the next page with `fetchNextPage`. +- `isFetchingPreviousPage: boolean` + - Will be `true` while fetching the previous page with + `fetchPreviousPage`. +- `fetchNextPage: (options?: FetchNextPageOptions) => Promise` - This function allows you to fetch the next "page" of results. - - fetchMoreVariableOverride allows you to optionally override the fetch - more variable returned from your getCanFetchMore option to your query - function to retrieve the next page of results. - - previous option which will determine if the data you are fetching is - should be prepended instead of appended to your infinite list. e.g. - `fetchMore(nextPageVars, { previous: true })` -- `canFetchMore: Boolean` - - If using `paginated` mode, this will be `true` if there is more data - to be fetched (known via the required `getFetchMore` option function). + - `options.pageParam: unknown` allows you to manually specify a page + param instead of using `getNextPageParam`. +- `fetchPreviousPage: (options?: FetchPreviousPageOptions) => Promise` + - This function allows you to fetch the previous "page" of results. + - `options.pageParam: unknown` allows you to manually specify a page + param instead of using `getPreviousPageParam`. +- `hasNextPage: boolean` + - This will be `true` if there is a next page to be fetched (known via + the `getNextPageParam` option). +- `hasPreviousPage: boolean` + - This will be `true` if there is a previous page to be fetched (known + via the `getPreviousPageParam` option). - `setQueryData()` - `Function(newData, opts) => void` - A function to manually update the cache for a query. - `newData` can be an object of new data or a function that receives the diff --git a/app/pages/docs/use-mutation.mdx b/app/pages/docs/use-mutation.mdx index a7edd53..414aa08 100644 --- a/app/pages/docs/use-mutation.mdx +++ b/app/pages/docs/use-mutation.mdx @@ -39,29 +39,30 @@ function (props) { const [ invoke, { - status, + data, + error, + isError, isIdle, isLoading, + isPaused, isSuccess, - isError, - data, - error, - reset + mutate, + reset, + status, } ] = useMutation(mutationResolver, { - onMutate, - onSuccess, + mutationKey, onError, + onMutate, onSettled, - throwOnError, + onSuccess, useErrorBoundary, }) const promise = invoke(inputArguments, { - onSuccess, - onSettled, onError, - throwOnError, + onSettled, + onSuccess, }) ``` @@ -74,7 +75,12 @@ const promise = invoke(inputArguments, { ### Options {#options} -- `onMutate: Function(inputArguments) => Promise | snapshotValue` +- `mutationKey: string` + - Optional + - A mutation key can be set to inherit defaults set with + `queryClient.setMutationDefaults` or to identify the mutation in the + devtools. +- `onMutate: (variables: TVariables) => Promise | TContext | void` - Optional - This function will fire before the mutation function is fired and is passed the same variables the mutation function would receive @@ -83,55 +89,62 @@ const promise = invoke(inputArguments, { - The value returned from this function will be passed to both the `onError` and `onSettled` functions in the event of a mutation failure and can be useful for rolling back optimistic updates. -- `onSuccess: Function(data, inputArguments) => Promise | undefined` +- `onSuccess: (data: TData, variables: TVariables, context?: TContext) => Promise | void` - Optional - This function will fire when the mutation is successful and will be passed the mutation's result. - - Fires after the `mutate`-level `onSuccess` handler (if it is defined) - If a promise is returned, it will be awaited and resolved before proceeding -- `onError: Function(err, inputArguments, onMutateValue) => Promise | undefined` +- `onError: (err: TError, variables: TVariables, context?: TContext) => Promise | void` - Optional - This function will fire if the mutation encounters an error and will be passed the error. - - Fires after the `mutate`-level `onError` handler (if it is defined) - If a promise is returned, it will be awaited and resolved before proceeding -- `onSettled: Function(data, error, inputArguments, onMutateValue) => Promise | undefined` +- `onSettled: (data: TData, error: TError, variables: TVariables, context?: TContext) => Promise | void` - Optional - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error - - Fires after the `mutate`-level `onSettled` handler (if it is defined) - If a promise is returned, it will be awaited and resolved before proceeding -- `throwOnError` - - Defaults to `true` - - Set this to `false` if failed mutations should not re-throw errors - from the mutation function to the `mutate` function. +- `retry: boolean | number | (failureCount: number, error: TError) => boolean` + - If `false`, failed mutations will not retry by default. + - If `true`, failed mutations will retry infinitely. + - If set to an `number`, e.g. `3`, failed mutations will retry until the + failed mutations count meets that number. +- `retryDelay: number | (retryAttempt: number, error: TError) => number` + - This function receives a `retryAttempt` integer and the actual Error + and returns the delay to apply before the next attempt in + milliseconds. + - A function like + `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` + applies exponential backoff. + - A function like `attempt => attempt * 1000` applies linear backoff. - `useErrorBoundary` - - Defaults to false, typically you will not use this + - Defaults to the global query config's `useErrorBoundary` value, which + is `false` - Set this to true if you want mutation errors to be thrown in the render phase and propagate to the nearest error boundary ### Returns {#returns} -`[invoke, mutationExtras]` +`[mutate, mutationExtras]` -##### `invoke: Function(inputArguments, { onSuccess, onSettled, onError, throwOnError }) => Promise` +##### `mutate: (variables: TVariables, { onSuccess, onSettled, onError }) => Promise` -- The mutation function you can call with inputArguments to trigger the - mutation and optionally override the original mutation options. -- `inputArguments: any` +- The mutation function you can call with variables to trigger the + mutation and optionally override options passed to `useMutation`. +- `variables: TVariables` - Optional - - The inputArguments object to pass to the `mutationResolver`. + - The variables object to pass to the `mutationFn`. - Remaining options extend the same options described above in the `useMutation` hook. -- Lifecycle callbacks defined here will fire **after** those of the same - type defined in the `useMutation`-level options. +- If you make multiple requests, `onSuccess` will fire only after the + latest call you've made. ##### `mutationExtras: Object` -- `status: String` +- `status: string` - Will be: - `idle` initial status prior to the mutation function executing. - `loading` if the mutation is currently executing. @@ -139,11 +152,11 @@ const promise = invoke(inputArguments, { - `success` if the last mutation attempt was successful. - `isIdle`, `isLoading`, `isSuccess`, `isError`: boolean variables derived from `status` -- `data: undefined | Any` +- `data: undefined | unknown` - Defaults to `undefined` - - The last successfully resolved data for the mutation. -- `error: null | Error` + - The last successfully resolved data for the query. +- `error: null | TError` - The error object for the query, if an error was encountered. -- `reset: Function() => void` +- `reset: () => void` - A function to clean the mutation internal state (i.e., it resets the mutation to its initial state). diff --git a/app/pages/docs/use-paginated-query.mdx b/app/pages/docs/use-paginated-query.mdx index 4930c2e..668f389 100644 --- a/app/pages/docs/use-paginated-query.mdx +++ b/app/pages/docs/use-paginated-query.mdx @@ -3,16 +3,24 @@ title: usePaginatedQuery sidebar_label: usePaginatedQuery --- +Use `usePaginatedQuery` instead of `useQuery`, if you want to divide large +data into smaller contiguous intervals of data. For instance, you have +many numbered pages, and you want to show the first three pages initially. +After clicking on `Show next pages`, the user should see the following +three pages only. For this case, you can `usePaginatedQuery` as shown in +the following example. + ### Example {#example} ```ts -import {Suspense} from "react" +import { Suspense } from "react" import { Link, BlitzPage, usePaginatedQuery, useRouterQuery, useRouter, + Routes, } from "blitz" import getProjects from "app/products/queries/getProjects" @@ -20,22 +28,22 @@ const ITEMS_PER_PAGE = 3 const Projects = () => { const router = useRouter() - const {page = 0} = useRouterQuery() - const [{projects, hasMore}] = usePaginatedQuery(getProjects, { - skip: ITEMS_PER_PAGE * Number(page), + const page = Number(router.query.page) || 0 + const [{ projects, hasMore }] = usePaginatedQuery(getProjects, { + orderBy: { id: "asc" }, + skip: ITEMS_PER_PAGE * page, take: ITEMS_PER_PAGE, }) const goToPreviousPage = () => - router.push({query: {page: Number(page) - 1}}) - const goToNextPage = () => - router.push({query: {page: Number(page) + 1}}) + router.push({ query: { page: page - 1 } }) + const goToNextPage = () => router.push({ query: { page: page + 1 } }) return (
        {projects.map((project) => (

        - + {project.name}

        @@ -54,25 +62,34 @@ const Projects = () => { And here's the query to work with that: ```ts -export default async function getProjects( - {where, orderBy, cursor, take, skip}: GetProjectsInput, - ctx: Record = {}, -) { - const projects = await db.project.findMany({ - where, - orderBy, - take, - skip, - }) - - const count = await db.project.count() - const hasMore = skip! + take! < count - - return { - projects, - hasMore, +import { paginate, resolver } from "blitz" +import db, { Prisma } from "db" + +interface GetProjectsInput + extends Pick< + Prisma.ProjectFindManyArgs, + "where" | "orderBy" | "skip" | "take" + > {} + +export default resolver.pipe( + resolver.authorize(), + async ({ where, orderBy, skip = 0, take = 100 }: GetProjectsInput) => { + const { items: projects, hasMore, nextPage, count } = await paginate({ + skip, + take, + count: () => db.project.count({ where }), + query: (paginateArgs) => + db.project.findMany({ ...paginateArgs, where, orderBy }), + }) + + return { + projects, + nextPage, + hasMore, + count, + } } -} +) ``` ## API {#api} @@ -82,12 +99,28 @@ export default async function getProjects( const [ queryResult, { - latestData, - isFetching, + dataUpdatedAt, + error, + errorUpdatedAt, failureCount, + isError, + isFetched, + isFetchedAfterMount, + isFetching, + isIdle, + isLoading, + isLoadingError, + isPlaceholderData, + isPreviousData, + isRefetchError, + isStale, + isSuccess, refetch, + remove, + status, + setQueryData, } -] = useQuery(queryResolver, queryInputArguments, options) +] = usePaginatedQuery(queryResolver, queryInputArguments, options) ``` ### Arguments {#arguments} @@ -109,33 +142,86 @@ The options are identical to the options for the `[queryResult, queryExtras]` -##### `queryResult: Any` +##### `queryResult: TData` - Defaults to `undefined`. - The last successfully resolved data for the query. -- When fetching with new input arguments, the value will resolve to the - last known successful value, regardless of input arguments ##### `queryExtras: Object` -- `latestData: Any` +- `status: String` + - Will be: + - `idle` if the query is idle. This only happens if a query is + initialized with `enabled: false` and no initial data is available. + - `loading` if the query is in a "hard" loading state. This means + there is no cached data and the query is currently fetching, eg + `isFetching === true` + - `error` if the query attempt resulted in an error. The corresponding + `error` property has the error received from the attempted fetch + - `success` if the query has received a response with no errors and is + ready to display its data. The corresponding `data` property on the + query is the data received from the successful fetch or if the + query's `enabled` property is set to `false` and has not been + fetched yet `data` is the first `initialData` supplied to the query + on initialization. +- `isIdle: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isLoading: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isSuccess: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isError: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isLoadingError: boolean` + - Will be `true` if the query failed while fetching for the first time. +- `isRefetchError: boolean` + - Will be `true` if the query failed while refetching. +- `data: TData` - Defaults to `undefined`. - - The actual data object for this query and its specific input arguments - - When fetching an uncached query, this value will be `undefined` -- `isFetching: Boolean` + - The last successfully resolved data for the query. +- `dataUpdatedAt: number` + - The timestamp for when the query most recently returned the `status` + as `"success"`. +- `error: null | TError` + - Defaults to `null` + - The error object for the query, if an error was thrown. +- `errorUpdatedAt: number` + - The timestamp for when the query most recently returned the `status` + as `"error"`. +- `isStale: boolean` + - Will be `true` if the data in the cache is invalidated or if the data + is older than the given `staleTime`. +- `isPlaceholderData: boolean` + - Will be `true` if the data shown is the placeholder data. +- `isPreviousData: boolean` + - Will be `true` when data from the previous query is returned. +- `isFetched: boolean` + - Will be `true` if the query has been fetched. +- `isFetchedAfterMount: boolean` + - Will be `true` if the query has been fetched after the component + mounted. + - This property can be used to not show any previously cached data. +- `isFetching: boolean` + - Defaults to `true` so long as `enabled` is set to `false` - Will be `true` if the query is currently fetching, including background fetching. -- `failureCount: Integer` +- `failureCount: number` - The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. -- `refetch: Function({ force, throwOnError }) => void` - - A function to manually refetch the query if it is stale. - - To bypass the stale check, you can pass the `force: true` option and - refetch it regardless of it's freshness +- `refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise` + - A function to manually refetch the query. - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option -- `setQueryData()` - `Function(newData, opts) => void` + - If `cancelRefetch` is `true`, then the current request will be + cancelled before a new request is made +- `remove: () => void` + - A function to remove the query from the cache. +- `setQueryData()` - `Function(newData, opts) => Promise` - A function to manually update the cache for a query. - `newData` can be an object of new data or a function that receives the old data and returns the new data @@ -145,4 +231,4 @@ The options are identical to the options for the ensure the data is correct. Disable refetch by passing an options object `{refetch: false}` as the second argument. - See the [Blitz mutation usage docs](./mutation-usage#setQueryData) for - example usage of `setQueryData()` + example usage of `setQueryData()`. diff --git a/app/pages/docs/use-query.mdx b/app/pages/docs/use-query.mdx index 6c42d0d..0e287ae 100644 --- a/app/pages/docs/use-query.mdx +++ b/app/pages/docs/use-query.mdx @@ -11,15 +11,15 @@ used to display errors. If you need, you can read the [React Concurrent Mode Docs](https://reactjs.org/docs/concurrent-mode-intro.html). ```tsx -import {Suspense} from "react" -import {useQuery, useRouter, useParam} from "blitz" +import { Suspense } from "react" +import { useQuery, useRouter, useParam } from "blitz" import getProject from "app/projects/queries/getProject" import ErrorBoundary from "app/components/ErrorBoundary" function Project() { const router = useRouter() const projectId = useParam("projectId", "number") - const [project] = useQuery(getProject, {where: {id: projectId}}) + const [project] = useQuery(getProject, { where: { id: projectId } }) return
        {project.name}
        } @@ -53,29 +53,53 @@ export default WrappedProject const [ queryResult, { - isFetching, + dataUpdatedAt, + error, + errorUpdatedAt, failureCount, + isError, + isFetched, + isFetchedAfterMount, + isFetching, + isIdle, + isLoading, + isLoadingError, + isPlaceholderData, + isPreviousData, + isRefetchError, + isStale, + isSuccess, refetch, + remove, + status, setQueryData, } ] = useQuery(queryResolver, queryInputArguments, { - enabled, - forceFetchOnMount, - retry, - retryDelay, - staleTime, cacheTime, + enabled, + initialData, + initialDataUpdatedAt + isDataEqual, + keepPreviousData, + notifyOnChangeProps, + notifyOnChangePropsExclusions, + onError, + onSettled, + onSuccess, + queryKeyHashFn, refetchInterval, refetchIntervalInBackground, - refetchOnWindowFocus, + refetchOnMount, refetchOnReconnect, - notifiyOnStatusChange, - onSuccess, - onError, - onSettled, + refetchOnWindowFocus, + retry, + retryOnMount, + retryDelay, + select, + staleTime, + structuralSharing, suspense, - initialData, - refetchOnMount, + useErrorBoundary, }) ``` @@ -91,117 +115,215 @@ const [ ### Options {#options} -- `enabled: Boolean` - - Set this to `false` to disable automatic refetching when the query - mounts or changes query keys. - - To refetch the query, use the `refetch` method returned from the - `useQuery` instance. -- `forceFetchOnMount: Boolean` - - Optional - - Defaults to `false` - - Set this to `true` to always fetch when the component mounts - (regardless of staleness). -- `retry: Boolean | Int | Function(failureCount, error) => Boolean` +- `enabled: boolean` + - Set this to `false` to disable this query from automatically running. + - Can be used for [Dependent Queries](./query-usage#dependent-queries). +- `retry: boolean | number | (failureCount: number, error: TError) => boolean` - If `false`, failed queries will not retry by default. - If `true`, failed queries will retry infinitely. - - If set to an `Int`, e.g. `3`, failed queries will retry until the + - If set to a `number`, e.g. `3`, failed queries will retry until the failed query count meets that number. - - If set to a function `(failureCount, error) => boolean` failed queries - will retry until the function returns false. -- `retryDelay: Function(retryAttempt: Int) => Int` - - This function receives a `retryAttempt` integer and returns the delay - to apply before the next attempt in milliseconds. +- `retryOnMount: boolean` + - If set to `false`, the query will not be retried on mount if it + contains an error. Defaults to `true`. +- `retryDelay: number | (retryAttempt: number, error: TError) => number` + - This function receives a `retryAttempt` integer and the actual Error + and returns the delay to apply before the next attempt in + milliseconds. - A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential backoff. - A function like `attempt => attempt * 1000` applies linear backoff. -- `staleTime: Int | Infinity` - - The time in milliseconds that cache data remains fresh. After a - successful cache update, that cache data will become stale after this - duration. - - If set to `Infinity`, query will never go stale -- `cacheTime: Int | Infinity` +- `staleTime: number | Infinity` + - The time in milliseconds after data is considered stale. This value + only applies to the hook it is defined on. + - If set to `Infinity`, the data will never be considered stale +- `cacheTime: number | Infinity` - The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache - data will be garbage collected after this duration. + data will be garbage collected after this duration. When different + cache times are specified, the longest one will be used. - If set to `Infinity`, will disable garbage collection -- `refetchInterval: false | Integer` +- `refetchInterval: false | number` - Optional - If set to a number, all queries will continuously refetch at this frequency in milliseconds -- `refetchIntervalInBackground: Boolean` +- `refetchIntervalInBackground: boolean` - Optional - If set to `true`, queries that are set to continuously refetch with a `refetchInterval` will continue to refetch while their tab/window is in the background -- `refetchOnWindowFocus: Boolean` +- `refetchOnMount: boolean | "always"` + - Optional + - Defaults to `true` + - If set to `true`, the query will refetch on mount if the data is + stale. + - If set to `false`, the query will not refetch on mount. + - If set to `"always"`, the query will always refetch on mount. +- `refetchOnWindowFocus: boolean | "always"` + - Optional + - Defaults to `true` + - If set to `true`, the query will refetch on window focus if the data + is stale. + - If set to `false`, the query will not refetch on window focus. + - If set to `"always"`, the query will always refetch on window focus. +- `refetchOnReconnect: boolean | "always"` - Optional - - Set this to `false` to disable automatic refetching on window focus - (useful, when `refetchAllOnWindowFocus` is set to `true`). - - Set this to `true` to enable automatic refetching on window focus - (useful, when `refetchAllOnWindowFocus` is set to `false`. -- `refetchOnReconnect: Boolean` + - Defaults to `true` + - If set to `true`, the query will refetch on reconnect if the data is + stale. + - If set to `false`, the query will not refetch on reconnect. + - If set to `"always"`, the query will always refetch on reconnect. +- `notifyOnChangeProps: string[] | "tracked"` - Optional - - Set this to `true` or `false` to enable/disable automatic refetching - on reconnect for this query. -- `notifyOnStatusChange: Boolean` + - If set, the component will only re-render if any of the listed + properties change. + - If set to `['data', 'error']` for example, the component will only + re-render when the `data` or `error` properties change. + - If set to `"tracked"`, access to properties will be tracked, and the + component will only re-render when one of the tracked properties + change. +- `notifyOnChangePropsExclusions: string[]` - Optional - - Whether a change to the query status should re-render a component. - - If set to `false`, the component will only re-render when the actual - `data` or `error` changes. - - Defaults to `true`. -- `onSuccess: Function(data) => data` + - If set, the component will not re-render if any of the listed + properties change. + - If set to `['isStale']` for example, the component will not re-render + when the `isStale` property changes. +- `onSuccess: (data: TData) => void` - Optional - This function will fire any time the query successfully fetches new data. -- `onError: Function(err) => void` +- `onError: (error: TError) => void` - Optional - This function will fire if the query encounters an error and will be passed the error. -- `onSettled: Function(data, error) => data` +- `onSettled: (data?: TData, error?: TError) => void` - Optional - This function will fire any time the query is either successfully fetched or errors and be passed either the data or error -- `initialData: any | Function() => any` +- `select: (data: TData) => unknown` + - Optional + - This option can be used to transform or select a part of the data + returned by the query function. +- `suspense: boolean` + - Optional + - Set this to `false` to disable suspense mode. + - When `true`, `useQuery` will suspend when `status === 'loading'` + - When `true`, `useQuery` will throw runtime errors when + `status === 'error'` +- `initialData: TData | () => TData` - Optional - If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet) - If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initialData -- `refetchOnMount: Boolean` + - Initial data is considered stale by default unless a `staleTime` has + been set. + - `initialData` **is persisted** to the cache +- `initialDataUpdatedAt: number | (() => number | undefined)` - Optional - - Defaults to `true` - - If set to `false`, will disable additional instances of a query to - trigger background refetches -- `suspense: Boolean` + - If set, this value will be used as the time (in milliseconds) of when + the `initialData` itself was last updated. +- `placeholderData: TData | () => TData` - Optional - - Enabled by default. Set this to `false` to disable suspense mode. + - If set, this value will be used as the placeholder data for this + particular query observer while the query is still in the `loading` + data and no initialData has been provided. + - `placeholderData` is **not persisted** to the cache +- `keepPreviousData: boolean` + - Optional + - Defaults to `false` + - If set, any previous `data` will be kept when fetching new data + because the query key changed. +- `structuralSharing: boolean` + - Optional + - Defaults to `true` ### Returns {#returns} `[queryResult, queryExtras]` -##### `queryResult: Any` +##### `queryResult: TData` - Defaults to `undefined`. - The last successfully resolved data for the query. ##### `queryExtras: Object` -- `isFetching: Boolean` +- `status: String` + - Will be: + - `idle` if the query is idle. This only happens if a query is + initialized with `enabled: false` and no initial data is available. + - `loading` if the query is in a "hard" loading state. This means + there is no cached data and the query is currently fetching, eg + `isFetching === true` + - `error` if the query attempt resulted in an error. The corresponding + `error` property has the error received from the attempted fetch + - `success` if the query has received a response with no errors and is + ready to display its data. The corresponding `data` property on the + query is the data received from the successful fetch or if the + query's `enabled` property is set to `false` and has not been + fetched yet `data` is the first `initialData` supplied to the query + on initialization. +- `isIdle: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isLoading: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isSuccess: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isError: boolean` + - A derived boolean from the `status` variable above, provided for + convenience. +- `isLoadingError: boolean` + - Will be `true` if the query failed while fetching for the first time. +- `isRefetchError: boolean` + - Will be `true` if the query failed while refetching. +- `data: TData` + - Defaults to `undefined`. + - The last successfully resolved data for the query. +- `dataUpdatedAt: number` + - The timestamp for when the query most recently returned the `status` + as `"success"`. +- `error: null | TError` + - Defaults to `null` + - The error object for the query, if an error was thrown. +- `errorUpdatedAt: number` + - The timestamp for when the query most recently returned the `status` + as `"error"`. +- `isStale: boolean` + - Will be `true` if the data in the cache is invalidated or if the data + is older than the given `staleTime`. +- `isPlaceholderData: boolean` + - Will be `true` if the data shown is the placeholder data. +- `isPreviousData: boolean` + - Will be `true` when `keepPreviousData` is set and data from the + previous query is returned. +- `isFetched: boolean` + - Will be `true` if the query has been fetched. +- `isFetchedAfterMount: boolean` + - Will be `true` if the query has been fetched after the component + mounted. + - This property can be used to not show any previously cached data. +- `isFetching: boolean` + - Defaults to `true` so long as `enabled` is set to `false` - Will be `true` if the query is currently fetching, including background fetching. -- `failureCount: Integer` +- `failureCount: number` - The failure count for the query. - Incremented every time the query fails. - Reset to `0` when the query succeeds. -- `refetch()` - `Function({ force, throwOnError }) => void` - - A function to manually refetch the query if it is stale. - - To bypass the stale check, you can pass the `force: true` option and - refetch it regardless of it's freshness +- `refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise` + - A function to manually refetch the query. - If the query errors, the error will only be logged. If you want an error to be thrown, pass the `throwOnError: true` option + - If `cancelRefetch` is `true`, then the current request will be + cancelled before a new request is made +- `remove: () => void` + - A function to remove the query from the cache. - `setQueryData()` - `Function(newData, opts) => Promise` - A function to manually update the cache for a query. - `newData` can be an object of new data or a function that receives the @@ -212,4 +334,4 @@ const [ ensure the data is correct. Disable refetch by passing an options object `{refetch: false}` as the second argument. - See the [Blitz mutation usage docs](./mutation-usage#setQueryData) for - example usage of `setQueryData()` + example usage of `setQueryData()`. diff --git a/app/pages/docs/webpack-config.mdx b/app/pages/docs/webpack-config.mdx index a9fef17..843ebc7 100644 --- a/app/pages/docs/webpack-config.mdx +++ b/app/pages/docs/webpack-config.mdx @@ -10,7 +10,7 @@ extends its config inside `blitz.config.js`, like so: module.exports = { webpack: ( config, - {buildId, dev, isServer, defaultLoaders, webpack}, + { buildId, dev, isServer, defaultLoaders, webpack } ) => { // Note: we provide webpack above so you should not `require` it // Perform customizations to webpack config diff --git a/app/pages/docs/why-blitz.mdx b/app/pages/docs/why-blitz.mdx index b3ffc44..6d785ce 100644 --- a/app/pages/docs/why-blitz.mdx +++ b/app/pages/docs/why-blitz.mdx @@ -126,9 +126,30 @@ scheiden en organiseren op elke manier die je wilt. Voorbeelden: +<<<<<<< HEAD - `app/pages/` zou de homepage kunnen bevatten en pagina's zoals "Over ons" - `app/products/pages/` zou alle pagina's kunnen bevatten die te maken hebben met producten - `app/admin/pages/` zou alle pagina's kunnen bevatten die te maken hebben met de backend administratie sectie +======= +- `app/pages/` could contain the homepage and pages like "about" +- `app/products/pages/` could contain all the pages related to products +- `app/admin/pages/` could contain all pages related to the backend admin + section + +### 9. Route Manifest {#9-route-manifest} + +Next.js requires you to manually type out page locations. Blitz comes with +a [Route Manifest](./route-manifest), so you can do: + +```ts + +// instead of + +``` + +This improves expressiveness and simplifies moving pages to other +location. +>>>>>>> 9fe39d8ebeff642759bb10ad1b0cd2f1114ec7aa diff --git a/app/pages/docs/writing-recipes.mdx b/app/pages/docs/writing-recipes.mdx index 301ae6a..d14cc04 100644 --- a/app/pages/docs/writing-recipes.mdx +++ b/app/pages/docs/writing-recipes.mdx @@ -44,7 +44,7 @@ set that up. ```typescript // index.ts -import {RecipeBuilder} from "@blitzjs/installer" +import { RecipeBuilder } from "@blitzjs/installer" export default RecipeBuilder().build() ``` @@ -60,7 +60,7 @@ they can look for support if they need it. RecipeBuilder() .setName("My Package") .setDescription( - "A little bit of information about what exactly is being installed.", + "A little bit of information about what exactly is being installed." ) .setOwner("Fake Author ") .setRepoLink("https://github.com/fake-author/my-recipe") @@ -107,8 +107,8 @@ builder.addAddDependenciesStep({ stepName: "Add npm dependencies", explanation: `We'll install the Tailwind library itself, as well as PostCSS for removing unused styles from our production bundles.`, packages: [ - {name: "tailwindcss", version: "1"}, - {name: "postcss-preset-env", version: "latest", isDevDep: true}, + { name: "tailwindcss", version: "1" }, + { name: "postcss-preset-env", version: "latest", isDevDep: true }, ], }) ``` @@ -130,7 +130,7 @@ anywhere in your recipe's file structure, you supply the path as a part of the recipe definition. ```typescript -import {join} from "path" +import { join } from "path" builder.addNewFilesStep({ stepId: "addStyles", @@ -161,7 +161,7 @@ path is a glob pattern, the installer process will prompt the user to select a file matching the pattern. ```typescript -import {addImport, paths} from "@blitzjs/installer" +import { addImport, paths } from "@blitzjs/installer" import j from "jscodeshift" import Collection from "jscodeshift/src/Collection" @@ -173,7 +173,7 @@ builder.addTransformFilesStep({ transform(program: Collection) { const stylesImport = j.importDeclaration( [], - j.literal("app/styles/index.css"), + j.literal("app/styles/index.css") ) return addImport(program, stylesImport)! }, @@ -187,11 +187,19 @@ testing, the tests are quick to write: ```typescript import j from "jscodeshift" +import { customTsParser } from "@blitzjs/installer" const sampleFile = `export default function Comp() { return
        hello!
        ; })` -expect(addImport(j(sampleFile), newImport).toSource()).toMatchSnapshot() +expect( + addImport( + j(sampleFile, { + parser: customTsParser, + }), + newImport + ).toSource() +).toMatchSnapshot() ``` #### Modifying Non-JS files @@ -212,6 +220,169 @@ builder This step would append "Paul Plain was here!" to the user's README.md +#### Modifying Prisma schemas + +A lot of recipes may need to add or modify models in the schema.prisma +file in order to apply the recipe's effects. You can attempt to manipulate +the schema using plain string transformations in `transformPlain`, but a +lot of recipes may require the ability to query something about the schema +first. For example, to determine the model on the other end of a +[Relation](https://www.prisma.io/docs/concepts/components/prisma-schema/relations/), +or to detect if a field already exists. + +For your convenience, there are several pre-written utilities for common +schema modifications: + +##### Create an Enum + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Create the enum Role with two values, USER and ADMIN + return addPrismaEnum(source, { + type: "enum", + name: "Role", + enumerators: [ + {type: "enumerator", name: "USER"}, + {type: "enumerator", name: "ADMIN"}, + ], + }) +} +``` + +##### Add a Field to a Model + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Add a field "name String @unique" to the "Project" model + return addPrismaField(source, "Project", { + type: "field", + name: "name", + fieldType: "String", + optional: false, + attributes: [{type: "attribute", kind: "field", name: "unique"}], + }) +} +``` + +##### Create a Generator + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Create a prisma generator for nexus-prisma + return addPrismaGenerator(source, { + type: "generator", + name: "nexusPrisma", + assignments: [ + {type: "assignment", key: "provider", value: '"nexus-prisma"'}, + ], + }) +} +``` + +##### Create a Model + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Create a prisma model called Project + return addPrismaModel(source, { + type: "model", + name: "Project", + properties: [{type: "field", name: "name", fieldType: "String"}], + }) +} +``` + +##### Add an Attribute such as an Index to a Model + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Creates an index attribute on the Project model "@@index([name])" + return addPrismaModelAttribute(source, "Project", { + type: "attribute", + kind: "model", + name: "index", + args: [ + {type: "attributeArgument", value: {type: "array", args: ["name"]}}, + ], + }) +} +``` + +##### Set the schema's Datasource + +Since a prisma schema can only have one data source, there is no "add" +utility, this will replace the schema's current data source. + +```ts +singleFileSearch: paths.prismaSchema(), +transformPlain(source: string) { + // Set the datasource to postgresql + return setPrismaDataSource(source, { + type: "datasource", + name: "db", + assignments: [ + {type: "assignment", key: "provider", value: '"postgresql"'}, + { + type: "assignment", + key: "url", + value: {type: "function", name: "env", params: ['"DATABASE_URL"']}, + }, + ], + }) +} +``` + +##### Custom Schema Transformations with produceSchema + +If the provided helpers aren't flexible enough for your recipe, you can +use the `produceSchema` utility function to parse the prisma schema file +and apply custom transformations. It will convert the schema into a JSON +object format that you can modify using JavaScript, then print the schema +(with your changes applied) back out to a string. All of the above helpers +are implemented using `produceSchema`. + +```ts +builder.addTransformFilesStep({ + ..., + singleFileSearch: paths.prismaSchema(), + transformPlain(source: string) { + return produceSchema(source, (schema) => { + // find a model named "User" + const model = schema.list.find(function(item): item is Model { + return item.type === "model" && item.name === "User" + }) as Model + if (!model) return + + // find a field on the "User" model named "email" + const field = model.properties.find(function (property): property is Field { + return property.type === "attribute" && property.name === "email" + }) + if (!field) return + + // add the "@unique" attribute to "email" + field.attributes?.push({ + type: "attribute", + kind: "field", + name: "unique" + }) + }) + } +}) +``` + +It is a best practice for schema transformations to be idempotent, meaning +that the function should not attempt to make a change to the schema if +that change already has been made. For instance, do not add a field to a +model if that field already exists. + +To see how the schema file is parsed, +[click here](https://github.com/MrLeebo/prisma-ast). + ### Publishing {#publishing} That's all you need to build a recipe! At this point, you can commit and diff --git a/app/pages/index.js b/app/pages/index.js index 214e565..5b6be5a 100644 --- a/app/pages/index.js +++ b/app/pages/index.js @@ -228,7 +228,10 @@ const Home = ({randomContributors}) => { target="_blank" rel="noopener noreferrer" > - {contributor.name}', - }, - info: { - keyword: "info", - svg: - '', - }, - }, - }, - ], - ], + remarkPlugins: [withProse, withTableOfContents, withSyntaxHighlighting, withBlitzLinks], }, }, createLoader(function (source) { @@ -141,6 +131,10 @@ module.exports = withBundleAnalyzer({ } } + if (/^<\/Card>$/m.test(source)) { + extra.push(`import { Card } from '@/components/docs/Card'`) + } + return [ ...(typeof fields === "undefined" ? extra : []), typeof fields === "undefined" ? body : "", diff --git a/package.json b/package.json index cd7f945..a26a4dc 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "lint": "yarn lint:code && yarn lint:docs", "lint:code": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .", "lint:docs": "alex app/pages/docs/**/*.mdx", - "english-slugify": "node scripts/english-slugify.js", + "english-slugify": "node scripts/english-slugify.mjs", "prepare": "husky install" }, "lint-staged": { @@ -18,18 +18,18 @@ }, "dependencies": { "@docsearch/react": "1.0.0-alpha.28", - "@octokit/rest": "18.5.2", - "@reach/rect": "0.14.0", - "@sindresorhus/slugify": "1.1.0", + "@octokit/rest": "18.5.3", + "@reach/rect": "0.15.0", + "@sindresorhus/slugify": "2.0.0", "@visx/hierarchy": "1.7.0", "@visx/responsive": "1.7.0", - "blitz": "0.33.1", + "blitz": "0.34.3", "clsx": "1.1.1", "dlv": "1.1.3", "fathom-client": "3.0.0", "focus-visible": "5.2.0", - "framer-motion": "4.0.3", - "gray-matter": "4.0.2", + "framer-motion": "4.1.9", + "gray-matter": "4.0.3", "just-group-by": "1.0.0", "next-themes": "0.0.14", "prismjs": "1.23.0", @@ -48,27 +48,25 @@ }, "devDependencies": { "@mdx-js/loader": "1.6.22", - "@next/bundle-analyzer": "10.0.9", + "@next/bundle-analyzer": "10.1.3", "@svgr/webpack": "5.5.0", - "@tailwindcss/jit": "0.1.17", "@tailwindcss/typography": "0.4.0", "alex": "9.1.0", "autoprefixer": "10.2.5", "babel-plugin-preval": "5.0.0", - "eslint": "7.23.0", + "eslint": "7.25.0", "eslint-plugin-simple-import-sort": "7.0.0", "file-loader": "6.2.0", "glob": "7.1.6", "husky": "6.0.0", "lint-staged": "10.5.4", "minimatch": "3.0.4", - "postcss": "8.2.8", + "postcss": "8.2.12", "postcss-nested": "5.0.5", "prettier": "2.2.1", "pretty-quick": "3.1.0", - "remark-admonitions": "1.2.1", "simple-functional-loader": "1.2.1", - "tailwindcss": "2.0.4" + "tailwindcss": "2.1.2" }, "private": true } diff --git a/postcss.config.js b/postcss.config.js index bfe13b1..58bdd3e 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,3 +1,3 @@ module.exports = { - plugins: ["@tailwindcss/jit", "postcss-nested", "autoprefixer"], + plugins: ["tailwindcss", "postcss-nested", "autoprefixer"], } diff --git a/scripts/english-slugify.js b/scripts/english-slugify.mjs similarity index 91% rename from scripts/english-slugify.js rename to scripts/english-slugify.mjs index 8904b02..bb664f9 100644 --- a/scripts/english-slugify.js +++ b/scripts/english-slugify.mjs @@ -1,6 +1,6 @@ -const slugify = require("@sindresorhus/slugify") -const fs = require("fs/promises") -const path = require("path") +import slugify from "@sindresorhus/slugify" +import fs from "fs/promises" +import path from "path" async function main() { const docsPath = path.resolve(process.cwd(), "app", "pages", "docs") diff --git a/tailwind.config.js b/tailwind.config.js index 9d52cb8..e97669d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,6 +4,7 @@ const {default: flattenColorPalette} = require("tailwindcss/lib/util/flattenColo const {toRgba} = require("tailwindcss/lib/util/withAlphaVariable") module.exports = { + mode: "jit", purge: { content: ["{app,pages,remark}/**/*.{js,jsx,ts,tsx}"], options: { @@ -78,12 +79,6 @@ module.exports = { string: "#A2F679", highlight: "rgba(134, 239, 172, 0.25)", }, - - supplementary: { - yellow: "#FDEA69", - blue: "#69C6FD", - red: "#FF003D", - }, }, fontSize: { xxs: "0.75rem", // 12px diff --git a/yarn.lock b/yarn.lock index 8eb0994..9146fdd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -137,6 +137,27 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.11.tgz#9c8fe523c206979c9a81b1e12fe50c1254f1aa35" integrity sha512-BwKEkO+2a67DcFeS3RLl0Z3Gs2OvdXewuWjc1Hfokhb5eQWP9YRYH1/+VrVZvql2CfjOiNGqSAFOYt4lsqTHzg== +"@babel/core@7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/core@7.12.9": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" @@ -159,28 +180,6 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.1.tgz#7ddd027176debe40f13bb88bac0c21218c5b1ecf" - integrity sha512-FzeKfFBG2rmFtGiiMdXZPFt/5R5DXubVi82uYhjGX4Msf+pgYQMCFIqFXZWs5vbIYbf14VeBIgdGI03CDOOM1w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@babel/generator" "^7.13.0" - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-transforms" "^7.13.0" - "@babel/helpers" "^7.13.0" - "@babel/parser" "^7.13.0" - "@babel/template" "^7.12.13" - "@babel/traverse" "^7.13.0" - "@babel/types" "^7.13.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - lodash "^4.17.19" - semver "7.0.0" - source-map "^0.5.0" - "@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" @@ -234,6 +233,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.12.10", "@babel/generator@^7.13.0", "@babel/generator@^7.13.9": + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== + dependencies: + "@babel/types" "^7.13.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.12.17": version "7.12.17" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.17.tgz#9ef1dd792d778b32284411df63f4f668a9957287" @@ -243,15 +251,6 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/generator@^7.13.0", "@babel/generator@^7.13.9", "@babel/generator@^7.4.0": - version "7.13.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" - integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== - dependencies: - "@babel/types" "^7.13.0" - jsesc "^2.5.1" - source-map "^0.5.0" - "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" @@ -614,7 +613,7 @@ "@babel/traverse" "^7.12.17" "@babel/types" "^7.12.17" -"@babel/helpers@^7.13.0", "@babel/helpers@^7.13.10": +"@babel/helpers@^7.13.10": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8" integrity sha512-4VO883+MWPDUVRF3PhiLBUFHoX/bsLTGFpFK/HqvvfBZz2D57u9XzPVNFVBTc0PW/CWR9BXTOKt8NF4DInUHcQ== @@ -641,7 +640,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.13.0", "@babel/parser@^7.13.10", "@babel/parser@^7.4.3": +"@babel/parser@^7.1.0", "@babel/parser@^7.13.0", "@babel/parser@^7.13.10": version "7.13.11" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.11.tgz#f93ebfc99d21c1772afbbaa153f47e7ce2f50b88" integrity sha512-PhuoqeHoO9fc4ffMEVk4qb/w/s2iOSWohvbHxLtxui0eBg3Lg5gN1U8wp1V1u61hOWkPQJJyJzGH6Y+grwkq8Q== @@ -651,6 +650,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== +"@babel/parser@^7.12.10", "@babel/parser@^7.13.15": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8" + integrity sha512-b9COtcAlVEQljy/9fbcMHpG+UIW9ReF+gpaxDHTlZd0c6/UU9ng8zdySAW9sRTzpvcdCHn6bUcbuYUgGzLAWVQ== + "@babel/parser@^7.12.13", "@babel/parser@^7.12.17", "@babel/parser@^7.12.7": version "7.12.17" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.17.tgz#bc85d2d47db38094e5bb268fc761716e7d693848" @@ -1419,7 +1423,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.12.5": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.6.2": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== @@ -1435,7 +1439,7 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.3.3", "@babel/template@^7.4.0": +"@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.3.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== @@ -1444,7 +1448,7 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.4.3": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== @@ -1474,6 +1478,20 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.12.10": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.15.tgz#c38bf7679334ddd4028e8e1f7b3aa5019f0dada7" + integrity sha512-/mpZMNvj6bce59Qzl09fHEs8Bt8NnpEDQYleHUPZQ3wXUMvXi+HJPLars68oAbmp839fGoOkv2pSL2z9ajCIaQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.15" + "@babel/types" "^7.13.14" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.12.17", "@babel/traverse@^7.12.9": version "7.12.17" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.17.tgz#40ec8c7ffb502c4e54c7f95492dc11b88d718619" @@ -1498,7 +1516,7 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.13.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.0": +"@babel/types@^7.0.0", "@babel/types@^7.13.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== @@ -1516,6 +1534,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.10", "@babel/types@^7.13.14": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d" + integrity sha512-A2aa3QTkWoyqsZZFl56MLUsfmh7O0gN41IPvXAE/++8ojpbz12SszD7JEGYVdn4f9Kt4amIei07swF1h4AqmmQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.12.7": version "7.12.17" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.17.tgz#9d711eb807e0934c90b8b1ca0eb1f7230d150963" @@ -1539,21 +1566,21 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@blitzjs/babel-preset@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/babel-preset/-/babel-preset-0.33.1.tgz#dfbb6fe1d5c989cfb2feb124e70071992c1b660f" - integrity sha512-VjVPUjMFVPZ8MuKKZt8fEF0zzAbIhxCXxkBG5Jh9KHq2TGf+vn1iYp7PqvnoBhzdwhS5PjTXFT11CTPEixOPMQ== +"@blitzjs/babel-preset@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/babel-preset/-/babel-preset-0.34.3.tgz#c3756c6bdeca540072ed3472ed1bb148834896af" + integrity sha512-A5kqm69btVWXQaeqA2qySRkSeKUw/SrW+iF5VE6hFDz/euINMKrRQiKxS3on3lotb1LBUP3FTF2iHHN6PSmq0g== dependencies: "@babel/helper-module-imports" "^7.0.0" babel-plugin-superjson-next "0.2.2" -"@blitzjs/cli@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/cli/-/cli-0.33.1.tgz#8a25202a03bfd99d84f58e5e1041cb760b7fc5ed" - integrity sha512-TZ9m7qIgFqrsG2kIw4ZMQB7nJgV4JUABVEs3aCQ+p9iza4fnb/qx2/5JyRJu7QaqcDdZViDrCU5wfHgAl4pvwQ== +"@blitzjs/cli@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/cli/-/cli-0.34.3.tgz#4a40bdf0f955a261f85728e03f7f57d719df10ca" + integrity sha512-ZRS7sNPlZ8A1RqtAdgG9uhsstad28XZYCQum76tkPuh++T8qvMKJCyzGdRjX2ScyoD7Ny9HhujokxPdTVbq6Pg== dependencies: - "@blitzjs/display" "0.33.1" - "@blitzjs/repl" "0.33.1" + "@blitzjs/display" "0.34.3" + "@blitzjs/repl" "0.34.3" "@oclif/command" "1.8.0" "@oclif/config" "1.17.0" "@oclif/plugin-autocomplete" "0.3.0" @@ -1582,21 +1609,21 @@ tsconfig-paths "3.9.0" v8-compile-cache "2.2.0" -"@blitzjs/config@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/config/-/config-0.33.1.tgz#6530a5f64c6b8bbdecc2dd59e2bc077e73953f6d" - integrity sha512-zK0y0exmUrPPEclBh9OcXNN3TRA2XpinFFyuonhmLxN4Vh1qw3bx3iiJdP9xN4yCUIXlBAU++dBaHDZOciJsIg== +"@blitzjs/config@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/config/-/config-0.34.3.tgz#83604d63e9722a80ba3fa324e99dba359e6b658b" + integrity sha512-3MAmHK6Kh7XJIT6mCETUvRFalqJLkk1wCYBuFXLtzqpwry/bSgPHBzAlpzccgSys5zpjBvbftns2X3i1L9X2gQ== dependencies: fs-extra "^9.1.0" pkg-dir "^5.0.0" -"@blitzjs/core@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/core/-/core-0.33.1.tgz#8f98c52e41b6f5f117c46cb719021b5ad9e75cc5" - integrity sha512-TC2K64XjKb1AGMNWfJPJOLGgWYAeLxlTkHFR7IUXn4wnCDcGXbiwUz/2HVTET7INPdDu5v3st7xNmmrBV6DoJA== +"@blitzjs/core@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/core/-/core-0.34.3.tgz#8078ec3f9856450dd303a828782b7742bde93323" + integrity sha512-moheoboOMVxR5YGEpexjt5HxO1NyoY984uvSsqiEmQkoWz6Fk/HvU2tfwlj+ybNOkBr2XNU6pAzxbMVZflHdzw== dependencies: - "@blitzjs/config" "0.33.1" - "@blitzjs/display" "0.33.1" + "@blitzjs/config" "0.34.3" + "@blitzjs/display" "0.34.3" "@types/secure-password" "3.1.0" b64-lite "^1.4.0" bad-behavior "^1.0.1" @@ -1608,33 +1635,33 @@ jsonwebtoken "8.5.1" lodash.frompairs "4.0.1" nanoid "^3.1.20" - next "10.0.9" + next "npm:@blitzjs/next@10.1.3-0.34.3" npm-which "^3.0.1" null-loader "4.0.1" passport "0.4.1" - react-query "2.5.12" + react-query "3.13.9" secure-password "4.0.0" superjson "1.7.2" -"@blitzjs/display@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/display/-/display-0.33.1.tgz#cd163a6f3353ba7cc59a8f6e2e82f8d3b1f07d82" - integrity sha512-JCVhqivxjebKJXIzy5rPe6Hv8V5tWPtBOO6DTsE/6FZezI4VYY2sgN20g00Ac2XH14hIzsSu9doHiTIk9tJzvQ== +"@blitzjs/display@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/display/-/display-0.34.3.tgz#9d17d16658c3d5576509356bccc33351e581ec4b" + integrity sha512-PvZphihfJKFmr5aVLQZgq/MEYDJFb2I8NmwNwNE8U+M4asctZACbiXeuRnjqN3JUultO8bk+ZyLos4vUr6nDcw== dependencies: - "@blitzjs/config" "0.33.1" - "@blitzjs/display" "0.33.1" + "@blitzjs/config" "0.34.3" + "@blitzjs/display" "0.34.3" chalk "^4.1.0" console-table-printer "^2.7.5" ora "^5.3.0" readline "1.3.0" tslog "^3.1.1" -"@blitzjs/file-pipeline@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/file-pipeline/-/file-pipeline-0.33.1.tgz#73cf82f1337756b608d9b6e72749a4f09eca4ed8" - integrity sha512-E0OWzngW/Y2booHR6DqJNbea2FJYSJAL5KjkS8veYgr1d2NIB2M8gx29B9HdG+ki4IGA0o9S7emCeK0Hl46uog== +"@blitzjs/file-pipeline@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/file-pipeline/-/file-pipeline-0.34.3.tgz#10c40e8906683fc5e936b27f04b981f7ad4c5cf7" + integrity sha512-AeSAypDniFuXC9xUbz07daFAbQWBIUzlz3M6tCWA2lWFBegPDciC/3xKeP/LCHjKqSVpA5tQcR2qVsoxM0R1Qg== dependencies: - "@blitzjs/display" "0.33.1" + "@blitzjs/display" "0.34.3" chalk "^4.1.0" chokidar "3.5.1" flush-write-stream "2.0.0" @@ -1653,21 +1680,20 @@ vinyl-file "3.0.0" vinyl-fs "3.0.3" -"@blitzjs/generator@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/generator/-/generator-0.33.1.tgz#49658c48bad30041d9b53ae15f0c4c56d8a67f37" - integrity sha512-RpnVdu0zzaOGX2PNX2xM3JBu0TdHjukpOPvNNv5jqXED6yUa7GF3nrnFyKbDwNfq4GmRG+yUZIPZUGXFwIvSrA== +"@blitzjs/generator@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/generator/-/generator-0.34.3.tgz#0b75758bc5b8e319853f548a0df161621c418107" + integrity sha512-KlsroS8Tx0Dq1MkcfT3qBux90CgKFp2Gs4AHWy1ZYV/9Fiu3lw/d53sY1msEEB0ggIhXjlb+AFgE5FqtBG5+FA== dependencies: - "@babel/core" "7.13.1" + "@babel/core" "7.12.10" "@babel/plugin-transform-typescript" "7.12.1" - "@blitzjs/display" "0.33.1" + "@blitzjs/display" "0.34.3" "@types/jscodeshift" "0.7.2" chalk "^4.1.0" cross-spawn "7.0.3" diff "5.0.0" enquirer "2.3.6" fs-extra "^9.1.0" - fs-readdir-recursive "1.1.0" got "^11.8.1" jscodeshift "0.11.0" mem-fs "1.2.0" @@ -1678,16 +1704,16 @@ username "^5.1.0" vinyl "2.2.1" -"@blitzjs/installer@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/installer/-/installer-0.33.1.tgz#3813ffedc9414d35e09bde3fbd2cd66c1dcb398c" - integrity sha512-15OVfrkPv8uotL1oaJdtoXQtA73VHDGE59fV2fH3hx+/U6qLsBe+i1YNz8hY5ziIW96JxzmfCAl0tq9STkPtaA== +"@blitzjs/installer@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/installer/-/installer-0.34.3.tgz#51f33c855391c00fb1a5f417fb4818a4e3c00249" + integrity sha512-y7Od0YCj+ltwegNB0gmtjnLJk5e6uiqfHp8ZmpK/mnETIJXfXab/xXSJBhvyKcEvh0oO9GQC7v7ivGGouBL57g== dependencies: - "@babel/core" "7.13.1" + "@babel/core" "7.12.10" "@babel/plugin-transform-typescript" "7.12.1" - "@blitzjs/config" "0.33.1" - "@blitzjs/display" "0.33.1" - "@blitzjs/generator" "0.33.1" + "@blitzjs/config" "0.34.3" + "@blitzjs/display" "0.34.3" + "@blitzjs/generator" "0.34.3" "@types/jscodeshift" "0.7.2" cross-spawn "7.0.3" diff "5.0.0" @@ -1702,26 +1728,26 @@ recast "0.20.4" ts-node "^9.1.1" -"@blitzjs/repl@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/repl/-/repl-0.33.1.tgz#2090cef38bced1017fece43943a193c541f029c3" - integrity sha512-Sk2Wsl08lJgpXg+nbNeVVnsjoLsMRm1n6RegbWbrScLXSzEi707BvVQvnGtgJwv4t9m+ab1av/uYPyrz8vcY8Q== +"@blitzjs/repl@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/repl/-/repl-0.34.3.tgz#403469358ec162077ab4dde91cf3be93bde060e2" + integrity sha512-XHj9DYPqc8KY+zEPcoTL9Nc4vups7Vj4Fz5v82o7i6SPXGuzuCsOJu528HwtX8Y5fO5EHJFNAp8bhr8cDML20g== dependencies: - "@blitzjs/config" "0.33.1" + "@blitzjs/config" "0.34.3" chokidar "3.5.1" globby "11.0.2" pkg-dir "^5.0.0" progress "^2.0.3" -"@blitzjs/server@0.33.1": - version "0.33.1" - resolved "https://registry.yarnpkg.com/@blitzjs/server/-/server-0.33.1.tgz#6efd8a3623afd43a55b4b46d32b15441e8575407" - integrity sha512-BpeOcFjSslskLIKoTc8242xJIsA3vpc9P6ObrHG+5kuo5VsxN1vPjoEnBOemAYRbQiJliEr5pdDE7Bk7h4TiWA== +"@blitzjs/server@0.34.3": + version "0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/server/-/server-0.34.3.tgz#9e682b0b1ee6cf144a986bc4e1f268e0d248af56" + integrity sha512-FVmKHH9sawM/xTRtboUKRMehxeChTosD6Eyj/XxrvP+GAirgCKPLefttyjvwzJdw+y7h+RWHH5iZpxdQDXppDg== dependencies: - "@blitzjs/config" "0.33.1" - "@blitzjs/core" "0.33.1" - "@blitzjs/display" "0.33.1" - "@blitzjs/file-pipeline" "0.33.1" + "@blitzjs/config" "0.34.3" + "@blitzjs/core" "0.34.3" + "@blitzjs/display" "0.34.3" + "@blitzjs/file-pipeline" "0.34.3" cross-spawn "7.0.3" detect-port "1.3.0" expand-tilde "2.0.2" @@ -1910,15 +1936,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" - integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== - dependencies: - "@jest/source-map" "^24.9.0" - chalk "^2.0.1" - slash "^2.0.0" - "@jest/console@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" @@ -1965,16 +1982,6 @@ slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^24.3.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" - integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== - dependencies: - "@jest/fake-timers" "^24.9.0" - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - jest-mock "^24.9.0" - "@jest/environment@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" @@ -1985,15 +1992,6 @@ "@types/node" "*" jest-mock "^26.6.2" -"@jest/fake-timers@^24.3.0", "@jest/fake-timers@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" - integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== - dependencies: - "@jest/types" "^24.9.0" - jest-message-util "^24.9.0" - jest-mock "^24.9.0" - "@jest/fake-timers@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" @@ -2047,15 +2045,6 @@ optionalDependencies: node-notifier "^8.0.0" -"@jest/source-map@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" - integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== - dependencies: - callsites "^3.0.0" - graceful-fs "^4.1.15" - source-map "^0.6.0" - "@jest/source-map@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" @@ -2065,15 +2054,6 @@ graceful-fs "^4.2.4" source-map "^0.6.0" -"@jest/test-result@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" - integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== - dependencies: - "@jest/console" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@jest/test-result@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" @@ -2095,28 +2075,6 @@ jest-runner "^26.6.3" jest-runtime "^26.6.3" -"@jest/transform@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" - integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== - dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^24.9.0" - babel-plugin-istanbul "^5.1.0" - chalk "^2.0.1" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.1.15" - jest-haste-map "^24.9.0" - jest-regex-util "^24.9.0" - jest-util "^24.9.0" - micromatch "^3.1.10" - pirates "^4.0.1" - realpath-native "^1.1.0" - slash "^2.0.0" - source-map "^0.6.1" - write-file-atomic "2.4.1" - "@jest/transform@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" @@ -2138,15 +2096,6 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^24.3.0", "@jest/types@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" - integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^13.0.0" - "@jest/types@^26.6.2": version "26.6.2" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" @@ -2202,27 +2151,27 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@next/bundle-analyzer@10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-10.0.9.tgz#e25d1c16b35348d8ed8e2d0608647cc519ce3911" - integrity sha512-xHU8BTtQty8g8Uq1TTiGyeOhX9Qo4q/jOmEcI9n5qQRlHB7DVNKmG4Jx5QoQ9DwWL7Rd0bPeFqvoTOlrqmIQ3g== +"@next/bundle-analyzer@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-10.1.3.tgz#bf9a6883c66a210632954c957fe81fde04b35af5" + integrity sha512-25/I1+f83jJOryarNNGQ0cAlYdGfz5HFyQXmal4skKXhMKyWEBSKOu88tIZzsWktlhOEB8QC7O9KVgAlXPqTyw== dependencies: webpack-bundle-analyzer "4.3.0" -"@next/env@10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@next/env/-/env-10.0.9.tgz#455fd364c8a5ee012b2cd4406d5294164990706d" - integrity sha512-MERX3DY5u0Ed29eAsXeFBCZlFAGBtmjf7+Nht0hfgB25MPKKkIbC/0MRPcX/PQcAgLHsAHO6ay1u9xKzR4Vzjw== +"@next/env@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@next/env/-/env-10.1.3.tgz#29e5d62919b4a7b1859f8d36169848dc3f5ddebe" + integrity sha512-q7z7NvmRs66lCQmVJtKjDxVtMTjSwP6ExVzaH46pbTH60MHgzEJ9H4jXrFLTihPmCIvpAv6Ai04jbS8dcg1ZMQ== -"@next/polyfill-module@10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.0.9.tgz#0c21442dd73ec31ae30ac560bc5c5fdce068a98f" - integrity sha512-kPOP6ku/e8zdrK8hwxOrjUrPLcdDEj12huLHVz+DZU+20q6VlhMOtR8aKHW1460L4LoLE/DAa7YyIuxtArhDRg== +"@next/polyfill-module@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.1.3.tgz#beafe89bc4235d436fa0ed02c9d2a5d311fb0238" + integrity sha512-1DtUVcuoBJAn5IrxIZQjUG1KTPkiXMYloykPSkRxawimgvG9dRj2kscU+4KGNSFxHoxW9c68VRCb+7MDz5aGGw== -"@next/react-dev-overlay@10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.0.9.tgz#5162d66c05b2a0ca0d155f7e6663e8134d9d4ac9" - integrity sha512-JsSh2Y004MEuPYqBD9eTl4PVZIjSzSy2GcD7MrW/gQcExYNpeMIJAbh8/OcyO1t+OnQeIHF5s/xTMsDHBGNcew== +"@next/react-dev-overlay@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.1.3.tgz#ee1c6033b29be9b383e061bd9705021d131ea445" + integrity sha512-vIgUah3bR9+MKzwU1Ni5ONfYM0VdI42i7jZ+Ei1c0wjwkG9anVnDqhSQ3mVg62GP2nt7ExaaFyf9THbsw5KYXg== dependencies: "@babel/code-frame" "7.12.11" anser "1.4.9" @@ -2236,10 +2185,10 @@ stacktrace-parser "0.1.10" strip-ansi "6.0.0" -"@next/react-refresh-utils@10.0.9": - version "10.0.9" - resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.0.9.tgz#cdf9e41f8854c113397853daf78469b0c8140f14" - integrity sha512-LSoKnM+fI9MHHew+mBg1w2e4/gjwPQsI+mDTzmfwdBwje+j9U2Int6XOZftMqBPXSlL04vjC9SRBkp0+3h8cNA== +"@next/react-refresh-utils@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.1.3.tgz#65b3e1b9846c02452787fde1d54ad9c54b506dbd" + integrity sha512-P4GJZuLKfD/o42JvGZ/xP4Hxg68vd3NeZxOLqIuQKFjjaYgC2IrO+lE5PTwGmRkytjfprJC+9j7Jss/xQAS6QA== "@nodelib/fs.scandir@2.1.3": version "2.1.3" @@ -2425,10 +2374,10 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.0.1.tgz#7453d8281ce66b8ed1607f7ac7d751c3baffd2cc" integrity sha512-9AuC04PUnZrjoLiw3uPtwGh9FE4Q3rTqs51oNlQ0rkwgE8ftYsOC+lsrQyvCvWm85smBbSc0FNRKKumvGyb44Q== -"@octokit/openapi-types@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-6.0.0.tgz#7da8d7d5a72d3282c1a3ff9f951c8133a707480d" - integrity sha512-CnDdK7ivHkBtJYzWzZm7gEkanA7gKH6a09Eguz7flHw//GacPJLmkHA3f3N++MJmlxD1Fl+mB7B32EEpSCwztQ== +"@octokit/openapi-types@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-6.1.1.tgz#27f9386fcbcb9846b27b1bc8a41ba6f313c922a6" + integrity sha512-ICBhnEb+ahi/TTdNuYb/kTyKVBgAM0VD4k6JPzlhJyzt3Z+Tq/bynwCD+gpkJP7AEcNnzC8YO5R39trmzEo2UA== "@octokit/plugin-paginate-rest@^2.6.2": version "2.6.2" @@ -2442,12 +2391,12 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz#394d59ec734cd2f122431fbaf05099861ece3c44" integrity sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg== -"@octokit/plugin-rest-endpoint-methods@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.0.tgz#cf2cdeb24ea829c31688216a5b165010b61f9a98" - integrity sha512-Jc7CLNUueIshXT+HWt6T+M0sySPjF32mSFQAK7UfAg8qGeRI6OM1GSBxDLwbXjkqy2NVdnqCedJcP1nC785JYg== +"@octokit/plugin-rest-endpoint-methods@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.1.tgz#631b8d4edc6798b03489911252a25f2a4e58c594" + integrity sha512-vvWbPtPqLyIzJ7A4IPdTl+8IeuKAwMJ4LjvmqWOOdfSuqWQYZXq2CEd0hsnkidff2YfKlguzujHs/reBdAx8Sg== dependencies: - "@octokit/types" "^6.13.0" + "@octokit/types" "^6.13.1" deprecation "^2.3.1" "@octokit/request-error@^2.0.0": @@ -2473,15 +2422,15 @@ once "^1.4.0" universal-user-agent "^6.0.0" -"@octokit/rest@18.5.2": - version "18.5.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.5.2.tgz#0369e554b7076e3749005147be94c661c7a5a74b" - integrity sha512-Kz03XYfKS0yYdi61BkL9/aJ0pP2A/WK5vF/syhu9/kY30J8He3P68hv9GRpn8bULFx2K0A9MEErn4v3QEdbZcw== +"@octokit/rest@18.5.3": + version "18.5.3" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.5.3.tgz#6a2e6006a87ebbc34079c419258dd29ec9ff659d" + integrity sha512-KPAsUCr1DOdLVbZJgGNuE/QVLWEaVBpFQwDAz/2Cnya6uW2wJ/P5RVGk0itx7yyN1aGa8uXm2pri4umEqG1JBA== dependencies: "@octokit/core" "^3.2.3" "@octokit/plugin-paginate-rest" "^2.6.2" "@octokit/plugin-request-log" "^1.0.2" - "@octokit/plugin-rest-endpoint-methods" "5.0.0" + "@octokit/plugin-rest-endpoint-methods" "5.0.1" "@octokit/types@^6.0.0", "@octokit/types@^6.0.1", "@octokit/types@^6.0.3": version "6.1.2" @@ -2491,12 +2440,12 @@ "@octokit/openapi-types" "^2.0.1" "@types/node" ">= 8" -"@octokit/types@^6.13.0": - version "6.13.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.13.0.tgz#779e5b7566c8dde68f2f6273861dd2f0409480d0" - integrity sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA== +"@octokit/types@^6.13.1": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.13.2.tgz#e3423dc733567ac4836e116b34d154a8e9cbbf3c" + integrity sha512-jN5LImYHvv7W6SZargq1UMJ3EiaqIz5qkpfsv4GAb4b16SGqctxtOU2TQAZxvsKHkOw2A4zxdsi5wR9en1/ezQ== dependencies: - "@octokit/openapi-types" "^6.0.0" + "@octokit/openapi-types" "^6.1.1" "@opentelemetry/api@0.14.0": version "0.14.0" @@ -2632,24 +2581,24 @@ resolved "https://registry.yarnpkg.com/@reach/observe-rect/-/observe-rect-1.2.0.tgz#d7a6013b8aafcc64c778a0ccb83355a11204d3b2" integrity sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ== -"@reach/rect@0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.14.0.tgz#ac0cb48814c2fbf8cff5a53edf3556c01fe33dc6" - integrity sha512-mXunIyFUCbzWlUVwMuI/nL3tLDsPWwe+5knXHQQG5cOqE9tosLt9PqVYQW5iMHdpl9pGqbx7yVXMZKp2hookJg== +"@reach/rect@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@reach/rect/-/rect-0.15.0.tgz#c374b2971d250d7eeea6846fb4d64733b799f94e" + integrity sha512-Nu0zG4Xq8Z0C3Yr3wbjtj7fvII1q2KopHDStNtmL26oWPzlaZJ9A1K6rZSPIqxKkx1hvl6AUTeom7eHTIKhHjA== dependencies: "@reach/observe-rect" "1.2.0" - "@reach/utils" "0.14.0" + "@reach/utils" "0.15.0" prop-types "^15.7.2" + tiny-warning "^1.0.3" tslib "^2.1.0" -"@reach/utils@0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.14.0.tgz#f3ff579c737c3e9528f6f940bc518452f2636810" - integrity sha512-QbSFO5p44qUCkOllJM06Lt5A/EsoVIYlB9Ij1vKEezy53keaa5bc879dD2Ahv+mMf+E1VppCeiL6YYvdpJmVVQ== +"@reach/utils@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.15.0.tgz#5b183d668f9bb900b2dec7a33c028a2a828d27b2" + integrity sha512-JHHN7T5ucFiuQbqkgv8ECbRWKfRiJxrO/xHR3fHf+f2C7mVs/KkJHhYtovS1iEapR4silygX9PY0+QUmHPOTYw== dependencies: - "@types/warning" "^3.0.0" + tiny-warning "^1.0.3" tslib "^2.1.0" - warning "^4.0.3" "@salesforce/lazy-require@0.4.0": version "0.4.0" @@ -2669,20 +2618,20 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== -"@sindresorhus/slugify@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-1.1.0.tgz#2f195365d9b953384305b62664b44b4036c49430" - integrity sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw== +"@sindresorhus/slugify@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-2.0.0.tgz#9ccd8f9d29b8187f5b3e33e4423abae8a82ca00c" + integrity sha512-lGRwhzEHTiTlPj8HrSQpZ+YXbFW28pmO7/Xq5XREEt7Xd/JVgszec1I1XFGb2XeMYHKIY/Sc0V45DBGJbFzsoQ== dependencies: - "@sindresorhus/transliterate" "^0.1.1" - escape-string-regexp "^4.0.0" + "@sindresorhus/transliterate" "^1.0.0" + escape-string-regexp "^5.0.0" -"@sindresorhus/transliterate@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-0.1.1.tgz#779b31244781d3c898f185b61d58c89e7c782674" - integrity sha512-QSdIQ5keUFAZ3KLbfbsntW39ox0Ym8183RqTwBq/ZEFoN3NQAtGV+qWaNdzKpIDHgj9J2CQ2iNDRVU11Zyr7MQ== +"@sindresorhus/transliterate@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-1.0.0.tgz#7efc60bd347c16f416582eb7d18fee3bbaa3379b" + integrity sha512-5429x9FXQzC8UIav+yeMVOQTL/DdJ3ANJOyuSAvwVSLmPSsw/7KWyXpncvFbJEe4h2MfvINSrjhRgDiltSjTlw== dependencies: - escape-string-regexp "^2.0.0" + escape-string-regexp "^5.0.0" lodash.deburr "^4.1.0" "@sinonjs/commons@^1.7.0": @@ -2816,21 +2765,6 @@ dependencies: defer-to-connect "^2.0.0" -"@tailwindcss/jit@0.1.17": - version "0.1.17" - resolved "https://registry.yarnpkg.com/@tailwindcss/jit/-/jit-0.1.17.tgz#0fe54a6bd9473c3c1a5cb622ba771d69117a3d49" - integrity sha512-Of3NbM2Peex6iPkOap5JBmAPq6oVjKEKMysy6iH/9Vl0TjuEuB094Uc7yzJz8q6j6AQEImlaOGxwF+sdBlG2pw== - dependencies: - chokidar "^3.5.1" - dlv "^1.1.3" - fast-glob "^3.2.5" - lodash.topath "^4.5.2" - normalize-path "^3.0.0" - object-hash "^2.1.1" - parse-glob "^3.0.4" - postcss-selector-parser "^6.0.4" - quick-lru "^5.1.1" - "@tailwindcss/typography@0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.4.0.tgz#b80974ad6af93df7b06e1981cb4d79698b6ad5c7" @@ -2878,7 +2812,7 @@ "@types/react" ">=16.9.0" "@types/react-test-renderer" ">=16.9.0" -"@testing-library/react@^11.2.3": +"@testing-library/react@11.2.5": version "11.2.5" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.5.tgz#ae1c36a66c7790ddb6662c416c27863d87818eb9" integrity sha512-yEx7oIa/UWLe2F2dqK0FtMF9sJWNXD+2PPtp39BvE0Kh9MJ9Kl0HrZAgEuhUJR+Lx8Di6Xz+rKwSdEPY2UV8ZQ== @@ -3002,14 +2936,6 @@ dependencies: "@types/istanbul-lib-coverage" "*" -"@types/istanbul-reports@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" - integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== - dependencies: - "@types/istanbul-lib-coverage" "*" - "@types/istanbul-lib-report" "*" - "@types/istanbul-reports@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" @@ -3017,7 +2943,7 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@*", "@types/jest@26.x", "@types/jest@^26.0.20": +"@types/jest@*", "@types/jest@26.0.20", "@types/jest@26.x": version "26.0.20" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.20.tgz#cd2f2702ecf69e86b586e1f5223a60e454056307" integrity sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA== @@ -3165,11 +3091,6 @@ dependencies: "@types/node" "*" -"@types/stack-utils@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" - integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== - "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" @@ -3187,23 +3108,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== -"@types/warning@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" - integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= - "@types/yargs-parser@*": version "20.2.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== -"@types/yargs@^13.0.0": - version "13.0.11" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.11.tgz#def2f0c93e4bdf2c61d7e34899b17e34be28d3b1" - integrity sha512-NRqD6T4gktUrDi1o1wLH3EKC1o2caCr7/wR87ODcbVITQF106OM3sFN92ysZ++wqelOd1CTzatnOBRDYYG6wGQ== - dependencies: - "@types/yargs-parser" "*" - "@types/yargs@^15.0.0": version "15.0.13" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.13.tgz#34f7fec8b389d7f3c1fd08026a5763e072d3c6dc" @@ -3216,13 +3125,13 @@ resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== -"@typescript-eslint/eslint-plugin@~4.14.0": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.2.tgz#47a15803cfab89580b96933d348c2721f3d2f6fe" - integrity sha512-uMGfG7GFYK/nYutK/iqYJv6K/Xuog/vrRRZX9aEP4Zv1jsYXuvFUMDFLhUnc8WFv3D2R5QhNQL3VYKmvLS5zsQ== +"@typescript-eslint/eslint-plugin@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.17.0.tgz#6f856eca4e6a52ce9cf127dfd349096ad936aa2d" + integrity sha512-/fKFDcoHg8oNan39IKFOb5WmV7oWhQe1K6CDaAVfJaNWEhmfqlA24g+u1lqU5bMH7zuNasfMId4LaYWC5ijRLw== dependencies: - "@typescript-eslint/experimental-utils" "4.14.2" - "@typescript-eslint/scope-manager" "4.14.2" + "@typescript-eslint/experimental-utils" "4.17.0" + "@typescript-eslint/scope-manager" "4.17.0" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -3230,61 +3139,60 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.2.tgz#9df35049d1d36b6cbaba534d703648b9e1f05cbb" - integrity sha512-mV9pmET4C2y2WlyHmD+Iun8SAEqkLahHGBkGqDVslHkmoj3VnxnGP4ANlwuxxfq1BsKdl/MPieDbohCEQgKrwA== +"@typescript-eslint/experimental-utils@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.17.0.tgz#762c44aaa1a6a3c05b6d63a8648fb89b89f84c80" + integrity sha512-ZR2NIUbnIBj+LGqCFGQ9yk2EBQrpVVFOh9/Kd0Lm6gLpSAcCuLLe5lUCibKGCqyH9HPwYC0GIJce2O1i8VYmWA== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.14.2" - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/typescript-estree" "4.14.2" + "@typescript-eslint/scope-manager" "4.17.0" + "@typescript-eslint/types" "4.17.0" + "@typescript-eslint/typescript-estree" "4.17.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@~4.14.0": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.14.2.tgz#31e216e4baab678a56e539f9db9862e2542c98d0" - integrity sha512-ipqSP6EuUsMu3E10EZIApOJgWSpcNXeKZaFeNKQyzqxnQl8eQCbV+TSNsl+s2GViX2d18m1rq3CWgnpOxDPgHg== +"@typescript-eslint/parser@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.17.0.tgz#141b647ffc72ebebcbf9b0fe6087f65b706d3215" + integrity sha512-KYdksiZQ0N1t+6qpnl6JeK9ycCFprS9xBAiIrw4gSphqONt8wydBw4BXJi3C11ywZmyHulvMaLjWsxDjUSDwAw== dependencies: - "@typescript-eslint/scope-manager" "4.14.2" - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/typescript-estree" "4.14.2" + "@typescript-eslint/scope-manager" "4.17.0" + "@typescript-eslint/types" "4.17.0" + "@typescript-eslint/typescript-estree" "4.17.0" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.14.2.tgz#64cbc9ca64b60069aae0c060b2bf81163243b266" - integrity sha512-cuV9wMrzKm6yIuV48aTPfIeqErt5xceTheAgk70N1V4/2Ecj+fhl34iro/vIssJlb7XtzcaD07hWk7Jk0nKghg== +"@typescript-eslint/scope-manager@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.17.0.tgz#f4edf94eff3b52a863180f7f89581bf963e3d37d" + integrity sha512-OJ+CeTliuW+UZ9qgULrnGpPQ1bhrZNFpfT/Bc0pzNeyZwMik7/ykJ0JHnQ7krHanFN9wcnPK89pwn84cRUmYjw== dependencies: - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/visitor-keys" "4.14.2" + "@typescript-eslint/types" "4.17.0" + "@typescript-eslint/visitor-keys" "4.17.0" -"@typescript-eslint/types@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.14.2.tgz#d96da62be22dc9dc6a06647f3633815350fb3174" - integrity sha512-LltxawRW6wXy4Gck6ZKlBD05tCHQUj4KLn4iR69IyRiDHX3d3NCAhO+ix5OR2Q+q9bjCrHE/HKt+riZkd1At8Q== +"@typescript-eslint/types@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.17.0.tgz#f57d8fc7f31b348db946498a43050083d25f40ad" + integrity sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g== -"@typescript-eslint/typescript-estree@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.2.tgz#9c5ebd8cae4d7b014f890acd81e8e17f309c9df9" - integrity sha512-ESiFl8afXxt1dNj8ENEZT12p+jl9PqRur+Y19m0Z/SPikGL6rqq4e7Me60SU9a2M28uz48/8yct97VQYaGl0Vg== +"@typescript-eslint/typescript-estree@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.17.0.tgz#b835d152804f0972b80dbda92477f9070a72ded1" + integrity sha512-lRhSFIZKUEPPWpWfwuZBH9trYIEJSI0vYsrxbvVvNyIUDoKWaklOAelsSkeh3E2VBSZiNe9BZ4E5tYBZbUczVQ== dependencies: - "@typescript-eslint/types" "4.14.2" - "@typescript-eslint/visitor-keys" "4.14.2" + "@typescript-eslint/types" "4.17.0" + "@typescript-eslint/visitor-keys" "4.17.0" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" - lodash "^4.17.15" semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.2.tgz#997cbe2cb0690e1f384a833f64794e98727c70c6" - integrity sha512-KBB+xLBxnBdTENs/rUgeUKO0UkPBRs2vD09oMRRIkj5BEN8PX1ToXV532desXfpQnZsYTyLLviS7JrPhdL154w== +"@typescript-eslint/visitor-keys@4.17.0": + version "4.17.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.17.0.tgz#9c304cfd20287c14a31d573195a709111849b14d" + integrity sha512-WfuMN8mm5SSqXuAr9NM+fItJ0SVVphobWYkWOwQ1odsfC014Vdxk/92t4JwS1Q6fCA/ABfCKpa3AVtpUKTNKGQ== dependencies: - "@typescript-eslint/types" "4.14.2" + "@typescript-eslint/types" "4.17.0" eslint-visitor-keys "^2.0.0" "@visx/group@1.7.0": @@ -3321,19 +3229,11 @@ prop-types "^15.6.1" resize-observer-polyfill "1.5.1" -abab@^2.0.0, abab@^2.0.3, abab@^2.0.5: +abab@^2.0.3, abab@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -acorn-globals@^4.3.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" - integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== - dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" - acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -3356,11 +3256,6 @@ acorn-node@^1.6.1: acorn-walk "^7.0.0" xtend "^4.0.2" -acorn-walk@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" - integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== - acorn-walk@^7.0.0, acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" @@ -3371,11 +3266,6 @@ acorn-walk@^8.0.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.0.2.tgz#d4632bfc63fd93d0f15fd05ea0e984ffd3f5a8c3" integrity sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A== -acorn@^6.0.1, acorn@^6.0.4: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" @@ -3640,10 +3530,10 @@ array-differ@^3.0.0: resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== -array-equal@^1.0.0: +array-filter@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= array-includes@^3.1.1: version "3.1.1" @@ -3718,6 +3608,16 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assert@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + dependencies: + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" + assert@^1.1.1: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" @@ -3763,11 +3663,6 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - async@0.9.x: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -3815,6 +3710,13 @@ autoprefixer@10.2.5: normalize-range "^0.1.2" postcss-value-parser "^4.1.0" +available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -3895,16 +3797,6 @@ babel-plugin-extract-import-names@1.6.22: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-istanbul@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" - integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - find-up "^3.0.0" - istanbul-lib-instrument "^3.3.0" - test-exclude "^5.2.3" - babel-plugin-istanbul@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" @@ -4058,6 +3950,18 @@ before-after-hook@^2.1.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== +better-path-resolve@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/better-path-resolve/-/better-path-resolve-1.0.0.tgz#13a35a1104cdd48a7b74bf8758f96a1ee613f99d" + integrity sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g== + dependencies: + is-windows "^1.0.0" + +big-integer@^1.6.16: + version "1.6.48" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" + integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -4068,13 +3972,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" @@ -4084,33 +3981,33 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" -blitz@0.33.1: - version "0.33.1" - resolved "https://registry.yarnpkg.com/blitz/-/blitz-0.33.1.tgz#4a4cccb9bd1e6633fd6e17b3258656289f651a6e" - integrity sha512-1SfQmtWXRGtu63rqK3Rb3B1V6WdOiBlF2ruZX3zRjiP0FFC8wuIoAX5qiiVEKWO6te3b6XHsxaiwW0Zcn7Q7JA== - dependencies: - "@blitzjs/babel-preset" "0.33.1" - "@blitzjs/cli" "0.33.1" - "@blitzjs/config" "0.33.1" - "@blitzjs/core" "0.33.1" - "@blitzjs/display" "0.33.1" - "@blitzjs/generator" "0.33.1" - "@blitzjs/installer" "0.33.1" - "@blitzjs/server" "0.33.1" +blitz@0.34.3: + version "0.34.3" + resolved "https://registry.yarnpkg.com/blitz/-/blitz-0.34.3.tgz#27f84c53c4ec3b01a428b1b87e9823013ad95ae1" + integrity sha512-C0zNSrdAO+9L0yfX3bRU9T8orfhSQCdbjy46XW4GKNKotU7qHu0rpafJZX9hYf/0MEHmKXc+7yxByJpoH2+DiQ== + dependencies: + "@blitzjs/babel-preset" "0.34.3" + "@blitzjs/cli" "0.34.3" + "@blitzjs/config" "0.34.3" + "@blitzjs/core" "0.34.3" + "@blitzjs/display" "0.34.3" + "@blitzjs/generator" "0.34.3" + "@blitzjs/installer" "0.34.3" + "@blitzjs/server" "0.34.3" "@testing-library/jest-dom" "5.11.9" - "@testing-library/react" "^11.2.3" + "@testing-library/react" "11.2.5" "@testing-library/react-hooks" "^4.0.1" - "@types/jest" "^26.0.20" + "@types/jest" "26.0.20" chalk "^4.1.0" envinfo "^7.7.3" - eslint-config-blitz "0.33.1" + eslint-config-blitz "0.34.3" jest "^26.6.3" - jest-environment-jsdom-fourteen "^1.0.1" jest-watch-typeahead "^0.6.1" os-name "^4.0.0" pkg-dir "^5.0.0" react-test-renderer "17.0.1" resolve-from "^5.0.0" + symlink-dir "4.1.0" ts-jest "26.5.0" bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: @@ -4173,6 +4070,19 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" +broadcast-channel@^3.4.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.5.3.tgz#c75c39d923ae8af6284a893bfdc8bd3996d2dd2d" + integrity sha512-OLOXfwReZa2AAAh9yOUyiALB3YxBe0QpThwwuyRHLgpl8bSznSDmV6Mz7LeBJg1VZsMcDcNMy7B53w12qHrIhQ== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.0.4" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -4237,7 +4147,7 @@ browserify-sign@^4.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -browserify-zlib@^0.2.0: +browserify-zlib@0.2.0, browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== @@ -4495,12 +4405,12 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -ccount@^1.0.0, ccount@^1.0.3: +ccount@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -4972,7 +4882,7 @@ console-table-printer@^2.7.5: dependencies: simple-wcswidth "^1.0.0" -constants-browserify@^1.0.0: +constants-browserify@1.0.0, constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= @@ -5237,22 +5147,15 @@ csso@^4.0.2: dependencies: css-tree "^1.0.0" -cssom@0.3.x, cssom@^0.3.4, cssom@~0.3.6: - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - cssom@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== -cssstyle@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" - integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== - dependencies: - cssom "0.3.x" +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.3.0: version "2.3.0" @@ -5298,15 +5201,6 @@ data-uri-to-buffer@3.0.1: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== -data-urls@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" - integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== - dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" - data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -5518,6 +5412,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.5.tgz#9d270aa7eaa5af0b72c4c9d9b814e7f4ce738b79" + integrity sha512-qi86tE6hRcFHy8jI1m2VG+LaPUR1LhqDa5G8tVjuUXmOrpuAgqsA1pN0+ldgr3aKUH+QLI9hCY/OcRYisERejw== + detect-port@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" @@ -5619,6 +5518,11 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" +domain-browser@4.19.0: + version "4.19.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1" + integrity sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ== + domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" @@ -5634,13 +5538,6 @@ domelementtype@^2.0.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -5790,6 +5687,13 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encoding@0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -5892,6 +5796,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -5902,7 +5811,7 @@ escape-goat@^2.0.0: resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: +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== @@ -5917,17 +5826,10 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^1.11.0: - version "1.14.3" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" - integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== - dependencies: - esprima "^4.0.1" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== escodegen@^2.0.0: version "2.0.0" @@ -5941,13 +5843,13 @@ escodegen@^2.0.0: optionalDependencies: source-map "~0.6.1" -eslint-config-blitz@0.33.1: - version "0.33.1" - resolved "https://registry.yarnpkg.com/eslint-config-blitz/-/eslint-config-blitz-0.33.1.tgz#122bd0606c2f62cbe1d30cf9b926bcbcdd760e57" - integrity sha512-ObSP361SlIa9EEoYZWkj21M6/Qu+dwEXtJrd0BH8OrWDGJ7kgFIwI/zKrwTAirbiOZFQGKRQYedXo91YtNDSlw== +eslint-config-blitz@0.34.3: + version "0.34.3" + resolved "https://registry.yarnpkg.com/eslint-config-blitz/-/eslint-config-blitz-0.34.3.tgz#337a41187333944d2e03ed320a985d4dd8194e07" + integrity sha512-sYR8IcJSG4sag3FrlRRNtRPpNDxY5qSq1oiPjsCgN3rdbx7OcvuBMUsqSVXtoNh4PEgrltOXJVBcrwX7cVmwhA== dependencies: - "@typescript-eslint/eslint-plugin" "~4.14.0" - "@typescript-eslint/parser" "~4.14.0" + "@typescript-eslint/eslint-plugin" "4.17.0" + "@typescript-eslint/parser" "4.17.0" babel-eslint "~10.1.0" eslint-config-react-app "~6.0.0" eslint-plugin-cypress "~2.11.2" @@ -6083,10 +5985,10 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@7.23.0: - version "7.23.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.23.0.tgz#8d029d252f6e8cf45894b4bee08f5493f8e94325" - integrity sha512-kqvNVbdkjzpFy0XOszNwjkKzZ+6TcwCQ/h+ozlcIWwaimBBuhlQ4nN6kbiM2L+OjDcznkTJxzYfRFH92sx4a0Q== +eslint@7.25.0: + version "7.25.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.25.0.tgz#1309e4404d94e676e3e831b3a3ad2b050031eb67" + integrity sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw== dependencies: "@babel/code-frame" "7.12.11" "@eslint/eslintrc" "^0.4.0" @@ -6159,7 +6061,7 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== @@ -6441,11 +6343,6 @@ file-loader@6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - filelist@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" @@ -6470,15 +6367,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-cache-dir@3.3.1, find-cache-dir@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-cache-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -6488,6 +6376,15 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -6564,18 +6461,16 @@ focus-visible@5.2.0: resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3" integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ== -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -6612,23 +6507,23 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -framer-motion@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-4.0.3.tgz#e20a32c6825dc08c98e130640cb6441ec2920b7d" - integrity sha512-5p9VPpgPctMJuNW8CqHSk9k/v3xAUpReWzlgKl1a1fsvqzcFgNGENZPfBwHuukanvMmh3trzO5jZNX0Kc8/pAA== +framer-motion@4.1.9: + version "4.1.9" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-4.1.9.tgz#e4b237cb4cedb26002fb61fdbb64149a7cb3c422" + integrity sha512-s5vvzxlHk8sxvvFOr/jA7pON7elI4bvsqjmgeyvLZj0z58yzC94AGx09uB+wuzuWpKOoFwjgiD+ClcyMQ6WC9A== dependencies: - framesync "5.2.3" + framesync "5.3.0" hey-listen "^1.0.8" - popmotion "9.3.4" + popmotion "9.3.5" style-value-types "4.1.4" tslib "^2.1.0" optionalDependencies: "@emotion/is-prop-valid" "^0.8.2" -framesync@5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/framesync/-/framesync-5.2.3.tgz#73e26c83e108fb95f05515ee5c6fdf20c9fd47ab" - integrity sha512-5PxjYm5RxvsT68a9trOOL/61POxL7DcHrbx+j/50CR33mvBdp0aUTI+EfrMeVXprx3XOZ37NWg6r5ZQQOA2arA== +framesync@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-5.3.0.tgz#0ecfc955e8f5a6ddc8fdb0cc024070947e1a0d9b" + integrity sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA== dependencies: tslib "^2.1.0" @@ -6693,24 +6588,11 @@ fs-mkdirp-stream@^1.0.0: graceful-fs "^4.1.11" through2 "^2.0.3" -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.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@^2.1.2, fsevents@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -6986,12 +6868,12 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -gray-matter@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" - integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== +gray-matter@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" + integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== dependencies: - js-yaml "^3.11.0" + js-yaml "^3.13.1" kind-of "^6.0.2" section-matter "^1.0.0" strip-bom-string "^1.0.0" @@ -7167,17 +7049,6 @@ hast-util-embedded@^1.0.0: dependencies: hast-util-is-element "^1.1.0" -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - hast-util-from-parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" @@ -7274,16 +7145,6 @@ hast-util-whitespace@^1.0.0: resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - hastscript@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" @@ -7333,13 +7194,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== - dependencies: - whatwg-encoding "^1.0.1" - html-encoding-sniffer@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" @@ -7409,7 +7263,7 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" -https-browserify@^1.0.0: +https-browserify@1.0.0, https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= @@ -7449,6 +7303,13 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -7607,13 +7468,6 @@ internal-slot@^1.0.2: has "^1.0.3" side-channel "^1.0.2" -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" @@ -7654,6 +7508,13 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-arguments@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" + integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== + dependencies: + call-bind "^1.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -7693,16 +7554,16 @@ is-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.3, is-callable@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" - integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== - is-callable@^1.1.4, is-callable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== +is-callable@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" + integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -7825,6 +7686,11 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" + integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== + is-glob@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -7864,6 +7730,14 @@ is-interactive@^1.0.0: resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== +is-nan@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -7997,6 +7871,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.1" +is-typed-array@^1.1.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e" + integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.2" + es-abstract "^1.18.0-next.2" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -8024,7 +7909,7 @@ is-whitespace-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== -is-windows@^1.0.1, is-windows@^1.0.2: +is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -8088,29 +7973,11 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== - istanbul-lib-coverage@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" @@ -8237,18 +8104,6 @@ jest-each@^26.6.2: jest-util "^26.6.2" pretty-format "^26.6.2" -jest-environment-jsdom-fourteen@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-1.0.1.tgz#4cd0042f58b4ab666950d96532ecb2fc188f96fb" - integrity sha512-DojMX1sY+at5Ep+O9yME34CdidZnO3/zfPh8UW+918C5fIZET5vCjfkegixmsi7AtdYfkr4bPlIzmWnlvQkP7Q== - dependencies: - "@jest/environment" "^24.3.0" - "@jest/fake-timers" "^24.3.0" - "@jest/types" "^24.3.0" - jest-mock "^24.0.0" - jest-util "^24.0.0" - jsdom "^14.1.0" - jest-environment-jsdom@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" @@ -8279,25 +8134,6 @@ jest-get-type@^26.3.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== -jest-haste-map@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" - integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== - dependencies: - "@jest/types" "^24.9.0" - anymatch "^2.0.0" - fb-watchman "^2.0.0" - graceful-fs "^4.1.15" - invariant "^2.2.4" - jest-serializer "^24.9.0" - jest-util "^24.9.0" - jest-worker "^24.9.0" - micromatch "^3.1.10" - sane "^4.0.3" - walker "^1.0.7" - optionalDependencies: - fsevents "^1.2.7" - jest-haste-map@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" @@ -8361,20 +8197,6 @@ jest-matcher-utils@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" -jest-message-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" - integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/stack-utils" "^1.0.1" - chalk "^2.0.1" - micromatch "^3.1.10" - slash "^2.0.0" - stack-utils "^1.0.1" - jest-message-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" @@ -8390,13 +8212,6 @@ jest-message-util@^26.6.2: slash "^3.0.0" stack-utils "^2.0.2" -jest-mock@^24.0.0, jest-mock@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" - integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== - dependencies: - "@jest/types" "^24.9.0" - jest-mock@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" @@ -8410,11 +8225,6 @@ jest-pnp-resolver@^1.2.2: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== -jest-regex-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" - integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== - jest-regex-util@^26.0.0: version "26.0.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" @@ -8502,11 +8312,6 @@ jest-runtime@^26.6.3: strip-bom "^4.0.0" yargs "^15.4.1" -jest-serializer@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" - integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== - jest-serializer@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" @@ -8537,24 +8342,6 @@ jest-snapshot@^26.6.2: pretty-format "^26.6.2" semver "^7.3.2" -jest-util@^24.0.0, jest-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" - integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== - dependencies: - "@jest/console" "^24.9.0" - "@jest/fake-timers" "^24.9.0" - "@jest/source-map" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - callsites "^3.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.15" - is-ci "^2.0.0" - mkdirp "^0.5.1" - slash "^2.0.0" - source-map "^0.6.0" - jest-util@^26.1.0, jest-util@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" @@ -8605,13 +8392,14 @@ jest-watcher@^26.3.0, jest-watcher@^26.6.2: jest-util "^26.6.2" string-length "^4.0.1" -jest-worker@24.9.0, jest-worker@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" - integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== +jest-worker@27.0.0-next.5: + version "27.0.0-next.5" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.0-next.5.tgz#5985ee29b12a4e191f4aae4bb73b97971d86ec28" + integrity sha512-mk0umAQ5lT+CaOJ+Qp01N6kz48sJG2kr2n1rX0koqKf6FIygQV0qLOdN9SCYID4IVeSigDOcPeGLozdMLYfb5g== dependencies: + "@types/node" "*" merge-stream "^2.0.0" - supports-color "^6.1.0" + supports-color "^8.0.0" jest-worker@^26.6.2: version "26.6.2" @@ -8631,19 +8419,16 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.11.0, js-yaml@^3.6.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" @@ -8652,6 +8437,14 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.6.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -8682,38 +8475,6 @@ jscodeshift@0.11.0: temp "^0.8.1" write-file-atomic "^2.3.0" -jsdom@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b" - integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng== - dependencies: - abab "^2.0.0" - acorn "^6.0.4" - acorn-globals "^4.3.0" - array-equal "^1.0.0" - cssom "^0.3.4" - cssstyle "^1.1.1" - data-urls "^1.1.0" - domexception "^1.0.1" - escodegen "^1.11.0" - html-encoding-sniffer "^1.0.2" - nwsapi "^2.1.3" - parse5 "5.1.0" - pn "^1.1.0" - request "^2.88.0" - request-promise-native "^1.0.5" - saxes "^3.1.9" - symbol-tree "^3.2.2" - tough-cookie "^2.5.0" - w3c-hr-time "^1.0.1" - w3c-xmlserializer "^1.1.2" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.5" - whatwg-mimetype "^2.3.0" - whatwg-url "^7.0.0" - ws "^6.1.2" - xml-name-validator "^3.0.0" - jsdom@^16.4.0: version "16.5.1" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.1.tgz#4ced6bbd7b77d67fb980e64d9e3e6fb900f97dd6" @@ -8766,11 +8527,6 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -9070,16 +8826,6 @@ load-json-file@^2.0.0: pify "^2.0.0" strip-bom "^3.0.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - load-plugin@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/load-plugin/-/load-plugin-3.0.0.tgz#8f3ce57cf4e5111639911012487bc1c2ba3d0e6c" @@ -9298,7 +9044,7 @@ longest-streak@^2.0.1: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -9405,6 +9151,14 @@ markdown-table@^2.0.0: dependencies: repeat-string "^1.0.0" +match-sorter@^6.0.2: + version "6.3.0" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.0.tgz#454a1b31ed218cddbce6231a0ecb5fdc549fed01" + integrity sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ== + dependencies: + "@babel/runtime" "^7.12.5" + remove-accents "0.4.2" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -9571,6 +9325,11 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +microseconds@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" + integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -9675,7 +9434,7 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -9734,10 +9493,12 @@ multimatch@^5.0.0: arrify "^2.0.1" minimatch "^3.0.4" -nan@^2.12.1: - version "2.14.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" - integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= + dependencies: + big-integer "^1.6.16" nanoassert@^1.0.0: version "1.1.0" @@ -9754,6 +9515,11 @@ nanoid@^3.1.20: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== +nanoid@^3.1.22: + version "3.1.22" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" + integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -9803,46 +9569,58 @@ next-themes@0.0.14: resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.14.tgz#2b9861990bc453149e23d8e6ef1a25a119e36675" integrity sha512-x09OaM+wg3SIlEjOv8B21aw/E36jxTtfW3Dm/DPwMsSMluGt7twe1LigA6nc+mXP1u0qu9MxBaIrPPH6UTiKnA== -next@10.0.9: - version "10.0.9" - resolved "https://registry.yarnpkg.com/next/-/next-10.0.9.tgz#ad5d8e0368fee8363cdfd64d22dfbf71f683ae66" - integrity sha512-HyoVjYydcM6LaFAUOHSxVQCcKOsIimVO/IKXCuWUu1rr6DDgXbWNg/8ckH084qD46MOYlLzjViiZ3KCmNQL4Cw== +"next@npm:@blitzjs/next@10.1.3-0.34.3": + version "10.1.3-0.34.3" + resolved "https://registry.yarnpkg.com/@blitzjs/next/-/next-10.1.3-0.34.3.tgz#6ae0a769b3740267c99b9ead7caeef02c210b328" + integrity sha512-imoVqfPnxgQ5aJ1v1PIfIlDRK8bKL6OhiHUJ3+WGtTaJDfyvXQEIa1M4MrZsEua92jV5/VUbRICp7erJRwGqrw== dependencies: "@babel/runtime" "7.12.5" "@hapi/accept" "5.0.1" - "@next/env" "10.0.9" - "@next/polyfill-module" "10.0.9" - "@next/react-dev-overlay" "10.0.9" - "@next/react-refresh-utils" "10.0.9" + "@next/env" "10.1.3" + "@next/polyfill-module" "10.1.3" + "@next/react-dev-overlay" "10.1.3" + "@next/react-refresh-utils" "10.1.3" "@opentelemetry/api" "0.14.0" + assert "2.0.0" ast-types "0.13.2" + browserify-zlib "0.2.0" browserslist "4.16.1" buffer "5.6.0" caniuse-lite "^1.0.30001179" chalk "2.4.2" chokidar "3.5.1" + constants-browserify "1.0.0" crypto-browserify "3.12.0" cssnano-simple "1.2.2" + domain-browser "4.19.0" + encoding "0.1.13" etag "1.8.1" - find-cache-dir "3.3.1" get-orientation "1.1.2" - jest-worker "24.9.0" + https-browserify "1.0.0" + jest-worker "27.0.0-next.5" native-url "0.3.4" node-fetch "2.6.1" node-html-parser "1.4.9" node-libs-browser "^2.2.1" + os-browserify "0.3.0" p-limit "3.1.0" path-browserify "1.0.1" pnp-webpack-plugin "1.6.4" postcss "8.1.7" process "0.11.10" prop-types "15.7.2" + querystring-es3 "0.2.1" raw-body "2.4.1" react-is "16.13.1" react-refresh "0.8.3" stream-browserify "3.0.0" + stream-http "3.1.1" + string_decoder "1.3.0" styled-jsx "3.3.2" + timers-browserify "2.0.12" + tty-browserify "0.0.1" use-subscription "1.5.1" + util "0.12.3" vm-browserify "1.1.2" watchpack "2.1.1" @@ -10060,7 +9838,7 @@ null-loader@4.0.1: loader-utils "^2.0.0" schema-utils "^3.0.0" -nwsapi@^2.1.3, nwsapi@^2.2.0: +nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== @@ -10099,6 +9877,14 @@ object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + object-keys@^1.0.12, object-keys@^1.0.9, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -10158,15 +9944,6 @@ object.getownpropertydescriptors@^2.1.0: define-properties "^1.1.3" es-abstract "^1.17.0-next.1" -object.getownpropertydescriptors@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" - integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -10253,7 +10030,7 @@ ordered-read-streams@^1.0.0: dependencies: readable-stream "^2.0.1" -os-browserify@^0.3.0: +os-browserify@0.3.0, os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= @@ -10482,14 +10259,6 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" @@ -10514,21 +10283,11 @@ parse-passwd@^1.0.0: resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= -parse5@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" - integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== - parse5@6.0.1, parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -10612,13 +10371,6 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -10662,11 +10414,6 @@ pify@^2.0.0, pify@^2.3.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" @@ -10724,11 +10471,6 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - pnp-webpack-plugin@1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" @@ -10736,12 +10478,12 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" -popmotion@9.3.4: - version "9.3.4" - resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-9.3.4.tgz#9dea29e752491396b0beebc360d9837598f24c7c" - integrity sha512-CwUJwVEkhXZg7ZCtWLrO2lK40g/J+cEwAV0bPxOq83g2UNrvN2HTcUDnlf/rq6QeMKJPwDvXd6R8SsJO5BjDXg== +popmotion@9.3.5: + version "9.3.5" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-9.3.5.tgz#e821aff3424a021b0f2c93922db31c55cfe64149" + integrity sha512-Lr2rq8OP0j8D7CO2/6eO17ALeFCxjx1hfTGbMg+TLqFj+KZSGOoj6gRBVTzDINGqo6LQrORQSSSDaCL5OrB3bw== dependencies: - framesync "5.2.3" + framesync "5.3.0" hey-listen "^1.0.8" style-value-types "4.1.4" tslib "^2.1.0" @@ -10769,7 +10511,7 @@ postcss-js@^3.0.3: camelcase-css "^2.0.1" postcss "^8.1.6" -postcss-nested@5.0.5, postcss-nested@^5.0.5: +postcss-nested@5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.5.tgz#f0a107d33a9fab11d7637205f5321e27223e3603" integrity sha512-GSRXYz5bccobpTzLQZXOnSOfKl6TwVr5CyAQJUPub4nuRJSOECK5AqurxVgmtxP48p0Kc/ndY/YyS1yqldX0Ew== @@ -10806,13 +10548,13 @@ postcss@8.1.7, postcss@^8.1.6: nanoid "^3.1.16" source-map "^0.6.1" -postcss@8.2.8: - version "8.2.8" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece" - integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw== +postcss@8.2.12: + version "8.2.12" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.12.tgz#81248a1a87e0f575cc594a99a08207fd1c4addc4" + integrity sha512-BJnGT5+0q2tzvs6oQfnY2NpEJ7rIXNfBnZtQOKCIsweeWXBXeDd5k31UgTdS3d/c02ouspufn37mTaHWkJyzMQ== dependencies: colorette "^1.2.2" - nanoid "^3.1.20" + nanoid "^3.1.22" source-map "^0.6.1" postcss@^6.0.9: @@ -11060,7 +10802,7 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -querystring-es3@^0.2.0: +querystring-es3@0.2.1, querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= @@ -11180,12 +10922,14 @@ react-player@2.9.0: prop-types "^15.7.2" react-fast-compare "^3.0.1" -react-query@2.5.12: - version "2.5.12" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-2.5.12.tgz#f48be402886b9d95f892d836c2476ee3fdd3e479" - integrity sha512-ni2Hrz8tU/WCc5EQj+QB0jzSgxKdVL3tznFvTrXDmGjTxFj9hg1vXoxEPAn8d4pXy+lgPAflcjxht3IakUgHzg== +react-query@3.13.9: + version "3.13.9" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.13.9.tgz#52f3e29176eb115248b4c6e3b5c0bea7b60322d4" + integrity sha512-gPJ2ekm2NA911C9Fc18h///WcE7b4edf5K1JGtyi8kTSv0q9FyM2V+ttTbBAKafTMbbYh4Xg2wqXlR+/cIUZPw== dependencies: - ts-toolbelt "^6.9.4" + "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" + match-sorter "^6.0.2" react-reconciler@^0.24.0: version "0.24.0" @@ -11259,14 +11003,6 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" -read-pkg-up@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" - integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== - dependencies: - find-up "^3.0.0" - read-pkg "^3.0.0" - 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" @@ -11285,15 +11021,6 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - read-pkg@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" @@ -11360,13 +11087,6 @@ readline@1.3.0: resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" integrity sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw= -realpath-native@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" - integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== - dependencies: - util.promisify "^1.0.0" - recast@0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/recast/-/recast-0.17.2.tgz#f18f18cf20bf3fad4522621a7f9c2ada37276814" @@ -11493,15 +11213,6 @@ regjsparser@^0.6.4: dependencies: jsesc "~0.5.0" -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - rehype-parse@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" @@ -11517,15 +11228,6 @@ rehype-retext@^2.0.1: dependencies: hast-util-to-nlcst "^1.0.0" -remark-admonitions@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" - remark-footnotes@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" @@ -11627,6 +11329,11 @@ remark-stringify@^8.1.0: unherit "^1.0.4" xtend "^4.0.1" +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= + remove-bom-buffer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" @@ -11649,6 +11356,13 @@ remove-trailing-separator@^1.0.1: resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= +rename-overwrite@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rename-overwrite/-/rename-overwrite-3.1.2.tgz#a176b9b64081aca8a7396d9f442e69eaa0caa30a" + integrity sha512-hRjXzyL+g9uBmRDpX8m/00zwtso+e3XQsOgsCJGGJOQm+paoNZCKBS8Hm9x4WFfPCv2W0Ql5HOFqHlPiAO/UDw== + dependencies: + rimraf "^3.0.2" + repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" @@ -11676,7 +11390,7 @@ request-promise-core@1.1.4: dependencies: lodash "^4.17.19" -request-promise-native@^1.0.5, request-promise-native@^1.0.9: +request-promise-native@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== @@ -11685,7 +11399,7 @@ request-promise-native@^1.0.5, request-promise-native@^1.0.9: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.88.0, request@^2.88.2: +request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -11864,7 +11578,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -11920,7 +11634,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -11945,13 +11659,6 @@ sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -saxes@^3.1.9: - version "3.1.11" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" - integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== - dependencies: - xmlchars "^2.1.1" - saxes@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" @@ -12170,11 +11877,6 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -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" @@ -12382,13 +12084,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-utils@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.4.tgz#4b600971dcfc6aed0cbdf2a8268177cc916c87c8" - integrity sha512-IPDJfugEGbfizBwBZRZ3xpccMdRyP5lqsBWXGQWimVjua/ccLCeMOAVjlc1R7LxFjo5sEDhyNIXd8mo/AiDS9w== - dependencies: - escape-string-regexp "^2.0.0" - stack-utils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" @@ -12449,6 +12144,16 @@ stream-combiner@~0.0.4: dependencies: duplexer "~0.1.1" +stream-http@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" + integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.4" + readable-stream "^3.6.0" + xtend "^4.0.2" + stream-http@^2.7.2: version "2.8.3" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" @@ -12573,7 +12278,7 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@1.3.0, string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -12767,6 +12472,13 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-hyperlinks@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" @@ -12807,11 +12519,20 @@ svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -symbol-tree@^3.2.2, symbol-tree@^3.2.4: +symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +symlink-dir@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/symlink-dir/-/symlink-dir-4.1.0.tgz#655bc0573f6a359fe4f07265dfb8c2ddb98d4fa7" + integrity sha512-yT256U0E+AcFxbSUc0suJXTdOjVbVk5MmBLzqD+unQRwQbcMhTvTZnG/3UZZknemOK8+nQz2lTBZs0+uYS2apg== + dependencies: + better-path-resolve "^1.0.0" + graceful-fs "^4.1.11" + rename-overwrite "^3.0.0" + table@^6.0.4: version "6.0.7" resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" @@ -12822,29 +12543,36 @@ table@^6.0.4: slice-ansi "^4.0.0" string-width "^4.2.0" -tailwindcss@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.0.4.tgz#cf13e62738c3a27065664e449d93b66ee2945506" - integrity sha512-WhgR0oiBxGOZ9jY0yVfaJCHnckR7U74Fs/BMsYxGdwGJQ5Hd/HlaKD26bEJFZOvYScJo0QcUj2ImldzedsG7Bw== +tailwindcss@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.1.2.tgz#29402bf73a445faedd03df6d3b177e7b52b7c4a1" + integrity sha512-T5t+wwd+/hsOyRw2HJuFuv0LTUm3MUdHm2DJ94GPVgzqwPPFa9XxX0KlwLWupUuiOUj6uiKURCzYPHFcuPch/w== dependencies: "@fullhuman/postcss-purgecss" "^3.1.3" bytes "^3.0.0" chalk "^4.1.0" + chokidar "^3.5.1" color "^3.1.3" detective "^5.2.0" didyoumean "^1.2.1" + dlv "^1.1.3" + fast-glob "^3.2.5" fs-extra "^9.1.0" html-tags "^3.1.0" lodash "^4.17.21" + lodash.topath "^4.5.2" modern-normalize "^1.0.0" node-emoji "^1.8.1" + normalize-path "^3.0.0" object-hash "^2.1.1" + parse-glob "^3.0.4" postcss-functions "^3" postcss-js "^3.0.3" - postcss-nested "^5.0.5" + postcss-nested "5.0.5" postcss-selector-parser "^6.0.4" postcss-value-parser "^4.1.0" pretty-hrtime "^1.0.3" + quick-lru "^5.1.1" reduce-css-calc "^2.1.8" resolve "^1.20.0" @@ -12945,16 +12673,6 @@ ternary-stream@^3.0.0: merge-stream "^2.0.0" through2 "^3.0.1" -test-exclude@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" - integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - read-pkg-up "^4.0.0" - require-main-filename "^2.0.0" - test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -13026,7 +12744,7 @@ through@2, through@^2.3.8, through@~2.3, through@~2.3.1: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -timers-browserify@^2.0.4: +timers-browserify@2.0.12, timers-browserify@^2.0.4: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== @@ -13038,6 +12756,11 @@ tiny-emitter@^2.0.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" @@ -13130,7 +12853,7 @@ totalist@^1.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== -tough-cookie@^2.3.3, tough-cookie@^2.5.0, tough-cookie@~2.5.0: +tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -13220,11 +12943,6 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -ts-toolbelt@^6.9.4: - version "6.15.5" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83" - integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A== - tsconfig-paths@3.9.0, tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -13274,6 +12992,11 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= +tty-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -13474,17 +13197,6 @@ unified@9.2.0, unified@^9.0.0: trough "^1.0.0" vfile "^4.0.0" -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -13583,7 +13295,7 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1: +unist-util-visit@2.0.3, unist-util-visit@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== @@ -13607,6 +13319,14 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unload@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" + integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "^2.0.4" + unpipe@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -13704,17 +13424,6 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= -util.promisify@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" - integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - for-each "^0.3.3" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.1" - util.promisify@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" @@ -13732,6 +13441,18 @@ util@0.10.3: dependencies: inherits "2.0.1" +util@0.12.3, util@^0.12.0: + version "0.12.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888" + integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + util@^0.11.0: version "0.11.1" resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" @@ -13902,22 +13623,13 @@ vm-browserify@1.1.2, vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2: +w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: browser-process-hrtime "^1.0.0" -w3c-xmlserializer@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" - integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== - dependencies: - domexception "^1.0.1" - webidl-conversions "^4.0.2" - xml-name-validator "^3.0.0" - w3c-xmlserializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" @@ -13932,13 +13644,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -warning@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - watchpack@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7" @@ -13954,7 +13659,7 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -web-namespaces@^1.0.0, web-namespaces@^1.1.2: +web-namespaces@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== @@ -13989,14 +13694,14 @@ webpack-bundle-analyzer@4.3.0: sirv "^1.0.7" ws "^7.3.1" -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: +whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== dependencies: iconv-lite "0.4.24" -whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: +whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== @@ -14035,6 +13740,19 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff" + integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA== + dependencies: + available-typed-arrays "^1.0.2" + call-bind "^1.0.0" + es-abstract "^1.18.0-next.1" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@^1.2.10, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -14100,15 +13818,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" - integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - write-file-atomic@^2.3.0: version "2.4.3" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" @@ -14128,13 +13837,6 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -ws@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - ws@^7, ws@^7.2.5: version "7.4.0" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.0.tgz#a5dd76a24197940d4a8bb9e0e152bb4503764da7" @@ -14160,7 +13862,7 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xmlchars@^2.1.1, xmlchars@^2.2.0: +xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
      - - - - Adam Markon - - -
      - CLI -
      - - - - Corey Brown - - - - - - - Jaga Santagostino - - - - + - Alexandru Stratulat + Patrick Engelkes - + - Patrick Engelkes + Myron Davis
      - + - Jamie Davenport + Reo Ishiyama - + - Myron Davis + Robert Malko
      - + - Reo Ishiyama + Kevin Langley Jr. - + - Robert Malko + Alessandro Buonerba - + - Kevin Langley Jr. + Tommaso Bruno