diff --git a/components/Blocks/TextBlock/RenderYJSFragment.tsx b/components/Blocks/TextBlock/RenderYJSFragment.tsx index 132e72a7..94dc872f 100644 --- a/components/Blocks/TextBlock/RenderYJSFragment.tsx +++ b/components/Blocks/TextBlock/RenderYJSFragment.tsx @@ -27,7 +27,7 @@ export function RenderYJSFragment({ return ( {children.length === 0 ? ( -
+
) : ( node.toArray().map((node, index) => { if (node.constructor === XmlText) { -- 2.51.2 From 045e283b252eacea1f5b83406a6a0dfdf117dd12 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Sun, 16 Nov 2025 23:45:06 -0500 Subject: [PATCH 002/118] mark yjs external package --- next.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/next.config.js b/next.config.js index f54ed91f..68b3188e 100644 --- a/next.config.js +++ b/next.config.js @@ -21,6 +21,7 @@ const nextConfig = { }, ]; }, + serverExternalPackages: ["yjs"], pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"], images: { loader: "custom", -- 2.51.2 From a613e397efca2cb6b7ca41e2c8765cf80e70350c Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 01:25:49 -0500 Subject: [PATCH 003/118] add alternate names to block commands --- components/Blocks/BlockCommandBar.tsx | 9 +++++++-- components/Blocks/BlockCommands.tsx | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/components/Blocks/BlockCommandBar.tsx b/components/Blocks/BlockCommandBar.tsx index 62bf0e87..2aaf7f99 100644 --- a/components/Blocks/BlockCommandBar.tsx +++ b/components/Blocks/BlockCommandBar.tsx @@ -47,9 +47,14 @@ export const BlockCommandBar = ({ }; let commandResults = blockCommands.filter((command) => { - const matchesSearch = command.name + const lowerSearchValue = searchValue.toLocaleLowerCase(); + const matchesName = command.name .toLocaleLowerCase() - .includes(searchValue.toLocaleLowerCase()); + .includes(lowerSearchValue); + const matchesAlternate = command.alternateNames?.some((altName) => + altName.toLocaleLowerCase().includes(lowerSearchValue) + ) ?? false; + const matchesSearch = matchesName || matchesAlternate; const isVisible = !pub || !command.hiddenInPublication; return matchesSearch && isVisible; }); diff --git a/components/Blocks/BlockCommands.tsx b/components/Blocks/BlockCommands.tsx index 9e8a78f8..326defaa 100644 --- a/components/Blocks/BlockCommands.tsx +++ b/components/Blocks/BlockCommands.tsx @@ -102,6 +102,7 @@ type Command = { name: string; icon: React.ReactNode; type: string; + alternateNames?: string[]; hiddenInPublication?: boolean; onSelect: ( rep: Replicache, @@ -125,6 +126,7 @@ export const blockCommands: Command[] = [ name: "Title", icon: , type: "text", + alternateNames: ["h1"], onSelect: async (rep, props, um) => { await setHeaderCommand(1, rep, props); }, @@ -133,6 +135,7 @@ export const blockCommands: Command[] = [ name: "Header", icon: , type: "text", + alternateNames: ["h2"], onSelect: async (rep, props, um) => { await setHeaderCommand(2, rep, props); }, @@ -141,6 +144,7 @@ export const blockCommands: Command[] = [ name: "Subheader", icon: , type: "text", + alternateNames: ["h3"], onSelect: async (rep, props, um) => { await setHeaderCommand(3, rep, props); }, -- 2.51.2 From b70eb51d3c5454edf8dd06c44541e235b565d553 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 12:51:40 -0500 Subject: [PATCH 004/118] use cloudflare browser api instead of microlink --- app/[leaflet_id]/publish/publishBskyPost.ts | 17 +++---- app/api/link_previews/route.ts | 16 +++---- src/utils/getMicroLinkOgImage.ts | 49 ++++++++++++++++++--- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/app/[leaflet_id]/publish/publishBskyPost.ts b/app/[leaflet_id]/publish/publishBskyPost.ts index 7fa16dd6..9fc2efb9 100644 --- a/app/[leaflet_id]/publish/publishBskyPost.ts +++ b/app/[leaflet_id]/publish/publishBskyPost.ts @@ -12,6 +12,10 @@ import { AtpBaseClient, PubLeafletDocument } from "lexicons/api"; import { createOauthClient } from "src/atproto-oauth"; import { supabaseServerClient } from "supabase/serverClient"; import { Json } from "supabase/database.types"; +import { + getMicroLinkOgImage, + getWebpageImage, +} from "src/utils/getMicroLinkOgImage"; export async function publishPostToBsky(args: { text: string; @@ -31,14 +35,11 @@ export async function publishPostToBsky(args: { credentialSession.fetchHandler.bind(credentialSession), ); let newPostUrl = args.url; - let preview_image = await fetch( - `https://pro.microlink.io/?url=${newPostUrl}&screenshot=true&viewport.width=1400&viewport.height=733&meta=false&embed=screenshot.url&force=true`, - { - headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - }, - ); + let preview_image = await getWebpageImage(newPostUrl, { + width: 1400, + height: 733, + noCache: true, + }); let binary = await preview_image.blob(); let resized_preview_image = await sharp(await binary.arrayBuffer()) diff --git a/app/api/link_previews/route.ts b/app/api/link_previews/route.ts index 090674d9..9b7ad6b2 100644 --- a/app/api/link_previews/route.ts +++ b/app/api/link_previews/route.ts @@ -5,6 +5,10 @@ import { NextRequest } from "next/server"; import * as z from "zod"; import { createClient } from "@supabase/supabase-js"; import { Database } from "supabase/database.types"; +import { + getMicroLinkOgImage, + getWebpageImage, +} from "src/utils/getMicroLinkOgImage"; let supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, process.env.SUPABASE_SERVICE_ROLE_KEY as string, @@ -27,17 +31,7 @@ export type LinkPreviewMetadataResult = ReturnType; export type LinkPreviewImageResult = ReturnType; async function get_link_image_preview(url: string) { - let image = await fetch( - `https://pro.microlink.io/?url=${url}&screenshot&viewport.width=1400&viewport.height=1213&embed=screenshot.url&meta=false&force=true`, - { - headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - next: { - revalidate: 600, - }, - }, - ); + let image = await getWebpageImage(url, { width: 1400, height: 1213 }); let key = await hash(url); if (image.status === 200) { await supabase.storage diff --git a/src/utils/getMicroLinkOgImage.ts b/src/utils/getMicroLinkOgImage.ts index 4ccf6ece..fac40494 100644 --- a/src/utils/getMicroLinkOgImage.ts +++ b/src/utils/getMicroLinkOgImage.ts @@ -2,21 +2,58 @@ import { headers } from "next/headers"; export async function getMicroLinkOgImage( path: string, - options?: { width?: number; height?: number; deviceScaleFactor?: number }, + options?: { + width?: number; + height?: number; + deviceScaleFactor?: number; + noCache?: boolean; + }, ) { const headersList = await headers(); const hostname = headersList.get("x-forwarded-host"); let protocol = headersList.get("x-forwarded-proto"); let full_path = `${protocol}://${hostname}${path}`; + return getWebpageImage(full_path, options); +} + +export async function getWebpageImage( + url: string, + options?: { + width?: number; + height?: number; + deviceScaleFactor?: number; + noCache?: boolean; + }, +) { let response = await fetch( - `https://pro.microlink.io/?url=${encodeURIComponent(full_path)}&screenshot=true&viewport.width=${options?.width || 1400}&viewport.height=${options?.height || 733}&viewport.deviceScaleFactor=${options?.deviceScaleFactor || 1}&meta=false&embed=screenshot.url&force=true`, + `https://api.cloudflare.com/client/v4/accounts/${process.env.CLOUDFLARE_ACCOUNT}/browser-rendering/screenshot`, { + method: "POST", headers: { - "x-api-key": process.env.MICROLINK_API_KEY!, - }, - next: { - revalidate: 600, + "Content-type": "application/json", + Authorization: `Bearer ${process.env.CLOUDFLARE_API_TOKEN}`, }, + body: JSON.stringify({ + url, + addStyleTag: [ + { + content: `* {overflow: hidden !important; }`, + }, + ], + gotoOptions: { + waitUntil: "load", + }, + viewport: { + width: options?.width || 1400, + height: options?.height || 733, + deviceScaleFactor: options?.deviceScaleFactor, + }, + }), + next: !options?.noCache + ? undefined + : { + revalidate: 600, + }, }, ); const clonedResponse = response.clone(); -- 2.51.2 From 86030fa61064c9a68d99adbc49c2ed198a65d80c Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 12:59:42 -0500 Subject: [PATCH 005/118] don't modify cache headers for cloudflare browser images --- src/utils/getMicroLinkOgImage.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/utils/getMicroLinkOgImage.ts b/src/utils/getMicroLinkOgImage.ts index fac40494..2d71e21c 100644 --- a/src/utils/getMicroLinkOgImage.ts +++ b/src/utils/getMicroLinkOgImage.ts @@ -56,17 +56,6 @@ export async function getWebpageImage( }, }, ); - const clonedResponse = response.clone(); - if (clonedResponse.status == 200) { - clonedResponse.headers.set( - "CDN-Cache-Control", - "s-maxage=600, stale-while-revalidate=3600", - ); - clonedResponse.headers.set( - "Cache-Control", - "s-maxage=600, stale-while-revalidate=3600", - ); - } - return clonedResponse; + return response; } -- 2.51.2 From 604cc827f41d311ea156e25d012de024b06a3af9 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 16:18:39 -0500 Subject: [PATCH 006/118] remove serverExternalPackages yjs --- next.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/next.config.js b/next.config.js index 68b3188e..f54ed91f 100644 --- a/next.config.js +++ b/next.config.js @@ -21,7 +21,6 @@ const nextConfig = { }, ]; }, - serverExternalPackages: ["yjs"], pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"], images: { loader: "custom", -- 2.51.2 From 4e8d3d34b508ebaab441aa5c584bd94f9b8e5a3e Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 16:20:36 -0500 Subject: [PATCH 007/118] Revert "render empty block as
" This reverts commit df74efe5d21a5f156350660894aa7680b3a888e8. --- components/Blocks/TextBlock/RenderYJSFragment.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Blocks/TextBlock/RenderYJSFragment.tsx b/components/Blocks/TextBlock/RenderYJSFragment.tsx index 94dc872f..132e72a7 100644 --- a/components/Blocks/TextBlock/RenderYJSFragment.tsx +++ b/components/Blocks/TextBlock/RenderYJSFragment.tsx @@ -27,7 +27,7 @@ export function RenderYJSFragment({ return ( {children.length === 0 ? ( -
+
) : ( node.toArray().map((node, index) => { if (node.constructor === XmlText) { -- 2.51.2 From 26eff9f5fb032ee330badb0943f48d3185d80c90 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 16:21:33 -0500 Subject: [PATCH 008/118] Revert "remove serverExternalPackages yjs" This reverts commit 604cc827f41d311ea156e25d012de024b06a3af9. --- next.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/next.config.js b/next.config.js index f54ed91f..68b3188e 100644 --- a/next.config.js +++ b/next.config.js @@ -21,6 +21,7 @@ const nextConfig = { }, ]; }, + serverExternalPackages: ["yjs"], pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"], images: { loader: "custom", -- 2.51.2 From 96b2c0b1485785027de30cef4d940f722ccc5e76 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 16:27:10 -0500 Subject: [PATCH 009/118] scroll page in browser screenshot --- src/utils/getMicroLinkOgImage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/getMicroLinkOgImage.ts b/src/utils/getMicroLinkOgImage.ts index 2d71e21c..c0b38592 100644 --- a/src/utils/getMicroLinkOgImage.ts +++ b/src/utils/getMicroLinkOgImage.ts @@ -35,6 +35,7 @@ export async function getWebpageImage( }, body: JSON.stringify({ url, + scrollPage: true, addStyleTag: [ { content: `* {overflow: hidden !important; }`, -- 2.51.2 From 9105cbfdf48231a2ededd043c988913468d80c79 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 16:49:19 -0500 Subject: [PATCH 010/118] catch editor state done before subscribing --- components/Blocks/TextBlock/mountProsemirror.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/Blocks/TextBlock/mountProsemirror.ts b/components/Blocks/TextBlock/mountProsemirror.ts index e77b36bd..f4a59e32 100644 --- a/components/Blocks/TextBlock/mountProsemirror.ts +++ b/components/Blocks/TextBlock/mountProsemirror.ts @@ -91,6 +91,10 @@ export function useMountProsemirror({ props }: { props: BlockProps }) { editorState.view?.updateState(editorState.editor); }); + let editorState = useEditorStates.getState().editorStates[entityID]; + if (editorState?.editor && !editorState.initial) + editorState.view?.updateState(editorState.editor); + return () => { unsubscribe(); view.destroy(); -- 2.51.2 From 416b6959b833ab2af354f618a2843317d68d77d9 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 17:10:57 -0500 Subject: [PATCH 011/118] make server time different from local --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 74fbb5ee..e7b52160 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "dev": "next dev --turbo", + "dev": "TZ=UTC next dev --turbo", "publish-lexicons": "tsx lexicons/publish.ts", "generate-db-types": "supabase gen types --local > supabase/database.types.ts && drizzle-kit introspect && rm -rf ./drizzle/*.sql ./drizzle/meta", "lexgen": "tsx ./lexicons/build.ts && lex gen-api ./lexicons/api ./lexicons/pub/leaflet/* ./lexicons/pub/leaflet/*/* ./lexicons/com/atproto/*/* ./lexicons/app/bsky/*/* --yes && find './lexicons/api' -type f -exec sed -i 's/\\.js'/'/g' {} \\;", -- 2.51.2 From cb5781ee29b7a53775612680cccf2b923064fcb1 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 17:32:39 -0500 Subject: [PATCH 012/118] fix scrollbar styling in screenshots --- src/utils/getMicroLinkOgImage.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/utils/getMicroLinkOgImage.ts b/src/utils/getMicroLinkOgImage.ts index c0b38592..f9386088 100644 --- a/src/utils/getMicroLinkOgImage.ts +++ b/src/utils/getMicroLinkOgImage.ts @@ -10,8 +10,12 @@ export async function getMicroLinkOgImage( }, ) { const headersList = await headers(); - const hostname = headersList.get("x-forwarded-host"); + let hostname = headersList.get("x-forwarded-host"); let protocol = headersList.get("x-forwarded-proto"); + if (process.env.NODE_ENV === "development") { + protocol === "https"; + hostname = "leaflet.pub"; + } let full_path = `${protocol}://${hostname}${path}`; return getWebpageImage(full_path, options); } @@ -38,7 +42,7 @@ export async function getWebpageImage( scrollPage: true, addStyleTag: [ { - content: `* {overflow: hidden !important; }`, + content: `* {scrollbar-width:none; }`, }, ], gotoOptions: { -- 2.51.2 From 76438c3d29a837f78e6ed069a1ffbe12ba977565 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 17 Nov 2025 17:45:20 -0500 Subject: [PATCH 013/118] rename confusing hook and reverse datetime pageload logic Squashed commit of the following: commit c3deb565892c3a87102ba2ba11a698d6907e4955 Author: Jared Pereira Date: Mon Nov 17 17:45:07 2025 -0500 remove logs commit 3ff4755bd48b52cef44f1e88a3f0ffda12670f28 Author: Jared Pereira Date: Mon Nov 17 17:38:04 2025 -0500 rename has page loaded and switch logic commit 558d9b7cb8c08a07277ac14bab3c465571ff0e7e Author: Jared Pereira Date: Mon Nov 17 17:19:00 2025 -0500 log effectivetz and locale commit 2748feba61f5e495480c92e108496da427be9727 Author: Jared Pereira Date: Mon Nov 17 17:11:17 2025 -0500 are we getting tz on server/client? --- .../[publication]/[rkey]/PublishBskyPostBlock.tsx | 4 ++-- components/Blocks/BlueskyPostBlock/index.tsx | 1 - components/Blocks/DateTimeBlock.tsx | 4 ++-- components/Blocks/TextBlock/index.tsx | 4 ++-- components/InitialPageLoadProvider.tsx | 4 ++-- components/Providers/RequestHeadersProvider.tsx | 6 +++++- src/hooks/useLocalizedDate.ts | 10 +++++----- 7 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/lish/[did]/[publication]/[rkey]/PublishBskyPostBlock.tsx b/app/lish/[did]/[publication]/[rkey]/PublishBskyPostBlock.tsx index 914c082e..596e12e2 100644 --- a/app/lish/[did]/[publication]/[rkey]/PublishBskyPostBlock.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PublishBskyPostBlock.tsx @@ -7,7 +7,7 @@ import { elementId } from "src/utils/elementId"; import { focusBlock } from "src/utils/focusBlock"; import { AppBskyFeedDefs, AppBskyFeedPost, RichText } from "@atproto/api"; import { Separator } from "components/Layout"; -import { useInitialPageLoad } from "components/InitialPageLoadProvider"; +import { useHasPageLoaded } from "components/InitialPageLoadProvider"; import { BlueskyTiny } from "components/Icons/BlueskyTiny"; import { CommentTiny } from "components/Icons/CommentTiny"; import { useLocalizedDate } from "src/hooks/useLocalizedDate"; @@ -123,7 +123,7 @@ export const PubBlueskyPostBlock = (props: { }; const ClientDate = (props: { date?: string }) => { - let pageLoaded = useInitialPageLoad(); + let pageLoaded = useHasPageLoaded(); const formattedDate = useLocalizedDate( props.date || new Date().toISOString(), { diff --git a/components/Blocks/BlueskyPostBlock/index.tsx b/components/Blocks/BlueskyPostBlock/index.tsx index d9169daa..bb04a7e3 100644 --- a/components/Blocks/BlueskyPostBlock/index.tsx +++ b/components/Blocks/BlueskyPostBlock/index.tsx @@ -10,7 +10,6 @@ import { BlueskyEmbed, PostNotAvailable } from "./BlueskyEmbed"; import { BlueskyPostEmpty } from "./BlueskyEmpty"; import { BlueskyRichText } from "./BlueskyRichText"; import { Separator } from "components/Layout"; -import { useInitialPageLoad } from "components/InitialPageLoadProvider"; import { BlueskyTiny } from "components/Icons/BlueskyTiny"; import { CommentTiny } from "components/Icons/CommentTiny"; import { useLocalizedDate } from "src/hooks/useLocalizedDate"; diff --git a/components/Blocks/DateTimeBlock.tsx b/components/Blocks/DateTimeBlock.tsx index 6e202355..29430a33 100644 --- a/components/Blocks/DateTimeBlock.tsx +++ b/components/Blocks/DateTimeBlock.tsx @@ -8,14 +8,14 @@ import { useUIState } from "src/useUIState"; import { setHours, setMinutes } from "date-fns"; import { Separator } from "react-aria-components"; import { Checkbox } from "components/Checkbox"; -import { useInitialPageLoad } from "components/InitialPageLoadProvider"; +import { useHasPageLoaded } from "components/InitialPageLoadProvider"; import { useSpring, animated } from "@react-spring/web"; import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; import { BlockCalendarSmall } from "components/Icons/BlockCalendarSmall"; export function DateTimeBlock(props: BlockProps) { const [isClient, setIsClient] = useState(false); - let initialPageLoad = useInitialPageLoad(); + let initialPageLoad = useHasPageLoaded(); useEffect(() => { setIsClient(true); diff --git a/components/Blocks/TextBlock/index.tsx b/components/Blocks/TextBlock/index.tsx index e143ac84..842efd10 100644 --- a/components/Blocks/TextBlock/index.tsx +++ b/components/Blocks/TextBlock/index.tsx @@ -4,7 +4,7 @@ import { useReplicache, useEntity } from "src/replicache"; import { isVisible } from "src/utils/isVisible"; import { EditorState, TextSelection } from "prosemirror-state"; import { RenderYJSFragment } from "./RenderYJSFragment"; -import { useInitialPageLoad } from "components/InitialPageLoadProvider"; +import { useHasPageLoaded } from "components/InitialPageLoadProvider"; import { BlockProps } from "../Block"; import { focusBlock } from "src/utils/focusBlock"; import { useUIState } from "src/useUIState"; @@ -37,7 +37,7 @@ export function TextBlock( }, ) { let isLocked = useEntity(props.entityID, "block/is-locked"); - let initialized = useInitialPageLoad(); + let initialized = useHasPageLoaded(); let first = props.previousBlock === null; let permission = useEntitySetContext().permissions.write; diff --git a/components/InitialPageLoadProvider.tsx b/components/InitialPageLoadProvider.tsx index a40eb2ac..7a408740 100644 --- a/components/InitialPageLoadProvider.tsx +++ b/components/InitialPageLoadProvider.tsx @@ -2,11 +2,11 @@ import { useEffect } from "react"; import { create } from "zustand"; -export const useInitialPageLoad = create(() => false); +export const useHasPageLoaded = create(() => false); export function InitialPageLoad(props: { children: React.ReactNode }) { useEffect(() => { setTimeout(() => { - useInitialPageLoad.setState(() => true); + useHasPageLoaded.setState(() => true); }, 80); }, []); return <>{props.children}; diff --git a/components/Providers/RequestHeadersProvider.tsx b/components/Providers/RequestHeadersProvider.tsx index f85a374a..7915e569 100644 --- a/components/Providers/RequestHeadersProvider.tsx +++ b/components/Providers/RequestHeadersProvider.tsx @@ -21,7 +21,11 @@ export const RequestHeadersProvider = (props: { }) => { return ( {props.children} diff --git a/src/hooks/useLocalizedDate.ts b/src/hooks/useLocalizedDate.ts index 4fab87f3..ad81a4cc 100644 --- a/src/hooks/useLocalizedDate.ts +++ b/src/hooks/useLocalizedDate.ts @@ -2,7 +2,7 @@ import { useContext, useMemo } from "react"; import { DateTime } from "luxon"; import { RequestHeadersContext } from "components/Providers/RequestHeadersProvider"; -import { useInitialPageLoad } from "components/InitialPageLoadProvider"; +import { useHasPageLoaded } from "components/InitialPageLoadProvider"; /** * Hook that formats a date string using Luxon with timezone and locale from request headers. @@ -20,14 +20,14 @@ export function useLocalizedDate( options?: Intl.DateTimeFormatOptions, ): string { const { timezone, language } = useContext(RequestHeadersContext); - const isInitialPageLoad = useInitialPageLoad(); + const hasPageLoaded = useHasPageLoaded(); return useMemo(() => { // Parse the date string to Luxon DateTime let dateTime = DateTime.fromISO(dateString); // On initial page load, use header timezone. After hydration, use system timezone - const effectiveTimezone = isInitialPageLoad + const effectiveTimezone = !hasPageLoaded ? timezone : Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -39,7 +39,7 @@ export function useLocalizedDate( // On initial page load, use header locale. After hydration, use system locale // Parse locale from accept-language header (take first locale) // accept-language format: "en-US,en;q=0.9,es;q=0.8" - const effectiveLocale = isInitialPageLoad + const effectiveLocale = !hasPageLoaded ? language?.split(",")[0]?.split(";")[0]?.trim() || "en-US" : Intl.DateTimeFormat().resolvedOptions().locale; @@ -49,5 +49,5 @@ export function useLocalizedDate( // Fallback to en-US if locale is invalid return dateTime.toLocaleString(options, { locale: "en-US" }); } - }, [dateString, options, timezone, language, isInitialPageLoad]); + }, [dateString, options, timezone, language, hasPageLoaded]); } -- 2.51.2 From 260781c6687a70653ae71d14208d0bb10adf27fb Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 18 Nov 2025 13:57:49 -0500 Subject: [PATCH 014/118] create leaflet_to_documents table --- drizzle/relations.ts | 24 ++++--- drizzle/schema.ts | 12 +++- supabase/database.types.ts | 39 ++++++++++++ ...251118185507_add_leaflets_to_documents.sql | 63 +++++++++++++++++++ 4 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 supabase/migrations/20251118185507_add_leaflets_to_documents.sql diff --git a/drizzle/relations.ts b/drizzle/relations.ts index ee948385..1e08d4fe 100644 --- a/drizzle/relations.ts +++ b/drizzle/relations.ts @@ -1,19 +1,15 @@ import { relations } from "drizzle-orm/relations"; -import { identities, publications, documents, comments_on_documents, bsky_profiles, entity_sets, entities, facts, email_auth_tokens, poll_votes_on_entity, permission_tokens, phone_rsvps_to_entity, custom_domains, custom_domain_routes, email_subscriptions_to_entity, atp_poll_records, atp_poll_votes, bsky_follows, subscribers_to_publications, permission_token_on_homepage, documents_in_publications, document_mentions_in_bsky, bsky_posts, publication_domains, leaflets_in_publications, publication_subscriptions, permission_token_rights } from "./schema"; +import { identities, notifications, publications, documents, comments_on_documents, bsky_profiles, entity_sets, entities, facts, email_auth_tokens, poll_votes_on_entity, permission_tokens, phone_rsvps_to_entity, custom_domains, custom_domain_routes, email_subscriptions_to_entity, atp_poll_records, atp_poll_votes, bsky_follows, subscribers_to_publications, permission_token_on_homepage, documents_in_publications, document_mentions_in_bsky, bsky_posts, publication_domains, leaflets_in_publications, publication_subscriptions, permission_token_rights } from "./schema"; -export const publicationsRelations = relations(publications, ({one, many}) => ({ +export const notificationsRelations = relations(notifications, ({one}) => ({ identity: one(identities, { - fields: [publications.identity_did], + fields: [notifications.recipient], references: [identities.atp_did] }), - subscribers_to_publications: many(subscribers_to_publications), - documents_in_publications: many(documents_in_publications), - publication_domains: many(publication_domains), - leaflets_in_publications: many(leaflets_in_publications), - publication_subscriptions: many(publication_subscriptions), })); export const identitiesRelations = relations(identities, ({one, many}) => ({ + notifications: many(notifications), publications: many(publications), email_auth_tokens: many(email_auth_tokens), bsky_profiles: many(bsky_profiles), @@ -39,6 +35,18 @@ export const identitiesRelations = relations(identities, ({one, many}) => ({ publication_subscriptions: many(publication_subscriptions), })); +export const publicationsRelations = relations(publications, ({one, many}) => ({ + identity: one(identities, { + fields: [publications.identity_did], + references: [identities.atp_did] + }), + subscribers_to_publications: many(subscribers_to_publications), + documents_in_publications: many(documents_in_publications), + publication_domains: many(publication_domains), + leaflets_in_publications: many(leaflets_in_publications), + publication_subscriptions: many(publication_subscriptions), +})); + export const comments_on_documentsRelations = relations(comments_on_documents, ({one}) => ({ document: one(documents, { fields: [comments_on_documents.document], diff --git a/drizzle/schema.ts b/drizzle/schema.ts index 4745bf86..153b82e6 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -1,4 +1,4 @@ -import { pgTable, pgEnum, text, jsonb, index, foreignKey, timestamp, uuid, bigint, boolean, unique, uniqueIndex, smallint, primaryKey } from "drizzle-orm/pg-core" +import { pgTable, pgEnum, text, jsonb, foreignKey, timestamp, boolean, uuid, index, bigint, unique, uniqueIndex, smallint, primaryKey } from "drizzle-orm/pg-core" import { sql } from "drizzle-orm" export const aal_level = pgEnum("aal_level", ['aal1', 'aal2', 'aal3']) @@ -15,7 +15,7 @@ export const key_type = pgEnum("key_type", ['aead-ietf', 'aead-det', 'hmacsha512 export const rsvp_status = pgEnum("rsvp_status", ['GOING', 'NOT_GOING', 'MAYBE']) export const action = pgEnum("action", ['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'ERROR']) export const equality_op = pgEnum("equality_op", ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in']) -export const buckettype = pgEnum("buckettype", ['STANDARD', 'ANALYTICS']) +export const buckettype = pgEnum("buckettype", ['STANDARD', 'ANALYTICS', 'VECTOR']) export const oauth_state_store = pgTable("oauth_state_store", { @@ -23,6 +23,14 @@ export const oauth_state_store = pgTable("oauth_state_store", { state: jsonb("state").notNull(), }); +export const notifications = pgTable("notifications", { + recipient: text("recipient").notNull().references(() => identities.atp_did, { onDelete: "cascade", onUpdate: "cascade" } ), + created_at: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(), + read: boolean("read").default(false).notNull(), + data: jsonb("data").notNull(), + id: uuid("id").primaryKey().notNull(), +}); + export const publications = pgTable("publications", { uri: text("uri").primaryKey().notNull(), indexed_at: timestamp("indexed_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(), diff --git a/supabase/database.types.ts b/supabase/database.types.ts index ae0c93b0..93efcbe3 100644 --- a/supabase/database.types.ts +++ b/supabase/database.types.ts @@ -624,6 +624,45 @@ export type Database = { }, ] } + leaflets_to_documents: { + Row: { + created_at: string + description: string + document: string + leaflet: string + title: string + } + Insert: { + created_at?: string + description?: string + document: string + leaflet: string + title?: string + } + Update: { + created_at?: string + description?: string + document?: string + leaflet?: string + title?: string + } + Relationships: [ + { + foreignKeyName: "leaflets_to_documents_document_fkey" + columns: ["document"] + isOneToOne: false + referencedRelation: "documents" + referencedColumns: ["uri"] + }, + { + foreignKeyName: "leaflets_to_documents_leaflet_fkey" + columns: ["leaflet"] + isOneToOne: false + referencedRelation: "permission_tokens" + referencedColumns: ["id"] + }, + ] + } notifications: { Row: { created_at: string diff --git a/supabase/migrations/20251118185507_add_leaflets_to_documents.sql b/supabase/migrations/20251118185507_add_leaflets_to_documents.sql new file mode 100644 index 00000000..f79aa7cd --- /dev/null +++ b/supabase/migrations/20251118185507_add_leaflets_to_documents.sql @@ -0,0 +1,63 @@ +create table "public"."leaflets_to_documents" ( + "leaflet" uuid not null, + "document" text not null, + "created_at" timestamp with time zone not null default now(), + "title" text not null default ''::text, + "description" text not null default ''::text +); + +alter table "public"."leaflets_to_documents" enable row level security; + +CREATE UNIQUE INDEX leaflets_to_documents_pkey ON public.leaflets_to_documents USING btree (leaflet, document); + +alter table "public"."leaflets_to_documents" add constraint "leaflets_to_documents_pkey" PRIMARY KEY using index "leaflets_to_documents_pkey"; + +alter table "public"."leaflets_to_documents" add constraint "leaflets_to_documents_document_fkey" FOREIGN KEY (document) REFERENCES documents(uri) ON UPDATE CASCADE ON DELETE CASCADE not valid; + +alter table "public"."leaflets_to_documents" validate constraint "leaflets_to_documents_document_fkey"; + +alter table "public"."leaflets_to_documents" add constraint "leaflets_to_documents_leaflet_fkey" FOREIGN KEY (leaflet) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; + +alter table "public"."leaflets_to_documents" validate constraint "leaflets_to_documents_leaflet_fkey"; + +grant delete on table "public"."leaflets_to_documents" to "anon"; + +grant insert on table "public"."leaflets_to_documents" to "anon"; + +grant references on table "public"."leaflets_to_documents" to "anon"; + +grant select on table "public"."leaflets_to_documents" to "anon"; + +grant trigger on table "public"."leaflets_to_documents" to "anon"; + +grant truncate on table "public"."leaflets_to_documents" to "anon"; + +grant update on table "public"."leaflets_to_documents" to "anon"; + +grant delete on table "public"."leaflets_to_documents" to "authenticated"; + +grant insert on table "public"."leaflets_to_documents" to "authenticated"; + +grant references on table "public"."leaflets_to_documents" to "authenticated"; + +grant select on table "public"."leaflets_to_documents" to "authenticated"; + +grant trigger on table "public"."leaflets_to_documents" to "authenticated"; + +grant truncate on table "public"."leaflets_to_documents" to "authenticated"; + +grant update on table "public"."leaflets_to_documents" to "authenticated"; + +grant delete on table "public"."leaflets_to_documents" to "service_role"; + +grant insert on table "public"."leaflets_to_documents" to "service_role"; + +grant references on table "public"."leaflets_to_documents" to "service_role"; + +grant select on table "public"."leaflets_to_documents" to "service_role"; + +grant trigger on table "public"."leaflets_to_documents" to "service_role"; + +grant truncate on table "public"."leaflets_to_documents" to "service_role"; + +grant update on table "public"."leaflets_to_documents" to "service_role"; -- 2.51.2 From 14fa6e7219fc80aaf9bb4ee33c4b654420c6ea58 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 18 Nov 2025 17:32:55 -0500 Subject: [PATCH 015/118] fix notifications empty state logic --- app/(home-pages)/notifications/NotificationList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/(home-pages)/notifications/NotificationList.tsx b/app/(home-pages)/notifications/NotificationList.tsx index bc0f054b..9cee7bba 100644 --- a/app/(home-pages)/notifications/NotificationList.tsx +++ b/app/(home-pages)/notifications/NotificationList.tsx @@ -23,7 +23,7 @@ export function NotificationList({ }, 500); }, []); - if (notifications.length !== 0) + if (notifications.length === 0) return (
no notifications yet...
-- 2.51.2 From 373b04cf5ecd28b68858a89de77de669dc485984 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 18 Nov 2025 17:54:53 -0500 Subject: [PATCH 016/118] empty text block as br not div --- components/Blocks/TextBlock/RenderYJSFragment.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Blocks/TextBlock/RenderYJSFragment.tsx b/components/Blocks/TextBlock/RenderYJSFragment.tsx index 132e72a7..94dc872f 100644 --- a/components/Blocks/TextBlock/RenderYJSFragment.tsx +++ b/components/Blocks/TextBlock/RenderYJSFragment.tsx @@ -27,7 +27,7 @@ export function RenderYJSFragment({ return ( {children.length === 0 ? ( -
+
) : ( node.toArray().map((node, index) => { if (node.constructor === XmlText) { -- 2.51.2 From 4ca94f361f208e9eff7aee9efcfc1c11b4e0b618 Mon Sep 17 00:00:00 2001 From: celine Date: Wed, 19 Nov 2025 14:25:15 -0500 Subject: [PATCH 017/118] add archived column to permission tokens on home table --- supabase/database.types.ts | 3 +++ ...119191717_add_archived_to_permission_tokens_on_homepage.sql | 1 + 2 files changed, 4 insertions(+) create mode 100644 supabase/migrations/20251119191717_add_archived_to_permission_tokens_on_homepage.sql diff --git a/supabase/database.types.ts b/supabase/database.types.ts index 93efcbe3..a27007c7 100644 --- a/supabase/database.types.ts +++ b/supabase/database.types.ts @@ -727,16 +727,19 @@ export type Database = { } permission_token_on_homepage: { Row: { + archived: boolean | null created_at: string identity: string token: string } Insert: { + archived?: boolean | null created_at?: string identity: string token: string } Update: { + archived?: boolean | null created_at?: string identity?: string token?: string diff --git a/supabase/migrations/20251119191717_add_archived_to_permission_tokens_on_homepage.sql b/supabase/migrations/20251119191717_add_archived_to_permission_tokens_on_homepage.sql new file mode 100644 index 00000000..c5ad7ec9 --- /dev/null +++ b/supabase/migrations/20251119191717_add_archived_to_permission_tokens_on_homepage.sql @@ -0,0 +1 @@ +alter table "public"."permission_token_on_homepage" add column "archived" boolean; -- 2.51.2 From edf0461885622fdd752ac7c0b428e3e1f2fa0ab6 Mon Sep 17 00:00:00 2001 From: celine Date: Thu, 20 Nov 2025 16:56:44 -0500 Subject: [PATCH 018/118] add archived col to leaflets in publicaitons --- supabase/database.types.ts | 3 +++ ...1120215250_add_archived_col_to_leaflets_in_publications.sql | 1 + 2 files changed, 4 insertions(+) create mode 100644 supabase/migrations/20251120215250_add_archived_col_to_leaflets_in_publications.sql diff --git a/supabase/database.types.ts b/supabase/database.types.ts index a27007c7..43d56b03 100644 --- a/supabase/database.types.ts +++ b/supabase/database.types.ts @@ -580,6 +580,7 @@ export type Database = { } leaflets_in_publications: { Row: { + archived: boolean | null description: string doc: string | null leaflet: string @@ -587,6 +588,7 @@ export type Database = { title: string } Insert: { + archived?: boolean | null description?: string doc?: string | null leaflet: string @@ -594,6 +596,7 @@ export type Database = { title?: string } Update: { + archived?: boolean | null description?: string doc?: string | null leaflet?: string diff --git a/supabase/migrations/20251120215250_add_archived_col_to_leaflets_in_publications.sql b/supabase/migrations/20251120215250_add_archived_col_to_leaflets_in_publications.sql new file mode 100644 index 00000000..cad7a1c0 --- /dev/null +++ b/supabase/migrations/20251120215250_add_archived_col_to_leaflets_in_publications.sql @@ -0,0 +1 @@ +alter table "public"."leaflets_in_publications" add column "archived" boolean; -- 2.51.2 From 09f1e55e3663cdeea4d9bfe7633dbf7401728c70 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Fri, 21 Nov 2025 15:34:27 -0500 Subject: [PATCH 019/118] count line breaks in bsky post editor as length --- app/[leaflet_id]/publish/BskyPostEditorProsemirror.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/[leaflet_id]/publish/BskyPostEditorProsemirror.tsx b/app/[leaflet_id]/publish/BskyPostEditorProsemirror.tsx index ff69b158..12af9a55 100644 --- a/app/[leaflet_id]/publish/BskyPostEditorProsemirror.tsx +++ b/app/[leaflet_id]/publish/BskyPostEditorProsemirror.tsx @@ -245,7 +245,9 @@ export function BlueskyPostEditorProsemirror(props: { view.updateState(newState); setEditorState(newState); props.editorStateRef.current = newState; - props.onCharCountChange?.(newState.doc.textContent.length); + props.onCharCountChange?.( + newState.doc.textContent.length + newState.doc.children.length - 1, + ); }, }, ); -- 2.51.2 From 07c18f454207969d641581a21e291fc0a61c11b2 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Fri, 21 Nov 2025 17:32:13 -0500 Subject: [PATCH 020/118] add notifications for bsky post mentions --- .../notifications/MentionNotification.tsx | 67 ++++++++----------- .../notifications/NotificationList.tsx | 4 ++ .../inngest/functions/index_post_mention.ts | 31 +++++++-- src/notifications.ts | 51 ++++++++++++-- 4 files changed, 105 insertions(+), 48 deletions(-) diff --git a/app/(home-pages)/notifications/MentionNotification.tsx b/app/(home-pages)/notifications/MentionNotification.tsx index 58ee25ee..7b24349c 100644 --- a/app/(home-pages)/notifications/MentionNotification.tsx +++ b/app/(home-pages)/notifications/MentionNotification.tsx @@ -1,50 +1,39 @@ import { MentionTiny } from "components/Icons/MentionTiny"; import { ContentLayout, Notification } from "./Notification"; +import { HydratedQuoteNotification } from "src/notifications"; +import { PubLeafletDocument, PubLeafletPublication } from "lexicons/api"; +import { AtUri } from "@atproto/api"; +import { Avatar } from "components/Avatar"; -export const DummyPostMentionNotification = (props: {}) => { - return ( - } - actionText={<>celine mentioned your post} - content={ - - I'm just gonna put the description here. The surrounding context is - just sort of a pain to figure out -
-
Title of the Mentioned Post
-
- And here is the description that follows it -
-
-
- } - /> - ); -}; +export const QuoteNotification = (props: HydratedQuoteNotification) => { + const postView = props.bskyPost.post_view as any; + const author = postView.author; + const displayName = author.displayName || author.handle || "Someone"; + const docRecord = props.document.data as PubLeafletDocument.Record; + const pubRecord = props.document.documents_in_publications[0]?.publications + ?.record as PubLeafletPublication.Record; + const rkey = new AtUri(props.document.uri).rkey; + const postText = postView.record?.text || ""; -export const DummyUserMentionNotification = (props: { - cardBorderHidden: boolean; -}) => { return ( } - actionText={<>celine mentioned you} + actionText={<>{displayName} quoted your post} content={ - -
- ...llo this is the content of a post or whatever here it comes{" "} - @celine and here it - was! ooooh heck yeah the high is unre... + +
+ +
+              {postText}
+            
} diff --git a/app/(home-pages)/notifications/NotificationList.tsx b/app/(home-pages)/notifications/NotificationList.tsx index 9cee7bba..74f085a0 100644 --- a/app/(home-pages)/notifications/NotificationList.tsx +++ b/app/(home-pages)/notifications/NotificationList.tsx @@ -7,6 +7,7 @@ import { markAsRead } from "./getNotifications"; import { ReplyNotification } from "./ReplyNotification"; import { useIdentityData } from "components/IdentityProvider"; import { FollowNotification } from "./FollowNotification"; +import { QuoteNotification } from "./MentionNotification"; export function NotificationList({ notifications, @@ -42,6 +43,9 @@ export function NotificationList({ if (n.type === "subscribe") { return ; } + if (n.type === "quote") { + return ; + } })}
diff --git a/app/api/inngest/functions/index_post_mention.ts b/app/api/inngest/functions/index_post_mention.ts index 06150cb0..73edfbe2 100644 --- a/app/api/inngest/functions/index_post_mention.ts +++ b/app/api/inngest/functions/index_post_mention.ts @@ -3,6 +3,8 @@ import { inngest } from "../client"; import { AtpAgent, AtUri } from "@atproto/api"; import { Json } from "supabase/database.types"; import { ids } from "lexicons/api/lexicons"; +import { Notification, pingIdentityToUpdateNotification } from "src/notifications"; +import { v7 } from "uuid"; export const index_post_mention = inngest.createFunction( { id: "index_post_mention" }, @@ -37,6 +39,12 @@ export const index_post_mention = inngest.createFunction( return { message: `No post found for ${event.data.post_uri}` }; } + const documentUri = AtUri.make( + pub.identity_did, + ids.PubLeafletDocument, + path[0], + ).toString(); + await step.run("index-bsky-post", async () => { await supabaseServerClient.from("bsky_posts").insert({ uri: bsky_post.uri, @@ -45,13 +53,26 @@ export const index_post_mention = inngest.createFunction( }); await supabaseServerClient.from("document_mentions_in_bsky").insert({ uri: bsky_post.uri, - document: AtUri.make( - pub.identity_did, - ids.PubLeafletDocument, - path[0], - ).toString(), + document: documentUri, link: event.data.document_link, }); }); + + await step.run("create-notification", async () => { + // Only create notification if the quote is from someone other than the author + if (bsky_post.author.did !== pub.identity_did) { + const notification: Notification = { + id: v7(), + recipient: pub.identity_did, + data: { + type: "quote", + bsky_post_uri: bsky_post.uri, + document_uri: documentUri, + }, + }; + await supabaseServerClient.from("notifications").insert(notification); + await pingIdentityToUpdateNotification(pub.identity_did); + } + }); }, ); diff --git a/src/notifications.ts b/src/notifications.ts index 4b6301d6..cc6acab0 100644 --- a/src/notifications.ts +++ b/src/notifications.ts @@ -11,22 +11,25 @@ export type Notification = Omit, "data"> & { export type NotificationData = | { type: "comment"; comment_uri: string; parent_uri?: string } - | { type: "subscribe"; subscription_uri: string }; + | { type: "subscribe"; subscription_uri: string } + | { type: "quote"; bsky_post_uri: string; document_uri: string }; export type HydratedNotification = | HydratedCommentNotification - | HydratedSubscribeNotification; + | HydratedSubscribeNotification + | HydratedQuoteNotification; export async function hydrateNotifications( notifications: NotificationRow[], ): Promise> { // Call all hydrators in parallel - const [commentNotifications, subscribeNotifications] = await Promise.all([ + const [commentNotifications, subscribeNotifications, quoteNotifications] = await Promise.all([ hydrateCommentNotifications(notifications), hydrateSubscribeNotifications(notifications), + hydrateQuoteNotifications(notifications), ]); // Combine all hydrated notifications - const allHydrated = [...commentNotifications, ...subscribeNotifications]; + const allHydrated = [...commentNotifications, ...subscribeNotifications, ...quoteNotifications]; // Sort by created_at to maintain order allHydrated.sort( @@ -122,6 +125,46 @@ async function hydrateSubscribeNotifications(notifications: NotificationRow[]) { })); } +export type HydratedQuoteNotification = Awaited< + ReturnType +>[0]; + +async function hydrateQuoteNotifications(notifications: NotificationRow[]) { + const quoteNotifications = notifications.filter( + (n): n is NotificationRow & { data: ExtractNotificationType<"quote"> } => + (n.data as NotificationData)?.type === "quote", + ); + + if (quoteNotifications.length === 0) { + return []; + } + + // Fetch bsky post data and document data + const bskyPostUris = quoteNotifications.map((n) => n.data.bsky_post_uri); + const documentUris = quoteNotifications.map((n) => n.data.document_uri); + + const { data: bskyPosts } = await supabaseServerClient + .from("bsky_posts") + .select("*") + .in("uri", bskyPostUris); + + const { data: documents } = await supabaseServerClient + .from("documents") + .select("*, documents_in_publications(publications(*))") + .in("uri", documentUris); + + return quoteNotifications.map((notification) => ({ + id: notification.id, + recipient: notification.recipient, + created_at: notification.created_at, + type: "quote" as const, + bsky_post_uri: notification.data.bsky_post_uri, + document_uri: notification.data.document_uri, + bskyPost: bskyPosts?.find((p) => p.uri === notification.data.bsky_post_uri)!, + document: documents?.find((d) => d.uri === notification.data.document_uri)!, + })); +} + export async function pingIdentityToUpdateNotification(did: string) { let channel = supabaseServerClient.channel(`identity.atp_did:${did}`); await channel.send({ -- 2.51.2 From 632093e627310b2485976f18a9fedc0f35665c4d Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Fri, 21 Nov 2025 17:42:18 -0500 Subject: [PATCH 021/118] use quotetiny not mentiontiny as quote notification icon --- app/(home-pages)/notifications/MentionNotification.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/(home-pages)/notifications/MentionNotification.tsx b/app/(home-pages)/notifications/MentionNotification.tsx index 7b24349c..a50304d8 100644 --- a/app/(home-pages)/notifications/MentionNotification.tsx +++ b/app/(home-pages)/notifications/MentionNotification.tsx @@ -1,4 +1,4 @@ -import { MentionTiny } from "components/Icons/MentionTiny"; +import { QuoteTiny } from "components/Icons/QuoteTiny"; import { ContentLayout, Notification } from "./Notification"; import { HydratedQuoteNotification } from "src/notifications"; import { PubLeafletDocument, PubLeafletPublication } from "lexicons/api"; @@ -19,7 +19,7 @@ export const QuoteNotification = (props: HydratedQuoteNotification) => { } + icon={} actionText={<>{displayName} quoted your post} content={ -- 2.51.2 From 0265ad44b4dd9c30480aa367ebaa9b9bec03f911 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Fri, 21 Nov 2025 17:49:52 -0500 Subject: [PATCH 022/118] handle multiple ingests for posts --- .../inngest/functions/index_post_mention.ts | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/app/api/inngest/functions/index_post_mention.ts b/app/api/inngest/functions/index_post_mention.ts index 73edfbe2..591874fe 100644 --- a/app/api/inngest/functions/index_post_mention.ts +++ b/app/api/inngest/functions/index_post_mention.ts @@ -46,12 +46,12 @@ export const index_post_mention = inngest.createFunction( ).toString(); await step.run("index-bsky-post", async () => { - await supabaseServerClient.from("bsky_posts").insert({ + await supabaseServerClient.from("bsky_posts").upsert({ uri: bsky_post.uri, cid: bsky_post.cid, post_view: bsky_post as Json, }); - await supabaseServerClient.from("document_mentions_in_bsky").insert({ + await supabaseServerClient.from("document_mentions_in_bsky").upsert({ uri: bsky_post.uri, document: documentUri, link: event.data.document_link, @@ -61,17 +61,29 @@ export const index_post_mention = inngest.createFunction( await step.run("create-notification", async () => { // Only create notification if the quote is from someone other than the author if (bsky_post.author.did !== pub.identity_did) { - const notification: Notification = { - id: v7(), - recipient: pub.identity_did, - data: { - type: "quote", - bsky_post_uri: bsky_post.uri, - document_uri: documentUri, - }, - }; - await supabaseServerClient.from("notifications").insert(notification); - await pingIdentityToUpdateNotification(pub.identity_did); + // Check if a notification already exists for this post and recipient + const { data: existingNotification } = await supabaseServerClient + .from("notifications") + .select("id") + .eq("recipient", pub.identity_did) + .eq("data->>type", "quote") + .eq("data->>bsky_post_uri", bsky_post.uri) + .eq("data->>document_uri", documentUri) + .single(); + + if (!existingNotification) { + const notification: Notification = { + id: v7(), + recipient: pub.identity_did, + data: { + type: "quote", + bsky_post_uri: bsky_post.uri, + document_uri: documentUri, + }, + }; + await supabaseServerClient.from("notifications").insert(notification); + await pingIdentityToUpdateNotification(pub.identity_did); + } } }); }, -- 2.51.2 From 8d7d293cd2bf55d39cbe3ad11c85cd4eaa4265f7 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Sat, 22 Nov 2025 02:59:02 -0500 Subject: [PATCH 023/118] add some scroll preservation to pub layouts --- .../[publication]/PublicationHomeLayout.tsx | 24 ++ app/lish/[did]/[publication]/page.tsx | 222 +++++++++--------- components/Pages/Page.tsx | 3 + 3 files changed, 136 insertions(+), 113 deletions(-) create mode 100644 app/lish/[did]/[publication]/PublicationHomeLayout.tsx diff --git a/app/lish/[did]/[publication]/PublicationHomeLayout.tsx b/app/lish/[did]/[publication]/PublicationHomeLayout.tsx new file mode 100644 index 00000000..4324f834 --- /dev/null +++ b/app/lish/[did]/[publication]/PublicationHomeLayout.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { usePreserveScroll } from "src/hooks/usePreserveScroll"; + +export function PublicationHomeLayout(props: { + uri: string; + showPageBackground: boolean; + children: React.ReactNode; +}) { + let { ref } = usePreserveScroll(props.uri); + return ( +
+
+ {props.children} +
+
+ ); +} diff --git a/app/lish/[did]/[publication]/page.tsx b/app/lish/[did]/[publication]/page.tsx index 0d217124..20487e88 100644 --- a/app/lish/[did]/[publication]/page.tsx +++ b/app/lish/[did]/[publication]/page.tsx @@ -15,6 +15,7 @@ import { SpeedyLink } from "components/SpeedyLink"; import { QuoteTiny } from "components/Icons/QuoteTiny"; import { CommentTiny } from "components/Icons/CommentTiny"; import { LocalizedDate } from "./LocalizedDate"; +import { PublicationHomeLayout } from "./PublicationHomeLayout"; export default async function Publication(props: { params: Promise<{ publication: string; did: string }>; @@ -66,131 +67,126 @@ export default async function Publication(props: { record={record} pub_creator={publication.identity_did} > -
-
-
- {record?.icon && ( -
- )} -

- {publication.name} -

-

- {record?.description}{" "} +

+ {record?.icon && ( +
+ )} +

+ {publication.name} +

+

+ {record?.description}{" "} +

+ {profile && ( +

+ by {profile.displayName}{" "} + + @{profile.handle} +

- {profile && ( -

- by {profile.displayName}{" "} - - @{profile.handle} - -

- )} -
- -
+ )} +
+
-
- {publication.documents_in_publications - .filter((d) => !!d?.documents) - .sort((a, b) => { - let aRecord = a.documents - ?.data! as PubLeafletDocument.Record; - let bRecord = b.documents - ?.data! as PubLeafletDocument.Record; - const aDate = aRecord.publishedAt - ? new Date(aRecord.publishedAt) - : new Date(0); - const bDate = bRecord.publishedAt - ? new Date(bRecord.publishedAt) - : new Date(0); - return bDate.getTime() - aDate.getTime(); // Sort by most recent first - }) - .map((doc) => { - if (!doc.documents) return null; - let uri = new AtUri(doc.documents.uri); - let doc_record = doc.documents - .data as PubLeafletDocument.Record; - let quotes = - doc.documents.document_mentions_in_bsky[0].count || 0; - let comments = - record?.preferences?.showComments === false - ? 0 - : doc.documents.comments_on_documents[0].count || 0; +
+
+ {publication.documents_in_publications + .filter((d) => !!d?.documents) + .sort((a, b) => { + let aRecord = a.documents?.data! as PubLeafletDocument.Record; + let bRecord = b.documents?.data! as PubLeafletDocument.Record; + const aDate = aRecord.publishedAt + ? new Date(aRecord.publishedAt) + : new Date(0); + const bDate = bRecord.publishedAt + ? new Date(bRecord.publishedAt) + : new Date(0); + return bDate.getTime() - aDate.getTime(); // Sort by most recent first + }) + .map((doc) => { + if (!doc.documents) return null; + let uri = new AtUri(doc.documents.uri); + let doc_record = doc.documents + .data as PubLeafletDocument.Record; + let quotes = + doc.documents.document_mentions_in_bsky[0].count || 0; + let comments = + record?.preferences?.showComments === false + ? 0 + : doc.documents.comments_on_documents[0].count || 0; - return ( - -
- -

{doc_record.title}

-

- {doc_record.description} -

-
+ return ( + +
+ +

{doc_record.title}

+

+ {doc_record.description} +

+
-
-

- {doc_record.publishedAt && ( - - )}{" "} -

- {comments > 0 || quotes > 0 ? "| " : ""} - {quotes > 0 && ( +
+

+ {doc_record.publishedAt && ( + + )}{" "} +

+ {comments > 0 || quotes > 0 ? "| " : ""} + {quotes > 0 && ( + + {quotes} + + )} + {comments > 0 && + record?.preferences?.showComments !== false && ( - {quotes} + {comments} )} - {comments > 0 && - record?.preferences?.showComments !== false && ( - - {comments} - - )} -
-
- - ); - })} -
+
+
+
+ ); + })}
-
+ ); diff --git a/components/Pages/Page.tsx b/components/Pages/Page.tsx index f9c7144f..59b5183c 100644 --- a/components/Pages/Page.tsx +++ b/components/Pages/Page.tsx @@ -16,6 +16,7 @@ import { focusPage } from "."; import { PageOptions } from "./PageOptions"; import { CardThemeProvider } from "components/ThemeManager/ThemeProvider"; import { useDrawerOpen } from "app/lish/[did]/[publication]/[rkey]/Interactions/InteractionDrawer"; +import { usePreserveScroll } from "src/hooks/usePreserveScroll"; export function Page(props: { entityID: string; @@ -83,6 +84,7 @@ export const PageWrapper = (props: { pageType: "canvas" | "doc"; drawerOpen: boolean | undefined; }) => { + let { ref } = usePreserveScroll(props.id); return ( // this div wraps the contents AND the page options. // it needs to be its own div because this container does NOT scroll, and therefore doesn't clip the absolutely positioned pageOptions @@ -95,6 +97,7 @@ export const PageWrapper = (props: { it needs to be a separate div so that the user can scroll from anywhere on the page if there isn't a card border */}
Date: Sat, 22 Nov 2025 17:02:23 -0500 Subject: [PATCH 024/118] add on update cascade to pt relations --- ...0118_add_cascade_on_update_to_pt_relations.sql | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 supabase/migrations/20251122220118_add_cascade_on_update_to_pt_relations.sql diff --git a/supabase/migrations/20251122220118_add_cascade_on_update_to_pt_relations.sql b/supabase/migrations/20251122220118_add_cascade_on_update_to_pt_relations.sql new file mode 100644 index 00000000..e363755c --- /dev/null +++ b/supabase/migrations/20251122220118_add_cascade_on_update_to_pt_relations.sql @@ -0,0 +1,15 @@ +alter table "public"."permission_token_on_homepage" drop constraint "permission_token_creator_token_fkey"; + +alter table "public"."leaflets_in_publications" drop constraint "leaflets_in_publications_leaflet_fkey"; + +alter table "public"."leaflets_in_publications" drop column "archived"; + +alter table "public"."permission_token_on_homepage" drop column "archived"; + +alter table "public"."permission_token_on_homepage" add constraint "permission_token_on_homepage_token_fkey" FOREIGN KEY (token) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; + +alter table "public"."permission_token_on_homepage" validate constraint "permission_token_on_homepage_token_fkey"; + +alter table "public"."leaflets_in_publications" add constraint "leaflets_in_publications_leaflet_fkey" FOREIGN KEY (leaflet) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; + +alter table "public"."leaflets_in_publications" validate constraint "leaflets_in_publications_leaflet_fkey"; -- 2.51.2 From 695201ca99bf5cae29a770d22aaf627d2165d2b8 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Sat, 22 Nov 2025 17:04:41 -0500 Subject: [PATCH 025/118] fix type error --- app/lish/[did]/[publication]/page.tsx | 2 +- components/Pages/Page.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lish/[did]/[publication]/page.tsx b/app/lish/[did]/[publication]/page.tsx index 20487e88..aa1ac273 100644 --- a/app/lish/[did]/[publication]/page.tsx +++ b/app/lish/[did]/[publication]/page.tsx @@ -69,7 +69,7 @@ export default async function Publication(props: { >
{record?.icon && ( diff --git a/components/Pages/Page.tsx b/components/Pages/Page.tsx index 59b5183c..fffb4a39 100644 --- a/components/Pages/Page.tsx +++ b/components/Pages/Page.tsx @@ -84,7 +84,7 @@ export const PageWrapper = (props: { pageType: "canvas" | "doc"; drawerOpen: boolean | undefined; }) => { - let { ref } = usePreserveScroll(props.id); + let { ref } = usePreserveScroll(props.id); return ( // this div wraps the contents AND the page options. // it needs to be its own div because this container does NOT scroll, and therefore doesn't clip the absolutely positioned pageOptions -- 2.51.2 From 7a1864ae2b66b78d362e20703e779ce07a0b17f2 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Sun, 23 Nov 2025 22:01:40 -0500 Subject: [PATCH 026/118] add hard breaks (#237) --- .../[did]/[publication]/[rkey]/BaseTextBlock.tsx | 12 +++++++++--- components/Blocks/TextBlock/RenderYJSFragment.tsx | 8 ++++++++ components/Blocks/TextBlock/keymap.ts | 10 +++++----- components/Blocks/TextBlock/schema.ts | 7 +++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/app/lish/[did]/[publication]/[rkey]/BaseTextBlock.tsx b/app/lish/[did]/[publication]/[rkey]/BaseTextBlock.tsx index 320cfe94..ee45e009 100644 --- a/app/lish/[did]/[publication]/[rkey]/BaseTextBlock.tsx +++ b/app/lish/[did]/[publication]/[rkey]/BaseTextBlock.tsx @@ -36,10 +36,16 @@ export function BaseTextBlock(props: { ${isStrikethrough ? "line-through decoration-tertiary" : ""} ${isHighlighted ? "highlight bg-highlight-1" : ""}`.replaceAll("\n", " "); + // Split text by newlines and insert
tags + const textParts = segment.text.split('\n'); + const renderedText = textParts.flatMap((part, i) => + i < textParts.length - 1 ? [part,
] : [part] + ); + if (isCode) { children.push( - {segment.text} + {renderedText} , ); } else if (link) { @@ -50,13 +56,13 @@ export function BaseTextBlock(props: { className={`text-accent-contrast hover:underline ${className}`} target="_blank" > - {segment.text} + {renderedText} , ); } else { children.push( - {segment.text} + {renderedText} , ); } diff --git a/components/Blocks/TextBlock/RenderYJSFragment.tsx b/components/Blocks/TextBlock/RenderYJSFragment.tsx index 94dc872f..3bc6afbb 100644 --- a/components/Blocks/TextBlock/RenderYJSFragment.tsx +++ b/components/Blocks/TextBlock/RenderYJSFragment.tsx @@ -60,6 +60,10 @@ export function RenderYJSFragment({ ); } + if (node.constructor === XmlElement && node.nodeName === "hard_break") { + return
; + } + return null; }) )} @@ -144,6 +148,10 @@ export function YJSFragmentToString( node: XmlElement | XmlText | XmlHook, ): string { if (node.constructor === XmlElement) { + // Handle hard_break nodes specially + if (node.nodeName === "hard_break") { + return "\n"; + } return node .toArray() .map((f) => YJSFragmentToString(f)) diff --git a/components/Blocks/TextBlock/keymap.ts b/components/Blocks/TextBlock/keymap.ts index 0bd952f4..5fe7fbad 100644 --- a/components/Blocks/TextBlock/keymap.ts +++ b/components/Blocks/TextBlock/keymap.ts @@ -145,12 +145,12 @@ export const TextBlockKeymap = ( ); }, "Shift-Enter": (state, dispatch, view) => { - if (multiLine) { - return baseKeymap.Enter(state, dispatch, view); + // Insert a hard break + let hardBreak = schema.nodes.hard_break.create(); + if (dispatch) { + dispatch(state.tr.replaceSelectionWith(hardBreak).scrollIntoView()); } - return um.withUndoGroup(() => - enter(propsRef, repRef)(state, dispatch, view), - ); + return true; }, "Ctrl-Enter": CtrlEnter(propsRef, repRef), "Meta-Enter": CtrlEnter(propsRef, repRef), diff --git a/components/Blocks/TextBlock/schema.ts b/components/Blocks/TextBlock/schema.ts index 24f018ce..71861a4d 100644 --- a/components/Blocks/TextBlock/schema.ts +++ b/components/Blocks/TextBlock/schema.ts @@ -115,6 +115,13 @@ let baseSchema = { text: { group: "inline", }, + hard_break: { + group: "inline", + inline: true, + selectable: false, + parseDOM: [{ tag: "br" }], + toDOM: () => ["br"] as const, + }, }, }; export const schema = new Schema(baseSchema); -- 2.51.2 From f3e2a86da80c38ebb9de4a3b3f6894eae2488675 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 24 Nov 2025 16:44:05 -0500 Subject: [PATCH 027/118] add migration to add back columns --- supabase/migrations/20251124214105_add_back_archived_cols.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 supabase/migrations/20251124214105_add_back_archived_cols.sql diff --git a/supabase/migrations/20251124214105_add_back_archived_cols.sql b/supabase/migrations/20251124214105_add_back_archived_cols.sql new file mode 100644 index 00000000..186bf18c --- /dev/null +++ b/supabase/migrations/20251124214105_add_back_archived_cols.sql @@ -0,0 +1,2 @@ +alter table "public"."permission_token_on_homepage" add column "archived" boolean; +alter table "public"."leaflets_in_publications" add column "archived" boolean; -- 2.51.2 From cb9348fbd692bcd737672dfb8ab96b5af831e5d1 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 00:34:31 -0500 Subject: [PATCH 028/118] use iframely for urls in embed block editor --- components/Blocks/EmbedBlock.tsx | 81 +++++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 16 deletions(-) diff --git a/components/Blocks/EmbedBlock.tsx b/components/Blocks/EmbedBlock.tsx index 3c0eaef9..919479b0 100644 --- a/components/Blocks/EmbedBlock.tsx +++ b/components/Blocks/EmbedBlock.tsx @@ -10,11 +10,15 @@ import { Separator } from "components/Layout"; import { Input } from "components/Input"; import { isUrl } from "src/utils/isURL"; import { elementId } from "src/utils/elementId"; -import { deleteBlock } from "./DeleteBlock"; import { focusBlock } from "src/utils/focusBlock"; import { useDrag } from "src/hooks/useDrag"; import { BlockEmbedSmall } from "components/Icons/BlockEmbedSmall"; import { CheckTiny } from "components/Icons/CheckTiny"; +import { DotLoader } from "components/utils/DotLoader"; +import { + LinkPreviewBody, + LinkPreviewMetadataResult, +} from "app/api/link_previews/route"; export const EmbedBlock = (props: BlockProps & { preview?: boolean }) => { let { permissions } = useEntitySetContext(); @@ -132,6 +136,7 @@ const BlockLinkInput = (props: BlockProps) => { let entity_set = useEntitySetContext(); let [linkValue, setLinkValue] = useState(""); + let [loading, setLoading] = useState(false); let { rep } = useReplicache(); let submit = async () => { let entity = props.entityID; @@ -149,21 +154,62 @@ const BlockLinkInput = (props: BlockProps) => { } let link = linkValue; if (!linkValue.startsWith("http")) link = `https://${linkValue}`; - // these mutations = simpler subset of addLinkBlock if (!rep) return; - await rep.mutate.assertFact({ - entity: entity, - attribute: "block/type", - data: { type: "block-type-union", value: "embed" }, - }); - await rep?.mutate.assertFact({ - entity: entity, - attribute: "embed/url", - data: { - type: "string", - value: link, - }, - }); + + // Try to get embed URL from iframely, fallback to direct URL + setLoading(true); + try { + let res = await fetch("/api/link_previews", { + headers: { "Content-Type": "application/json" }, + method: "POST", + body: JSON.stringify({ url: link, type: "meta" } as LinkPreviewBody), + }); + + let embedUrl = link; + let embedHeight = 360; + + if (res.status === 200) { + let data = await (res.json() as LinkPreviewMetadataResult); + if (data.success && data.data.links?.player?.[0]) { + let embed = data.data.links.player[0]; + embedUrl = embed.href; + embedHeight = embed.media?.height || 300; + } + } + + await rep.mutate.assertFact([ + { + entity: entity, + attribute: "embed/url", + data: { + type: "string", + value: embedUrl, + }, + }, + { + entity: entity, + attribute: "embed/height", + data: { + type: "number", + value: embedHeight, + }, + }, + ]); + } catch { + // On any error, fallback to using the URL directly + await rep.mutate.assertFact([ + { + entity: entity, + attribute: "embed/url", + data: { + type: "string", + value: link, + }, + }, + ]); + } finally { + setLoading(false); + } }; let smoker = useSmoker(); @@ -171,6 +217,7 @@ const BlockLinkInput = (props: BlockProps) => {
{ e.preventDefault(); + if (loading) return; let rect = document .getElementById("embed-block-submit") ?.getBoundingClientRect(); @@ -212,9 +259,11 @@ const BlockLinkInput = (props: BlockProps) => {
-- 2.51.2 From ea2f4fb3f5f5e77bc98dbec1da72f7c84f6c4392 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 15:17:30 -0500 Subject: [PATCH 029/118] Update/delete leaflets (#238) * unified leaflet option menus in published post and home * unified leaflet option menus in published post and home * streanlined shareButton, added archive data * added buttons to archive and unarchive in leaflet options * refactor to use a single Link element in the LeafletListItem * added filters for archive on home, filtered archive out of default leaflet list * update nextjs and add pub drafts * update for nextjs 16 * add pino to serverExternalPackages * make archiving in pubs work * update identity data on revalidate * refresh page on delete, fix text color on publish page * optimistically update leaflet lists on archive/etc * don't include archived when filtering on docs * handle logged out and non-pub owner cases * don't filter out archived undefined posts * fix titles for local docs * support canvas titles on homepage * fix sorts * filter docs better * remove template feature But keep the backend route so existing links still work --------- Co-authored-by: celine --- actions/deleteLeaflet.ts | 71 + actions/getIdentityData.ts | 1 + .../subscriptions/sendPostToSubscribers.ts | 2 +- .../home/Actions/CreateNewButton.tsx | 48 - app/(home-pages)/home/HomeLayout.tsx | 77 +- .../home/LeafletList/LeafletInfo.tsx | 76 +- .../home/LeafletList/LeafletListItem.tsx | 46 +- .../home/LeafletList/LeafletOptions.tsx | 491 +- .../home/LeafletList/LeafletPreview.tsx | 20 +- app/[leaflet_id]/publish/PublishPost.tsx | 5 +- .../rpc/[command]/getFactsFromHomeLeaflets.ts | 37 +- .../[publication]/dashboard/DraftList.tsx | 4 +- .../dashboard/PublicationSWRProvider.tsx | 24 +- .../dashboard/PublishedPostsLists.tsx | 198 +- .../[publication]/dashboard/deletePost.ts | 23 + app/lish/createPub/UpdatePubForm.tsx | 1 - app/lish/createPub/createPublication.ts | 1 + app/templates/TemplateList.tsx | 159 - app/templates/icon.tsx | 108 - app/templates/page.tsx | 29 - components/ActionBar/Publications.tsx | 1 + components/HomeButton.tsx | 1 + components/Icons/ArchiveSmall.tsx | 21 + components/Icons/TemplateRemoveSmall.tsx | 21 - components/Icons/TemplateSmall.tsx | 25 - components/Icons/UnpublishSmall.tsx | 19 + components/IdentityProvider.tsx | 19 +- components/Layout.tsx | 4 +- components/PageLayouts/DashboardLayout.tsx | 50 +- components/Pages/PageShareMenu.tsx | 6 +- components/ShareOptions/index.tsx | 42 +- next.config.js | 4 +- package-lock.json | 5913 +++++++++++------ package.json | 22 +- src/utils/getCurrentDeploymentDomain.ts | 6 +- src/utils/isBot.ts | 16 - tsconfig.json | 17 +- 37 files changed, 4700 insertions(+), 2908 deletions(-) delete mode 100644 app/templates/TemplateList.tsx delete mode 100644 app/templates/icon.tsx delete mode 100644 app/templates/page.tsx create mode 100644 components/Icons/ArchiveSmall.tsx delete mode 100644 components/Icons/TemplateRemoveSmall.tsx delete mode 100644 components/Icons/TemplateSmall.tsx create mode 100644 components/Icons/UnpublishSmall.tsx delete mode 100644 src/utils/isBot.ts diff --git a/actions/deleteLeaflet.ts b/actions/deleteLeaflet.ts index 5584a325..55534656 100644 --- a/actions/deleteLeaflet.ts +++ b/actions/deleteLeaflet.ts @@ -1,4 +1,5 @@ "use server"; +import { refresh } from "next/cache"; import { drizzle } from "drizzle-orm/node-postgres"; import { @@ -9,6 +10,8 @@ import { import { eq } from "drizzle-orm"; import { PermissionToken } from "src/replicache"; import { pool } from "supabase/pool"; +import { getIdentityData } from "./getIdentityData"; +import { supabaseServerClient } from "supabase/serverClient"; export async function deleteLeaflet(permission_token: PermissionToken) { const client = await pool.connect(); @@ -32,5 +35,73 @@ export async function deleteLeaflet(permission_token: PermissionToken) { .where(eq(permission_tokens.id, permission_token.id)); }); client.release(); + + refresh(); + return; +} + +export async function archivePost(token: string) { + let identity = await getIdentityData(); + if (!identity) throw new Error("No Identity"); + + // Archive on homepage + await supabaseServerClient + .from("permission_token_on_homepage") + .update({ archived: true }) + .eq("token", token) + .eq("identity", identity.id); + + // Check if leaflet is in any publications where user is the creator + let { data: leafletInPubs } = await supabaseServerClient + .from("leaflets_in_publications") + .select("publication, publications!inner(identity_did)") + .eq("leaflet", token); + + if (leafletInPubs) { + for (let pub of leafletInPubs) { + if (pub.publications.identity_did === identity.atp_did) { + await supabaseServerClient + .from("leaflets_in_publications") + .update({ archived: true }) + .eq("leaflet", token) + .eq("publication", pub.publication); + } + } + } + + refresh(); + return; +} + +export async function unarchivePost(token: string) { + let identity = await getIdentityData(); + if (!identity) throw new Error("No Identity"); + + // Unarchive on homepage + await supabaseServerClient + .from("permission_token_on_homepage") + .update({ archived: false }) + .eq("token", token) + .eq("identity", identity.id); + + // Check if leaflet is in any publications where user is the creator + let { data: leafletInPubs } = await supabaseServerClient + .from("leaflets_in_publications") + .select("publication, publications!inner(identity_did)") + .eq("leaflet", token); + + if (leafletInPubs) { + for (let pub of leafletInPubs) { + if (pub.publications.identity_did === identity.atp_did) { + await supabaseServerClient + .from("leaflets_in_publications") + .update({ archived: false }) + .eq("leaflet", token) + .eq("publication", pub.publication); + } + } + } + + refresh(); return; } diff --git a/actions/getIdentityData.ts b/actions/getIdentityData.ts index 7224413b..076bc760 100644 --- a/actions/getIdentityData.ts +++ b/actions/getIdentityData.ts @@ -24,6 +24,7 @@ export async function uncachedGetIdentityData() { entity_sets(entities(facts(*))) )), permission_token_on_homepage( + archived, created_at, permission_tokens!inner( id, diff --git a/actions/subscriptions/sendPostToSubscribers.ts b/actions/subscriptions/sendPostToSubscribers.ts index 6b590f19..8c5d4bed 100644 --- a/actions/subscriptions/sendPostToSubscribers.ts +++ b/actions/subscriptions/sendPostToSubscribers.ts @@ -57,7 +57,7 @@ export async function sendPostToSubscribers({ ) { return; } - let domain = getCurrentDeploymentDomain(); + let domain = await getCurrentDeploymentDomain(); let res = await fetch("https://api.postmarkapp.com/email/batch", { method: "POST", headers: { diff --git a/app/(home-pages)/home/Actions/CreateNewButton.tsx b/app/(home-pages)/home/Actions/CreateNewButton.tsx index 2052af7c..bfd7dfe7 100644 --- a/app/(home-pages)/home/Actions/CreateNewButton.tsx +++ b/app/(home-pages)/home/Actions/CreateNewButton.tsx @@ -1,46 +1,15 @@ "use client"; import { createNewLeaflet } from "actions/createNewLeaflet"; -import { createNewLeafletFromTemplate } from "actions/createNewLeafletFromTemplate"; import { ActionButton } from "components/ActionBar/ActionButton"; import { AddTiny } from "components/Icons/AddTiny"; import { BlockCanvasPageSmall } from "components/Icons/BlockCanvasPageSmall"; import { BlockDocPageSmall } from "components/Icons/BlockDocPageSmall"; -import { TemplateSmall } from "components/Icons/TemplateSmall"; import { Menu, MenuItem } from "components/Layout"; import { useIsMobile } from "src/hooks/isMobile"; -import { create } from "zustand"; -import { combine, createJSONStorage, persist } from "zustand/middleware"; -export const useTemplateState = create( - persist( - combine( - { - templates: [] as { id: string; name: string }[], - }, - (set) => ({ - removeTemplate: (template: { id: string }) => - set((state) => { - return { - templates: state.templates.filter((t) => t.id !== template.id), - }; - }), - addTemplate: (template: { id: string; name: string }) => - set((state) => { - if (state.templates.find((t) => t.id === template.id)) return state; - return { templates: [...state.templates, template] }; - }), - }), - ), - { - name: "home-templates", - storage: createJSONStorage(() => localStorage), - }, - ), -); export const CreateNewLeafletButton = (props: {}) => { let isMobile = useIsMobile(); - let templates = useTemplateState((s) => s.templates); let openNewLeaflet = (id: string) => { if (isMobile) { window.location.href = `/${id}?focusFirstBlock`; @@ -96,23 +65,6 @@ export const CreateNewLeafletButton = (props: {}) => {
- {templates.length > 0 && ( -
- )} - {templates.map((t) => { - return ( - { - let id = await createNewLeafletFromTemplate(t.id, false); - if (!id.error) openNewLeaflet(id.id); - }} - > - - New {t.name} - - ); - })} ); }; diff --git a/app/(home-pages)/home/HomeLayout.tsx b/app/(home-pages)/home/HomeLayout.tsx index e714df2e..f1f84e4f 100644 --- a/app/(home-pages)/home/HomeLayout.tsx +++ b/app/(home-pages)/home/HomeLayout.tsx @@ -21,7 +21,6 @@ import { } from "components/PageLayouts/DashboardLayout"; import { Actions } from "./Actions/Actions"; import { useCardBorderHidden } from "components/Pages/useCardBorderHidden"; -import { useTemplateState } from "./Actions/CreateNewButton"; import { GetLeafletDataReturnType } from "app/api/rpc/[command]/get_leaflet_data"; import { useState } from "react"; import { useDebouncedEffect } from "src/hooks/useDebouncedEffect"; @@ -33,6 +32,7 @@ import { type Leaflet = { added_at: string; + archived?: boolean | null; token: PermissionToken & { leaflets_in_publications?: Exclude< GetLeafletDataReturnType["result"]["data"], @@ -68,8 +68,11 @@ export const HomeLayout = (props: { let { identity } = useIdentityData(); let hasPubs = !identity || identity.publications.length === 0 ? false : true; - let hasTemplates = - useTemplateState((s) => s.templates).length === 0 ? false : true; + let hasArchived = + identity && + identity.permission_token_on_homepage.filter( + (leaflet) => leaflet.archived === true, + ).length > 0; return ( ), content: ( @@ -147,6 +150,7 @@ export function HomeLeafletList(props: { ? identity.permission_token_on_homepage.map((ptoh) => ({ added_at: ptoh.created_at, token: ptoh.permission_tokens as PermissionToken, + archived: ptoh.archived, })) : localLeaflets .sort((a, b) => (a.added_at > b.added_at ? -1 : 1)) @@ -204,7 +208,7 @@ export function LeafletList(props: { w-full ${display === "grid" ? "grid auto-rows-max md:grid-cols-4 sm:grid-cols-3 grid-cols-2 gap-y-4 gap-x-4 sm:gap-x-6 sm:gap-y-5 grow" : "flex flex-col gap-2 pt-2"} `} > - {props.leaflets.map(({ token: leaflet, added_at }, index) => ( + {props.leaflets.map(({ token: leaflet, added_at, archived }, index) => ( l.doc)} publishedAt={ leaflet.leaflets_in_publications?.find((l) => l.doc)?.documents ?.indexed_at } + document_uri={ + leaflet.leaflets_in_publications?.find((l) => l.doc)?.documents + ?.uri + } leaflet_id={leaflet.root_entity} loggedIn={!!identity} display={display} @@ -260,13 +271,13 @@ function useSearchedLeaflets( let sortedLeaflets = leaflets.sort((a, b) => { if (sort === "alphabetical") { - if (titles[a.token.root_entity] === titles[b.token.root_entity]) { + let titleA = titles[a.token.root_entity] ?? "Untitled"; + let titleB = titles[b.token.root_entity] ?? "Untitled"; + + if (titleA === titleB) { return a.added_at > b.added_at ? -1 : 1; } else { - return titles[a.token.root_entity].toLocaleLowerCase() > - titles[b.token.root_entity].toLocaleLowerCase() - ? 1 - : -1; + return titleA.toLocaleLowerCase() > titleB.toLocaleLowerCase() ? 1 : -1; } } else { return a.added_at === b.added_at @@ -279,28 +290,28 @@ function useSearchedLeaflets( } }); - let allTemplates = useTemplateState((s) => s.templates); - let filteredLeaflets = sortedLeaflets.filter(({ token: leaflet }) => { - let published = !!leaflet.leaflets_in_publications?.find((l) => l.doc); - let drafts = !!leaflet.leaflets_in_publications?.length && !published; - let docs = !leaflet.leaflets_in_publications?.length; - let templates = !!allTemplates.find((t) => t.id === leaflet.id); - // If no filters are active, show all - if ( - !filter.drafts && - !filter.published && - !filter.docs && - !filter.templates - ) - return true; + let filteredLeaflets = sortedLeaflets.filter( + ({ token: leaflet, archived: archived }) => { + let published = !!leaflet.leaflets_in_publications?.find((l) => l.doc); + let drafts = !!leaflet.leaflets_in_publications?.length && !published; + let docs = !leaflet.leaflets_in_publications?.length && !archived; + // If no filters are active, show all + if ( + !filter.drafts && + !filter.published && + !filter.docs && + !filter.archived + ) + return archived === false || archived === null || archived == undefined; - return ( - (filter.drafts && drafts) || - (filter.published && published) || - (filter.docs && docs) || - (filter.templates && templates) - ); - }); + return ( + (filter.drafts && drafts) || + (filter.published && published) || + (filter.docs && docs) || + (filter.archived && archived) + ); + }, + ); if (searchValue === "") return filteredLeaflets; let searchedLeaflets = filteredLeaflets.filter(({ token: leaflet }) => { return titles[leaflet.root_entity] diff --git a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx index eceb24da..478f853c 100644 --- a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx @@ -1,88 +1,74 @@ "use client"; -import { PermissionToken } from "src/replicache"; +import { PermissionToken, useEntity } from "src/replicache"; import { LeafletOptions } from "./LeafletOptions"; import Link from "next/link"; -import { useState } from "react"; -import { theme } from "tailwind.config"; -import { TemplateSmall } from "components/Icons/TemplateSmall"; +import { use, useState } from "react"; import { timeAgo } from "src/utils/timeAgo"; +import { usePublishLink } from "components/ShareOptions"; +import { Separator } from "components/Layout"; +import { usePageTitle } from "components/utils/UpdateLeafletTitle"; export const LeafletInfo = (props: { title?: string; - draft?: boolean; + draftInPublication?: string; published?: boolean; token: PermissionToken; leaflet_id: string; loggedIn: boolean; - isTemplate: boolean; className?: string; display: "grid" | "list"; added_at: string; publishedAt?: string; + document_uri?: string; + archived?: boolean | null; }) => { let [prefetch, setPrefetch] = useState(false); let prettyCreatedAt = props.added_at ? timeAgo(props.added_at) : ""; - let prettyPublishedAt = props.publishedAt ? timeAgo(props.publishedAt) : ""; + // Look up root page first, like UpdateLeafletTitle does + let firstPage = useEntity(props.leaflet_id, "root/page")[0]; + let entityID = firstPage?.data.value || props.leaflet_id; + let titleFromDb = usePageTitle(entityID); + + let title = props.title ?? titleFromDb ?? "Untitled"; + return (
- setPrefetch(true)} - onPointerDown={() => setPrefetch(true)} - prefetch={prefetch} - href={`/${props.token.id}`} - className="no-underline sm:hover:no-underline text-primary grow min-w-0" - > -

- {props.title} -

- +

+ {title} +

- {props.isTemplate && props.display === "list" ? ( - - ) : null}
- setPrefetch(true)} - onPointerDown={() => setPrefetch(true)} - prefetch={prefetch} - href={`/${props.token.id}`} - className="no-underline sm:hover:no-underline text-primary w-full" - > - {props.draft || props.published ? ( +
+ {props.archived ? ( +
Archived
+ ) : props.draftInPublication || props.published ? (
{props.published ? `Published ${prettyPublishedAt}` : `Draft ${prettyCreatedAt}`}
) : ( -
{prettyCreatedAt}
+
+ {prettyCreatedAt} +
)} - - {props.isTemplate && props.display === "grid" ? ( -
- -
- ) : null} +
); }; diff --git a/app/(home-pages)/home/LeafletList/LeafletListItem.tsx b/app/(home-pages)/home/LeafletList/LeafletListItem.tsx index b4b10cd3..9537f81b 100644 --- a/app/(home-pages)/home/LeafletList/LeafletListItem.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletListItem.tsx @@ -1,29 +1,27 @@ "use client"; import { PermissionToken } from "src/replicache"; -import { useTemplateState } from "../Actions/CreateNewButton"; import { LeafletListPreview, LeafletGridPreview } from "./LeafletPreview"; import { LeafletInfo } from "./LeafletInfo"; import { useState, useRef, useEffect } from "react"; +import { SpeedyLink } from "components/SpeedyLink"; export const LeafletListItem = (props: { token: PermissionToken; + archived?: boolean | null; leaflet_id: string; loggedIn: boolean; display: "list" | "grid"; cardBorderHidden: boolean; added_at: string; - title: string; - draft?: boolean; + title?: string; + draftInPublication?: string; published?: boolean; publishedAt?: string; + document_uri?: string; index: number; isHidden: boolean; showPreview?: boolean; }) => { - let isTemplate = useTemplateState( - (s) => !!s.templates.find((t) => t.id === props.token.id), - ); - let [isOnScreen, setIsOnScreen] = useState(props.index < 16 ? true : false); let previewRef = useRef(null); @@ -50,19 +48,23 @@ export const LeafletListItem = (props: { <>
+ {props.showPreview && ( )} - +
{props.cardBorderHidden && (
+
); }; + +const LeafletLink = (props: { id: string; className: string }) => { + return ( + + ); +}; diff --git a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx index e61920d3..6b810d58 100644 --- a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx @@ -1,32 +1,52 @@ "use client"; import { Menu, MenuItem } from "components/Layout"; -import { useReplicache, type PermissionToken } from "src/replicache"; -import { hideDoc } from "../storage"; import { useState } from "react"; -import { ButtonPrimary } from "components/Buttons"; -import { useTemplateState } from "../Actions/CreateNewButton"; -import { useSmoker, useToaster } from "components/Toast"; -import { removeLeafletFromHome } from "actions/removeLeafletFromHome"; -import { useIdentityData } from "components/IdentityProvider"; -import { HideSmall } from "components/Icons/HideSmall"; -import { MoreOptionsTiny } from "components/Icons/MoreOptionsTiny"; -import { TemplateRemoveSmall } from "components/Icons/TemplateRemoveSmall"; -import { TemplateSmall } from "components/Icons/TemplateSmall"; +import { ButtonPrimary, ButtonTertiary } from "components/Buttons"; +import { useToaster } from "components/Toast"; import { MoreOptionsVerticalTiny } from "components/Icons/MoreOptionsVerticalTiny"; -import { addLeafletToHome } from "actions/addLeafletToHome"; +import { DeleteSmall } from "components/Icons/DeleteSmall"; +import { + archivePost, + deleteLeaflet, + unarchivePost, +} from "actions/deleteLeaflet"; +import { ArchiveSmall } from "components/Icons/ArchiveSmall"; +import { UnpublishSmall } from "components/Icons/UnpublishSmall"; +import { + deletePost, + unpublishPost, +} from "app/lish/[did]/[publication]/dashboard/deletePost"; +import { ShareButton } from "components/ShareOptions"; +import { ShareSmall } from "components/Icons/ShareSmall"; +import { HideSmall } from "components/Icons/HideSmall"; +import { hideDoc } from "../storage"; + +import { PermissionToken } from "src/replicache"; +import { + useIdentityData, + mutateIdentityData, +} from "components/IdentityProvider"; +import { + usePublicationData, + mutatePublicationData, +} from "app/lish/[did]/[publication]/dashboard/PublicationSWRProvider"; export const LeafletOptions = (props: { leaflet: PermissionToken; - isTemplate: boolean; - loggedIn: boolean; - added_at: string; + draftInPublication?: string; + document_uri?: string; + shareLink: string; + archived?: boolean | null; + loggedIn?: boolean; }) => { - let { mutate: mutateIdentity } = useIdentityData(); - let [state, setState] = useState<"normal" | "template">("normal"); + let [state, setState] = useState<"normal" | "areYouSure">( + "normal", + ); let [open, setOpen] = useState(false); - let smoker = useSmoker(); - let toaster = useToaster(); + let { identity } = useIdentityData(); + let isPublicationOwner = + !!identity?.atp_did && !!props.document_uri?.includes(identity.atp_did); return ( <> { e.preventDefault; e.stopPropagation; @@ -49,81 +69,30 @@ export const LeafletOptions = (props: { } > {state === "normal" ? ( - <> - {!props.isTemplate ? ( - { - e.preventDefault(); - setState("template"); - }} - > - Add as Template - - ) : ( - { - useTemplateState.getState().removeTemplate(props.leaflet); - let newLeafletButton = - document.getElementById("new-leaflet-button"); - if (!newLeafletButton) return; - let rect = newLeafletButton.getBoundingClientRect(); - smoker({ - static: true, - text: Removed template!, - position: { - y: rect.top, - x: rect.right + 5, - }, - }); - }} - > - Remove from Templates - - )} - { - if (props.loggedIn) { - mutateIdentity( - (s) => { - if (!s) return s; - return { - ...s, - permission_token_on_homepage: - s.permission_token_on_homepage.filter( - (ptrh) => - ptrh.permission_tokens.id !== props.leaflet.id, - ), - }; - }, - { revalidate: false }, - ); - await removeLeafletFromHome([props.leaflet.id]); - mutateIdentity(); - } else { - hideDoc(props.leaflet); - } - toaster({ - content: ( -
- Doc removed!{" "} - -
- ), - type: "success", - }); - }} - > - - Remove from Home -
- - ) : state === "template" ? ( - + ) : props.document_uri && isPublicationOwner ? ( + + ) : ( + + ) + ) : state === "areYouSure" ? ( + setState("normal")} leaflet={props.leaflet} - close={() => setOpen(false)} + document_uri={props.document_uri} + draft={!!props.draftInPublication} /> ) : null}
@@ -131,90 +100,286 @@ export const LeafletOptions = (props: { ); }; -const UndoRemoveFromHomeButton = (props: { +const DefaultOptions = (props: { + setState: (s: "areYouSure") => void; + draftInPublication?: string; leaflet: PermissionToken; - added_at: string | undefined; + shareLink: string; + archived?: boolean | null; }) => { let toaster = useToaster(); - let { mutate } = useIdentityData(); + let { mutate: mutatePub } = usePublicationData(); + let { mutate: mutateIdentity } = useIdentityData(); return ( -
+ } + subtext="" + smokerText="Link copied!" + id="get-link" + link={`/${props.shareLink}`} + /> +
+ { + if (!props.archived) { + mutateIdentityData(mutateIdentity, (data) => { + let item = data.permission_token_on_homepage.find( + (p) => p.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = true; + }); + mutatePublicationData(mutatePub, (data) => { + let item = data.publication?.leaflets_in_publications.find( + (l) => l.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = true; + }); + await archivePost(props.leaflet.id); + toaster({ + content: ( +
+ Archived{props.draftInPublication ? " Draft" : " Leaflet"}! + { + mutateIdentityData(mutateIdentity, (data) => { + let item = data.permission_token_on_homepage.find( + (p) => p.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = false; + }); + mutatePublicationData(mutatePub, (data) => { + let item = + data.publication?.leaflets_in_publications.find( + (l) => l.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = false; + }); + await unarchivePost(props.leaflet.id); + toaster({ + content: ( +
+ Unarchived! +
+ ), + type: "success", + }); + }} + > + Undo? +
+
+ ), + type: "success", + }); + } else { + mutateIdentityData(mutateIdentity, (data) => { + let item = data.permission_token_on_homepage.find( + (p) => p.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = false; + }); + mutatePublicationData(mutatePub, (data) => { + let item = data.publication?.leaflets_in_publications.find( + (l) => l.permission_tokens?.id === props.leaflet.id, + ); + if (item) item.archived = false; + }); + await unarchivePost(props.leaflet.id); + toaster({ + content:
Unarchived!
, + type: "success", + }); + } + }} + > + + {!props.archived ? " Archive" : "Unarchive"} + {props.draftInPublication ? " Draft" : " Leaflet"} +
+ { + e.preventDefault(); + props.setState("areYouSure"); + }} + > + + Delete Forever + + + ); +}; - toaster({ - content:
Recovered Doc!
, - type: "success", - }); - }} - className="underline" - > - Undo? - +const LoggedOutOptions = (props: { + leaflet: PermissionToken; + setState: (s: "areYouSure") => void; + shareLink: string; +}) => { + let toaster = useToaster(); + return ( + <> + + + Copy Edit Link +
+ } + subtext="" + smokerText="Link copied!" + id="get-link" + link={`/${props.shareLink}`} + /> +
+ { + hideDoc(props.leaflet); + toaster({ + content:
Removed from Home!
, + type: "success", + }); + }} + > + + Remove from Home +
+ { + e.preventDefault(); + props.setState("areYouSure"); + }} + > + + Delete Forever + + ); }; -const AddTemplateForm = (props: { +const PublishedPostOptions = (props: { + setState: (s: "areYouSure") => void; + document_uri: string; leaflet: PermissionToken; - close: () => void; + shareLink: string; }) => { - let [name, setName] = useState(""); - let smoker = useSmoker(); + let toaster = useToaster(); return ( -
- + <> + + + Copy Post Link +
+ } + smokerText="Link copied!" + id="get-link" + link={`${props.shareLink}`} + /> - { - useTemplateState.getState().addTemplate({ - name, - id: props.leaflet.id, - }); - let newLeafletButton = document.getElementById("new-leaflet-button"); - if (!newLeafletButton) return; - let rect = newLeafletButton.getBoundingClientRect(); - smoker({ - static: true, - text: Added {name}!, - position: { - y: rect.top, - x: rect.right + 5, - }, +
+ { + if (props.document_uri) { + await unpublishPost(props.document_uri); + } + toaster({ + content:
Unpublished Post!
, + type: "success", }); - props.close(); }} - className="place-self-end" > - Add Template -
+ +
+ Unpublish Post +
+ Move this post back into drafts +
+
+ + { + e.preventDefault(); + props.setState("areYouSure"); + }} + > + +
+ Delete Post +
+ Unpublish AND delete +
+
+
+ + ); +}; + +const DeleteAreYouSureForm = (props: { + backToMenu: () => void; + document_uri?: string; + leaflet: PermissionToken; + draft?: boolean; +}) => { + let toaster = useToaster(); + let { mutate: mutatePub } = usePublicationData(); + let { mutate: mutateIdentity } = useIdentityData(); + + return ( +
+
Are you sure?
+
+ This will delete it forever for everyone! +
+
+ props.backToMenu()}> + Nevermind + + { + mutateIdentityData(mutateIdentity, (data) => { + data.permission_token_on_homepage = + data.permission_token_on_homepage.filter( + (p) => p.permission_tokens?.id !== props.leaflet.id, + ); + }); + mutatePublicationData(mutatePub, (data) => { + if (!data.publication) return; + data.publication.leaflets_in_publications = + data.publication.leaflets_in_publications.filter( + (l) => l.permission_tokens?.id !== props.leaflet.id, + ); + }); + if (props.document_uri) { + await deletePost(props.document_uri); + } + deleteLeaflet(props.leaflet); + + toaster({ + content: ( +
+ Deleted{" "} + {props.document_uri + ? "Post!" + : props.draft + ? "Draft" + : "Leaflet!"} +
+ ), + type: "success", + }); + }} + > + Delete it! +
+
); }; + diff --git a/app/(home-pages)/home/LeafletList/LeafletPreview.tsx b/app/(home-pages)/home/LeafletList/LeafletPreview.tsx index bd8e10b4..e3530f8a 100644 --- a/app/(home-pages)/home/LeafletList/LeafletPreview.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletPreview.tsx @@ -8,13 +8,9 @@ import { useEntity, useReferenceToEntity, } from "src/replicache"; -import { useTemplateState } from "../Actions/CreateNewButton"; import { useCardBorderHidden } from "components/Pages/useCardBorderHidden"; import { LeafletContent } from "./LeafletContent"; import { Tooltip } from "components/Tooltip"; -import { useState } from "react"; -import Link from "next/link"; -import { SpeedyLink } from "components/SpeedyLink"; export const LeafletListPreview = (props: { draft?: boolean; @@ -137,12 +133,12 @@ export const LeafletGridPreview = (props: { ); return ( -
-
+
+
-
); }; - -const LeafletPreviewLink = (props: { id: string }) => { - return ( - - ); -}; diff --git a/app/[leaflet_id]/publish/PublishPost.tsx b/app/[leaflet_id]/publish/PublishPost.tsx index 570dfd4a..52ac63e9 100644 --- a/app/[leaflet_id]/publish/PublishPost.tsx +++ b/app/[leaflet_id]/publish/PublishPost.tsx @@ -94,7 +94,7 @@ const PublishPostForm = ( } return ( -
+

Publish Options

{ @@ -161,7 +161,6 @@ const PublishPostForm = ( />
- {/*
*/}
{props.title}
{props.description}
@@ -209,7 +208,7 @@ const PublishPostSuccess = (props: { return (
-

Published!

+

Published!

b.type === "text" || b.type === "heading", - ); + + // Check page type to determine which blocks to look up + let [pageType] = scan.eav(rootEntity, "page/type"); + let isCanvas = pageType?.data.value === "canvas"; + + // Get blocks and sort by position + let rawBlocks = isCanvas + ? scan.eav(rootEntity, "canvas/block").sort((a, b) => { + if (a.data.position.y === b.data.position.y) + return a.data.position.x - b.data.position.x; + return a.data.position.y - b.data.position.y; + }) + : scan.eav(rootEntity, "card/block").sort((a, b) => { + if (a.data.position === b.data.position) + return a.id > b.id ? 1 : -1; + return a.data.position > b.data.position ? 1 : -1; + }); + + // Map to get type and filter for text/heading + let blocks = rawBlocks + .map((b) => { + let type = scan.eav(b.data.value, "block/type")[0]; + if ( + !type || + (type.data.value !== "text" && type.data.value !== "heading") + ) + return null; + return b.data; + }) + .filter((b): b is NonNullable => b !== null); + + let title = blocks[0]; + if (!title) titles[token] = "Untitled"; else { let [content] = scan.eav(title.value, "block/text"); diff --git a/app/lish/[did]/[publication]/dashboard/DraftList.tsx b/app/lish/[did]/[publication]/dashboard/DraftList.tsx index fadce76f..c7f9a11d 100644 --- a/app/lish/[did]/[publication]/dashboard/DraftList.tsx +++ b/app/lish/[did]/[publication]/dashboard/DraftList.tsx @@ -26,8 +26,11 @@ export function DraftList(props: { cardBorderHidden={!props.showPageBackground} leaflets={leaflets_in_publications .filter((l) => !l.documents) + .filter((l) => !l.archived) .map((l) => { return { + archived: l.archived, + added_at: "", token: { ...l.permission_tokens!, leaflets_in_publications: [ @@ -39,7 +42,6 @@ export function DraftList(props: { }, ], }, - added_at: "", }; })} initialFacts={pub_data.leaflet_data.facts || {}} diff --git a/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx b/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx index 17a0b1f0..96f51b9c 100644 --- a/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx +++ b/app/lish/[did]/[publication]/dashboard/PublicationSWRProvider.tsx @@ -2,8 +2,11 @@ import type { GetPublicationDataReturnType } from "app/api/rpc/[command]/get_publication_data"; import { callRPC } from "app/api/rpc/client"; -import { createContext, useContext } from "react"; -import useSWR, { SWRConfig } from "swr"; +import { createContext, useContext, useEffect } from "react"; +import useSWR, { SWRConfig, KeyedMutator, mutate } from "swr"; +import { produce, Draft } from "immer"; + +export type PublicationData = GetPublicationDataReturnType["result"]; const PublicationContext = createContext({ name: "", did: "" }); export function PublicationSWRDataProvider(props: { @@ -13,6 +16,10 @@ export function PublicationSWRDataProvider(props: { children: React.ReactNode; }) { let key = `publication-data-${props.publication_did}-${props.publication_rkey}`; + useEffect(() => { + console.log("UPDATING"); + mutate(key, props.publication_data); + }, [props.publication_data]); return ( , + recipe: (draft: Draft>) => void, +) { + mutate( + (data) => { + if (!data) return data; + return produce(data, recipe); + }, + { revalidate: false }, + ); +} diff --git a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx index 3d998853..12e2cc15 100644 --- a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx +++ b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx @@ -18,6 +18,7 @@ import { SpeedyLink } from "components/SpeedyLink"; import { QuoteTiny } from "components/Icons/QuoteTiny"; import { CommentTiny } from "components/Icons/CommentTiny"; import { useLocalizedDate } from "src/hooks/useLocalizedDate"; +import { LeafletOptions } from "app/(home-pages)/home/LeafletList/LeafletOptions"; export function PublishedPostsList(props: { searchValue: string; @@ -57,6 +58,10 @@ export function PublishedPostsList(props: { let quotes = doc.documents.document_mentions_in_bsky[0]?.count || 0; let comments = doc.documents.comments_on_documents[0]?.count || 0; + let postLink = data?.publication + ? `${getPublicationURL(data?.publication)}/${new AtUri(doc.documents.uri).rkey}` + : ""; + return (
@@ -80,14 +85,22 @@ export function PublishedPostsList(props: {
{leaflet && ( - - - + <> + + + + + + )} -
@@ -133,102 +146,79 @@ export function PublishedPostsList(props: { ); } -let Options = (props: { document_uri: string }) => { - return ( - - - - } - > - <> - - - - ); -}; +// function OptionsMenu(props: { document_uri: string }) { +// let { mutate, data } = usePublicationData(); +// let [state, setState] = useState<"normal" | "confirm">("normal"); -function OptionsMenu(props: { document_uri: string }) { - let { mutate, data } = usePublicationData(); - let [state, setState] = useState<"normal" | "confirm">("normal"); - - let postLink = data?.publication - ? `${getPublicationURL(data?.publication)}/${new AtUri(props.document_uri).rkey}` - : null; - - if (state === "normal") { - return ( - <> - - Share Post Link - -
- } - subtext="" - smokerText="Post link copied!" - id="get-post-link" - fullLink={postLink?.includes("https") ? postLink : undefined} - link={postLink} - /> +// if (state === "normal") { +// return ( +// <> +// +// Share Post Link +// +//
+// } +// subtext="" +// smokerText="Post link copied!" +// id="get-post-link" +// fullLink={postLink?.includes("https") ? postLink : undefined} +// link={postLink} +// /> -
- { - e.preventDefault(); - setState("confirm"); - return; - }} - > - Delete Post - - - - ); - } - if (state === "confirm") { - return ( -
- Are you sure? -
- This action cannot be undone! -
- { - await mutate((data) => { - if (!data) return data; - return { - ...data, - publication: { - ...data.publication!, - leaflets_in_publications: - data.publication?.leaflets_in_publications.filter( - (l) => l.doc !== props.document_uri, - ) || [], - documents_in_publications: - data.publication?.documents_in_publications.filter( - (d) => d.documents?.uri !== props.document_uri, - ) || [], - }, - }; - }, false); - await deletePost(props.document_uri); - }} - > - Delete - -
- ); - } -} +//
+// { +// e.preventDefault(); +// setState("confirm"); +// return; +// }} +// > +// Delete Post +// +// +// +// ); +// } +// if (state === "confirm") { +// return ( +//
+// Are you sure? +//
+// This action cannot be undone! +//
+// { +// await mutate((data) => { +// if (!data) return data; +// return { +// ...data, +// publication: { +// ...data.publication!, +// leaflets_in_publications: +// data.publication?.leaflets_in_publications.filter( +// (l) => l.doc !== props.document_uri, +// ) || [], +// documents_in_publications: +// data.publication?.documents_in_publications.filter( +// (d) => d.documents?.uri !== props.document_uri, +// ) || [], +// }, +// }; +// }, false); +// await deletePost(props.document_uri); +// }} +// > +// Delete +// +//
+// ); +// } +//} function PublishedDate(props: { dateString: string }) { const formattedDate = useLocalizedDate(props.dateString, { @@ -237,9 +227,5 @@ function PublishedDate(props: { dateString: string }) { day: "2-digit", }); - return ( -

- Published {formattedDate} -

- ); + return

Published {formattedDate}

; } diff --git a/app/lish/[did]/[publication]/dashboard/deletePost.ts b/app/lish/[did]/[publication]/dashboard/deletePost.ts index 362b979a..1723ed0f 100644 --- a/app/lish/[did]/[publication]/dashboard/deletePost.ts +++ b/app/lish/[did]/[publication]/dashboard/deletePost.ts @@ -30,5 +30,28 @@ export async function deletePost(document_uri: string) { .delete() .eq("doc", document_uri), ]); + + return revalidatePath("/lish/[did]/[publication]/dashboard", "layout"); +} + +export async function unpublishPost(document_uri: string) { + let identity = await getIdentityData(); + if (!identity || !identity.atp_did) throw new Error("No Identity"); + + const oauthClient = await createOauthClient(); + let credentialSession = await oauthClient.restore(identity.atp_did); + let agent = new AtpBaseClient( + credentialSession.fetchHandler.bind(credentialSession), + ); + let uri = new AtUri(document_uri); + if (uri.host !== identity.atp_did) return; + + await Promise.all([ + agent.pub.leaflet.document.delete({ + repo: credentialSession.did, + rkey: uri.rkey, + }), + supabaseServerClient.from("documents").delete().eq("uri", document_uri), + ]); return revalidatePath("/lish/[did]/[publication]/dashboard", "layout"); } diff --git a/app/lish/createPub/UpdatePubForm.tsx b/app/lish/createPub/UpdatePubForm.tsx index 85354893..05f367e2 100644 --- a/app/lish/createPub/UpdatePubForm.tsx +++ b/app/lish/createPub/UpdatePubForm.tsx @@ -66,7 +66,6 @@ export const EditPubForm = (props: { if (!pubData) return; e.preventDefault(); props.setLoadingAction(true); - console.log("step 1:update"); let data = await updatePublication({ uri: pubData.uri, name: nameValue, diff --git a/app/lish/createPub/createPublication.ts b/app/lish/createPub/createPublication.ts index bd4f7ab2..9ce067cb 100644 --- a/app/lish/createPub/createPublication.ts +++ b/app/lish/createPub/createPublication.ts @@ -101,6 +101,7 @@ export async function createPublication({ await supabaseServerClient .from("custom_domains") .insert({ domain, confirmed: true, identity: null }); + await supabaseServerClient .from("publication_domains") .insert({ domain, publication: result.uri, identity: identity.atp_did }); diff --git a/app/templates/TemplateList.tsx b/app/templates/TemplateList.tsx deleted file mode 100644 index a6eadd41..00000000 --- a/app/templates/TemplateList.tsx +++ /dev/null @@ -1,159 +0,0 @@ -"use client"; - -import { ButtonPrimary } from "components/Buttons"; -import Image from "next/image"; -import Link from "next/link"; -import { createNewLeafletFromTemplate } from "actions/createNewLeafletFromTemplate"; -import { AddTiny } from "components/Icons/AddTiny"; - -export function LeafletTemplate(props: { - title: string; - description?: string; - image: string; - alt: string; - templateID: string; // readonly id for the leaflet that will be duplicated -}) { - return ( -
-
-
- {props.alt} -
-
-
-
-

- {props.title} -

- {props.description && ( -
- {props.description} -
- )} -
-
- - - Preview - - - { - let id = await createNewLeafletFromTemplate( - props.templateID, - false, - ); - window.open(`/${id}`, "_blank"); - }} - > - Create - - -
-
-
- ); -} - -export function TemplateList(props: { - name: string; - description?: string; - children: React.ReactNode; -}) { - return ( -
-
-

{props.name}

-

{props.description}

-
-
- {props.children} -
-
- ); -} - -export function TemplateListThemes() { - return ( - <> - - - - - - - - ); -} - -export function TemplateListExamples() { - return ( - - - - - - - ); -} diff --git a/app/templates/icon.tsx b/app/templates/icon.tsx deleted file mode 100644 index e9f2c3f4..00000000 --- a/app/templates/icon.tsx +++ /dev/null @@ -1,108 +0,0 @@ -// NOTE: duplicated from home/icon.tsx -// we could make it different so it's clear it's not your personal colors? - -import { ImageResponse } from "next/og"; -import type { Fact } from "src/replicache"; -import type { Attribute } from "src/replicache/attributes"; -import { Database } from "../../supabase/database.types"; -import { createServerClient } from "@supabase/ssr"; -import { parseHSBToRGB } from "src/utils/parseHSB"; -import { cookies } from "next/headers"; - -// Route segment config -export const revalidate = 0; -export const preferredRegion = ["sfo1"]; -export const dynamic = "force-dynamic"; -export const fetchCache = "force-no-store"; - -// Image metadata -export const size = { - width: 32, - height: 32, -}; -export const contentType = "image/png"; - -// Image generation -let supabase = createServerClient( - process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, - process.env.SUPABASE_SERVICE_ROLE_KEY as string, - { cookies: {} }, -); -export default async function Icon() { - let cookieStore = await cookies(); - let identity = cookieStore.get("identity"); - let rootEntity: string | null = null; - if (identity) { - let res = await supabase - .from("identities") - .select( - `*, - permission_tokens!identities_home_page_fkey(*, permission_token_rights(*)), - permission_token_on_homepage( - *, permission_tokens(*, permission_token_rights(*)) - ) - `, - ) - .eq("id", identity?.value) - .single(); - rootEntity = res.data?.permission_tokens?.root_entity || null; - } - let outlineColor, fillColor; - if (rootEntity) { - let { data } = await supabase.rpc("get_facts", { - root: rootEntity, - }); - let initialFacts = (data as unknown as Fact[]) || []; - let themePageBG = initialFacts.find( - (f) => f.attribute === "theme/card-background", - ) as Fact<"theme/card-background"> | undefined; - - let themePrimary = initialFacts.find( - (f) => f.attribute === "theme/primary", - ) as Fact<"theme/primary"> | undefined; - - outlineColor = parseHSBToRGB(`hsba(${themePageBG?.data.value})`); - - fillColor = parseHSBToRGB(`hsba(${themePrimary?.data.value})`); - } - - return new ImageResponse( - ( - // ImageResponse JSX element -
- - {/* outline */} - - - {/* fill */} - - -
- ), - // ImageResponse options - { - // For convenience, we can re-use the exported icons size metadata - // config to also set the ImageResponse's width and height. - ...size, - headers: { - "Cache-Control": "no-cache", - }, - }, - ); -} diff --git a/app/templates/page.tsx b/app/templates/page.tsx deleted file mode 100644 index ea8f6de4..00000000 --- a/app/templates/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import Link from "next/link"; -import { TemplateListExamples, TemplateListThemes } from "./TemplateList"; -import { ActionButton } from "components/ActionBar/ActionButton"; -import { HomeSmall } from "components/Icons/HomeSmall"; - -export const metadata = { - title: "Leaflet Templates", - description: "example themes and documents you can use!", -}; - -export default function Templates() { - return ( -
-
-
- {/* NOT using b/c it does a permission check we don't need */} - - } label="Go Home" /> - -
-
-

Template Library

- - -
-
-
- ); -} diff --git a/components/ActionBar/Publications.tsx b/components/ActionBar/Publications.tsx index a16f8aee..1c616151 100644 --- a/components/ActionBar/Publications.tsx +++ b/components/ActionBar/Publications.tsx @@ -105,6 +105,7 @@ const PubListEmpty = () => { side="right" align="start" className="p-1! max-w-56" + asChild trigger={ { permission_token_on_homepage: [ ...identity.permission_token_on_homepage, { + archived: null, created_at: new Date().toISOString(), permission_tokens: { ...permission_token, diff --git a/components/Icons/ArchiveSmall.tsx b/components/Icons/ArchiveSmall.tsx new file mode 100644 index 00000000..f0459af7 --- /dev/null +++ b/components/Icons/ArchiveSmall.tsx @@ -0,0 +1,21 @@ +import { Props } from "./Props"; + +export const ArchiveSmall = (props: Props) => { + return ( + + + + ); +}; diff --git a/components/Icons/TemplateRemoveSmall.tsx b/components/Icons/TemplateRemoveSmall.tsx deleted file mode 100644 index 9768bec3..00000000 --- a/components/Icons/TemplateRemoveSmall.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Props } from "./Props"; - -export const TemplateRemoveSmall = (props: Props) => { - return ( - - - - ); -}; diff --git a/components/Icons/TemplateSmall.tsx b/components/Icons/TemplateSmall.tsx deleted file mode 100644 index 93f27c7b..00000000 --- a/components/Icons/TemplateSmall.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Props } from "./Props"; - -export const TemplateSmall = (props: Props & { fill?: string }) => { - return ( - - - - - ); -}; diff --git a/components/Icons/UnpublishSmall.tsx b/components/Icons/UnpublishSmall.tsx new file mode 100644 index 00000000..d3400c94 --- /dev/null +++ b/components/Icons/UnpublishSmall.tsx @@ -0,0 +1,19 @@ +import { Props } from "./Props"; + +export const UnpublishSmall = (props: Props) => { + return ( + + + + ); +}; diff --git a/components/IdentityProvider.tsx b/components/IdentityProvider.tsx index 947def39..a880080e 100644 --- a/components/IdentityProvider.tsx +++ b/components/IdentityProvider.tsx @@ -4,16 +4,30 @@ import { createContext, useContext, useEffect } from "react"; import useSWR, { KeyedMutator, mutate } from "swr"; import { DashboardState } from "./PageLayouts/DashboardLayout"; import { supabaseBrowserClient } from "supabase/browserClient"; +import { produce, Draft } from "immer"; export type InterfaceState = { dashboards: { [id: string]: DashboardState | undefined }; }; -type Identity = Awaited>; +export type Identity = Awaited>; let IdentityContext = createContext({ identity: null as Identity, mutate: (() => {}) as KeyedMutator, }); export const useIdentityData = () => useContext(IdentityContext); + +export function mutateIdentityData( + mutate: KeyedMutator, + recipe: (draft: Draft>) => void, +) { + mutate( + (data) => { + if (!data) return data; + return produce(data, recipe); + }, + { revalidate: false }, + ); +} export function IdentityContextProvider(props: { children: React.ReactNode; initialValue: Identity; @@ -21,6 +35,9 @@ export function IdentityContextProvider(props: { let { data: identity, mutate } = useSWR("identity", () => getIdentityData(), { fallbackData: props.initialValue, }); + useEffect(() => { + mutate(props.initialValue); + }, [props.initialValue]); useEffect(() => { if (!identity?.atp_did) return; let supabase = supabaseBrowserClient(); diff --git a/components/Layout.tsx b/components/Layout.tsx index 52184571..0caa13c9 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -6,9 +6,7 @@ import { PopoverOpenContext } from "./Popover"; import { useState } from "react"; export const Separator = (props: { classname?: string }) => { - return ( -
- ); + return
; }; export const Menu = (props: { diff --git a/components/PageLayouts/DashboardLayout.tsx b/components/PageLayouts/DashboardLayout.tsx index 291e5b31..9fcd52df 100644 --- a/components/PageLayouts/DashboardLayout.tsx +++ b/components/PageLayouts/DashboardLayout.tsx @@ -33,7 +33,7 @@ export type DashboardState = { drafts: boolean; published: boolean; docs: boolean; - templates: boolean; + archived: boolean; }; }; @@ -45,7 +45,12 @@ type DashboardStore = { const defaultDashboardState: DashboardState = { display: undefined, sort: undefined, - filter: { drafts: false, published: false, docs: false, templates: false }, + filter: { + drafts: false, + published: false, + docs: false, + archived: false, + }, }; export const useDashboardStore = create((set, get) => ({ @@ -255,7 +260,7 @@ export const HomeDashboardControls = (props: { hasBackgroundImage: boolean; defaultDisplay: Exclude; hasPubs: boolean; - hasTemplates: boolean; + hasArchived: boolean; }) => { let { display, sort } = useDashboardState(); display = display || props.defaultDisplay; @@ -276,13 +281,11 @@ export const HomeDashboardControls = (props: { - {props.hasPubs || props.hasTemplates ? ( + {props.hasPubs ? ( <> - {props.hasPubs} - {props.hasTemplates} {" "} @@ -369,7 +372,10 @@ function Tab(props: { ); } -const FilterOptions = (props: { hasPubs: boolean; hasTemplates: boolean }) => { +const FilterOptions = (props: { + hasPubs: boolean; + hasArchived: boolean; +}) => { let { filter } = useDashboardState(); let setState = useSetDashboardState(); let filterCount = Object.values(filter).filter(Boolean).length; @@ -406,20 +412,18 @@ const FilterOptions = (props: { hasPubs: boolean; hasTemplates: boolean }) => { )} - {props.hasTemplates && ( - <> - - setState({ - filter: { ...filter, templates: !!e.target.checked }, - }) - } - > - Templates - - + {props.hasArchived && ( + + setState({ + filter: { ...filter, archived: !!e.target.checked }, + }) + } + > + Archived + )} { docs: false, published: false, drafts: false, - templates: false, + archived: false, }, }); }} diff --git a/components/Pages/PageShareMenu.tsx b/components/Pages/PageShareMenu.tsx index e4b37e7a..1ae183da 100644 --- a/components/Pages/PageShareMenu.tsx +++ b/components/Pages/PageShareMenu.tsx @@ -14,16 +14,14 @@ export const PageShareMenu = (props: { entityID: string }) => {
!!s.templates.find((t) => t.id === permission_token.id), - ); - return ( <> - {isTemplate && ( - <> - -
- - )} - -
-
- {props.text} -
-
- {props.subtext} -
- {/* optional help text */} - {props.helptext && ( -
- {props.helptext} +
+ {props.text} + + {props.subtext && ( +
+ {props.subtext}
)}
diff --git a/next.config.js b/next.config.js index 68b3188e..5dd44882 100644 --- a/next.config.js +++ b/next.config.js @@ -21,7 +21,7 @@ const nextConfig = { }, ]; }, - serverExternalPackages: ["yjs"], + serverExternalPackages: ["yjs", "pino"], pageExtensions: ["js", "jsx", "ts", "tsx", "md", "mdx"], images: { loader: "custom", @@ -31,8 +31,8 @@ const nextConfig = { { protocol: "https", hostname: "bdefzwcumgzjwllsnaej.supabase.co" }, ], }, + reactCompiler: true, experimental: { - reactCompiler: true, serverActions: { bodySizeLimit: "5mb", }, diff --git a/package-lock.json b/package-lock.json index 48d6531c..d63df567 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,8 +21,8 @@ "@hono/node-server": "^1.14.3", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/bundle-analyzer": "^15.3.2", - "@next/mdx": "15.3.2", + "@next/bundle-analyzer": "16.0.3", + "@next/mdx": "16.0.3", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-popover": "^1.1.15", @@ -51,7 +51,7 @@ "linkifyjs": "^4.2.0", "luxon": "^3.7.2", "multiformats": "^13.3.2", - "next": "^15.5.3", + "next": "16.0.3", "pg": "^8.16.3", "prosemirror-commands": "^1.5.2", "prosemirror-inputrules": "^1.4.0", @@ -59,10 +59,10 @@ "prosemirror-model": "^1.21.0", "prosemirror-schema-basic": "^1.2.2", "prosemirror-state": "^1.4.3", - "react": "^19.1.1", + "react": "19.2.0", "react-aria-components": "^1.8.0", "react-day-picker": "^9.3.0", - "react-dom": "^19.1.1", + "react-dom": "19.2.0", "react-use-measure": "^2.1.1", "redlock": "^5.0.0-beta.2", "rehype-parse": "^9.0.0", @@ -92,13 +92,13 @@ "@types/katex": "^0.16.7", "@types/luxon": "^3.7.1", "@types/node": "^22.15.17", - "@types/react": "19.1.3", - "@types/react-dom": "19.1.3", + "@types/react": "19.2.6", + "@types/react-dom": "19.2.3", "@types/uuid": "^10.0.0", "drizzle-kit": "^0.21.2", "esbuild": "^0.25.4", - "eslint": "8.57.0", - "eslint-config-next": "^15.5.3", + "eslint": "^9.39.1", + "eslint-config-next": "16.0.3", "postcss": "^8.4.38", "prettier": "3.2.5", "supabase": "^1.187.3", @@ -567,6 +567,175 @@ "node": ">=18.7.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -577,22 +746,89 @@ } }, "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "license": "MIT", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", - "license": "MIT", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dependencies": { "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -714,1253 +950,2032 @@ "source-map-support": "^0.5.21" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm": { "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", "cpu": [ - "x64" + "arm" ], "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": ">=12" } }, - "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-arm64": { "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/@esbuild-kit/esm-loader": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz", - "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", - "dev": true, - "dependencies": { - "@esbuild-kit/core-utils": "^3.3.2", - "get-tsconfig": "^4.7.0" } }, - "node_modules/@esbuild-plugins/node-globals-polyfill": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", - "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], "dev": true, - "peerDependencies": { - "esbuild": "*" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@esbuild-plugins/node-modules-polyfill": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", - "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "escape-string-regexp": "^4.0.0", - "rollup-plugin-node-polyfills": "^0.2.1" - }, - "peerDependencies": { - "esbuild": "*" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", - "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.9" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", - "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.0", - "@floating-ui/utils": "^0.2.9" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", - "license": "MIT" - }, - "node_modules/@formatjs/ecma402-abstract": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz", - "integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==", - "license": "MIT", - "dependencies": { - "@formatjs/fast-memoize": "2.2.7", - "@formatjs/intl-localematcher": "0.6.1", - "decimal.js": "^10.4.3", - "tslib": "^2.8.0" - } - }, - "node_modules/@formatjs/fast-memoize": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", - "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz", - "integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==", - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.3.4", - "@formatjs/icu-skeleton-parser": "1.8.14", - "tslib": "^2.8.0" - } - }, - "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.14", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz", - "integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==", - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.3.4", - "tslib": "^2.8.0" - } - }, - "node_modules/@formatjs/intl-localematcher": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz", - "integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz", - "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.7.13", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@hono/node-server": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.14.3.tgz", - "integrity": "sha512-KuDMwwghtFYSmIpr4WrKs1VpelTrptvJ+6x6mbUcZnFcc213cumTF5BdqfHyW93B19TNI4Vaev14vOI2a0Ie3w==", - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" + "node": ">=12" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.10.0" + "node": ">=12" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", - "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ - "arm64" + "ppc64" ], + "dev": true, "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.3" + "node": ">=12" } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", - "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ - "x64" + "riscv64" ], + "dev": true, "optional": true, "os": [ - "darwin" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.3" + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ - "arm64" + "s390x" ], + "dev": true, "optional": true, "os": [ - "darwin" + "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ - "darwin" + "linux" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", - "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ - "arm" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "netbsd" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", - "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "openbsd" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", - "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", "cpu": [ - "ppc64" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "sunos" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", - "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ - "s390x" + "arm64" ], + "dev": true, "optional": true, "os": [ - "linux" + "win32" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", - "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ - "x64" + "ia32" ], + "dev": true, "optional": true, "os": [ - "linux" + "win32" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", - "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "node_modules/@esbuild-kit/core-utils/node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ - "arm64" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "win32" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=12" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", - "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "node_modules/@esbuild-kit/core-utils/node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/@esbuild-kit/esm-loader": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz", + "integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==", + "dev": true, + "dependencies": { + "@esbuild-kit/core-utils": "^3.3.2", + "get-tsconfig": "^4.7.0" + } + }, + "node_modules/@esbuild-plugins/node-globals-polyfill": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", + "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "dev": true, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild-plugins/node-modules-polyfill": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", + "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^4.0.0", + "rollup-plugin-node-polyfills": "^0.2.1" + }, + "peerDependencies": { + "esbuild": "*" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ - "x64" + "ppc64" ], + "dev": true, "optional": true, "os": [ - "linux" + "aix" ], - "funding": { - "url": "https://opencollective.com/libvips" + "engines": { + "node": ">=18" } }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", - "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", - "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", - "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ - "ppc64" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", - "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ - "s390x" + "x64" ], + "dev": true, "optional": true, "os": [ - "linux" + "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", - "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "cpu": [ + "arm" + ], + "dev": true, "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", - "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", - "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ - "x64" + "ia32" ], + "dev": true, "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + "node": ">=18" } }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", - "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ - "wasm32" + "loong64" ], + "dev": true, "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.5.0" - }, + "os": [ + "linux" + ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=18" } }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", - "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ - "arm64" + "mips64el" ], + "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=18" } }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", - "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ - "ia32" + "ppc64" ], + "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=18" } }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", - "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ - "x64" + "riscv64" ], + "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=18" } }, - "node_modules/@inngest/ai": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@inngest/ai/-/ai-0.1.5.tgz", - "integrity": "sha512-Nj+Ee/O3EYmPIw+2eGryRh+b2TcqaZyL52RaO1/Cz707R/HrJVVDx8uRQo93gSeN4lMlaOluNrdleyM5M5wcQA==", - "license": "Apache-2.0", - "dependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@internationalized/date": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.0.tgz", - "integrity": "sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" + "node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@internationalized/message": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.7.tgz", - "integrity": "sha512-gLQlhEW4iO7DEFPf/U7IrIdA3UyLGS0opeqouaFwlMObLUzwexRjbygONHDVbC9G9oFLXsLyGKYkJwqXw/QADg==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0", - "intl-messageformat": "^10.1.0" + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@internationalized/number": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.1.tgz", - "integrity": "sha512-UVsb4bCwbL944E0SX50CHFtWEeZ2uB5VozZ5yDXJdq6iPZsZO5p+bjVMZh2GxHf4Bs/7xtDCcPwEa2NU9DaG/g==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@internationalized/string": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.6.tgz", - "integrity": "sha512-LR2lnM4urJta5/wYJVV7m8qk5DrMZmLRTuFhbQO5b9/sKLHgty6unQy1Li4+Su2DWydmB4aZdS5uxBRXIq2aAw==", - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.0" + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", - "license": "MIT" + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@ipld/dag-cbor": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-7.0.3.tgz", - "integrity": "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==", - "license": "(Apache-2.0 AND MIT)", - "dependencies": { - "cborg": "^1.6.0", - "multiformats": "^9.5.4" - } - }, - "node_modules/@ipld/dag-cbor/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "minipass": "^7.0.4" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, - "node_modules/@jpwilliams/waitgroup": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@jpwilliams/waitgroup/-/waitgroup-2.1.1.tgz", - "integrity": "sha512-0CxRhNfkvFCTLZBKGvKxY2FYtYW1yWhO2McLqBL0X5UWvYjIf9suH8anKW/DNutl369A75Ewyoh2iJMwBZ2tRg==", - "license": "MIT" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@mdx-js/loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.0.tgz", - "integrity": "sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg==", "dependencies": { - "@mdx-js/mdx": "^3.0.0", - "source-map": "^0.7.0" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "webpack": ">=5" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@mdx-js/loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "engines": { - "node": ">= 8" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", - "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/mdx/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dependencies": { - "@types/estree": "^1.0.0" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@mdx-js/mdx/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, "engines": { - "node": ">= 8" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@mdx-js/react": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", - "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@next/bundle-analyzer": { - "version": "15.3.2", - "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-15.3.2.tgz", - "integrity": "sha512-zY5O1PNKNxWEjaFX8gKzm77z2oL0cnj+m5aiqNBgay9LPLCDO13Cf+FJONeNq/nJjeXptwHFT9EMmTecF9U4Iw==", - "license": "MIT", - "dependencies": { - "webpack-bundle-analyzer": "4.10.1" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@next/env": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.3.tgz", - "integrity": "sha512-RSEDTRqyihYXygx/OJXwvVupfr9m04+0vH8vyy0HfZ7keRto6VX9BbEk0J2PUk0VGy6YhklJUSrgForov5F9pw==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.3.tgz", - "integrity": "sha512-SdhaKdko6dpsSr0DldkESItVrnPYB1NS2NpShCSX5lc7SSQmLZt5Mug6t2xbiuVWEVDLZSuIAoQyYVBYp0dR5g==", + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", "dev": true, - "license": "MIT", "dependencies": { - "fast-glob": "3.3.1" + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, - "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@types/json-schema": "^7.0.15" }, "engines": { - "node": ">=8.6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, - "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@next/mdx": { - "version": "15.3.2", - "resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-15.3.2.tgz", - "integrity": "sha512-D6lSSbVzn1EiPwrBKG5QzXClcgdqiNCL8a3/6oROinzgZnYSxbVmnfs0UrqygtGSOmgW7sdJJSEOy555DoAwvw==", - "license": "MIT", - "dependencies": { - "source-map": "^0.7.0" - }, - "peerDependencies": { - "@mdx-js/loader": ">=0.15.0", - "@mdx-js/react": ">=0.15.0" + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "@mdx-js/loader": { - "optional": true - }, - "@mdx-js/react": { - "optional": true - } + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/@next/mdx/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.3.tgz", - "integrity": "sha512-nzbHQo69+au9wJkGKTU9lP7PXv0d1J5ljFpvb+LnEomLtSbJkbZyEs6sbF3plQmiOB2l9OBtN2tNSvCH1nQ9Jg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, "engines": { - "node": ">= 10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@next/swc-darwin-x64": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.3.tgz", - "integrity": "sha512-w83w4SkOOhekJOcA5HBvHyGzgV1W/XvOfpkrxIse4uPWhYTTRwtGEM4v/jiXwNSJvfRvah0H8/uTLBKRXlef8g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=14" } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.3.tgz", - "integrity": "sha512-+m7pfIs0/yvgVu26ieaKrifV8C8yiLe7jVp9SpcIzg7XmyyNE7toC1fy5IOQozmr6kWl/JONC51osih2RyoXRw==", - "cpu": [ - "arm64" - ], + "node_modules/@floating-ui/core": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", + "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@floating-ui/utils": "^0.2.9" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.3.tgz", - "integrity": "sha512-u3PEIzuguSenoZviZJahNLgCexGFhso5mxWCrrIMdvpZn6lkME5vc/ADZG8UUk5K1uWRy4hqSFECrON6UKQBbQ==", - "cpu": [ - "arm64" - ], + "node_modules/@floating-ui/dom": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", + "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@floating-ui/core": "^1.7.0", + "@floating-ui/utils": "^0.2.9" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.3.tgz", - "integrity": "sha512-lDtOOScYDZxI2BENN9m0pfVPJDSuUkAD1YXSvlJF0DKwZt0WlA7T7o3wrcEr4Q+iHYGzEaVuZcsIbCps4K27sA==", - "cpu": [ - "x64" - ], + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.3.tgz", - "integrity": "sha512-9vWVUnsx9PrY2NwdVRJ4dUURAQ8Su0sLRPqcCCxtX5zIQUBES12eRVHq6b70bbfaVaxIDGJN2afHui0eDm+cLg==", - "cpu": [ - "x64" - ], + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "license": "MIT" + }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz", + "integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.1", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.3.tgz", - "integrity": "sha512-1CU20FZzY9LFQigRi6jM45oJMU3KziA5/sSG+dXeVaTm661snQP6xu3ykGxxwU5sLG3sh14teO/IOEPVsQMRfA==", - "cpu": [ - "arm64" - ], + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "tslib": "^2.8.0" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.3.tgz", - "integrity": "sha512-JMoLAq3n3y5tKXPQwCK5c+6tmwkuFDa2XAxz8Wm4+IVthdBZdZGh+lmiLUHg9f9IDwIQpUjp+ysd6OkYTyZRZw==", - "cpu": [ - "x64" - ], + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz", + "integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.4", + "@formatjs/icu-skeleton-parser": "1.8.14", + "tslib": "^2.8.0" } }, - "node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz", + "integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.7.1" + "@formatjs/ecma402-abstract": "2.3.4", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz", + "integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz", + "integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.13", + "@js-sdsl/ordered-map": "^4.4.2" }, "engines": { - "node": "^14.21.3 || >=16" + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "node_modules/@hono/node-server": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.14.3.tgz", + "integrity": "sha512-KuDMwwghtFYSmIpr4WrKs1VpelTrptvJ+6x6mbUcZnFcc213cumTF5BdqfHyW93B19TNI4Vaev14vOI2a0Ie3w==", "license": "MIT", "engines": { - "node": "^14.21.3 || >=16" + "node": ">=18.14.1" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "hono": "^4" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, "engines": { - "node": ">= 8" + "node": ">=18.18.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, "engines": { - "node": ">= 8" + "node": ">=18.18.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@inngest/ai": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@inngest/ai/-/ai-0.1.5.tgz", + "integrity": "sha512-Nj+Ee/O3EYmPIw+2eGryRh+b2TcqaZyL52RaO1/Cz707R/HrJVVDx8uRQo93gSeN4lMlaOluNrdleyM5M5wcQA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^22.10.5", + "typescript": "^5.7.3" + } + }, + "node_modules/@internationalized/date": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.0.tgz", + "integrity": "sha512-J51AJ0fEL68hE4CwGPa6E0PO6JDaVLd8aln48xFCSy7CZkZc96dGEGmLs2OEEbBxcsVZtfrqkXJwI2/MSG8yKw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/message": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.7.tgz", + "integrity": "sha512-gLQlhEW4iO7DEFPf/U7IrIdA3UyLGS0opeqouaFwlMObLUzwexRjbygONHDVbC9G9oFLXsLyGKYkJwqXw/QADg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "intl-messageformat": "^10.1.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.1.tgz", + "integrity": "sha512-UVsb4bCwbL944E0SX50CHFtWEeZ2uB5VozZ5yDXJdq6iPZsZO5p+bjVMZh2GxHf4Bs/7xtDCcPwEa2NU9DaG/g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.6.tgz", + "integrity": "sha512-LR2lnM4urJta5/wYJVV7m8qk5DrMZmLRTuFhbQO5b9/sKLHgty6unQy1Li4+Su2DWydmB4aZdS5uxBRXIq2aAw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" + }, + "node_modules/@ipld/dag-cbor": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@ipld/dag-cbor/-/dag-cbor-7.0.3.tgz", + "integrity": "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==", + "license": "(Apache-2.0 AND MIT)", + "dependencies": { + "cborg": "^1.6.0", + "multiformats": "^9.5.4" + } + }, + "node_modules/@ipld/dag-cbor/node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jpwilliams/waitgroup": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@jpwilliams/waitgroup/-/waitgroup-2.1.1.tgz", + "integrity": "sha512-0CxRhNfkvFCTLZBKGvKxY2FYtYW1yWhO2McLqBL0X5UWvYjIf9suH8anKW/DNutl369A75Ewyoh2iJMwBZ2tRg==", + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@mdx-js/loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-3.1.0.tgz", + "integrity": "sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg==", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "webpack": ">=5" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@mdx-js/loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@mdx-js/mdx/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@next/bundle-analyzer": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-16.0.3.tgz", + "integrity": "sha512-6Xo8f8/ZXtASfTPa6TH1aUn+xDg9Pkyl1YHVxu+89cVdLH7MnYjxv3rPOfEJ9BwCZCU2q4Flyw5MwltfD2pGbA==", + "dependencies": { + "webpack-bundle-analyzer": "4.10.1" + } + }, + "node_modules/@next/env": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.3.tgz", + "integrity": "sha512-IqgtY5Vwsm14mm/nmQaRMmywCU+yyMIYfk3/MHZ2ZTJvwVbBn3usZnjMi1GacrMVzVcAxJShTCpZlPs26EdEjQ==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.3.tgz", + "integrity": "sha512-6sPWmZetzFWMsz7Dhuxsdmbu3fK+/AxKRtj7OB0/3OZAI2MHB/v2FeYh271LZ9abvnM1WIwWc/5umYjx0jo5sQ==", + "dev": true, + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@next/mdx": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-16.0.3.tgz", + "integrity": "sha512-uVl2JSEGAjBV+EVnpt1cZN88SK3lJ2n7Fc+iqTsgVx2g9+Y6ru+P6nuUgXd38OHPUIwzL6k2V1u4iV3kwuTySQ==", + "dependencies": { + "source-map": "^0.7.0" + }, + "peerDependencies": { + "@mdx-js/loader": ">=0.15.0", + "@mdx-js/react": ">=0.15.0" + }, + "peerDependenciesMeta": { + "@mdx-js/loader": { + "optional": true + }, + "@mdx-js/react": { + "optional": true + } + } + }, + "node_modules/@next/mdx/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.3.tgz", + "integrity": "sha512-MOnbd92+OByu0p6QBAzq1ahVWzF6nyfiH07dQDez4/Nku7G249NjxDVyEfVhz8WkLiOEU+KFVnqtgcsfP2nLXg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.3.tgz", + "integrity": "sha512-i70C4O1VmbTivYdRlk+5lj9xRc2BlK3oUikt3yJeHT1unL4LsNtN7UiOhVanFdc7vDAgZn1tV/9mQwMkWOJvHg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.3.tgz", + "integrity": "sha512-O88gCZ95sScwD00mn/AtalyCoykhhlokxH/wi1huFK+rmiP5LAYVs/i2ruk7xST6SuXN4NI5y4Xf5vepb2jf6A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.3.tgz", + "integrity": "sha512-CEErFt78S/zYXzFIiv18iQCbRbLgBluS8z1TNDQoyPi8/Jr5qhR3e8XHAIxVxPBjDbEMITprqELVc5KTfFj0gg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.3.tgz", + "integrity": "sha512-Tc3i+nwt6mQ+Dwzcri/WNDj56iWdycGVh5YwwklleClzPzz7UpfaMw1ci7bLl6GRYMXhWDBfe707EXNjKtiswQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.3.tgz", + "integrity": "sha512-zTh03Z/5PBBPdTurgEtr6nY0vI9KR9Ifp/jZCcHlODzwVOEKcKRBtQIGrkc7izFgOMuXDEJBmirwpGqdM/ZixA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.3.tgz", + "integrity": "sha512-Jc1EHxtZovcJcg5zU43X3tuqzl/sS+CmLgjRP28ZT4vk869Ncm2NoF8qSTaL99gh6uOzgM99Shct06pSO6kA6g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.3.tgz", + "integrity": "sha512-N7EJ6zbxgIYpI/sWNzpVKRMbfEGgsWuOIvzkML7wxAAZhPk1Msxuo/JDu1PKjWGrAoOLaZcIX5s+/pF5LIbBBg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -5997,12 +7012,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", - "dev": true - }, "node_modules/@shikijs/core": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.8.1.tgz", @@ -6597,6 +7606,12 @@ "@types/unist": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -6723,22 +7738,20 @@ "integrity": "sha512-B34A7uot1Cv0XtaHRYDATltAdKx0BvVKNgYNqE4WjtPUa4VQJM7kxeXcVKaH+KS+kCmZ+6w+QaUdcljiheiBJA==" }, "node_modules/@types/react": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.3.tgz", - "integrity": "sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==", - "license": "MIT", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz", + "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "dependencies": { - "csstype": "^3.0.2" + "csstype": "^3.2.2" } }, "node_modules/@types/react-dom": { - "version": "19.1.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.3.tgz", - "integrity": "sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==", + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, - "license": "MIT", "peerDependencies": { - "@types/react": "^19.0.0" + "@types/react": "^19.2.0" } }, "node_modules/@types/shimmer": { @@ -6776,19 +7789,18 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz", - "integrity": "sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz", + "integrity": "sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/type-utils": "8.32.0", - "@typescript-eslint/utils": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/type-utils": "8.47.0", + "@typescript-eslint/utils": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, @@ -6800,22 +7812,30 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "@typescript-eslint/parser": "^8.47.0", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.0.tgz", - "integrity": "sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.47.0.tgz", + "integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "debug": "^4.3.4" }, "engines": { @@ -6827,18 +7847,38 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", + "dev": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.0.tgz", - "integrity": "sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6848,15 +7888,31 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.0.tgz", - "integrity": "sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz", + "integrity": "sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.32.0", - "@typescript-eslint/utils": "8.32.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -6869,15 +7925,14 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.0.tgz", - "integrity": "sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", "dev": true, - "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -6887,14 +7942,15 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.0.tgz", - "integrity": "sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/visitor-keys": "8.32.0", + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -6910,15 +7966,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -6928,7 +7983,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6940,16 +7994,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.0.tgz", - "integrity": "sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.32.0", - "@typescript-eslint/types": "8.32.0", - "@typescript-eslint/typescript-estree": "8.32.0" + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6960,18 +8013,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.0.tgz", - "integrity": "sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.32.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.47.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6981,19 +8033,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -7167,7 +8206,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7264,17 +8302,19 @@ "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7305,17 +8345,18 @@ } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7325,15 +8366,15 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7544,6 +8585,15 @@ } ] }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.30", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.30.tgz", + "integrity": "sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bignumber.js": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", @@ -7662,6 +8712,39 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -7765,9 +8848,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001717", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001717.tgz", - "integrity": "sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "funding": [ { "type": "opencollective", @@ -7781,8 +8864,7 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ], - "license": "CC-BY-4.0" + ] }, "node_modules/canonicalize": { "version": "1.0.8", @@ -8105,6 +9187,12 @@ "node": ">= 0.6" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -8156,9 +9244,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -8170,9 +9258,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" }, "node_modules/d": { "version": "1.0.2", @@ -8294,202 +9382,542 @@ } } }, - "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", - "license": "MIT" + "node_modules/decimal.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", + "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", + "license": "MIT" + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", + "dev": true, + "dependencies": { + "heap": ">= 0.2.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dreamopt": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz", + "integrity": "sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==", + "dev": true, + "dependencies": { + "wordwrap": ">=0.0.2" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/drizzle-kit": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.21.4.tgz", + "integrity": "sha512-Nxcc1ONJLRgbhmR+azxjNF9Ly9privNLEIgW53c92whb4xp8jZLH1kMCh/54ci1mTMuYxPdOukqLwJ8wRudNwA==", + "dev": true, + "dependencies": { + "@esbuild-kit/esm-loader": "^2.5.5", + "commander": "^9.4.1", + "env-paths": "^3.0.0", + "esbuild": "^0.19.7", + "esbuild-register": "^3.5.0", + "glob": "^8.1.0", + "hanji": "^0.0.5", + "json-diff": "0.9.0", + "zod": "^3.20.2" + }, + "bin": { + "drizzle-kit": "bin.cjs" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/decode-named-character-reference": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", - "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/drizzle-kit/node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/drizzle-kit/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10" + "node": ">=12" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">=12" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=12" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "node_modules/drizzle-kit/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" + "node_modules/drizzle-kit/node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/drizzle-kit/node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/difflib": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", - "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", + "node_modules/drizzle-kit/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "heap": ">= 0.2.0" - }, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/drizzle-kit/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/drizzle-kit/node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, - "node_modules/dreamopt": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz", - "integrity": "sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==", + "node_modules/drizzle-kit/node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "wordwrap": ">=0.0.2" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.4.0" + "node": ">=12" } }, - "node_modules/drizzle-kit": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.21.4.tgz", - "integrity": "sha512-Nxcc1ONJLRgbhmR+azxjNF9Ly9privNLEIgW53c92whb4xp8jZLH1kMCh/54ci1mTMuYxPdOukqLwJ8wRudNwA==", + "node_modules/drizzle-kit/node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@esbuild-kit/esm-loader": "^2.5.5", - "commander": "^9.4.1", - "env-paths": "^3.0.0", - "esbuild": "^0.19.7", - "esbuild-register": "^3.5.0", - "glob": "^8.1.0", - "hanji": "^0.0.5", - "json-diff": "0.9.0", - "zod": "^3.20.2" - }, - "bin": { - "drizzle-kit": "bin.cjs" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/drizzle-kit/node_modules/@esbuild/linux-x64": { + "node_modules/drizzle-kit/node_modules/@esbuild/win32-x64": { "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": ">=12" @@ -8678,6 +10106,12 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/electron-to-chromium": { + "version": "1.5.258", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.258.tgz", + "integrity": "sha512-rHUggNV5jKQ0sSdWwlaRDkFc3/rRJIVnOSe9yR4zrR07m3ZxhP4N27Hlg8VeJGGYgFTxK5NqDmWI4DSH72vIJg==", + "dev": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -8731,28 +10165,27 @@ } }, "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, - "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -8764,21 +10197,24 @@ "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", + "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", + "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", + "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -8787,7 +10223,7 @@ "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -8870,12 +10306,15 @@ } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -9031,10 +10470,26 @@ "esbuild": ">=0.12 <1" } }, + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -9057,80 +10512,82 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-next": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.3.tgz", - "integrity": "sha512-e6j+QhQFOr5pfsc8VJbuTD9xTXJaRvMHYjEeLPA2pFkheNlgPLCkxdvhxhfuM4KGcqSZj2qEnpHisdTVs3BxuQ==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.3.tgz", + "integrity": "sha512-5F6qDjcZldf0Y0ZbqvWvap9xzYUxyDf7/of37aeyhvkrQokj/4bT1JYWZdlWUr283aeVa+s52mPq9ogmGg+5dw==", "dev": true, - "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "15.5.3", - "@rushstack/eslint-patch": "^1.10.3", - "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@next/eslint-plugin-next": "16.0.3", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.31.0", + "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", - "eslint-plugin-react-hooks": "^5.0.0" + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" }, "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "peerDependenciesMeta": { @@ -9139,6 +10596,18 @@ } } }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -9185,11 +10654,10 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -9212,30 +10680,29 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, - "license": "MIT", "dependencies": { "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", + "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", - "is-core-module": "^2.15.1", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", + "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "engines": { @@ -9339,18 +10806,45 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", "dev": true, - "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, + "node_modules/eslint-plugin-react-hooks/node_modules/zod": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/eslint-plugin-react-hooks/node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -9393,28 +10887,28 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9436,17 +10930,17 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -9802,9 +11296,9 @@ } }, "node_modules/fast-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", - "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -9815,8 +11309,7 @@ "type": "opencollective", "url": "https://opencollective.com/fastify" } - ], - "license": "BSD-3-Clause" + ] }, "node_modules/fastq": { "version": "1.17.1", @@ -9864,15 +11357,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -9937,23 +11430,22 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, "node_modules/follow-redirects": { @@ -10155,6 +11647,15 @@ "node": ">=14" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -10316,15 +11817,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10784,6 +12282,21 @@ "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", "dev": true }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/hono": { "version": "4.7.11", "resolved": "https://registry.npmjs.org/hono/-/hono-4.7.11.tgz", @@ -10888,9 +12401,9 @@ } }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -11375,6 +12888,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -11401,15 +12926,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -11666,9 +13182,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -11677,6 +13193,18 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -11713,8 +13241,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -13581,12 +15108,11 @@ } }, "node_modules/next": { - "version": "15.5.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.3.tgz", - "integrity": "sha512-r/liNAx16SQj4D+XH/oI1dlpv9tdKJ6cONYPwwcCC46f2NjpaRWY+EKCzULfgQYV6YKXjHBchff2IZBSlZmJNw==", - "license": "MIT", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.3.tgz", + "integrity": "sha512-Ka0/iNBblPFcIubTA1Jjh6gvwqfjrGq1Y2MTI5lbjeLIAfmC+p5bQmojpRZqgHHVu5cG4+qdIiwXiBSm/8lZ3w==", "dependencies": { - "@next/env": "15.5.3", + "@next/env": "16.0.3", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", @@ -13596,18 +15122,18 @@ "next": "dist/bin/next" }, "engines": { - "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.3", - "@next/swc-darwin-x64": "15.5.3", - "@next/swc-linux-arm64-gnu": "15.5.3", - "@next/swc-linux-arm64-musl": "15.5.3", - "@next/swc-linux-x64-gnu": "15.5.3", - "@next/swc-linux-x64-musl": "15.5.3", - "@next/swc-win32-arm64-msvc": "15.5.3", - "@next/swc-win32-x64-msvc": "15.5.3", - "sharp": "^0.34.3" + "@next/swc-darwin-arm64": "16.0.3", + "@next/swc-darwin-x64": "16.0.3", + "@next/swc-linux-arm64-gnu": "16.0.3", + "@next/swc-linux-arm64-musl": "16.0.3", + "@next/swc-linux-x64-gnu": "16.0.3", + "@next/swc-linux-x64-musl": "16.0.3", + "@next/swc-win32-arm64-msvc": "16.0.3", + "@next/swc-win32-x64-msvc": "16.0.3", + "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -13732,6 +15258,12 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -14101,15 +15633,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -14798,10 +16321,9 @@ } }, "node_modules/react": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", - "license": "MIT", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "engines": { "node": ">=0.10.0" } @@ -14920,15 +16442,14 @@ } }, "node_modules/react-dom": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", - "license": "MIT", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "dependencies": { - "scheduler": "^0.26.0" + "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.1.1" + "react": "^19.2.0" } }, "node_modules/react-is": { @@ -15441,7 +16962,6 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -15497,57 +17017,20 @@ "node_modules/resolve.exports": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, "node_modules/rollup-plugin-inject": { @@ -15707,10 +17190,9 @@ "license": "ISC" }, "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" }, "node_modules/scmp": { "version": "2.1.0", @@ -16155,6 +17637,19 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stoppable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", @@ -16482,12 +17977,6 @@ "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", "license": "ISC" }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/thread-stream": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", @@ -16643,831 +18132,1207 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=18.12" + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-morph": { + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-24.0.0.tgz", + "integrity": "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.25.0", + "code-block-writer": "^13.0.3" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/twilio": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.3.7.tgz", + "integrity": "sha512-9PaIXQ2CSfKKKjsQ7YpLRi7vo77ryevjoylR+7uSB0D/9t5VOYz+QNxNuR3YGk9UCt/f5pxzjVQraWVI5lQFSQ==", + "license": "MIT", + "dependencies": { + "axios": "^1.7.4", + "dayjs": "^1.11.9", + "https-proxy-agent": "^5.0.0", + "jsonwebtoken": "^9.0.2", + "qs": "^6.9.4", + "scmp": "^2.1.0", + "xmlbuilder": "^13.0.2" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/twilio/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/twilio/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", + "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.47.0", + "@typescript-eslint/parser": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/ts-morph": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-24.0.0.tgz", - "integrity": "sha512-2OAOg/Ob5yx9Et7ZX4CvTCc0UFoZHwLEJ+dpDPSUi5TgwwlTlX47w+iFRrEwzUZwYACjq83cgjS/Da50Ga37uw==", - "dev": true, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "license": "MIT", - "dependencies": { - "@ts-morph/common": "~0.25.0", - "code-block-writer": "^13.0.3" - } + "peer": true }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, + "node_modules/uint8arrays": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", + "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", + "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "multiformats": "^9.4.2" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" + "node_modules/uint8arrays/node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" }, - "node_modules/tsx": { - "version": "4.19.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", - "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { - "node": ">=18.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/twilio": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.3.7.tgz", - "integrity": "sha512-9PaIXQ2CSfKKKjsQ7YpLRi7vo77ryevjoylR+7uSB0D/9t5VOYz+QNxNuR3YGk9UCt/f5pxzjVQraWVI5lQFSQ==", + "node_modules/undici": { + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", + "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "dependencies": { - "axios": "^1.7.4", - "dayjs": "^1.11.9", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^9.0.2", - "qs": "^6.9.4", - "scmp": "^2.1.0", - "xmlbuilder": "^13.0.2" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=14.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/twilio/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", "dependencies": { - "debug": "4" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "engines": { - "node": ">= 6.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/twilio/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "dependencies": { - "agent-base": "6", - "debug": "4" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", "dependencies": { - "prelude-ls": "^1.2.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": ">= 0.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">= 0.8" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, - "engines": { - "node": ">= 0.4" + "bin": { + "update-browserslist-db": "cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "tslib": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, - "engines": { - "node": ">=14.17" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", "license": "MIT", - "peer": true + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } }, - "node_modules/uint8arrays": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.0.0.tgz", - "integrity": "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA==", + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "license": "MIT", - "dependencies": { - "multiformats": "^9.4.2" + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/uint8arrays/node_modules/multiformats": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", - "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", - "license": "(Apache-2.0 AND MIT)" + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", + "integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/undici": { - "version": "6.21.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz", - "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==", - "license": "MIT", - "engines": { - "node": ">=18.17" + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "license": "MIT" - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", "dependencies": { "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", + "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "is-plain-object": "^5.0.0", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "node_modules/whatwg-url": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=18" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { - "@types/unist": "^3.0.0" + "isexe": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", - "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/use-callback-ref": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/workerd": { + "version": "1.20240524.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240524.0.tgz", + "integrity": "sha512-LWLe5D8PVHBcqturmBbwgI71r7YPpIMYZoVEH6S4G35EqIJ55cb0n3FipoSyraoIfpcCxCFxX1K6WsRHbP3pFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "workerd": "bin/workerd" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + "node": ">=16" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20240524.0", + "@cloudflare/workerd-darwin-arm64": "1.20240524.0", + "@cloudflare/workerd-linux-64": "1.20240524.0", + "@cloudflare/workerd-linux-arm64": "1.20240524.0", + "@cloudflare/workerd-windows-64": "1.20240524.0" } }, - "node_modules/use-sidecar": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", - "license": "MIT", + "node_modules/wrangler": { + "version": "3.57.2", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.57.2.tgz", + "integrity": "sha512-QegYf0FW+4prlFKE9iHr1EGrCo8ejcGL9gaqEXrzQ0vbTdazykYbY0I5UpHFLNq2dIF9I/ifEoLRKr636tyHEw==", + "dev": true, "dependencies": { - "detect-node-es": "^1.1.0", - "tslib": "^2.0.0" + "@cloudflare/kv-asset-handler": "0.3.2", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "esbuild": "0.17.19", + "miniflare": "3.20240524.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "resolve": "^1.22.8", + "resolve.exports": "^2.0.2", + "selfsigned": "^2.0.1", + "source-map": "0.6.1", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=10" + "node": ">=16.17.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + "@cloudflare/workers-types": "^4.20240524.0" }, "peerDependenciesMeta": { - "@types/react": { + "@cloudflare/workers-types": { "optional": true } } }, - "node_modules/use-sync-external-store": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", + "node_modules/wrangler/node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.4.0" + "node": ">=12" } }, - "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" + "node_modules/wrangler/node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=12" } }, - "node_modules/vfile": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", - "integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/wrangler/node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/wrangler/node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/w3c-keyname": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", + "node_modules/wrangler/node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { "node": ">=12" } }, - "node_modules/webpack-bundle-analyzer": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz", - "integrity": "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==", - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "gzip-size": "^6.0.0", - "html-escaper": "^2.0.2", - "is-plain-object": "^5.0.0", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" - }, + "node_modules/wrangler/node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10.13.0" + "node": ">=12" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", + "node_modules/wrangler/node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10" + "node": ">=12" } }, - "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node_modules/wrangler/node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/whatwg-url": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", - "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", - "license": "MIT", - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, + "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "node_modules/wrangler/node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "node_modules/wrangler/node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/workerd": { - "version": "1.20240524.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240524.0.tgz", - "integrity": "sha512-LWLe5D8PVHBcqturmBbwgI71r7YPpIMYZoVEH6S4G35EqIJ55cb0n3FipoSyraoIfpcCxCFxX1K6WsRHbP3pFA==", + "node_modules/wrangler/node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], "dev": true, - "hasInstallScript": true, - "bin": { - "workerd": "bin/workerd" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20240524.0", - "@cloudflare/workerd-darwin-arm64": "1.20240524.0", - "@cloudflare/workerd-linux-64": "1.20240524.0", - "@cloudflare/workerd-linux-arm64": "1.20240524.0", - "@cloudflare/workerd-windows-64": "1.20240524.0" + "node": ">=12" } }, - "node_modules/wrangler": { - "version": "3.57.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.57.2.tgz", - "integrity": "sha512-QegYf0FW+4prlFKE9iHr1EGrCo8ejcGL9gaqEXrzQ0vbTdazykYbY0I5UpHFLNq2dIF9I/ifEoLRKr636tyHEw==", + "node_modules/wrangler/node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@cloudflare/kv-asset-handler": "0.3.2", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@esbuild-plugins/node-modules-polyfill": "^0.2.2", - "blake3-wasm": "^2.1.5", - "chokidar": "^3.5.3", - "esbuild": "0.17.19", - "miniflare": "3.20240524.0", - "nanoid": "^3.3.3", - "path-to-regexp": "^6.2.0", - "resolve": "^1.22.8", - "resolve.exports": "^2.0.2", - "selfsigned": "^2.0.1", - "source-map": "0.6.1", - "xxhash-wasm": "^1.0.1" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=16.17.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@cloudflare/workers-types": "^4.20240524.0" - }, - "peerDependenciesMeta": { - "@cloudflare/workers-types": { - "optional": true - } + "node": ">=12" } }, - "node_modules/wrangler/node_modules/@esbuild/linux-x64": { + "node_modules/wrangler/node_modules/@esbuild/win32-x64": { "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", - "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "linux" + "win32" ], "engines": { "node": ">=12" diff --git a/package.json b/package.json index e7b52160..3a5b8ca4 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,8 @@ "@hono/node-server": "^1.14.3", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/bundle-analyzer": "^15.3.2", - "@next/mdx": "15.3.2", + "@next/bundle-analyzer": "16.0.3", + "@next/mdx": "16.0.3", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-popover": "^1.1.15", @@ -61,7 +61,7 @@ "linkifyjs": "^4.2.0", "luxon": "^3.7.2", "multiformats": "^13.3.2", - "next": "^15.5.3", + "next": "16.0.3", "pg": "^8.16.3", "prosemirror-commands": "^1.5.2", "prosemirror-inputrules": "^1.4.0", @@ -69,10 +69,10 @@ "prosemirror-model": "^1.21.0", "prosemirror-schema-basic": "^1.2.2", "prosemirror-state": "^1.4.3", - "react": "^19.1.1", + "react": "19.2.0", "react-aria-components": "^1.8.0", "react-day-picker": "^9.3.0", - "react-dom": "^19.1.1", + "react-dom": "19.2.0", "react-use-measure": "^2.1.1", "redlock": "^5.0.0-beta.2", "rehype-parse": "^9.0.0", @@ -102,13 +102,13 @@ "@types/katex": "^0.16.7", "@types/luxon": "^3.7.1", "@types/node": "^22.15.17", - "@types/react": "19.1.3", - "@types/react-dom": "19.1.3", + "@types/react": "19.2.6", + "@types/react-dom": "19.2.3", "@types/uuid": "^10.0.0", "drizzle-kit": "^0.21.2", "esbuild": "^0.25.4", - "eslint": "8.57.0", - "eslint-config-next": "^15.5.3", + "eslint": "^9.39.1", + "eslint-config-next": "16.0.3", "postcss": "^8.4.38", "prettier": "3.2.5", "supabase": "^1.187.3", @@ -120,7 +120,7 @@ "overrides": { "ajv": "^8.17.1", "whatwg-url": "^14.0.0", - "@types/react": "19.1.3", - "@types/react-dom": "19.1.3" + "@types/react": "19.2.6", + "@types/react-dom": "19.2.3" } } diff --git a/src/utils/getCurrentDeploymentDomain.ts b/src/utils/getCurrentDeploymentDomain.ts index c8fd21b2..9a438ebd 100644 --- a/src/utils/getCurrentDeploymentDomain.ts +++ b/src/utils/getCurrentDeploymentDomain.ts @@ -1,6 +1,6 @@ -import { headers, type UnsafeUnwrappedHeaders } from "next/headers"; -export function getCurrentDeploymentDomain() { - const headersList = (headers() as unknown as UnsafeUnwrappedHeaders); +import { headers } from "next/headers"; +export async function getCurrentDeploymentDomain() { + const headersList = await headers(); const hostname = headersList.get("x-forwarded-host"); let protocol = headersList.get("x-forwarded-proto"); return `${protocol}://${hostname}/`; diff --git a/src/utils/isBot.ts b/src/utils/isBot.ts deleted file mode 100644 index 1f1a8222..00000000 --- a/src/utils/isBot.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { cookies, headers, type UnsafeUnwrappedHeaders } from "next/headers"; -export function getIsBot() { - const userAgent = - (headers() as unknown as UnsafeUnwrappedHeaders).get("user-agent") || ""; - const botPatterns = [ - /bot/i, - /crawler/i, - /spider/i, - /googlebot/i, - /bingbot/i, - /yahoo/i, - // Add more patterns as needed - ]; - - return botPatterns.some((pattern) => pattern.test(userAgent)); -} diff --git a/tsconfig.json b/tsconfig.json index 23ebaecd..ba4b959c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,13 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "types": ["@cloudflare/workers-types"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "types": [ + "@cloudflare/workers-types" + ], "baseUrl": ".", "allowJs": true, "skipLibCheck": true, @@ -30,7 +36,10 @@ "**/*.js", "**/*.ts", "**/*.tsx", - "**/*.mdx" + "**/*.mdx", + ".next/dev/types/**/*.ts" ], - "exclude": ["node_modules"] + "exclude": [ + "node_modules" + ] } -- 2.51.2 From 9500048ba8aa3f6fc8949e263ac42ac484e81920 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 15:35:13 -0500 Subject: [PATCH 030/118] fix share links in menu --- app/(home-pages)/home/LeafletList/LeafletInfo.tsx | 2 +- .../home/LeafletList/LeafletOptions.tsx | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx index 478f853c..f974b758 100644 --- a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx @@ -46,7 +46,7 @@ export const LeafletInfo = (props: { leaflet={props.token} draftInPublication={props.draftInPublication} document_uri={props.document_uri} - shareLink={`/${props.token.id}`} + shareLink={`${props.token.id}`} archived={props.archived} loggedIn={props.loggedIn} /> diff --git a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx index 6b810d58..891f49f0 100644 --- a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx @@ -40,9 +40,7 @@ export const LeafletOptions = (props: { archived?: boolean | null; loggedIn?: boolean; }) => { - let [state, setState] = useState<"normal" | "areYouSure">( - "normal", - ); + let [state, setState] = useState<"normal" | "areYouSure">("normal"); let [open, setOpen] = useState(false); let { identity } = useIdentityData(); let isPublicationOwner = @@ -82,10 +80,7 @@ export const LeafletOptions = (props: { {...props} /> ) : ( - + ) ) : state === "areYouSure" ? (

@@ -382,4 +377,3 @@ const DeleteAreYouSureForm = (props: {
); }; - -- 2.51.2 From e9e82366d7a58c00b71d6ba44ae410853ff04e58 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 15:35:20 -0500 Subject: [PATCH 031/118] next 16 types --- next-env.d.ts | 2 +- tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/next-env.d.ts b/next-env.d.ts index 830fb594..c4b7818f 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -/// +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/tsconfig.json b/tsconfig.json index ba4b959c..43324c37 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,7 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", + "jsx": "react-jsx", "plugins": [ { "name": "next" -- 2.51.2 From 7ab65db1d209d0f4b01fb80a2f6b87fa2774e4b6 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 17:07:39 -0500 Subject: [PATCH 032/118] add link prop --- app/(home-pages)/home/LeafletList/LeafletOptions.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx index 891f49f0..3df1f504 100644 --- a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx @@ -275,6 +275,7 @@ const PublishedPostOptions = (props: { } smokerText="Link copied!" id="get-link" + link="" fullLink={props.shareLink} /> -- 2.51.2 From 16ad54871c10ae09cd96b233a88b39eb937c22e3 Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Tue, 25 Nov 2025 18:03:18 -0500 Subject: [PATCH 033/118] Feature/publish leaflets (#235) * reorganized Actions in leaflet a bit * started up on the publish button, WIP * added an icon for one-offs/looseleafs/whatever * adjusted popover to new one step design * wrap up styling tweaks to the publish popover * title input in publish post details form now pulls first block content as title * add a looseleaf button to the homepage * icon stuffffff * make save as draft and publish work to existing pub * make publication optional on documents * support publishing standalone leaflets * support adding theme to standalone published docs * render standalone published docs at /p/ * render standalone published docs properly on homepage * handle publishing doc theme * delete entiteis before publishing * tweak publish page styles * add published link for standaloen docs in share menu * style tweaks to make starting a new pub an external link rather than a redirect * tiny lil teaks to create pub form * fix type errors * added the looseleaf page * handle canvases better * some small tweaks * handle publishing canvas pages as first page * simplify page handling and support root canvas page * add basic looseleaf page * don't show looseleafs tab if none * add first page to start of array * fix metadata on read links * get theme from correct place and fix pub metadata * remove flex on published page link block content * fix imports and types * fix looseleaf titles --------- Co-authored-by: celine --- actions/createPublicationDraft.ts | 6 + actions/getIdentityData.ts | 1 + .../publications/moveLeafletToPublication.ts | 33 ++ .../updateLeafletDraftMetadata.ts | 26 -- actions/publishToPublication.ts | 253 ++++++++--- app/(home-pages)/discover/PubListing.tsx | 2 +- app/(home-pages)/home/Actions/Actions.tsx | 3 +- app/(home-pages)/home/HomeLayout.tsx | 23 +- .../home/LeafletList/LeafletInfo.tsx | 5 +- .../home/LeafletList/LeafletOptions.tsx | 2 +- app/(home-pages)/home/page.tsx | 3 +- .../looseleafs/LooseleafsLayout.tsx | 116 +++++ app/(home-pages)/looseleafs/page.tsx | 47 ++ app/(home-pages)/reader/ReaderContent.tsx | 2 +- app/[leaflet_id]/Actions.tsx | 98 ---- app/[leaflet_id]/Footer.tsx | 36 +- app/[leaflet_id]/Sidebar.tsx | 40 +- app/[leaflet_id]/actions/BackToPubButton.tsx | 27 ++ .../[leaflet_id]/actions/HelpButton.tsx | 12 +- .../[leaflet_id]/actions}/HomeButton.tsx | 37 +- app/[leaflet_id]/actions/PublishButton.tsx | 427 ++++++++++++++++++ .../actions}/ShareOptions/DomainOptions.tsx | 4 +- .../actions}/ShareOptions/getShareLink.ts | 0 .../actions}/ShareOptions/index.tsx | 17 +- app/[leaflet_id]/page.tsx | 7 +- app/[leaflet_id]/publish/PublishPost.tsx | 84 +++- app/[leaflet_id]/publish/page.tsx | 72 ++- app/api/rpc/[command]/get_leaflet_data.ts | 6 +- app/globals.css | 1 + .../[did]/[publication]/[rkey]/CanvasPage.tsx | 45 +- .../[rkey]/DocumentPageRenderer.tsx | 145 ++++++ .../[rkey]/LinearDocumentPage.tsx | 82 ++-- .../[rkey]/PostHeader/PostHeader.tsx | 35 +- .../[did]/[publication]/[rkey]/PostPages.tsx | 176 ++++---- .../[rkey]/PublishedPageBlock.tsx | 9 +- .../[publication]/[rkey]/extractCodeBlocks.ts | 5 +- .../[publication]/[rkey]/getPostPageData.ts | 9 +- app/lish/[did]/[publication]/[rkey]/page.tsx | 162 +------ .../dashboard/PublishedPostsLists.tsx | 2 +- app/lish/[did]/[publication]/page.tsx | 4 +- app/lish/createPub/CreatePubForm.tsx | 13 +- app/lish/createPub/UpdatePubForm.tsx | 6 +- app/lish/createPub/page.tsx | 2 +- app/login/LoginForm.tsx | 2 +- .../[rkey]/l-quote/[quote]/opengraph-image.ts | 19 + .../[rkey]/l-quote/[quote]/page.tsx | 8 + app/p/[didOrHandle]/[rkey]/page.tsx | 90 ++++ appview/index.ts | 37 +- components/ActionBar/Navigation.tsx | 17 +- components/ActionBar/Publications.tsx | 72 ++- components/Blocks/RSVPBlock/SendUpdate.tsx | 4 +- components/Buttons.tsx | 56 ++- components/Icons/LooseleafSmall.tsx | 19 + components/Input.tsx | 12 +- components/Layout.tsx | 1 + components/PageSWRDataProvider.tsx | 12 +- components/Pages/Page.tsx | 2 +- components/Pages/PageShareMenu.tsx | 7 +- components/Pages/PublicationMetadata.tsx | 32 +- components/ThemeManager/PubThemeSetter.tsx | 45 +- .../ThemeManager/PublicationThemeProvider.tsx | 49 +- components/ThemeManager/ThemeProvider.tsx | 6 +- components/ThemeManager/ThemeSetter.tsx | 4 +- components/ThemeManager/colorToLexicons.ts | 44 ++ lexicons/api/lexicons.ts | 6 +- lexicons/api/types/pub/leaflet/document.ts | 4 +- lexicons/pub/leaflet/document.json | 7 +- lexicons/src/document.ts | 3 +- .../getPublicationMetadataFromLeafletData.ts | 50 ++ 69 files changed, 1870 insertions(+), 823 deletions(-) create mode 100644 actions/publications/moveLeafletToPublication.ts delete mode 100644 actions/publications/updateLeafletDraftMetadata.ts create mode 100644 app/(home-pages)/looseleafs/LooseleafsLayout.tsx create mode 100644 app/(home-pages)/looseleafs/page.tsx delete mode 100644 app/[leaflet_id]/Actions.tsx create mode 100644 app/[leaflet_id]/actions/BackToPubButton.tsx rename components/HelpPopover.tsx => app/[leaflet_id]/actions/HelpButton.tsx (94%) rename {components => app/[leaflet_id]/actions}/HomeButton.tsx (63%) create mode 100644 app/[leaflet_id]/actions/PublishButton.tsx rename {components => app/[leaflet_id]/actions}/ShareOptions/DomainOptions.tsx (99%) rename {components => app/[leaflet_id]/actions}/ShareOptions/getShareLink.ts (100%) rename {components => app/[leaflet_id]/actions}/ShareOptions/index.tsx (95%) create mode 100644 app/lish/[did]/[publication]/[rkey]/DocumentPageRenderer.tsx create mode 100644 app/p/[didOrHandle]/[rkey]/l-quote/[quote]/opengraph-image.ts create mode 100644 app/p/[didOrHandle]/[rkey]/l-quote/[quote]/page.tsx create mode 100644 app/p/[didOrHandle]/[rkey]/page.tsx create mode 100644 components/Icons/LooseleafSmall.tsx create mode 100644 components/ThemeManager/colorToLexicons.ts create mode 100644 src/utils/getPublicationMetadataFromLeafletData.ts diff --git a/actions/createPublicationDraft.ts b/actions/createPublicationDraft.ts index 12d67938..164a91cb 100644 --- a/actions/createPublicationDraft.ts +++ b/actions/createPublicationDraft.ts @@ -11,6 +11,12 @@ export async function createPublicationDraft(publication_uri: string) { redirectUser: false, firstBlockType: "text", }); + let { data: publication } = await supabaseServerClient + .from("publications") + .select("*") + .eq("uri", publication_uri) + .single(); + if (publication?.identity_did !== identity.atp_did) return; await supabaseServerClient .from("leaflets_in_publications") diff --git a/actions/getIdentityData.ts b/actions/getIdentityData.ts index 076bc760..b2d16130 100644 --- a/actions/getIdentityData.ts +++ b/actions/getIdentityData.ts @@ -30,6 +30,7 @@ export async function uncachedGetIdentityData() { id, root_entity, permission_token_rights(*), + leaflets_to_documents(*, documents(*)), leaflets_in_publications(*, publications(*), documents(*)) ) ) diff --git a/actions/publications/moveLeafletToPublication.ts b/actions/publications/moveLeafletToPublication.ts new file mode 100644 index 00000000..a3ee8c62 --- /dev/null +++ b/actions/publications/moveLeafletToPublication.ts @@ -0,0 +1,33 @@ +"use server"; + +import { getIdentityData } from "actions/getIdentityData"; +import { supabaseServerClient } from "supabase/serverClient"; + +export async function moveLeafletToPublication( + leaflet_id: string, + publication_uri: string, + metadata: { title: string; description: string }, + entitiesToDelete: string[], +) { + let identity = await getIdentityData(); + if (!identity || !identity.atp_did) return null; + let { data: publication } = await supabaseServerClient + .from("publications") + .select("*") + .eq("uri", publication_uri) + .single(); + if (publication?.identity_did !== identity.atp_did) return; + + await supabaseServerClient.from("leaflets_in_publications").insert({ + publication: publication_uri, + leaflet: leaflet_id, + doc: null, + title: metadata.title, + description: metadata.description, + }); + + await supabaseServerClient + .from("entities") + .delete() + .in("id", entitiesToDelete); +} diff --git a/actions/publications/updateLeafletDraftMetadata.ts b/actions/publications/updateLeafletDraftMetadata.ts deleted file mode 100644 index c15fb1eb..00000000 --- a/actions/publications/updateLeafletDraftMetadata.ts +++ /dev/null @@ -1,26 +0,0 @@ -"use server"; - -import { getIdentityData } from "actions/getIdentityData"; -import { supabaseServerClient } from "supabase/serverClient"; - -export async function updateLeafletDraftMetadata( - leafletID: string, - publication_uri: string, - title: string, - description: string, -) { - let identity = await getIdentityData(); - if (!identity?.atp_did) return null; - let { data: publication } = await supabaseServerClient - .from("publications") - .select() - .eq("uri", publication_uri) - .single(); - if (!publication || publication.identity_did !== identity.atp_did) - return null; - await supabaseServerClient - .from("leaflets_in_publications") - .update({ title, description }) - .eq("leaflet", leafletID) - .eq("publication", publication_uri); -} diff --git a/actions/publishToPublication.ts b/actions/publishToPublication.ts index eb62eb97..946ed6ab 100644 --- a/actions/publishToPublication.ts +++ b/actions/publishToPublication.ts @@ -44,6 +44,12 @@ import { $Typed, UnicodeString } from "@atproto/api"; import { List, parseBlocksToList } from "src/utils/parseBlocksToList"; import { getBlocksWithTypeLocal } from "src/hooks/queries/useBlocks"; import { Lock } from "src/utils/lock"; +import type { PubLeafletPublication } from "lexicons/api"; +import { + ColorToRGB, + ColorToRGBA, +} from "components/ThemeManager/colorToLexicons"; +import { parseColor } from "@react-stately/color"; export async function publishToPublication({ root_entity, @@ -51,12 +57,14 @@ export async function publishToPublication({ leaflet_id, title, description, + entitiesToDelete, }: { root_entity: string; - publication_uri: string; + publication_uri?: string; leaflet_id: string; title?: string; description?: string; + entitiesToDelete?: string[]; }) { const oauthClient = await createOauthClient(); let identity = await getIdentityData(); @@ -66,20 +74,49 @@ export async function publishToPublication({ let agent = new AtpBaseClient( credentialSession.fetchHandler.bind(credentialSession), ); - let { data: draft } = await supabaseServerClient - .from("leaflets_in_publications") - .select("*, publications(*), documents(*)") - .eq("publication", publication_uri) - .eq("leaflet", leaflet_id) - .single(); - if (!draft || identity.atp_did !== draft?.publications?.identity_did) - throw new Error("No draft or not publisher"); + + // Check if we're publishing to a publication or standalone + let draft: any = null; + let existingDocUri: string | null = null; + + if (publication_uri) { + // Publishing to a publication - use leaflets_in_publications + let { data } = await supabaseServerClient + .from("leaflets_in_publications") + .select("*, publications(*), documents(*)") + .eq("publication", publication_uri) + .eq("leaflet", leaflet_id) + .single(); + if (!data || identity.atp_did !== data?.publications?.identity_did) + throw new Error("No draft or not publisher"); + draft = data; + existingDocUri = draft?.doc; + } else { + // Publishing standalone - use leaflets_to_documents + let { data } = await supabaseServerClient + .from("leaflets_to_documents") + .select("*, documents(*)") + .eq("leaflet", leaflet_id) + .single(); + draft = data; + existingDocUri = draft?.document; + } + + // Heuristic: Remove title entities if this is the first time publishing + // (when coming from a standalone leaflet with entitiesToDelete passed in) + if (entitiesToDelete && entitiesToDelete.length > 0 && !existingDocUri) { + await supabaseServerClient + .from("entities") + .delete() + .in("id", entitiesToDelete); + } + let { data } = await supabaseServerClient.rpc("get_facts", { root: root_entity, }); let facts = (data as unknown as Fact[]) || []; - let { firstPageBlocks, pages } = await processBlocksToPages( + let { pages } = await processBlocksToPages( facts, agent, root_entity, @@ -88,37 +125,41 @@ export async function publishToPublication({ let existingRecord = (draft?.documents?.data as PubLeafletDocument.Record | undefined) || {}; + + // Extract theme for standalone documents (not for publications) + let theme: PubLeafletPublication.Theme | undefined; + if (!publication_uri) { + theme = await extractThemeFromFacts(facts, root_entity, agent); + } + let record: PubLeafletDocument.Record = { - $type: "pub.leaflet.document", - author: credentialSession.did!, - publication: publication_uri, publishedAt: new Date().toISOString(), ...existingRecord, + $type: "pub.leaflet.document", + author: credentialSession.did!, + ...(publication_uri && { publication: publication_uri }), + ...(theme && { theme }), title: title || "Untitled", description: description || "", - pages: [ - { - $type: "pub.leaflet.pages.linearDocument", - blocks: firstPageBlocks, - }, - ...pages.map((p) => { - if (p.type === "canvas") { - return { - $type: "pub.leaflet.pages.canvas" as const, - id: p.id, - blocks: p.blocks as PubLeafletPagesCanvas.Block[], - }; - } else { - return { - $type: "pub.leaflet.pages.linearDocument" as const, - id: p.id, - blocks: p.blocks as PubLeafletPagesLinearDocument.Block[], - }; - } - }), - ], + pages: pages.map((p) => { + if (p.type === "canvas") { + return { + $type: "pub.leaflet.pages.canvas" as const, + id: p.id, + blocks: p.blocks as PubLeafletPagesCanvas.Block[], + }; + } else { + return { + $type: "pub.leaflet.pages.linearDocument" as const, + id: p.id, + blocks: p.blocks as PubLeafletPagesLinearDocument.Block[], + }; + } + }), }; - let rkey = draft?.doc ? new AtUri(draft.doc).rkey : TID.nextStr(); + + // Keep the same rkey if updating an existing document + let rkey = existingDocUri ? new AtUri(existingDocUri).rkey : TID.nextStr(); let { data: result } = await agent.com.atproto.repo.putRecord({ rkey, repo: credentialSession.did!, @@ -127,24 +168,45 @@ export async function publishToPublication({ validate: false, //TODO publish the lexicon so we can validate! }); + // Optimistically create database entries await supabaseServerClient.from("documents").upsert({ uri: result.uri, data: record as Json, }); - await Promise.all([ - //Optimistically put these in! - supabaseServerClient.from("documents_in_publications").upsert({ - publication: record.publication, + + if (publication_uri) { + // Publishing to a publication - update both tables + await Promise.all([ + supabaseServerClient.from("documents_in_publications").upsert({ + publication: publication_uri, + document: result.uri, + }), + supabaseServerClient + .from("leaflets_in_publications") + .update({ + doc: result.uri, + }) + .eq("leaflet", leaflet_id) + .eq("publication", publication_uri), + ]); + } else { + // Publishing standalone - update leaflets_to_documents + await supabaseServerClient.from("leaflets_to_documents").upsert({ + leaflet: leaflet_id, document: result.uri, - }), - supabaseServerClient - .from("leaflets_in_publications") - .update({ - doc: result.uri, - }) - .eq("leaflet", leaflet_id) - .eq("publication", publication_uri), - ]); + title: title || "Untitled", + description: description || "", + }); + + // Heuristic: Remove title entities if this is the first time publishing standalone + // (when entitiesToDelete is provided and there's no existing document) + if (entitiesToDelete && entitiesToDelete.length > 0 && !existingDocUri) { + await supabaseServerClient + .from("entities") + .delete() + .in("id", entitiesToDelete); + } + } return { rkey, record: JSON.parse(JSON.stringify(record)) }; } @@ -169,9 +231,30 @@ async function processBlocksToPages( let firstEntity = scan.eav(root_entity, "root/page")?.[0]; if (!firstEntity) throw new Error("No root page"); - let blocks = getBlocksWithTypeLocal(facts, firstEntity?.data.value); - let b = await blocksToRecord(blocks, did); - return { firstPageBlocks: b, pages }; + + // Check if the first page is a canvas or linear document + let [pageType] = scan.eav(firstEntity.data.value, "page/type"); + + if (pageType?.data.value === "canvas") { + // First page is a canvas + let canvasBlocks = await canvasBlocksToRecord(firstEntity.data.value, did); + pages.unshift({ + id: firstEntity.data.value, + blocks: canvasBlocks, + type: "canvas", + }); + } else { + // First page is a linear document + let blocks = getBlocksWithTypeLocal(facts, firstEntity?.data.value); + let b = await blocksToRecord(blocks, did); + pages.unshift({ + id: firstEntity.data.value, + blocks: b, + type: "doc", + }); + } + + return { pages }; async function uploadImage(src: string) { let data = await fetch(src); @@ -572,3 +655,71 @@ type ExcludeString = T extends string ? never : T /* maybe literal, not the whole `string` */ : T; /* not a string */ + +async function extractThemeFromFacts( + facts: Fact[], + root_entity: string, + agent: AtpBaseClient, +): Promise { + let scan = scanIndexLocal(facts); + let pageBackground = scan.eav(root_entity, "theme/page-background")?.[0]?.data + .value; + let cardBackground = scan.eav(root_entity, "theme/card-background")?.[0]?.data + .value; + let primary = scan.eav(root_entity, "theme/primary")?.[0]?.data.value; + let accentBackground = scan.eav(root_entity, "theme/accent-background")?.[0] + ?.data.value; + let accentText = scan.eav(root_entity, "theme/accent-text")?.[0]?.data.value; + let showPageBackground = !scan.eav( + root_entity, + "theme/card-border-hidden", + )?.[0]?.data.value; + let backgroundImage = scan.eav(root_entity, "theme/background-image")?.[0]; + let backgroundImageRepeat = scan.eav( + root_entity, + "theme/background-image-repeat", + )?.[0]; + + let theme: PubLeafletPublication.Theme = { + showPageBackground: showPageBackground ?? true, + }; + + if (pageBackground) + theme.backgroundColor = ColorToRGBA(parseColor(`hsba(${pageBackground})`)); + if (cardBackground) + theme.pageBackground = ColorToRGBA(parseColor(`hsba(${cardBackground})`)); + if (primary) theme.primary = ColorToRGB(parseColor(`hsba(${primary})`)); + if (accentBackground) + theme.accentBackground = ColorToRGB( + parseColor(`hsba(${accentBackground})`), + ); + if (accentText) + theme.accentText = ColorToRGB(parseColor(`hsba(${accentText})`)); + + // Upload background image if present + if (backgroundImage?.data) { + let imageData = await fetch(backgroundImage.data.src); + if (imageData.status === 200) { + let binary = await imageData.blob(); + let blob = await agent.com.atproto.repo.uploadBlob(binary, { + headers: { "Content-Type": binary.type }, + }); + + theme.backgroundImage = { + $type: "pub.leaflet.theme.backgroundImage", + image: blob.data.blob, + repeat: backgroundImageRepeat?.data.value ? true : false, + ...(backgroundImageRepeat?.data.value && { + width: backgroundImageRepeat.data.value, + }), + }; + } + } + + // Only return theme if at least one property is set + if (Object.keys(theme).length > 1 || theme.showPageBackground !== true) { + return theme; + } + + return undefined; +} diff --git a/app/(home-pages)/discover/PubListing.tsx b/app/(home-pages)/discover/PubListing.tsx index fae42889..285a36cd 100644 --- a/app/(home-pages)/discover/PubListing.tsx +++ b/app/(home-pages)/discover/PubListing.tsx @@ -16,7 +16,7 @@ export const PubListing = ( }, ) => { let record = props.record as PubLeafletPublication.Record; - let theme = usePubTheme(record); + let theme = usePubTheme(record.theme); let backgroundImage = record?.theme?.backgroundImage?.image?.ref ? blobRefToSrc( record?.theme?.backgroundImage?.image?.ref, diff --git a/app/(home-pages)/home/Actions/Actions.tsx b/app/(home-pages)/home/Actions/Actions.tsx index 5f99d3f6..20852f4d 100644 --- a/app/(home-pages)/home/Actions/Actions.tsx +++ b/app/(home-pages)/home/Actions/Actions.tsx @@ -1,7 +1,7 @@ "use client"; import { ThemePopover } from "components/ThemeManager/ThemeSetter"; import { CreateNewLeafletButton } from "./CreateNewButton"; -import { HelpPopover } from "components/HelpPopover"; +import { HelpButton } from "app/[leaflet_id]/actions/HelpButton"; import { AccountSettings } from "./AccountSettings"; import { useIdentityData } from "components/IdentityProvider"; import { useReplicache } from "src/replicache"; @@ -18,7 +18,6 @@ export const Actions = () => { ) : ( )} - ); }; diff --git a/app/(home-pages)/home/HomeLayout.tsx b/app/(home-pages)/home/HomeLayout.tsx index f1f84e4f..4ab12a44 100644 --- a/app/(home-pages)/home/HomeLayout.tsx +++ b/app/(home-pages)/home/HomeLayout.tsx @@ -30,7 +30,7 @@ import { PublicationBanner, } from "./HomeEmpty/HomeEmpty"; -type Leaflet = { +export type Leaflet = { added_at: string; archived?: boolean | null; token: PermissionToken & { @@ -38,6 +38,10 @@ type Leaflet = { GetLeafletDataReturnType["result"]["data"], null >["leaflets_in_publications"]; + leaflets_to_documents?: Exclude< + GetLeafletDataReturnType["result"]["data"], + null + >["leaflets_to_documents"]; }; }; @@ -130,7 +134,8 @@ export function HomeLeafletList(props: { ...identity.permission_token_on_homepage.reduce( (acc, tok) => { let title = - tok.permission_tokens.leaflets_in_publications[0]?.title; + tok.permission_tokens.leaflets_in_publications[0]?.title || + tok.permission_tokens.leaflets_to_documents[0]?.title; if (title) acc[tok.permission_tokens.root_entity] = title; return acc; }, @@ -222,6 +227,7 @@ export function LeafletList(props: { value={{ ...leaflet, leaflets_in_publications: leaflet.leaflets_in_publications || [], + leaflets_to_documents: leaflet.leaflets_to_documents || [], blocked_by_admin: null, custom_domain_routes: [], }} @@ -233,10 +239,15 @@ export function LeafletList(props: { draftInPublication={ leaflet.leaflets_in_publications?.[0]?.publication } - published={!!leaflet.leaflets_in_publications?.find((l) => l.doc)} + published={ + !!leaflet.leaflets_in_publications?.find((l) => l.doc) || + !!leaflet.leaflets_to_documents?.find((l) => !!l.documents) + } publishedAt={ leaflet.leaflets_in_publications?.find((l) => l.doc)?.documents - ?.indexed_at + ?.indexed_at || + leaflet.leaflets_to_documents?.find((l) => !!l.documents) + ?.documents?.indexed_at } document_uri={ leaflet.leaflets_in_publications?.find((l) => l.doc)?.documents @@ -292,7 +303,9 @@ function useSearchedLeaflets( let filteredLeaflets = sortedLeaflets.filter( ({ token: leaflet, archived: archived }) => { - let published = !!leaflet.leaflets_in_publications?.find((l) => l.doc); + let published = + !!leaflet.leaflets_in_publications?.find((l) => l.doc) || + !!leaflet.leaflets_to_documents?.find((l) => l.document); let drafts = !!leaflet.leaflets_in_publications?.length && !published; let docs = !leaflet.leaflets_in_publications?.length && !archived; // If no filters are active, show all diff --git a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx index f974b758..20004a7c 100644 --- a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx @@ -1,11 +1,8 @@ "use client"; import { PermissionToken, useEntity } from "src/replicache"; import { LeafletOptions } from "./LeafletOptions"; -import Link from "next/link"; -import { use, useState } from "react"; +import { useState } from "react"; import { timeAgo } from "src/utils/timeAgo"; -import { usePublishLink } from "components/ShareOptions"; -import { Separator } from "components/Layout"; import { usePageTitle } from "components/utils/UpdateLeafletTitle"; export const LeafletInfo = (props: { diff --git a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx index 3df1f504..0e9b3db5 100644 --- a/app/(home-pages)/home/LeafletList/LeafletOptions.tsx +++ b/app/(home-pages)/home/LeafletList/LeafletOptions.tsx @@ -17,7 +17,6 @@ import { deletePost, unpublishPost, } from "app/lish/[did]/[publication]/dashboard/deletePost"; -import { ShareButton } from "components/ShareOptions"; import { ShareSmall } from "components/Icons/ShareSmall"; import { HideSmall } from "components/Icons/HideSmall"; import { hideDoc } from "../storage"; @@ -31,6 +30,7 @@ import { usePublicationData, mutatePublicationData, } from "app/lish/[did]/[publication]/dashboard/PublicationSWRProvider"; +import { ShareButton } from "app/[leaflet_id]/actions/ShareOptions"; export const LeafletOptions = (props: { leaflet: PermissionToken; diff --git a/app/(home-pages)/home/page.tsx b/app/(home-pages)/home/page.tsx index 32c8fd95..5408ab37 100644 --- a/app/(home-pages)/home/page.tsx +++ b/app/(home-pages)/home/page.tsx @@ -29,7 +29,8 @@ export default async function Home() { ...auth_res?.permission_token_on_homepage.reduce( (acc, tok) => { let title = - tok.permission_tokens.leaflets_in_publications[0]?.title; + tok.permission_tokens.leaflets_in_publications[0]?.title || + tok.permission_tokens.leaflets_to_documents[0]?.title; if (title) acc[tok.permission_tokens.root_entity] = title; return acc; }, diff --git a/app/(home-pages)/looseleafs/LooseleafsLayout.tsx b/app/(home-pages)/looseleafs/LooseleafsLayout.tsx new file mode 100644 index 00000000..d40d28d4 --- /dev/null +++ b/app/(home-pages)/looseleafs/LooseleafsLayout.tsx @@ -0,0 +1,116 @@ +"use client"; +import { DashboardLayout } from "components/PageLayouts/DashboardLayout"; +import { useCardBorderHidden } from "components/Pages/useCardBorderHidden"; +import { useState } from "react"; +import { useDebouncedEffect } from "src/hooks/useDebouncedEffect"; +import { Fact, PermissionToken } from "src/replicache"; +import { Attribute } from "src/replicache/attributes"; +import { Actions } from "../home/Actions/Actions"; +import { callRPC } from "app/api/rpc/client"; +import { useIdentityData } from "components/IdentityProvider"; +import useSWR from "swr"; +import { getHomeDocs } from "../home/storage"; +import { Leaflet, LeafletList } from "../home/HomeLayout"; + +export const LooseleafsLayout = (props: { + entityID: string | null; + titles: { [root_entity: string]: string }; + initialFacts: { + [root_entity: string]: Fact[]; + }; +}) => { + let [searchValue, setSearchValue] = useState(""); + let [debouncedSearchValue, setDebouncedSearchValue] = useState(""); + + useDebouncedEffect( + () => { + setDebouncedSearchValue(searchValue); + }, + 200, + [searchValue], + ); + + let cardBorderHidden = !!useCardBorderHidden(props.entityID); + return ( + } + tabs={{ + home: { + controls: null, + content: ( + + ), + }, + }} + /> + ); +}; + +export const LooseleafList = (props: { + titles: { [root_entity: string]: string }; + initialFacts: { + [root_entity: string]: Fact[]; + }; + searchValue: string; + cardBorderHidden: boolean; +}) => { + let { identity } = useIdentityData(); + let { data: initialFacts } = useSWR( + "home-leaflet-data", + async () => { + if (identity) { + let { result } = await callRPC("getFactsFromHomeLeaflets", { + tokens: identity.permission_token_on_homepage.map( + (ptrh) => ptrh.permission_tokens.root_entity, + ), + }); + let titles = { + ...result.titles, + ...identity.permission_token_on_homepage.reduce( + (acc, tok) => { + let title = + tok.permission_tokens.leaflets_in_publications[0]?.title || + tok.permission_tokens.leaflets_to_documents[0]?.title; + if (title) acc[tok.permission_tokens.root_entity] = title; + return acc; + }, + {} as { [k: string]: string }, + ), + }; + return { ...result, titles }; + } + }, + { fallbackData: { facts: props.initialFacts, titles: props.titles } }, + ); + + let leaflets: Leaflet[] = identity + ? identity.permission_token_on_homepage + .filter( + (ptoh) => ptoh.permission_tokens.leaflets_to_documents.length > 0, + ) + .map((ptoh) => ({ + added_at: ptoh.created_at, + token: ptoh.permission_tokens as PermissionToken, + })) + : []; + return ( + + ); +}; diff --git a/app/(home-pages)/looseleafs/page.tsx b/app/(home-pages)/looseleafs/page.tsx new file mode 100644 index 00000000..9ae9f7b3 --- /dev/null +++ b/app/(home-pages)/looseleafs/page.tsx @@ -0,0 +1,47 @@ +import { getIdentityData } from "actions/getIdentityData"; +import { DashboardLayout } from "components/PageLayouts/DashboardLayout"; +import { Actions } from "../home/Actions/Actions"; +import { Fact } from "src/replicache"; +import { Attribute } from "src/replicache/attributes"; +import { getFactsFromHomeLeaflets } from "app/api/rpc/[command]/getFactsFromHomeLeaflets"; +import { supabaseServerClient } from "supabase/serverClient"; +import { LooseleafsLayout } from "./LooseleafsLayout"; + +export default async function Home() { + let auth_res = await getIdentityData(); + + let [allLeafletFacts] = await Promise.all([ + auth_res + ? getFactsFromHomeLeaflets.handler( + { + tokens: auth_res.permission_token_on_homepage.map( + (r) => r.permission_tokens.root_entity, + ), + }, + { supabase: supabaseServerClient }, + ) + : undefined, + ]); + + let home_docs_initialFacts = allLeafletFacts?.result || {}; + + return ( + { + let title = + tok.permission_tokens.leaflets_in_publications[0]?.title || + tok.permission_tokens.leaflets_to_documents[0]?.title; + if (title) acc[tok.permission_tokens.root_entity] = title; + return acc; + }, + {} as { [k: string]: string }, + ), + }} + initialFacts={home_docs_initialFacts.facts || {}} + /> + ); +} diff --git a/app/(home-pages)/reader/ReaderContent.tsx b/app/(home-pages)/reader/ReaderContent.tsx index 11e49566..53b6edb5 100644 --- a/app/(home-pages)/reader/ReaderContent.tsx +++ b/app/(home-pages)/reader/ReaderContent.tsx @@ -102,7 +102,7 @@ const Post = (props: Post) => { let postRecord = props.documents.data as PubLeafletDocument.Record; let postUri = new AtUri(props.documents.uri); - let theme = usePubTheme(pubRecord); + let theme = usePubTheme(pubRecord?.theme); let backgroundImage = pubRecord?.theme?.backgroundImage?.image?.ref ? blobRefToSrc( pubRecord?.theme?.backgroundImage?.image?.ref, diff --git a/app/[leaflet_id]/Actions.tsx b/app/[leaflet_id]/Actions.tsx deleted file mode 100644 index ebb6c89f..00000000 --- a/app/[leaflet_id]/Actions.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { publishToPublication } from "actions/publishToPublication"; -import { - getBasePublicationURL, - getPublicationURL, -} from "app/lish/createPub/getPublicationURL"; -import { ActionButton } from "components/ActionBar/ActionButton"; -import { GoBackSmall } from "components/Icons/GoBackSmall"; -import { PublishSmall } from "components/Icons/PublishSmall"; -import { useLeafletPublicationData } from "components/PageSWRDataProvider"; -import { SpeedyLink } from "components/SpeedyLink"; -import { useToaster } from "components/Toast"; -import { DotLoader } from "components/utils/DotLoader"; -import { useParams, useRouter } from "next/navigation"; -import { useState } from "react"; -import { useReplicache } from "src/replicache"; -import { Json } from "supabase/database.types"; - -export const BackToPubButton = (props: { - publication: { - identity_did: string; - indexed_at: string; - name: string; - record: Json; - uri: string; - }; -}) => { - return ( - - } - label="To Pub" - /> - - ); -}; - -export const PublishButton = () => { - let { data: pub } = useLeafletPublicationData(); - let params = useParams(); - let router = useRouter(); - if (!pub?.doc) - return ( - } - label={"Publish!"} - onClick={() => { - router.push(`/${params.leaflet_id}/publish`); - }} - /> - ); - - return ; -}; - -const UpdateButton = () => { - let [isLoading, setIsLoading] = useState(false); - let { data: pub, mutate } = useLeafletPublicationData(); - let { permission_token, rootEntity } = useReplicache(); - let toaster = useToaster(); - - return ( - } - label={isLoading ? : "Update!"} - onClick={async () => { - if (!pub || !pub.publications) return; - setIsLoading(true); - let doc = await publishToPublication({ - root_entity: rootEntity, - publication_uri: pub.publications.uri, - leaflet_id: permission_token.id, - title: pub.title, - description: pub.description, - }); - setIsLoading(false); - mutate(); - toaster({ - content: ( -
- {pub.doc ? "Updated! " : "Published! "} - - link - -
- ), - type: "success", - }); - }} - /> - ); -}; diff --git a/app/[leaflet_id]/Footer.tsx b/app/[leaflet_id]/Footer.tsx index d6eb1ff3..94a5a9a3 100644 --- a/app/[leaflet_id]/Footer.tsx +++ b/app/[leaflet_id]/Footer.tsx @@ -4,12 +4,13 @@ import { Footer as ActionFooter } from "components/ActionBar/Footer"; import { Media } from "components/Media"; import { ThemePopover } from "components/ThemeManager/ThemeSetter"; import { Toolbar } from "components/Toolbar"; -import { ShareOptions } from "components/ShareOptions"; -import { HomeButton } from "components/HomeButton"; +import { ShareOptions } from "app/[leaflet_id]/actions/ShareOptions"; +import { HomeButton } from "app/[leaflet_id]/actions/HomeButton"; +import { PublishButton } from "./actions/PublishButton"; import { useEntitySetContext } from "components/EntitySetProvider"; -import { HelpPopover } from "components/HelpPopover"; +import { HelpButton } from "app/[leaflet_id]/actions/HelpButton"; import { Watermark } from "components/Watermark"; -import { BackToPubButton, PublishButton } from "./Actions"; +import { BackToPubButton } from "./actions/BackToPubButton"; import { useLeafletPublicationData } from "components/PageSWRDataProvider"; import { useIdentityData } from "components/IdentityProvider"; @@ -36,24 +37,19 @@ export function LeafletFooter(props: { entityID: string }) { />
) : entity_set.permissions.write ? ( - pub?.publications && - identity?.atp_did && - pub.publications.identity_did === identity.atp_did ? ( - + + {pub?.publications && + identity?.atp_did && + pub.publications.identity_did === identity.atp_did ? ( - - - - - - ) : ( - + ) : ( - - - - - ) + )} + + + + + ) : (
diff --git a/app/[leaflet_id]/Sidebar.tsx b/app/[leaflet_id]/Sidebar.tsx index edbdf086..568ed74d 100644 --- a/app/[leaflet_id]/Sidebar.tsx +++ b/app/[leaflet_id]/Sidebar.tsx @@ -1,16 +1,15 @@ "use client"; -import { ActionButton } from "components/ActionBar/ActionButton"; import { Sidebar } from "components/ActionBar/Sidebar"; import { useEntitySetContext } from "components/EntitySetProvider"; -import { HelpPopover } from "components/HelpPopover"; -import { HomeButton } from "components/HomeButton"; +import { HelpButton } from "app/[leaflet_id]/actions/HelpButton"; +import { HomeButton } from "app/[leaflet_id]/actions/HomeButton"; import { Media } from "components/Media"; import { useLeafletPublicationData } from "components/PageSWRDataProvider"; -import { ShareOptions } from "components/ShareOptions"; +import { ShareOptions } from "app/[leaflet_id]/actions/ShareOptions"; import { ThemePopover } from "components/ThemeManager/ThemeSetter"; +import { PublishButton } from "./actions/PublishButton"; import { Watermark } from "components/Watermark"; -import { useUIState } from "src/useUIState"; -import { BackToPubButton, PublishButton } from "./Actions"; +import { BackToPubButton } from "./actions/BackToPubButton"; import { useIdentityData } from "components/IdentityProvider"; import { useReplicache } from "src/replicache"; @@ -29,25 +28,17 @@ export function LeafletSidebar() {
{entity_set.permissions.write && ( + + + + +
{pub?.publications && identity?.atp_did && pub.publications.identity_did === identity.atp_did ? ( - <> - - - - -
- - + ) : ( - <> - - - -
- - + )}
)} @@ -59,10 +50,3 @@ export function LeafletSidebar() { ); } - -const blurPage = () => { - useUIState.setState(() => ({ - focusedEntity: null, - selectedBlocks: [], - })); -}; diff --git a/app/[leaflet_id]/actions/BackToPubButton.tsx b/app/[leaflet_id]/actions/BackToPubButton.tsx new file mode 100644 index 00000000..574eb57b --- /dev/null +++ b/app/[leaflet_id]/actions/BackToPubButton.tsx @@ -0,0 +1,27 @@ +import { getBasePublicationURL } from "app/lish/createPub/getPublicationURL"; +import { ActionButton } from "components/ActionBar/ActionButton"; +import { GoBackSmall } from "components/Icons/GoBackSmall"; +import { SpeedyLink } from "components/SpeedyLink"; +import { Json } from "supabase/database.types"; + +export const BackToPubButton = (props: { + publication: { + identity_did: string; + indexed_at: string; + name: string; + record: Json; + uri: string; + }; +}) => { + return ( + + } + label="To Pub" + /> + + ); +}; diff --git a/components/HelpPopover.tsx b/app/[leaflet_id]/actions/HelpButton.tsx similarity index 94% rename from components/HelpPopover.tsx rename to app/[leaflet_id]/actions/HelpButton.tsx index 84623469..651a4b54 100644 --- a/components/HelpPopover.tsx +++ b/app/[leaflet_id]/actions/HelpButton.tsx @@ -1,16 +1,16 @@ "use client"; -import { ShortcutKey } from "./Layout"; -import { Media } from "./Media"; -import { Popover } from "./Popover"; +import { ShortcutKey } from "../../../components/Layout"; +import { Media } from "../../../components/Media"; +import { Popover } from "../../../components/Popover"; import { metaKey } from "src/utils/metaKey"; -import { useEntitySetContext } from "./EntitySetProvider"; +import { useEntitySetContext } from "../../../components/EntitySetProvider"; import { useState } from "react"; import { ActionButton } from "components/ActionBar/ActionButton"; -import { HelpSmall } from "./Icons/HelpSmall"; +import { HelpSmall } from "../../../components/Icons/HelpSmall"; import { isMac } from "src/utils/isDevice"; import { useIsMobile } from "src/hooks/isMobile"; -export const HelpPopover = (props: { noShortcuts?: boolean }) => { +export const HelpButton = (props: { noShortcuts?: boolean }) => { let entity_set = useEntitySetContext(); let isMobile = useIsMobile(); diff --git a/components/HomeButton.tsx b/app/[leaflet_id]/actions/HomeButton.tsx similarity index 63% rename from components/HomeButton.tsx rename to app/[leaflet_id]/actions/HomeButton.tsx index 43cf2d3e..54d54753 100644 --- a/components/HomeButton.tsx +++ b/app/[leaflet_id]/actions/HomeButton.tsx @@ -1,15 +1,15 @@ "use client"; import Link from "next/link"; -import { useEntitySetContext } from "./EntitySetProvider"; +import { useEntitySetContext } from "../../../components/EntitySetProvider"; import { ActionButton } from "components/ActionBar/ActionButton"; -import { useParams, useSearchParams } from "next/navigation"; -import { useIdentityData } from "./IdentityProvider"; +import { useSearchParams } from "next/navigation"; +import { useIdentityData } from "../../../components/IdentityProvider"; import { useReplicache } from "src/replicache"; import { addLeafletToHome } from "actions/addLeafletToHome"; -import { useSmoker } from "./Toast"; -import { AddToHomeSmall } from "./Icons/AddToHomeSmall"; -import { HomeSmall } from "./Icons/HomeSmall"; -import { permission } from "process"; +import { useSmoker } from "../../../components/Toast"; +import { AddToHomeSmall } from "../../../components/Icons/AddToHomeSmall"; +import { HomeSmall } from "../../../components/Icons/HomeSmall"; +import { produce } from "immer"; export function HomeButton() { let { permissions } = useEntitySetContext(); @@ -47,20 +47,17 @@ const AddToHomeButton = (props: {}) => { await addLeafletToHome(permission_token.id); mutate((identity) => { if (!identity) return; - return { - ...identity, - permission_token_on_homepage: [ - ...identity.permission_token_on_homepage, - { - archived: null, - created_at: new Date().toISOString(), - permission_tokens: { - ...permission_token, - leaflets_in_publications: [], - }, + return produce((draft) => { + draft.permission_token_on_homepage.push({ + created_at: new Date().toISOString(), + archived: null, + permission_tokens: { + ...permission_token, + leaflets_to_documents: [], + leaflets_in_publications: [], }, - ], - }; + }); + })(identity); }); smoker({ position: { diff --git a/app/[leaflet_id]/actions/PublishButton.tsx b/app/[leaflet_id]/actions/PublishButton.tsx new file mode 100644 index 00000000..4098d1ff --- /dev/null +++ b/app/[leaflet_id]/actions/PublishButton.tsx @@ -0,0 +1,427 @@ +"use client"; +import { publishToPublication } from "actions/publishToPublication"; +import { getPublicationURL } from "app/lish/createPub/getPublicationURL"; +import { ActionButton } from "components/ActionBar/ActionButton"; +import { + PubIcon, + PubListEmptyContent, + PubListEmptyIllo, +} from "components/ActionBar/Publications"; +import { ButtonPrimary, ButtonTertiary } from "components/Buttons"; +import { AddSmall } from "components/Icons/AddSmall"; +import { LooseLeafSmall } from "components/Icons/LooseleafSmall"; +import { PublishSmall } from "components/Icons/PublishSmall"; +import { useIdentityData } from "components/IdentityProvider"; +import { InputWithLabel } from "components/Input"; +import { Menu, MenuItem } from "components/Layout"; +import { + useLeafletDomains, + useLeafletPublicationData, +} from "components/PageSWRDataProvider"; +import { Popover } from "components/Popover"; +import { SpeedyLink } from "components/SpeedyLink"; +import { useToaster } from "components/Toast"; +import { DotLoader } from "components/utils/DotLoader"; +import { PubLeafletPublication } from "lexicons/api"; +import { useParams, useRouter, useSearchParams } from "next/navigation"; +import { useState, useMemo } from "react"; +import { useIsMobile } from "src/hooks/isMobile"; +import { useReplicache, useEntity } from "src/replicache"; +import { Json } from "supabase/database.types"; +import { + useBlocks, + useCanvasBlocksWithType, +} from "src/hooks/queries/useBlocks"; +import * as Y from "yjs"; +import * as base64 from "base64-js"; +import { YJSFragmentToString } from "components/Blocks/TextBlock/RenderYJSFragment"; +import { BlueskyLogin } from "app/login/LoginForm"; +import { moveLeafletToPublication } from "actions/publications/moveLeafletToPublication"; +import { AddTiny } from "components/Icons/AddTiny"; + +export const PublishButton = (props: { entityID: string }) => { + let { data: pub } = useLeafletPublicationData(); + let params = useParams(); + let router = useRouter(); + + if (!pub) return ; + if (!pub?.doc) + return ( + } + label={"Publish!"} + onClick={() => { + router.push(`/${params.leaflet_id}/publish`); + }} + /> + ); + + return ; +}; + +const UpdateButton = () => { + let [isLoading, setIsLoading] = useState(false); + let { data: pub, mutate } = useLeafletPublicationData(); + let { permission_token, rootEntity } = useReplicache(); + let { identity } = useIdentityData(); + let toaster = useToaster(); + + return ( + } + label={isLoading ? : "Update!"} + onClick={async () => { + if (!pub) return; + setIsLoading(true); + let doc = await publishToPublication({ + root_entity: rootEntity, + publication_uri: pub.publications?.uri, + leaflet_id: permission_token.id, + title: pub.title, + description: pub.description, + }); + setIsLoading(false); + mutate(); + + // Generate URL based on whether it's in a publication or standalone + let docUrl = pub.publications + ? `${getPublicationURL(pub.publications)}/${doc?.rkey}` + : `https://leaflet.pub/p/${identity?.atp_did}/${doc?.rkey}`; + + toaster({ + content: ( +
+ {pub.doc ? "Updated! " : "Published! "} + link +
+ ), + type: "success", + }); + }} + /> + ); +}; + +const PublishToPublicationButton = (props: { entityID: string }) => { + let { identity } = useIdentityData(); + let { permission_token } = useReplicache(); + let query = useSearchParams(); + console.log(query.get("publish")); + let [open, setOpen] = useState(query.get("publish") !== null); + + let isMobile = useIsMobile(); + identity && identity.atp_did && identity.publications.length > 0; + let [selectedPub, setSelectedPub] = useState(undefined); + let router = useRouter(); + let { title, entitiesToDelete } = useTitle(props.entityID); + let [description, setDescription] = useState(""); + + return ( + setOpen(o)} + side={isMobile ? "top" : "right"} + align={isMobile ? "center" : "start"} + className="sm:max-w-sm w-[1000px]" + trigger={ + } + label={"Publish on ATP"} + /> + } + > + {!identity || !identity.atp_did ? ( +
+
+
+ +
+
Publish on AT Proto
+ { + <> +
+ Link a Bluesky account to start
a publishing on AT + Proto +
+ + + + } +
+
+ ) : ( +
+ +
+
+ +
+
+ +
+ {selectedPub !== "looseleaf" && selectedPub && ( + + )} + { + if (!selectedPub) return; + e.preventDefault(); + if (selectedPub === "create") return; + + // For looseleaf, navigate without publication_uri + if (selectedPub === "looseleaf") { + router.push( + `${permission_token.id}/publish?title=${encodeURIComponent(title)}&description=${encodeURIComponent(description)}&entitiesToDelete=${encodeURIComponent(JSON.stringify(entitiesToDelete))}`, + ); + } else { + router.push( + `${permission_token.id}/publish?publication_uri=${encodeURIComponent(selectedPub)}&title=${encodeURIComponent(title)}&description=${encodeURIComponent(description)}&entitiesToDelete=${encodeURIComponent(JSON.stringify(entitiesToDelete))}`, + ); + } + }} + > + Next{selectedPub === "create" && ": Create Pub!"} + +
+
+ )} +
+ ); +}; + +const SaveAsDraftButton = (props: { + selectedPub: string | undefined; + leafletId: string; + metadata: { title: string; description: string }; + entitiesToDelete: string[]; +}) => { + let { mutate } = useLeafletPublicationData(); + let { rep } = useReplicache(); + let [isLoading, setIsLoading] = useState(false); + + return ( + { + if (!props.selectedPub) return; + if (props.selectedPub === "create") return; + e.preventDefault(); + setIsLoading(true); + await moveLeafletToPublication( + props.leafletId, + props.selectedPub, + props.metadata, + props.entitiesToDelete, + ); + await Promise.all([rep?.pull(), mutate()]); + setIsLoading(false); + }} + > + {isLoading ? : "Save as Draft"} + + ); +}; + +const PostDetailsForm = (props: { + title: string; + description: string; + setDescription: (d: string) => void; +}) => { + return ( +
+
Post Details
+
+ + props.setDescription(e.currentTarget.value)} + /> +
+
+ ); +}; + +const PubSelector = (props: { + selectedPub: string | undefined; + setSelectedPub: (s: string) => void; + publications: { + identity_did: string; + indexed_at: string; + name: string; + record: Json | null; + uri: string; + }[]; +}) => { + // HEY STILL TO DO + // test out logged out, logged in but no pubs, and pubbed up flows + + return ( +
+
Publish to…
+ {props.publications.length === 0 || props.publications === undefined ? ( +
+
+ +
+
+ Publish as Looseleaf +
+
+ Publish this as a one off doc to AT Proto +
+
+
+
+ +
+
+ Publish to Publication +
+
+ Publish your writing to a blog on AT Proto +
+
+
+ You don't have any Publications yet.{" "} + + Create one + {" "} + to get started! +
+
+
+
+ ) : ( +
+ props.setSelectedPub("looseleaf")} + > + + Publish as Looseleaf + +
+ {props.publications.map((p) => { + let pubRecord = p.record as PubLeafletPublication.Record; + return ( + props.setSelectedPub(p.uri)} + > + <> + + {p.name} + + + ); + })} + +
+ )} +
+ ); +}; + +const PubOption = (props: { + selected: boolean; + onSelect: () => void; + children: React.ReactNode; +}) => { + return ( + + ); +}; + +let useTitle = (entityID: string) => { + let rootPage = useEntity(entityID, "root/page")[0].data.value; + let canvasBlocks = useCanvasBlocksWithType(rootPage).filter( + (b) => b.type === "text" || b.type === "heading", + ); + let blocks = useBlocks(rootPage).filter( + (b) => b.type === "text" || b.type === "heading", + ); + let firstBlock = canvasBlocks[0] || blocks[0]; + + let firstBlockText = useEntity(firstBlock?.value, "block/text")?.data.value; + + const leafletTitle = useMemo(() => { + if (!firstBlockText) return "Untitled"; + let doc = new Y.Doc(); + const update = base64.toByteArray(firstBlockText); + Y.applyUpdate(doc, update); + let nodes = doc.getXmlElement("prosemirror").toArray(); + return YJSFragmentToString(nodes[0]) || "Untitled"; + }, [firstBlockText]); + + // Only handle second block logic for linear documents, not canvas + let isCanvas = canvasBlocks.length > 0; + let secondBlock = !isCanvas ? blocks[1] : undefined; + let secondBlockTextValue = useEntity(secondBlock?.value || null, "block/text") + ?.data.value; + const secondBlockText = useMemo(() => { + if (!secondBlockTextValue) return ""; + let doc = new Y.Doc(); + const update = base64.toByteArray(secondBlockTextValue); + Y.applyUpdate(doc, update); + let nodes = doc.getXmlElement("prosemirror").toArray(); + return YJSFragmentToString(nodes[0]) || ""; + }, [secondBlockTextValue]); + + let entitiesToDelete = useMemo(() => { + let etod: string[] = []; + // Only delete first block if it's a heading type + if (firstBlock?.type === "heading") { + etod.push(firstBlock.value); + } + // Delete second block if it's empty text (only for linear documents) + if ( + !isCanvas && + secondBlockText.trim() === "" && + secondBlock?.type === "text" + ) { + etod.push(secondBlock.value); + } + return etod; + }, [firstBlock, secondBlockText, secondBlock, isCanvas]); + + return { title: leafletTitle, entitiesToDelete }; +}; diff --git a/components/ShareOptions/DomainOptions.tsx b/app/[leaflet_id]/actions/ShareOptions/DomainOptions.tsx similarity index 99% rename from components/ShareOptions/DomainOptions.tsx rename to app/[leaflet_id]/actions/ShareOptions/DomainOptions.tsx index b579df46..1221c788 100644 --- a/components/ShareOptions/DomainOptions.tsx +++ b/app/[leaflet_id]/actions/ShareOptions/DomainOptions.tsx @@ -8,7 +8,7 @@ import { useIdentityData } from "components/IdentityProvider"; import { addDomain } from "actions/domains/addDomain"; import { callRPC } from "app/api/rpc/client"; import { useLeafletDomains } from "components/PageSWRDataProvider"; -import { usePublishLink } from "."; +import { useReadOnlyShareLink } from "."; import { addDomainPath } from "actions/domains/addDomainPath"; import { useReplicache } from "src/replicache"; import { deleteDomain } from "actions/domains/deleteDomain"; @@ -74,7 +74,7 @@ export const DomainOptions = (props: { let toaster = useToaster(); let smoker = useSmoker(); - let publishLink = usePublishLink(); + let publishLink = useReadOnlyShareLink(); return (
diff --git a/components/ShareOptions/getShareLink.ts b/app/[leaflet_id]/actions/ShareOptions/getShareLink.ts similarity index 100% rename from components/ShareOptions/getShareLink.ts rename to app/[leaflet_id]/actions/ShareOptions/getShareLink.ts diff --git a/components/ShareOptions/index.tsx b/app/[leaflet_id]/actions/ShareOptions/index.tsx similarity index 95% rename from components/ShareOptions/index.tsx rename to app/[leaflet_id]/actions/ShareOptions/index.tsx index 34788ddb..7739150b 100644 --- a/components/ShareOptions/index.tsx +++ b/app/[leaflet_id]/actions/ShareOptions/index.tsx @@ -21,7 +21,7 @@ import { useIsMobile } from "src/hooks/isMobile"; export type ShareMenuStates = "default" | "login" | "domain"; -export let usePublishLink = () => { +export let useReadOnlyShareLink = () => { let { permission_token, rootEntity } = useReplicache(); let entity_set = useEntitySetContext(); let { data: publishLink } = useSWR( @@ -60,8 +60,7 @@ export function ShareOptions() { trigger={ - primary={!!!pub} - secondary={!!pub} + secondary label={`Share ${pub ? "Draft" : ""}`} /> } @@ -93,11 +92,13 @@ const ShareMenu = (props: { let record = pub?.documents?.data as PubLeafletDocument.Record | null; - let postLink = - pub?.publications && pub.documents - ? `${getPublicationURL(pub.publications)}/${new AtUri(pub?.documents.uri).rkey}` - : null; - let publishLink = usePublishLink(); + let docURI = pub?.documents ? new AtUri(pub?.documents.uri) : null; + let postLink = !docURI + ? null + : pub?.publications + ? `${getPublicationURL(pub.publications)}/${docURI.rkey}` + : `p/${docURI.host}/${docURI.rkey}`; + let publishLink = useReadOnlyShareLink(); let [collabLink, setCollabLink] = useState(null); useEffect(() => { // strip leading '/' character from pathname diff --git a/app/[leaflet_id]/page.tsx b/app/[leaflet_id]/page.tsx index 81376965..44265a4e 100644 --- a/app/[leaflet_id]/page.tsx +++ b/app/[leaflet_id]/page.tsx @@ -13,6 +13,7 @@ import { getPollData } from "actions/pollActions"; import { supabaseServerClient } from "supabase/serverClient"; import { get_leaflet_data } from "app/api/rpc/[command]/get_leaflet_data"; import { NotFoundLayout } from "components/PageLayouts/NotFoundLayout"; +import { getPublicationMetadataFromLeafletData } from "src/utils/getPublicationMetadataFromLeafletData"; export const preferredRegion = ["sfo1"]; export const dynamic = "force-dynamic"; @@ -70,11 +71,7 @@ export async function generateMetadata(props: Props): Promise { ); let rootEntity = res.data?.root_entity; if (!rootEntity || !res.data) return { title: "Leaflet not found" }; - let publication_data = - res.data?.leaflets_in_publications?.[0] || - res.data?.permission_token_rights[0].entity_sets?.permission_tokens?.find( - (p) => p.leaflets_in_publications.length, - )?.leaflets_in_publications?.[0]; + let publication_data = getPublicationMetadataFromLeafletData(res.data); if (publication_data) { return { title: publication_data.title || "Untitled", diff --git a/app/[leaflet_id]/publish/PublishPost.tsx b/app/[leaflet_id]/publish/PublishPost.tsx index 52ac63e9..3d5b459b 100644 --- a/app/[leaflet_id]/publish/PublishPost.tsx +++ b/app/[leaflet_id]/publish/PublishPost.tsx @@ -18,6 +18,8 @@ import { editorStateToFacetedText, } from "./BskyPostEditorProsemirror"; import { EditorState } from "prosemirror-state"; +import { LooseLeafSmall } from "components/Icons/LooseleafSmall"; +import { PubIcon } from "components/ActionBar/Publications"; type Props = { title: string; @@ -25,9 +27,10 @@ type Props = { root_entity: string; profile: ProfileViewDetailed; description: string; - publication_uri: string; + publication_uri?: string; record?: PubLeafletPublication.Record; posts_in_pub?: number; + entitiesToDelete?: string[]; }; export function PublishPost(props: Props) { @@ -72,10 +75,15 @@ const PublishPostForm = ( leaflet_id: props.leaflet_id, title: props.title, description: props.description, + entitiesToDelete: props.entitiesToDelete, }); if (!doc) return; - let post_url = `https://${props.record?.base_path}/${doc.rkey}`; + // Generate post URL based on whether it's in a publication or standalone + let post_url = props.record?.base_path + ? `https://${props.record.base_path}/${doc.rkey}` + : `https://leaflet.pub/p/${props.profile.did}/${doc.rkey}`; + let [text, facets] = editorStateRef.current ? editorStateToFacetedText(editorStateRef.current) : []; @@ -95,7 +103,6 @@ const PublishPostForm = ( return (
-

Publish Options

{ e.preventDefault(); @@ -103,6 +110,11 @@ const PublishPostForm = ( }} >
+ +
{ @@ -164,10 +176,14 @@ const PublishPostForm = (
{props.title}
{props.description}
-
-

- {props.record?.base_path} -

+ {props.record && ( + <> +
+

+ {props.record?.base_path} +

+ + )}
@@ -198,23 +214,59 @@ const PublishPostForm = ( ); }; +const PublishingTo = (props: { + publication_uri?: string; + record?: PubLeafletPublication.Record; +}) => { + if (props.publication_uri && props.record) { + return ( +
+

Publishing to

+
+ +
{props.record.name}
+
+
+ ); + } + + return ( +
+

Publishing as

+
+ +
Looseleaf
+
+
+ ); +}; + const PublishPostSuccess = (props: { post_url: string; - publication_uri: string; + publication_uri?: string; record: Props["record"]; posts_in_pub: number; }) => { - let uri = new AtUri(props.publication_uri); + let uri = props.publication_uri ? new AtUri(props.publication_uri) : null; return (
-

Published!

- - Back to Dashboard - +

Published!

+ {uri && props.record ? ( + + Back to Dashboard + + ) : ( + + Back to Home + + )} See published post
); diff --git a/app/[leaflet_id]/publish/page.tsx b/app/[leaflet_id]/publish/page.tsx index 578afb69..9ee5917c 100644 --- a/app/[leaflet_id]/publish/page.tsx +++ b/app/[leaflet_id]/publish/page.tsx @@ -13,6 +13,12 @@ export const fetchCache = "force-no-store"; type Props = { // this is now a token id not leaflet! Should probs rename params: Promise<{ leaflet_id: string }>; + searchParams: Promise<{ + publication_uri: string; + title: string; + description: string; + entitiesToDelete: string; + }>; }; export default async function PublishLeafletPage(props: Props) { let leaflet_id = (await props.params).leaflet_id; @@ -27,12 +33,36 @@ export default async function PublishLeafletPage(props: Props) { *, documents_in_publications(count) ), - documents(*))`, + documents(*)), + leaflets_to_documents( + *, + documents(*) + )`, ) .eq("id", leaflet_id) .single(); let rootEntity = data?.root_entity; - if (!data || !rootEntity || !data.leaflets_in_publications[0]) + + // Try to find publication from leaflets_in_publications first + let publication = data?.leaflets_in_publications[0]?.publications; + + // If not found, check if publication_uri is in searchParams + if (!publication) { + let pub_uri = (await props.searchParams).publication_uri; + if (pub_uri) { + console.log(decodeURIComponent(pub_uri)); + let { data: pubData, error } = await supabaseServerClient + .from("publications") + .select("*, documents_in_publications(count)") + .eq("uri", decodeURIComponent(pub_uri)) + .single(); + console.log(error); + publication = pubData; + } + } + + // Check basic data requirements + if (!data || !rootEntity) return (
missin something @@ -42,10 +72,33 @@ export default async function PublishLeafletPage(props: Props) { let identity = await getIdentityData(); if (!identity || !identity.atp_did) return null; - let pub = data.leaflets_in_publications[0]; - let agent = new AtpAgent({ service: "https://public.api.bsky.app" }); + // Get title and description from either source + let title = + data.leaflets_in_publications[0]?.title || + data.leaflets_to_documents[0]?.title || + decodeURIComponent((await props.searchParams).title || ""); + let description = + data.leaflets_in_publications[0]?.description || + data.leaflets_to_documents[0]?.description || + decodeURIComponent((await props.searchParams).description || ""); + + let agent = new AtpAgent({ service: "https://public.api.bsky.app" }); let profile = await agent.getProfile({ actor: identity.atp_did }); + + // Parse entitiesToDelete from URL params + let searchParams = await props.searchParams; + let entitiesToDelete: string[] = []; + try { + if (searchParams.entitiesToDelete) { + entitiesToDelete = JSON.parse( + decodeURIComponent(searchParams.entitiesToDelete), + ); + } + } catch (e) { + // If parsing fails, just use empty array + } + return ( ); diff --git a/app/api/rpc/[command]/get_leaflet_data.ts b/app/api/rpc/[command]/get_leaflet_data.ts index e8390b9e..19779b39 100644 --- a/app/api/rpc/[command]/get_leaflet_data.ts +++ b/app/api/rpc/[command]/get_leaflet_data.ts @@ -7,6 +7,7 @@ export type GetLeafletDataReturnType = Awaited< >; const leaflets_in_publications_query = `leaflets_in_publications(*, publications(*), documents(*))`; +const leaflets_to_documents_query = `leaflets_to_documents(*, documents(*))`; export const get_leaflet_data = makeRoute({ route: "get_leaflet_data", input: z.object({ @@ -18,9 +19,10 @@ export const get_leaflet_data = makeRoute({ .from("permission_tokens") .select( `*, - permission_token_rights(*, entity_sets(permission_tokens(${leaflets_in_publications_query}))), + permission_token_rights(*, entity_sets(permission_tokens(${leaflets_in_publications_query}, ${leaflets_to_documents_query}))), custom_domain_routes!custom_domain_routes_edit_permission_token_fkey(*), - ${leaflets_in_publications_query}`, + ${leaflets_in_publications_query}, + ${leaflets_to_documents_query}`, ) .eq("id", token_id) .single(); diff --git a/app/globals.css b/app/globals.css index 03008310..4193cdbd 100644 --- a/app/globals.css +++ b/app/globals.css @@ -339,6 +339,7 @@ pre.shiki { @apply focus-within:outline-offset-1; @apply disabled:border-border-light; + @apply disabled:hover:border-border-light; @apply disabled:bg-border-light; @apply disabled:text-tertiary; } diff --git a/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx b/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx index 7602cdf3..32bccd2c 100644 --- a/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx +++ b/app/lish/[did]/[publication]/[rkey]/CanvasPage.tsx @@ -21,41 +21,34 @@ import { InfoSmall } from "components/Icons/InfoSmall"; import { PostHeader } from "./PostHeader/PostHeader"; import { useDrawerOpen } from "./Interactions/InteractionDrawer"; import { PollData } from "./fetchPollData"; +import { SharedPageProps } from "./PostPages"; export function CanvasPage({ - document, blocks, - did, - profile, - preferences, - pubRecord, - prerenderedCodeBlocks, - bskyPostData, - pollData, - document_uri, - pageId, - pageOptions, - fullPageScroll, pages, -}: { - document_uri: string; - document: PostPageData; + ...props +}: Omit & { blocks: PubLeafletPagesCanvas.Block[]; - profile: ProfileViewDetailed; - pubRecord: PubLeafletPublication.Record; - did: string; - prerenderedCodeBlocks?: Map; - bskyPostData: AppBskyFeedDefs.PostView[]; - pollData: PollData[]; - preferences: { showComments?: boolean }; - pageId?: string; - pageOptions?: React.ReactNode; - fullPageScroll: boolean; pages: (PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main)[]; }) { + const { + document, + did, + profile, + preferences, + pubRecord, + theme, + prerenderedCodeBlocks, + bskyPostData, + pollData, + document_uri, + pageId, + pageOptions, + fullPageScroll, + } = props; if (!document) return null; - let hasPageBackground = !!pubRecord.theme?.showPageBackground; + let hasPageBackground = !!theme?.showPageBackground; let isSubpage = !!pageId; let drawer = useDrawerOpen(document_uri); diff --git a/app/lish/[did]/[publication]/[rkey]/DocumentPageRenderer.tsx b/app/lish/[did]/[publication]/[rkey]/DocumentPageRenderer.tsx new file mode 100644 index 00000000..b53b6383 --- /dev/null +++ b/app/lish/[did]/[publication]/[rkey]/DocumentPageRenderer.tsx @@ -0,0 +1,145 @@ +import { AtpAgent } from "@atproto/api"; +import { AtUri } from "@atproto/syntax"; +import { ids } from "lexicons/api/lexicons"; +import { + PubLeafletBlocksBskyPost, + PubLeafletDocument, + PubLeafletPagesLinearDocument, + PubLeafletPagesCanvas, + PubLeafletPublication, +} from "lexicons/api"; +import { QuoteHandler } from "./QuoteHandler"; +import { + PublicationBackgroundProvider, + PublicationThemeProvider, +} from "components/ThemeManager/PublicationThemeProvider"; +import { getPostPageData } from "./getPostPageData"; +import { PostPageContextProvider } from "./PostPageContext"; +import { PostPages } from "./PostPages"; +import { extractCodeBlocks } from "./extractCodeBlocks"; +import { LeafletLayout } from "components/LeafletLayout"; +import { fetchPollData } from "./fetchPollData"; + +export async function DocumentPageRenderer({ + did, + rkey, +}: { + did: string; + rkey: string; +}) { + let agent = new AtpAgent({ + service: "https://public.api.bsky.app", + fetch: (...args) => + fetch(args[0], { + ...args[1], + next: { revalidate: 3600 }, + }), + }); + + let [document, profile] = await Promise.all([ + getPostPageData(AtUri.make(did, ids.PubLeafletDocument, rkey).toString()), + agent.getProfile({ actor: did }), + ]); + + if (!document?.data) + return ( +
+
+
+

Sorry, post not found!

+

+ This may be a glitch on our end. If the issue persists please{" "} + send us a note. +

+
+
+
+ ); + + let record = document.data as PubLeafletDocument.Record; + let bskyPosts = + record.pages.flatMap((p) => { + let page = p as PubLeafletPagesLinearDocument.Main; + return page.blocks?.filter( + (b) => b.block.$type === ids.PubLeafletBlocksBskyPost, + ); + }) || []; + + // Batch bsky posts into groups of 25 and fetch in parallel + let bskyPostBatches = []; + for (let i = 0; i < bskyPosts.length; i += 25) { + bskyPostBatches.push(bskyPosts.slice(i, i + 25)); + } + + let bskyPostResponses = await Promise.all( + bskyPostBatches.map((batch) => + agent.getPosts( + { + uris: batch.map((p) => { + let block = p?.block as PubLeafletBlocksBskyPost.Main; + return block.postRef.uri; + }), + }, + { headers: {} }, + ), + ), + ); + + let bskyPostData = + bskyPostResponses.length > 0 + ? bskyPostResponses.flatMap((response) => response.data.posts) + : []; + + // Extract poll blocks and fetch vote data + let pollBlocks = record.pages.flatMap((p) => { + let page = p as PubLeafletPagesLinearDocument.Main; + return ( + page.blocks?.filter((b) => b.block.$type === ids.PubLeafletBlocksPoll) || + [] + ); + }); + let pollData = await fetchPollData( + pollBlocks.map((b) => (b.block as any).pollRef.uri), + ); + + // Get theme from publication or document (for standalone docs) + let pubRecord = document.documents_in_publications[0]?.publications + ?.record as PubLeafletPublication.Record | undefined; + let theme = pubRecord?.theme || record.theme || null; + let pub_creator = + document.documents_in_publications[0]?.publications?.identity_did || did; + + let firstPage = record.pages[0]; + + let firstPageBlocks = + ( + firstPage as + | PubLeafletPagesLinearDocument.Main + | PubLeafletPagesCanvas.Main + ).blocks || []; + let prerenderedCodeBlocks = await extractCodeBlocks(firstPageBlocks); + + return ( + + + + + + + + + + + + ); +} diff --git a/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx b/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx index ffa27a28..18e4fdd0 100644 --- a/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx +++ b/app/lish/[did]/[publication]/[rkey]/LinearDocumentPage.tsx @@ -23,43 +23,35 @@ import { useDrawerOpen } from "./Interactions/InteractionDrawer"; import { PageWrapper } from "components/Pages/Page"; import { decodeQuotePosition } from "./quotePosition"; import { PollData } from "./fetchPollData"; +import { SharedPageProps } from "./PostPages"; export function LinearDocumentPage({ - document, blocks, - did, - profile, - preferences, - pubRecord, - prerenderedCodeBlocks, - bskyPostData, - document_uri, - pageId, - pageOptions, - pollData, - fullPageScroll, -}: { - document_uri: string; - document: PostPageData; + ...props +}: Omit & { blocks: PubLeafletPagesLinearDocument.Block[]; - profile?: ProfileViewDetailed; - pubRecord: PubLeafletPublication.Record; - did: string; - prerenderedCodeBlocks?: Map; - bskyPostData: AppBskyFeedDefs.PostView[]; - pollData: PollData[]; - preferences: { showComments?: boolean }; - pageId?: string; - pageOptions?: React.ReactNode; - fullPageScroll: boolean; }) { + const { + document, + did, + profile, + preferences, + pubRecord, + theme, + prerenderedCodeBlocks, + bskyPostData, + pollData, + document_uri, + pageId, + pageOptions, + fullPageScroll, + } = props; let { identity } = useIdentityData(); let drawer = useDrawerOpen(document_uri); - if (!document || !document.documents_in_publications[0].publications) - return null; + if (!document) return null; - let hasPageBackground = !!pubRecord.theme?.showPageBackground; + let hasPageBackground = !!theme?.showPageBackground; let record = document.data as PubLeafletDocument.Record; const isSubpage = !!pageId; @@ -114,22 +106,24 @@ export function LinearDocumentPage({ Edit Post ) : ( - + document.documents_in_publications[0]?.publications && ( + + ) )}
diff --git a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx index ebea43ff..1ad7ed76 100644 --- a/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostHeader/PostHeader.tsx @@ -27,8 +27,7 @@ export function PostHeader(props: { let record = document?.data as PubLeafletDocument.Record; let profile = props.profile; - let pub = props.data?.documents_in_publications[0].publications; - let pubRecord = pub?.record as PubLeafletPublication.Record; + let pub = props.data?.documents_in_publications[0]?.publications; const formattedDate = useLocalizedDate( record.publishedAt || new Date().toISOString(), @@ -36,11 +35,10 @@ export function PostHeader(props: { year: "numeric", month: "long", day: "2-digit", - } + }, ); - if (!document?.data || !document.documents_in_publications[0].publications) - return; + if (!document?.data) return; return (
- - {pub?.name} - + {pub && ( + + {pub?.name} + + )} {identity && - identity.atp_did === - document.documents_in_publications[0]?.publications - .identity_did && + pub && + identity.atp_did === pub.identity_did && document.leaflets_in_publications[0] && ( - | -

{formattedDate}

+ |

{formattedDate}

) : null} |{" "} diff --git a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx index 00b061b2..e599e241 100644 --- a/app/lish/[did]/[publication]/[rkey]/PostPages.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PostPages.tsx @@ -98,9 +98,53 @@ export const closePage = (page: string) => }; }); +// Shared props type for both page components +export type SharedPageProps = { + document: PostPageData; + did: string; + profile: ProfileViewDetailed; + preferences: { showComments?: boolean }; + pubRecord?: PubLeafletPublication.Record; + theme?: PubLeafletPublication.Theme | null; + prerenderedCodeBlocks?: Map; + bskyPostData: AppBskyFeedDefs.PostView[]; + pollData: PollData[]; + document_uri: string; + fullPageScroll: boolean; + pageId?: string; + pageOptions?: React.ReactNode; + allPages: (PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main)[]; +}; + +// Component that renders either Canvas or Linear page based on page type +function PageRenderer({ + page, + ...sharedProps +}: { + page: PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main; +} & SharedPageProps) { + const isCanvas = PubLeafletPagesCanvas.isMain(page); + + if (isCanvas) { + return ( + + ); + } + + return ( + + ); +} + export function PostPages({ document, - blocks, did, profile, preferences, @@ -112,9 +156,8 @@ export function PostPages({ }: { document_uri: string; document: PostPageData; - blocks: PubLeafletPagesLinearDocument.Block[]; profile: ProfileViewDetailed; - pubRecord: PubLeafletPublication.Record; + pubRecord?: PubLeafletPublication.Record; did: string; prerenderedCodeBlocks?: Map; bskyPostData: AppBskyFeedDefs.PostView[]; @@ -123,37 +166,48 @@ export function PostPages({ }) { let drawer = useDrawerOpen(document_uri); useInitializeOpenPages(); - let pages = useOpenPages(); - if (!document || !document.documents_in_publications[0].publications) - return null; + let openPageIds = useOpenPages(); + if (!document) return null; - let hasPageBackground = !!pubRecord.theme?.showPageBackground; let record = document.data as PubLeafletDocument.Record; + let theme = pubRecord?.theme || record.theme || null; + let hasPageBackground = !!theme?.showPageBackground; let quotesAndMentions = document.quotesAndMentions; - let fullPageScroll = !hasPageBackground && !drawer && pages.length === 0; + let firstPage = record.pages[0] as + | PubLeafletPagesLinearDocument.Main + | PubLeafletPagesCanvas.Main; + + // Shared props used for all pages + const sharedProps: SharedPageProps = { + document, + did, + profile, + preferences, + pubRecord, + theme, + prerenderedCodeBlocks, + bskyPostData, + pollData, + document_uri, + allPages: record.pages as ( + | PubLeafletPagesLinearDocument.Main + | PubLeafletPagesCanvas.Main + )[], + fullPageScroll: !hasPageBackground && !drawer && openPageIds.length === 0, + }; + return ( <> - {!fullPageScroll && } - + {!sharedProps.fullPageScroll && } + + {drawer && !drawer.pageId && ( )} - {pages.map((p) => { + {openPageIds.map((pageId) => { let page = record.pages.find( - (page) => - ( - page as - | PubLeafletPagesLinearDocument.Main - | PubLeafletPagesCanvas.Main - ).id === p, + (p) => + (p as PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main) + .id === pageId, ) as | PubLeafletPagesLinearDocument.Main | PubLeafletPagesCanvas.Main | undefined; - if (!page) return null; - const isCanvas = PubLeafletPagesCanvas.isMain(page); + if (!page) return null; return ( - + - {isCanvas ? ( - closePage(page?.id!)} - hasPageBackground={hasPageBackground} - /> - } - /> - ) : ( - closePage(page?.id!)} - hasPageBackground={hasPageBackground} - /> - } - /> - )} + closePage(page.id!)} + hasPageBackground={hasPageBackground} + /> + } + /> {drawer && drawer.pageId === page.id && ( ); })} - {!fullPageScroll && } + + {!sharedProps.fullPageScroll && } ); } diff --git a/app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx b/app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx index aad2a8d5..a671285c 100644 --- a/app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx +++ b/app/lish/[did]/[publication]/[rkey]/PublishedPageBlock.tsx @@ -106,7 +106,7 @@ export function DocLinkBlock(props: {
{title && (
(null); let { rootEntity } = useReplicache(); let data = useContext(PostPageContext); - let theme = data?.documents_in_publications[0]?.publications - ?.record as PubLeafletPublication.Record; + let theme = data?.theme; let pageWidth = `var(--page-width-unitless)`; - let cardBorderHidden = !theme.theme?.showPageBackground; + let cardBorderHidden = !theme?.showPageBackground; return (
> { const codeBlocks = new Map(); - // Process all pages in the document + // Process all blocks (works for both linear and canvas) for (let i = 0; i < blocks.length; i++) { const block = blocks[i]; const currentIndex = [i]; diff --git a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts index 2c004601..7f26cd9f 100644 --- a/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts +++ b/app/lish/[did]/[publication]/[rkey]/getPostPageData.ts @@ -1,6 +1,6 @@ import { supabaseServerClient } from "supabase/serverClient"; import { AtUri } from "@atproto/syntax"; -import { PubLeafletPublication } from "lexicons/api"; +import { PubLeafletDocument, PubLeafletPublication } from "lexicons/api"; export async function getPostPageData(uri: string) { let { data: document } = await supabaseServerClient @@ -43,9 +43,16 @@ export async function getPostPageData(uri: string) { ...uniqueBacklinks, ]; + let theme = + ( + document?.documents_in_publications[0]?.publications + ?.record as PubLeafletPublication.Record + )?.theme || (document?.data as PubLeafletDocument.Record)?.theme; + return { ...document, quotesAndMentions, + theme, }; } diff --git a/app/lish/[did]/[publication]/[rkey]/page.tsx b/app/lish/[did]/[publication]/[rkey]/page.tsx index f791d173..0d7f22e5 100644 --- a/app/lish/[did]/[publication]/[rkey]/page.tsx +++ b/app/lish/[did]/[publication]/[rkey]/page.tsx @@ -1,26 +1,9 @@ import { supabaseServerClient } from "supabase/serverClient"; import { AtUri } from "@atproto/syntax"; import { ids } from "lexicons/api/lexicons"; -import { - PubLeafletBlocksBskyPost, - PubLeafletDocument, - PubLeafletPagesLinearDocument, - PubLeafletPublication, -} from "lexicons/api"; +import { PubLeafletDocument } from "lexicons/api"; import { Metadata } from "next"; -import { AtpAgent } from "@atproto/api"; -import { QuoteHandler } from "./QuoteHandler"; -import { InteractionDrawer } from "./Interactions/InteractionDrawer"; -import { - PublicationBackgroundProvider, - PublicationThemeProvider, -} from "components/ThemeManager/PublicationThemeProvider"; -import { getPostPageData } from "./getPostPageData"; -import { PostPageContextProvider } from "./PostPageContext"; -import { PostPages } from "./PostPages"; -import { extractCodeBlocks } from "./extractCodeBlocks"; -import { LeafletLayout } from "components/LeafletLayout"; -import { fetchPollData } from "./fetchPollData"; +import { DocumentPageRenderer } from "./DocumentPageRenderer"; export async function generateMetadata(props: { params: Promise<{ publication: string; did: string; rkey: string }>; @@ -57,7 +40,9 @@ export async function generateMetadata(props: { export default async function Post(props: { params: Promise<{ publication: string; did: string; rkey: string }>; }) { - let did = decodeURIComponent((await props.params).did); + let params = await props.params; + let did = decodeURIComponent(params.did); + if (!did) return (
@@ -68,141 +53,6 @@ export default async function Post(props: {

); - let agent = new AtpAgent({ - service: "https://public.api.bsky.app", - fetch: (...args) => - fetch(args[0], { - ...args[1], - next: { revalidate: 3600 }, - }), - }); - let [document, profile] = await Promise.all([ - getPostPageData( - AtUri.make( - did, - ids.PubLeafletDocument, - (await props.params).rkey, - ).toString(), - ), - agent.getProfile({ actor: did }), - ]); - if (!document?.data || !document.documents_in_publications[0].publications) - return ( -
- ); - let record = document.data as PubLeafletDocument.Record; - let bskyPosts = - record.pages.flatMap((p) => { - let page = p as PubLeafletPagesLinearDocument.Main; - return page.blocks?.filter( - (b) => b.block.$type === ids.PubLeafletBlocksBskyPost, - ); - }) || []; - - // Batch bsky posts into groups of 25 and fetch in parallel - let bskyPostBatches = []; - for (let i = 0; i < bskyPosts.length; i += 25) { - bskyPostBatches.push(bskyPosts.slice(i, i + 25)); - } - - let bskyPostResponses = await Promise.all( - bskyPostBatches.map((batch) => - agent.getPosts( - { - uris: batch.map((p) => { - let block = p?.block as PubLeafletBlocksBskyPost.Main; - return block.postRef.uri; - }), - }, - { headers: {} }, - ), - ), - ); - - let bskyPostData = - bskyPostResponses.length > 0 - ? bskyPostResponses.flatMap((response) => response.data.posts) - : []; - - // Extract poll blocks and fetch vote data - let pollBlocks = record.pages.flatMap((p) => { - let page = p as PubLeafletPagesLinearDocument.Main; - return ( - page.blocks?.filter((b) => b.block.$type === ids.PubLeafletBlocksPoll) || - [] - ); - }); - let pollData = await fetchPollData( - pollBlocks.map((b) => (b.block as any).pollRef.uri), - ); - - let pubRecord = document.documents_in_publications[0]?.publications - .record as PubLeafletPublication.Record; - - let firstPage = record.pages[0]; - let blocks: PubLeafletPagesLinearDocument.Block[] = []; - if (PubLeafletPagesLinearDocument.isMain(firstPage)) { - blocks = firstPage.blocks || []; - } - - let prerenderedCodeBlocks = await extractCodeBlocks(blocks); - - return ( - - - - {/* - TODO: SCROLL PAGE TO FIT DRAWER - If the drawer fits without scrolling, dont scroll - If both drawer and page fit if you scrolled it, scroll it all into the center - If the drawer and pafe doesn't all fit, scroll to drawer - - TODO: SROLL BAR - If there is no drawer && there is no page bg, scroll the entire page - If there is either a drawer open OR a page background, scroll just the post content - - TODO: HIGHLIGHTING BORKED - on chrome, if you scroll backward, things stop working - seems like if you use an older browser, sel direction is not a thing yet - */} - - - - - - - - ); + return ; } diff --git a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx index 12e2cc15..38cf82d3 100644 --- a/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx +++ b/app/lish/[did]/[publication]/dashboard/PublishedPostsLists.tsx @@ -13,7 +13,7 @@ import { ButtonPrimary } from "components/Buttons"; import { MoreOptionsVerticalTiny } from "components/Icons/MoreOptionsVerticalTiny"; import { DeleteSmall } from "components/Icons/DeleteSmall"; import { ShareSmall } from "components/Icons/ShareSmall"; -import { ShareButton } from "components/ShareOptions"; +import { ShareButton } from "app/[leaflet_id]/actions/ShareOptions"; import { SpeedyLink } from "components/SpeedyLink"; import { QuoteTiny } from "components/Icons/QuoteTiny"; import { CommentTiny } from "components/Icons/CommentTiny"; diff --git a/app/lish/[did]/[publication]/page.tsx b/app/lish/[did]/[publication]/page.tsx index aa1ac273..cf5d50af 100644 --- a/app/lish/[did]/[publication]/page.tsx +++ b/app/lish/[did]/[publication]/page.tsx @@ -60,11 +60,11 @@ export default async function Publication(props: { try { return ( { onChange={(e) => setShowInDiscover(e.target.checked)} >
-

- Show In{" "} +

Show In Discover

+

+ Your posts will appear on our{" "} Discover - -

-

- You'll be able to change this later! + {" "} + page. You can change this at any time!


-
+

- This publication will appear on our public Discover page + Your posts will appear on our{" "} + + Discover + {" "} + page. You can change this at any time!

diff --git a/app/lish/createPub/page.tsx b/app/lish/createPub/page.tsx index 848dde28..f22b8b67 100644 --- a/app/lish/createPub/page.tsx +++ b/app/lish/createPub/page.tsx @@ -26,7 +26,7 @@ export default async function CreatePub() {

Create Your Publication!

-
+
diff --git a/app/login/LoginForm.tsx b/app/login/LoginForm.tsx index 13a8e228..a9ffa1ba 100644 --- a/app/login/LoginForm.tsx +++ b/app/login/LoginForm.tsx @@ -213,7 +213,7 @@ export function BlueskyLogin(props: { @@ -92,21 +93,34 @@ export const ButtonTertiary = forwardRef< HTMLButtonElement, { fullWidth?: boolean; + fullWidthOnMobile?: boolean; children: React.ReactNode; compact?: boolean; } & ButtonProps >((props, ref) => { - let { fullWidth, children, compact, ...buttonProps } = props; + let { + className, + fullWidth, + fullWidthOnMobile, + compact, + children, + ...buttonProps + } = props; return ( diff --git a/components/Icons/LooseleafSmall.tsx b/components/Icons/LooseleafSmall.tsx new file mode 100644 index 00000000..7d2599be --- /dev/null +++ b/components/Icons/LooseleafSmall.tsx @@ -0,0 +1,19 @@ +import { Props } from "./Props"; + +export const LooseLeafSmall = (props: Props) => { + return ( + + + + ); +}; diff --git a/components/Input.tsx b/components/Input.tsx index 97213a69..5666bb01 100644 --- a/components/Input.tsx +++ b/components/Input.tsx @@ -100,9 +100,17 @@ export const InputWithLabel = ( JSX.IntrinsicElements["textarea"], ) => { let { label, textarea, ...inputProps } = props; - let style = `appearance-none w-full font-normal not-italic bg-transparent text-base text-primary focus:outline-0 ${props.className} outline-hidden resize-none`; + let style = ` + appearance-none resize-none w-full + bg-transparent + outline-hidden focus:outline-0 + font-normal not-italic text-base text-primary disabled:text-tertiary + disabled:cursor-not-allowed + ${props.className}`; return ( -