WIP changes

This commit is contained in:
daniel31x13 2023-11-02 01:52:49 -04:00
parent b1b0d98eb2
commit b458fad567
20 changed files with 358 additions and 43 deletions

View File

@ -0,0 +1,21 @@
import { NextApiRequest } from "next";
import { getToken } from "next-auth/jwt";
type Props = {
req: NextApiRequest;
};
export default async function authenticateUser({ req }: Props) {
const token = await getToken({ req });
if (!token?.id) {
return { response: "You must be logged in.", status: 401 };
} else if (token.isSubscriber === false)
return {
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
status: 401,
};
return token;
}

View File

@ -40,6 +40,7 @@
"eslint-config-next": "13.4.9",
"framer-motion": "^10.16.4",
"jsdom": "^22.1.0",
"micro": "^10.0.1",
"next": "13.4.12",
"next-auth": "^4.22.1",
"next-themes": "^0.2.1",

View File

@ -16,7 +16,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.username)
return res.status(401).json({ response: "You must be logged in." });
else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -1,10 +1,9 @@
import { prisma } from "@/lib/api/db";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
import { AuthOptions, Session } from "next-auth";
import { AuthOptions, Session, User } from "next-auth";
import bcrypt from "bcrypt";
import EmailProvider from "next-auth/providers/email";
import { JWT } from "next-auth/jwt";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { Adapter } from "next-auth/adapters";
import sendVerificationRequest from "@/lib/api/sendVerificationRequest";
@ -19,6 +18,7 @@ const providers: Provider[] = [
type: "credentials",
credentials: {},
async authorize(credentials, req) {
console.log("User logged in...");
if (!credentials) return null;
const { username, password } = credentials as {
@ -81,13 +81,6 @@ export const authOptions: AuthOptions = {
verifyRequest: "/confirmation",
},
callbacks: {
session: async ({ session, token }: { session: Session; token: JWT }) => {
session.user.id = parseInt(token.id as string);
session.user.username = token.username as string;
session.user.isSubscriber = token.isSubscriber as boolean;
return session;
},
async jwt({ token, trigger, user }) {
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;
@ -121,7 +114,7 @@ export const authOptions: AuthOptions = {
}
if (trigger === "signIn") {
token.id = user.id;
token.id = user.id as number;
token.username = (user as any).username;
} else if (trigger === "update" && token.id) {
console.log(token);
@ -132,7 +125,7 @@ export const authOptions: AuthOptions = {
},
});
if (user) {
if (user?.name && user.username && user.email) {
token.name = user.name;
token.username = user.username?.toLowerCase();
token.email = user.email?.toLowerCase();
@ -140,6 +133,13 @@ export const authOptions: AuthOptions = {
}
return token;
},
async session({ session, token }) {
session.user.id = token.id;
session.user.username = token.username;
session.user.isSubscriber = token.isSubscriber;
return session;
},
},
};

View File

@ -17,7 +17,7 @@ export default async function Index(req: NextApiRequest, res: NextApiResponse) {
.status(401)
.send("You must be logged in.");
else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -13,7 +13,7 @@ export default async function collections(
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -13,7 +13,7 @@ export default async function collections(
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -10,7 +10,7 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -1,18 +1,10 @@
// For future...
// import { getToken } from "next-auth/jwt";
import { NextApiRequest, NextApiResponse } from "next";
import { getToken } from "next-auth/jwt";
// export default async (req, res) => {
// // If you don't have NEXTAUTH_SECRET set, you will have to pass your secret as `secret` to `getToken`
// console.log({ req });
// const token = await getToken({ req, raw: true });
// if (token) {
// // Signed in
// console.log("JSON Web Token", JSON.stringify(token, null, 2));
// } else {
// // Not Signed in
// res.status(401);
// }
// res.end();
// };
export {};
export default async (req: NextApiRequest, res: NextApiResponse) => {
// if using `NEXTAUTH_SECRET` env variable, we detect it, and you won't actually need to `secret`
// const token = await getToken({ req })
const token = await getToken({ req });
console.log("JSON Web Token", token);
res.end();
};

View File

@ -12,7 +12,7 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -11,7 +11,7 @@ export default async function links(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -4,14 +4,19 @@ import { authOptions } from "@/pages/api/v1/auth/[...nextauth]";
import getLinks from "@/lib/api/controllers/links/getLinks";
import postLink from "@/lib/api/controllers/links/postLink";
import { LinkRequestQuery } from "@/types/global";
import { getToken } from "next-auth/jwt";
export default async function links(req: NextApiRequest, res: NextApiResponse) {
const session = await getServerSession(req, res, authOptions);
const token = await getToken({ req });
// const session = await getServerSession(req, res, authOptions);
return res.status(200).json(token);
if (!session?.user?.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -20,7 +20,7 @@ export default async function users(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user.id) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -9,7 +9,7 @@ export default async function tags(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.username) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -9,7 +9,7 @@ export default async function tags(req: NextApiRequest, res: NextApiResponse) {
if (!session?.user?.username) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -26,7 +26,7 @@ export default async function users(req: NextApiRequest, res: NextApiResponse) {
if (!userId) {
return res.status(401).json({ response: "You must be logged in." });
} else if (session?.user?.isSubscriber === false)
res.status(401).json({
return res.status(401).json({
response:
"You are not a subscriber, feel free to reach out to us at support@linkwarden.app in case of any issues.",
});

View File

@ -0,0 +1,62 @@
// TODO - Stripe webhooks for user cancellation...
// import { NextApiRequest, NextApiResponse } from "next";
// import Stripe from "stripe";
// import { buffer } from "micro";
// import { prisma } from "@/lib/api/db";
// const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string, {
// apiVersion: "2022-11-15",
// });
// const endpointSecret =
// "whsec_7c144bcd924041257e3d83eac1e2fba9c8a938b240fd8adb1c902f079e0cdee0";
// export const config = {
// api: {
// bodyParser: false,
// },
// };
// export default async function handler(
// req: NextApiRequest,
// res: NextApiResponse
// ) {
// if (req.method === "POST") {
// const buf = await buffer(req);
// const sig = req.headers["stripe-signature"];
// let event: Stripe.Event;
// try {
// if (!sig) throw new Error("Stripe Signature is not defined.");
// event = stripe.webhooks.constructEvent(buf, sig, endpointSecret);
// } catch (err) {
// console.log(err);
// return res.status(400).send({ response: "Error..." });
// }
// // Handle the event
// switch (event.type) {
// case "customer.subscription.deleted":
// const customerSubscriptionDeleted = event.data.object as any;
// // Revoke all the token under the customers email...
// const customer = (await stripe.customers.retrieve(
// customerSubscriptionDeleted.customer
// )) as any;
// if (customer?.email) {
// // Revoke tokens inside the database
// }
// break;
// // ... handle other event types
// default:
// console.log(`Unhandled event type ${event.type}`);
// }
// return res.status(200).send({ response: "Done!" });
// }
// }

125
pages/test.tsx Normal file
View File

@ -0,0 +1,125 @@
import SubmitButton from "@/components/SubmitButton";
import TextInput from "@/components/TextInput";
import CenteredForm from "@/layouts/CenteredForm";
import { signIn } from "next-auth/react";
import Link from "next/link";
import { useState, FormEvent } from "react";
import { toast } from "react-hot-toast";
interface FormData {
username: string;
password: string;
}
const emailEnabled = process.env.NEXT_PUBLIC_EMAIL_PROVIDER;
export default function Login() {
const [submitLoader, setSubmitLoader] = useState(false);
const [form, setForm] = useState<FormData>({
username: "",
password: "",
});
async function loginUser(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
if (form.username !== "" && form.password !== "") {
setSubmitLoader(true);
const load = toast.loading("Authenticating...");
const res = await signIn("credentials", {
username: form.username,
password: form.password,
redirect: false,
});
console.log(res);
toast.dismiss(load);
setSubmitLoader(false);
if (!res?.ok) {
toast.error("Invalid login.");
}
} else {
toast.error("Please fill out all the fields.");
}
}
return (
<CenteredForm text="Sign in to your account">
<form onSubmit={loginUser}>
<div className="p-4 mx-auto flex flex-col gap-3 justify-between max-w-[30rem] min-w-80 w-full bg-slate-50 dark:bg-neutral-800 rounded-2xl shadow-md border border-sky-100 dark:border-neutral-700">
<p className="text-3xl text-black dark:text-white text-center font-extralight">
Enter your credentials
</p>
<hr className="border-1 border-sky-100 dark:border-neutral-700" />
<div>
<p className="text-sm text-black dark:text-white w-fit font-semibold mb-1">
Username
{emailEnabled ? " or Email" : undefined}
</p>
<TextInput
autoFocus={true}
placeholder="johnny"
value={form.username}
className="bg-white"
onChange={(e) => setForm({ ...form, username: e.target.value })}
/>
</div>
<div className="w-full">
<p className="text-sm text-black dark:text-white w-fit font-semibold mb-1">
Password
</p>
<TextInput
type="password"
placeholder="••••••••••••••"
value={form.password}
className="bg-white"
onChange={(e) => setForm({ ...form, password: e.target.value })}
/>
{emailEnabled && (
<div className="w-fit ml-auto mt-1">
<Link
href={"/forgot"}
className="text-gray-500 dark:text-gray-400 font-semibold"
>
Forgot Password?
</Link>
</div>
)}
</div>
<SubmitButton
type="submit"
label="Login"
className=" w-full text-center"
loading={submitLoader}
/>
{process.env.NEXT_PUBLIC_DISABLE_REGISTRATION ===
"true" ? undefined : (
<div className="flex items-baseline gap-1 justify-center">
<p className="w-fit text-gray-500 dark:text-gray-400">
New here?
</p>
<Link
href={"/register"}
className="block text-black dark:text-white font-semibold"
>
Sign Up
</Link>
</div>
)}
</div>
</form>
</CenteredForm>
);
}

32
types/next-auth.d.ts vendored
View File

@ -1,4 +1,5 @@
import NextAuth from "next-auth";
import { JWT } from "next-auth/jwt";
declare module "next-auth" {
interface Session {
@ -9,4 +10,35 @@ declare module "next-auth" {
isSubscriber: boolean;
};
}
interface User {
id: number;
name: string;
username: string;
email: string;
emailVerified: Date;
image: string;
password: string;
archiveAsScreenshot: boolean;
archiveAsPDF: boolean;
archiveAsWaybackMachine: boolean;
isPrivate: boolean;
createdAt: Date;
updatedAt: Date;
}
}
declare module "next-auth/jwt" {
interface JWT {
name: string;
email: string;
picture: string;
sub: string;
isSubscriber: boolean;
id: number;
username: string;
iat: number;
exp: number;
jti: string;
}
}

View File

@ -1702,6 +1702,11 @@ are-we-there-yet@^2.0.0:
delegates "^1.0.0"
readable-stream "^3.6.0"
arg@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==
arg@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
@ -1929,6 +1934,11 @@ busboy@1.6.0:
dependencies:
streamsearch "^1.1.0"
bytes@3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
call-bind@^1.0.0, call-bind@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@ -2079,6 +2089,11 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0:
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
content-type@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
convert-source-map@^1.5.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
@ -2256,6 +2271,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
detect-libc@^2.0.0, detect-libc@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
@ -3122,6 +3142,17 @@ html-encoding-sniffer@^3.0.0:
dependencies:
whatwg-encoding "^2.0.0"
http-errors@1.7.3:
version "1.7.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
dependencies:
depd "~1.1.2"
inherits "2.0.4"
setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
@ -3148,6 +3179,13 @@ https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1:
agent-base "6"
debug "4"
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@ -3186,7 +3224,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.3, inherits@^2.0.4:
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -3613,6 +3651,15 @@ merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micro@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/micro/-/micro-10.0.1.tgz#2601e02b0dacd2eaee77e9de18f12b2e595c5951"
integrity sha512-9uwZSsUrqf6+4FLLpiPj5TRWQv5w5uJrJwsx1LR/TjqvQmKC1XnGQ9OHrFwR3cbZ46YqPqxO/XJCOpWnqMPw2Q==
dependencies:
arg "4.1.0"
content-type "1.0.4"
raw-body "2.4.1"
micromatch@^4.0.4, micromatch@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
@ -4273,6 +4320,16 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
raw-body@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
dependencies:
bytes "3.1.0"
http-errors "1.7.3"
iconv-lite "0.4.24"
unpipe "1.0.0"
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
@ -4483,7 +4540,7 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3"
is-regex "^1.1.4"
"safer-buffer@>= 2.1.2 < 3.0.0", 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==
@ -4519,6 +4576,11 @@ set-blocking@^2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
setprototypeof@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
sharp@^0.32.1:
version "0.32.1"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.1.tgz#41aa0d0b2048b2e0ee453d9fcb14ec1f408390fe"
@ -4615,6 +4677,11 @@ sshpk@^1.7.0:
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
"statuses@>= 1.5.0 < 2":
version "1.5.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
stop-iteration-iterator@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
@ -4877,6 +4944,11 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
toidentifier@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
tough-cookie@^4.1.2:
version "4.1.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
@ -4997,6 +5069,11 @@ universalify@^0.2.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
unpipe@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
update-browserslist-db@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"