diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8f325ad..363c83f 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -9,7 +9,7 @@
"request": "launch",
"runtimeArgs": [
"run",
- "dev",
+ "app:dev",
],
"runtimeExecutable": "yarn",
"skipFiles": [
diff --git a/components/Intro.tsx b/components/Intro.tsx
deleted file mode 100644
index 7638435..0000000
--- a/components/Intro.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Trans, useTranslation } from "next-i18next"
-import { LoginContext } from "../contexts/login"
-import { useDefinedContext } from "../utils/definedContext"
-import { InputSlug } from "./InputEventSlug"
-import { LoginButton } from "./LoginButton"
-import { LogoutLink } from "./LogoutLink"
-import { TelegramUser } from "./TelegramUser"
-
-
-export function Intro() {
- const {t} = useTranslation("common")
- const [login, _] = useDefinedContext(LoginContext)
-
- const loginMessage = login ? <>
-
- introTelegramLoggedIn(1: )
-
-
-
- > : <>
- {t("introTelegramLogin")}
- >
-
- const input = login ? <>
-
- {t("introCreateEvent")}
-
-
- > : <>
-
- >
-
- return <>
-
- {loginMessage}
-
- {input}
- >
-}
\ No newline at end of file
diff --git a/components/LoginButton.tsx b/components/LoginButton.tsx
deleted file mode 100644
index 54f1ee5..0000000
--- a/components/LoginButton.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as React from 'react';
-import {LoginContext} from "../contexts/login"
-import OriginalTelegramLoginButton from 'react-telegram-login'
-import { useDefinedContext } from '../utils/definedContext';
-
-export function LoginButton(props: any) {
- const [login, setLogin] = useDefinedContext(LoginContext)
-
- return (
-
-
-
- )
-}
\ No newline at end of file
diff --git a/components/LogoutLink.tsx b/components/LogoutLink.tsx
index 46f5269..eb39009 100644
--- a/components/LogoutLink.tsx
+++ b/components/LogoutLink.tsx
@@ -8,9 +8,11 @@ export function LogoutLink() {
return (
+ (
setLogin(null)}>
{t("introTelegramLogout")}
+ )
)
}
\ No newline at end of file
diff --git a/components/TelegramLoginButton.tsx b/components/TelegramLoginButton.tsx
new file mode 100644
index 0000000..1ec9dfb
--- /dev/null
+++ b/components/TelegramLoginButton.tsx
@@ -0,0 +1,14 @@
+import * as React from 'react';
+import { default as OriginalTelegramLoginButton } from 'react-telegram-login'
+
+
+export function TelegramLoginButton(props: any) {
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/components/TutorialTelegramLogin.tsx b/components/TutorialTelegramLogin.tsx
new file mode 100644
index 0000000..635fbb8
--- /dev/null
+++ b/components/TutorialTelegramLogin.tsx
@@ -0,0 +1,41 @@
+import { useTranslation } from "next-i18next"
+import { useCallback } from "react"
+import { LoginContext } from "../contexts/login"
+import { useDefinedContext } from "../utils/definedContext"
+import { TelegramLoginButton } from "./TelegramLoginButton"
+import * as Telegram from "../utils/telegram"
+import axios from "axios"
+
+
+export function TutorialTelegramLogin() {
+ const { t } = useTranslation("common")
+ const [login, setLogin] = useDefinedContext(LoginContext)
+
+ const onLogin = useCallback(
+ async (data: Telegram.LoginData) => {
+ console.debug("[Telegram] Logged in successfully, now forwarding to the server...")
+ const response = await axios.post("/api/login/telegram", data)
+ console.info(response)
+ },
+ []
+ )
+
+ if (!login) {
+ return <>
+
+ {t("introTelegramLogin")}
+
+
+ >
+ }
+ else {
+ return <>
+
+
+
+ >
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 304bfd6..fd4c8e1 100644
--- a/package.json
+++ b/package.json
@@ -3,26 +3,33 @@
"version": "0.1.0",
"private": true,
"scripts": {
- "dev": "next dev",
- "build": "next build",
- "start": "next start",
- "lint": "next lint"
+ "app:dev": "next dev",
+ "app:build": "next build",
+ "app:start": "next start",
+ "app:lint": "next lint",
+ "db:dev": "dotenv -e .env.local prisma db push --force-reset",
+ "db:generate": "dotenv -e .env.local prisma generate"
},
"dependencies": {
"@prisma/client": "3.14.0",
+ "axios": "^0.27.2",
"classnames": "^2.3.1",
+ "cors": "^2.8.5",
+ "crypto-random-string": "^5.0.0",
"next": "12.1.6",
"next-i18next": "^11.0.0",
"prisma": "^3.14.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-storage-hooks": "^4.0.1",
- "react-telegram-login": "^1.1.2"
+ "react-telegram-login": "^1.1.2",
+ "swr": "^1.3.0"
},
"devDependencies": {
"@types/node": "17.0.35",
"@types/react": "18.0.9",
"@types/react-dom": "18.0.4",
+ "dotenv-cli": "^5.1.0",
"eslint": "8.15.0",
"eslint-config-next": "12.1.6",
"typescript": "4.6.4"
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 1baa3a8..290d36b 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,7 +1,4 @@
import '../styles/globals.css'
-import '../styles/telegram.css'
-import '../styles/postcard.css'
-import "../styles/index.css"
import type { AppProps } from 'next/app'
import { LoginContext } from '../contexts/login'
import { useEffect, useState } from 'react'
diff --git a/pages/api/.gitignore b/pages/api/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/pages/api/login/telegram.ts b/pages/api/login/telegram.ts
new file mode 100644
index 0000000..d1f4d0e
--- /dev/null
+++ b/pages/api/login/telegram.ts
@@ -0,0 +1,79 @@
+import { NextApiRequest, NextApiResponse } from "next"
+import { prisma } from "../../../utils/prismaClient"
+import * as Telegram from "../../../utils/telegram"
+import {default as cryptoRandomString} from "crypto-random-string"
+
+
+
+export default function handler(req: NextApiRequest, res: NextApiResponse) {
+ switch(req.method) {
+ case "POST":
+ const token = process.env.TELEGRAM_TOKEN
+ const validity_ms = parseInt(process.env.FESTA_TOKEN_VALIDITY_MS!) // Wrong typing?
+ const now = new Date()
+
+ if(!token) {
+ return res.status(503).json({error: "`TELEGRAM_TOKEN` was not set up"})
+ }
+ if(!validity_ms) {
+ return res.status(503).json({error: "`FESTA_TOKEN_VALIDITY_MS` was not set up"})
+ }
+
+ try {
+ var lr: Telegram.LoginResponse = new Telegram.LoginResponse(req.body)
+ }
+ catch(_) {
+ return res.status(422).json({error: "Malformed data"})
+ }
+
+ if(!lr.isRecent()) {
+ // Not sure?
+ return res.status(408).json({error: "Telegram login data is not recent"})
+ }
+
+ if(!lr.isValid(token)) {
+ return res.status(401).json({error: "Telegram login data has been tampered"})
+ }
+
+ prisma.user.upsert({
+ where: {
+ id: lr.id,
+ },
+ update: {
+ id: lr.id,
+ firstName: lr.first_name,
+ lastName: lr.last_name,
+ username: lr.username,
+ photoUrl: lr.photo_url,
+ lastAuthDate: now,
+ },
+ create: {
+ id: lr.id,
+ firstName: lr.first_name,
+ lastName: lr.last_name,
+ username: lr.username,
+ photoUrl: lr.photo_url,
+ lastAuthDate: now,
+ }
+ })
+
+ const tokenString = cryptoRandomString({length: 16, type: "base64"})
+ const tokenExpiration = new Date(+ now + validity_ms)
+
+ prisma.token.create({
+ data: {
+ userId: lr.id,
+ token: tokenString,
+ expiresAt: tokenExpiration,
+ }
+ })
+
+ return res.status(200).json({
+ token: tokenString,
+ expiresAt: tokenExpiration.toISOString(),
+ })
+
+ default:
+ return res.status(405).json({error: "Invalid method"})
+ }
+}
\ No newline at end of file
diff --git a/pages/index.tsx b/pages/index.tsx
index 9c6c345..18a83d7 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -2,19 +2,42 @@ import type { NextPage, NextPageContext } from 'next'
import { useTranslation } from 'next-i18next'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { Intro } from '../components/Intro';
-import { LoginButton } from '../components/LoginButton';
+import { TutorialTelegramLogin } from '../components/TutorialTelegramLogin';
+import { LoginContext } from '../contexts/login';
+import { useDefinedContext } from '../utils/definedContext';
export async function getStaticProps(context: NextPageContext) {
- return {props: {
- ...(await serverSideTranslations(context.locale ?? "it-IT", ["common"]))
- }}
+ return {
+ props: {
+ ...(await serverSideTranslations(context.locale ?? "it-IT", ["common"]))
+ }
+ }
}
const Page: NextPage = () => {
- const {t} = useTranslation("common")
+ const { t } = useTranslation("common")
+ const [login, setLogin] = useDefinedContext(LoginContext)
+
+ if (!login) {
+ return (
+
+
+
+ {t("siteTitle")}
+
+
+ {t("siteSubtitle")}
+
+
+
+
+
+
+ )
+ }
return (
-
+
{t("siteTitle")}
@@ -23,10 +46,7 @@ const Page: NextPage = () => {
{t("siteSubtitle")}
-
-
-
-
+
)
}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index ee9d092..b70584f 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -40,7 +40,14 @@ model User {
username String?
photoUrl String?
lastAuthDate DateTime
- hash String
+ tokens Token[]
+}
+
+model Token {
+ userId BigInt
+ user User @relation(fields: [userId], references: [id])
+ token String @id
+ expiresAt DateTime
}
/// A partecipant is a person who may or may not partecipate to the event.
diff --git a/public/locales/it-IT/common.json b/public/locales/it-IT/common.json
index 9e26dfe..a8ed247 100644
--- a/public/locales/it-IT/common.json
+++ b/public/locales/it-IT/common.json
@@ -1 +1,9 @@
-{}
\ No newline at end of file
+{
+ "siteTitle": "Festa",
+ "siteSubtitle": "Organizza con facilità il tuo evento!",
+ "introTelegramLogin": "Per prima cosa, effettua il login con Telegram.",
+ "introTelegramLoggedIn": "Sei connesso come <1/>!",
+ "introTelegramLogout": "Non sei tu?",
+ "introCreateEvent": "Dai un nome al tuo primo evento:",
+ "introCreateEventSlugPlaceholder": "nome-evento-2022"
+}
diff --git a/public/locales/it-IT/common.json.disabled b/public/locales/it-IT/common.json.disabled
deleted file mode 100644
index f1e29c3..0000000
--- a/public/locales/it-IT/common.json.disabled
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "siteTitle": "Festa",
- "siteSubtitle": "Organizza il tuo evento ora!",
- "introTelegramLogin": "Effettua il login con Telegram per iniziare a creare il tuo evento.",
- "introTelegramLoggedIn": "Sei connesso come <1/>!",
- "introTelegramLogout": "Non sei tu?",
- "introCreateEvent": ""
-}
\ No newline at end of file
diff --git a/styles/globals.css b/styles/globals.css
index 2606d1a..0647813 100644
--- a/styles/globals.css
+++ b/styles/globals.css
@@ -1,49 +1,24 @@
-@media (prefers-color-scheme: light) {
- body {
- --background: #fafafa;
- --foreground: black;
- --border: darkgray;
-
- --anchor: #4444ff;
- --anchor-visited: #aa44ff;
- --anchor-active: #ff4444;
-
- --positive: #008800;
- --negative: #880000;
- }
+* {
+ box-sizing: border-box;
}
-@media (prefers-color-scheme: dark) {
- body {
- --background: #050505;
- --foreground: white;
- --border: darkgray;
-
- --anchor: #8888ff;
- --anchor-visited: #aa88ff;
- --anchor-active: #ff8888;
-
- --positive: #88ff88;
- --negative: #ff8888;
- }
+*::selection {
+ background-color: var(--selection);
+ color: var(--foreground);
+ text-shadow: none;
}
-
body {
padding: 0;
margin: 0;
background-color: var(--background);
- font-family: sans-serif;
color: var(--foreground);
+ font-family: sans-serif;
text-shadow: 1px 1px 1px var(--background);
}
-* {
- box-sizing: border-box;
-}
-
h1, h2, h3, h4, h5, h6 {
margin: 0;
text-shadow: 2px 2px 2px var(--background);
@@ -66,7 +41,7 @@ input, button {
margin: 2px 4px;
color: var(--foreground);
- background-color: var(--background);
+ background-color: var(--interactable);
border-width: 2px;
border-color: var(--border);
@@ -103,4 +78,9 @@ input[type="submit"]:active, button:active {
.input-negative {
border-color: var(--negative);
color: var(--negative);
-}
\ No newline at end of file
+}
+
+@import "index.css";
+@import "postcard.css";
+@import "telegram.css";
+@import "variables.css";
\ No newline at end of file
diff --git a/styles/index.css b/styles/index.css
index acad757..da15a28 100644
--- a/styles/index.css
+++ b/styles/index.css
@@ -1,4 +1,4 @@
-.index {
+.page-index {
display: flex;
flex-direction: column;
@@ -10,21 +10,21 @@
}
@media only screen and (max-width: 639px) {
- .index h1 {
+ .page-index h1 {
font-size: 5rem;
}
- .index h2 {
+ .page-index h2 {
font-size: 1.5rem;
}
}
@media only screen and (min-width: 640px) {
- .index h1 {
+ .page-index h1 {
font-size: 10rem;
}
- .index h2 {
+ .page-index h2 {
font-size: 2.5rem;
}
}
\ No newline at end of file
diff --git a/styles/telegram.css b/styles/telegram.css
index 44f91bc..0baa5fe 100644
--- a/styles/telegram.css
+++ b/styles/telegram.css
@@ -1,28 +1,3 @@
-/* Taken from the Telegram widget button */
.container-btn-telegram > div {
height: 40px;
}
-
-.btn-telegram {
- display: inline-block;
- vertical-align: top;
- font-weight: 500;
- background-color: #54a9eb;
- text-overflow: ellipsis;
- overflow: hidden;
- margin: 0;
- border: none;
- color: #fff;
- cursor: pointer;
-
- font-size: 16px;
- line-height: 20px;
- padding: 9px 21px 11px;
- border-radius: 20px;
-}
-
-.avatar-telegram-inline {
- height: 1em;
- border-radius: 20px;
- margin-right: 3px;
-}
diff --git a/styles/variables.css b/styles/variables.css
new file mode 100644
index 0000000..6145ef1
--- /dev/null
+++ b/styles/variables.css
@@ -0,0 +1,33 @@
+/* Light theme / unsupported */
+ body {
+ --background: #fafafa;
+ --foreground: black;
+ --border: gray;
+ --interactable: #fafafab5;
+ --selection: #7777ff;
+
+ --anchor: #4444ff;
+ --anchor-visited: #aa44ff;
+ --anchor-active: #ff4444;
+
+ --positive: #008800;
+ --negative: #880000;
+ }
+
+/* Dark theme */
+@media (prefers-color-scheme: dark) {
+ body {
+ --background: #050505;
+ --foreground: white;
+ --border: gray;
+ --interactable: #050505b5;
+ --selection: #3333dd;
+
+ --anchor: #8888ff;
+ --anchor-visited: #aa88ff;
+ --anchor-active: #ff8888;
+
+ --positive: #88ff88;
+ --negative: #ff8888;
+ }
+}
diff --git a/utils/definedContext.tsx b/utils/definedContext.ts
similarity index 100%
rename from utils/definedContext.tsx
rename to utils/definedContext.ts
diff --git a/utils/prismaClient.ts b/utils/prismaClient.ts
new file mode 100644
index 0000000..47a110b
--- /dev/null
+++ b/utils/prismaClient.ts
@@ -0,0 +1,3 @@
+import { PrismaClient } from "@prisma/client";
+
+export const prisma = new PrismaClient()
diff --git a/utils/stateContext.tsx b/utils/stateContext.ts
similarity index 100%
rename from utils/stateContext.tsx
rename to utils/stateContext.ts
diff --git a/utils/telegram.ts b/utils/telegram.ts
index 3436082..d0aad04 100644
--- a/utils/telegram.ts
+++ b/utils/telegram.ts
@@ -74,6 +74,11 @@ export class LoginResponse implements LoginData {
* @param queryObj The query string object, from `context.query`.
*/
constructor(ld: LoginData) {
+ if(!ld.id) throw new Error("Missing `id`")
+ if(!ld.first_name) throw new Error("Missing `first_name`")
+ if(!ld.auth_date) throw new Error("Missing `auth_date`")
+ if(!ld.hash) throw new Error("Missing `hash`")
+
this.id = ld.id
this.first_name = ld.first_name
this.last_name = ld.last_name
diff --git a/yarn.lock b/yarn.lock
index 016377b..c381969 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -335,11 +335,24 @@ ast-types-flow@^0.0.7:
resolved "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
axe-core@^4.3.5:
version "4.4.2"
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c"
integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==
+axios@^0.27.2:
+ version "0.27.2"
+ resolved "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
+ integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
+ dependencies:
+ follow-redirects "^1.14.9"
+ form-data "^4.0.0"
+
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
@@ -408,6 +421,13 @@ color-name@~1.1.4:
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -423,7 +443,15 @@ core-js@^3:
resolved "https://registry.npmjs.org/core-js/-/core-js-3.22.7.tgz#8d6c37f630f6139b8732d10f2c114c3f1d00024f"
integrity sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg==
-cross-spawn@^7.0.2:
+cors@^2.8.5:
+ version "2.8.5"
+ resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
+ integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
+ dependencies:
+ object-assign "^4"
+ vary "^1"
+
+cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -432,6 +460,13 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
+crypto-random-string@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-5.0.0.tgz#12b4ca8ba936c36d757b65b71a7d85a69a02c18a"
+ integrity sha512-KWjTXWwxFd6a94m5CdRGW/t82Tr8DoBc9dNnPCAbFI1EBweN6v1tv8y4Y1m7ndkp/nkIBRxUxAzpaBnR2k3bcQ==
+ dependencies:
+ type-fest "^2.12.2"
+
csstype@^3.0.2:
version "3.1.0"
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
@@ -476,6 +511,11 @@ define-properties@^1.1.3, define-properties@^1.1.4:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@@ -497,6 +537,26 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
+dotenv-cli@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-5.1.0.tgz#0d2942b089082da0157f9b26bd6c5c4dd51ef48e"
+ integrity sha512-NoEZAlKo9WVrG0b3i9mBxdD6INdDuGqdgR74t68t8084QcI077/1MnPerRW1odl+9uULhcdnQp2U0pYVppKHOA==
+ dependencies:
+ cross-spawn "^7.0.3"
+ dotenv "^16.0.0"
+ dotenv-expand "^8.0.1"
+ minimist "^1.2.5"
+
+dotenv-expand@^8.0.1:
+ version "8.0.3"
+ resolved "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-8.0.3.tgz#29016757455bcc748469c83a19b36aaf2b83dd6e"
+ integrity sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==
+
+dotenv@^16.0.0:
+ version "16.0.1"
+ resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d"
+ integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==
+
emoji-regex@^9.2.2:
version "9.2.2"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
@@ -822,6 +882,20 @@ flatted@^3.1.0:
resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
+follow-redirects@^1.14.9:
+ version "1.15.1"
+ resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
+ integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -1234,6 +1308,18 @@ micromatch@^4.0.4:
braces "^3.0.2"
picomatch "^2.3.1"
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -1241,7 +1327,7 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
dependencies:
brace-expansion "^1.1.7"
-minimist@^1.2.0, minimist@^1.2.6:
+minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
version "1.2.6"
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
@@ -1307,7 +1393,7 @@ next@12.1.6:
"@next/swc-win32-ia32-msvc" "12.1.6"
"@next/swc-win32-x64-msvc" "12.1.6"
-object-assign@^4.1.1:
+object-assign@^4, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -1713,6 +1799,11 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+swr@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
+ integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
+
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@@ -1759,6 +1850,11 @@ type-fest@^0.20.2:
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+type-fest@^2.12.2:
+ version "2.13.0"
+ resolved "https://registry.npmjs.org/type-fest/-/type-fest-2.13.0.tgz#d1ecee38af29eb2e863b22299a3d68ef30d2abfb"
+ integrity sha512-lPfAm42MxE4/456+QyIaaVBAwgpJb6xZ8PRu09utnhPdWwcyj9vgy6Sq0Z5yNbJ21EdxB5dRU/Qg8bsyAMtlcw==
+
typescript@4.6.4:
version "4.6.4"
resolved "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9"
@@ -1786,6 +1882,11 @@ v8-compile-cache@^2.0.3:
resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+vary@^1:
+ version "1.1.2"
+ resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+
void-elements@3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"