diff --git a/services/auth.proxy.cors.sh/.gitignore b/.archives/auth.proxy.cors.sh/.gitignore similarity index 100% rename from services/auth.proxy.cors.sh/.gitignore rename to .archives/auth.proxy.cors.sh/.gitignore diff --git a/services/auth.proxy.cors.sh/deploy/prod.sh b/.archives/auth.proxy.cors.sh/deploy/prod.sh similarity index 100% rename from services/auth.proxy.cors.sh/deploy/prod.sh rename to .archives/auth.proxy.cors.sh/deploy/prod.sh diff --git a/services/auth.proxy.cors.sh/deploy/staging.sh b/.archives/auth.proxy.cors.sh/deploy/staging.sh similarity index 100% rename from services/auth.proxy.cors.sh/deploy/staging.sh rename to .archives/auth.proxy.cors.sh/deploy/staging.sh diff --git a/services/auth.proxy.cors.sh/handler.ts b/.archives/auth.proxy.cors.sh/handler.ts similarity index 100% rename from services/auth.proxy.cors.sh/handler.ts rename to .archives/auth.proxy.cors.sh/handler.ts diff --git a/services/auth.proxy.cors.sh/package.json b/.archives/auth.proxy.cors.sh/package.json similarity index 100% rename from services/auth.proxy.cors.sh/package.json rename to .archives/auth.proxy.cors.sh/package.json diff --git a/services/auth.proxy.cors.sh/readme.md b/.archives/auth.proxy.cors.sh/readme.md similarity index 100% rename from services/auth.proxy.cors.sh/readme.md rename to .archives/auth.proxy.cors.sh/readme.md diff --git a/services/auth.proxy.cors.sh/serverless.yml b/.archives/auth.proxy.cors.sh/serverless.yml similarity index 100% rename from services/auth.proxy.cors.sh/serverless.yml rename to .archives/auth.proxy.cors.sh/serverless.yml diff --git a/services/auth.proxy.cors.sh/yarn.lock b/.archives/auth.proxy.cors.sh/yarn.lock similarity index 100% rename from services/auth.proxy.cors.sh/yarn.lock rename to .archives/auth.proxy.cors.sh/yarn.lock diff --git a/cli/bin.ts b/.archives/cli/bin.ts similarity index 100% rename from cli/bin.ts rename to .archives/cli/bin.ts diff --git a/cli/index.ts b/.archives/cli/index.ts similarity index 100% rename from cli/index.ts rename to .archives/cli/index.ts diff --git a/cli/jes.config.js b/.archives/cli/jes.config.js similarity index 100% rename from cli/jes.config.js rename to .archives/cli/jes.config.js diff --git a/cli/package.json b/.archives/cli/package.json similarity index 100% rename from cli/package.json rename to .archives/cli/package.json diff --git a/cli/readme.md b/.archives/cli/readme.md similarity index 100% rename from cli/readme.md rename to .archives/cli/readme.md diff --git a/cli/tsconfig.json b/.archives/cli/tsconfig.json similarity index 100% rename from cli/tsconfig.json rename to .archives/cli/tsconfig.json diff --git a/cli/update/index.ts b/.archives/cli/update/index.ts similarity index 100% rename from cli/update/index.ts rename to .archives/cli/update/index.ts diff --git a/cli/version/index.ts b/.archives/cli/version/index.ts similarity index 100% rename from cli/version/index.ts rename to .archives/cli/version/index.ts diff --git a/cli/yarn.lock b/.archives/cli/yarn.lock similarity index 100% rename from cli/yarn.lock rename to .archives/cli/yarn.lock diff --git a/services/mail.cors.sh/onboarding.mjml b/.archives/mail.cors.sh/onboarding.mjml similarity index 100% rename from services/mail.cors.sh/onboarding.mjml rename to .archives/mail.cors.sh/onboarding.mjml diff --git a/services/mail.cors.sh/onboarding_with_payment_success.mjml b/.archives/mail.cors.sh/onboarding_with_payment_success.mjml similarity index 100% rename from services/mail.cors.sh/onboarding_with_payment_success.mjml rename to .archives/mail.cors.sh/onboarding_with_payment_success.mjml diff --git a/services/mail.cors.sh/render/onboarding.subject b/.archives/mail.cors.sh/render/onboarding.subject similarity index 100% rename from services/mail.cors.sh/render/onboarding.subject rename to .archives/mail.cors.sh/render/onboarding.subject diff --git a/services/mail.cors.sh/render/onboarding.template.html b/.archives/mail.cors.sh/render/onboarding.template.html similarity index 100% rename from services/mail.cors.sh/render/onboarding.template.html rename to .archives/mail.cors.sh/render/onboarding.template.html diff --git a/services/mail.cors.sh/render/onboarding_with_payment_success.subject b/.archives/mail.cors.sh/render/onboarding_with_payment_success.subject similarity index 100% rename from services/mail.cors.sh/render/onboarding_with_payment_success.subject rename to .archives/mail.cors.sh/render/onboarding_with_payment_success.subject diff --git a/services/mail.cors.sh/render/onboarding_with_payment_success.template.html b/.archives/mail.cors.sh/render/onboarding_with_payment_success.template.html similarity index 100% rename from services/mail.cors.sh/render/onboarding_with_payment_success.template.html rename to .archives/mail.cors.sh/render/onboarding_with_payment_success.template.html diff --git a/services/lagacy/.gitignore b/.archives/proxy/.gitignore similarity index 100% rename from services/lagacy/.gitignore rename to .archives/proxy/.gitignore diff --git a/services/lagacy/README.md b/.archives/proxy/README.md similarity index 100% rename from services/lagacy/README.md rename to .archives/proxy/README.md diff --git a/services/lagacy/lib/cors.ts b/.archives/proxy/lib/cors.ts similarity index 100% rename from services/lagacy/lib/cors.ts rename to .archives/proxy/lib/cors.ts diff --git a/services/lagacy/lib/utils.ts b/.archives/proxy/lib/utils.ts similarity index 100% rename from services/lagacy/lib/utils.ts rename to .archives/proxy/lib/utils.ts diff --git a/services/lagacy/package.json b/.archives/proxy/package.json similarity index 100% rename from services/lagacy/package.json rename to .archives/proxy/package.json diff --git a/services/lagacy/serverless.yml b/.archives/proxy/serverless.yml similarity index 100% rename from services/lagacy/serverless.yml rename to .archives/proxy/serverless.yml diff --git a/services/lagacy/src/_util/size.ts b/.archives/proxy/src/_util/size.ts similarity index 100% rename from services/lagacy/src/_util/size.ts rename to .archives/proxy/src/_util/size.ts diff --git a/services/lagacy/src/app.ts b/.archives/proxy/src/app.ts similarity index 100% rename from services/lagacy/src/app.ts rename to .archives/proxy/src/app.ts diff --git a/services/lagacy/src/auth/_tmp_static_api_keys/.gitignore b/.archives/proxy/src/auth/_tmp_static_api_keys/.gitignore similarity index 100% rename from services/lagacy/src/auth/_tmp_static_api_keys/.gitignore rename to .archives/proxy/src/auth/_tmp_static_api_keys/.gitignore diff --git a/services/lagacy/src/auth/_tmp_static_api_keys/README.md b/.archives/proxy/src/auth/_tmp_static_api_keys/README.md similarity index 100% rename from services/lagacy/src/auth/_tmp_static_api_keys/README.md rename to .archives/proxy/src/auth/_tmp_static_api_keys/README.md diff --git a/services/lagacy/src/auth/_tmp_static_api_keys/index.js b/.archives/proxy/src/auth/_tmp_static_api_keys/index.js similarity index 100% rename from services/lagacy/src/auth/_tmp_static_api_keys/index.js rename to .archives/proxy/src/auth/_tmp_static_api_keys/index.js diff --git a/services/lagacy/src/auth/index.ts b/.archives/proxy/src/auth/index.ts similarity index 100% rename from services/lagacy/src/auth/index.ts rename to .archives/proxy/src/auth/index.ts diff --git a/services/lagacy/src/auth/static-account-api-key-auth.ts b/.archives/proxy/src/auth/static-account-api-key-auth.ts similarity index 100% rename from services/lagacy/src/auth/static-account-api-key-auth.ts rename to .archives/proxy/src/auth/static-account-api-key-auth.ts diff --git a/services/lagacy/src/index.ts b/.archives/proxy/src/index.ts similarity index 100% rename from services/lagacy/src/index.ts rename to .archives/proxy/src/index.ts diff --git a/services/lagacy/src/limit/README.md b/.archives/proxy/src/limit/README.md similarity index 100% rename from services/lagacy/src/limit/README.md rename to .archives/proxy/src/limit/README.md diff --git a/services/lagacy/src/limit/blacklist-origin.ts b/.archives/proxy/src/limit/blacklist-origin.ts similarity index 100% rename from services/lagacy/src/limit/blacklist-origin.ts rename to .archives/proxy/src/limit/blacklist-origin.ts diff --git a/services/lagacy/src/limit/index.ts b/.archives/proxy/src/limit/index.ts similarity index 100% rename from services/lagacy/src/limit/index.ts rename to .archives/proxy/src/limit/index.ts diff --git a/services/lagacy/src/limit/payload-limit.ts b/.archives/proxy/src/limit/payload-limit.ts similarity index 100% rename from services/lagacy/src/limit/payload-limit.ts rename to .archives/proxy/src/limit/payload-limit.ts diff --git a/services/lagacy/src/limit/unknown-host-limit.ts b/.archives/proxy/src/limit/unknown-host-limit.ts similarity index 100% rename from services/lagacy/src/limit/unknown-host-limit.ts rename to .archives/proxy/src/limit/unknown-host-limit.ts diff --git a/services/lagacy/src/usage/README.md b/.archives/proxy/src/usage/README.md similarity index 100% rename from services/lagacy/src/usage/README.md rename to .archives/proxy/src/usage/README.md diff --git a/services/lagacy/src/usage/index.ts b/.archives/proxy/src/usage/index.ts similarity index 100% rename from services/lagacy/src/usage/index.ts rename to .archives/proxy/src/usage/index.ts diff --git a/services/lagacy/src/usage/model.ts b/.archives/proxy/src/usage/model.ts similarity index 100% rename from services/lagacy/src/usage/model.ts rename to .archives/proxy/src/usage/model.ts diff --git a/services/lagacy/tsconfig.json b/.archives/proxy/tsconfig.json similarity index 100% rename from services/lagacy/tsconfig.json rename to .archives/proxy/tsconfig.json diff --git a/services/lagacy/yarn.lock b/.archives/proxy/yarn.lock similarity index 100% rename from services/lagacy/yarn.lock rename to .archives/proxy/yarn.lock diff --git a/.vscode/settings.json b/.vscode/settings.json index f73bbc8..0869d6e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,6 +12,8 @@ "**/node_modules": true, "**/.build": true, "**/.lock": true, - "**/*.code-search": true + "**/.archives": true, + "**/*.code-search": true, + "**/.next": true, } } diff --git a/docs/blog/2019-05-28-first-blog-post.md b/docs/blog/2019-05-28-first-blog-post.md deleted file mode 100644 index 02f3f81..0000000 --- a/docs/blog/2019-05-28-first-blog-post.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -slug: first-blog-post -title: First Blog Post -authors: - name: Gao Wei - title: Docusaurus Core Team - url: https://github.com/wgao19 - image_url: https://github.com/wgao19.png -tags: [hola, docusaurus] ---- - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/docs/blog/2019-05-29-long-blog-post.md b/docs/blog/2019-05-29-long-blog-post.md deleted file mode 100644 index 26ffb1b..0000000 --- a/docs/blog/2019-05-29-long-blog-post.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -slug: long-blog-post -title: Long Blog Post -authors: endi -tags: [hello, docusaurus] ---- - -This is the summary of a very long blog post, - -Use a `` comment to limit blog post size in the list view. - - - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet - -Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet diff --git a/docs/blog/2021-08-01-mdx-blog-post.mdx b/docs/blog/2021-08-01-mdx-blog-post.mdx deleted file mode 100644 index c04ebe3..0000000 --- a/docs/blog/2021-08-01-mdx-blog-post.mdx +++ /dev/null @@ -1,20 +0,0 @@ ---- -slug: mdx-blog-post -title: MDX Blog Post -authors: [slorber] -tags: [docusaurus] ---- - -Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/). - -:::tip - -Use the power of React to create interactive blog posts. - -```js - -``` - - - -::: diff --git a/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg b/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg deleted file mode 100644 index 11bda09..0000000 Binary files a/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg and /dev/null differ diff --git a/docs/blog/2021-08-26-welcome/index.md b/docs/blog/2021-08-26-welcome/index.md deleted file mode 100644 index 9455168..0000000 --- a/docs/blog/2021-08-26-welcome/index.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -slug: welcome -title: Welcome -authors: [slorber, yangshun] -tags: [facebook, hello, docusaurus] ---- - -[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog). - -Simply add Markdown files (or folders) to the `blog` directory. - -Regular blog authors can be added to `authors.yml`. - -The blog post date can be extracted from filenames, such as: - -- `2019-05-30-welcome.md` -- `2019-05-30-welcome/index.md` - -A blog post folder can be convenient to co-locate blog post images: - -![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg) - -The blog supports tags as well! - -**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config. diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml deleted file mode 100644 index bcb2991..0000000 --- a/docs/blog/authors.yml +++ /dev/null @@ -1,17 +0,0 @@ -endi: - name: Endilie Yacop Sucipto - title: Maintainer of Docusaurus - url: https://github.com/endiliey - image_url: https://github.com/endiliey.png - -yangshun: - name: Yangshun Tay - title: Front End Engineer @ Facebook - url: https://github.com/yangshun - image_url: https://github.com/yangshun.png - -slorber: - name: Sébastien Lorber - title: Docusaurus maintainer - url: https://sebastienlorber.com - image_url: https://github.com/slorber.png diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 876749d..21e5ed9 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -42,13 +42,6 @@ const config = { // Remove this to remove the "edit this page" links. editUrl: "https://github.com/gridaco/cors.sh/tree/main/docs/", }, - blog: { - showReadingTime: true, - // Please change this to your repo. - // Remove this to remove the "edit this page" links. - editUrl: - "https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/", - }, // tracking googleAnalytics: { trackingID: "G-XG051N1VS3", @@ -77,7 +70,6 @@ const config = { position: "left", label: "Tutorial", }, - { to: "/blog", label: "Blog", position: "left" }, { href: "https://github.com/facebook/docusaurus", label: "GitHub", @@ -113,10 +105,6 @@ const config = { { title: "More", items: [ - { - label: "Blog", - to: "/blog", - }, { label: "GitHub", href: "https://github.com/gridaco/cors.sh", @@ -124,7 +112,7 @@ const config = { ], }, ], - copyright: `Copyright © ${new Date().getFullYear()} Grida, Inc. Built with Docusaurus.`, + copyright: `Copyright © ${new Date().getFullYear()} Grida, Inc.`, }, prism: { theme: lightCodeTheme, diff --git a/packages/api/index.ts b/packages/api/index.ts index a459811..dfcc470 100644 --- a/packages/api/index.ts +++ b/packages/api/index.ts @@ -2,14 +2,14 @@ import Axios, { AxiosInstance, AxiosError } from "axios"; const HOST = process.env.NODE_ENV === "production" - ? "https://services.cors.sh" - : "http://localhost:4021"; + ? "https://cors.sh" + : "http://localhost:8823"; export class Client { private _client: AxiosInstance; constructor(credentials: { "x-cors-service-checkout-session-id"?: string }) { this._client = Axios.create({ - baseURL: HOST, + baseURL: HOST + '/api', headers: { ...credentials, }, diff --git a/packages/editor-ui b/packages/editor-ui index 6f0a9a4..14e8de7 160000 --- a/packages/editor-ui +++ b/packages/editor-ui @@ -1 +1 @@ -Subproject commit 6f0a9a4a5abf5c9e1ac5bc9799eac4886616ad9c +Subproject commit 14e8de73e9f92ad220d3721ced8e722b37c00309 diff --git a/services/services.cors.sh/app.ts b/services/services.cors.sh/app.ts deleted file mode 100644 index 96f1c19..0000000 --- a/services/services.cors.sh/app.ts +++ /dev/null @@ -1,34 +0,0 @@ -import express from "express"; -import useragent from "express-useragent"; -import cors from "cors"; -import bodyParser from "body-parser"; -import router from "./routes"; - -function logErrors(err, req, res, next) { - console.error(err.stack); - next(err); -} - -const app = express(); - -app.get("/", (req, res) => { - res.redirect("https://cors.sh"); -}); - -app.use(cors()); - -app.use( - bodyParser.urlencoded({ - extended: true, - }) -); - -app.use(useragent.express()); - -app.use(bodyParser.json()); - -app.use(logErrors); - -app.use(router); - -export { app }; diff --git a/services/services.cors.sh/auth/jwt.ts b/services/services.cors.sh/auth/jwt.ts deleted file mode 100644 index b39fb7c..0000000 --- a/services/services.cors.sh/auth/jwt.ts +++ /dev/null @@ -1,31 +0,0 @@ -import jwt from "jsonwebtoken"; - -const _SECRET = process.env.SERVICE_JWT_SECRET as string; - -export interface ServiceUserSignature { - type: "customer"; - service: "cors.sh"; - id: string; -} - -export function decode_jwt(token: string): ServiceUserSignature { - return jwt.verify(token, _SECRET) as ServiceUserSignature; -} - -export function encode_jwt(service_user_id: string): string { - const payload: ServiceUserSignature = { - type: "customer", - service: "cors.sh", - id: service_user_id, - }; - return jwt.sign(payload, _SECRET); -} - -export function verify(token: string) { - const pl = jwt.verify(token, _SECRET) as ServiceUserSignature; - if (pl.service == "cors.sh" && pl.type == "customer") { - return pl.id; - } else { - throw new Error("invalid token"); - } -} diff --git a/services/services.cors.sh/auth/middleware.ts b/services/services.cors.sh/auth/middleware.ts deleted file mode 100644 index 79b4c8d..0000000 --- a/services/services.cors.sh/auth/middleware.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { verify } from "./jwt"; -import { Request, Response } from "express"; -import { prisma, stripe } from "../clients"; -import { SECURE_BROWSER_COOKIE_AUTH_KEY } from "./key"; - -// since the secure cookie cannot be forged, we have no additional validation on the jwt from client's secure http only cookie. -// the possible hacking scenario is.. -// 1. the hacker steals the jwt secret (impossible, but somehow.) -// 2. the hacker finds out the customer id of services.cors.sh -// 3. the hacker sets the cookie with the jwt token, and the customer id. -// - seems secure enough for now. -export async function authMiddleware(req: Request, res: Response, next) { - const _1 = await standardAuthorizer(req); - if (_1) { - const { customer } = _1; - res.locals.customer = customer; - next(); - return; - } - - const _2 = await checoutSessionAuthorizer(req); - if (_2) { - const { customer } = _2; - res.locals.customer = customer; - next(); - return; - } - - return res.status(401).json({ error: "Unauthorized" }); -} - -async function checoutSessionAuthorizer(req: Request) { - const checkout_session_id = req.headers["x-cors-service-checkout-session-id"]; - if (!checkout_session_id) { - return false; - } - - const checkout_session = await stripe.checkout.sessions.retrieve( - checkout_session_id as string - ); - - const { customer: stripe_customer_id } = checkout_session; - - const customer = await prisma.customer.findUnique({ - where: { - stripeId: stripe_customer_id as string, - }, - }); - - if (!customer) { - return false; - } - - return { - customer, - }; -} - -async function standardAuthorizer(req: Request): Promise { - const authorization = req.signedCookies?.[SECURE_BROWSER_COOKIE_AUTH_KEY]; - if (!authorization) { - return false; - } - - try { - const customerid = verify(authorization); - const customer = await prisma.customer.findUnique({ - where: { - id: customerid, - }, - }); - - return { - customer, - }; - } catch (e) { - return false; - } -} diff --git a/services/services.cors.sh/clients/index.ts b/services/services.cors.sh/clients/index.ts deleted file mode 100644 index cde685c..0000000 --- a/services/services.cors.sh/clients/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./prisma"; -export * from "./stripe"; -export * from "./ses"; diff --git a/services/services.cors.sh/clients/prisma.ts b/services/services.cors.sh/clients/prisma.ts deleted file mode 100644 index 901f3a0..0000000 --- a/services/services.cors.sh/clients/prisma.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -export const prisma = new PrismaClient(); diff --git a/services/services.cors.sh/clients/ses.ts b/services/services.cors.sh/clients/ses.ts deleted file mode 100644 index 97392ce..0000000 --- a/services/services.cors.sh/clients/ses.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as AWS from "@aws-sdk/client-ses"; - -const SENDER_EMAIL = "no-reply@cors.sh"; -const ses = new AWS.SES({}); - -interface EmailBody_Raw { - subject: string; - text: string; -} - -interface EmailBody_Html { - subject: string; - html: string; -} - -type EmailContent = EmailBody_Raw | EmailBody_Html; - -export function emailWithTemplate(to: string, template: string, data: object) { - return ses.sendTemplatedEmail({ - Destination: { - ToAddresses: [to], - }, - Source: SENDER_EMAIL, - Template: template, - TemplateData: JSON.stringify(data), - }); -} - -export async function email( - to: string, - content: EmailContent -): Promise { - try { - const sendResp = await ses.sendEmail({ - Destination: { - ToAddresses: [to], - }, - Source: SENDER_EMAIL, - Message: { - Subject: { - Data: content.subject, - }, - Body: - "text" in content - ? { - Text: { - Data: content.text, - }, - } - : { - Html: { - Data: content.html, - }, - }, - }, - }); - } catch (error) { - console.error(error); - throw new Error("failed while sending email"); - } - return true; -} diff --git a/services/services.cors.sh/clients/stripe.ts b/services/services.cors.sh/clients/stripe.ts deleted file mode 100644 index b311c26..0000000 --- a/services/services.cors.sh/clients/stripe.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Stripe } from "stripe"; - -export const stripe = new Stripe(process.env.STRIPE_API_KEY, { - apiVersion: "2022-08-01", -}); diff --git a/services/services.cors.sh/controllers/applications.ts b/services/services.cors.sh/controllers/applications.ts deleted file mode 100644 index 1eb062f..0000000 --- a/services/services.cors.sh/controllers/applications.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { prisma, stripe, emailWithTemplate } from "../clients"; -import { sign_live_key, sign_temporary_key, sign_test_key } from "../keygen"; -import { nanoid } from "nanoid"; -import type { Application, OnboardingApplications } from "@prisma/client"; -import sync from "../sync"; -import { logNewOnboardingProc, logNewApplication } from "./_telemetry"; - -type CreateOnboardingApplicationBody = - | { - type: "with-form"; - name: string; - allowedOrigins: string[]; - priceId: string; - } - | { - type: "with-email"; - email: string; - }; - -export async function createOnboardingApplication( - body: CreateOnboardingApplicationBody, - send_onboarding_email_if_possible: boolean = true -) { - let email_available = false; - let email: string; - let name: string; - let allowedOrigins: string[]; - let priceId: string; - - switch (body.type) { - case "with-email": { - email = body.email; - name = "My first cors.sh app"; - email_available = true; - break; - } - case "with-form": { - email = `${nanoid(10)}@unknown-users.cors.sh`; - name = body.name; - allowedOrigins = body.allowedOrigins; - priceId = body.priceId; - break; - } - } - - const { key: tmpkey, expires_at } = sign_temporary_key(); - - let data: OnboardingApplications; - - // check if email exists - let duplicated: OnboardingApplications | null = null; - if (email_available) { - duplicated = await prisma.onboardingApplications.findUnique({ - where: { email: email }, - }); - } - - // if duplicated, update the existing one with the new key. - if (duplicated) { - // if the last interaction is within 5 minutes, ignore the request - if (duplicated.updatedAt) { - } - data = await prisma.onboardingApplications.update({ - where: { id: duplicated.id }, - data: { - // this will be renewed since the signature contains the expiration time - key: tmpkey, - }, - }); - } else { - data = await prisma.onboardingApplications.create({ - data: { - key: tmpkey, - email: email, - name: name, - allowedOrigins: allowedOrigins ?? [], - expiresAt: expires_at.toDate(), - priceId, - }, - }); - } - - if (email_available && send_onboarding_email_if_possible) { - // send an email to the user - const res = await sendOnboardingEmail(email, data); - console.log("email sent", res); - } - - // log event to slack - try { - !duplicated && (await logNewOnboardingProc(data)); - } catch (e) { - console.error("failed to log new onboarding application", e); // not critical - } - - return { - id: data.id, - // omit the key since it also works as a verification code for faster signup - // key: "omitted" - email: data.email, - name: data.name, - allowedOrigins: data.allowedOrigins, - priceId: data.priceId, - }; -} - -export async function getOnboardingApplication(id: string) { - return await prisma.onboardingApplications.findUnique({ - where: { id: id }, - select: { - // omit private data - id: true, - name: true, - email: true, - allowedOrigins: true, - priceId: true, - createdAt: true, - updatedAt: true, - }, - }); -} - -async function sendOnboardingEmail( - email: string, - application?: OnboardingApplications -) { - if (!application) { - application = await prisma.onboardingApplications.findUnique({ - where: { email: email }, - }); - } - - if (!application) { - return false; - } - - const { key, emailSentAt } = application; - - // if the last interaction is within 1 minutes, ignore the request - if (emailSentAt && emailSentAt.length > 0) { - const lastSentAt = emailSentAt[emailSentAt.length - 1]; - if (lastSentAt) { - const diff = new Date().getTime() - lastSentAt.getTime(); - if (diff < 60000) { - return false; - } - } - } - - // sls stage - - await emailWithTemplate( - email, - `mail_cors_sh_onboarding_${process.env.STAGE}`, - { - CODE: key, - ONBOARDINGLINK: `https://cors.sh/onboarding/${application.id}`, - } - ); - - // update the tmp app - await prisma.onboardingApplications.update({ - where: { id: application.id }, - data: { - emailSentAt: { - push: new Date(), - }, - }, - }); - - return true; -} - -export async function signApplication(application: Application) { - // - const { key: apikey_test } = sign_test_key(application.signature_test); - const { key: apikey_live } = sign_live_key(application.signature_live); - - const payload = { - ...application, - apikey_test, - apikey_live, - }; - - return payload; -} - -export async function createApplication({ - id, - name, - allowedOrigins, - owner, -}: { - id?: string; - name: string; - allowedOrigins?: string[]; - owner: { id: string }; -}) { - const placeholder_test = nanoid(10); - const placeholder_live = nanoid(10); - - const application = await prisma.application.create({ - data: { - id: id, - name: name, - signature_test: placeholder_test, - signature_live: placeholder_live, - allowedOrigins: allowedOrigins ?? [], - owner: { - connect: { - id: owner.id, - }, - }, - }, - }); - - const salt_test = nanoid(10); - const salt_live = nanoid(10); - const signature_test = application.id + salt_test; - const signature_live = application.id + salt_live; - - const updated = await prisma.application.update({ - where: { id: application.id }, - data: { - signature_test, - signature_live, - }, - }); - - // once application is created and initially signed, sync to the keys table - await sync(updated); - - return updated; -} - -export async function convertApplication({ - onboarding_id, - checkout_session_id, -}: { - onboarding_id: string; - checkout_session_id: string; -}) { - const checkout_session = await stripe.checkout.sessions.retrieve( - checkout_session_id as string - ); - - const { customer: stripe_customer } = checkout_session; - const stripe_customer_id = - typeof stripe_customer === "string" ? stripe_customer : stripe_customer.id; - - const customer = await prisma.customer.findUnique({ - where: { stripeId: stripe_customer_id }, - }); - - // place this right before application create since its a delete and cannot be undone. (reduce chance of error when it fails) - const tmp = await prisma.onboardingApplications.delete({ - where: { id: onboarding_id as string }, - }); - - const application = await createApplication({ - id: tmp.id, - name: tmp.name || "Untitled", - allowedOrigins: tmp.allowedOrigins, - owner: { id: customer.id }, - }); - - const signed = await signApplication(application); - - // once application is created and initially signed, sync to the keys table - await sync(application); - - // send email to the user - try { - await emailWithTemplate( - customer.email, - `mail_cors_sh_onboarding_with_payment_success_${process.env.STAGE}`, - { - APPLICATIONNAME: tmp.name, - CODE_LIVE: signed.apikey_live, - CODE_TEST: signed.apikey_test, - } - ); - console.log("email sent", true); - // // set email verified to true? - } catch (e) { - console.error("email failed", e); - } - - // log event to slack - try { - await logNewApplication(signed); - } catch (e) { - console.error("failed to log new application", e); // not critical - } - - return application; -} diff --git a/services/services.cors.sh/index.ts b/services/services.cors.sh/index.ts deleted file mode 100644 index 77ad1f5..0000000 --- a/services/services.cors.sh/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { configure as serverlessExpress } from "@vendia/serverless-express"; -import { APIGatewayProxyHandler } from "aws-lambda"; - -import { app } from "./app"; - -export const handler: APIGatewayProxyHandler = serverlessExpress({ app }); diff --git a/services/services.cors.sh/routes/applications/index.ts b/services/services.cors.sh/routes/applications/index.ts deleted file mode 100644 index 4966666..0000000 --- a/services/services.cors.sh/routes/applications/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Application } from "@prisma/client"; -import * as express from "express"; -import { prisma } from "../../clients"; -import { - createApplication, - signApplication, -} from "../../controllers/applications"; - -const router = express.Router(); - -// list all my applications -router.get("/", async (req, res) => { - const applications = await prisma.application.findMany({ - where: { - ownerId: res.locals.customer.id, - }, - }); - - res.json(applications); -}); - -// get a single application -router.get("/:id", async (req, res) => { - console.info("fething application securely", { - id: req.params.id, - customer: res.locals.customer, - }); - const id = req.params.id; - const application = await prisma.application.findUnique({ - where: { - id: id, - }, - }); - - console.info("fetched application", application); - - if (!application) { - return res.status(404).json({ error: "application not found" }); - } - - if (application.ownerId !== res.locals.customer.id) { - return res.status(403).json({ error: "application not found" }); - } - - const signed = await signApplication(application); - - res.json(msak(signed)); -}); - -// create a new application -router.post("/", async (req, res) => { - // - const { name } = req.body; - - const app = await createApplication({ - name, - owner: res.locals.customer, - }); - - const signed = await signApplication(app); - - res.json(msak(signed)); -}); - -router.put("/:id", async (req, res) => { - const id = req.params.id; - await prisma.application.update({ - where: { - id: id, - }, - data: { - ...req.body, - }, - }); - - res.json({ success: true }); // or.. updated body? -}); - -function msak( - signed: Application & { - apikey_test: string; - apikey_live: string; - } -) { - return { - id: signed.id, - name: signed.name, - allowedOrigins: signed.allowedOrigins, - allowedTargets: signed.allowedTargets, - // available once - apikey_test: signed.apikey_test, - apikey_live: signed.apikey_live, - }; -} - -export default router; diff --git a/services/services.cors.sh/routes/auth/index.ts b/services/services.cors.sh/routes/auth/index.ts deleted file mode 100644 index 83f4f61..0000000 --- a/services/services.cors.sh/routes/auth/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as express from "express"; -import Axios from "axios"; -import { prisma } from "../../clients"; -import { encode_jwt, SECURE_BROWSER_COOKIE_AUTH_KEY } from "../../auth"; - -const router = express.Router(); - -const authclient = Axios.create({ - baseURL: "https://accounts.services.grida.co", -}); - -// user signin with grida, retrieve oauth token from grida, sends it here, -// this service will check the token, if valid, it will generate a new token for the user, -// and send it back to the client with secure, http only cookie. -router.post("signin", async (req, res) => { - const authorization = req.headers["proxy-authorization"]; - if (!authorization) { - res.status(401).json({ error: "no authorization header" }); - return; - } - - // authenticate via accounts.grida.co - // request auth server for authentication. - const { data } = await authclient.get("/verify", { - headers: { - // proxy the header, in form of "Bearer " - authorization, - }, - }); - - const customer = await prisma.customer.findUnique({ - where: { - // workspaceId: data.id, - }, - }); - - // sign customer (user) signature - const jwt = encode_jwt(customer.id); - - // set secure cookie when authorized. - res - .cookie(SECURE_BROWSER_COOKIE_AUTH_KEY, jwt, { - signed: true, - domain: ".cors.sh", - secure: true, - httpOnly: true, - sameSite: "strict", - // no expiration. it is a secure cookie, that only has access to cors.sh. let's keep it this way for now. - // expires: null - }) - .json({ - success: true, - customer: customer, - }); -}); - -export default router; diff --git a/services/services.cors.sh/routes/index.ts b/services/services.cors.sh/routes/index.ts deleted file mode 100644 index e0a96ee..0000000 --- a/services/services.cors.sh/routes/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as express from "express"; -import router_payments from "./payments"; -import router_stripe_webhooks from "./webhooks-stripe"; -import router_applications from "./applications"; -import router_onboarding from "./onboarding"; -import router_auth from "./auth"; -import cors from "cors"; -import { authMiddleware } from "../auth"; - -const router = express.Router(); - -const cors_website_only = cors({ - origin: process.env.NODE_ENV === "production" ? "https://cors.sh" : "*", -}); - -// router.use("/", router_posts); -router.use("/auth", cors_website_only, router_auth); -router.use("/payments", router_payments); -router.use("/webhooks/stripe", router_stripe_webhooks); -router.use( - "/applications", - cors_website_only, - authMiddleware, - router_applications -); -router.use("/onboarding", cors_website_only, router_onboarding); - -export default router; diff --git a/services/services.cors.sh/routes/onboarding/index.ts b/services/services.cors.sh/routes/onboarding/index.ts deleted file mode 100644 index 4d3638e..0000000 --- a/services/services.cors.sh/routes/onboarding/index.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as express from "express"; -import { - getOnboardingApplication, - createOnboardingApplication, - convertApplication, -} from "../../controllers/applications"; - -const router = express.Router(); - -// create -router.post("/with-email", async (req, res) => { - // create new temporary application bind to the email (form is optional) - - const { email } = req.body; - - // @requires: email - if (!email) { - return res.status(400).json({ error: "email is required" }); - } - - const d = await createOnboardingApplication({ - type: "with-email", - email, - }); - - res.status(201).json(d); -}); - -router.post("/with-form", async (req, res) => { - // create new temporary application bind to the form (email is optional) - - const { name, allowedOrigins, priceId } = req.body; - - const d = await createOnboardingApplication({ - type: "with-form", - name, - allowedOrigins, - priceId, - }); - - res.status(201).json(d); -}); - -router.get("/:id", async (req, res) => { - // this route does not have a guard by design. - // get onboarding application (only public data) - const { id } = req.params; - - const d = await getOnboardingApplication(id); - - if (!d) { - return res.status(404).json({ error: "application not found" }); - } - - res.status(200).json(d); -}); - -// conversion -router.post("/:id/convert", async (req, res) => { - const { id: onboarding_id } = req.params; - const { checkout_session_id } = req.body; - - const application = await convertApplication({ - onboarding_id, - checkout_session_id, - }); - - res.status(201).json(application); -}); - -export default router; diff --git a/services/services.cors.sh/routes/payments/index.ts b/services/services.cors.sh/routes/payments/index.ts deleted file mode 100644 index 251f5e5..0000000 --- a/services/services.cors.sh/routes/payments/index.ts +++ /dev/null @@ -1,157 +0,0 @@ -import type { Customer } from "@prisma/client"; -import * as express from "express"; -import { prisma, stripe } from "../../clients"; -import { getOnboardingApplication } from "../../controllers/applications"; - -const router = express.Router(); - -const WEBHOST = process.env.WEBHOST; -const WEBURL_CONSOLE = WEBHOST + "/console"; -const PROTOCOL = process.env.NODE_ENV === "production" ? "https" : "http"; -// e.g. -// http://localhost:4021/payments/checkout/new?price=price_1Lda7UAvR3geCh5rVaajCSw6&onboarding_id=63b9a40c02478a88364d7202 -router.get("/checkout/new", async (req, res) => { - const host = req.headers.host; - - const { onboarding_id: _q_onboarding } = req.query; - - const onboarding = await getOnboardingApplication(_q_onboarding as string); - - if (!onboarding) { - return res.status(400).json({ error: "invalid session" }); - } - - const { priceId } = onboarding; - - const price = await stripe.prices.retrieve(priceId, { - expand: ["product"], - }); - - const extra_params = new URLSearchParams({ - onboarding_id: _q_onboarding as string, - }); - - const session = await stripe.checkout.sessions.create({ - billing_address_collection: "auto", - line_items: [ - { - price: price.id, - // For metered billing, do not pass quantity - quantity: 1, - }, - ], - mode: "subscription", - // e.g. http://localhost:8823/?success=true&session_id=cs_test_a1qQdhxwfS5kKZJ1kToxKqAr2K6yHneucfi65lIs1OPVkmoH14YNAev76S - success_url: `${PROTOCOL}://${host}/payments/success?session_id={CHECKOUT_SESSION_ID}&${extra_params}`, - cancel_url: `${PROTOCOL}://${host}/payments/canceled?session_id={CHECKOUT_SESSION_ID}&${extra_params}`, - }); - - res.redirect(303, session.url); -}); - -router.get("/success", async (req, res) => { - const { session_id, onboarding_id } = req.query; - - const checkout_session = await stripe.checkout.sessions.retrieve( - session_id as string - ); - - const { - customer: stripe_customer_id, - customer_email, // can be null if created on checkout page (unless explicitly specified by our side.) - customer_details, - subscription, - } = checkout_session; - - // on success, convert onboarding app to a real app (and remove the temporary app) - // (if user has one.) - - // remove - const tmp = await prisma.onboardingApplications.findUnique({ - where: { id: onboarding_id as string }, - }); - - // if onboarding's email is placeholded. get email from checkout via stripe - const email = tmp.email.endsWith("@unknown-users.cors.sh") - ? customer_email ?? customer_details.email - : tmp.email; - - // create customer - // TODO: what if already exists? - - let customer_exists_with_same_email: Customer; - try { - customer_exists_with_same_email = await prisma.customer.findUnique({ - where: { email }, - }); - } catch (e) { - console.error("Caught exeption while finding existing customer", e); - } - - if (customer_exists_with_same_email) { - // TODO: we'll need a better way to handle this since we need to test this with same email multiple times. - // we can't tell if the purchase is for the same user or not. - // yet, if the existing one is verified, we should protect it. - // if not, we should give the new one a chance. - const params = new URLSearchParams({ - error: "identity_conflict", - message: - "Your payment was successful, but we detected a suspicious activity. Please contact customer support.", - session_id: session_id as string, - onboarding_id: tmp.id, - application_id: tmp.id, - }); - const redirect_uri = `${WEBHOST}/onboarding/payment-success-with-issue?${params.toString()}`; - res.redirect(303, redirect_uri); - } else { - const customer = await prisma.customer.create({ - data: { - stripeId: stripe_customer_id as string, - email: email, - emailVerified: false, - }, - }); - - const _params = { - session_id: session_id as string, - onboarding_id: tmp?.id, - customer_id: customer.id, - application_id: tmp.id, - }; - // prettier-ignore - Object.keys(_params).forEach((key) => _params[key] === undefined ? delete _params[key] : {}); - - const params = new URLSearchParams(_params); - - const redirect_uri = `${WEBHOST}/onboarding/payment-success?${params.toString()}`; - - res.redirect(303, redirect_uri); - } -}); - -router.get("/canceled", async (req, res) => { - // remove the temporary app - const { session_id, onboarding_id } = req.query; - - res.redirect(303, `https://cors.sh/`); -}); - -router.post("/portal-session", async (req, res) => { - // For demonstration purposes, we're using the Checkout session to retrieve the customer ID. - // Typically this is stored alongside the authenticated user in your database. - const { session_id } = req.body; - const checkoutSession = await stripe.checkout.sessions.retrieve(session_id); - - // This is the url to which the customer will be redirected when they are done - // managing their billing with the portal. - const returnUrl = WEBURL_CONSOLE; - - const portalSession = await stripe.billingPortal.sessions.create({ - customer: checkoutSession.customer as string, - return_url: returnUrl, - }); - - res.redirect(303, portalSession.url); -}); - -export default router; diff --git a/services/services.cors.sh/routes/payments/readme.md b/services/services.cors.sh/routes/payments/readme.md deleted file mode 100644 index 269e46d..0000000 --- a/services/services.cors.sh/routes/payments/readme.md +++ /dev/null @@ -1,27 +0,0 @@ -# Payments with stripe - -## About - -This subscirption checkout follows instruction from https://stripe.com/docs/billing/quickstart which uses the checkout api, webhooks and customer portal for subscription management. Most of the service relies on stripe's built in features. - -## Setting up webhook - -**Local testing (manual trigger)** - -[Install stripe cli](https://stripe.com/docs/stripe-cli) - -```bash -brew install stripe/stripe-cli/stripe -``` - -Follow the instructions at https://dashboard.stripe.com/webhooks/create?endpoint_location=local - -```bash -stripe login -stripe listen --forward-to localhost:4242/webhook -stripe trigger payment_intent.succeeded # or other event as you want -``` - -**Local testing (production testing)** - -Setup ngrok to proxy request & register webhook at https://dashboard.stripe.com/webhooks/create?endpoint_location=hosted diff --git a/services/services.cors.sh/routes/webhooks-stripe/index.ts b/services/services.cors.sh/routes/webhooks-stripe/index.ts deleted file mode 100644 index 244f3b7..0000000 --- a/services/services.cors.sh/routes/webhooks-stripe/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as express from "express"; -import { stripe } from "../../clients"; - -const router = express.Router(); - -router.post( - /** - * /webhooks/stripe - defined in routes/index.ts - */ - "/", - express.raw({ type: "application/json" }), - (request, response) => { - let event = request.body; - // Replace this endpoint secret with your endpoint's unique secret - // If you are testing with the CLI, find the secret by running 'stripe listen' - // If you are using an endpoint defined with the API or dashboard, look in your webhook settings - // at https://dashboard.stripe.com/webhooks - const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; - // Only verify the event if you have an endpoint secret defined. - // Otherwise use the basic event deserialized with JSON.parse - if (endpointSecret) { - // Get the signature sent by Stripe - const signature = request.headers["stripe-signature"]; - try { - event = stripe.webhooks.constructEvent( - request.body, - signature, - endpointSecret - ); - } catch (err) { - console.log(`⚠️ Webhook signature verification failed.`, err.message); - return response.sendStatus(400); - } - } - let subscription; - let status; - // Handle the event - switch (event.type) { - case "customer.subscription.trial_will_end": - subscription = event.data.object; - status = subscription.status; - console.log(`Subscription status is ${status}.`); - // Then define and call a method to handle the subscription trial ending. - // handleSubscriptionTrialEnding(subscription); - break; - case "customer.subscription.deleted": - subscription = event.data.object; - status = subscription.status; - console.log(`Subscription status is ${status}.`); - // Then define and call a method to handle the subscription deleted. - // handleSubscriptionDeleted(subscriptionDeleted); - break; - case "customer.subscription.created": - subscription = event.data.object; - status = subscription.status; - console.log(`Subscription status is ${status}.`); - // Then define and call a method to handle the subscription created. - // handleSubscriptionCreated(subscription); - break; - case "customer.subscription.updated": - subscription = event.data.object; - status = subscription.status; - console.log(`Subscription status is ${status}.`); - // Then define and call a method to handle the subscription update. - // handleSubscriptionUpdated(subscription); - break; - default: - // Unexpected event type - console.log(`Unhandled event type ${event.type}.`); - } - // Return a 200 response to acknowledge receipt of the event - response.send(); - } -); - -export default router; diff --git a/services/services.cors.sh/ses-email-templates/index.js b/services/services.cors.sh/ses-email-templates/index.js index d291001..b7eeeb3 100644 --- a/services/services.cors.sh/ses-email-templates/index.js +++ b/services/services.cors.sh/ses-email-templates/index.js @@ -1,7 +1,7 @@ const fs = require("fs"); const path = require("path"); -const dir = path.join(__dirname, "../../mail.cors.sh", "render"); +const dir = path.join(__dirname, "../../../.archives/mail.cors.sh", "render"); const templates = fs .readdirSync(dir) // list files ending with .template.html diff --git a/services/services.cors.sh/sync/index.ts b/services/services.cors.sh/sync/index.ts deleted file mode 100644 index 66912cf..0000000 --- a/services/services.cors.sh/sync/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -import AWS from "aws-sdk"; -import * as keygen from "../keygen"; -import type { KeyInfo } from "./type"; -import type { Application } from "@prisma/client"; -import day from "dayjs"; - -const db = new AWS.DynamoDB.DocumentClient(); - -export default async function sync(application: Application) { - const { id, signature_live, signature_test, allowedOrigins, allowedTargets } = - application; - - // TODO: we are using application.id as the billing group, but we should - // use the subscription id instead (in the future) - const billing_group = id; - - const data = { - // TODO: get plan data - // for now, fixing it as "2023.t1", which is the pro plan - plan: "2023.t1", - allowedOrigins, - allowedTargets, - }; - - // TODO: get subscription data. to calculate expires_at - // for now, we are givving all keys a 3 year expiry - const expires_at = day().add(3, "year").unix(); - - // test - sync_record(signature_test, "test", billing_group, expires_at, data); - - // live - sync_record(signature_live, "live", billing_group, expires_at, data); -} - -function sync_record( - signature: string, - type: "live" | "test", - billing_group: string, - expires_at: number, - data: { - plan: string; - allowedOrigins: string[]; - allowedTargets: string[]; - } -) { - const record: KeyInfo = { - key: keygen.sign(signature, type).token, - plan: data.plan, - config: { - allowed_origins: data.allowedOrigins, - allowed_targets: data.allowedTargets, - }, - active: true, - billing_group, - expires_at, - synced_at: day().unix(), - }; - - // write to db - return db - .put({ - TableName: process.env.DYNAMODB_TABLE_SERVICE_KEYS!, - Item: record, - }) - .promise(); -} - -export async function activate(id: string, active: boolean) { - // update "active" field of the key - // write to db - - return db.update({ - TableName: process.env.DYNAMODB_TABLE_SERVICE_KEYS!, - Key: { - id, - }, - UpdateExpression: "set active = :active", - ExpressionAttributeValues: { - ":active": active, - }, - }); -} diff --git a/services/services.cors.sh/sync/type.ts b/services/services.cors.sh/sync/type.ts deleted file mode 100644 index 12e1b89..0000000 --- a/services/services.cors.sh/sync/type.ts +++ /dev/null @@ -1,13 +0,0 @@ -// shared db -export interface KeyInfo { - key: string; - plan: string; - config: { - allowed_origins: string[]; - allowed_targets: string[]; - }; - active: boolean; - billing_group: string; - expires_at: number; - synced_at: number; -} diff --git a/services/services.cors.sh/test/config.env.test b/services/services.cors.sh/test/config.env.test deleted file mode 100644 index 769341c..0000000 --- a/services/services.cors.sh/test/config.env.test +++ /dev/null @@ -1 +0,0 @@ -API_KEY_TEMP_OTP_SECRET="test" \ No newline at end of file diff --git a/services/services.cors.sh/test/setup-tests.ts b/services/services.cors.sh/test/setup-tests.ts deleted file mode 100644 index ec8363b..0000000 --- a/services/services.cors.sh/test/setup-tests.ts +++ /dev/null @@ -1,3 +0,0 @@ -import dotenv from "dotenv"; - -dotenv.config({ path: "./config.env.test" }); diff --git a/supabase/.gitignore b/supabase/.gitignore new file mode 100644 index 0000000..a3ad880 --- /dev/null +++ b/supabase/.gitignore @@ -0,0 +1,4 @@ +# Supabase +.branches +.temp +.env diff --git a/supabase/config.toml b/supabase/config.toml new file mode 100644 index 0000000..026e852 --- /dev/null +++ b/supabase/config.toml @@ -0,0 +1,141 @@ +# A string used to distinguish different Supabase projects on the same host. Defaults to the +# working directory name when running `supabase init`. +project_id = "cors.sh" + +[api] +enabled = true +# Port to use for the API URL. +port = 54321 +# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API +# endpoints. public and storage are always included. +schemas = ["public", "storage", "graphql_public"] +# Extra schemas to add to the search_path of every request. public is always included. +extra_search_path = ["public", "extensions"] +# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size +# for accidental or malicious requests. +max_rows = 1000 + +[db] +# Port to use for the local database URL. +port = 54322 +# Port used by db diff command to initialize the shadow database. +shadow_port = 54320 +# The database major version to use. This has to be the same as your remote database's. Run `SHOW +# server_version;` on the remote database to check. +major_version = 15 + +[db.pooler] +enabled = false +# Port to use for the local connection pooler. +port = 54329 +# Specifies when a server connection can be reused by other clients. +# Configure one of the supported pooler modes: `transaction`, `session`. +pool_mode = "transaction" +# How many server connections to allow per user/database pair. +default_pool_size = 20 +# Maximum number of client connections allowed. +max_client_conn = 100 + +[realtime] +enabled = true +# Bind realtime via either IPv4 or IPv6. (default: IPv6) +# ip_version = "IPv6" + +[studio] +enabled = true +# Port to use for Supabase Studio. +port = 54323 +# External URL of the API server that frontend connects to. +api_url = "http://127.0.0.1" + +# Email testing server. Emails sent with the local dev setup are not actually sent - rather, they +# are monitored, and you can view the emails that would have been sent from the web interface. +[inbucket] +enabled = true +# Port to use for the email testing server web interface. +port = 54324 +# Uncomment to expose additional ports for testing user applications that send emails. +# smtp_port = 54325 +# pop3_port = 54326 + +[storage] +enabled = true +# The maximum file size allowed (e.g. "5MB", "500KB"). +file_size_limit = "50MiB" + +[auth] +enabled = true +# The base URL of your website. Used as an allow-list for redirects and for constructing URLs used +# in emails. +site_url = "http://127.0.0.1:3000" +# A list of *exact* URLs that auth providers are permitted to redirect to post authentication. +additional_redirect_urls = ["https://127.0.0.1:3000"] +# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week). +jwt_expiry = 3600 +# If disabled, the refresh token will never expire. +enable_refresh_token_rotation = true +# Allows refresh tokens to be reused after expiry, up to the specified interval in seconds. +# Requires enable_refresh_token_rotation = true. +refresh_token_reuse_interval = 10 +# Allow/disallow new user signups to your project. +enable_signup = true + +[auth.email] +# Allow/disallow new user signups via email to your project. +enable_signup = true +# If enabled, a user will be required to confirm any email change on both the old, and new email +# addresses. If disabled, only the new email is required to confirm. +double_confirm_changes = true +# If enabled, users need to confirm their email address before signing in. +enable_confirmations = false + +# Uncomment to customize email template +# [auth.email.template.invite] +# subject = "You have been invited" +# content_path = "./supabase/templates/invite.html" + +[auth.sms] +# Allow/disallow new user signups via SMS to your project. +enable_signup = true +# If enabled, users need to confirm their phone number before signing in. +enable_confirmations = false +# Template for sending OTP to users +template = "Your code is {{ .Code }} ." + +# Use pre-defined map of phone number to OTP for testing. +[auth.sms.test_otp] +# 4152127777 = "123456" + +# Configure one of the supported SMS providers: `twilio`, `twilio_verify`, `messagebird`, `textlocal`, `vonage`. +[auth.sms.twilio] +enabled = false +account_sid = "" +message_service_sid = "" +# DO NOT commit your Twilio auth token to git. Use environment variable substitution instead: +auth_token = "env(SUPABASE_AUTH_SMS_TWILIO_AUTH_TOKEN)" + +# Use an external OAuth provider. The full list of providers are: `apple`, `azure`, `bitbucket`, +# `discord`, `facebook`, `github`, `gitlab`, `google`, `keycloak`, `linkedin`, `notion`, `twitch`, +# `twitter`, `slack`, `spotify`, `workos`, `zoom`. +[auth.external.apple] +enabled = false +client_id = "" +# DO NOT commit your OAuth provider secret to git. Use environment variable substitution instead: +secret = "env(SUPABASE_AUTH_EXTERNAL_APPLE_SECRET)" +# Overrides the default auth redirectUrl. +redirect_uri = "" +# Overrides the default auth provider URL. Used to support self-hosted gitlab, single-tenant Azure, +# or any other third-party OIDC providers. +url = "" + +[analytics] +enabled = false +port = 54327 +vector_port = 54328 +# Configure one of the supported backends: `postgres`, `bigquery`. +backend = "postgres" + +# Experimental features may be deprecated any time +[experimental] +# Configures Postgres storage engine to use OrioleDB (S3) +orioledb_version = "" diff --git a/supabase/functions/.vscode/extensions.json b/supabase/functions/.vscode/extensions.json new file mode 100644 index 0000000..74baffc --- /dev/null +++ b/supabase/functions/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["denoland.vscode-deno"] +} diff --git a/supabase/functions/.vscode/settings.json b/supabase/functions/.vscode/settings.json new file mode 100644 index 0000000..6f4f84f --- /dev/null +++ b/supabase/functions/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "deno.enable": true, + "deno.lint": true, + "editor.defaultFormatter": "denoland.vscode-deno" +} diff --git a/supabase/functions/log-slack/index.ts b/supabase/functions/log-slack/index.ts new file mode 100644 index 0000000..31f439e --- /dev/null +++ b/supabase/functions/log-slack/index.ts @@ -0,0 +1,29 @@ +// Follow this setup guide to integrate the Deno language server with your editor: +// https://deno.land/manual/getting_started/setup_your_environment +// This enables autocomplete, go to definition, etc. + +console.log("Hello from Functions!") + +Deno.serve(async (req) => { + const { name } = await req.json() + const data = { + message: `Hello ${name}!`, + } + + return new Response( + JSON.stringify(data), + { headers: { "Content-Type": "application/json" } }, + ) +}) + +/* To invoke locally: + + 1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start) + 2. Make an HTTP request: + + curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/log-slack' \ + --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \ + --header 'Content-Type: application/json' \ + --data '{"name":"Functions"}' + +*/ diff --git a/supabase/migrations/20231207085024_init.sql b/supabase/migrations/20231207085024_init.sql new file mode 100644 index 0000000..e5bcd5a --- /dev/null +++ b/supabase/migrations/20231207085024_init.sql @@ -0,0 +1,40 @@ +CREATE TABLE customers ( + id uuid not null references auth.users on delete cascade, + email VARCHAR(255) UNIQUE, + email_verified BOOLEAN DEFAULT false NOT NULL, + stripe_id VARCHAR(255) UNIQUE NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + + primary key (id) +); + +alter table customers enable row level security; + +CREATE TABLE applications ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) DEFAULT 'Untitled', + allowed_origins TEXT[] DEFAULT ARRAY[]::TEXT[] NOT NULL, + allowed_targets TEXT[] DEFAULT ARRAY[]::TEXT[] NOT NULL, + owner_id INT NOT NULL, + archived_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, + expires_at TIMESTAMP, + signature_live VARCHAR(255) UNIQUE NOT NULL, + signature_test VARCHAR(255) UNIQUE NOT NULL, + FOREIGN KEY (owner_id) REFERENCES customers(id) +); + +alter table applications enable row level security; + +CREATE TABLE applications_onboarding ( + id SERIAL PRIMARY KEY, + email VARCHAR(255) UNIQUE, + name VARCHAR(255), + allowed_origins TEXT[] DEFAULT ARRAY[]::TEXT[], + price_id VARCHAR(255), + key VARCHAR(255) UNIQUE, + email_sent_at TIMESTAMP[] DEFAULT ARRAY[]::TIMESTAMP[], + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + expires_at TIMESTAMP NOT NULL +); diff --git a/supabase/seed.sql b/supabase/seed.sql new file mode 100644 index 0000000..e69de29 diff --git a/vscode.code-workspace b/vscode.code-workspace new file mode 100644 index 0000000..a9ad457 --- /dev/null +++ b/vscode.code-workspace @@ -0,0 +1,17 @@ +{ + "folders": [ + { + "name": "project-root", + "path": "./" + }, + { + "name": "supabase-functions", + "path": "supabase/functions" + } + ], + "settings": { + "files.exclude": { + "supabase/functions/": true + } + } +} diff --git a/web/app/(auth)/auth/callback/route.ts b/web/app/(auth)/auth/callback/route.ts new file mode 100644 index 0000000..6eec7e9 --- /dev/null +++ b/web/app/(auth)/auth/callback/route.ts @@ -0,0 +1,56 @@ +import { createServerClient, type CookieOptions } from "@supabase/ssr"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; +import { redirect_uri } from "@/lib/q"; +import type { NextRequest } from "next/server"; + +export async function GET(request: NextRequest) { + const host = request.nextUrl.origin; + const cookieStore = cookies(); + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value; + }, + set(name: string, value: string, options: CookieOptions) { + cookieStore.set({ name, value, ...options }); + }, + remove(name: string, options: CookieOptions) { + cookieStore.set({ name, value: "", ...options }); + }, + }, + } + ); + + const code = request.nextUrl.searchParams.get("code"); + + if (code) { + await supabase.auth.exchangeCodeForSession(code); + } else { + return NextResponse.redirect(host + "/signin"); + } + + const { data } = await supabase.auth.getUser(); + + const _redirect_uri = redirect_uri.parse(request.nextUrl.searchParams); + + if (_redirect_uri) { + return NextResponse.redirect( + redirect_uri.abs({ + host, + redirect_uri: _redirect_uri, + }) + ); + } + + if (data.user!.app_metadata['customer_id']) { + return NextResponse.redirect(host + "/console"); + } + + // URL to redirect to after sign in process completes + return NextResponse.redirect(host + "/"); +} diff --git a/web/app/(auth)/layout.tsx b/web/app/(auth)/layout.tsx new file mode 100644 index 0000000..7eb17c9 --- /dev/null +++ b/web/app/(auth)/layout.tsx @@ -0,0 +1,43 @@ +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import { Toaster } from "react-hot-toast"; +import GoogleAnalytics from '@/components/ga'; +import ChatwootWidget from "@/components/chatwoot"; +import '../globals.console.css' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata: Metadata = { + title: 'CORS.SH - A Fast & Reliable CORS Proxy for your websites', + description: "One CORS Proxy you'll ever need", + metadataBase: new URL('https://cors.sh'), + openGraph: { + images: [ + "/og-image-01.jpg", + ] + } +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + {process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS ? ( + + ) : null} + +
+
+ +
+ {children} +
+ + + ) +} diff --git a/web/app/(auth)/signin/page.tsx b/web/app/(auth)/signin/page.tsx new file mode 100644 index 0000000..c0edd84 --- /dev/null +++ b/web/app/(auth)/signin/page.tsx @@ -0,0 +1,78 @@ +"use client"; + +import React from "react"; +import { createBrowserClient } from '@supabase/ssr' +import { useSearchParams } from "next/navigation"; +import { redirect_uri } from "@/lib/q"; +import useHost from "@/hooks/useHost"; +import Link from "next/link"; + +export default function SigninPage() { + const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) + + const host = useHost(); + const searchParams = useSearchParams(); + + const _redirect_uri = redirect_uri.parse(searchParams!); + + const redirect = redirect_uri.make(`${host}/auth/callback`, { + redirect_uri: _redirect_uri, + }); + + const onsigninwith_google = () => { + supabase.auth.signInWithOAuth({ + provider: "google", + options: { + redirectTo: redirect?.toString(), + }, + }); + }; + + const onsigninwith_github = () => { + + supabase.auth.signInWithOAuth({ + provider: 'github', + options: { + redirectTo: redirect?.toString(), + }, + }); + }; + + return ( +
+
+
+
+
+
+
+

Welcome back

+

+ Sign in to your account +

+
+
+ + +
+
+
+

By continuing, you agree to CORS.SH's Terms of Service and Privacy Policy, and to receive periodic emails with updates.

+
+
+ +
+
+
+
+ ); +} diff --git a/web/app/(auth)/signout/route.ts b/web/app/(auth)/signout/route.ts new file mode 100644 index 0000000..0142d82 --- /dev/null +++ b/web/app/(auth)/signout/route.ts @@ -0,0 +1,35 @@ +import { createServerClient, type CookieOptions } from "@supabase/ssr"; +import { cookies } from "next/headers"; +import { NextRequest, NextResponse } from "next/server"; + + +export async function GET(request: NextRequest) { + const requestUrl = new URL(request.url); + + const cookieStore = cookies(); + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value; + }, + set(name: string, value: string, options: CookieOptions) { + cookieStore.set({ name, value, ...options }); + }, + remove(name: string, options: CookieOptions) { + cookieStore.set({ name, value: "", ...options }); + }, + }, + } + ); + + await supabase.auth.signOut(); + await supabase.auth.refreshSession(); + + return NextResponse.redirect(`${requestUrl.origin}/signin`, { + status: 301, + });; +} diff --git a/web/app/(console)/console/[id]/page.tsx b/web/app/(console)/console/applications/[id]/page.tsx similarity index 63% rename from web/app/(console)/console/[id]/page.tsx rename to web/app/(console)/console/applications/[id]/page.tsx index 56c21c7..0b9f906 100644 --- a/web/app/(console)/console/[id]/page.tsx +++ b/web/app/(console)/console/applications/[id]/page.tsx @@ -4,10 +4,10 @@ import styled from "@emotion/styled"; import { Pencil1Icon } from "@radix-ui/react-icons"; import client, { ApplicationWithApiKey } from "@cors.sh/service-api"; import { FormPageLayout, PageCloseButton } from "@app/ui/layouts"; -import { Button, TextFormField } from "@editor-ui/console"; +import { TextFormField } from "@editor-ui/console"; import { Logo } from "@/components/logo"; -import { UnderlineButton } from "@app/ui/components"; import { ApiKeyReveal } from "@app/ui/components"; +import { Button, Form, FormFooter, FormHeader, FormRow } from "@/console"; export default function ApplicationDetailPage({ params }: { params: { @@ -24,40 +24,50 @@ export default function ApplicationDetailPage({ params }: { } return ( - - - -
- -
- +
+
+ + {application.name} + + + + + + - - + + + + + + + + + +
+
- - Archive application
- +
); } @@ -72,7 +82,7 @@ function EditableTitle({ initialValue = "" }: { initialValue?: string }) { ref.current?.focus(); ref.current?.setSelectionRange(0, text.length); } - }, [editing]); + }, [editing, text.length]); return ( @@ -95,7 +105,7 @@ function EditableTitle({ initialValue = "" }: { initialValue?: string }) { }} value={text} /> - + ); } diff --git a/web/app/(console)/console/new/page.tsx b/web/app/(console)/console/applications/new/page.tsx similarity index 52% rename from web/app/(console)/console/new/page.tsx rename to web/app/(console)/console/applications/new/page.tsx index 765f968..23e721a 100644 --- a/web/app/(console)/console/new/page.tsx +++ b/web/app/(console)/console/applications/new/page.tsx @@ -1,10 +1,10 @@ 'use client' import React, { useEffect } from "react"; -import { Button, TextFormField } from "@editor-ui/console"; +import { TextFormField } from "@editor-ui/console"; import client from "@cors.sh/service-api"; import { useRouter } from "next/navigation"; -import { FormPageLayout } from "@app/ui/layouts"; +import { Form, FormFooter, FormHeader, FormRow, Button } from "@/console"; export default function NewApplicationPage() { const router = useRouter(); @@ -47,9 +47,9 @@ export default function NewApplicationPage() { }, [name, allowedOrigins]); return ( - -

Create new application

-
+
+ + {/*
- -
- + + */} +
); } + +function CreateApplicationForm() { + return ( +
+ +

+ Create a new application +

+

+ Your project will have its own dedicated instance and full postgres database. +
+ An API will be set up so you can easily interact with your new database. +

+
+ + + + + + + + +
+

You can rename your project later

+ +
+
+
+ ) +} diff --git a/web/app/(console)/console/applications/page.tsx b/web/app/(console)/console/applications/page.tsx new file mode 100644 index 0000000..89b4451 --- /dev/null +++ b/web/app/(console)/console/applications/page.tsx @@ -0,0 +1,66 @@ +import React from "react"; +import Link from "next/link"; +import type { Metadata } from 'next' +import { ApplicationItem } from "@/components/console/application-item"; +import { Client } from "@cors.sh/service-api"; +import { Button, Form, FormHeader, FormRow } from "@/console"; + +export const metadata: Metadata = { + title: "Dashboard", +} + +export default async function AppsPage() { + // const client = new Client({}); + // const applications = await client.listApplications() + const applications: any[] = [] + + return ( +
+
+

+ Applications +

+ + + +
+
+ { + applications.length === 0 + ? + : ( +
+ {applications.map((application) => ( + + + + ))} +
+ ) + } + +
+
+ ); +} + +function Empty() { + return ( +
+ + You don't have any applications yet + + + + + + +
+ ) +} \ No newline at end of file diff --git a/web/app/(console)/console/general/page.tsx b/web/app/(console)/console/general/page.tsx new file mode 100644 index 0000000..6823199 --- /dev/null +++ b/web/app/(console)/console/general/page.tsx @@ -0,0 +1,5 @@ +export default function TeamPage() { + return
+ +
+} \ No newline at end of file diff --git a/web/app/(console)/console/invoices/page.tsx b/web/app/(console)/console/invoices/page.tsx new file mode 100644 index 0000000..f2ac796 --- /dev/null +++ b/web/app/(console)/console/invoices/page.tsx @@ -0,0 +1,5 @@ +export default function InvoicesPage() { + return
+ +
+} \ No newline at end of file diff --git a/web/app/(console)/console/page.tsx b/web/app/(console)/console/page.tsx index dd97bae..89ffd73 100644 --- a/web/app/(console)/console/page.tsx +++ b/web/app/(console)/console/page.tsx @@ -1,57 +1,114 @@ import React from "react"; import Link from "next/link"; import type { Metadata } from 'next' -import { ApplicationItem, ApplicationList } from "@/components/console/application-list"; -import { FormPageLayout } from "@app/ui/layouts"; -import { UnderlineButton } from "@app/ui/components"; - +import { ApplicationItem } from "@/components/console/application-item"; +import BarChart from "@/components/charts/bar-chart"; +import { Prism } from "@/components/prism"; +import { examples } from "@/k"; +import { ChartCard } from "@/components/charts/cart-card"; +import { Button, Card, Form, FormFooter, FormHeader, FormRow } from "@/console"; export const metadata: Metadata = { title: "Dashboard", } -export default function ConsoleIndex() { - const applications = [ - { - id: "1", - name: "My app", - }, - { - id: "2", - name: "My app 2", - }, - ] +const applications = [ + { + id: "1", + name: "My app", + }, + { + id: "2", + name: "My app 2", + }, +] + +export default function ConsoleHome() { return ( - <> - - {/* */} -
- - {applications.map((application) => ( - - ))} - -
+
+
+
+

+ Usage +

+
+ + + +
+
- - {/* */} - Create new application - {/* */} - - - {/* */} - Manage subscription - {/* */} - + {applications.map((application) => ( + + + + ))}
- - +
+
+
+ + QuickStarts + + + + {examples.fetch('https://example.com')} + + +
+
+
+ {quick_starts.map((d, i) => { + return + })} +
+
+ +
+ +
); } + +const quick_starts = [ + { + title: "Ticktok", + description: "Learn how to integrate Ticktok API with your application", + }, + { + title: "Shopify", + description: "Learn how to integrate Ticktok API with your application", + }, + { + title: "Your Server", + description: "Learn how to integrate CORS Proxy to your own server", + }, +] as const + +function QuickStartCard({ + icon, + title, + description, +}: { + icon?: React.ReactNode; + title: string; + description: string; +}) { + return ( + + ) +} diff --git a/web/app/(console)/console/settings/page.tsx b/web/app/(console)/console/settings/page.tsx new file mode 100644 index 0000000..bed313d --- /dev/null +++ b/web/app/(console)/console/settings/page.tsx @@ -0,0 +1,31 @@ +import { Button } from "@/console"; +import Link from "next/link"; + +export default function SettingsPage() { + return ( +
+
+

+ Settings +

+
+
+

+ Members +

+

+ Invite members to your organization. +

+
+
+ + + +
+
+ ) +} \ No newline at end of file diff --git a/web/app/(console)/console/team/page.tsx b/web/app/(console)/console/team/page.tsx new file mode 100644 index 0000000..a489d15 --- /dev/null +++ b/web/app/(console)/console/team/page.tsx @@ -0,0 +1,5 @@ +export default function GeneralSettingsPage() { + return
+ +
+} \ No newline at end of file diff --git a/web/app/(console)/console/usage/page.tsx b/web/app/(console)/console/usage/page.tsx new file mode 100644 index 0000000..ec303b6 --- /dev/null +++ b/web/app/(console)/console/usage/page.tsx @@ -0,0 +1,18 @@ +import BarChart from "@/components/charts/bar-chart" +import { ChartCard } from "@/components/charts/cart-card" +import React from "react" + +export default function UsagePage() { + return ( +
+
+

+ Usage +

+
+ + + +
+ ) +} \ No newline at end of file diff --git a/web/app/(console)/layout.tsx b/web/app/(console)/layout.tsx index 7985358..6445657 100644 --- a/web/app/(console)/layout.tsx +++ b/web/app/(console)/layout.tsx @@ -1,11 +1,14 @@ +import Image from 'next/image' import type { Metadata } from 'next' import { Inter } from 'next/font/google' import { Toaster } from "react-hot-toast"; -import '../globals.css' import GoogleAnalytics from '@/components/ga'; import ChatwootWidget from "@/components/chatwoot"; import { Heading, Link, Theme } from '@radix-ui/themes'; -import { GearIcon, GitHubLogoIcon, MagnifyingGlassIcon, OpenInNewWindowIcon } from '@radix-ui/react-icons'; +import { FileTextIcon, GearIcon, GitHubLogoIcon, HomeIcon, LayersIcon, LightningBoltIcon, MagnifyingGlassIcon, OpenInNewWindowIcon, QuestionMarkCircledIcon, RocketIcon } from '@radix-ui/react-icons'; +import '../globals.console.css' + + const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { @@ -35,19 +38,26 @@ export default function RootLayout({ {process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS} /> ) : null} -
-
- -
- -
- - - {children} - + + +
+
+
+
+ +
+ +
+ {children} +
+
+
+
- -
+
+
) @@ -55,22 +65,40 @@ export default function RootLayout({ function Sidebar() { - return
- - CORS.SH - + return
+
+ + CORS.SH + +
- + Dashboard - - - Apps + + + Applications + + + + Usage & Plans - + + + Docs + + + + FAQ + + - Events + Settings @@ -83,7 +111,7 @@ function Sidebar() { function NavItem({ children, ...props }: React.PropsWithChildren>) { return ( {children} @@ -92,9 +120,10 @@ function NavItem({ children, ...props }: React.PropsWithChildren) { - return
- {children} -
- +function TopBar() { + return ( +
+
CORS
+
+ ) } \ No newline at end of file diff --git a/web/app/(dev)/dev/emails/onboarding/page.tsx b/web/app/(dev)/dev/emails/onboarding/page.tsx new file mode 100644 index 0000000..127c056 --- /dev/null +++ b/web/app/(dev)/dev/emails/onboarding/page.tsx @@ -0,0 +1,5 @@ +import { OnboardingEmailTemplate } from "@/components/emails/onboarding"; + +export default function OnboardingEmailDevPage() { + return +} \ No newline at end of file diff --git a/web/app/(dev)/dev/emails/page.tsx b/web/app/(dev)/dev/emails/page.tsx new file mode 100644 index 0000000..c2ca50f --- /dev/null +++ b/web/app/(dev)/dev/emails/page.tsx @@ -0,0 +1,13 @@ +import Link from "next/link"; + +export default function EmailDevPage() { + return
+ + Onboarding Email + +
+ + Payment Success Email + +
+} \ No newline at end of file diff --git a/web/app/(dev)/dev/emails/payment-success/page.tsx b/web/app/(dev)/dev/emails/payment-success/page.tsx new file mode 100644 index 0000000..4425cc2 --- /dev/null +++ b/web/app/(dev)/dev/emails/payment-success/page.tsx @@ -0,0 +1,5 @@ +import { PaymentSuccessEmailTemplate } from "@/components/emails/payment-success"; + +export default function PaymentSuccessEmailDevPage() { + return +} \ No newline at end of file diff --git a/web/app/(dev)/layout.tsx b/web/app/(dev)/layout.tsx new file mode 100644 index 0000000..a14e64f --- /dev/null +++ b/web/app/(dev)/layout.tsx @@ -0,0 +1,16 @@ +export const metadata = { + title: 'Next.js', + description: 'Generated by Next.js', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/web/app/(service)/api/applications/[id]/route.ts b/web/app/(service)/api/applications/[id]/route.ts new file mode 100644 index 0000000..5cfaece --- /dev/null +++ b/web/app/(service)/api/applications/[id]/route.ts @@ -0,0 +1,51 @@ +import { + getApplication, + signApplication, + updateApplication, +} from "@/lib/controllers/applications"; +import { mask } from "@/lib/mask"; +import { NextResponse } from "next/server"; + +/** + * get a single application + */ +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + const { id } = params; + + const customer_id = Number(request.headers.get("x-cors-service-customer-id") as string); + + const application = await getApplication(id); + + if (!application) { + return NextResponse.json( + { error: "application not found" }, + { status: 404 } + ); + } + + if (application.owner_id !== customer_id) { + return NextResponse.json( + { error: "application not found" }, + { status: 403 } + ); + } + + const signed = await signApplication(application); + + return NextResponse.json(mask(signed)); +} + +export async function PUT( + request: Request, + { params }: { params: { id: string } } +) { + const data = await request.json(); + const { id } = params; + + await updateApplication(id, data); + + return NextResponse.json({ success: true }); // or.. updated body? +} diff --git a/web/app/(service)/api/applications/route.ts b/web/app/(service)/api/applications/route.ts new file mode 100644 index 0000000..49d0761 --- /dev/null +++ b/web/app/(service)/api/applications/route.ts @@ -0,0 +1,34 @@ +import { + createApplication, + getMyApplications, + signApplication, +} from "@/lib/controllers/applications"; +import { mask } from "@/lib/mask"; +import { NextResponse } from "next/server"; + +/** + * list all my applications + */ +export async function GET(request: Request) { + const customer_id = Number(request.headers.get("x-cors-service-customer-id") as string); + const applications = await getMyApplications(customer_id); + + return NextResponse.json(applications); +} + +/** + * create a new application + */ +export async function POST(request: Request) { + const customer_id = Number(request.headers.get("x-cors-service-customer-id") as string); + const { name } = await request.json(); + + const app = await createApplication({ + name, + owner: { id: customer_id }, + }); + + const signed = await signApplication(app!); + + return NextResponse.json(mask(signed)); +} diff --git a/web/app/(service)/api/onboarding/[id]/convert/route.ts b/web/app/(service)/api/onboarding/[id]/convert/route.ts new file mode 100644 index 0000000..9f2a813 --- /dev/null +++ b/web/app/(service)/api/onboarding/[id]/convert/route.ts @@ -0,0 +1,17 @@ +import { convertApplication } from "@/lib/controllers/applications"; +import { NextResponse } from "next/server"; + +export async function POST( + request: Request, + { params }: { params: { id: string } } +) { + const { id: onboarding_id } = params; + const { checkout_session_id } = await request.json(); + + const application = await convertApplication({ + onboarding_id, + checkout_session_id, + }); + + return NextResponse.json(application, { status: 201 }); +} diff --git a/web/app/(service)/api/onboarding/[id]/route.ts b/web/app/(service)/api/onboarding/[id]/route.ts new file mode 100644 index 0000000..2d12456 --- /dev/null +++ b/web/app/(service)/api/onboarding/[id]/route.ts @@ -0,0 +1,22 @@ +import { getOnboardingApplication } from "@/lib/controllers/applications"; +import { NextResponse } from "next/server"; + +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + // this route does not have a guard by design. + // get onboarding application (only public data) + const { id } = params; + + const d = await getOnboardingApplication(id); + + if (!d) { + return NextResponse.json( + { error: "application not found" }, + { status: 404 } + ); + } + + return NextResponse.json(d, { status: 200 }); +} diff --git a/web/app/(service)/api/onboarding/with-email/route.ts b/web/app/(service)/api/onboarding/with-email/route.ts new file mode 100644 index 0000000..4c7f513 --- /dev/null +++ b/web/app/(service)/api/onboarding/with-email/route.ts @@ -0,0 +1,21 @@ +import { NextResponse } from "next/server"; +import { createOnboardingApplication } from "@/lib/controllers/applications"; +import type { NextApiRequest, NextApiResponse } from "next"; + +export async function POST(req: Request) { + // create new temporary application bind to the email (form is optional) + + const { email } = await req.json(); + + // @requires: email + if (!email) { + return NextResponse.json({ error: "email is required" }, { status: 400 }); + } + + const d = await createOnboardingApplication({ + type: "with-email", + email, + }); + + return NextResponse.json(d, { status: 201 }); +} diff --git a/web/app/(service)/api/onboarding/with-form/route.ts b/web/app/(service)/api/onboarding/with-form/route.ts new file mode 100644 index 0000000..be3becc --- /dev/null +++ b/web/app/(service)/api/onboarding/with-form/route.ts @@ -0,0 +1,16 @@ +import { createOnboardingApplication } from "@/lib/controllers/applications"; +import { NextResponse } from "next/server"; + +export async function POST(request: Request) { + // create new temporary application bind to the form (email is optional) + const { name, allowedOrigins, priceId } = await request.json(); + + const d = await createOnboardingApplication({ + type: "with-form", + name, + allowedOrigins, + priceId, + }); + + return NextResponse.json(d, { status: 201 }); +} diff --git a/web/app/(service)/api/payments/canceled/route.ts b/web/app/(service)/api/payments/canceled/route.ts new file mode 100644 index 0000000..6e5528c --- /dev/null +++ b/web/app/(service)/api/payments/canceled/route.ts @@ -0,0 +1,9 @@ +import { NextRequest, NextResponse } from "next/server"; + +export async function GET(request: NextRequest) { + const searchParams = request.nextUrl.searchParams; + const session_id = searchParams.get("session_id"); + const onboarding_id = searchParams.get("onboarding_id"); + + return NextResponse.redirect(`https://cors.sh/`, { status: 303 }); +} diff --git a/web/app/(service)/api/payments/checkout/new/route.ts b/web/app/(service)/api/payments/checkout/new/route.ts new file mode 100644 index 0000000..86c5309 --- /dev/null +++ b/web/app/(service)/api/payments/checkout/new/route.ts @@ -0,0 +1,50 @@ +import { stripe } from "@/lib/clients"; +import { getOnboardingApplication } from "@/lib/controllers/applications"; +import { NextResponse } from "next/server"; +import { type NextRequest } from 'next/server' + + +const PROTOCOL = process.env.NODE_ENV === "production" ? "https" : "http"; + +// e.g. +// http://localhost:4021/payments/checkout/new?price=price_1Lda7UAvR3geCh5rVaajCSw6&onboarding_id=63b9a40c02478a88364d7202 +export async function GET(request: NextRequest) { + // + const host = request.headers.get("host"); + + const searchParams = request.nextUrl.searchParams; + const _q_onboarding = searchParams.get("onboarding_id") + + const onboarding = await getOnboardingApplication(_q_onboarding as string); + + if (!onboarding) { + return NextResponse.json({ error: "invalid session" }, { status: 400 }); + } + + const { price_id } = onboarding; + + const price = await stripe.prices.retrieve(price_id!, { + expand: ["product"], + }); + + const extra_params = new URLSearchParams({ + onboarding_id: _q_onboarding as string, + }); + + const session = await stripe.checkout.sessions.create({ + billing_address_collection: "auto", + line_items: [ + { + price: price.id, + // For metered billing, do not pass quantity + quantity: 1, + }, + ], + mode: "subscription", + // e.g. http://localhost:8823/?success=true&session_id=cs_test_a1qQdhxwfS5kKZJ1kToxKqAr2K6yHneucfi65lIs1OPVkmoH14YNAev76S + success_url: `${PROTOCOL}://${host}/payments/success?session_id={CHECKOUT_SESSION_ID}&${extra_params}`, + cancel_url: `${PROTOCOL}://${host}/payments/canceled?session_id={CHECKOUT_SESSION_ID}&${extra_params}`, + }); + + return NextResponse.redirect(session.url!, { status: 303 }); +} diff --git a/web/app/(service)/api/payments/portal-session/route.ts b/web/app/(service)/api/payments/portal-session/route.ts new file mode 100644 index 0000000..7b6c60a --- /dev/null +++ b/web/app/(service)/api/payments/portal-session/route.ts @@ -0,0 +1,23 @@ +import { stripe } from "@/lib/clients"; +import { NextRequest, NextResponse } from "next/server"; + +const HOST = process.env.NEXT_PUBLIC_HOST ?? "http://localhost:8823"; +const WEBURL_CONSOLE = HOST + "/console"; + +export async function POST(request: NextRequest) { + // For demonstration purposes, we're using the Checkout session to retrieve the customer ID. + // Typically this is stored alongside the authenticated user in your database. + const { session_id } = await request.json(); + const checkoutSession = await stripe.checkout.sessions.retrieve(session_id); + + // This is the url to which the customer will be redirected when they are done + // managing their billing with the portal. + const returnUrl = WEBURL_CONSOLE; + + const portalSession = await stripe.billingPortal.sessions.create({ + customer: checkoutSession.customer as string, + return_url: returnUrl, + }); + + return NextResponse.redirect(portalSession.url, { status: 303 }); +} diff --git a/web/app/(service)/api/payments/success/_route.ts b/web/app/(service)/api/payments/success/_route.ts new file mode 100644 index 0000000..73d451c --- /dev/null +++ b/web/app/(service)/api/payments/success/_route.ts @@ -0,0 +1,92 @@ +import { stripe } from "@/lib/clients"; +import { getOnboardingApplication } from "@/lib/controllers/applications"; +import { createCustomer, getCustomerWithEmail } from "@/lib/customers"; +import { Customer } from "@/types/app"; +import { NextResponse, type NextRequest } from "next/server"; + + +const HOST = process.env.NEXT_PUBLIC_HOST ?? "http://localhost:8823"; + + +export async function GET(request: NextRequest) { + + const searchParams = request.nextUrl.searchParams; + const session_id = searchParams.get("session_id"); + const onboarding_id = searchParams.get("onboarding_id"); + + + const checkout_session = await stripe.checkout.sessions.retrieve( + session_id as string + ); + + const { + customer: stripe_customer_id, + customer_email, // can be null if created on checkout page (unless explicitly specified by our side.) + customer_details, + subscription, + } = checkout_session; + + // on success, convert onboarding app to a real app (and remove the temporary app) + // (if user has one.) + + // remove + const tmp = await getOnboardingApplication(onboarding_id as string); + const _email = tmp!.email; + + // if onboarding's email is placeholded. get email from checkout via stripe + const email = _email?.endsWith("@unknown-users.cors.sh") + ? customer_email ?? customer_details?.email + : _email; + + // create customer + // TODO: what if already exists? + + let customer_exists_with_same_email: Customer | undefined; + try { + const _customer = await getCustomerWithEmail(email!); + if (_customer) customer_exists_with_same_email = _customer; + } catch (e) { + console.error("Caught exeption while finding existing customer", e); + } + + if (customer_exists_with_same_email) { + // TODO: we'll need a better way to handle this since we need to test this with same email multiple times. + // we can't tell if the purchase is for the same user or not. + // yet, if the existing one is verified, we should protect it. + // if not, we should give the new one a chance. + const _params = { + error: "identity_conflict", + message: + "Your payment was successful, but we detected a suspicious activity. Please contact customer support.", + session_id: session_id as string, + onboarding_id: String(tmp?.id), + application_id: String(tmp?.id), + } + const params = new URLSearchParams(_params); + const redirect_uri = `${HOST}/onboarding/payment-success-with-issue?${params.toString()}`; + return NextResponse.redirect(redirect_uri, { status: 303 }); + } else { + + const customer = await createCustomer({ + stripe_customer_id: stripe_customer_id as string, + email: email!, + }); + + const _params = { + session_id: session_id as string, + onboarding_id: tmp?.id ? String(tmp!.id) : undefined, + customer_id: customer!.id, + application_id: tmp?.id ? String(tmp?.id) : undefined, + } as any as { [key: string]: string }; + + // prettier-ignore + Object.keys(_params).forEach((key) => (_params as any)[key] === undefined ? delete (_params as any)[key] : {}); + + const params = new URLSearchParams(_params); + + const redirect_uri = `${HOST}/onboarding/payment-success?${params.toString()}`; + + return NextResponse.redirect(redirect_uri, { status: 303 }); + } +} + diff --git a/web/app/(service)/auth/signin/_route.ts b/web/app/(service)/auth/signin/_route.ts new file mode 100644 index 0000000..8f1e514 --- /dev/null +++ b/web/app/(service)/auth/signin/_route.ts @@ -0,0 +1,69 @@ +/* +// LEGACY +import Axios from "axios"; +import { encode_jwt, SECURE_BROWSER_COOKIE_AUTH_KEY } from "@/lib/auth"; +import { NextResponse } from "next/server"; + +const authclient = Axios.create({ + baseURL: "https://accounts.services.grida.co", +}); + +// user signin with grida, retrieve oauth token from grida, sends it here, +// this service will check the token, if valid, it will generate a new token for the user, +// and send it back to the client with secure, http only cookie. +export async function POST(req: Request) { + const authorization = req.headers.get("proxy-authorization"); + + if (!authorization) { + return NextResponse.json( + { error: "no authorization header" }, + { status: 401 } + ); + } + + // authenticate via accounts.grida.co + // request auth server for authentication. + const { data } = await authclient.get("/verify", { + headers: { + // proxy the header, in form of "Bearer " + authorization, + }, + }); + + const customer = await prisma.customer.findUnique({ + where: { + // workspaceId: data.id, + }, + }); + + // sign customer (user) signature + const jwt = encode_jwt(customer.id); + + // set secure cookie when authorized. + NextResponse.json( + { + success: true, + customer: customer, + }, + { + status: 200, + headers: { + "set-cookie": `${SECURE_BROWSER_COOKIE_AUTH_KEY}=${jwt}; Domain=.cors.sh; Path=/; Secure; HttpOnly; SameSite=Strict;`, + // .cookie(SECURE_BROWSER_COOKIE_AUTH_KEY, jwt, { + // signed: true, + // domain: ".cors.sh", + // secure: true, + // httpOnly: true, + // sameSite: "strict", + // // no expiration. it is a secure cookie, that only has access to cors.sh. let's keep it this way for now. + // // expires: null + // }) + }, + } + ); +} +*/ + +const dummy = () => {}; + +export default dummy; diff --git a/web/app/(service)/webhooks/stripe/route.ts b/web/app/(service)/webhooks/stripe/route.ts new file mode 100644 index 0000000..5908a7d --- /dev/null +++ b/web/app/(service)/webhooks/stripe/route.ts @@ -0,0 +1,85 @@ +import { NextResponse } from "next/server"; +import { stripe } from "@/lib/clients"; + + +export async function POST(request: Request) { + // raw body for webhook signing + let event: any = await request.text(); + + if (!event) { + return NextResponse.error(); + } + + // Replace this endpoint secret with your endpoint's unique secret + // If you are testing with the CLI, find the secret by running 'stripe listen' + // If you are using an endpoint defined with the API or dashboard, look in your webhook settings + // at https://dashboard.stripe.com/webhooks + const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; + // Only verify the event if you have an endpoint secret defined. + // Otherwise use the basic event deserialized with JSON.parse + if (endpointSecret) { + // Get the signature sent by Stripe + const signature = request.headers.get("stripe-signature"); + try { + event = stripe.webhooks.constructEvent( + event, + signature!, + endpointSecret + ); + } catch (err: any) { + console.log(`⚠️ Webhook signature verification failed.`, err.message); + return NextResponse.error(); + } + } + + let subscription; + let status; + + // Handle the event + switch (event!.type) { + case "customer.subscription.trial_will_end": + subscription = event.data.object; + status = subscription.status; + console.log(`Subscription status is ${status}.`); + // Then define and call a method to handle the subscription trial ending. + // handleSubscriptionTrialEnding(subscription); + break; + case "customer.subscription.deleted": + subscription = event.data.object; + status = subscription.status; + console.log(`Subscription status is ${status}.`); + // Then define and call a method to handle the subscription deleted. + // handleSubscriptionDeleted(subscriptionDeleted); + break; + case "customer.subscription.created": + subscription = event.data.object; + status = subscription.status; + console.log(`Subscription status is ${status}.`); + // Then define and call a method to handle the subscription created. + // handleSubscriptionCreated(subscription); + break; + case "customer.subscription.updated": + subscription = event.data.object; + status = subscription.status; + console.log(`Subscription status is ${status}.`); + // Then define and call a method to handle the subscription update. + // handleSubscriptionUpdated(subscription); + break; + default: + // Unexpected event type + console.log(`Unhandled event type ${event.type}.`); + } + + // Return a 200 response to acknowledge receipt of the event + NextResponse.json({}, { status: 200 }); +} + +// router.post( +// /** +// * /webhooks/stripe - defined in routes/index.ts +// */ +// "/", +// express.raw({ type: "application/json" }), +// (request, response) => { +// } +// ); diff --git a/web/app/globals.console.css b/web/app/globals.console.css new file mode 100644 index 0000000..6499641 --- /dev/null +++ b/web/app/globals.console.css @@ -0,0 +1,27 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 250, 250, 250; + --background-end-rgb: 250, 250, 250; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); +} diff --git a/web/components/charts/bar-chart.tsx b/web/components/charts/bar-chart.tsx new file mode 100644 index 0000000..abf44d1 --- /dev/null +++ b/web/components/charts/bar-chart.tsx @@ -0,0 +1,74 @@ +'use client' + +import React, { useMemo } from 'react'; +import { Bar } from '@visx/shape'; +import { Group } from '@visx/group'; +import letterFrequency, { LetterFrequency } from '@visx/mock-data/lib/mocks/letterFrequency'; +import { scaleBand, scaleLinear } from '@visx/scale'; + +const data = letterFrequency.slice(5); +const verticalMargin = 120; + +// accessors +const getLetter = (d: LetterFrequency) => d.letter; +const getLetterFrequency = (d: LetterFrequency) => Number(d.frequency) * 100; + +export type BarsProps = { + width: number; + height: number; + events?: boolean; +}; + +export default function BarChart({ width, height, events = false }: BarsProps) { + // bounds + const xMax = width; + const yMax = height - verticalMargin; + + // scales, memoize for performance + const xScale = useMemo( + () => + scaleBand({ + range: [0, xMax], + round: true, + domain: data.map(getLetter), + padding: 0.4, + }), + [xMax], + ); + const yScale = useMemo( + () => + scaleLinear({ + range: [yMax, 0], + round: true, + domain: [0, Math.max(...data.map(getLetterFrequency))], + }), + [yMax], + ); + + return width < 10 ? null : ( + + + {data.map((d) => { + const letter = getLetter(d); + const barWidth = xScale.bandwidth(); + const barHeight = yMax - (yScale(getLetterFrequency(d)) ?? 0); + const barX = xScale(letter); + const barY = yMax - barHeight; + return ( + { + if (events) alert(`clicked: ${JSON.stringify(Object.values(d))}`); + }} + /> + ); + })} + + + ); +} \ No newline at end of file diff --git a/web/components/charts/cart-card.tsx b/web/components/charts/cart-card.tsx new file mode 100644 index 0000000..31d582c --- /dev/null +++ b/web/components/charts/cart-card.tsx @@ -0,0 +1,16 @@ +import React from "react"; + +export function ChartCard({ label, children }: React.PropsWithChildren<{ + label: string | React.ReactNode; +}>) { + return
+
+

+ {label} +

+
+ {children} +
+} \ No newline at end of file diff --git a/web/components/console/application-item.tsx b/web/components/console/application-item.tsx new file mode 100644 index 0000000..16c0acc --- /dev/null +++ b/web/components/console/application-item.tsx @@ -0,0 +1,31 @@ +import { ArrowRightIcon, GlobeIcon, LayersIcon } from "@radix-ui/react-icons"; + + +export function ApplicationItem({ + id, + name, + allowedOrigins, +}: { + id: string; + name: string; + allowedOrigins?: string[]; +}) { + return ( +
+
+ + + {name} ({id}) + + +
+ + {allowedOrigins?.map((u) => ( + {u} + ))} + +
+ ); +} \ No newline at end of file diff --git a/web/components/console/application-list.tsx b/web/components/console/application-list.tsx deleted file mode 100644 index 6704bee..0000000 --- a/web/components/console/application-list.tsx +++ /dev/null @@ -1,56 +0,0 @@ -'use client' - -import styled from "@emotion/styled"; -import { ArrowRightIcon } from "@radix-ui/react-icons"; -import Link from "next/link"; - -export const ApplicationList = styled.div` - display: flex; - flex-direction: column; - align-items: stretch; - width: 100%; - gap: 8px; -`; - -export function ApplicationItem({ - id, - name, - allowedOrigins, -}: { - id: string; - name: string; - allowedOrigins?: string[]; -}) { - return ( - - - - {name} ({id}) - - - - - ); -} - -const ItemWrap = styled.div` - flex: 1; - display: flex; - cursor: pointer; - justify-content: space-between; - flex-direction: row; - align-items: center; - flex: none; - border-radius: 4px; - border: solid 1px rgba(0, 0, 0, 0.1); - box-sizing: border-box; - padding: 21px; - - &:hover { - border: solid 1px rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.02); - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); - } - - transition: all 0.2s ease-in-out; -`; diff --git a/web/components/emails/onboarding.tsx b/web/components/emails/onboarding.tsx new file mode 100644 index 0000000..6110feb --- /dev/null +++ b/web/components/emails/onboarding.tsx @@ -0,0 +1,143 @@ +import React from "react"; +import { Button, Head, Tailwind } from "@react-email/components"; + +const HOST = process.env.NEXT_PUBLIC_HOST || "http://localhost:8823"; + +interface OnboardingEmailTemplateProps { + code: string; + onboarding_url: string; +} + +export const subject = "CORS.SH | your API Key for cors.proxy.sh"; + +export function OnboardingEmailTemplate({ + code, + onboarding_url, +}: OnboardingEmailTemplateProps) { + return ( + +
+ + {/* eslint-disable-next-line @next/next/no-page-custom-font */} + + +
+

+ Your API key for +
+ proxy.cors.sh +

+
+
+

Your temporary API key is..

+

+ {code} +

+

Copy & Paste this api key to your api call (XHR) header.

+

Example usage

+

+ You can use the api key like below. For more example, visit{" "} + https://cors.sh/#usage +

+
+ +
+

Next (Action required)

+

+ Since this key is a temporary key to get you started, you have to + sign-in & claim your account to get a permanent one.{" "} + This key will only be valid for 3 days. +

+ +

+ + button not working? copy & paste this link to your browser + +
+ + {onboarding_url} + +

+
+ {/* footer */} +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + CORS.SH Logo +

+ + A Grida Product |{" "} + Contact + +

+
+
+
+ ); +} + +function CodeBlock({ code }: { code: string }) { + return ( + +
+        fetch
+        (
+        
+          'https://proxy.cors.sh/https://acme.com'
+        
+        ,
+        {
+        
+   headers + : + { +
+      + 'x-cors-api-key' + : +  '{code}' +
+   } +
+ }) +
+
+
+ ); +} diff --git a/web/components/emails/payment-success.tsx b/web/components/emails/payment-success.tsx new file mode 100644 index 0000000..209e409 --- /dev/null +++ b/web/components/emails/payment-success.tsx @@ -0,0 +1,86 @@ +import React from "react"; +import { Button, Head, Tailwind } from "@react-email/components"; + +const HOST = process.env.NEXT_PUBLIC_HOST || "http://localhost:8823"; + +export const subject = "CORS.SH | Your first project" + +interface PaymentSuccessEmailTemplateProps { + applicationName: string; + codeTest: string; + codeLive: string; +} + +export function PaymentSuccessEmailTemplate({applicationName, + codeTest, + codeLive,}: PaymentSuccessEmailTemplateProps) { + return ( + +
+ + {/* eslint-disable-next-line @next/next/no-page-custom-font */} + + +
+

Thank you for
your subscription

+
+
+

We’re all set. Let’s get rid of the cors errors by extending your api call with proxy.cors.sh like below.

+

Your API key for your first application “{applicationName}” is..

+

+ # for testing
{codeTest}

# for production
{codeLive} +

+

Copy & Paste this api key to your api call (XHR) header.

+

Example usage

+

You can use the api key like below. For more example, visit https://cors.sh/#usage

+
+ +
+

Read the docs

+
+ {/* footer */} +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + CORS.SH Logo +

+ A Grida Product | Contact +

+
+
+
+ ); +} + +function CodeBlock2({ codeTest}: { + codeTest: string; +}) { + return (
+  
+ fetch + ( + 'https://proxy.cors.sh/https://acme.com' + , + { +
+   headers + : + { +
+     'x-cors-api-key' + : +  '{codeTest}' +
+   } +
+ }) +
+
+
) +} \ No newline at end of file diff --git a/web/components/header-user-actions.tsx b/web/components/header-user-actions.tsx new file mode 100644 index 0000000..90e58ba --- /dev/null +++ b/web/components/header-user-actions.tsx @@ -0,0 +1,33 @@ +'use client' + +import React, { useState } from "react" +import Link from "next/link" +import { useUser } from "@/hooks/useUser" + +export default function HeaderUserActions() { + + const user = useUser() + + return <> + { + user ? ( + + Console + + ) : ( + + Sign in + + ) + } + { + !user && ( + + + + ) + } + +} \ No newline at end of file diff --git a/web/components/header.tsx b/web/components/header.tsx index 2b80ea9..65000bb 100644 --- a/web/components/header.tsx +++ b/web/components/header.tsx @@ -2,6 +2,7 @@ import React from "react" import { GitHubLogoIcon } from "@radix-ui/react-icons" import Link from "next/link" import { SlashIcon } from "@radix-ui/react-icons" +import HeaderUserActions from "./header-user-actions" export function Header() { @@ -39,14 +40,7 @@ export function Header() {
- {/* - Console - */} - - - +
diff --git a/web/components/prism/index.tsx b/web/components/prism/index.tsx new file mode 100644 index 0000000..e267726 --- /dev/null +++ b/web/components/prism/index.tsx @@ -0,0 +1,18 @@ +'use client' +import React from 'react'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { atomDark as scheme } from 'react-syntax-highlighter/dist/esm/styles/prism'; + + +export function Prism({ children, style, language = 'typescript' }: React.PropsWithChildren<{ + style?: React.CSSProperties + language?: string +}>) { + {/* @ts-ignore */ } + return + {children} + +} \ No newline at end of file diff --git a/web/console/button.tsx b/web/console/button.tsx new file mode 100644 index 0000000..470bb5f --- /dev/null +++ b/web/console/button.tsx @@ -0,0 +1,20 @@ + +export function Button({ variant = 'primary', children, ...props }: React.ButtonHTMLAttributes & { + variant?: "primary" | "secondary" | "danger" +}) { + return ( + + ) +} diff --git a/web/console/card.tsx b/web/console/card.tsx new file mode 100644 index 0000000..842ce03 --- /dev/null +++ b/web/console/card.tsx @@ -0,0 +1,9 @@ +import React from "react"; + +export function Card({ children }: React.HTMLAttributes) { + return ( +
+ {children} +
+ ) +} \ No newline at end of file diff --git a/web/console/form.tsx b/web/console/form.tsx new file mode 100644 index 0000000..d675010 --- /dev/null +++ b/web/console/form.tsx @@ -0,0 +1,46 @@ +export function Form({ children }: React.FormHTMLAttributes) { + return ( +
+ {children} +
+ ) +} + +export function FormHeader({ children }: React.PropsWithChildren<{}>) { + return ( +
+ {/* default title style */} + + {children} + +
+ ) +} + +export function FormFooter({ children }: React.PropsWithChildren<{}>) { + return ( +
+ {children} +
+ ) +} + +export function FormRow({ label, children, noborder }: React.PropsWithChildren<{ + label?: string | React.ReactNode + noborder?: boolean +}>) { + { + return ( +
+ {label &&
+ {label} +
} +
+ {children} +
+
+ ) + } +} \ No newline at end of file diff --git a/web/console/index.ts b/web/console/index.ts new file mode 100644 index 0000000..4f126a6 --- /dev/null +++ b/web/console/index.ts @@ -0,0 +1,3 @@ +export * from "./button" +export * from "./form" +export * from "./card" \ No newline at end of file diff --git a/web/hooks/useHost.ts b/web/hooks/useHost.ts new file mode 100644 index 0000000..a78dd2f --- /dev/null +++ b/web/hooks/useHost.ts @@ -0,0 +1,15 @@ +import { useState, useEffect } from "react"; + +const useHost = () => { + const [host, setHost] = useState(); + + useEffect(() => { + if (typeof window !== "undefined") { + setHost(window.location.origin); + } + }, []); + + return host; +}; + +export default useHost; diff --git a/web/hooks/useUser.ts b/web/hooks/useUser.ts new file mode 100644 index 0000000..9cb0cc4 --- /dev/null +++ b/web/hooks/useUser.ts @@ -0,0 +1,25 @@ +import { useEffect, useState } from "react"; +import { createBrowserClient } from "@supabase/ssr"; +// import { isProUser } from "@/s/q-user"; +import { User } from "@supabase/supabase-js"; + +export function useUser() { + const [user, setUser] = useState(null); + const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ); + + useEffect(() => { + supabase.auth.onAuthStateChange((event, session) => { + setUser(session?.user ?? null); + }); + }, [supabase]); + + if (!user) return null; + + return { + ...user, + // isPro: user && isProUser(user), + }; +} diff --git a/services/services.cors.sh/auth/index.ts b/web/lib/auth/index.ts similarity index 69% rename from services/services.cors.sh/auth/index.ts rename to web/lib/auth/index.ts index 51b1c43..4794bba 100644 --- a/services/services.cors.sh/auth/index.ts +++ b/web/lib/auth/index.ts @@ -1,3 +1,2 @@ export * from "./key"; -export * from "./jwt"; export * from "./middleware"; diff --git a/services/services.cors.sh/auth/key.ts b/web/lib/auth/key.ts similarity index 100% rename from services/services.cors.sh/auth/key.ts rename to web/lib/auth/key.ts diff --git a/web/lib/auth/middleware.ts b/web/lib/auth/middleware.ts new file mode 100644 index 0000000..c667bb3 --- /dev/null +++ b/web/lib/auth/middleware.ts @@ -0,0 +1,101 @@ +// import { verify } from "./jwt"; +// import { SECURE_BROWSER_COOKIE_AUTH_KEY } from "./key"; +import { stripe } from "../clients"; +import { supabase } from "../supabase"; +import { NextResponse } from "next/server"; +import { createServerClient, CookieOptions } from "@supabase/ssr"; +import { cookies } from "next/headers"; + +// since the secure cookie cannot be forged, we have no additional validation on the jwt from client's secure http only cookie. +// the possible hacking scenario is.. +// 1. the hacker steals the jwt secret (impossible, but somehow.) +// 2. the hacker finds out the customer id of services.cors.sh +// 3. the hacker sets the cookie with the jwt token, and the customer id. +// - seems secure enough for now. +export async function authMiddleware(req: Request, res: Response) { + const _1 = await standardAuthorizer(req); + if (_1) { + const { customer } = _1; + res.headers.set("x-cors-service-customer-id", String(customer.id)); + return res; + } + + const _2 = await checoutSessionAuthorizer(req); + if (_2) { + const { customer } = _2; + res.headers.set("x-cors-service-customer-id", String(customer.id)); + return res; + } + + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); +} + +async function checoutSessionAuthorizer(req: Request) { + const checkout_session_id = req.headers.get( + "x-cors-service-checkout-session-id" + ); + if (!checkout_session_id) { + return false; + } + + const checkout_session = await stripe.checkout.sessions.retrieve( + checkout_session_id as string + ); + + const { customer: stripe_customer_id } = checkout_session; + + const { data: customer } = await supabase + .from("customers") + .select("*") + .eq("stripe_id", stripe_customer_id as string) + .single(); + + if (!customer) { + return false; + } + + return { + customer, + }; +} + +async function standardAuthorizer(req: Request): Promise { + const cookieStore = cookies(); + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return cookieStore.get(name)?.value; + }, + set(name: string, value: string, options: CookieOptions) { + cookieStore.set({ name, value, ...options }); + }, + remove(name: string, options: CookieOptions) { + cookieStore.set({ name, value: "", ...options }); + }, + }, + } + ); + + const { data } = await supabase.auth.getUser(); + const user = data.user; + + if (!user) { + return false + } + + // TODO: fetch customer + const { data: customer } = await supabase + .from("customers") + .select("*") + .eq("id", user.id) + .single(); + if (!customer) { + return false + } + + return customer +} diff --git a/services/services.cors.sh/auth/readme.md b/web/lib/auth/readme.md similarity index 100% rename from services/services.cors.sh/auth/readme.md rename to web/lib/auth/readme.md diff --git a/web/lib/clients/index.ts b/web/lib/clients/index.ts new file mode 100644 index 0000000..7582f3b --- /dev/null +++ b/web/lib/clients/index.ts @@ -0,0 +1,2 @@ +export * from "./stripe"; +export * from "./resend" \ No newline at end of file diff --git a/web/lib/clients/resend.ts b/web/lib/clients/resend.ts new file mode 100644 index 0000000..6ed938e --- /dev/null +++ b/web/lib/clients/resend.ts @@ -0,0 +1,3 @@ +import { Resend } from "resend"; + +export const resend = new Resend(process.env.RESEND_API_KEY); diff --git a/services/services.cors.sh/clients/slack.ts b/web/lib/clients/slack.ts similarity index 100% rename from services/services.cors.sh/clients/slack.ts rename to web/lib/clients/slack.ts diff --git a/web/lib/clients/stripe.ts b/web/lib/clients/stripe.ts new file mode 100644 index 0000000..3fa5771 --- /dev/null +++ b/web/lib/clients/stripe.ts @@ -0,0 +1,5 @@ +import { Stripe } from "stripe"; + +export const stripe = new Stripe(process.env.STRIPE_API_KEY!, { + apiVersion: "2023-10-16", +}); diff --git a/services/services.cors.sh/controllers/_telemetry.ts b/web/lib/controllers/_telemetry.ts similarity index 60% rename from services/services.cors.sh/controllers/_telemetry.ts rename to web/lib/controllers/_telemetry.ts index a8c435c..9d511ba 100644 --- a/services/services.cors.sh/controllers/_telemetry.ts +++ b/web/lib/controllers/_telemetry.ts @@ -1,27 +1,35 @@ -import type { OnboardingApplications, Application } from "@prisma/client"; -import { prisma } from "../clients"; +import { Application, OnboardingApplication } from "@/types/app"; import { slack, blocks } from "../clients/slack"; +import { supabase } from "../supabase"; + +export async function logNewOnboardingProc(data: OnboardingApplication) { + const { count } = await supabase.from("applications_onboarding").select("*", { + count: "exact", + head: true, + }); -export async function logNewOnboardingProc(data: OnboardingApplications) { - const total = await prisma.onboardingApplications.count(); const { id, name, email } = data; const title = `New Onboarding Application`; const dataToLog = { name, email, - total, + total: count, }; const message = blocks({ title, data: dataToLog }); await slack({ blocks: message }); } export async function logNewApplication(data: Application) { - const total = await prisma.application.count(); + const { count } = await supabase.from("applications").select("*", { + count: "exact", + head: true, + }); + const { name } = data; const title = `New Application`; const dataToLog = { name, - total, + total: count, }; const message = blocks({ title, data: dataToLog }); await slack({ blocks: message }); diff --git a/web/lib/controllers/applications.ts b/web/lib/controllers/applications.ts new file mode 100644 index 0000000..c439dc2 --- /dev/null +++ b/web/lib/controllers/applications.ts @@ -0,0 +1,382 @@ +import { stripe, resend } from "../clients"; +import { sign_live_key, sign_temporary_key, sign_test_key } from "../keygen"; +import { nanoid } from "nanoid"; +// import sync from "../sync"; +import { logNewOnboardingProc, logNewApplication } from "./_telemetry"; +import { Application, OnboardingApplication } from "@/types/app"; +import { supabase } from "../supabase"; +import { OnboardingEmailTemplate, subject as onboarding_email_template_subject } from "@/components/emails/onboarding"; +import { PaymentSuccessEmailTemplate, subject as payment_success_email_template_subject} from "@/components/emails/payment-success" + +type CreateOnboardingApplicationBody = + | { + type: "with-form"; + name: string; + allowedOrigins: string[]; + priceId: string; + } + | { + type: "with-email"; + email: string; + }; + +export async function createOnboardingApplication( + body: CreateOnboardingApplicationBody, + send_onboarding_email_if_possible: boolean = true +) { + let email_available = false; + let email: string; + let name: string; + let allowedOrigins: string[] = []; + let priceId: string | undefined; + + switch (body.type) { + case "with-email": { + email = body.email; + name = "My first cors.sh app"; + email_available = true; + break; + } + case "with-form": { + email = `${nanoid(10)}@unknown-users.cors.sh`; + name = body.name; + allowedOrigins = body.allowedOrigins; + priceId = body.priceId; + break; + } + } + + const { key: tmpkey, expires_at } = sign_temporary_key(); + + let data: OnboardingApplication; + + // check if email exists + let duplicated: OnboardingApplication | null = null; + if (email_available) { + const { data } = await supabase + .from("applications_onboarding") + .select("*") + .eq("email", email) + .single(); + + duplicated = data; + } + + // if duplicated, update the existing one with the new key. + if (duplicated) { + // if the last interaction is within 5 minutes, ignore the request + if (duplicated.updated_at) { + } + + const { data: _data } = await supabase + .from("applications_onboarding") + .update({ key: tmpkey }) + .eq("id", duplicated.id) + .select() + .single(); + + if (_data) data = _data; + } else { + const { data: _data } = await supabase + .from("applications_onboarding") + .insert({ + key: tmpkey, + email: email, + name: name, + allowed_origins: allowedOrigins ?? [], + expires_at: expires_at.toISOString(), + price_id: priceId, + }); + } + + if (email_available && send_onboarding_email_if_possible) { + // send an email to the user + const res = await sendOnboardingEmail(email, data!); + console.log("email sent", res); + } + + // log event to slack + try { + !duplicated && (await logNewOnboardingProc(data!)); + } catch (e) { + console.error("failed to log new onboarding application", e); // not critical + } + + return { + id: data!.id, + // omit the key since it also works as a verification code for faster signup + // key: "omitted" + email: data!.email, + name: data!.name, + allowedOrigins: data!.allowed_origins, + priceId: data!.price_id, + }; +} + +export async function getOnboardingApplication(id: string) { + const { data } = await supabase + .from("applications_onboarding") + .select( + ` + id, + name, + email, + allowed_origins, + price_id, + created_at, + updated_at + ` + ) + .eq("id", id) + .single(); + + return data; +} + +async function sendOnboardingEmail( + email: string, + application?: OnboardingApplication +) { + if (!application) { + const { data } = await supabase + .from("applications_onboarding") + .select("*") + .eq("email", email) + .single(); + + if (data) application = data; + } + + if (!application) { + return false; + } + + const { key, email_sent_at } = application; + + // if the last interaction is within 1 minutes, ignore the request + if (email_sent_at && email_sent_at.length > 0) { + const lastSentAt = email_sent_at[email_sent_at.length - 1]; + if (lastSentAt) { + const diff = new Date().getTime() - new Date(lastSentAt).getTime(); + if (diff < 60000) { + return false; + } + } + } + + // send email with resend api + try { + const response = await resend.emails.send({ + from: "CORS.SH ", + to: [email], + subject: onboarding_email_template_subject, + react: OnboardingEmailTemplate({ + code: key as string, + onboarding_url: `https://cors.sh/onboarding/${application.id}` + }) as React.ReactElement, + }); + + if (response.error) { + console.error("email failed", response.error); + return false; + } + + console.log("email sent", response); + } catch (error) { + console.error("email failed", error); + return false; + } + + + // await emailWithTemplate( + // email, + // `mail_cors_sh_onboarding_${process.env.STAGE}`, + // { + // CODE: key, + // ONBOARDINGLINK: `https://cors.sh/onboarding/${application.id}`, + // } + // ); + + // update the tmp app + await supabase + .from("applications_onboarding") + .update({ + email_sent_at: [ + ...(application.email_sent_at ?? []), + new Date().toISOString(), + ], + }) + .eq("id", application.id); + + return true; +} + +export async function getApplication(id: string) { + const { data } = await supabase + .from("applications") + .select("*") + .eq("id", id) + .single(); + + return data; +} + +export async function getMyApplications(customerId: number) { + const { data } = await supabase + .from("applications") + .select("*") + .eq("owner_id", customerId); + + const applications = data; + + return applications; +} + +export async function updateApplication(id: string, data: Application) { + const { data: _data } = await supabase + .from("applications") + .update(data) + .eq("id", id) + .select() + .single(); + + return data; +} + +export async function signApplication(application: Application) { + // + const { key: apikey_test } = sign_test_key(application.signature_test); + const { key: apikey_live } = sign_live_key(application.signature_live); + + const payload = { + ...application, + apikey_test, + apikey_live, + }; + + return payload; +} + +export async function createApplication({ + id, + name, + allowedOrigins, + owner, +}: { + id?: number; + name: string; + allowedOrigins?: string[]; + owner: { id: number }; +}) { + const placeholder_test = nanoid(10); + const placeholder_live = nanoid(10); + + const { data: application } = await supabase + .from("applications") + .insert({ + id: id, + name: name, + signature_test: placeholder_test, + signature_live: placeholder_live, + allowed_origins: allowedOrigins ?? [], + owner_id: owner.id, + }) + .select() + .single(); + + const salt_test = nanoid(10); + const salt_live = nanoid(10); + const signature_test = application!.id + salt_test; + const signature_live = application!.id + salt_live; + + const { data: updated } = await supabase + .from("applications") + .update({ + signature_test, + signature_live, + }) + .eq("id", application!.id) + .select() + .single(); + + // once application is created and initially signed, sync to the keys table + // TODO: + // await sync(updated); + + return updated; +} + +export async function convertApplication({ + onboarding_id, + checkout_session_id, +}: { + onboarding_id: string; + checkout_session_id: string; +}) { + const checkout_session = await stripe.checkout.sessions.retrieve( + checkout_session_id as string + ); + + const { customer: stripe_customer } = checkout_session; + const stripe_customer_id = + typeof stripe_customer === "string" ? stripe_customer : stripe_customer!.id; + + const { data: customer } = await supabase + .from("customers") + .select("*") + .eq("stripe_id", stripe_customer_id) + .single(); + + // place this right before application create since its a delete and cannot be undone. (reduce chance of error when it fails) + const { data: tmp } = await supabase + .from("applications_onboarding") + .delete() + .eq("id", onboarding_id as string) + .select() + .single(); + + const application = await createApplication({ + id: tmp!.id, + name: tmp!.name || "Untitled", + allowedOrigins: tmp!.allowed_origins || [], + owner: { id: customer!.id }, + }); + + const signed = await signApplication(application!); + + // once application is created and initially signed, sync to the keys table + // TODO: + // await sync(application); + + // send email to the user + try { + const response = await resend.emails.send({ + from: "CORS.SH ", + to: [customer!.email!], + subject: payment_success_email_template_subject, + react: PaymentSuccessEmailTemplate({ + applicationName: tmp!.name || "Untitled", + codeLive: signed.apikey_live, + codeTest: signed.apikey_test, + }) as React.ReactElement, + }); + + if (response.error) { + console.error("email failed", response.error); + } + + console.log("email sent", response); + } catch (error) { + console.error("email failed", error); + } + + + // log event to slack + try { + await logNewApplication(signed); + } catch (e) { + console.error("failed to log new application", e); // not critical + } + + return application; +} diff --git a/web/lib/customers.ts b/web/lib/customers.ts new file mode 100644 index 0000000..e711a8f --- /dev/null +++ b/web/lib/customers.ts @@ -0,0 +1,31 @@ +import { supabase } from "./supabase"; + +export async function getCustomerWithEmail(email: string) { + const { data } = await supabase + .from("customers") + .select("*") + .eq("email", email) + .single(); + + return data; +} + +export async function createCustomer({ + stripe_customer_id, + email, +}: { + stripe_customer_id: string; + email: string; +}) { + const { data: customer } = await supabase + .from("customers") + .insert({ + stripe_id: stripe_customer_id as string, + email: email, + email_verified: false, + }) + .select() + .single(); + + return customer; +} diff --git a/services/services.cors.sh/keygen/index.ts b/web/lib/keygen/index.ts similarity index 96% rename from services/services.cors.sh/keygen/index.ts rename to web/lib/keygen/index.ts index 0003da6..ed25e9a 100644 --- a/services/services.cors.sh/keygen/index.ts +++ b/web/lib/keygen/index.ts @@ -1,7 +1,7 @@ import crypto from "crypto"; import day from "dayjs"; -const API_KEY_TEMP_AES_KEY = process.env.API_KEY_TEMP_AES_KEY; +const API_KEY_TEMP_AES_KEY = process.env.API_KEY_TEMP_AES_KEY!; const _aes_key = Buffer.from(API_KEY_TEMP_AES_KEY, "hex"); const API_KEY_TEMP_AES_IV: string = process.env.API_KEY_TEMP_AES_IV!; const _aes_iv = Buffer.from(API_KEY_TEMP_AES_IV, "hex"); @@ -108,7 +108,7 @@ function prefix(type: "test" | "live" | "temp") { } function encrypt(data: string | object, type: "test" | "live") { - const key = API_KEY_HASH_SECRET_BY_TYPE[type]; + const key = API_KEY_HASH_SECRET_BY_TYPE[type]!; const hmac = crypto.createHmac("sha256", key); hmac.update(JSON.stringify(data)); return hmac.digest("hex"); diff --git a/web/lib/mask.ts b/web/lib/mask.ts new file mode 100644 index 0000000..1463c94 --- /dev/null +++ b/web/lib/mask.ts @@ -0,0 +1,18 @@ +import { Application } from "@/types/app"; + +export function mask( + signed: Application & { + apikey_test: string; + apikey_live: string; + } +) { + return { + id: signed.id, + name: signed.name, + allowedOrigins: signed.allowed_origins, + allowedTargets: signed.allowed_targets, + // available once + apikey_test: signed.apikey_test, + apikey_live: signed.apikey_live, + }; +} diff --git a/web/lib/q/index.ts b/web/lib/q/index.ts new file mode 100644 index 0000000..cd0cad2 --- /dev/null +++ b/web/lib/q/index.ts @@ -0,0 +1 @@ +export * as redirect_uri from "./redirect_uri"; diff --git a/web/lib/q/redirect_uri.ts b/web/lib/q/redirect_uri.ts new file mode 100644 index 0000000..edaf9c2 --- /dev/null +++ b/web/lib/q/redirect_uri.ts @@ -0,0 +1,57 @@ +import type { ReadonlyURLSearchParams } from "next/navigation"; + +const key = "redirect_uri" as const; +/** + * Parses the redirect uri from the given request + * @returns {string} The redirect uri + */ +export function parse( + searchParams: URLSearchParams | ReadonlyURLSearchParams +): string { + try { + return searchParams.get(key) || ""; + } catch (e) { + return (searchParams as any)[key] || ""; + } +} + +export function make( + base: T, + { redirect_uri }: { redirect_uri?: string } +): T | undefined { + if (typeof base === "string" && base.startsWith("/")) { + // relative path + return (base + (redirect_uri ? `?${key}=${redirect_uri}` : "")) as T; + } + + try { + const url = typeof base === "string" ? new URL(base) : (base as URL); + + if (redirect_uri) { + url.searchParams.set(key, redirect_uri); + } + return url as T; + } catch (e) { + return undefined; + } +} + +/** + * Returns the absolute redirect uri + * This is required for server redirect response + */ +export function abs({ + host, + redirect_uri, +}: { + host: string; + redirect_uri: string; +}): string { + // check if redirect_uri is absolute + if (redirect_uri.startsWith("http")) { + return redirect_uri; + } + + // else, + return host + redirect_uri; +} diff --git a/web/lib/supabase.ts b/web/lib/supabase.ts new file mode 100644 index 0000000..ed624d9 --- /dev/null +++ b/web/lib/supabase.ts @@ -0,0 +1,7 @@ +import { Database } from "@/types/supabase"; +import { createClient } from "@supabase/supabase-js"; + +export const supabase = createClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.SUPABASE_SERVICE_ROLE_SECRET! +); diff --git a/web/lib/sync.ts b/web/lib/sync.ts new file mode 100644 index 0000000..a1612b0 --- /dev/null +++ b/web/lib/sync.ts @@ -0,0 +1,146 @@ +import { DynamoDBClient, PutItemCommand, UpdateItemCommand } from "@aws-sdk/client-dynamodb"; +import * as keygen from "./keygen"; +import day from "dayjs"; +import { Application } from "@/types/app"; + +const client = new DynamoDBClient(); + +// TODO: replace me +const TABLE = process.env.DYNAMODB_TABLE_SERVICE_KEYS! + +export default async function sync(application: Application) { + const { + id, + signature_live, + signature_test, + allowed_origins, + allowed_targets, + } = application; + + // TODO: we are using application.id as the billing group, but we should + // use the subscription id instead (in the future) + const billing_group = id; + + const data = { + // TODO: get plan data + // for now, fixing it as "2023.t1", which is the pro plan + plan: "2023.t1", + allowedOrigins: allowed_origins, + allowedTargets: allowed_targets, + }; + + // TODO: get subscription data. to calculate expires_at + // for now, we are givving all keys a 3 year expiry + const expires_at = day().add(3, "year").unix(); + + // test + sync_record(signature_test, "test", String(billing_group), expires_at, data); + + // live + sync_record(signature_live, "live", String(billing_group), expires_at, data); +} + +async function sync_record( + signature: string, + type: "live" | "test", + billing_group: string, + expires_at: number, + data: { + plan: string; + allowedOrigins: string[] | null; + allowedTargets: string[] | null; + } +) { + const record: KeyInfo = { + key: keygen.sign(signature, type).token, + plan: data.plan, + config: { + allowed_origins: data.allowedOrigins, + allowed_targets: data.allowedTargets, + }, + active: true, + billing_group, + expires_at, + synced_at: day().unix(), + }; + + // write to db + // return client + // .put({ + // TableName: process.env.DYNAMODB_TABLE_SERVICE_KEYS!, + // Item: record, + // }) + // .promise(); + const command = new PutItemCommand({ + TableName: TABLE, + Item: { + key: { + S: record.key, + }, + plan: { + S: record.plan, + }, + config: { + M: { + allowed_origins: { + SS: record.config.allowed_origins ?? [], + }, + allowed_targets: { + SS: record.config.allowed_targets ?? [], + }, + }, + }, + active: { + BOOL: record.active, + }, + billing_group: { + S: record.billing_group, + }, + expires_at: { + N: String(record.expires_at), + }, + synced_at: { + N: String(record.synced_at), + }, + }, + }); + + return await client.send(command); +} + + +export async function activate(id: string, active: boolean) { + // update "active" field of the key + // write to db + + const command = new UpdateItemCommand({ + TableName: TABLE, + Key: { + id: { + S: id, + }, + }, + UpdateExpression: "set active = :active", + ExpressionAttributeValues: { + ":active": { + BOOL: active, + }, + }, + }); + + return await client.send(command); +} + +// shared db +export interface KeyInfo { + key: string; + plan: string; + config: { + allowed_origins: string[] | null; + allowed_targets: string[] | null; + }; + active: boolean; + billing_group: string; + expires_at: number; + synced_at: number; +} diff --git a/web/middleware.ts b/web/middleware.ts new file mode 100644 index 0000000..9859031 --- /dev/null +++ b/web/middleware.ts @@ -0,0 +1,68 @@ +import { createServerClient, type CookieOptions } from '@supabase/ssr' +import { NextResponse, type NextRequest } from 'next/server' +import { authMiddleware } from './lib/auth/middleware' + +export async function middleware(request: NextRequest) { + + if (request.nextUrl.pathname.startsWith('/applications')) { + const response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + + await supabase_session_middleware(request, response) + return await authMiddleware(request, response) + } + + const response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + + await supabase_session_middleware(request, response) + + return response +} + + +async function supabase_session_middleware(request: NextRequest, response: NextResponse) { + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + get(name: string) { + return request.cookies.get(name)?.value + }, + set(name: string, value: string, options: CookieOptions) { + request.cookies.set({ + name, + value, + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + }, + remove(name: string, options: CookieOptions) { + request.cookies.set({ + name, + value: '', + ...options, + }) + response = NextResponse.next({ + request: { + headers: request.headers, + }, + }) + }, + }, + } + ) + + await supabase.auth.getSession() +} \ No newline at end of file diff --git a/web/package.json b/web/package.json index 6c169e0..e7fb52e 100644 --- a/web/package.json +++ b/web/package.json @@ -9,14 +9,22 @@ "lint": "next lint" }, "dependencies": { + "@aws-sdk/client-dynamodb": "^3.506.0", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/themes": "^2.0.1", + "@react-email/components": "0.0.14", + "@supabase/ssr": "^0.0.10", + "@supabase/supabase-js": "^2.39.0", "@use-gesture/react": "^10.3.0", + "@visx/gradient": "^3.3.0", + "@visx/mock-data": "^3.3.0", + "@visx/shape": "^3.5.0", "add": "^2.0.6", "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.10", "framer-motion": "^10.16.4", "next": "14.0.1", "prismjs": "^1.29.0", @@ -24,10 +32,13 @@ "react-dom": "^18", "react-hot-toast": "^2.4.1", "react-select": "^5.7.7", - "react-syntax-highlighter": "^15.5.0" + "react-syntax-highlighter": "^15.5.0", + "redis": "^4.6.12", + "resend": "^3.1.0", + "stripe": "^14.8.0" }, "devDependencies": { - "@types/node": "^20", + "@types/node": "^20.11.16", "@types/react": "^18", "@types/react-dom": "^18", "@types/react-syntax-highlighter": "^15.5.9", @@ -35,7 +46,8 @@ "eslint": "^8", "eslint-config-next": "14.0.1", "postcss": "^8", + "supabase": "^1.115.5", "tailwindcss": "^3.3.0", - "typescript": "^5" + "typescript": "^5.3.3" } } diff --git a/web/pages/onboarding/payment-success.tsx b/web/pages/onboarding/payment-success.tsx index c050937..847213b 100644 --- a/web/pages/onboarding/payment-success.tsx +++ b/web/pages/onboarding/payment-success.tsx @@ -36,7 +36,7 @@ export default function PaymentSuccessPage({ currency: "USD", // }); - }, []); + }, [session]); const onNext = () => { setBusy(true); diff --git a/web/public/email-content/CORS.SH-black.svg b/web/public/email-content/CORS.SH-black.svg new file mode 100644 index 0000000..51ddadd --- /dev/null +++ b/web/public/email-content/CORS.SH-black.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/services/services.cors.sh/scripts/aes-256-cbc-creds.js b/web/scripts/aes-256-cbc-creds.js similarity index 100% rename from services/services.cors.sh/scripts/aes-256-cbc-creds.js rename to web/scripts/aes-256-cbc-creds.js diff --git a/web/supabase/index.ts b/web/supabase/index.ts new file mode 100644 index 0000000..e05be78 --- /dev/null +++ b/web/supabase/index.ts @@ -0,0 +1,6 @@ +import { createBrowserClient } from "@supabase/ssr"; + +export const supabase = createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! +); \ No newline at end of file diff --git a/web/tailwind.config.ts b/web/tailwind.config.ts index c7ead80..bb57b20 100644 --- a/web/tailwind.config.ts +++ b/web/tailwind.config.ts @@ -4,6 +4,7 @@ const config: Config = { content: [ './pages/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx,mdx}', + './console/**/*.{js,ts,jsx,tsx,mdx}', './app/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { diff --git a/web/tsconfig.json b/web/tsconfig.json index c714696..021b409 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -1,10 +1,14 @@ { "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, - "strict": true, + "strict": false, "noEmit": true, "esModuleInterop": true, "module": "esnext", @@ -19,9 +23,19 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "strictNullChecks": true }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } diff --git a/web/types/app.ts b/web/types/app.ts new file mode 100644 index 0000000..7096e62 --- /dev/null +++ b/web/types/app.ts @@ -0,0 +1,6 @@ +import { Database } from "./supabase"; + +export type Customer = Database["public"]["Tables"]["customers"]["Row"]; +export type OnboardingApplication = + Database["public"]["Tables"]["applications_onboarding"]["Row"]; +export type Application = Database["public"]["Tables"]["applications"]["Row"]; diff --git a/web/types/supabase.ts b/web/types/supabase.ts new file mode 100644 index 0000000..c514d73 --- /dev/null +++ b/web/types/supabase.ts @@ -0,0 +1,216 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[]; + +export interface Database { + public: { + Tables: { + applications: { + Row: { + allowed_origins: string[] | null; + allowed_targets: string[] | null; + archived_at: string | null; + created_at: string; + expires_at: string | null; + id: number; + name: string; + owner_id: number; + signature_live: string; + signature_test: string; + }; + Insert: { + allowed_origins?: string[] | null; + allowed_targets?: string[] | null; + archived_at?: string | null; + created_at?: string | null; + expires_at?: string | null; + id?: number; + name?: string | null; + owner_id: number; + signature_live?: string | null; + signature_test?: string | null; + }; + Update: { + allowed_origins?: string[] | null; + allowed_targets?: string[] | null; + archived_at?: string | null; + created_at?: string | null; + expires_at?: string | null; + id?: number; + name?: string | null; + owner_id?: number; + signature_live?: string | null; + signature_test?: string | null; + }; + Relationships: [ + { + foreignKeyName: "applications_owner_id_fkey"; + columns: ["owner_id"]; + isOneToOne: false; + referencedRelation: "customers"; + referencedColumns: ["id"]; + } + ]; + }; + applications_onboarding: { + Row: { + allowed_origins: string[] | null; + created_at: string | null; + email: string | null; + email_sent_at: string[] | null; + expires_at: string; + id: number; + key: string | null; + name: string | null; + price_id: string | null; + updated_at: string | null; + }; + Insert: { + allowed_origins?: string[] | null; + created_at?: string | null; + email?: string | null; + email_sent_at?: string[] | null; + expires_at: string; + id?: number; + key?: string | null; + name?: string | null; + price_id?: string | null; + updated_at?: string | null; + }; + Update: { + allowed_origins?: string[] | null; + created_at?: string | null; + email?: string | null; + email_sent_at?: string[] | null; + expires_at?: string; + id?: number; + key?: string | null; + name?: string | null; + price_id?: string | null; + updated_at?: string | null; + }; + Relationships: []; + }; + customers: { + Row: { + created_at: string | null; + email: string | null; + email_verified: boolean | null; + id: number; + stripe_id: string | null; + }; + Insert: { + created_at?: string | null; + email?: string | null; + email_verified?: boolean | null; + id?: number; + stripe_id?: string | null; + }; + Update: { + created_at?: string | null; + email?: string | null; + email_verified?: boolean | null; + id?: number; + stripe_id?: string | null; + }; + Relationships: []; + }; + }; + Views: { + [_ in never]: never; + }; + Functions: { + [_ in never]: never; + }; + Enums: { + [_ in never]: never; + }; + CompositeTypes: { + [_ in never]: never; + }; + }; +} + +export type Tables< + PublicTableNameOrOptions extends + | keyof (Database["public"]["Tables"] & Database["public"]["Views"]) + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] & + Database[PublicTableNameOrOptions["schema"]]["Views"]) + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? (Database[PublicTableNameOrOptions["schema"]]["Tables"] & + Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends { + Row: infer R; + } + ? R + : never + : PublicTableNameOrOptions extends keyof (Database["public"]["Tables"] & + Database["public"]["Views"]) + ? (Database["public"]["Tables"] & + Database["public"]["Views"])[PublicTableNameOrOptions] extends { + Row: infer R; + } + ? R + : never + : never; + +export type TablesInsert< + PublicTableNameOrOptions extends + | keyof Database["public"]["Tables"] + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Insert: infer I; + } + ? I + : never + : PublicTableNameOrOptions extends keyof Database["public"]["Tables"] + ? Database["public"]["Tables"][PublicTableNameOrOptions] extends { + Insert: infer I; + } + ? I + : never + : never; + +export type TablesUpdate< + PublicTableNameOrOptions extends + | keyof Database["public"]["Tables"] + | { schema: keyof Database }, + TableName extends PublicTableNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"] + : never = never +> = PublicTableNameOrOptions extends { schema: keyof Database } + ? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Update: infer U; + } + ? U + : never + : PublicTableNameOrOptions extends keyof Database["public"]["Tables"] + ? Database["public"]["Tables"][PublicTableNameOrOptions] extends { + Update: infer U; + } + ? U + : never + : never; + +export type Enums< + PublicEnumNameOrOptions extends + | keyof Database["public"]["Enums"] + | { schema: keyof Database }, + EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database } + ? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"] + : never = never +> = PublicEnumNameOrOptions extends { schema: keyof Database } + ? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName] + : PublicEnumNameOrOptions extends keyof Database["public"]["Enums"] + ? Database["public"]["Enums"][PublicEnumNameOrOptions] + : never; diff --git a/yarn.lock b/yarn.lock index 120e2c9..8f1c0e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -46,6 +46,499 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/ie11-detection@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" + integrity sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/sha256-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" + integrity sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/sha256-js" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" + integrity sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/supports-web-crypto@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" + integrity sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/util@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" + integrity sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/client-dynamodb@^3.506.0": + version "3.506.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-dynamodb/-/client-dynamodb-3.506.0.tgz#f6ec6976518ee8a0a3c975116700aef7663bb1d7" + integrity sha512-UaTSXZ/s7QLY0W6Mp0ZuoiuKQD2tEg6riAgVk5LWurWc20yuBT78n+lq8moKai3YfUbHsxqe1sJuC5mWEd18Xw== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.504.0" + "@aws-sdk/core" "3.496.0" + "@aws-sdk/credential-provider-node" "3.504.0" + "@aws-sdk/middleware-endpoint-discovery" "3.502.0" + "@aws-sdk/middleware-host-header" "3.502.0" + "@aws-sdk/middleware-logger" "3.502.0" + "@aws-sdk/middleware-recursion-detection" "3.502.0" + "@aws-sdk/middleware-user-agent" "3.502.0" + "@aws-sdk/region-config-resolver" "3.502.0" + "@aws-sdk/types" "3.502.0" + "@aws-sdk/util-endpoints" "3.502.0" + "@aws-sdk/util-user-agent-browser" "3.502.0" + "@aws-sdk/util-user-agent-node" "3.502.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.1" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + "@smithy/util-waiter" "^2.1.1" + tslib "^2.5.0" + uuid "^8.3.2" + +"@aws-sdk/client-sso-oidc@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.504.0.tgz#78ed1e921fcda039e8525a92bf5760e8bd0091a8" + integrity sha512-ODA33/nm2srhV08EW0KZAP577UgV0qjyr7Xp2yEo8MXWL4ZqQZprk1c+QKBhjr4Djesrm0VPmSD/np0mtYP68A== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.504.0" + "@aws-sdk/core" "3.496.0" + "@aws-sdk/middleware-host-header" "3.502.0" + "@aws-sdk/middleware-logger" "3.502.0" + "@aws-sdk/middleware-recursion-detection" "3.502.0" + "@aws-sdk/middleware-signing" "3.502.0" + "@aws-sdk/middleware-user-agent" "3.502.0" + "@aws-sdk/region-config-resolver" "3.502.0" + "@aws-sdk/types" "3.502.0" + "@aws-sdk/util-endpoints" "3.502.0" + "@aws-sdk/util-user-agent-browser" "3.502.0" + "@aws-sdk/util-user-agent-node" "3.502.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.1" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.502.0.tgz#8cf21d8f52a5bef65bf7b458051b3f61f7db822c" + integrity sha512-OZAYal1+PQgUUtWiHhRayDtX0OD+XpXHKAhjYgEIPbyhQaCMp3/Bq1xDX151piWXvXqXLJHFKb8DUEqzwGO9QA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.496.0" + "@aws-sdk/middleware-host-header" "3.502.0" + "@aws-sdk/middleware-logger" "3.502.0" + "@aws-sdk/middleware-recursion-detection" "3.502.0" + "@aws-sdk/middleware-user-agent" "3.502.0" + "@aws-sdk/region-config-resolver" "3.502.0" + "@aws-sdk/types" "3.502.0" + "@aws-sdk/util-endpoints" "3.502.0" + "@aws-sdk/util-user-agent-browser" "3.502.0" + "@aws-sdk/util-user-agent-node" "3.502.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.1" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.504.0.tgz#78a0beaf988ad2647d79c7157083dfd55953f41e" + integrity sha512-IESs8FkL7B/uY+ml4wgoRkrr6xYo4PizcNw6JX17eveq1gRBCPKeGMjE6HTDOcIYZZ8rqz/UeuH3JD4UhrMOnA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/core" "3.496.0" + "@aws-sdk/middleware-host-header" "3.502.0" + "@aws-sdk/middleware-logger" "3.502.0" + "@aws-sdk/middleware-recursion-detection" "3.502.0" + "@aws-sdk/middleware-user-agent" "3.502.0" + "@aws-sdk/region-config-resolver" "3.502.0" + "@aws-sdk/types" "3.502.0" + "@aws-sdk/util-endpoints" "3.502.0" + "@aws-sdk/util-user-agent-browser" "3.502.0" + "@aws-sdk/util-user-agent-node" "3.502.0" + "@smithy/config-resolver" "^2.1.1" + "@smithy/core" "^1.3.1" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/hash-node" "^2.1.1" + "@smithy/invalid-dependency" "^2.1.1" + "@smithy/middleware-content-length" "^2.1.1" + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-body-length-browser" "^2.1.1" + "@smithy/util-body-length-node" "^2.2.1" + "@smithy/util-defaults-mode-browser" "^2.1.1" + "@smithy/util-defaults-mode-node" "^2.1.1" + "@smithy/util-endpoints" "^1.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/core@3.496.0": + version "3.496.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.496.0.tgz#ec1394753b6b2f6e38aea593e30b2db5c7390969" + integrity sha512-yT+ug7Cw/3eJi7x2es0+46x12+cIJm5Xv+GPWsrTFD1TKgqO/VPEgfDtHFagDNbFmjNQA65Ygc/kEdIX9ICX/A== + dependencies: + "@smithy/core" "^1.3.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.502.0.tgz#800e63b2b9d90b078a120d474d5a3b1ec5b48514" + integrity sha512-KIB8Ae1Z7domMU/jU4KiIgK4tmYgvuXlhR54ehwlVHxnEoFPoPuGHFZU7oFn79jhhSLUFQ1lRYMxP0cEwb7XeQ== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-http@3.503.1": + version "3.503.1" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.503.1.tgz#e882a4b740c9193650053033b3001b03ca4b12c8" + integrity sha512-rTdlFFGoPPFMF2YjtlfRuSgKI+XsF49u7d98255hySwhsbwd3Xp+utTTPquxP+CwDxMHbDlI7NxDzFiFdsoZug== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-stream" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.504.0.tgz#d463dae3a309c1e9181811f27c484fd9bfa6821f" + integrity sha512-ODICLXfr8xTUd3wweprH32Ge41yuBa+u3j0JUcLdTUO1N9ldczSMdo8zOPlP0z4doqD3xbnqMkjNQWgN/Q+5oQ== + dependencies: + "@aws-sdk/client-sts" "3.504.0" + "@aws-sdk/credential-provider-env" "3.502.0" + "@aws-sdk/credential-provider-process" "3.502.0" + "@aws-sdk/credential-provider-sso" "3.504.0" + "@aws-sdk/credential-provider-web-identity" "3.504.0" + "@aws-sdk/types" "3.502.0" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.504.0.tgz#c6014f56dd59be295114290164e00375d33f2952" + integrity sha512-6+V5hIh+tILmUjf2ZQWQINR3atxQVgH/bFrGdSR/sHSp/tEgw3m0xWL3IRslWU1e4/GtXrfg1iYnMknXy68Ikw== + dependencies: + "@aws-sdk/credential-provider-env" "3.502.0" + "@aws-sdk/credential-provider-http" "3.503.1" + "@aws-sdk/credential-provider-ini" "3.504.0" + "@aws-sdk/credential-provider-process" "3.502.0" + "@aws-sdk/credential-provider-sso" "3.504.0" + "@aws-sdk/credential-provider-web-identity" "3.504.0" + "@aws-sdk/types" "3.502.0" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.502.0.tgz#6c41d8845a1c7073491a064c158363de04640381" + integrity sha512-fJJowOjQ4infYQX0E1J3xFVlmuwEYJAFk0Mo1qwafWmEthsBJs+6BR2RiWDELHKrSK35u4Pf3fu3RkYuCtmQFw== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.504.0.tgz#ad036805e8677f6a53b24aa82991596aa11ac605" + integrity sha512-4MgH2or2SjPzaxM08DCW+BjaX4DSsEGJlicHKmz6fh+w9JmLh750oXcTnbvgUeVz075jcs6qTKjvUcsdGM/t8Q== + dependencies: + "@aws-sdk/client-sso" "3.502.0" + "@aws-sdk/token-providers" "3.504.0" + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.504.0.tgz#53de7dee538ecaeec534e369bca76c546b8f4cc5" + integrity sha512-L1ljCvGpIEFdJk087ijf2ohg7HBclOeB1UgBxUBBzf4iPRZTQzd2chGaKj0hm2VVaXz7nglswJeURH5PFcS5oA== + dependencies: + "@aws-sdk/client-sts" "3.504.0" + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/endpoint-cache@3.495.0": + version "3.495.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/endpoint-cache/-/endpoint-cache-3.495.0.tgz#f1c59a4315e61394ebd18b3dda211485c07ee7f8" + integrity sha512-XCDrpiS50WaPzPzp7FwsChPHtX9PQQUU4nRzcn2N7IkUtpcFCUx8m1PAZe086VQr6hrbdeE4Z4j8hUPNwVdJGQ== + dependencies: + mnemonist "0.38.3" + tslib "^2.5.0" + +"@aws-sdk/middleware-endpoint-discovery@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.502.0.tgz#cce2e260f97568ca88d4c6fe492ada91a116f9d7" + integrity sha512-DQBbyelebBshYPTb5ah25sAdMTQKYBUYE0If66sXHNUQAdUg28z076kE4E8p8RxyfGHqESN2MrqfIjQpEnjcqg== + dependencies: + "@aws-sdk/endpoint-cache" "3.495.0" + "@aws-sdk/types" "3.502.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.502.0.tgz#2651fb3509990271c89eb50133fb17cb8ae435f6" + integrity sha512-EjnG0GTYXT/wJBmm5/mTjDcAkzU8L7wQjOzd3FTXuTCNNyvAvwrszbOj5FlarEw5XJBbQiZtBs+I5u9+zy560w== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.502.0.tgz#558cefdd233779f15687957f9f07497199b22d72" + integrity sha512-FDyv6K4nCoHxbjLGS2H8ex8I0KDIiu4FJgVRPs140ZJy6gE5Pwxzv6YTzZGLMrnqcIs9gh065Lf6DjwMelZqaw== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.502.0.tgz#c22e2c0c1d551e58c788264687324bb7186af2cc" + integrity sha512-hvbyGJbxeuezxOu8VfFmcV4ql1hKXLxHTe5FNYfEBat2KaZXVhc1Hg+4TvB06/53p+E8J99Afmumkqbxs2esUA== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.502.0.tgz#48b3503147eecb1a53a63633462de353668f635a" + integrity sha512-4hF08vSzJ7L6sB+393gOFj3s2N6nLusYS0XrMW6wYNFU10IDdbf8Z3TZ7gysDJJHEGQPmTAesPEDBsasGWcMxg== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/signature-v4" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.502.0.tgz#dd740f150d6f3110cf5b08fedf361d202f899c93" + integrity sha512-TxbBZbRiXPH0AUxegqiNd9aM9zNSbfjtBs5MEfcBsweeT/B2O7K1EjP9+CkB8Xmk/5FLKhAKLr19b1TNoE27rw== + dependencies: + "@aws-sdk/types" "3.502.0" + "@aws-sdk/util-endpoints" "3.502.0" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/region-config-resolver@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.502.0.tgz#c18a04060879eb03c47c05b05fc296119ee073ba" + integrity sha512-mxmsX2AGgnSM+Sah7mcQCIneOsJQNiLX0COwEttuf8eO+6cLMAZvVudH3BnWTfea4/A9nuri9DLCqBvEmPrilg== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.504.0": + version "3.504.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.504.0.tgz#f7f60b1152458e7094529ea3f3ced6ce92eece9f" + integrity sha512-YIJWWsZi2ClUiILS1uh5L6VjmCUSTI6KKMuL9DkGjYqJ0aI6M8bd8fT9Wm7QmXCyjcArTgr/Atkhia4T7oKvzQ== + dependencies: + "@aws-sdk/client-sso-oidc" "3.504.0" + "@aws-sdk/types" "3.502.0" + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/types@3.502.0", "@aws-sdk/types@^3.222.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.502.0.tgz#c23dda4df7fdbe32642d4f5ab23516f455fb6aba" + integrity sha512-M0DSPYe/gXhwD2QHgoukaZv5oDxhW3FfvYIrJptyqUq3OnPJBcDbihHjrE0PBtfh/9kgMZT60/fQ2NVFANfa2g== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/util-endpoints@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.502.0.tgz#aee818c0c53dfedfd49599fc260cd880faea5e82" + integrity sha512-6LKFlJPp2J24r1Kpfoz5ESQn+1v5fEjDB3mtUKRdpwarhm3syu7HbKlHCF3KbcCOyahobvLvhoedT78rJFEeeg== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/types" "^2.9.1" + "@smithy/util-endpoints" "^1.1.1" + tslib "^2.5.0" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.495.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz#9034fd8db77991b28ed20e067acdd53e8b8f824b" + integrity sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-browser@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.502.0.tgz#87b42abff6944052c78a84981637ac21859dd016" + integrity sha512-v8gKyCs2obXoIkLETAeEQ3AM+QmhHhst9xbM1cJtKUGsRlVIak/XyyD+kVE6kmMm1cjfudHpHKABWk9apQcIZQ== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/types" "^2.9.1" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.502.0": + version "3.502.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.502.0.tgz#04ac4d0371d4f243f12ddc23b42ca8ceb27dfad9" + integrity sha512-9RjxpkGZKbTdl96tIJvAo+vZoz4P/cQh36SBUt9xfRfW0BtsaLyvSrvlR5wyUYhvRcC12Axqh/8JtnAPq//+Vw== + dependencies: + "@aws-sdk/types" "3.502.0" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.4", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.4.tgz#03ae5af150be94392cb5c7ccd97db5a19a5da6aa" @@ -1909,6 +2402,18 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@isaacs/string-locale-compare@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" @@ -2413,6 +2918,16 @@ dependencies: "@octokit/openapi-types" "^12.11.0" +"@one-ini/wasm@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" + integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.11" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.11.tgz#7c2268cedaa0644d677e8c4f377bc8fb304f714a" @@ -3909,6 +4424,171 @@ "@radix-ui/react-visually-hidden" "^1.0.3" classnames "^2.3.2" +"@react-email/body@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/body/-/body-0.0.7.tgz#f2ac3cef62c6ef5805f77e3cc3f907af3ff1e718" + integrity sha512-vjJ5P1MUNWV0KNivaEWA6MGj/I3c764qQJMsKjCHlW6mkFJ4SXbm2OlQFtKAb++Bj8LDqBlnE6oW77bWcMc0NA== + +"@react-email/button@0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@react-email/button/-/button-0.0.13.tgz#9e148356d62393030d4efbe9a16b918165ea8466" + integrity sha512-e/y8u2odJ8fF83B+wvL2FXzVcbQSUh2Cn2JH2Ez4L6AuPELsh8s2JYo081IDsXc16IyFiYpObn0blOt7s/qp8g== + +"@react-email/code-block@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@react-email/code-block/-/code-block-0.0.2.tgz#4873ba652b85eefb648036d9cd7da5dc551e8d89" + integrity sha512-bQApEmpsvIcVYXdPCXhJB9CGCyShhn/c1JdctE/6R1uIosLbWt40evvVfp2X9STdi02Dhsjxw/AcGuQE6zGZqw== + dependencies: + prismjs "1.29.0" + +"@react-email/code-inline@0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@react-email/code-inline/-/code-inline-0.0.1.tgz#b6d826630757ce2b4bcf66595daa4b29e72b3384" + integrity sha512-SeZKTB9Q4+TUafzeUm/8tGK3dFgywUHb1od/BrAiJCo/im65aT+oJfggJLjK2jCdSsus8odcK2kReeM3/FCNTQ== + +"@react-email/column@0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@react-email/column/-/column-0.0.9.tgz#3107f50216c0cfed0a42b0386e3ccfdac0ec12e6" + integrity sha512-1ekqNBgmbS6m97/sUFOnVvQtLYljUWamw8Y44VId95v6SjiJ4ca+hMcdOteHWBH67xkRofEOWTvqDRea5SBV8w== + +"@react-email/components@0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@react-email/components/-/components-0.0.14.tgz#9f6c06be7e9319e9fa51bb682c8f12103a9c7623" + integrity sha512-t/sNj0R9Mx9Sx5degPQcSBeWotNs7eUwiv72KN8v6fxaf87XlnMo0CPcKI/1by2DHZr5S0258ZQOO7vEFrbcLw== + dependencies: + "@react-email/body" "0.0.7" + "@react-email/button" "0.0.13" + "@react-email/code-block" "0.0.2" + "@react-email/code-inline" "0.0.1" + "@react-email/column" "0.0.9" + "@react-email/container" "0.0.11" + "@react-email/font" "0.0.5" + "@react-email/head" "0.0.7" + "@react-email/heading" "0.0.11" + "@react-email/hr" "0.0.7" + "@react-email/html" "0.0.7" + "@react-email/img" "0.0.7" + "@react-email/link" "0.0.7" + "@react-email/preview" "0.0.8" + "@react-email/render" "0.0.12" + "@react-email/row" "0.0.7" + "@react-email/section" "0.0.11" + "@react-email/tailwind" "0.0.14" + "@react-email/text" "0.0.7" + +"@react-email/container@0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@react-email/container/-/container-0.0.11.tgz#821d1546aaeb59765095d90de82ef5c8b92d9d6f" + integrity sha512-jzl/EHs0ClXIRFamfH+NR/cqv4GsJJscqRhdYtnWYuRAsWpKBM1muycrrPqIVhWvWi6sFHInWTt07jX+bDc3SQ== + +"@react-email/font@0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@react-email/font/-/font-0.0.5.tgz#8f991776bf2a56cc4ba23d1240ef418ac210768a" + integrity sha512-if/qKYmH3rJ2egQJoKbV8SfKCPavu+ikUq/naT/UkCr8Q0lkk309tRA0x7fXG/WeIrmcipjMzFRGTm2TxTecDw== + +"@react-email/head@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/head/-/head-0.0.7.tgz#94c9ef200467899503c903e13d0da94b6e10a8dc" + integrity sha512-IcXL4jc0H1qzAXJCD9ajcRFBQdbUHkjKJyiUeogpaYSVZSq6cVDWQuGaI23TA9k+pI2TFeQimogUFb3Kgeeudw== + +"@react-email/heading@0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@react-email/heading/-/heading-0.0.11.tgz#1a9ae35fd5644948594474f1a1668ad9d3f68036" + integrity sha512-EF5ZtRCxhHPw3m+8iibKKg0RAvAeHj1AP68sjU7s6+J+kvRgllr/E972Wi5Y8UvcIGossCvpX1WrSMDzeB4puA== + dependencies: + "@radix-ui/react-slot" "1.0.2" + +"@react-email/hr@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/hr/-/hr-0.0.7.tgz#ba32b8f06c969fc1ac360987e5fba0dbc2af1f45" + integrity sha512-8suK0M/deXHt0DBSeKhSC4bnCBCBm37xk6KJh9M0/FIKlvdltQBem52YUiuqVl1XLB87Y6v6tvspn3SZ9fuxEA== + +"@react-email/html@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/html/-/html-0.0.7.tgz#de9b758924d37f09801623782715359fea1d9db1" + integrity sha512-oy7OoRtoOKApVI/5Lz1OZptMKmMYJu9Xn6+lOmdBQchAuSdQtWJqxhrSj/iI/mm8HZWo6MZEQ6SFpfOuf8/P6Q== + +"@react-email/img@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/img/-/img-0.0.7.tgz#ad6bc3c22546c917add035faa3ebdecb2a6568c8" + integrity sha512-up9tM2/dJ24u/CFjcvioKbyGuPw1yeJg605QA7VkrygEhd0CoQEjjgumfugpJ+VJgIt4ZjT9xMVCK5QWTIWoaA== + +"@react-email/link@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/link/-/link-0.0.7.tgz#7670b5be4430f173a467423a5c79c2d0e261b70b" + integrity sha512-hXPChT3ZMyKnUSA60BLEMD2maEgyB2A37yg5bASbLMrXmsExHi6/IS1h2XiUPLDK4KqH5KFaFxi2cdNo1JOKwA== + +"@react-email/preview@0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@react-email/preview/-/preview-0.0.8.tgz#f09ca0525e49494450255abbd3a025df310a7bd3" + integrity sha512-Jm0KUYBZQd2w0s2QRMQy0zfHdo3Ns+9bYSE1OybjknlvhANirjuZw9E5KfWgdzO7PyrRtB1OBOQD8//Obc4uIQ== + +"@react-email/render@0.0.12": + version "0.0.12" + resolved "https://registry.yarnpkg.com/@react-email/render/-/render-0.0.12.tgz#66c3217ad2018545da2ba0537d8cfd32316e3da4" + integrity sha512-S8WRv/PqECEi6x0QJBj0asnAb5GFtJaHlnByxLETLkgJjc76cxMYDH4r9wdbuJ4sjkcbpwP3LPnVzwS+aIjT7g== + dependencies: + html-to-text "9.0.5" + js-beautify "^1.14.11" + react "18.2.0" + react-dom "18.2.0" + +"@react-email/row@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/row/-/row-0.0.7.tgz#a5d2653d7f3c443654e477b42641de62362304c3" + integrity sha512-h7pwrLVGk5CIx7Ai/oPxBgCCAGY7BEpCUQ7FCzi4+eThcs5IdjSwDPefLEkwaFS8KZc56UNwTAH92kNq5B7blg== + +"@react-email/section@0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@react-email/section/-/section-0.0.11.tgz#a20b8f8176eeed8cc455aed65e3a49fceb9a6f2f" + integrity sha512-3bZ/DuvX1julATI7oqYza6pOtWZgLJDBaa62LFFEvYjisyN+k6lrP2KOucPsDKu2DOkUzlQgK0FOm6VQJX+C0w== + +"@react-email/tailwind@0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@react-email/tailwind/-/tailwind-0.0.14.tgz#e4cccbf898c388970b6affe37e44a70be3d06f5e" + integrity sha512-SRRcm08zxrAR5XozaW0X+GAJlTJITakZe0UXBiFZDlSDBLwFMxjaGuQwccqNF0LxDnxmduxYB71mzEAqecgTZg== + dependencies: + react "18.2.0" + +"@react-email/text@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@react-email/text/-/text-0.0.7.tgz#5e0a93cb52c943ada389161220c6d31b55d4a28f" + integrity sha512-eHCx0mdllGcgK9X7wiLKjNZCBRfxRVNjD3NNYRmOc3Icbl8M9JHriJIfxBuGCmGg2UAORK5P3KmaLQ8b99/pbA== + +"@redis/bloom@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.2.0.tgz#d3fd6d3c0af3ef92f26767b56414a370c7b63b71" + integrity sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg== + +"@redis/client@1.5.13": + version "1.5.13" + resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.5.13.tgz#78786218fc1632ee4b5f7d73b8d456c95880e086" + integrity sha512-epkUM9D0Sdmt93/8Ozk43PNjLi36RZzG+d/T1Gdu5AI8jvghonTeLYV69WVWdilvFo+PYxbP0TZ0saMvr6nscQ== + dependencies: + cluster-key-slot "1.1.2" + generic-pool "3.9.0" + yallist "4.0.0" + +"@redis/graph@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.1.1.tgz#8c10df2df7f7d02741866751764031a957a170ea" + integrity sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw== + +"@redis/json@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.6.tgz#b7a7725bbb907765d84c99d55eac3fcf772e180e" + integrity sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw== + +"@redis/search@1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.1.6.tgz#33bcdd791d9ed88ab6910243a355d85a7fedf756" + integrity sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw== + +"@redis/time-series@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.5.tgz#a6d70ef7a0e71e083ea09b967df0a0ed742bc6ad" + integrity sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg== + "@rushstack/eslint-patch@^1.3.3": version "1.5.1" resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz#5f1b518ec5fa54437c0b7c4a821546c64fed6922" @@ -3921,6 +4601,400 @@ dependencies: any-observable "^0.3.0" +"@selderee/plugin-htmlparser2@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz#d5b5e29a7ba6d3958a1972c7be16f4b2c188c517" + integrity sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ== + dependencies: + domhandler "^5.0.3" + selderee "^0.11.0" + +"@smithy/abort-controller@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.1.1.tgz#bb68596a7c8213c2ef259bc7fb0f0c118c67ea9d" + integrity sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/config-resolver@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.1.1.tgz#fc6b036084b98fd26a8ff01a5d7eb676e41749c7" + integrity sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + "@smithy/util-config-provider" "^2.2.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/core@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-1.3.1.tgz#ecedc564e68453b02c20db9e8435d59005c066d8" + integrity sha512-tf+NIu9FkOh312b6M9G4D68is4Xr7qptzaZGZUREELF8ysE1yLKphqt7nsomjKZVwW7WE5pDDex9idowNGRQ/Q== + dependencies: + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-retry" "^2.1.1" + "@smithy/middleware-serde" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/credential-provider-imds@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz#4805bf5e104718b959cf8699113fa9de6ddeeafa" + integrity sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + tslib "^2.5.0" + +"@smithy/eventstream-codec@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz#4405ab0f9c77d439c575560c4886e59ee17d6d38" + integrity sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@smithy/types" "^2.9.1" + "@smithy/util-hex-encoding" "^2.1.1" + tslib "^2.5.0" + +"@smithy/fetch-http-handler@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz#b4d73bbc1449f61234077d58c705b843a8587bf0" + integrity sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg== + dependencies: + "@smithy/protocol-http" "^3.1.1" + "@smithy/querystring-builder" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-base64" "^2.1.1" + tslib "^2.5.0" + +"@smithy/hash-node@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.1.1.tgz#0f8a22d97565ca948724f72267e4d3a2f33740a8" + integrity sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-buffer-from" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/invalid-dependency@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz#bd69fa24dd35e9bc65a160bd86becdf1399e4463" + integrity sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/is-array-buffer@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz#07b4c77ae67ed58a84400c76edd482271f9f957b" + integrity sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ== + dependencies: + tslib "^2.5.0" + +"@smithy/middleware-content-length@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz#df767de12d594bc5622009fb0fc8343522697d8c" + integrity sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g== + dependencies: + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/middleware-endpoint@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz#9e500df4d944741808e92018ccd2e948b598a49f" + integrity sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q== + dependencies: + "@smithy/middleware-serde" "^2.1.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/url-parser" "^2.1.1" + "@smithy/util-middleware" "^2.1.1" + tslib "^2.5.0" + +"@smithy/middleware-retry@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz#ddc749dd927f136714f76ca5a52dcfb0993ee162" + integrity sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/service-error-classification" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-retry" "^2.1.1" + tslib "^2.5.0" + uuid "^8.3.2" + +"@smithy/middleware-serde@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz#2c5750f76e276a5249720f6c3c24fac29abbee16" + integrity sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/middleware-stack@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz#67f992dc36e8a6861f881f80a81c1c30956a0396" + integrity sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/node-config-provider@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz#c440c7948d58d72f0e212aa1967aa12f0729defd" + integrity sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg== + dependencies: + "@smithy/property-provider" "^2.1.1" + "@smithy/shared-ini-file-loader" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/node-http-handler@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz#77d23279ff0a12cbe7cde93c5e7c0e86ad56dd20" + integrity sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA== + dependencies: + "@smithy/abort-controller" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/querystring-builder" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/property-provider@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.1.1.tgz#0f7ffc5e43829eaca5b2b5aae8554807a52b30f3" + integrity sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/protocol-http@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-3.1.1.tgz#eee522d0ed964a72b735d64925e07bcfb7a7806f" + integrity sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/querystring-builder@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz#b9693448ad3f8e0767d84cf5cae29f35514591fb" + integrity sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg== + dependencies: + "@smithy/types" "^2.9.1" + "@smithy/util-uri-escape" "^2.1.1" + tslib "^2.5.0" + +"@smithy/querystring-parser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz#a4282a66cc56844317dbff824e573f469bbfc032" + integrity sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/service-error-classification@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz#dd24e1ec529ae9ec8e87d8b15f0fc8f7e17f3d02" + integrity sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw== + dependencies: + "@smithy/types" "^2.9.1" + +"@smithy/shared-ini-file-loader@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz#a2e28b4d85f8a8262a84403fa2b74a086b3a7703" + integrity sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/signature-v4@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.1.1.tgz#6080171e3d694f40d3f553bbc236c5c433efd4d2" + integrity sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg== + dependencies: + "@smithy/eventstream-codec" "^2.1.1" + "@smithy/is-array-buffer" "^2.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-hex-encoding" "^2.1.1" + "@smithy/util-middleware" "^2.1.1" + "@smithy/util-uri-escape" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/smithy-client@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.3.1.tgz#0c3a4a0d3935c7ad2240cc23181f276705212b1f" + integrity sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA== + dependencies: + "@smithy/middleware-endpoint" "^2.4.1" + "@smithy/middleware-stack" "^2.1.1" + "@smithy/protocol-http" "^3.1.1" + "@smithy/types" "^2.9.1" + "@smithy/util-stream" "^2.1.1" + tslib "^2.5.0" + +"@smithy/types@^2.9.1": + version "2.9.1" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.9.1.tgz#ed04d4144eed3b8bd26d20fc85aae8d6e357ebb9" + integrity sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw== + dependencies: + tslib "^2.5.0" + +"@smithy/url-parser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.1.1.tgz#a30de227b6734650d740b6dff74d488b874e85e3" + integrity sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q== + dependencies: + "@smithy/querystring-parser" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-base64@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.1.1.tgz#af729085cc9d92ebd54a5d2c5d0aa5a0c31f83bf" + integrity sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g== + dependencies: + "@smithy/util-buffer-from" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-body-length-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz#1fc77072768013ae646415eedb9833cd252d055d" + integrity sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag== + dependencies: + tslib "^2.5.0" + +"@smithy/util-body-length-node@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz#a6f5c9911f1c3e23efb340d5ce7a590b62f2056e" + integrity sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-buffer-from@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz#f9346bf8b23c5ba6f6bdb61dd9db779441ba8d08" + integrity sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg== + dependencies: + "@smithy/is-array-buffer" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-config-provider@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz#aea0a80236d6cedaee60473802899cff4a8cc0ba" + integrity sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw== + dependencies: + tslib "^2.5.0" + +"@smithy/util-defaults-mode-browser@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz#be9ac82acee6ec4821b610e7187b0e147f0ba8ff" + integrity sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA== + dependencies: + "@smithy/property-provider" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + bowser "^2.11.0" + tslib "^2.5.0" + +"@smithy/util-defaults-mode-node@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.1.tgz#0910ee00aac3e8a08aac3e6ae8794e52f3efef02" + integrity sha512-tYVrc+w+jSBfBd267KDnvSGOh4NMz+wVH7v4CClDbkdPfnjvImBZsOURncT5jsFwR9KCuDyPoSZq4Pa6+eCUrA== + dependencies: + "@smithy/config-resolver" "^2.1.1" + "@smithy/credential-provider-imds" "^2.2.1" + "@smithy/node-config-provider" "^2.2.1" + "@smithy/property-provider" "^2.1.1" + "@smithy/smithy-client" "^2.3.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-endpoints@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz#45426dba6fb42282a0ad955600b2b3ba050d118f" + integrity sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw== + dependencies: + "@smithy/node-config-provider" "^2.2.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-hex-encoding@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz#978252b9fb242e0a59bae4ead491210688e0d15f" + integrity sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-middleware@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.1.1.tgz#903ba19bb17704f4b476fb9ade9bf9eb0174bc3d" + integrity sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA== + dependencies: + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-retry@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.1.1.tgz#f2d3566b6e5b841028c7240c852007d4037e49b2" + integrity sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA== + dependencies: + "@smithy/service-error-classification" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + +"@smithy/util-stream@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.1.1.tgz#3ae0e88c3a1a45899e29c1655d2e5a3865b6c0a6" + integrity sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ== + dependencies: + "@smithy/fetch-http-handler" "^2.4.1" + "@smithy/node-http-handler" "^2.3.1" + "@smithy/types" "^2.9.1" + "@smithy/util-base64" "^2.1.1" + "@smithy/util-buffer-from" "^2.1.1" + "@smithy/util-hex-encoding" "^2.1.1" + "@smithy/util-utf8" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-uri-escape@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz#7eedc93b73ecda68f12fb9cf92e9fa0fbbed4d83" + integrity sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw== + dependencies: + tslib "^2.5.0" + +"@smithy/util-utf8@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.1.1.tgz#690018dd28f47f014114497735e51417ea5900a6" + integrity sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A== + dependencies: + "@smithy/util-buffer-from" "^2.1.1" + tslib "^2.5.0" + +"@smithy/util-waiter@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-2.1.1.tgz#292d4d09cda7df38aba6ea2abd7d948e3f11bf2d" + integrity sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA== + dependencies: + "@smithy/abort-controller" "^2.1.1" + "@smithy/types" "^2.9.1" + tslib "^2.5.0" + "@stitches/react@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@stitches/react/-/react-1.2.8.tgz#954f8008be8d9c65c4e58efa0937f32388ce3a38" @@ -4782,6 +5856,71 @@ regenerator-runtime "^0.13.7" resolve-from "^5.0.0" +"@supabase/functions-js@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.1.5.tgz#ed1b85f499dfda21d40fe39b86ab923117cb572b" + integrity sha512-BNzC5XhCzzCaggJ8s53DP+WeHHGT/NfTsx2wUSSGKR2/ikLFQTBCDzMvGz/PxYMqRko/LwncQtKXGOYp1PkPaw== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/gotrue-js@^2.56.0": + version "2.60.0" + resolved "https://registry.yarnpkg.com/@supabase/gotrue-js/-/gotrue-js-2.60.0.tgz#6ec7e79c77ba410275c4bc7b6d78f9abdd039546" + integrity sha512-I9C8dmVZfZOfivBD64BcNzktJU89wIctor+CYguWYJ6m6lIi2iKtaKmJvBmKRMTL3AG7fnEoFPYgYq2XtjS59Q== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/node-fetch@^2.6.14": + version "2.6.15" + resolved "https://registry.yarnpkg.com/@supabase/node-fetch/-/node-fetch-2.6.15.tgz#731271430e276983191930816303c44159e7226c" + integrity sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ== + dependencies: + whatwg-url "^5.0.0" + +"@supabase/postgrest-js@^1.8.6": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.9.0.tgz#00dddbe8119f1ec2179057e563bb54f28e6e31e3" + integrity sha512-axP6cU69jDrLbfihJKQ6vU27tklD0gzb9idkMN363MtTXeJVt5DQNT3JnJ58JVNBdL74hgm26rAsFNvHk+tnSw== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/realtime-js@^2.8.4": + version "2.9.0" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.9.0.tgz#7c1ff41d674e06ab003cff1d43105c4ae93d8a56" + integrity sha512-e/SI+/eqFJorAKAgVAwKQ9hSDQSBp86Yh7XbQmfJJ90LEfpM52HlTfJt/03lcepRu6BmH5h1uYn1b4zta7ghdw== + dependencies: + "@supabase/node-fetch" "^2.6.14" + "@types/phoenix" "^1.5.4" + "@types/websocket" "^1.0.3" + ws "^8.14.2" + +"@supabase/ssr@^0.0.10": + version "0.0.10" + resolved "https://registry.yarnpkg.com/@supabase/ssr/-/ssr-0.0.10.tgz#b2595c7dab6cc37f51d1529118fab2df4510b3bf" + integrity sha512-eVs7+bNlff8Fd79x8K3Jbfpmf8P8QRA1Z6rUDN+fi4ReWvRBZyWOFfR6eqlsX6vTjvGgTiEqujFSkv2PYW5kbQ== + dependencies: + cookie "^0.5.0" + ramda "^0.29.0" + +"@supabase/storage-js@^2.5.4": + version "2.5.5" + resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.5.5.tgz#2958e2a2cec8440e605bb53bd36649288c4dfa01" + integrity sha512-OpLoDRjFwClwc2cjTJZG8XviTiQH4Ik8sCiMK5v7et0MDu2QlXjCAW3ljxJB5+z/KazdMOTnySi+hysxWUPu3w== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/supabase-js@^2.39.0": + version "2.39.0" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.39.0.tgz#08ac64b441bd9e1c7ff660b15219a8bf786daed8" + integrity sha512-cYfnwWRW5rYBbPT/BNIejtRT9ULdD9PnIExQV28PZpqcqm3PLwS4f3pY7WGB01Da63VYdvktZPKuYvreqsj/Zg== + dependencies: + "@supabase/functions-js" "^2.1.5" + "@supabase/gotrue-js" "^2.56.0" + "@supabase/node-fetch" "^2.6.14" + "@supabase/postgrest-js" "^1.8.6" + "@supabase/realtime-js" "^2.8.4" + "@supabase/storage-js" "^2.5.4" + "@swc/helpers@0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d" @@ -4820,6 +5959,84 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== +"@types/d3-array@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac" + integrity sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-color@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.0.tgz#6594da178ded6c7c3842f3cc0ac84b156f12f2d4" + integrity sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA== + +"@types/d3-delaunay@6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz#006b7bd838baec1511270cb900bf4fc377bbbf41" + integrity sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ== + +"@types/d3-format@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d" + integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg== + +"@types/d3-geo@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-interpolate@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc" + integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@^1", "@types/d3-path@^1.0.8": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.11.tgz#45420fee2d93387083b34eae4fe6d996edf482bc" + integrity sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw== + +"@types/d3-random@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.3.tgz#ef7889985851fc90285861cd7141c9e88fe7c4ff" + integrity sha512-Ghs4R3CcgJ3o6svszRzIH4b8PPYex/COo+rhhZjDAs+bVducXwjmVSi27WcDOaLLCBV2t3tfVH9bYXAL76IvQA== + +"@types/d3-scale@4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69" + integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA== + dependencies: + "@types/d3-time" "*" + +"@types/d3-shape@^1.3.1": + version "1.3.12" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.3.12.tgz#8f2f9f7a12e631ce6700d6d55b84795ce2c8b259" + integrity sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q== + dependencies: + "@types/d3-path" "^1" + +"@types/d3-time-format@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-2.1.0.tgz#011e0fb7937be34a9a8f580ae1e2f2f1336a8a22" + integrity sha512-/myT3I7EwlukNOX2xVdMzb8FRgNzRMpsZddwst9Ld/VFe6LyJyRp0s32l/V9XoUzk+Gqu56F/oGk6507+8BxrA== + +"@types/d3-time@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-time@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819" + integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg== + "@types/eslint-scope@^3.7.3": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" @@ -4846,6 +6063,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/geojson@*": + version "7946.0.13" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.13.tgz#e6e77ea9ecf36564980a861e24e62a095988775e" + integrity sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ== + "@types/glob@*": version "8.1.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" @@ -4915,7 +6137,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lodash@^4.14.167": +"@types/lodash@^4.14.167", "@types/lodash@^4.14.172": version "4.14.202" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== @@ -4945,18 +6167,32 @@ "@types/node" "*" form-data "^4.0.0" -"@types/node@*", "@types/node@^20": +"@types/node@*": version "20.9.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.3.tgz#e089e1634436f676ff299596c9531bd2b59fffc6" integrity sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw== dependencies: undici-types "~5.26.4" +"@types/node@>=8.1.0": + version "20.10.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198" + integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg== + dependencies: + undici-types "~5.26.4" + "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0": version "16.18.63" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.63.tgz#17703190b6f623cf2dfb4cc624b1db9b60b4c634" integrity sha512-Q2VSI/lVKza0Z5qeY/JrHcwi9fxzBktDvNHthr0TVA/D3yMdHDw9syggng+wJPlsBLgx4jPpOrcJ100wnpniTg== +"@types/node@^20.11.16": + version "20.11.16" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.16.tgz#4411f79411514eb8e2926f036c86c9f0e4ec6708" + integrity sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ== + dependencies: + undici-types "~5.26.4" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" @@ -4979,6 +6215,11 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== +"@types/phoenix@^1.5.4": + version "1.6.4" + resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.4.tgz#cceac93a827555473ad38057d1df7d06eef1ed71" + integrity sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA== + "@types/pretty-hrtime@^1.0.0": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#ee1bd8c9f7a01b3445786aad0ef23aba5f511a44" @@ -5092,6 +6333,13 @@ anymatch "^3.0.0" source-map "^0.6.0" +"@types/websocket@^1.0.3": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.10.tgz#804b1a02780da522f5742bc184a6d16a2eb78c7c" + integrity sha512-svjGZvPB7EzuYS94cI7a+qhwgGU1y89wUgjT6E2wVUfmAGIvRfT7obBvRtnhXCSsoMdlG4gBFGE7MfkIXZLoww== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -5173,6 +6421,89 @@ dependencies: "@use-gesture/core" "10.3.0" +"@visx/curve@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@visx/curve/-/curve-3.3.0.tgz#a5ed8f1511d404ef83c0b956ed5021088ac64b0e" + integrity sha512-G1l1rzGWwIs8ka3mBhO/gj8uYK6XdU/3bwRSoiZ+MockMahQFPog0bUkuVgPwwzPSJfsA/E5u53Y/DNesnHQxg== + dependencies: + "@types/d3-shape" "^1.3.1" + d3-shape "^1.0.6" + +"@visx/gradient@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@visx/gradient/-/gradient-3.3.0.tgz#c0d0a7435b78053742e61731dae22c7464cd342c" + integrity sha512-t3vqukahDQsJ64/fcm85woFm2XPpSPMBz92gFvaY4J8EJY3e6rFOg382v5Dm17fgNsLRKJA0Vqo7mUtDe2pWOw== + dependencies: + "@types/react" "*" + prop-types "^15.5.7" + +"@visx/group@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@visx/group/-/group-3.3.0.tgz#20c1b75c1ab31798c3c702b6f58c412c688a6373" + integrity sha512-yKepDKwJqlzvnvPS0yDuW13XNrYJE4xzT6xM7J++441nu6IybWWwextyap8ey+kU651cYDb+q1Oi6aHvQwyEyw== + dependencies: + "@types/react" "*" + classnames "^2.3.1" + prop-types "^15.6.2" + +"@visx/mock-data@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@visx/mock-data/-/mock-data-3.3.0.tgz#c9c08bb22b68adcc43da2968c61f998b26dccd95" + integrity sha512-yb5R/tAU8fjwRSc5VL1UPYbkD+BoYjXUorblE3/oDcSfFrOvpRMZzSaYCBbZ6jtllge3Ks6QVzwyUUj1/xweqQ== + dependencies: + "@types/d3-random" "^2.2.0" + d3-random "^2.2.2" + +"@visx/scale@3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/scale/-/scale-3.5.0.tgz#c3db3863bbdd24d44781104ef5ee4cdc8df6f11d" + integrity sha512-xo3zrXV2IZxrMq9Y9RUVJUpd93h3NO/r/y3GVi5F9AsbOzOhsLIbsPkunhO9mpUSR8LZ9TiumLEBrY+3frRBSg== + dependencies: + "@visx/vendor" "3.5.0" + +"@visx/shape@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/shape/-/shape-3.5.0.tgz#fa4bb7a9ed863360be541d75c434503246305e36" + integrity sha512-DP3t9jBQ7dSE3e6ptA1xO4QAIGxO55GrY/6P+S6YREuQGjZgq20TLYLAsiaoPEzFSS4tp0m12ZTPivWhU2VBTw== + dependencies: + "@types/d3-path" "^1.0.8" + "@types/d3-shape" "^1.3.1" + "@types/lodash" "^4.14.172" + "@types/react" "*" + "@visx/curve" "3.3.0" + "@visx/group" "3.3.0" + "@visx/scale" "3.5.0" + classnames "^2.3.1" + d3-path "^1.0.5" + d3-shape "^1.2.0" + lodash "^4.17.21" + prop-types "^15.5.10" + +"@visx/vendor@3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@visx/vendor/-/vendor-3.5.0.tgz#a9990382ba759b9c4049be303d65d2cb3ca034a8" + integrity sha512-yt3SEZRVmt36+APsCISSO9eSOtzQkBjt+QRxNRzcTWuzwMAaF3PHCCSe31++kkpgY9yFoF+Gfes1TBe5NlETiQ== + dependencies: + "@types/d3-array" "3.0.3" + "@types/d3-color" "3.1.0" + "@types/d3-delaunay" "6.0.1" + "@types/d3-format" "3.0.1" + "@types/d3-geo" "3.1.0" + "@types/d3-interpolate" "3.0.1" + "@types/d3-scale" "4.0.2" + "@types/d3-time" "3.0.0" + "@types/d3-time-format" "2.1.0" + d3-array "3.2.1" + d3-color "3.1.0" + d3-delaunay "6.0.2" + d3-format "3.1.0" + d3-geo "3.1.0" + d3-interpolate "3.0.1" + d3-scale "4.0.2" + d3-time "3.1.0" + d3-time-format "4.1.0" + internmap "2.0.3" + "@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": version "1.11.6" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" @@ -5454,6 +6785,11 @@ abbrev@^1.0.0, abbrev@~1.1.1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -5509,6 +6845,13 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" +agent-base@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + agentkeepalive@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" @@ -5604,6 +6947,11 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -5628,6 +6976,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansi-to-html@^0.6.11: version "0.6.15" resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" @@ -6201,6 +7554,16 @@ bin-links@^3.0.3: rimraf "^3.0.0" write-file-atomic "^4.0.0" +bin-links@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.3.tgz#9e4a3c5900830aee3d7f52178b65e01dcdde64a5" + integrity sha512-obsRaULtJurnfox/MDwgq6Yo9kzbv1CPTk/1/s7Z/61Lezc8IKkFCOXNeVLXz0456WRzBQmSsDWlai2tIhBsfA== + dependencies: + cmd-shim "^6.0.0" + npm-normalize-package-bin "^3.0.0" + read-cmd-shim "^4.0.0" + write-file-atomic "^5.0.0" + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -6256,6 +7619,11 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + boxen@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -6806,7 +8174,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.3.2: +classnames@^2.3.1, classnames@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== @@ -6898,6 +8266,11 @@ clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +cluster-key-slot@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + cmd-shim@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-5.0.0.tgz#8d0aaa1a6b0708630694c4dbde070ed94c707724" @@ -6905,6 +8278,11 @@ cmd-shim@^5.0.0: dependencies: mkdirp-infer-owner "^2.0.0" +cmd-shim@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.2.tgz#435fd9e5c95340e61715e19f90209ed6fcd9e0a4" + integrity sha512-+FFYbB0YLaAkhkcrjkyNLYDiOsFSfRjwjY19LXk/psmMx1z00xlCv7hhQoTGXXIKi+YXHL/iiFo8NqMVQX9nOw== + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -6972,6 +8350,11 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -7042,6 +8425,14 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" +config-chain@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -7084,7 +8475,7 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: +cookie@0.5.0, cookie@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== @@ -7312,6 +8703,93 @@ cyclist@^1.0.1: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.2.tgz#673b5f233bf34d8e602b949429f8171d9121bea3" integrity sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA== +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3": + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-array@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.1.tgz#39331ea706f5709417d31bbb6ec152e0328b39b3" + integrity sha512-gUY/qeHq/yNqqoCKNq4vtpFLdoCdvyNpWoC/KNjhGbhDuQpAM9sIQQKkXSNpXa9h5KySs/gzm7R88WkUutgwWQ== + dependencies: + internmap "1 - 2" + +"d3-color@1 - 3", d3-color@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-delaunay@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92" + integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ== + dependencies: + delaunator "5" + +"d3-format@1 - 3", d3-format@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.0.tgz#74fd54e1f4cebd5185ac2039217a98d39b0a4c0e" + integrity sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA== + dependencies: + d3-array "2.5.0 - 3" + +"d3-interpolate@1.2.0 - 3", d3-interpolate@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1, d3-path@^1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +d3-random@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-2.2.2.tgz#5eebd209ef4e45a2b362b019c1fb21c2c98cbb6e" + integrity sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw== + +d3-scale@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +d3-shape@^1.0.6, d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -7324,6 +8802,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + date-fns@^1.27.2: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" @@ -7334,6 +8817,11 @@ date-format@0.0.2: resolved "https://registry.yarnpkg.com/date-format/-/date-format-0.0.2.tgz#fafd448f72115ef1e2b739155ae92f2be6c28dd1" integrity sha512-M4obuJx8jU5T91lcbwi0+QPNVaWOY1DQYz5xUuKYWO93osVzB2ZPqyDUc5T+mDjbA1X8VOb4JDZ+8r2MrSOp7Q== +dayjs@^1.11.10: + version "1.11.10" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" + integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -7419,7 +8907,7 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.2.2: +deepmerge@^4.2.2, deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -7485,6 +8973,13 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +delaunator@5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" + integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw== + dependencies: + robust-predicates "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -7639,6 +9134,15 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -7649,7 +9153,7 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@^2.0.1, domelementtype@^2.2.0: +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== @@ -7661,6 +9165,13 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -7670,6 +9181,15 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -7698,6 +9218,11 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -7706,6 +9231,16 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +editorconfig@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-1.0.4.tgz#040c9a8e9a6c5288388b87c2db07028aa89f53a3" + integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q== + dependencies: + "@one-ini/wasm" "0.1.1" + commander "^10.0.0" + minimatch "9.0.1" + semver "^7.5.3" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -7842,6 +9377,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-ci@^5.0.2: version "5.5.0" resolved "https://registry.yarnpkg.com/env-ci/-/env-ci-5.5.0.tgz#43364e3554d261a586dec707bc32be81112b545f" @@ -8482,6 +10022,13 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -8508,6 +10055,14 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + fetch-retry@^5.0.2: version "5.0.6" resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56" @@ -8699,6 +10254,14 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -8759,6 +10322,13 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -8911,6 +10481,11 @@ gauge@^4.0.3: strip-ansi "^6.0.1" wide-align "^1.1.5" +generic-pool@3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" + integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== + gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -9053,6 +10628,17 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.3.3: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -9435,6 +11021,17 @@ html-tags@^3.1.0: resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== +html-to-text@9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-9.0.5.tgz#6149a0f618ae7a0db8085dca9bbf96d32bb8368d" + integrity sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg== + dependencies: + "@selderee/plugin-htmlparser2" "^0.11.0" + deepmerge "^4.3.1" + dom-serializer "^2.0.0" + htmlparser2 "^8.0.2" + selderee "^0.11.0" + html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" @@ -9465,6 +11062,16 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +htmlparser2@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + http-cache-semantics@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" @@ -9512,6 +11119,14 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -9630,6 +11245,11 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + ini@^3.0.0, ini@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.1.tgz#c76ec81007875bc44d544ff7a11a55d12294102d" @@ -9667,6 +11287,11 @@ internal-slot@^1.0.4, internal-slot@^1.0.5: hasown "^2.0.0" side-channel "^1.0.4" +"internmap@1 - 2", internmap@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + interpret@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" @@ -10231,6 +11856,15 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + java-properties@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/java-properties/-/java-properties-1.0.2.tgz#ccd1fa73907438a5b5c38982269d0e771fe78211" @@ -10313,6 +11947,16 @@ jiti@^1.19.1: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== +js-beautify@^1.14.11: + version "1.14.11" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.14.11.tgz#57b17e009549ac845bdc58eddf8e1862e311314e" + integrity sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw== + dependencies: + config-chain "^1.1.13" + editorconfig "^1.0.3" + glob "^10.3.3" + nopt "^7.2.0" + js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -10523,6 +12167,11 @@ lazy-universal-dotenv@^3.0.1: dotenv "^8.0.0" dotenv-expand "^5.1.0" +leac@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/leac/-/leac-0.6.0.tgz#dcf136e382e666bd2475f44a1096061b70dc0912" + integrity sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -10849,6 +12498,11 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +"lru-cache@^9.1.1 || ^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -11183,6 +12837,13 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== +minimatch@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -11197,6 +12858,13 @@ minimatch@^5.0.1, minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -11270,6 +12938,11 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -11323,6 +12996,13 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mnemonist@0.38.3: + version "0.38.3" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.3.tgz#35ec79c1c1f4357cfda2fe264659c2775ccd7d9d" + integrity sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw== + dependencies: + obliterator "^1.6.1" + moment@^2.18.1: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" @@ -11478,6 +13158,11 @@ node-dir@^0.1.10: dependencies: minimatch "^3.0.2" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" @@ -11490,6 +13175,15 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.2.10: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-gyp@^9.0.0, node-gyp@^9.1.0: version "9.4.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" @@ -11562,6 +13256,13 @@ nopt@^6.0.0: dependencies: abbrev "^1.0.0" +nopt@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" + integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + dependencies: + abbrev "^2.0.0" + normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -11647,6 +13348,11 @@ npm-normalize-package-bin@^2.0.0: resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== +npm-normalize-package-bin@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== + npm-package-arg@^9.0.0, npm-package-arg@^9.0.1, npm-package-arg@^9.1.0: version "9.1.2" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-9.1.2.tgz#fc8acecb00235f42270dda446f36926ddd9ac2bc" @@ -11960,6 +13666,11 @@ objectorarray@^1.0.5: resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== +obliterator@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-1.6.1.tgz#dea03e8ab821f6c4d96a299e17aef6a3af994ef3" + integrity sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -12244,6 +13955,14 @@ parse5@^6.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parseley@^0.12.0: + version "0.12.1" + resolved "https://registry.yarnpkg.com/parseley/-/parseley-0.12.1.tgz#4afd561d50215ebe259e3e7a853e62f600683aef" + integrity sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw== + dependencies: + leac "^0.6.0" + peberminta "^0.9.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -12309,6 +14028,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -12346,6 +14073,11 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +peberminta@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/peberminta/-/peberminta-0.9.0.tgz#8ec9bc0eb84b7d368126e71ce9033501dca2a352" + integrity sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -12599,7 +14331,7 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== -prismjs@^1.27.0, prismjs@^1.29.0: +prismjs@1.29.0, prismjs@^1.27.0, prismjs@^1.29.0: version "1.29.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== @@ -12693,7 +14425,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@^15.0.0, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -12709,6 +14441,11 @@ property-information@^5.0.0, property-information@^5.3.0: dependencies: xtend "^4.0.0" +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -12786,7 +14523,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.10.0, qs@^6.11.2: +qs@^6.10.0, qs@^6.11.0, qs@^6.11.2: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== @@ -12823,6 +14560,11 @@ ramda@^0.28.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97" integrity sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA== +ramda@^0.29.0: + version "0.29.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196" + integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -12882,7 +14624,7 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" -react-dom@^18: +react-dom@18.2.0, react-dom@^18: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== @@ -13045,7 +14787,7 @@ react-window@^1.8.6: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -react@^18: +react@18.2.0, react@^18: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== @@ -13064,6 +14806,11 @@ read-cmd-shim@^3.0.0: resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz#868c235ec59d1de2db69e11aec885bc095aea087" integrity sha512-kEmDUoYf/CDy8yZbLTmhB1X9kkjf9Q80PCNsDMb7ufrGd6zZSQA1+UyjrO+pZm5K/S4OXCWJeiIt1JA8kAsa6g== +read-cmd-shim@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" + integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== + read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz#323ca529630da82cb34b36cc0b996693c98c2b83" @@ -13189,6 +14936,18 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redis@^4.6.12: + version "4.6.12" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.6.12.tgz#b607c93e9b0dd09e641f837092e9a68cc6ac6570" + integrity sha512-41Xuuko6P4uH4VPe5nE3BqXHB7a9lkFL0J29AlxKaIfD6eWO8VO/5PDF9ad2oS+mswMsfFxaM5DlE3tnXT+P8Q== + dependencies: + "@redis/bloom" "1.2.0" + "@redis/client" "1.5.13" + "@redis/graph" "1.1.1" + "@redis/json" "1.0.6" + "@redis/search" "1.1.6" + "@redis/time-series" "1.0.5" + reflect.getprototypeof@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" @@ -13417,6 +15176,13 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +resend@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/resend/-/resend-3.1.0.tgz#3c167cd073f70944a34f77070e2a3c4ef56eb046" + integrity sha512-H+Ll0bAim1L1slAGzjPZlYAlWqihHAdCM14POqJ0AUgEPfwZQ3Eb6Z9HCO5Wsi3IDMHihPx+O77kzgprj5CchQ== + dependencies: + "@react-email/render" "0.0.12" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -13505,6 +15271,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +robust-predicates@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -13635,6 +15406,13 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +selderee@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.11.0.tgz#6af0c7983e073ad3e35787ffe20cefd9daf0ec8a" + integrity sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA== + dependencies: + parseley "^0.12.0" + "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -13810,6 +15588,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -14097,6 +15880,15 @@ string-argv@^0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -14106,15 +15898,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -14123,6 +15906,15 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.8: version "4.0.10" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" @@ -14197,6 +15989,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -14218,12 +16017,12 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: - ansi-regex "^5.0.1" + ansi-regex "^6.0.1" strip-bom@^2.0.0: version "2.0.0" @@ -14266,6 +16065,19 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +stripe@^14.8.0: + version "14.8.0" + resolved "https://registry.yarnpkg.com/stripe/-/stripe-14.8.0.tgz#2b72791ccb42f3a5c636bacbff00b88dc97a10dd" + integrity sha512-Qdecqk7lx095BE829NWxrG1+69NjPuHrpZqeR61i2KO00fpKkjMX9TYjwFU+WjQD6ZcNmCGOwNfnz5VnI5bjIg== + dependencies: + "@types/node" ">=8.1.0" + qs "^6.11.0" + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + style-loader@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" @@ -14306,6 +16118,16 @@ sucrase@^3.32.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" +supabase@^1.115.5: + version "1.115.5" + resolved "https://registry.yarnpkg.com/supabase/-/supabase-1.115.5.tgz#6ec81bcb168741c2fa4bb3a7a039f7f65ad00454" + integrity sha512-jAJ/d3Dge1/mV284RHBp6dkGLJCmdMO3FE6hnyn1S1Si3Bx4/EUD3zXtkkSNs4lAx6jcyibwh3iULm6n4yFzZA== + dependencies: + bin-links "^4.0.1" + https-proxy-agent "^7.0.2" + node-fetch "^3.2.10" + tar "6.2.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -14395,7 +16217,7 @@ tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: +tar@6.2.0, tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2: version "6.2.0" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73" integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ== @@ -14683,12 +16505,12 @@ tsconfig-paths@^3.14.2: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.11.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -14806,10 +16628,10 @@ typescript@^4.1.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -typescript@^5: - version "5.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.2.tgz#00d1c7c1c46928c5845c1ee8d0cc2791031d4c43" - integrity sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ== +typescript@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== uglify-js@^3.1.4: version "3.17.4" @@ -15255,6 +17077,11 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -15482,6 +17309,15 @@ worker-rpc@^0.1.0: dependencies: microevent.ts "~0.1.1" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" @@ -15490,14 +17326,14 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" wrappy@1: version "1.0.2" @@ -15522,7 +17358,15 @@ write-file-atomic@^4.0.0, write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^8.2.3: +write-file-atomic@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +ws@^8.14.2, ws@^8.2.3: version "8.14.2" resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== @@ -15554,16 +17398,16 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@4.0.0, yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"