diff --git a/apps/pay/app/[username]/layout.tsx b/apps/pay/app/[username]/layout.tsx new file mode 100644 index 00000000000..ad7840a6fcd --- /dev/null +++ b/apps/pay/app/[username]/layout.tsx @@ -0,0 +1,15 @@ +import React from "react" + +import AppLayout from "@/components/Layouts/AppLayout" + +export default function UserNameLayout({ + children, + params, +}: { + children: React.ReactNode + params: { + username: string + } +}) { + return {children} +} diff --git a/apps/pay/pages/[username].tsx b/apps/pay/app/[username]/page.tsx similarity index 78% rename from apps/pay/pages/[username].tsx rename to apps/pay/app/[username]/page.tsx index b7038a8be28..0ec545b93ec 100644 --- a/apps/pay/pages/[username].tsx +++ b/apps/pay/app/[username]/page.tsx @@ -1,5 +1,5 @@ +"use client" import Link from "next/link" -import { useRouter } from "next/router" import React from "react" import Container from "react-bootstrap/Container" import Image from "react-bootstrap/Image" @@ -8,15 +8,18 @@ import Head from "next/head" import { gql } from "@apollo/client" -import ParsePayment from "../components/ParsePOSPayment" -import PinToHomescreen from "../components/PinToHomescreen" +import { useSearchParams } from "next/navigation" -import CurrencyDropdown from "../components/Currency/currency-dropdown" +import ParsePayment from "../../components/ParsePOSPayment" +import PinToHomescreen from "../../components/PinToHomescreen" -import { useAccountDefaultWalletsQuery } from "../lib/graphql/generated" +import CurrencyDropdown from "../../components/Currency/currency-dropdown" -import reducer, { ACTIONS } from "./_reducer" -import styles from "./_user.module.css" +import { useAccountDefaultWalletsQuery } from "../../lib/graphql/generated" + +import reducer, { ACTIONS } from "../_reducer" + +import styles from "../_user.module.css" gql` query accountDefaultWallets($username: Username!) { @@ -28,11 +31,18 @@ gql` } ` -function ReceivePayment() { - const router = useRouter() - const { username, memo, display } = router.query - const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) - const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) +type ReceivePaymentProps = { + params: { + username: string + } +} + +function ReceivePayment({ params }: ReceivePaymentProps) { + const searchParams = useSearchParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} + + const { memo, display } = query + const { username } = params let accountUsername: string if (!username) { @@ -81,7 +91,7 @@ function ReceivePayment() { return ( <> - {router.query.username ? ( + {username ? ( { localStorage.setItem("display", newDisplayCurrency) - router.push( - { - query: { ...router.query, display: newDisplayCurrency }, - }, - undefined, - { shallow: true }, + window.history.pushState( + {}, + "", + `${window.location.pathname}?${new URLSearchParams({ + ...query, + display: newDisplayCurrency, + }).toString()}`, ) + setTimeout(() => { - // hard reload to re-calculate currency - // in a future PR we can manage state globally for selected display currency + // Hard reload to re-calculate currency window.location.reload() }, 100) }} @@ -157,6 +168,7 @@ function ReceivePayment() { dispatch={dispatch} defaultWalletCurrency={data?.accountDefaultWallet.walletCurrency} walletId={data?.accountDefaultWallet.id} + username={accountUsername} /> )} diff --git a/apps/pay/pages/[username]/print.tsx b/apps/pay/app/[username]/print/page.tsx similarity index 96% rename from apps/pay/pages/[username]/print.tsx rename to apps/pay/app/[username]/print/page.tsx index cfb742a49fe..265a6a849d5 100644 --- a/apps/pay/pages/[username]/print.tsx +++ b/apps/pay/app/[username]/print/page.tsx @@ -1,18 +1,22 @@ -import Row from "react-bootstrap/Row" +"use client" import Col from "react-bootstrap/Col" +import Row from "react-bootstrap/Row" import Card from "react-bootstrap/Card" import Container from "react-bootstrap/Container" import ReactToPrint from "react-to-print" import { bech32 } from "bech32" import { QRCode } from "react-qrcode-logo" import { useRef } from "react" -import { useRouter } from "next/router" -export default function Print() { +export default function Print({ + params, +}: { + params: { + username: string + } +}) { + const { username } = params const componentRef = useRef(null) - - const router = useRouter() - const username = router.query.username as string const url = new URL(window.location.href) const unencodedLnurl = `${url.protocol}//${url.host}/.well-known/lnurlp/${username}` const lnurl = bech32.encode( diff --git a/apps/pay/pages/_reducer.tsx b/apps/pay/app/_reducer.tsx similarity index 100% rename from apps/pay/pages/_reducer.tsx rename to apps/pay/app/_reducer.tsx diff --git a/apps/pay/pages/_user.module.css b/apps/pay/app/_user.module.css similarity index 100% rename from apps/pay/pages/_user.module.css rename to apps/pay/app/_user.module.css diff --git a/apps/pay/pages/index.css b/apps/pay/app/globals.css similarity index 87% rename from apps/pay/pages/index.css rename to apps/pay/app/globals.css index 56826b7c711..3a62b27ad1f 100644 --- a/apps/pay/pages/index.css +++ b/apps/pay/app/globals.css @@ -1,17 +1,13 @@ -@import url("https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@200;300;400;600;700&display=swap"); +@tailwind base; +@tailwind components; +@tailwind utilities; body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", - "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; -} - .error { color: red; margin: 20px auto; diff --git a/apps/pay/pages/_app.tsx b/apps/pay/app/layout.tsx similarity index 52% rename from apps/pay/pages/_app.tsx rename to apps/pay/app/layout.tsx index 51564264b18..4c8cf83a532 100644 --- a/apps/pay/pages/_app.tsx +++ b/apps/pay/app/layout.tsx @@ -1,29 +1,28 @@ -// Disable no-unassigned-import rule because we are importing css files -// eslint-disable-next-line -import "bootstrap/dist/css/bootstrap.min.css" -// eslint-disable-next-line -import "./index.css" -import Script from "next/script" -import { NextPage } from "next" -import dynamic from "next/dynamic" +import type { Metadata } from "next" +import { Inter_Tight } from "next/font/google" + +// eslint-disable-next-line import/no-unassigned-import +import "./globals.css" + +// eslint-disable-next-line import/no-unassigned-import +import "bootstrap/dist/css/bootstrap.css" + import Head from "next/head" -import { useRouter } from "next/router" +import Script from "next/script" + +import { ApolloWrapper } from "@/components/apollo-wrapper" +import { APP_DESCRIPTION } from "@/config/config" -import AppLayout from "../components/Layouts/AppLayout" -import { APP_DESCRIPTION } from "../config/config" +const inter = Inter_Tight({ subsets: ["latin"] }) -const GraphQLProvider = dynamic(() => import("../lib/graphql"), { ssr: false }) +export const metadata: Metadata = { + title: "Blink Cash Register", + description: "Blink official lightning network node", +} -export default function Layout({ - Component, - pageProps, -}: { - Component: NextPage - pageProps: Record -}) { - const { username } = useRouter().query +export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - <> + @@ -44,11 +43,9 @@ export default function Layout({ gtag('config', 'UA-181044262-1'); `} - - - - - - + + {children} + + ) } diff --git a/apps/pay/pages/index.tsx b/apps/pay/app/page.tsx similarity index 91% rename from apps/pay/pages/index.tsx rename to apps/pay/app/page.tsx index 72aa16c44a0..7a0de975edc 100644 --- a/apps/pay/pages/index.tsx +++ b/apps/pay/app/page.tsx @@ -1,4 +1,5 @@ -import React from "react" +"use client" +import React, { useEffect } from "react" import Card from "react-bootstrap/Card" import Col from "react-bootstrap/Col" import Container from "react-bootstrap/Container" @@ -7,7 +8,7 @@ import ListGroup from "react-bootstrap/ListGroup" import Row from "react-bootstrap/Row" import { gql, useQuery } from "@apollo/client" -import { useRouter } from "next/router" +import { useRouter } from "next/navigation" import CurrencyDropdown from "../components/Currency/currency-dropdown" import { getClientSideGqlConfig } from "../config/config" @@ -25,24 +26,22 @@ function Home() { ? `https://mempool.space/signet/lightning/node/` : `https://mempool.space/lightning/node/` const { loading, error, data } = useQuery(GET_NODE_STATS) - const [selectedDisplayCurrency, setSelectedDisplayCurrency] = React.useState( - localStorage.getItem("display") ?? "USD", - ) + const [selectedDisplayCurrency, setSelectedDisplayCurrency] = + React.useState("USD") + + useEffect(() => { + const displayCurrency = localStorage.getItem("display") + if (displayCurrency) { + setSelectedDisplayCurrency(displayCurrency) + } + }, []) const router = useRouter() const [username, setUsername] = React.useState("") const handleSubmit = (event: React.FormEvent) => { event.preventDefault() - - router.push( - { - pathname: username, - query: { display: selectedDisplayCurrency }, - }, - undefined, - { shallow: true }, - ) + router.push(`${username}?display=${selectedDisplayCurrency}`, { scroll: true }) } return ( diff --git a/apps/pay/pages/setuppwa/index.tsx b/apps/pay/app/setuppwa/page.tsx similarity index 77% rename from apps/pay/pages/setuppwa/index.tsx rename to apps/pay/app/setuppwa/page.tsx index 35011cd29d3..b64559467cd 100644 --- a/apps/pay/pages/setuppwa/index.tsx +++ b/apps/pay/app/setuppwa/page.tsx @@ -1,15 +1,38 @@ -import { useRouter } from "next/router" -import React from "react" +"use client" +import { useRouter } from "next/navigation" +import React, { useEffect } from "react" import CurrencyDropdown from "../../components/Currency/currency-dropdown" const SetupPwa = () => { const router = useRouter() const [username, setUsername] = React.useState("") - const username_from_local = localStorage.getItem("username") - const display_currency_from_local = localStorage.getItem("display") + + let username_from_local: string | null = null + let display_currency_from_local: string | null = null + + useEffect(() => { + username_from_local = localStorage.getItem("username") + display_currency_from_local = localStorage.getItem("display") + }, []) + const [selectedDisplayCurrency, setSelectedDisplayCurrency] = React.useState("USD") + React.useEffect(() => { + if (username_from_local) { + window.history.pushState( + {}, + "", + `${username_from_local}??display=${display_currency_from_local}`, + ) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [username_from_local]) + + if (!username_from_local || !display_currency_from_local) { + return + } + const handleSubmit = (event: React.FormEvent) => { event.preventDefault() @@ -21,30 +44,9 @@ const SetupPwa = () => { localStorage.setItem("display", selectedDisplayCurrency) } - router.push( - { - pathname: `${username}`, - query: { display: selectedDisplayCurrency }, - }, - undefined, - { shallow: true }, - ) + router.push(`${username}?display=${selectedDisplayCurrency}`) } - React.useEffect(() => { - if (username_from_local) { - router.push( - { - pathname: `${username_from_local}`, - query: { display: display_currency_from_local }, - }, - undefined, - { shallow: true }, - ) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [username_from_local]) - if (!username_from_local) { return (
diff --git a/apps/pay/components/Currency/currency-dropdown.tsx b/apps/pay/components/Currency/currency-dropdown.tsx index edaaa6056d3..c66b6129edf 100644 --- a/apps/pay/components/Currency/currency-dropdown.tsx +++ b/apps/pay/components/Currency/currency-dropdown.tsx @@ -1,6 +1,7 @@ +"use client" import React, { useEffect } from "react" -import { useRouter } from "next/router" +import { useSearchParams } from "next/navigation" import { useCurrencyListQuery } from "../../lib/graphql/generated" @@ -15,18 +16,20 @@ export default function CurrencyDropdown({ style?: React.CSSProperties showOnlyFlag?: boolean }) { - const router = useRouter() + const searchParams = useSearchParams() + const display = searchParams?.get("display") + const { data: currencyData } = useCurrencyListQuery() const [selectedDisplayCurrency, setSelectedDisplayCurrency] = React.useState( - router.query.display && typeof router.query.display === "string" - ? router.query.display + display && typeof display === "string" + ? display : localStorage.getItem("display") ?? "USD", ) const [isDropDownOpen, setIsDropDownOpen] = React.useState(false) useEffect(() => { - if (router.query?.display && typeof router.query.display === "string") { - setSelectedDisplayCurrency(router.query.display) + if (display && typeof display === "string") { + setSelectedDisplayCurrency(display) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) diff --git a/apps/pay/components/Layouts/AppLayout.tsx b/apps/pay/components/Layouts/AppLayout.tsx index 50191d023d3..8b04fcb56eb 100644 --- a/apps/pay/components/Layouts/AppLayout.tsx +++ b/apps/pay/components/Layouts/AppLayout.tsx @@ -1,6 +1,8 @@ -import copy from "copy-to-clipboard" +"use client" + import Link from "next/link" -import { useRouter } from "next/router" +import copy from "copy-to-clipboard" +import { useRouter, useSearchParams } from "next/navigation" import React from "react" import { Image, OverlayTrigger, Tooltip } from "react-bootstrap" @@ -15,7 +17,8 @@ type Props = { const AppLayout = ({ children, username }: Props) => { const router = useRouter() - const { memo } = useRouter().query + const searchParams = useSearchParams() + const memo = searchParams?.get("memo") const [openSideBar, setOpenSideBar] = React.useState(false) const [copied, setCopied] = React.useState(false) const lightningAddr = username @@ -40,15 +43,9 @@ const AppLayout = ({ children, username }: Props) => { const navigateHome = () => { let pathname = "/" if (username) pathname = `/${username}` - router.push( - { - pathname, - }, - undefined, - { shallow: true }, - ) + window.history.pushState({}, "", `${pathname}`) setTimeout(() => { - router.reload() // Force a reload after a short delay to allow location href to update + router.refresh() // Force a reload after a short delay to allow location href to update }, 200) } diff --git a/apps/pay/components/Memo/index.tsx b/apps/pay/components/Memo/index.tsx index 8c9bd4379bc..6df45c2ce5a 100644 --- a/apps/pay/components/Memo/index.tsx +++ b/apps/pay/components/Memo/index.tsx @@ -1,8 +1,9 @@ -import { useRouter } from "next/router" import React from "react" import { Modal } from "react-bootstrap" -import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer" +import { useSearchParams, useParams } from "next/navigation" + +import { ACTIONS, ACTION_TYPE } from "../../app/_reducer" import styles from "./memo.module.css" @@ -12,35 +13,32 @@ interface Props { } const Memo = ({ state, dispatch }: Props) => { - const router = useRouter() - const { username, amount, sats, unit, memo, display } = router.query + const searchParams = useSearchParams() + const { username } = useParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} + + const { amount, sats, unit, memo, display } = query const [openModal, setOpenModal] = React.useState(false) const [note, setNote] = React.useState(memo?.toString() || "") const handleSetMemo = () => { if (unit === "SAT" || unit === "CENT") { - router.push( - { - pathname: `${username}`, - query: { - amount: amount, - sats: sats, - unit: unit, - memo: note, - display, - }, - }, - undefined, - { shallow: true }, + window.history.pushState( + {}, + "", + `${username}?${new URLSearchParams({ + amount: amount, + sats: sats, + unit: unit, + memo: note, + display, + }).toString()}`, ) } else { - router.push( - { - pathname: `${username}`, - query: { memo: note, display }, - }, - undefined, - { shallow: true }, + window.history.pushState( + {}, + "", + `${username}?${new URLSearchParams({ memo: note, display }).toString()}`, ) } handleClose() diff --git a/apps/pay/components/ParsePOSPayment/Digit-Button.tsx b/apps/pay/components/ParsePOSPayment/Digit-Button.tsx index 32d91548bc1..46c5ed42483 100644 --- a/apps/pay/components/ParsePOSPayment/Digit-Button.tsx +++ b/apps/pay/components/ParsePOSPayment/Digit-Button.tsx @@ -1,6 +1,6 @@ import React from "react" -import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer" +import { ACTIONS, ACTION_TYPE } from "../../app/_reducer" interface Props { digit: string diff --git a/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx b/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx index 8ba2f355dd2..d2b1dbb7360 100644 --- a/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx +++ b/apps/pay/components/ParsePOSPayment/Receive-Invoice.tsx @@ -1,7 +1,7 @@ /* eslint-disable react-hooks/exhaustive-deps */ // TODO: remove eslint-disable, the logic likely needs to be reworked import copy from "copy-to-clipboard" -import { useRouter } from "next/router" +import { useParams, useSearchParams } from "next/navigation" import React, { useCallback } from "react" import Image from "react-bootstrap/Image" import OverlayTrigger from "react-bootstrap/OverlayTrigger" @@ -13,7 +13,7 @@ import { USD_INVOICE_EXPIRE_INTERVAL, getClientSidePayDomain } from "../../confi import useCreateInvoice from "../../hooks/use-Create-Invoice" import { LnInvoiceObject } from "../../lib/graphql/index.types.d" import useSatPrice from "../../lib/use-sat-price" -import { ACTION_TYPE } from "../../pages/_reducer" +import { ACTION_TYPE } from "../../app/_reducer" import PaymentOutcome from "../PaymentOutcome" import { Share } from "../Share" @@ -32,9 +32,11 @@ const USD_MAX_INVOICE_TIME = 5 // minutes const PROGRESS_BAR_MAX_WIDTH = 100 // percent function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }: Props) { - const deviceDetails = window.navigator.userAgent - const router = useRouter() - const { username, amount, unit, sats, memo } = router.query + const deviceDetails = window.navigator?.userAgent + const searchParams = useSearchParams() + const { username } = useParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} + const { amount, unit, sats, memo } = query const { usdToSats, satsToUsd } = useSatPrice() @@ -109,11 +111,11 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }: ) const paymentAmount = React.useMemo(() => { - if (!router.query.sats || typeof router.query.sats !== "string") { + if (!query.sats || typeof query.sats !== "string") { alert("No sats amount provided") return } - let amt = safeAmount(router.query.sats) + let amt = safeAmount(query.sats) if (recipientWalletCurrency === "USD") { const usdAmount = satsToUsd(Number(amt)) if (isNaN(usdAmount)) return @@ -137,11 +139,11 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }: let amt = paymentAmount if (recipientWalletCurrency === "USD") { - if (!router.query.sats || typeof router.query.sats !== "string") { + if (!query.sats || typeof query.sats !== "string") { alert("No sats amount provided") return } else { - const usdAmount = satsToUsd(Number(router.query.sats)) + const usdAmount = satsToUsd(Number(query.sats)) if (isNaN(usdAmount)) return const cents = parseFloat(usdAmount.toFixed(2)) * 100 amt = cents.toFixed() @@ -175,7 +177,7 @@ function ReceiveInvoice({ recipientWalletCurrency, walletId, state, dispatch }: const isMobileDevice = useCallback(() => { const mobileDevice = /android|iPhone|iPod|kindle|HMSCore|windows phone|ipad/i - if (window.navigator.maxTouchPoints > 1 || mobileDevice.test(deviceDetails)) { + if (window.navigator?.maxTouchPoints > 1 || mobileDevice.test(deviceDetails)) { return true } return false diff --git a/apps/pay/components/ParsePOSPayment/index.tsx b/apps/pay/components/ParsePOSPayment/index.tsx index f0c6366cde2..90106ec1a59 100644 --- a/apps/pay/components/ParsePOSPayment/index.tsx +++ b/apps/pay/components/ParsePOSPayment/index.tsx @@ -1,6 +1,5 @@ -import { ParsedUrlQuery } from "querystring" - -import { useRouter } from "next/router" +"use client" +import { useRouter, useSearchParams } from "next/navigation" import React, { useEffect } from "react" import Container from "react-bootstrap/Container" import Image from "react-bootstrap/Image" @@ -8,13 +7,8 @@ import Image from "react-bootstrap/Image" import CurrencyInput, { formatValue } from "react-currency-input-field" import useRealtimePrice from "../../lib/use-realtime-price" -import { ACTION_TYPE, ACTIONS } from "../../pages/_reducer" -import { - formatOperand, - parseDisplayCurrency, - safeAmount, - getLocaleConfig, -} from "../../utils/utils" +import { ACTION_TYPE, ACTIONS } from "../../app/_reducer" +import { formatOperand, safeAmount, getLocaleConfig } from "../../utils/utils" import Memo from "../Memo" import { useDisplayCurrency } from "../../lib/use-display-currency" @@ -26,6 +20,9 @@ import styles from "./parse-payment.module.css" import ReceiveInvoice from "./Receive-Invoice" function isRunningStandalone() { + if (typeof window === "undefined") { + return false + } return window.matchMedia("(display-mode: standalone)").matches } @@ -34,6 +31,7 @@ interface Props { walletId?: string dispatch: React.Dispatch state: React.ComponentState + username: string } interface UpdateAmount { @@ -56,10 +54,19 @@ const defaultCurrencyMetadata: Currency = { __typename: "Currency", } -function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Props) { +function ParsePayment({ + defaultWalletCurrency, + walletId, + dispatch, + state, + username, +}: Props) { const router = useRouter() - const { username, amount, sats, unit, memo, currency } = router.query - const { display } = parseDisplayCurrency(router.query) + const searchParams = useSearchParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} + const { amount, sats, unit, memo, currency } = query + + const display = searchParams?.get("display") ?? localStorage.getItem("display") ?? "USD" const { currencyToSats, satsToCurrency, hasLoaded } = useRealtimePrice(display) const { currencyList } = useDisplayCurrency() const [valueInFiat, setValueInFiat] = React.useState(0) @@ -96,10 +103,11 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop const initialAmount = safeAmount(amount).toString() const initialSats = safeAmount(sats).toString() const initialDisplay = display ?? localStorage.getItem("display") ?? "USD" - const initialUsername = router.query.username - const initialQuery = { ...router.query } + const initialUsername = username + const initialQuery = searchParams ? Object.fromEntries(searchParams.entries()) : {} + delete initialQuery?.currency - const newQuery: ParsedUrlQuery = { + const newQuery = { amount: initialAmount, sats: initialSats, unit: initialUnit, @@ -108,20 +116,14 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop username: initialUsername, } if (initialQuery !== newQuery) { - router.push( - { - pathname: `${username}`, - query: { - amount: initialAmount, - sats: initialSats, - unit: initialUnit, - memo: memo ?? "", - display: initialDisplay, - }, - }, - undefined, - { shallow: true }, - ) + const newUrl = `${username}?${new URLSearchParams({ + amount: initialAmount, + sats: initialSats, + unit: initialUnit, + memo: memo ?? "", + display: initialDisplay, + }).toString()}` + window.history.pushState({}, "", newUrl) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -136,7 +138,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop } else if (sats) { return { shouldUpdate: true, - value: sats.toString(), + value: sats?.toString(), } } } else { @@ -152,20 +154,15 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop const toggleCurrency = () => { const newUnit = unit === AmountUnit.Sat ? AmountUnit.Cent : AmountUnit.Sat prevUnit.current = (unit as AmountUnit) || AmountUnit.Cent - router.push( - { - pathname: `${username}`, - query: { - currency: defaultWalletCurrency, - unit: newUnit, - memo, - display, - amount, - sats, - }, - }, - undefined, - { shallow: true }, + router.replace( + `${username}?${new URLSearchParams({ + currency: defaultWalletCurrency || "USD", + unit: newUnit.toString(), + memo: memo?.toString(), + display: display.toString(), + amount: amount.toString(), + sats: sats?.toString(), + }).toString()}`, ) } @@ -192,7 +189,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop if (isNaN(Number(amt))) return const formattedValue = formatValue({ value: amt, - intlConfig: { locale: navigator.language, currency: display }, + intlConfig: { locale: navigator?.language, currency: display }, }) localStorage.setItem("formattedFiatValue", formattedValue) setValueInFiat(amt) @@ -209,21 +206,20 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop // 3) update the query params const newQuery = { - amount: amt, - sats: satsAmt, - currency: defaultWalletCurrency, - unit, - memo, - display, + amount: amt.toString(), + sats: satsAmt.toString(), + currency: defaultWalletCurrency?.toString() || "USD", + unit: unit.toString(), + memo: memo?.toString(), + display: display.toString(), } - if (router.query !== newQuery && !skipRouterPush) { - router.push( - { - pathname: `${username}`, - query: newQuery, - }, - undefined, - { shallow: true }, + + const initalQuery = searchParams ? Object.fromEntries(searchParams.entries()) : {} + if (initalQuery !== newQuery && !skipRouterPush) { + window.history.pushState( + {}, + "", + `${username}?${new URLSearchParams(newQuery).toString()}`, ) } } @@ -323,7 +319,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop fontWeight: 600, }} value={!amount ? 0 : valueInFiat} - intlConfig={{ locale: navigator.language, currency: display }} + intlConfig={{ locale: navigator?.language, currency: display }} readOnly={true} />
@@ -388,7 +384,7 @@ function ParsePayment({ defaultWalletCurrency, walletId, dispatch, state }: Prop dispatch={dispatch} disabled={unit === AmountUnit.Sat} displayValue={ - getLocaleConfig({ locale: navigator.language, currency: display }) + getLocaleConfig({ locale: navigator?.language, currency: display }) .decimalSeparator } /> diff --git a/apps/pay/components/PaymentOutcome/index.tsx b/apps/pay/components/PaymentOutcome/index.tsx index 5094d765172..c77da47ed45 100644 --- a/apps/pay/components/PaymentOutcome/index.tsx +++ b/apps/pay/components/PaymentOutcome/index.tsx @@ -1,4 +1,5 @@ -import { useRouter } from "next/router" +"use client" +import { useParams, useSearchParams } from "next/navigation" import React, { useRef } from "react" import Image from "react-bootstrap/Image" @@ -6,7 +7,7 @@ import { useReactToPrint } from "react-to-print" import { gql } from "@apollo/client" -import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer" +import { ACTIONS, ACTION_TYPE } from "../../app/_reducer" import { useLnInvoicePaymentStatusSubscription } from "../../lib/graphql/generated" @@ -33,8 +34,10 @@ gql` ` function PaymentOutcome({ paymentRequest, paymentAmount, dispatch }: Props) { - const router = useRouter() - const { amount, sats, username, memo } = router.query + const searchParams = useSearchParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} + const { username } = useParams() + const { amount, sats, memo } = query const componentRef = useRef(null) const printReceipt = useReactToPrint({ diff --git a/apps/pay/components/PaymentOutcome/receipt.tsx b/apps/pay/components/PaymentOutcome/receipt.tsx index cb7e93fdb02..0fbff9b03a2 100644 --- a/apps/pay/components/PaymentOutcome/receipt.tsx +++ b/apps/pay/components/PaymentOutcome/receipt.tsx @@ -1,3 +1,4 @@ +"use client" import React from "react" import Image from "react-bootstrap/Image" diff --git a/apps/pay/components/PinToHomescreen/index.tsx b/apps/pay/components/PinToHomescreen/index.tsx index 6ff26beae8f..f5ae61399d0 100644 --- a/apps/pay/components/PinToHomescreen/index.tsx +++ b/apps/pay/components/PinToHomescreen/index.tsx @@ -2,7 +2,7 @@ import React from "react" import { Image } from "react-bootstrap" import { getOS } from "../../lib/download" -import { ACTIONS, ACTION_TYPE } from "../../pages/_reducer" +import { ACTIONS, ACTION_TYPE } from "../../app/_reducer" import Modal from "../CustomModal/modal" import { @@ -23,7 +23,7 @@ const browser = (function () { //@ts-ignore const test = function (regexp) { if (typeof window !== "undefined") { - return regexp.test(window.navigator.userAgent) + return regexp.test(window.navigator?.userAgent) } } switch (true) { @@ -62,7 +62,7 @@ const PinToHomescreen = ({ pinnedToHomeScreenModalVisible, dispatch }: Props) => }) } - const ua = window.navigator.userAgent + const ua = window.navigator?.userAgent const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i) const webkit = !!ua.match(/WebKit/i) const iOSSafari = iOS && webkit && !ua.match(/CriOS/i) diff --git a/apps/pay/components/Share/share-controller.tsx b/apps/pay/components/Share/share-controller.tsx index a63b522f4cf..907de223356 100644 --- a/apps/pay/components/Share/share-controller.tsx +++ b/apps/pay/components/Share/share-controller.tsx @@ -25,12 +25,12 @@ const ShareController: FC = ({ getImage && getImage() onInteraction && onInteraction() - if (!navigator.canShare) { + if (!navigator?.canShare) { return onNonNativeShare && onNonNativeShare() } try { - await navigator.share(shareData) + await navigator?.share(shareData) onSuccess && onSuccess() } catch (err) { onError && onError(err) diff --git a/apps/pay/components/Share/share-pop-up.tsx b/apps/pay/components/Share/share-pop-up.tsx index fb12eae74ce..5449cb205ca 100644 --- a/apps/pay/components/Share/share-pop-up.tsx +++ b/apps/pay/components/Share/share-pop-up.tsx @@ -32,7 +32,7 @@ const SharePopup: FC = ({ const data = await fetch(image) const blob = await data.blob() - await navigator.clipboard.write([ + await navigator?.clipboard.write([ new ClipboardItem({ [blob.type]: blob, }), diff --git a/apps/pay/components/apollo-wrapper.tsx b/apps/pay/components/apollo-wrapper.tsx new file mode 100644 index 00000000000..d64d5bc68fc --- /dev/null +++ b/apps/pay/components/apollo-wrapper.tsx @@ -0,0 +1,100 @@ +"use client" +import { ApolloLink, HttpLink, split } from "@apollo/client" +import { + ApolloNextAppProvider, + NextSSRInMemoryCache, + NextSSRApolloClient, + SSRMultipartLink, +} from "@apollo/experimental-nextjs-app-support/ssr" + +import { RetryLink } from "@apollo/client/link/retry" +import { onError } from "@apollo/client/link/error" +import { getMainDefinition } from "@apollo/client/utilities" +import { GraphQLWsLink } from "@apollo/client/link/subscriptions" +import { createClient } from "graphql-ws" + +import { getClientSideGqlConfig } from "@/config/config" + +function makeClient() { + const httpLink = new HttpLink({ + uri: getClientSideGqlConfig().coreGqlUrl, + fetchOptions: { cache: "no-store" }, + }) + + const wsLink = new GraphQLWsLink( + createClient({ + url: getClientSideGqlConfig().coreGqlWebSocketUrl, + retryAttempts: 12, + connectionParams: {}, + shouldRetry: (errOrCloseEvent) => { + console.warn({ errOrCloseEvent }, "entering shouldRetry function for websocket") + // TODO: understand how the backend is closing the connection + // for instance during a new version rollout or k8s upgrade + // + // in the meantime: + // returning true instead of the default 'Any non-`CloseEvent`' + // to force createClient to attempt a reconnection + return true + }, + // Voluntary not using: webSocketImpl: WebSocket + // seems react native already have an implement of the websocket? + // + // TODO: implement keepAlive and reconnection? + // https://github.com/enisdenjo/graphql-ws/blob/master/docs/interfaces/client.ClientOptions.md#keepalive + }), + ) + + const errorLink = onError(({ graphQLErrors, networkError }) => { + if (graphQLErrors) + graphQLErrors.forEach(({ message, locations, path }) => { + if (message === "PersistedQueryNotFound") { + console.log(`[GraphQL info]: Message: ${message}, Path: ${path}}`, { + locations, + }) + } else { + console.warn(`[GraphQL error]: Message: ${message}, Path: ${path}}`, { + locations, + }) + } + }) + + if (networkError) { + console.log(`[Network error]: ${networkError}`) + } + }) + + const retryLink = new RetryLink({ + attempts: { + max: 5, + }, + }) + + const link = split( + ({ query }) => { + const definition = getMainDefinition(query) + return ( + definition.kind === "OperationDefinition" && + definition.operation === "subscription" + ) + }, + wsLink, + ApolloLink.from([errorLink, retryLink, httpLink]), + ) + + return new NextSSRApolloClient({ + cache: new NextSSRInMemoryCache(), + link: + typeof window === "undefined" + ? ApolloLink.from([ + new SSRMultipartLink({ + stripDefer: true, + }), + link, + ]) + : link, + }) +} + +export function ApolloWrapper({ children }: React.PropsWithChildren) { + return {children} +} diff --git a/apps/pay/components/receive-amount.tsx b/apps/pay/components/receive-amount.tsx index 50fdb6fe17b..b7a891669c0 100644 --- a/apps/pay/components/receive-amount.tsx +++ b/apps/pay/components/receive-amount.tsx @@ -2,7 +2,7 @@ import { ParsedUrlQuery } from "querystring" import React, { useState, useEffect } from "react" import { useDebouncedCallback } from "use-debounce" -import { useRouter } from "next/router" +import { useParams, useRouter, useSearchParams } from "next/navigation" import useSatPrice from "../lib/use-sat-price" @@ -29,9 +29,12 @@ export default function ReceiveAmount({ recipientWalletCurrency: string }) { const router = useRouter() + const searchParams = useSearchParams() + const { username } = useParams() + const query = searchParams ? Object.fromEntries(searchParams.entries()) : {} const { satsToUsd, usdToSats } = useSatPrice() - const { amount, currency } = parseQueryAmount(router.query) // USD or SATs - const { display } = parseDisplayCurrency(router.query) + const { amount, currency } = parseQueryAmount(query) // USD or SATs + const { display } = parseDisplayCurrency(query) function toggleCurrency() { const newCurrency = currency === "SATS" ? "USD" : "SATS" @@ -39,12 +42,15 @@ export default function ReceiveAmount({ newCurrency === "SATS" ? Math.round(usdToSats(amount)) : satsToUsd(amount) router.push( - getUpdatedURL(router.query, { currency: newCurrency, amount: newAmount, display }), + getUpdatedURL( + { ...query, username }, + { currency: newCurrency, amount: newAmount, display }, + ), ) } const handleAmountUpdate = useDebouncedCallback(({ numberValue }) => { - router.push(getUpdatedURL(router.query, { amount: numberValue })) + router.push(getUpdatedURL({ ...query, username }, { amount: numberValue })) }, 1000) const getSatsForInvoice = React.useCallback(() => { diff --git a/apps/pay/config/config.ts b/apps/pay/config/config.ts index 7e4ba9edbd1..157472d77de 100644 --- a/apps/pay/config/config.ts +++ b/apps/pay/config/config.ts @@ -1,29 +1,28 @@ import { env } from "../env" + export const USD_INVOICE_EXPIRE_INTERVAL = 60 * 5 export const MAX_INPUT_VALUE_LENGTH = 14 export const APP_DESCRIPTION = "Blink official lightning network node" // TODO get rid of this by removing the use of build time env vars in the client export const getClientSideGqlConfig = () => { - const hostname = new URL(window.location.href).hostname + let hostname, coreGqlUrl, coreGqlWebSocketUrl - let coreGqlUrl + if (typeof window !== "undefined") { + hostname = new URL(window.location.href).hostname + } - // Allow overriding the coreGqlUrl for local development, otherwise use the default in the URL - if (env.NEXT_PUBLIC_CORE_GQL_URL || typeof window === "undefined") { + if (env.NEXT_PUBLIC_CORE_GQL_URL) { coreGqlUrl = env.NEXT_PUBLIC_CORE_GQL_URL - } else { + } else if (hostname) { const hostPartsApi = hostname.split(".") hostPartsApi[0] = "api" coreGqlUrl = `https://${hostPartsApi.join(".")}/graphql` } - let coreGqlWebSocketUrl - - // Allow overriding the coreGqlWebSocketUrl for local development, otherwise use the default in the URL - if (env.NEXT_PUBLIC_CORE_GQL_WEB_SOCKET_URL || typeof window === "undefined") { + if (env.NEXT_PUBLIC_CORE_GQL_WEB_SOCKET_URL) { coreGqlWebSocketUrl = env.NEXT_PUBLIC_CORE_GQL_WEB_SOCKET_URL - } else { + } else if (hostname) { const hostPartsWs = hostname.split(".") hostPartsWs[0] = "ws" coreGqlWebSocketUrl = `wss://${hostPartsWs.join(".")}/graphql` @@ -36,9 +35,11 @@ export const getClientSideGqlConfig = () => { } export const getClientSidePayDomain = () => { - if (env.NEXT_PUBLIC_PAY_DOMAIN || typeof window === "undefined") { + if (env.NEXT_PUBLIC_PAY_DOMAIN) { return env.NEXT_PUBLIC_PAY_DOMAIN + } else if (typeof window !== "undefined") { + return new URL(window.location.href).hostname.split(".").slice(-2).join(".") } else { - return new URL(window.location.href).hostname.split(".").slice(-2).join(".") // Return the last two parts of the hostname (e.g. "blink.sv") + return "" } } diff --git a/apps/pay/lib/download.ts b/apps/pay/lib/download.ts index 1177ae50e68..6f30d3bff5d 100644 --- a/apps/pay/lib/download.ts +++ b/apps/pay/lib/download.ts @@ -1,6 +1,12 @@ export const getOS = () => { - // @ts-expect-error: opera browser property is not a standard thing - const userAgent = navigator.userAgent || navigator.vendor || window.opera + let userAgent + + if (typeof window !== "undefined") { + // @ts-expect-error: opera browser property is not a standard thing + userAgent = navigator?.userAgent || navigator?.vendor || window.opera + } else { + return undefined + } // Windows Phone must come first because its UA also contains "Android" if (/windows phone/i.test(userAgent)) { diff --git a/apps/pay/next.config.js b/apps/pay/next.config.js index 87e824fd8b0..b22e18f6337 100644 --- a/apps/pay/next.config.js +++ b/apps/pay/next.config.js @@ -5,6 +5,7 @@ module.exports = { experimental: { outputFileTracingRoot: require("path").join(__dirname, "../../"), instrumentationHook: true, + missingSuspenseWithCSRBailout: false, }, output: "standalone", } diff --git a/apps/pay/package.json b/apps/pay/package.json index c83b4342c9b..b3db2a80131 100644 --- a/apps/pay/package.json +++ b/apps/pay/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@apollo/client": "^3.7.12", + "@apollo/experimental-nextjs-app-support": "^0.8.0", "@galoymoney/client": "^0.2.2", "@t3-oss/env-nextjs": "^0.6.1", "bech32": "^2.0.0", @@ -26,7 +27,7 @@ "ioredis": "^5.3.1", "lnurl-pay": "^1.0.1", "lodash.debounce": "^4.0.8", - "next": "^13.4.19", + "next": "^14.1.0", "react": "^18.2.0", "react-bootstrap": "^1.6.4", "react-currency-input-field": "^3.6.10", @@ -34,6 +35,7 @@ "react-lottie": "^1.2.3", "react-qrcode-logo": "^2.9.0", "react-to-print": "^2.14.12", + "ssr": "link:@apollo/experimental-nextjs-app-support/ssr", "use-debounce": "^8.0.4", "use-react-screenshot": "^3.0.0", "zod": "^3.22.4" @@ -59,7 +61,7 @@ "@typescript-eslint/parser": "^5.51.0", "cypress": "^13.6.1", "eslint": "^8.52.0", - "eslint-config-next": "14.0.4", + "eslint-config-next": "14.1.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-import": "^2.26.0", diff --git a/apps/pay/tsconfig.json b/apps/pay/tsconfig.json index 2b5cff7b42d..8013931202e 100644 --- a/apps/pay/tsconfig.json +++ b/apps/pay/tsconfig.json @@ -24,7 +24,10 @@ { "name": "next" } - ] + ], + "paths": { + "@/*": ["./*"] + } }, "include": [ "**/*", diff --git a/apps/pay/utils/utils.ts b/apps/pay/utils/utils.ts index 1341029810f..d213be1c42a 100644 --- a/apps/pay/utils/utils.ts +++ b/apps/pay/utils/utils.ts @@ -53,7 +53,7 @@ export const getOriginalRequestInfo = (request: Request) => { } } -export function safeAmount(amount: number | string | string[] | undefined) { +export function safeAmount(amount: number | string | string[] | undefined | null) { try { if (isNaN(Number(amount))) return 0 const theSafeAmount = ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d485357c008..4fcf29ba616 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -571,9 +571,12 @@ importers: '@apollo/client': specifier: ^3.7.12 version: 3.8.8(graphql-ws@5.14.2)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@apollo/experimental-nextjs-app-support': + specifier: ^0.8.0 + version: 0.8.0(@apollo/client@3.8.8)(next@14.1.0)(react@18.2.0) '@galoymoney/client': specifier: ^0.2.2 - version: 0.2.6(@bitcoinerlab/secp256k1@1.0.5)(bitcoinjs-lib@5.0.5)(bolt11@1.4.1)(lnurl-pay@1.0.1)(url@0.11.3) + version: 0.2.6(@bitcoinerlab/secp256k1@1.1.1)(bitcoinjs-lib@5.0.5)(bolt11@1.4.1)(lnurl-pay@1.0.1)(url@0.11.3) '@t3-oss/env-nextjs': specifier: ^0.6.1 version: 0.6.1(typescript@5.2.2)(zod@3.22.4) @@ -611,8 +614,8 @@ importers: specifier: ^4.0.8 version: 4.0.8 next: - specifier: ^13.4.19 - version: 13.5.6(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0) + specifier: ^14.1.0 + version: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -634,6 +637,9 @@ importers: react-to-print: specifier: ^2.14.12 version: 2.14.15(react-dom@18.2.0)(react@18.2.0) + ssr: + specifier: link:@apollo/experimental-nextjs-app-support/ssr + version: link:@apollo/experimental-nextjs-app-support/ssr use-debounce: specifier: ^8.0.4 version: 8.0.4(react@18.2.0) @@ -705,8 +711,8 @@ importers: specifier: ^8.52.0 version: 8.54.0 eslint-config-next: - specifier: 14.0.4 - version: 14.0.4(eslint@8.54.0)(typescript@5.2.2) + specifier: 14.1.0 + version: 14.1.0(eslint@8.54.0)(typescript@5.2.2) eslint-config-react-app: specifier: ^7.0.1 version: 7.0.1(@babel/plugin-syntax-flow@7.23.3)(@babel/plugin-transform-react-jsx@7.23.4)(eslint@8.54.0)(typescript@5.2.2) @@ -715,7 +721,7 @@ importers: version: 8.0.3(@babel/plugin-syntax-flow@7.23.3)(@babel/plugin-transform-react-jsx@7.23.4)(eslint@8.54.0) eslint-plugin-import: specifier: ^2.26.0 - version: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + version: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) eslint-plugin-jest: specifier: ^27.2.1 version: 27.6.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.54.0)(typescript@5.2.2) @@ -1578,6 +1584,21 @@ packages: ts-invariant: 0.10.3 dev: false + /@apollo/experimental-nextjs-app-support@0.8.0(@apollo/client@3.8.8)(next@14.1.0)(react@18.2.0): + resolution: {integrity: sha512-uyNIkOkew0T6ukC8ycbWBeTu8gtDSD5i+NVGEHU0DIEQaToFHObYcvIxaQ/8hvWzgvnpNU/KMsApfGXA9Xkpyw==} + peerDependencies: + '@apollo/client': ^3.9.0 + next: ^13.4.1 || ^14.0.0 + react: ^18 + dependencies: + '@apollo/client': 3.8.8(graphql-ws@5.14.2)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + next: 14.1.0(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + server-only: 0.0.1 + superjson: 1.13.3 + ts-invariant: 0.10.3 + dev: false + /@apollo/protobufjs@1.2.7: resolution: {integrity: sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==} hasBin: true @@ -5323,8 +5344,8 @@ packages: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@bitcoinerlab/secp256k1@1.0.5: - resolution: {integrity: sha512-8gT+ukTCFN2rTxn4hD9Jq3k+UJwcprgYjfK/SQUSLgznXoIgsBnlPuARMkyyuEjycQK9VvnPiejKdszVTflh+w==} + /@bitcoinerlab/secp256k1@1.1.1: + resolution: {integrity: sha512-uhjW51WfVLpnHN7+G0saDcM/k9IqcyTbZ+bDgLF3AX8V/a3KXSE9vn7UPBrcdU72tp0J4YPR7BHp2m7MLAZ/1Q==} dependencies: '@noble/hashes': 1.3.3 '@noble/secp256k1': 1.7.1 @@ -6103,7 +6124,7 @@ packages: /@floating-ui/utils@0.1.6: resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==} - /@galoymoney/client@0.2.6(@bitcoinerlab/secp256k1@1.0.5)(bitcoinjs-lib@5.0.5)(bolt11@1.4.1)(lnurl-pay@1.0.1)(url@0.11.3): + /@galoymoney/client@0.2.6(@bitcoinerlab/secp256k1@1.1.1)(bitcoinjs-lib@5.0.5)(bolt11@1.4.1)(lnurl-pay@1.0.1)(url@0.11.3): resolution: {integrity: sha512-HCYMB39EO1/2RJ6Dz9ZJkRDCKd5b3IyaajfR2db4i4hQZ6i4z1nuEFT/04ERu27Mlrxrb0qjHfYmAPTRR20xdg==} peerDependencies: '@bitcoinerlab/secp256k1': ^1.0.5 @@ -6112,7 +6133,7 @@ packages: lnurl-pay: ^1.0.1 url: '>=0.11.0' dependencies: - '@bitcoinerlab/secp256k1': 1.0.5 + '@bitcoinerlab/secp256k1': 1.1.1 bitcoinjs-lib: 5.0.5 bolt11: 1.4.1 lnurl-pay: 1.0.1 @@ -7960,7 +7981,7 @@ packages: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: 16.8.1 - tslib: 2.6.2 + tslib: 2.5.3 dev: true /@graphql-tools/optimize@2.0.0(graphql@16.8.1): @@ -8112,7 +8133,7 @@ packages: '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) graphql: 16.8.1 - tslib: 2.6.2 + tslib: 2.5.3 transitivePeerDependencies: - encoding - supports-color @@ -8127,7 +8148,7 @@ packages: '@ardatan/relay-compiler': 12.0.0(graphql@16.8.1) '@graphql-tools/utils': 10.0.11(graphql@16.8.1) graphql: 16.8.1 - tslib: 2.6.2 + tslib: 2.5.3 transitivePeerDependencies: - encoding - supports-color @@ -8332,7 +8353,7 @@ packages: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: 16.8.1 - tslib: 2.6.2 + tslib: 2.4.1 /@graphql-tools/utils@9.2.1(graphql@16.8.1): resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} @@ -9159,10 +9180,6 @@ packages: tar-fs: 2.1.1 dev: true - /@next/env@13.5.6: - resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} - dev: false - /@next/env@14.0.1: resolution: {integrity: sha512-Ms8ZswqY65/YfcjrlcIwMPD7Rg/dVjdLapMcSHG26W6O67EJDF435ShW4H4LXi1xKO1oRc97tLXUpx8jpLe86A==} dev: false @@ -9193,15 +9210,6 @@ packages: glob: 10.3.10 dev: true - /@next/swc-darwin-arm64@13.5.6: - resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - /@next/swc-darwin-arm64@14.0.1: resolution: {integrity: sha512-JyxnGCS4qT67hdOKQ0CkgFTp+PXub5W1wsGvIq98TNbF3YEIN7iDekYhYsZzc8Ov0pWEsghQt+tANdidITCLaw==} engines: {node: '>= 10'} @@ -9229,15 +9237,6 @@ packages: dev: false optional: true - /@next/swc-darwin-x64@13.5.6: - resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - /@next/swc-darwin-x64@14.0.1: resolution: {integrity: sha512-625Z7bb5AyIzswF9hvfZWa+HTwFZw+Jn3lOBNZB87lUS0iuCYDHqk3ujuHCkiyPtSC0xFBtYDLcrZ11mF/ap3w==} engines: {node: '>= 10'} @@ -9265,15 +9264,6 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-gnu@13.5.6: - resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - /@next/swc-linux-arm64-gnu@14.0.1: resolution: {integrity: sha512-iVpn3KG3DprFXzVHM09kvb//4CNNXBQ9NB/pTm8LO+vnnnaObnzFdS5KM+w1okwa32xH0g8EvZIhoB3fI3mS1g==} engines: {node: '>= 10'} @@ -9301,15 +9291,6 @@ packages: dev: false optional: true - /@next/swc-linux-arm64-musl@13.5.6: - resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - /@next/swc-linux-arm64-musl@14.0.1: resolution: {integrity: sha512-mVsGyMxTLWZXyD5sen6kGOTYVOO67lZjLApIj/JsTEEohDDt1im2nkspzfV5MvhfS7diDw6Rp/xvAQaWZTv1Ww==} engines: {node: '>= 10'} @@ -9337,15 +9318,6 @@ packages: dev: false optional: true - /@next/swc-linux-x64-gnu@13.5.6: - resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - /@next/swc-linux-x64-gnu@14.0.1: resolution: {integrity: sha512-wMqf90uDWN001NqCM/auRl3+qVVeKfjJdT9XW+RMIOf+rhUzadmYJu++tp2y+hUbb6GTRhT+VjQzcgg/QTD9NQ==} engines: {node: '>= 10'} @@ -9373,15 +9345,6 @@ packages: dev: false optional: true - /@next/swc-linux-x64-musl@13.5.6: - resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - /@next/swc-linux-x64-musl@14.0.1: resolution: {integrity: sha512-ol1X1e24w4j4QwdeNjfX0f+Nza25n+ymY0T2frTyalVczUmzkVD7QGgPTZMHfR1aLrO69hBs0G3QBYaj22J5GQ==} engines: {node: '>= 10'} @@ -9409,15 +9372,6 @@ packages: dev: false optional: true - /@next/swc-win32-arm64-msvc@13.5.6: - resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - /@next/swc-win32-arm64-msvc@14.0.1: resolution: {integrity: sha512-WEmTEeWs6yRUEnUlahTgvZteh5RJc4sEjCQIodJlZZ5/VJwVP8p2L7l6VhzQhT4h7KvLx/Ed4UViBdne6zpIsw==} engines: {node: '>= 10'} @@ -9445,15 +9399,6 @@ packages: dev: false optional: true - /@next/swc-win32-ia32-msvc@13.5.6: - resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - /@next/swc-win32-ia32-msvc@14.0.1: resolution: {integrity: sha512-oFpHphN4ygAgZUKjzga7SoH2VGbEJXZa/KL8bHCAwCjDWle6R1SpiGOdUdA8EJ9YsG1TYWpzY6FTbUA+iAJeww==} engines: {node: '>= 10'} @@ -9481,15 +9426,6 @@ packages: dev: false optional: true - /@next/swc-win32-x64-msvc@13.5.6: - resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - /@next/swc-win32-x64-msvc@14.0.1: resolution: {integrity: sha512-FFp3nOJ/5qSpeWT0BZQ+YE1pSMk4IMpkME/1DwKBwhg4mJLB9L+6EXuJi4JEwaJdl5iN+UUlmUD3IsR1kx5fAg==} engines: {node: '>= 10'} @@ -11786,6 +11722,10 @@ packages: resolution: {integrity: sha512-6i/8UoL0P5y4leBIGzvkZdS85RDMG9y1ihZzmTZQ5LdHUYmZ7pKFoj8X0236s3lusPs1Fa5HTQUpwI+UfTcmeA==} dev: true + /@rushstack/eslint-patch@1.7.2: + resolution: {integrity: sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==} + dev: true + /@scure/base@1.1.3: resolution: {integrity: sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==} dev: false @@ -14799,27 +14739,6 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.19.1(eslint@8.54.0)(typescript@5.2.2): - resolution: {integrity: sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.2.2) - '@typescript-eslint/visitor-keys': 6.19.1 - debug: 4.3.4(supports-color@5.5.0) - eslint: 8.54.0 - typescript: 5.2.2 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -17079,7 +16998,7 @@ packages: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: pascal-case: 3.1.2 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /camelcase-css@2.0.1: @@ -17097,6 +17016,7 @@ packages: /caniuse-lite@1.0.30001561: resolution: {integrity: sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==} + dev: true /caniuse-lite@1.0.30001568: resolution: {integrity: sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==} @@ -17107,12 +17027,17 @@ packages: /caniuse-lite@1.0.30001585: resolution: {integrity: sha512-yr2BWR1yLXQ8fMpdS/4ZZXpseBgE7o4g41x3a6AJOqZuOi+iE/WdJYAuZ6Y95i4Ohd2Y+9MzIWRR+uGABH4s3Q==} + dev: true + + /caniuse-lite@1.0.30001587: + resolution: {integrity: sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==} + dev: false /capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 upper-case-first: 2.0.2 dev: true @@ -17217,7 +17142,7 @@ packages: path-case: 3.0.4 sentence-case: 3.0.4 snake-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /char-regex@1.0.2: @@ -17622,7 +17547,7 @@ packages: resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 upper-case: 2.0.2 dev: true @@ -18541,7 +18466,7 @@ packages: dependencies: debug: 4.3.4(supports-color@5.5.0) is-url: 1.2.4 - postcss: 8.4.32 + postcss: 8.4.35 postcss-values-parser: 2.0.1 transitivePeerDependencies: - supports-color @@ -18733,7 +18658,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 /dotenv-expand@10.0.0: resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} @@ -19213,7 +19138,7 @@ packages: - supports-color dev: true - /eslint-config-next@14.0.4(eslint@8.54.0)(typescript@5.2.2): + /eslint-config-next@14.0.4(eslint@8.56.0)(typescript@5.3.3): resolution: {integrity: sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 @@ -19224,22 +19149,22 @@ packages: dependencies: '@next/eslint-plugin-next': 14.0.4 '@rushstack/eslint-patch': 1.5.1 - '@typescript-eslint/parser': 6.19.1(eslint@8.54.0)(typescript@5.2.2) - eslint: 8.54.0 + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.54.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) - eslint-plugin-react: 7.33.2(eslint@8.54.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.54.0) - typescript: 5.2.2 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0) + eslint-plugin-react: 7.33.2(eslint@8.56.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0) + typescript: 5.3.3 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color dev: true - /eslint-config-next@14.0.4(eslint@8.56.0)(typescript@5.3.3): - resolution: {integrity: sha512-9/xbOHEQOmQtqvQ1UsTQZpnA7SlDMBtuKJ//S4JnoyK3oGLhILKXdBgu/UO7lQo/2xOykQULS1qQ6p2+EpHgAQ==} + /eslint-config-next@14.1.0(eslint@8.54.0)(typescript@5.2.2): + resolution: {integrity: sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -19247,17 +19172,17 @@ packages: typescript: optional: true dependencies: - '@next/eslint-plugin-next': 14.0.4 - '@rushstack/eslint-patch': 1.5.1 - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - eslint: 8.56.0 + '@next/eslint-plugin-next': 14.1.0 + '@rushstack/eslint-patch': 1.7.2 + '@typescript-eslint/parser': 5.62.0(eslint@8.54.0)(typescript@5.2.2) + eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.56.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0) - eslint-plugin-jsx-a11y: 6.8.0(eslint@8.56.0) - eslint-plugin-react: 7.33.2(eslint@8.56.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.56.0) - typescript: 5.3.3 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.54.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) + eslint-plugin-react: 7.33.2(eslint@8.54.0) + eslint-plugin-react-hooks: 4.6.0(eslint@8.54.0) + typescript: 5.2.2 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color @@ -19316,7 +19241,7 @@ packages: confusing-browser-globals: 1.0.11 eslint: 8.54.0 eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.23.3)(@babel/plugin-transform-react-jsx@7.23.4)(eslint@8.54.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.54.0)(typescript@5.2.2) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.54.0) eslint-plugin-react: 7.33.2(eslint@8.54.0) @@ -19342,7 +19267,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.52.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.54.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -19351,9 +19276,9 @@ packages: dependencies: debug: 4.3.4(supports-color@5.5.0) enhanced-resolve: 5.15.0 - eslint: 8.52.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.52.0) + eslint: 8.54.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -19365,7 +19290,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.54.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.52.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -19374,9 +19299,9 @@ packages: dependencies: debug: 4.3.4(supports-color@5.5.0) enhanced-resolve: 5.15.0 - eslint: 8.54.0 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) + eslint: 8.52.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0)(eslint@8.52.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -19434,7 +19359,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -19459,6 +19384,7 @@ packages: debug: 3.2.7(supports-color@8.1.1) eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.0)(eslint@8.54.0) transitivePeerDependencies: - supports-color dev: true @@ -19522,36 +19448,6 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0): - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.54.0)(typescript@5.2.2) - debug: 3.2.7(supports-color@8.1.1) - eslint: 8.54.0 - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.54.0) - transitivePeerDependencies: - - supports-color - dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.56.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} @@ -19656,7 +19552,7 @@ packages: string-natural-compare: 3.0.1 dev: true - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@5.62.0)(eslint@8.54.0): + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0): resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: @@ -19675,7 +19571,7 @@ packages: doctrine: 2.1.0 eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint@8.54.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -19726,41 +19622,6 @@ packages: - supports-color dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.54.0)(typescript@5.2.2) - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@8.1.1) - doctrine: 2.1.0 - eslint: 8.54.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) - hasown: 2.0.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} @@ -22380,7 +22241,7 @@ packages: resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} dependencies: capital-case: 1.0.4 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /help-me@5.0.0: @@ -23076,7 +22937,7 @@ packages: /is-lower-case@2.0.2: resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /is-map@2.0.2: @@ -23253,7 +23114,7 @@ packages: /is-upper-case@2.0.2: resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /is-url-superb@4.0.0: @@ -24883,13 +24744,13 @@ packages: /lower-case-first@2.0.2: resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 /lowercase-keys@1.0.0: resolution: {integrity: sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==} @@ -25704,45 +25565,6 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /next@13.5.6(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} - engines: {node: '>=16.14.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - dependencies: - '@next/env': 13.5.6 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001561 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(@babel/core@7.23.9)(react@18.2.0) - watchpack: 2.4.0 - optionalDependencies: - '@next/swc-darwin-arm64': 13.5.6 - '@next/swc-darwin-x64': 13.5.6 - '@next/swc-linux-arm64-gnu': 13.5.6 - '@next/swc-linux-arm64-musl': 13.5.6 - '@next/swc-linux-x64-gnu': 13.5.6 - '@next/swc-linux-x64-musl': 13.5.6 - '@next/swc-win32-arm64-msvc': 13.5.6 - '@next/swc-win32-ia32-msvc': 13.5.6 - '@next/swc-win32-x64-msvc': 13.5.6 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - dev: false - /next@14.0.1(@babel/core@7.23.9)(@opentelemetry/api@1.7.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-s4YaLpE4b0gmb3ggtmpmV+wt+lPRuGtANzojMQ2+gmBpgX9w5fTbjsy6dXByBuENsdCX5pukZH/GxdFgO62+pA==} engines: {node: '>=18.17.0'} @@ -25843,7 +25665,7 @@ packages: '@opentelemetry/api': 1.7.0 '@swc/helpers': 0.5.2 busboy: 1.6.0 - caniuse-lite: 1.0.30001585 + caniuse-lite: 1.0.30001587 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.2.0 @@ -25868,7 +25690,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.6.2 + tslib: 2.4.1 /node-abi@3.54.0: resolution: {integrity: sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==} @@ -26473,7 +26295,7 @@ packages: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /parent-module@1.0.1: @@ -26540,7 +26362,7 @@ packages: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /path-browserify@1.0.1: @@ -26551,7 +26373,7 @@ packages: resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 dev: true /path-exists@3.0.0: @@ -27119,6 +26941,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.35: + resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -28338,7 +28169,7 @@ packages: adjust-sourcemap-loader: 4.0.0 convert-source-map: 1.9.0 loader-utils: 2.0.4 - postcss: 8.4.32 + postcss: 8.4.31 source-map: 0.6.1 dev: true @@ -28655,7 +28486,7 @@ packages: resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.4.1 upper-case-first: 2.0.2 dev: true @@ -29028,7 +28859,7 @@ packages: /sponge-case@1.0.1: resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /sprintf-js@1.0.3: @@ -29536,7 +29367,7 @@ packages: /swap-case@2.0.2: resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /swc-loader@0.2.3(@swc/core@1.3.105)(webpack@5.89.0): @@ -29975,7 +29806,7 @@ packages: /title-case@3.0.3: resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /tmp@0.0.33: @@ -30645,13 +30476,13 @@ packages: /upper-case-first@2.0.2: resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /upper-case@2.0.2: resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} dependencies: - tslib: 2.6.2 + tslib: 2.4.1 dev: true /uri-js@4.4.1: