a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Feature/custom domain (#115)

* custom domains! sorry, i should have made more smaller commits

* remove duplicate icon

* fix url(/undefined) bg-images

* ovverride packages to remove punycode warning

* bunch of stuff to make custom domains work!

add columns to the routes table for edit and view permission tokens

* add @vercel/sdk

* handle copying custom domains share links

---------

Co-authored-by: celine <celine@hyperlink.academy>

authored by

Jared Pereira
celine
and committed by
GitHub
1585b108 d718d105

+971 -1138
+51
actions/domains/addDomain.ts
··· 1 + "use server"; 2 + import { Vercel } from "@vercel/sdk"; 3 + import { cookies } from "next/headers"; 4 + 5 + import { Database } from "supabase/database.types"; 6 + import { createServerClient } from "@supabase/ssr"; 7 + 8 + const VERCEL_TOKEN = process.env.VERCEL_TOKEN; 9 + const vercel = new Vercel({ 10 + bearerToken: VERCEL_TOKEN, 11 + }); 12 + 13 + let supabase = createServerClient<Database>( 14 + process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, 15 + process.env.SUPABASE_SERVICE_ROLE_KEY as string, 16 + { cookies: {} }, 17 + ); 18 + 19 + export async function addDomain(domain: string) { 20 + let auth_token = cookies().get("auth_token")?.value; 21 + if (!auth_token) return null; 22 + let { data: auth_data } = await supabase 23 + .from("email_auth_tokens") 24 + .select( 25 + `*, 26 + identities( 27 + *, 28 + custom_domains(*) 29 + )`, 30 + ) 31 + .eq("id", auth_token) 32 + .eq("confirmed", true) 33 + .single(); 34 + if (!auth_data || !auth_data.email) return null; 35 + 36 + await supabase.from("custom_domains").insert({ 37 + domain, 38 + identity: auth_data.email, 39 + confirmed: false, 40 + }); 41 + 42 + console.log( 43 + await vercel.projects.addProjectDomain({ 44 + idOrName: "prj_9jX4tmYCISnm176frFxk07fF74kG", 45 + teamId: "team_42xaJiZMTw9Sr7i0DcLTae9d", 46 + requestBody: { 47 + name: domain, 48 + }, 49 + }), 50 + ); 51 + }
+50
actions/domains/addDomainPath.ts
··· 1 + "use server"; 2 + import { cookies } from "next/headers"; 3 + import { Database } from "supabase/database.types"; 4 + import { createServerClient } from "@supabase/ssr"; 5 + 6 + let supabase = createServerClient<Database>( 7 + process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, 8 + process.env.SUPABASE_SERVICE_ROLE_KEY as string, 9 + { cookies: {} }, 10 + ); 11 + export async function addDomainPath({ 12 + domain, 13 + view_permission_token, 14 + edit_permission_token, 15 + route, 16 + }: { 17 + domain: string; 18 + view_permission_token: string; 19 + edit_permission_token: string; 20 + route: string; 21 + }) { 22 + let auth_token = cookies().get("auth_token")?.value; 23 + if (!auth_token) return null; 24 + let { data: auth_data } = await supabase 25 + .from("email_auth_tokens") 26 + .select( 27 + `*, 28 + identities( 29 + *, 30 + custom_domains(*) 31 + )`, 32 + ) 33 + .eq("id", auth_token) 34 + .eq("confirmed", true) 35 + .single(); 36 + if ( 37 + !auth_data || 38 + !auth_data.email || 39 + !auth_data.identities?.custom_domains.find((d) => d.domain === domain) 40 + ) 41 + return null; 42 + 43 + await supabase.from("custom_domain_routes").insert({ 44 + domain, 45 + route, 46 + view_permission_token, 47 + edit_permission_token, 48 + }); 49 + return true; 50 + }
+21
actions/domains/getLeafletDomains.ts
··· 1 + "use server"; 2 + 3 + import { createServerClient } from "@supabase/ssr"; 4 + import { cookies } from "next/headers"; 5 + import { Database } from "supabase/database.types"; 6 + 7 + let supabase = createServerClient<Database>( 8 + process.env.NEXT_PUBLIC_SUPABASE_API_URL as string, 9 + process.env.SUPABASE_SERVICE_ROLE_KEY as string, 10 + { cookies: {} }, 11 + ); 12 + export async function getLeafletDomains(id: string) { 13 + let res = await supabase 14 + .from("permission_tokens") 15 + .select( 16 + "*, permission_token_rights(*), custom_domain_routes!custom_domain_routes_edit_permission_token_fkey(*) ", 17 + ) 18 + .eq("id", id) 19 + .single(); 20 + return res.data?.custom_domain_routes; 21 + }
+6
actions/emailAuth.ts
··· 8 8 import { cookies } from "next/headers"; 9 9 10 10 async function sendAuthCode(email: string, code: string) { 11 + console.log(code); 12 + if (process.env.NODE_ENV === "development") { 13 + console.log("Auth code:", code); 14 + return; 15 + } 16 + 11 17 let res = await fetch("https://api.postmarkapp.com/email", { 12 18 method: "POST", 13 19 headers: {
+1
actions/getIdentityData.ts
··· 19 19 `*, 20 20 identities( 21 21 *, 22 + custom_domains(*), 22 23 home_leaflet:permission_tokens!identities_home_page_fkey(*, permission_token_rights(*)), 23 24 permission_token_on_homepage(created_at, permission_tokens!inner(*, permission_token_rights(*))) 24 25 )`,
+10 -4
app/[leaflet_id]/page.tsx
··· 10 10 import { Leaflet } from "./Leaflet"; 11 11 import { scanIndexLocal } from "src/replicache/utils"; 12 12 import { getRSVPData } from "actions/getRSVPData"; 13 - import { RSVPDataProvider } from "components/RSVPDataProvider"; 13 + import { PageSWRDataProvider } from "components/PageSWRDataProvider"; 14 14 15 15 export const preferredRegion = ["sfo1"]; 16 16 export const dynamic = "force-dynamic"; ··· 28 28 export default async function LeafletPage(props: Props) { 29 29 let res = await supabase 30 30 .from("permission_tokens") 31 - .select("*, permission_token_rights(*) ") 31 + .select( 32 + "*, permission_token_rights(*), custom_domain_routes!custom_domain_routes_edit_permission_token_fkey(*) ", 33 + ) 32 34 .eq("id", props.params.leaflet_id) 33 35 .single(); 34 36 let rootEntity = res.data?.root_entity; ··· 58 60 ]); 59 61 let initialFacts = (data as unknown as Fact<keyof typeof Attributes>[]) || []; 60 62 return ( 61 - <RSVPDataProvider data={rsvp_data}> 63 + <PageSWRDataProvider 64 + rsvp_data={rsvp_data} 65 + leaflet_id={res.data.id} 66 + domains={res.data.custom_domain_routes} 67 + > 62 68 <Leaflet 63 69 initialFacts={initialFacts} 64 70 leaflet_id={rootEntity} 65 71 token={res.data} 66 72 /> 67 - </RSVPDataProvider> 73 + </PageSWRDataProvider> 68 74 ); 69 75 } 70 76
+24
app/api/rpc/[command]/get_domain_status.ts
··· 1 + import { z } from "zod"; 2 + import { makeRoute } from "../lib"; 3 + import { Env } from "./route"; 4 + 5 + export const get_domain_status = makeRoute({ 6 + route: "get_domain_status", 7 + input: z.object({ 8 + domain: z.string(), 9 + }), 10 + handler: async ({ domain }, { vercel }: Pick<Env, "vercel">) => { 11 + let [status, config] = await Promise.all([ 12 + vercel.domains.getDomain({ 13 + domain, 14 + teamId: "team_42xaJiZMTw9Sr7i0DcLTae9d", 15 + }), 16 + vercel.domains.getDomainConfig({ 17 + domain, 18 + teamId: "team_42xaJiZMTw9Sr7i0DcLTae9d", 19 + }), 20 + ]); 21 + 22 + return { status, config }; 23 + }, 24 + });
+8 -1
app/api/rpc/[command]/route.ts
··· 6 6 import { Database } from "supabase/database.types"; 7 7 import { pull } from "./pull"; 8 8 import { getFactsFromHomeLeaflets } from "./getFactsFromHomeLeaflets"; 9 + import { Vercel } from "@vercel/sdk"; 10 + import { get_domain_status } from "./get_domain_status"; 9 11 10 12 const client = postgres(process.env.DB_URL as string, { idle_timeout: 5 }); 11 13 let supabase = createClient<Database>( ··· 14 16 ); 15 17 const db = drizzle(client); 16 18 19 + const VERCEL_TOKEN = process.env.VERCEL_TOKEN; 20 + const vercel = new Vercel({ 21 + bearerToken: VERCEL_TOKEN, 22 + }); 17 23 const Env = { 18 24 supabase, 25 + vercel, 19 26 }; 20 27 export type Env = typeof Env; 21 28 export type Routes = typeof Routes; 22 - let Routes = [push, pull, getFactsFromHomeLeaflets]; 29 + let Routes = [push, pull, getFactsFromHomeLeaflets, get_domain_status]; 23 30 export async function POST( 24 31 req: Request, 25 32 { params }: { params: { command: string } },
+1 -1
app/globals.css
··· 117 117 } 118 118 119 119 ::placeholder { 120 - @apply text-tertiary !important; 120 + @apply text-tertiary; 121 121 @apply italic; 122 122 } 123 123 /*END FONT STYLING*/
+2 -2
app/login/LoginForm.tsx
··· 6 6 import { loginWithEmailToken } from "actions/login"; 7 7 import { getHomeDocs } from "app/home/storage"; 8 8 import { ButtonPrimary } from "components/Buttons"; 9 - import { InputWithLabel } from "components/Layout"; 9 + import { InputWithLabel } from "components/Input"; 10 10 import { useSmoker, useToaster } from "components/Toast"; 11 11 import React, { useState } from "react"; 12 12 import useSWR, { mutate } from "swr"; ··· 113 113 114 114 return ( 115 115 <div className="flex flex-col gap-3 w-full max-w-sm pb-1"> 116 - <div className="flex flex-col gap-0.5"> 116 + <div className="flex flex-col"> 117 117 <h3>Log In or Sign Up</h3> 118 118 <div className=" text-secondary"> 119 119 Save your leaflets and access them on multiple devices!
+1 -1
components/Blocks/RSVPBlock/Atendees.tsx
··· 1 1 "use client"; 2 - import { useRSVPData } from "src/hooks/useRSVPData"; 2 + import { useRSVPData } from "components/PageSWRDataProvider"; 3 3 import { ButtonTertiary } from "components/Buttons"; 4 4 import { Popover } from "components/Popover"; 5 5
+1 -1
components/Blocks/RSVPBlock/ContactDetailsForm.tsx
··· 2 2 import { useSmoker, useToaster } from "components/Toast"; 3 3 import { RSVP_Status, RSVPButtons, State, useRSVPNameState } from "."; 4 4 import { createContext, useContext, useState } from "react"; 5 - import { useRSVPData } from "src/hooks/useRSVPData"; 5 + import { useRSVPData } from "components/PageSWRDataProvider"; 6 6 import { confirmPhoneAuthToken } from "actions/phone_auth/confirm_phone_auth_token"; 7 7 import { submitRSVP } from "actions/phone_rsvp_to_event"; 8 8
+1 -1
components/Blocks/RSVPBlock/SendUpdate.tsx
··· 1 1 "use client"; 2 2 import { useState } from "react"; 3 - import { useRSVPData } from "src/hooks/useRSVPData"; 3 + import { useRSVPData } from "components/PageSWRDataProvider"; 4 4 import { useEntitySetContext } from "components/EntitySetProvider"; 5 5 import { ButtonPrimary } from "components/Buttons"; 6 6 import { UpdateSmall } from "components/Icons";
+1 -1
components/Blocks/RSVPBlock/index.tsx
··· 3 3 import { BlockProps } from "components/Blocks/Block"; 4 4 import { useState } from "react"; 5 5 import { submitRSVP } from "actions/phone_rsvp_to_event"; 6 - import { useRSVPData } from "src/hooks/useRSVPData"; 6 + import { useRSVPData } from "components/PageSWRDataProvider"; 7 7 import { useEntitySetContext } from "components/EntitySetProvider"; 8 8 import { ButtonSecondary } from "components/Buttons"; 9 9 import { create } from "zustand";
+44 -1
components/Checkbox.tsx
··· 1 - import { CheckboxChecked, CheckboxEmpty } from "./Icons"; 1 + import { 2 + CheckboxChecked, 3 + CheckboxEmpty, 4 + RadioChecked, 5 + RadioEmpty, 6 + } from "./Icons"; 2 7 3 8 export function Checkbox(props: { 4 9 checked: boolean; ··· 30 35 </label> 31 36 ); 32 37 } 38 + 39 + export function Radio(props: { 40 + checked: boolean; 41 + onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; 42 + id: string; 43 + name: string; 44 + value: string; 45 + children: React.ReactNode; 46 + radioEmptyClassName?: string; 47 + radioCheckedClassName?: string; 48 + }) { 49 + return ( 50 + <label 51 + htmlFor={props.id} 52 + className={`flex gap-2 items-start cursor-pointer shrink-0 ${props.checked ? "text-primary font-bold " : " text-tertiary font-normal"}`} 53 + > 54 + <input 55 + type="radio" 56 + name={props.name} 57 + id={props.id} 58 + value={props.value} 59 + checked={props.checked} 60 + className="hidden" 61 + onChange={(e) => props.onChange(e)} 62 + /> 63 + {!props.checked ? ( 64 + <RadioEmpty 65 + className={`shrink-0 mt-[6px] text-tertiary ${props.radioEmptyClassName}`} 66 + /> 67 + ) : ( 68 + <RadioChecked 69 + className={`shrink-0 mt-[6px] text-accent-contrast ${props.radioCheckedClassName}`} 70 + /> 71 + )} 72 + {props.children} 73 + </label> 74 + ); 75 + }
+64 -20
components/Icons.tsx
··· 44 44 45 45 // SMALL ICONS 24X24 46 46 47 + export const AccountSmall = (props: Props) => { 48 + return ( 49 + <svg 50 + width="24" 51 + height="24" 52 + viewBox="0 0 24 24" 53 + fill="none" 54 + xmlns="http://www.w3.org/2000/svg" 55 + {...props} 56 + > 57 + <path 58 + fillRule="evenodd" 59 + clipRule="evenodd" 60 + d="M12.1186 4.00393C12.4755 4.21417 12.5944 4.67393 12.3841 5.03082L7.48811 13.3416C7.55452 13.3759 7.62551 13.4115 7.70068 13.4478C8.22649 13.7018 8.93184 13.9775 9.68768 14.0983C11.3104 14.3577 12.2206 14.15 12.5778 13.9741C12.9494 13.7911 13.399 13.944 13.582 14.3156C13.765 14.6872 13.6121 15.1368 13.2405 15.3198C12.4986 15.6851 11.2379 15.8651 9.45092 15.5795C8.5019 15.4278 7.65179 15.09 7.04836 14.7986C6.74415 14.6517 6.49643 14.5135 6.32286 14.4108C6.23595 14.3594 6.16726 14.3167 6.11899 14.2859C6.09485 14.2705 6.07578 14.2581 6.06205 14.2491L6.04551 14.2381L6.0403 14.2346L6.03847 14.2334L6.03744 14.2327L6.45839 13.6119C6.03716 14.2325 6.0373 14.2326 6.03744 14.2327C5.71013 14.0105 5.61139 13.5721 5.81219 13.2312L11.0917 4.26944C11.302 3.91255 11.7617 3.79368 12.1186 4.00393ZM5.99939 7.33218C6.76172 7.39081 7.43385 6.73443 7.50064 5.8661C7.56742 4.99778 7.00357 4.24634 6.24124 4.18771C5.4789 4.12907 4.80677 4.78546 4.73999 5.65378C4.67321 6.5221 5.23706 7.27355 5.99939 7.33218ZM17.0236 8.10185C17.7864 8.04973 18.3566 7.30312 18.2972 6.43426C18.2379 5.5654 17.5714 4.90331 16.8086 4.95543C16.0458 5.00755 15.4755 5.75416 15.5349 6.62302C15.5942 7.49188 16.2608 8.15397 17.0236 8.10185ZM16.8245 18.4262C17.1433 18.1618 17.1873 17.6889 16.9229 17.3701C16.6584 17.0513 16.1856 17.0073 15.8668 17.2717C13.8455 18.9485 11.3149 19.488 9.03465 19.0788C8.62695 19.0057 8.23713 19.2769 8.16398 19.6846C8.09083 20.0923 8.36204 20.4821 8.76974 20.5553C11.4587 21.0377 14.4429 20.4019 16.8245 18.4262Z" 61 + fill="currentColor" 62 + /> 63 + </svg> 64 + ); 65 + }; 66 + 47 67 export const AddSmall = (props: Props) => { 48 68 return ( 49 69 <svg ··· 505 525 ); 506 526 }; 507 527 508 - export const AccountSmall = (props: Props) => { 509 - return ( 510 - <svg 511 - width="24" 512 - height="24" 513 - viewBox="0 0 24 24" 514 - fill="none" 515 - xmlns="http://www.w3.org/2000/svg" 516 - {...props} 517 - > 518 - <path 519 - fillRule="evenodd" 520 - clipRule="evenodd" 521 - d="M12.1186 4.00393C12.4755 4.21417 12.5944 4.67393 12.3841 5.03082L7.48811 13.3416C7.55452 13.3759 7.62551 13.4115 7.70068 13.4478C8.22649 13.7018 8.93184 13.9775 9.68768 14.0983C11.3104 14.3577 12.2206 14.15 12.5778 13.9741C12.9494 13.7911 13.399 13.944 13.582 14.3156C13.765 14.6872 13.6121 15.1368 13.2405 15.3198C12.4986 15.6851 11.2379 15.8651 9.45092 15.5795C8.5019 15.4278 7.65179 15.09 7.04836 14.7986C6.74415 14.6517 6.49643 14.5135 6.32286 14.4108C6.23595 14.3594 6.16726 14.3167 6.11899 14.2859C6.09485 14.2705 6.07578 14.2581 6.06205 14.2491L6.04551 14.2381L6.0403 14.2346L6.03847 14.2334L6.03744 14.2327L6.45839 13.6119C6.03716 14.2325 6.0373 14.2326 6.03744 14.2327C5.71013 14.0105 5.61139 13.5721 5.81219 13.2312L11.0917 4.26944C11.302 3.91255 11.7617 3.79368 12.1186 4.00393ZM5.99939 7.33218C6.76172 7.39081 7.43385 6.73443 7.50064 5.8661C7.56742 4.99778 7.00357 4.24634 6.24124 4.18771C5.4789 4.12907 4.80677 4.78546 4.73999 5.65378C4.67321 6.5221 5.23706 7.27355 5.99939 7.33218ZM17.0236 8.10185C17.7864 8.04973 18.3566 7.30312 18.2972 6.43426C18.2379 5.5654 17.5714 4.90331 16.8086 4.95543C16.0458 5.00755 15.4755 5.75416 15.5349 6.62302C15.5942 7.49188 16.2608 8.15397 17.0236 8.10185ZM16.8245 18.4262C17.1433 18.1618 17.1873 17.6889 16.9229 17.3701C16.6584 17.0513 16.1856 17.0073 15.8668 17.2717C13.8455 18.9485 11.3149 19.488 9.03465 19.0788C8.62695 19.0057 8.23713 19.2769 8.16398 19.6846C8.09083 20.0923 8.36204 20.4821 8.76974 20.5553C11.4587 21.0377 14.4429 20.4019 16.8245 18.4262Z" 522 - fill="currentColor" 523 - /> 524 - </svg> 525 - ); 526 - }; 527 - 528 528 export const ShareSmall = (props: Props) => { 529 529 return ( 530 530 <svg ··· 721 721 fillRule="evenodd" 722 722 clipRule="evenodd" 723 723 d="M2 0C0.895431 0 0 0.89543 0 2V10C0 11.1046 0.89543 12 2 12H10C11.1046 12 12 11.1046 12 10V2C12 0.895431 11.1046 0 10 0H2ZM10.4554 3.95353C10.7769 3.59277 10.7451 3.03966 10.3843 2.71813C10.0236 2.3966 9.47046 2.4284 9.14893 2.78916L5.03209 7.40828L3.28982 5.92642C2.92171 5.61333 2.36949 5.65793 2.0564 6.02604C1.74331 6.39415 1.78791 6.94637 2.15602 7.25946L4.54955 9.29524C4.91165 9.60322 5.45339 9.56577 5.76966 9.21091L10.4554 3.95353Z" 724 + fill="currentColor" 725 + /> 726 + </svg> 727 + ); 728 + }; 729 + 730 + export const RadioEmpty = (props: Props) => { 731 + return ( 732 + <svg 733 + width="12" 734 + height="12" 735 + viewBox="0 0 12 12" 736 + fill="none" 737 + xmlns="http://www.w3.org/2000/svg" 738 + {...props} 739 + > 740 + <path 741 + fillRule="evenodd" 742 + clipRule="evenodd" 743 + d="M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11ZM6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12Z" 744 + fill="currentColor" 745 + /> 746 + </svg> 747 + ); 748 + }; 749 + 750 + export const RadioChecked = (props: Props) => { 751 + return ( 752 + <svg 753 + width="12" 754 + height="12" 755 + viewBox="0 0 12 12" 756 + fill="none" 757 + xmlns="http://www.w3.org/2000/svg" 758 + {...props} 759 + > 760 + <path 761 + fillRule="evenodd" 762 + clipRule="evenodd" 763 + d="M6 10.5C8.48528 10.5 10.5 8.48528 10.5 6C10.5 3.51472 8.48528 1.5 6 1.5C3.51472 1.5 1.5 3.51472 1.5 6C1.5 8.48528 3.51472 10.5 6 10.5ZM6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12Z" 764 + fill="currentColor" 765 + /> 766 + <path 767 + d="M9 6C9 7.65685 7.65685 9 6 9C4.34315 9 3 7.65685 3 6C3 4.34315 4.34315 3 6 3C7.65685 3 9 4.34315 9 6Z" 724 768 fill="currentColor" 725 769 /> 726 770 </svg>
+23
components/Input.tsx
··· 39 39 /> 40 40 ); 41 41 } 42 + 43 + export const InputWithLabel = ( 44 + props: { 45 + label: string; 46 + } & JSX.IntrinsicElements["input"], 47 + ) => { 48 + let { label, ...inputProps } = props; 49 + return ( 50 + <div> 51 + <div className="input-with-border flex flex-col"> 52 + <label> 53 + <div className="text-sm text-tertiary font-bold italic leading-none pt-0.5"> 54 + {props.label} 55 + </div> 56 + <Input 57 + {...inputProps} 58 + className={`appearance-none w-full font-normal bg-transparent text-base text-primary focus:outline-0 ${props.className}`} 59 + /> 60 + </label> 61 + </div> 62 + </div> 63 + ); 64 + };
+1 -1
components/MobileFooter.tsx
··· 35 35 <div className="flex flex-row gap-[6px] items-center "> 36 36 <HelpPopover /> 37 37 <ThemePopover entityID={props.entityID} /> 38 - <ShareOptions rootEntity={props.entityID} /> 38 + <ShareOptions /> 39 39 </div> 40 40 </div> 41 41 ) : (
+41
components/PageSWRDataProvider.tsx
··· 1 + "use client"; 2 + import { getRSVPData } from "actions/getRSVPData"; 3 + import { SWRConfig } from "swr"; 4 + import { useReplicache } from "src/replicache"; 5 + import useSWR from "swr"; 6 + import { getLeafletDomains } from "actions/domains/getLeafletDomains"; 7 + 8 + export function PageSWRDataProvider(props: { 9 + leaflet_id: string; 10 + domains: { domain: string }[]; 11 + rsvp_data: Awaited<ReturnType<typeof getRSVPData>>; 12 + children: React.ReactNode; 13 + }) { 14 + return ( 15 + <SWRConfig 16 + value={{ 17 + fallback: { 18 + rsvp_data: props.rsvp_data, 19 + [`${props.leaflet_id}-domains`]: props.domains, 20 + }, 21 + }} 22 + > 23 + {props.children} 24 + </SWRConfig> 25 + ); 26 + } 27 + 28 + export function useRSVPData() { 29 + let { permission_token } = useReplicache(); 30 + return useSWR(`rsvp_data`, () => 31 + getRSVPData( 32 + permission_token.permission_token_rights.map((pr) => pr.entity_set), 33 + ), 34 + ); 35 + } 36 + export function useLeafletDomains() { 37 + let { permission_token } = useReplicache(); 38 + return useSWR(`${permission_token.id}-domains`, () => 39 + getLeafletDomains(permission_token.id), 40 + ); 41 + }
+7
components/Pages/PageShareMenu.tsx
··· 1 + import { useLeafletDomains } from "components/PageSWRDataProvider"; 1 2 import { ShareButton, usePublishLink } from "components/ShareOptions"; 2 3 import { useEffect, useState } from "react"; 3 4 4 5 export const PageShareMenu = (props: { entityID: string }) => { 5 6 let publishLink = usePublishLink(); 7 + let { data: domains } = useLeafletDomains(); 6 8 let [collabLink, setCollabLink] = useState<null | string>(null); 7 9 useEffect(() => { 8 10 setCollabLink(window.location.pathname); ··· 24 26 helptext="🚨 recipients can view the entire Leaflet" 25 27 smokerText="Publish link copied!" 26 28 id="get-page-publish-link" 29 + fullLink={ 30 + domains?.[0] 31 + ? `https://${domains[0].domain}${domains[0].route}?page=${props.entityID}` 32 + : undefined 33 + } 27 34 link={`${publishLink}?page=${props.entityID}`} 28 35 /> 29 36 </div>
+1 -1
components/Pages/index.tsx
··· 63 63 <div className="flex flex-col h-full justify-between mt-1"> 64 64 {entity_set.permissions.write ? ( 65 65 <div className="flex flex-col justify-center gap-2 mr-4"> 66 - <ShareOptions rootEntity={props.rootPage} /> 66 + <ShareOptions /> 67 67 <LeafletOptions entityID={props.rootPage} /> 68 68 <HelpPopover /> 69 69 <hr className="text-border my-3" />
-14
components/RSVPDataProvider.tsx
··· 1 - "use client"; 2 - import { getRSVPData } from "actions/getRSVPData"; 3 - import { SWRConfig } from "swr"; 4 - 5 - export function RSVPDataProvider(props: { 6 - data: Awaited<ReturnType<typeof getRSVPData>>; 7 - children: React.ReactNode; 8 - }) { 9 - return ( 10 - <SWRConfig value={{ fallback: { rsvp_data: props.data } }}> 11 - {props.children} 12 - </SWRConfig> 13 - ); 14 - }
+1
components/SelectionManager.tsx
··· 474 474 if (e.key === "c" && (e.metaKey || e.ctrlKey)) { 475 475 if (!rep) return; 476 476 let [, , selectionWithFoldedChildren] = await getSortedSelection(); 477 + if (!selectionWithFoldedChildren) return; 477 478 await copySelection(rep, selectionWithFoldedChildren); 478 479 } 479 480 };
+355
components/ShareOptions/DomainOptions.tsx
··· 1 + import { useState } from "react"; 2 + import { ButtonPrimary } from "components/Buttons"; 3 + 4 + import { AddTiny } from "components/Icons"; 5 + import { useSmoker, useToaster } from "components/Toast"; 6 + import { Input, InputWithLabel } from "components/Input"; 7 + import useSWR from "swr"; 8 + import { useIdentityData } from "components/IdentityProvider"; 9 + import { addDomain } from "actions/domains/addDomain"; 10 + import { callRPC } from "app/api/rpc/client"; 11 + import { useLeafletDomains } from "components/PageSWRDataProvider"; 12 + import { usePublishLink } from "."; 13 + import { addDomainPath } from "actions/domains/addDomainPath"; 14 + import { useReplicache } from "src/replicache"; 15 + 16 + type DomainMenuState = 17 + | { 18 + state: "default"; 19 + } 20 + | { 21 + state: "domain-settings"; 22 + domain: string; 23 + } 24 + | { 25 + state: "add-domain"; 26 + } 27 + | { 28 + state: "has-domain"; 29 + domain: string; 30 + }; 31 + export function CustomDomainMenu(props: { 32 + setShareMenuState: (s: "default") => void; 33 + }) { 34 + let { data: domains } = useLeafletDomains(); 35 + let [state, setState] = useState<DomainMenuState>( 36 + domains?.[0] 37 + ? { state: "has-domain", domain: domains[0].domain } 38 + : { state: "default" }, 39 + ); 40 + switch (state.state) { 41 + case "has-domain": 42 + case "default": 43 + return ( 44 + <DomainOptions 45 + setDomainMenuState={setState} 46 + domainConnected={false} 47 + setShareMenuState={props.setShareMenuState} 48 + /> 49 + ); 50 + case "domain-settings": 51 + return ( 52 + <DomainSettings domain={state.domain} setDomainMenuState={setState} /> 53 + ); 54 + case "add-domain": 55 + return <AddDomain setDomainMenuState={setState} />; 56 + } 57 + } 58 + 59 + export const DomainOptions = (props: { 60 + setShareMenuState: (s: "default") => void; 61 + setDomainMenuState: (state: DomainMenuState) => void; 62 + domainConnected: boolean; 63 + }) => { 64 + let { data: domains, mutate: mutateDomains } = useLeafletDomains(); 65 + let [selectedDomain, setSelectedDomain] = useState<string | undefined>( 66 + domains?.[0]?.domain, 67 + ); 68 + let [selectedRoute, setSelectedRoute] = useState( 69 + domains?.[0]?.route.slice(1) || "", 70 + ); 71 + let { identity } = useIdentityData(); 72 + let { permission_token } = useReplicache(); 73 + 74 + let toaster = useToaster(); 75 + let smoker = useSmoker(); 76 + let publishLink = usePublishLink(); 77 + 78 + return ( 79 + <div className="px-3 py-1 flex flex-col gap-3 max-w-full w-[600px]"> 80 + <h3 className="text-secondary">Choose a Domain</h3> 81 + <div className="flex flex-col gap-1"> 82 + {identity?.custom_domains.map((domain) => { 83 + return ( 84 + <DomainOption 85 + selectedRoute={selectedRoute} 86 + setSelectedRoute={setSelectedRoute} 87 + key={domain.domain} 88 + domain={domain.domain} 89 + checked={selectedDomain === domain.domain} 90 + setChecked={setSelectedDomain} 91 + setDomainMenuState={props.setDomainMenuState} 92 + /> 93 + ); 94 + })} 95 + <button 96 + onMouseDown={() => { 97 + props.setDomainMenuState({ state: "add-domain" }); 98 + }} 99 + className="text-accent-contrast flex gap-2 items-center px-1 py-0.5" 100 + > 101 + <AddTiny /> Add a New Domain 102 + </button> 103 + </div> 104 + 105 + {/* ONLY SHOW IF A DOMAIN IS CURRENTLY CONNECTED */} 106 + <div className="flex gap-3 items-center justify-end"> 107 + {props.domainConnected && ( 108 + <button 109 + onMouseDown={() => { 110 + props.setShareMenuState("default"); 111 + toaster({ 112 + content: ( 113 + <div className="font-bold"> 114 + Unpublished from custom domain! 115 + </div> 116 + ), 117 + type: "error", 118 + }); 119 + }} 120 + > 121 + Unpublish 122 + </button> 123 + )} 124 + 125 + <ButtonPrimary 126 + id="publish-to-domain" 127 + disabled={ 128 + domains?.[0] 129 + ? domains[0].domain === selectedDomain && 130 + domains[0].route.slice(1) === selectedRoute 131 + : !selectedDomain 132 + } 133 + onClick={async () => { 134 + // let rect = document 135 + // .getElementById("publish-to-domain") 136 + // ?.getBoundingClientRect(); 137 + // smoker({ 138 + // error: true, 139 + // text: "url already in use!", 140 + // position: { 141 + // x: rect ? rect.left : 0, 142 + // y: rect ? rect.top + 26 : 0, 143 + // }, 144 + // }); 145 + if (!selectedDomain || !publishLink) return; 146 + await addDomainPath({ 147 + domain: selectedDomain, 148 + route: "/" + selectedRoute, 149 + view_permission_token: publishLink, 150 + edit_permission_token: permission_token.id, 151 + }); 152 + 153 + toaster({ 154 + content: ( 155 + <div className="font-bold"> 156 + Published to custom domain!{" "} 157 + <a className="underline text-accent-2" href="/"> 158 + View 159 + </a> 160 + </div> 161 + ), 162 + type: "success", 163 + }); 164 + mutateDomains(); 165 + props.setShareMenuState("default"); 166 + }} 167 + > 168 + Publish! 169 + </ButtonPrimary> 170 + </div> 171 + </div> 172 + ); 173 + }; 174 + 175 + const DomainOption = (props: { 176 + selectedRoute: string; 177 + setSelectedRoute: (s: string) => void; 178 + checked: boolean; 179 + setChecked: (checked: string) => void; 180 + domain: string; 181 + setDomainMenuState: (state: DomainMenuState) => void; 182 + }) => { 183 + let [value, setValue] = useState(""); 184 + let { data } = useSWR(props.domain, async (domain) => { 185 + return await callRPC("get_domain_status", { domain }); 186 + }); 187 + let pending = data?.config.misconfigured; 188 + return ( 189 + <label htmlFor={props.domain}> 190 + <input 191 + type="radio" 192 + name={props.domain} 193 + id={props.domain} 194 + value={props.domain} 195 + checked={props.checked} 196 + className="hidden appearance-none" 197 + onChange={() => props.setChecked(props.domain)} 198 + /> 199 + <div 200 + className={` 201 + px-[6px] py-1 202 + flex 203 + border rounded-md 204 + ${ 205 + pending 206 + ? "border-border-light text-secondary justify-between gap-2 items-center " 207 + : !props.checked 208 + ? "flex-wrap border-border-light" 209 + : "flex-wrap border-accent-1 bg-accent-1 text-accent-2 font-bold" 210 + } `} 211 + > 212 + <div className={`w-max truncate ${pending && "animate-pulse"}`}> 213 + {props.domain} 214 + </div> 215 + {props.checked && ( 216 + <div className="flex gap-0 w-full"> 217 + <span 218 + className="font-normal" 219 + style={value === "" ? { opacity: "0.5" } : {}} 220 + > 221 + / 222 + </span> 223 + 224 + <Input 225 + type="text" 226 + autoFocus 227 + className="appearance-none focus:outline-none font-normal text-accent-2 w-full bg-transparent placeholder:text-accent-2 placeholder:opacity-50" 228 + placeholder="add-optional-path" 229 + onChange={(e) => props.setSelectedRoute(e.target.value)} 230 + value={props.selectedRoute} 231 + /> 232 + </div> 233 + )} 234 + {pending && ( 235 + <button 236 + className="text-accent-contrast text-sm" 237 + onMouseDown={() => { 238 + props.setDomainMenuState({ 239 + state: "domain-settings", 240 + domain: props.domain, 241 + }); 242 + }} 243 + > 244 + details 245 + </button> 246 + )} 247 + </div> 248 + </label> 249 + ); 250 + }; 251 + 252 + export const AddDomain = (props: { 253 + setDomainMenuState: (state: DomainMenuState) => void; 254 + }) => { 255 + let [value, setValue] = useState(""); 256 + return ( 257 + <div className="flex flex-col gap-1 px-3 py-1 max-w-full w-[600px]"> 258 + <h3 className="text-secondary">Add a New Domain</h3> 259 + 260 + <Input 261 + className="input-with-border" 262 + placeholder="www.example.com" 263 + value={value} 264 + onChange={(e) => setValue(e.target.value)} 265 + /> 266 + 267 + <ButtonPrimary 268 + disabled={!value} 269 + className="place-self-end mt-2" 270 + onMouseDown={async () => { 271 + // call the vercel api, set the thing... 272 + await addDomain(value); 273 + props.setDomainMenuState({ state: "domain-settings", domain: value }); 274 + }} 275 + > 276 + Verify Domain 277 + </ButtonPrimary> 278 + </div> 279 + ); 280 + }; 281 + 282 + const DomainSettings = (props: { 283 + domain: string; 284 + setDomainMenuState: (s: DomainMenuState) => void; 285 + }) => { 286 + let isSubdomain = props.domain.split(".").length > 2; 287 + return ( 288 + <div className="flex flex-col gap-1 px-3 py-1 max-w-full w-[600px]"> 289 + <h3 className="text-secondary">Verify Domain</h3> 290 + 291 + <div className="text-secondary text-sm flex flex-col gap-3"> 292 + <div className="flex flex-col gap-[6px]"> 293 + <div> 294 + To verify this domain, add the following record to your DNS provider 295 + for <strong>{props.domain}</strong>. 296 + </div> 297 + 298 + {isSubdomain ? ( 299 + <div className="flex gap-3 p-1 border border-border-light rounded-md py-1"> 300 + <div className="flex flex-col "> 301 + <div className="text-tertiary">Type</div> 302 + <div>CNAME</div> 303 + </div> 304 + <div className="flex flex-col"> 305 + <div className="text-tertiary">Name</div> 306 + <div>{props.domain.split(".").slice(0, -2).join(".")}</div> 307 + </div> 308 + <div className="flex flex-col"> 309 + <div className="text-tertiary">Value</div> 310 + <div>cname.vercel-dns.com</div> 311 + </div> 312 + </div> 313 + ) : ( 314 + <div className="flex gap-3 p-1 border border-border-light rounded-md py-1"> 315 + <div className="flex flex-col "> 316 + <div className="text-tertiary">Type</div> 317 + <div>A</div> 318 + </div> 319 + <div className="flex flex-col"> 320 + <div className="text-tertiary">Name</div> 321 + <div>@</div> 322 + </div> 323 + <div className="flex flex-col"> 324 + <div className="text-tertiary">Value</div> 325 + <div>76.76.21.21</div> 326 + </div> 327 + </div> 328 + )} 329 + </div> 330 + <div> 331 + Once you do this, your provider may be pending for up to a few hours. 332 + </div> 333 + <div>Check back later to see if verfication was successful.</div> 334 + </div> 335 + 336 + <div className="flex gap-3 justify-between items-center mt-2"> 337 + <button 338 + className="text-accent-contrast font-bold " 339 + onMouseDown={() => { 340 + props.setDomainMenuState({ state: "default" }); 341 + }} 342 + > 343 + Delete Domain 344 + </button> 345 + <ButtonPrimary 346 + onMouseDown={() => { 347 + props.setDomainMenuState({ state: "default" }); 348 + }} 349 + > 350 + Back to Domains 351 + </ButtonPrimary> 352 + </div> 353 + </div> 354 + ); 355 + };
+117 -21
components/ShareOptions/index.tsx
··· 1 1 import { useReplicache } from "src/replicache"; 2 2 import { ShareSmall } from "components/Icons"; 3 - import { useEffect, useState } from "react"; 3 + import React, { useEffect, useState } from "react"; 4 4 import { getShareLink } from "./getShareLink"; 5 5 import { useEntitySetContext } from "components/EntitySetProvider"; 6 6 import { useSmoker } from "components/Toast"; ··· 8 8 import { HoverButton } from "components/Buttons"; 9 9 import useSWR from "swr"; 10 10 import { useTemplateState } from "app/home/CreateNewButton"; 11 + import LoginForm from "app/login/LoginForm"; 12 + import { AddDomain, CustomDomainMenu, DomainOptions } from "./DomainOptions"; 13 + import { useIdentityData } from "components/IdentityProvider"; 14 + import { useLeafletDomains } from "components/PageSWRDataProvider"; 15 + 16 + export type ShareMenuStates = "default" | "login" | "domain"; 11 17 12 18 export let usePublishLink = () => { 13 19 let { permission_token, rootEntity } = useReplicache(); ··· 31 37 return publishLink; 32 38 }; 33 39 34 - export function ShareOptions(props: { rootEntity: string }) { 40 + export function ShareOptions() { 35 41 let { permission_token } = useReplicache(); 36 - let entity_set = useEntitySetContext(); 37 - let publishLink = usePublishLink(); 38 - let [collabLink, setCollabLink] = useState<null | string>(null); 39 - useEffect(() => { 40 - // strip leading '/' character from pathname 41 - setCollabLink(window.location.pathname.slice(1)); 42 - }, []); 43 - 44 - let smoker = useSmoker(); 45 - 46 - let isTemplate = useTemplateState( 47 - (s) => !!s.templates.find((t) => t.id === permission_token.id), 48 - ); 42 + let [menuState, setMenuState] = useState<ShareMenuStates>("default"); 49 43 50 44 return ( 51 45 <Menu 52 46 className="max-w-xs" 47 + onOpenChange={() => { 48 + setMenuState("default"); 49 + }} 53 50 trigger={ 54 51 <HoverButton 55 52 icon=<ShareSmall /> ··· 59 56 /> 60 57 } 61 58 > 59 + {menuState === "login" ? ( 60 + <div className="px-3 py-1"> 61 + <LoginForm /> 62 + </div> 63 + ) : menuState === "domain" ? ( 64 + <CustomDomainMenu setShareMenuState={setMenuState} /> 65 + ) : ( 66 + <DefaultOptions setMenuState={setMenuState} domainConnected={false} /> 67 + )} 68 + </Menu> 69 + ); 70 + } 71 + 72 + const DefaultOptions = (props: { 73 + setMenuState: (state: ShareMenuStates) => void; 74 + domainConnected: boolean; 75 + }) => { 76 + let { permission_token } = useReplicache(); 77 + let publishLink = usePublishLink(); 78 + let [collabLink, setCollabLink] = useState<null | string>(null); 79 + useEffect(() => { 80 + // strip leading '/' character from pathname 81 + setCollabLink(window.location.pathname.slice(1)); 82 + }, []); 83 + let { data: domains } = useLeafletDomains(); 84 + 85 + let isTemplate = useTemplateState( 86 + (s) => !!s.templates.find((t) => t.id === permission_token.id), 87 + ); 88 + return ( 89 + <> 62 90 {isTemplate && ( 63 91 <> 64 92 <ShareButton ··· 80 108 /> 81 109 <ShareButton 82 110 text="Publish" 83 - subtext="Share a read-only version" 111 + subtext=<> 112 + {domains?.[0] ? ( 113 + <> 114 + This leaflet is published on{" "} 115 + <span className="italic underline"> 116 + {domains[0].domain}/{domains[0].route} 117 + </span> 118 + </> 119 + ) : ( 120 + "Send the read-only version" 121 + )} 122 + </> 84 123 smokerText="Publish link copied!" 85 124 id="get-publish-link" 125 + fullLink={ 126 + domains?.[0] 127 + ? `http://${domains[0].domain}${domains[0].route}` 128 + : undefined 129 + } 86 130 link={publishLink || ""} 87 131 /> 88 - </Menu> 132 + <hr className="border-border mt-1" /> 133 + <DomainMenuItem setMenuState={props.setMenuState} /> 134 + </> 89 135 ); 90 - } 136 + }; 91 137 92 138 export const ShareButton = (props: { 93 139 text: string; 94 - subtext: string; 140 + subtext: React.ReactNode; 95 141 helptext?: string; 96 142 smokerText: string; 97 143 id: string; 98 144 link: null | string; 145 + fullLink?: string; 99 146 }) => { 100 147 let smoker = useSmoker(); 101 148 ··· 105 152 onSelect={(e) => { 106 153 e.preventDefault(); 107 154 let rect = document.getElementById(props.id)?.getBoundingClientRect(); 108 - if (props.link) { 155 + if (props.link || props.fullLink) { 109 156 navigator.clipboard.writeText( 110 - `${location.protocol}//${location.host}/${props.link}`, 157 + props.fullLink 158 + ? props.fullLink 159 + : `${location.protocol}//${location.host}/${props.link}`, 111 160 ); 112 161 smoker({ 113 162 position: { ··· 140 189 </MenuItem> 141 190 ); 142 191 }; 192 + 193 + const DomainMenuItem = (props: { 194 + setMenuState: (state: ShareMenuStates) => void; 195 + }) => { 196 + let { identity } = useIdentityData(); 197 + let { data: domains } = useLeafletDomains(); 198 + 199 + if (identity === null) 200 + return ( 201 + <div className="text-tertiary font-normal text-sm px-3 py-1"> 202 + <button 203 + className="text-accent-contrast hover:font-bold" 204 + onClick={() => { 205 + props.setMenuState("login"); 206 + }} 207 + > 208 + Log In 209 + </button>{" "} 210 + to publish on a custom domain! 211 + </div> 212 + ); 213 + else 214 + return ( 215 + <> 216 + {domains?.[0] ? ( 217 + <button 218 + className="px-3 py-1 text-accent-contrast text-sm hover:font-bold w-fit text-left" 219 + onMouseDown={() => { 220 + props.setMenuState("domain"); 221 + }} 222 + > 223 + edit custom domain 224 + </button> 225 + ) : ( 226 + <MenuItem 227 + className="font-normal text-tertiary text-sm" 228 + onSelect={(e) => { 229 + e.preventDefault(); 230 + props.setMenuState("domain"); 231 + }} 232 + > 233 + Publish on a custom domain 234 + </MenuItem> 235 + )} 236 + </> 237 + ); 238 + };
+1 -1
components/Toast.tsx
··· 111 111 <div 112 112 className={`toast absolute right-2 w-max shadow-md px-3 py-1 flex flex-row gap-2 rounded-full border text-center ${ 113 113 props.toast?.type === "error" 114 - ? "bg-accent-red text-white border-white" 114 + ? "border-white bg-[#dc143c] text-white border font-bold" 115 115 : props.toast?.type === "success" 116 116 ? "bg-accent-1 text-accent-2 border border-accent-2" 117 117 : "bg-accent-1 text-accent-2 border border-accent-2"
+53 -42
drizzle/relations.ts
··· 1 1 import { relations } from "drizzle-orm/relations"; 2 - import { identities, custom_domains, custom_domain_routes, permission_tokens, entities, facts, entity_sets, email_subscriptions_to_entity, email_auth_tokens, phone_rsvps_to_entity, permission_token_on_homepage, permission_token_rights } from "./schema"; 3 - 4 - export const custom_domainsRelations = relations(custom_domains, ({one, many}) => ({ 5 - identity: one(identities, { 6 - fields: [custom_domains.identity], 7 - references: [identities.email] 8 - }), 9 - custom_domain_routes: many(custom_domain_routes), 10 - })); 11 - 12 - export const identitiesRelations = relations(identities, ({one, many}) => ({ 13 - custom_domains: many(custom_domains), 14 - permission_token: one(permission_tokens, { 15 - fields: [identities.home_page], 16 - references: [permission_tokens.id] 17 - }), 18 - email_auth_tokens: many(email_auth_tokens), 19 - permission_token_on_homepages: many(permission_token_on_homepage), 20 - })); 21 - 22 - export const custom_domain_routesRelations = relations(custom_domain_routes, ({one}) => ({ 23 - custom_domain: one(custom_domains, { 24 - fields: [custom_domain_routes.domain], 25 - references: [custom_domains.domain] 26 - }), 27 - permission_token: one(permission_tokens, { 28 - fields: [custom_domain_routes.permission_token], 29 - references: [permission_tokens.id] 30 - }), 31 - })); 32 - 33 - export const permission_tokensRelations = relations(permission_tokens, ({one, many}) => ({ 34 - custom_domain_routes: many(custom_domain_routes), 35 - entity: one(entities, { 36 - fields: [permission_tokens.root_entity], 37 - references: [entities.id] 38 - }), 39 - identities: many(identities), 40 - email_subscriptions_to_entities: many(email_subscriptions_to_entity), 41 - permission_token_on_homepages: many(permission_token_on_homepage), 42 - permission_token_rights: many(permission_token_rights), 43 - })); 2 + import { entities, facts, entity_sets, permission_tokens, identities, email_subscriptions_to_entity, email_auth_tokens, custom_domains, custom_domain_routes, phone_rsvps_to_entity, permission_token_on_homepage, permission_token_rights } from "./schema"; 44 3 45 4 export const factsRelations = relations(facts, ({one}) => ({ 46 5 entity: one(entities, { ··· 65 24 permission_token_rights: many(permission_token_rights), 66 25 })); 67 26 27 + export const permission_tokensRelations = relations(permission_tokens, ({one, many}) => ({ 28 + entity: one(entities, { 29 + fields: [permission_tokens.root_entity], 30 + references: [entities.id] 31 + }), 32 + identities: many(identities), 33 + email_subscriptions_to_entities: many(email_subscriptions_to_entity), 34 + custom_domain_routes_edit_permission_token: many(custom_domain_routes, { 35 + relationName: "custom_domain_routes_edit_permission_token_permission_tokens_id" 36 + }), 37 + custom_domain_routes_view_permission_token: many(custom_domain_routes, { 38 + relationName: "custom_domain_routes_view_permission_token_permission_tokens_id" 39 + }), 40 + permission_token_on_homepages: many(permission_token_on_homepage), 41 + permission_token_rights: many(permission_token_rights), 42 + })); 43 + 44 + export const identitiesRelations = relations(identities, ({one, many}) => ({ 45 + permission_token: one(permission_tokens, { 46 + fields: [identities.home_page], 47 + references: [permission_tokens.id] 48 + }), 49 + email_auth_tokens: many(email_auth_tokens), 50 + custom_domains: many(custom_domains), 51 + permission_token_on_homepages: many(permission_token_on_homepage), 52 + })); 53 + 68 54 export const email_subscriptions_to_entityRelations = relations(email_subscriptions_to_entity, ({one}) => ({ 69 55 entity: one(entities, { 70 56 fields: [email_subscriptions_to_entity.entity], ··· 80 66 identity: one(identities, { 81 67 fields: [email_auth_tokens.identity], 82 68 references: [identities.id] 69 + }), 70 + })); 71 + 72 + export const custom_domain_routesRelations = relations(custom_domain_routes, ({one}) => ({ 73 + custom_domain: one(custom_domains, { 74 + fields: [custom_domain_routes.domain], 75 + references: [custom_domains.domain] 76 + }), 77 + permission_token_edit_permission_token: one(permission_tokens, { 78 + fields: [custom_domain_routes.edit_permission_token], 79 + references: [permission_tokens.id], 80 + relationName: "custom_domain_routes_edit_permission_token_permission_tokens_id" 81 + }), 82 + permission_token_view_permission_token: one(permission_tokens, { 83 + fields: [custom_domain_routes.view_permission_token], 84 + references: [permission_tokens.id], 85 + relationName: "custom_domain_routes_view_permission_token_permission_tokens_id" 86 + }), 87 + })); 88 + 89 + export const custom_domainsRelations = relations(custom_domains, ({one, many}) => ({ 90 + custom_domain_routes: many(custom_domain_routes), 91 + identity: one(identities, { 92 + fields: [custom_domains.identity], 93 + references: [identities.email] 83 94 }), 84 95 })); 85 96
+21 -20
drizzle/schema.ts
··· 1 - import { pgTable, foreignKey, pgEnum, text, boolean, unique, uuid, jsonb, timestamp, bigint, uniqueIndex, smallint, primaryKey } from "drizzle-orm/pg-core" 1 + import { pgTable, foreignKey, pgEnum, uuid, text, jsonb, timestamp, bigint, unique, boolean, uniqueIndex, smallint, primaryKey } from "drizzle-orm/pg-core" 2 2 import { sql } from "drizzle-orm" 3 3 4 4 export const aal_level = pgEnum("aal_level", ['aal1', 'aal2', 'aal3']) ··· 13 13 export const action = pgEnum("action", ['INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'ERROR']) 14 14 export const equality_op = pgEnum("equality_op", ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in']) 15 15 16 - 17 - export const custom_domains = pgTable("custom_domains", { 18 - domain: text("domain").primaryKey().notNull(), 19 - identity: text("identity").default('').notNull().references(() => identities.email, { onDelete: "cascade", onUpdate: "cascade" } ), 20 - confirmed: boolean("confirmed").notNull(), 21 - }); 22 - 23 - export const custom_domain_routes = pgTable("custom_domain_routes", { 24 - id: uuid("id").defaultRandom().primaryKey().notNull(), 25 - domain: text("domain").notNull().references(() => custom_domains.domain), 26 - route: text("route").notNull(), 27 - permission_token: uuid("permission_token").notNull().references(() => permission_tokens.id, { onDelete: "cascade", onUpdate: "cascade" } ), 28 - }, 29 - (table) => { 30 - return { 31 - custom_domain_routes_domain_route_key: unique("custom_domain_routes_domain_route_key").on(table.domain, table.route), 32 - } 33 - }); 34 16 35 17 export const facts = pgTable("facts", { 36 18 id: uuid("id").primaryKey().notNull(), ··· 106 88 country_code: text("country_code").notNull(), 107 89 }); 108 90 91 + export const custom_domain_routes = pgTable("custom_domain_routes", { 92 + id: uuid("id").defaultRandom().primaryKey().notNull(), 93 + domain: text("domain").notNull().references(() => custom_domains.domain), 94 + route: text("route").notNull(), 95 + view_permission_token: uuid("view_permission_token").notNull().references(() => permission_tokens.id, { onDelete: "cascade", onUpdate: "cascade" } ), 96 + edit_permission_token: uuid("edit_permission_token").notNull().references(() => permission_tokens.id, { onDelete: "cascade", onUpdate: "cascade" } ), 97 + }, 98 + (table) => { 99 + return { 100 + custom_domain_routes_domain_route_key: unique("custom_domain_routes_domain_route_key").on(table.domain, table.route), 101 + } 102 + }); 103 + 104 + export const custom_domains = pgTable("custom_domains", { 105 + domain: text("domain").primaryKey().notNull(), 106 + identity: text("identity").default('').notNull().references(() => identities.email, { onDelete: "cascade", onUpdate: "cascade" } ), 107 + confirmed: boolean("confirmed").notNull(), 108 + }); 109 + 109 110 export const phone_rsvps_to_entity = pgTable("phone_rsvps_to_entity", { 110 111 created_at: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(), 111 112 phone_number: text("phone_number").notNull(), 113 + country_code: text("country_code").notNull(), 112 114 status: rsvp_status("status").notNull(), 113 115 id: uuid("id").defaultRandom().primaryKey().notNull(), 114 116 entity: uuid("entity").notNull().references(() => entities.id, { onDelete: "cascade", onUpdate: "cascade" } ), 115 117 name: text("name").default('').notNull(), 116 - country_code: text("country_code").notNull(), 117 118 plus_ones: smallint("plus_ones").default(0).notNull(), 118 119 }, 119 120 (table) => {
+3 -1
middleware.ts
··· 29 29 .eq("route", req.nextUrl.pathname) 30 30 .single(); 31 31 if (route) 32 - return NextResponse.rewrite(new URL(`/${route.permission_token}`, req.url)); 32 + return NextResponse.rewrite( 33 + new URL(`/${route.view_permission_token}`, req.url), 34 + ); 33 35 }
+29 -984
package-lock.json
··· 9 9 "version": "1.0.0", 10 10 "license": "ISC", 11 11 "dependencies": { 12 - "@baselime/node-opentelemetry": "^0.5.8", 13 12 "@mdx-js/loader": "^3.1.0", 14 13 "@mdx-js/react": "^3.1.0", 15 14 "@next/mdx": "^15.0.3", ··· 25 24 "@types/mdx": "^2.0.13", 26 25 "@vercel/analytics": "^1.3.1", 27 26 "@vercel/kv": "^1.0.1", 27 + "@vercel/sdk": "^1.3.1", 28 28 "base64-js": "^1.5.1", 29 29 "colorjs.io": "^0.5.2", 30 30 "drizzle-orm": "^0.30.10", ··· 107 107 "integrity": "sha512-aqzw+V8XSOkYlu7Aq1QhXqfxz5V6Vm6e0p6XZYZDEaGwSc6ac9OJ4B7U4BOo3mm7FzzRRHJ5yizeGKnj+REjBQ==", 108 108 "engines": { 109 109 "node": ">= 16" 110 - } 111 - }, 112 - "node_modules/@baselime/node-opentelemetry": { 113 - "version": "0.5.8", 114 - "resolved": "https://registry.npmjs.org/@baselime/node-opentelemetry/-/node-opentelemetry-0.5.8.tgz", 115 - "integrity": "sha512-wF3119LuxWLqCg1od6qHWqzz8fdod9HIB03Aa8EZNoxcGY7kxFXdDW8v1iz8jCx2bCRHw6ZYSL9Hpg8AwDnzyg==", 116 - "dependencies": { 117 - "@opentelemetry/api": "^1.8.0", 118 - "@opentelemetry/exporter-trace-otlp-http": "^0.50.0", 119 - "@opentelemetry/instrumentation": "^0.50.0", 120 - "@opentelemetry/instrumentation-http": "^0.50.0", 121 - "@opentelemetry/resource-detector-aws": "^1.4.1", 122 - "@opentelemetry/resources": "^1.23.0", 123 - "@opentelemetry/sdk-node": "^0.50.0", 124 - "@opentelemetry/sdk-trace-node": "^1.23.0", 125 - "@types/aws-lambda": "^8.10.136", 126 - "axios": "^1.6.8", 127 - "flat": "^6.0.1", 128 - "undici": "^6.11.1" 129 - }, 130 - "peerDependencies": { 131 - "@trpc/server": "^10.0.0 || ^11.0.0" 132 110 } 133 111 }, 134 112 "node_modules/@cloudflare/kv-asset-handler": { ··· 1198 1176 "tslib": "^2.4.0" 1199 1177 } 1200 1178 }, 1201 - "node_modules/@grpc/grpc-js": { 1202 - "version": "1.10.8", 1203 - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.8.tgz", 1204 - "integrity": "sha512-vYVqYzHicDqyKB+NQhAc54I1QWCBLCrYG6unqOIcBTHx+7x8C9lcoLj3KVJXs2VB4lUbpWY+Kk9NipcbXYWmvg==", 1205 - "dependencies": { 1206 - "@grpc/proto-loader": "^0.7.13", 1207 - "@js-sdsl/ordered-map": "^4.4.2" 1208 - }, 1209 - "engines": { 1210 - "node": ">=12.10.0" 1211 - } 1212 - }, 1213 - "node_modules/@grpc/proto-loader": { 1214 - "version": "0.7.13", 1215 - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", 1216 - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", 1217 - "dependencies": { 1218 - "lodash.camelcase": "^4.3.0", 1219 - "long": "^5.0.0", 1220 - "protobufjs": "^7.2.5", 1221 - "yargs": "^17.7.2" 1222 - }, 1223 - "bin": { 1224 - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" 1225 - }, 1226 - "engines": { 1227 - "node": ">=6" 1228 - } 1229 - }, 1230 1179 "node_modules/@humanwhocodes/config-array": { 1231 1180 "version": "0.11.14", 1232 1181 "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", ··· 1441 1390 "dependencies": { 1442 1391 "@jridgewell/resolve-uri": "^3.1.0", 1443 1392 "@jridgewell/sourcemap-codec": "^1.4.14" 1444 - } 1445 - }, 1446 - "node_modules/@js-sdsl/ordered-map": { 1447 - "version": "4.4.2", 1448 - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", 1449 - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", 1450 - "funding": { 1451 - "type": "opencollective", 1452 - "url": "https://opencollective.com/js-sdsl" 1453 1393 } 1454 1394 }, 1455 1395 "node_modules/@mdx-js/loader": { ··· 1825 1765 "version": "1.8.0", 1826 1766 "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz", 1827 1767 "integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==", 1768 + "optional": true, 1769 + "peer": true, 1828 1770 "engines": { 1829 1771 "node": ">=8.0.0" 1830 1772 } 1831 1773 }, 1832 - "node_modules/@opentelemetry/api-logs": { 1833 - "version": "0.50.0", 1834 - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.50.0.tgz", 1835 - "integrity": "sha512-JdZuKrhOYggqOpUljAq4WWNi5nB10PmgoF0y2CvedLGXd0kSawb/UBnWT8gg1ND3bHCNHStAIVT0ELlxJJRqrA==", 1836 - "dependencies": { 1837 - "@opentelemetry/api": "^1.0.0" 1838 - }, 1839 - "engines": { 1840 - "node": ">=14" 1841 - } 1842 - }, 1843 - "node_modules/@opentelemetry/context-async-hooks": { 1844 - "version": "1.24.1", 1845 - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.24.1.tgz", 1846 - "integrity": "sha512-R5r6DO4kgEOVBxFXhXjwospLQkv+sYxwCfjvoZBe7Zm6KKXAV9kDSJhi/D1BweowdZmO+sdbENLs374gER8hpQ==", 1847 - "engines": { 1848 - "node": ">=14" 1849 - }, 1850 - "peerDependencies": { 1851 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1852 - } 1853 - }, 1854 - "node_modules/@opentelemetry/core": { 1855 - "version": "1.23.0", 1856 - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.23.0.tgz", 1857 - "integrity": "sha512-hdQ/a9TMzMQF/BO8Cz1juA43/L5YGtCSiKoOHmrTEf7VMDAZgy8ucpWx3eQTnQ3gBloRcWtzvcrMZABC3PTSKQ==", 1858 - "dependencies": { 1859 - "@opentelemetry/semantic-conventions": "1.23.0" 1860 - }, 1861 - "engines": { 1862 - "node": ">=14" 1863 - }, 1864 - "peerDependencies": { 1865 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1866 - } 1867 - }, 1868 - "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { 1869 - "version": "0.50.0", 1870 - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.50.0.tgz", 1871 - "integrity": "sha512-w/NF4TrwHxx+Uz1M0rCOSVr6KgcoQPv3zF9JRqcebY2euD7ddWnLP0hE8JavyA1uq4UchnMp9faAk9n7hTCePw==", 1872 - "dependencies": { 1873 - "@grpc/grpc-js": "^1.7.1", 1874 - "@opentelemetry/core": "1.23.0", 1875 - "@opentelemetry/otlp-grpc-exporter-base": "0.50.0", 1876 - "@opentelemetry/otlp-transformer": "0.50.0", 1877 - "@opentelemetry/resources": "1.23.0", 1878 - "@opentelemetry/sdk-trace-base": "1.23.0" 1879 - }, 1880 - "engines": { 1881 - "node": ">=14" 1882 - }, 1883 - "peerDependencies": { 1884 - "@opentelemetry/api": "^1.0.0" 1885 - } 1886 - }, 1887 - "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": { 1888 - "version": "1.23.0", 1889 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 1890 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 1891 - "dependencies": { 1892 - "@opentelemetry/core": "1.23.0", 1893 - "@opentelemetry/semantic-conventions": "1.23.0" 1894 - }, 1895 - "engines": { 1896 - "node": ">=14" 1897 - }, 1898 - "peerDependencies": { 1899 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1900 - } 1901 - }, 1902 - "node_modules/@opentelemetry/exporter-trace-otlp-http": { 1903 - "version": "0.50.0", 1904 - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.50.0.tgz", 1905 - "integrity": "sha512-L7OtIMT7MsFqkmhbQlPBGRXt7152VN5esHpQEJYIBFedOEo3Da+yHpu5ojMZtPzpIvSpB5Xr5lnJUjJCbkttCA==", 1906 - "dependencies": { 1907 - "@opentelemetry/core": "1.23.0", 1908 - "@opentelemetry/otlp-exporter-base": "0.50.0", 1909 - "@opentelemetry/otlp-transformer": "0.50.0", 1910 - "@opentelemetry/resources": "1.23.0", 1911 - "@opentelemetry/sdk-trace-base": "1.23.0" 1912 - }, 1913 - "engines": { 1914 - "node": ">=14" 1915 - }, 1916 - "peerDependencies": { 1917 - "@opentelemetry/api": "^1.0.0" 1918 - } 1919 - }, 1920 - "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/resources": { 1921 - "version": "1.23.0", 1922 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 1923 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 1924 - "dependencies": { 1925 - "@opentelemetry/core": "1.23.0", 1926 - "@opentelemetry/semantic-conventions": "1.23.0" 1927 - }, 1928 - "engines": { 1929 - "node": ">=14" 1930 - }, 1931 - "peerDependencies": { 1932 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1933 - } 1934 - }, 1935 - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { 1936 - "version": "0.50.0", 1937 - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.50.0.tgz", 1938 - "integrity": "sha512-vavD9Ow6yOLiD+ocuS/oeciCsXNdsN41aYUrEljNaLXogvnkfMhJ+JLAhOnRSpzlVtRp7Ciw2BYGdYSebR0OsA==", 1939 - "dependencies": { 1940 - "@opentelemetry/core": "1.23.0", 1941 - "@opentelemetry/otlp-exporter-base": "0.50.0", 1942 - "@opentelemetry/otlp-proto-exporter-base": "0.50.0", 1943 - "@opentelemetry/otlp-transformer": "0.50.0", 1944 - "@opentelemetry/resources": "1.23.0", 1945 - "@opentelemetry/sdk-trace-base": "1.23.0" 1946 - }, 1947 - "engines": { 1948 - "node": ">=14" 1949 - }, 1950 - "peerDependencies": { 1951 - "@opentelemetry/api": "^1.0.0" 1952 - } 1953 - }, 1954 - "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { 1955 - "version": "1.23.0", 1956 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 1957 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 1958 - "dependencies": { 1959 - "@opentelemetry/core": "1.23.0", 1960 - "@opentelemetry/semantic-conventions": "1.23.0" 1961 - }, 1962 - "engines": { 1963 - "node": ">=14" 1964 - }, 1965 - "peerDependencies": { 1966 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1967 - } 1968 - }, 1969 - "node_modules/@opentelemetry/exporter-zipkin": { 1970 - "version": "1.23.0", 1971 - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.23.0.tgz", 1972 - "integrity": "sha512-2LOGvNUGONuIcWhynFaJorVyqv03uZkURScciLmOxvBf2lWTNPEj77br1dCpShIWBM+YlrH7Tc+JXAs+GC7DqA==", 1973 - "dependencies": { 1974 - "@opentelemetry/core": "1.23.0", 1975 - "@opentelemetry/resources": "1.23.0", 1976 - "@opentelemetry/sdk-trace-base": "1.23.0", 1977 - "@opentelemetry/semantic-conventions": "1.23.0" 1978 - }, 1979 - "engines": { 1980 - "node": ">=14" 1981 - }, 1982 - "peerDependencies": { 1983 - "@opentelemetry/api": "^1.0.0" 1984 - } 1985 - }, 1986 - "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": { 1987 - "version": "1.23.0", 1988 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 1989 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 1990 - "dependencies": { 1991 - "@opentelemetry/core": "1.23.0", 1992 - "@opentelemetry/semantic-conventions": "1.23.0" 1993 - }, 1994 - "engines": { 1995 - "node": ">=14" 1996 - }, 1997 - "peerDependencies": { 1998 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 1999 - } 2000 - }, 2001 - "node_modules/@opentelemetry/instrumentation": { 2002 - "version": "0.50.0", 2003 - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.50.0.tgz", 2004 - "integrity": "sha512-bhGhbJiZKpuu7wTaSak4hyZcFPlnDeuSF/2vglze8B4w2LubcSbbOnkVTzTs5SXtzh4Xz8eRjaNnAm+u2GYufQ==", 2005 - "dependencies": { 2006 - "@opentelemetry/api-logs": "0.50.0", 2007 - "@types/shimmer": "^1.0.2", 2008 - "import-in-the-middle": "1.7.1", 2009 - "require-in-the-middle": "^7.1.1", 2010 - "semver": "^7.5.2", 2011 - "shimmer": "^1.2.1" 2012 - }, 2013 - "engines": { 2014 - "node": ">=14" 2015 - }, 2016 - "peerDependencies": { 2017 - "@opentelemetry/api": "^1.3.0" 2018 - } 2019 - }, 2020 - "node_modules/@opentelemetry/instrumentation-http": { 2021 - "version": "0.50.0", 2022 - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.50.0.tgz", 2023 - "integrity": "sha512-bsd6Nv0FtN9C6M6vX/kgPzvJY9UhJc4CZZNvqDbsfVQv3/MWvPrYgthf41AhrehqeDnpfn/QGzNKtdWUduGanQ==", 2024 - "dependencies": { 2025 - "@opentelemetry/core": "1.23.0", 2026 - "@opentelemetry/instrumentation": "0.50.0", 2027 - "@opentelemetry/semantic-conventions": "1.23.0", 2028 - "semver": "^7.5.2" 2029 - }, 2030 - "engines": { 2031 - "node": ">=14" 2032 - }, 2033 - "peerDependencies": { 2034 - "@opentelemetry/api": "^1.3.0" 2035 - } 2036 - }, 2037 - "node_modules/@opentelemetry/otlp-exporter-base": { 2038 - "version": "0.50.0", 2039 - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.50.0.tgz", 2040 - "integrity": "sha512-JUmjmrCmE1/fc4LjCQMqLfudgSl5OpUkzx7iA94b4jgeODM7zWxUoVXL7/CT7fWf47Cn+pmKjMvTCSESqZZ3mA==", 2041 - "dependencies": { 2042 - "@opentelemetry/core": "1.23.0" 2043 - }, 2044 - "engines": { 2045 - "node": ">=14" 2046 - }, 2047 - "peerDependencies": { 2048 - "@opentelemetry/api": "^1.0.0" 2049 - } 2050 - }, 2051 - "node_modules/@opentelemetry/otlp-grpc-exporter-base": { 2052 - "version": "0.50.0", 2053 - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.50.0.tgz", 2054 - "integrity": "sha512-J500AczSD7xEsjXpwNzSh5HQqxW73PT3CCNsi1VEWCE+8UPgVfkHYIGRHGoch35DV+CMe1svbi7gAk3e5eCSVA==", 2055 - "dependencies": { 2056 - "@grpc/grpc-js": "^1.7.1", 2057 - "@opentelemetry/core": "1.23.0", 2058 - "@opentelemetry/otlp-exporter-base": "0.50.0", 2059 - "protobufjs": "^7.2.3" 2060 - }, 2061 - "engines": { 2062 - "node": ">=14" 2063 - }, 2064 - "peerDependencies": { 2065 - "@opentelemetry/api": "^1.0.0" 2066 - } 2067 - }, 2068 - "node_modules/@opentelemetry/otlp-proto-exporter-base": { 2069 - "version": "0.50.0", 2070 - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-proto-exporter-base/-/otlp-proto-exporter-base-0.50.0.tgz", 2071 - "integrity": "sha512-hlbn3eZbhxoK79Sq1ddj1f7qcx+PzsPQC/SFpJvaWgTaqacCbqJmpzWDKfRRCAC7iGX2Hj/sgpf8vysazqyMOw==", 2072 - "dependencies": { 2073 - "@opentelemetry/core": "1.23.0", 2074 - "@opentelemetry/otlp-exporter-base": "0.50.0", 2075 - "protobufjs": "^7.2.3" 2076 - }, 2077 - "engines": { 2078 - "node": ">=14" 2079 - }, 2080 - "peerDependencies": { 2081 - "@opentelemetry/api": "^1.0.0" 2082 - } 2083 - }, 2084 - "node_modules/@opentelemetry/otlp-transformer": { 2085 - "version": "0.50.0", 2086 - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.50.0.tgz", 2087 - "integrity": "sha512-s0sl1Yfqd5q1Kjrf6DqXPWzErL+XHhrXOfejh4Vc/SMTNqC902xDsC8JQxbjuramWt/+hibfguIvi7Ns8VLolA==", 2088 - "dependencies": { 2089 - "@opentelemetry/api-logs": "0.50.0", 2090 - "@opentelemetry/core": "1.23.0", 2091 - "@opentelemetry/resources": "1.23.0", 2092 - "@opentelemetry/sdk-logs": "0.50.0", 2093 - "@opentelemetry/sdk-metrics": "1.23.0", 2094 - "@opentelemetry/sdk-trace-base": "1.23.0" 2095 - }, 2096 - "engines": { 2097 - "node": ">=14" 2098 - }, 2099 - "peerDependencies": { 2100 - "@opentelemetry/api": ">=1.3.0 <1.9.0" 2101 - } 2102 - }, 2103 - "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { 2104 - "version": "1.23.0", 2105 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 2106 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 2107 - "dependencies": { 2108 - "@opentelemetry/core": "1.23.0", 2109 - "@opentelemetry/semantic-conventions": "1.23.0" 2110 - }, 2111 - "engines": { 2112 - "node": ">=14" 2113 - }, 2114 - "peerDependencies": { 2115 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2116 - } 2117 - }, 2118 - "node_modules/@opentelemetry/propagator-b3": { 2119 - "version": "1.24.1", 2120 - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.24.1.tgz", 2121 - "integrity": "sha512-nda97ZwhpZKyUJTXqQuKzNhPMUgMLunbbGWn8kroBwegn+nh6OhtyGkrVQsQLNdVKJl0KeB5z0ZgeWszrYhwFw==", 2122 - "dependencies": { 2123 - "@opentelemetry/core": "1.24.1" 2124 - }, 2125 - "engines": { 2126 - "node": ">=14" 2127 - }, 2128 - "peerDependencies": { 2129 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2130 - } 2131 - }, 2132 - "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/core": { 2133 - "version": "1.24.1", 2134 - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.1.tgz", 2135 - "integrity": "sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==", 2136 - "dependencies": { 2137 - "@opentelemetry/semantic-conventions": "1.24.1" 2138 - }, 2139 - "engines": { 2140 - "node": ">=14" 2141 - }, 2142 - "peerDependencies": { 2143 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2144 - } 2145 - }, 2146 - "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/semantic-conventions": { 2147 - "version": "1.24.1", 2148 - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz", 2149 - "integrity": "sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==", 2150 - "engines": { 2151 - "node": ">=14" 2152 - } 2153 - }, 2154 - "node_modules/@opentelemetry/propagator-jaeger": { 2155 - "version": "1.24.1", 2156 - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.24.1.tgz", 2157 - "integrity": "sha512-7bRBJn3FG1l195A1m+xXRHvgzAOBsfmRi9uZ5Da18oTh7BLmNDiA8+kpk51FpTsU1PCikPVpRDNPhKVB6lyzZg==", 2158 - "dependencies": { 2159 - "@opentelemetry/core": "1.24.1" 2160 - }, 2161 - "engines": { 2162 - "node": ">=14" 2163 - }, 2164 - "peerDependencies": { 2165 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2166 - } 2167 - }, 2168 - "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": { 2169 - "version": "1.24.1", 2170 - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.1.tgz", 2171 - "integrity": "sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==", 2172 - "dependencies": { 2173 - "@opentelemetry/semantic-conventions": "1.24.1" 2174 - }, 2175 - "engines": { 2176 - "node": ">=14" 2177 - }, 2178 - "peerDependencies": { 2179 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2180 - } 2181 - }, 2182 - "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/semantic-conventions": { 2183 - "version": "1.24.1", 2184 - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz", 2185 - "integrity": "sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==", 2186 - "engines": { 2187 - "node": ">=14" 2188 - } 2189 - }, 2190 - "node_modules/@opentelemetry/resource-detector-aws": { 2191 - "version": "1.5.0", 2192 - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.5.0.tgz", 2193 - "integrity": "sha512-JNk/kSzzNQaiMo/F0b/bm8S3Qtr/m89BckN9B4U/cPHSqKLdxX03vgRBOqkXJ5KlAD8kc6K1Etcr8QfvGw6+uA==", 2194 - "dependencies": { 2195 - "@opentelemetry/core": "^1.0.0", 2196 - "@opentelemetry/resources": "^1.0.0", 2197 - "@opentelemetry/semantic-conventions": "^1.22.0" 2198 - }, 2199 - "engines": { 2200 - "node": ">=14" 2201 - }, 2202 - "peerDependencies": { 2203 - "@opentelemetry/api": "^1.0.0" 2204 - } 2205 - }, 2206 - "node_modules/@opentelemetry/resources": { 2207 - "version": "1.24.1", 2208 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.1.tgz", 2209 - "integrity": "sha512-cyv0MwAaPF7O86x5hk3NNgenMObeejZFLJJDVuSeSMIsknlsj3oOZzRv3qSzlwYomXsICfBeFFlxwHQte5mGXQ==", 2210 - "dependencies": { 2211 - "@opentelemetry/core": "1.24.1", 2212 - "@opentelemetry/semantic-conventions": "1.24.1" 2213 - }, 2214 - "engines": { 2215 - "node": ">=14" 2216 - }, 2217 - "peerDependencies": { 2218 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2219 - } 2220 - }, 2221 - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { 2222 - "version": "1.24.1", 2223 - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.1.tgz", 2224 - "integrity": "sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==", 2225 - "dependencies": { 2226 - "@opentelemetry/semantic-conventions": "1.24.1" 2227 - }, 2228 - "engines": { 2229 - "node": ">=14" 2230 - }, 2231 - "peerDependencies": { 2232 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2233 - } 2234 - }, 2235 - "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { 2236 - "version": "1.24.1", 2237 - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz", 2238 - "integrity": "sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==", 2239 - "engines": { 2240 - "node": ">=14" 2241 - } 2242 - }, 2243 - "node_modules/@opentelemetry/sdk-logs": { 2244 - "version": "0.50.0", 2245 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.50.0.tgz", 2246 - "integrity": "sha512-PeUEupBB29p9nlPNqXoa1PUWNLsZnxG0DCDj3sHqzae+8y76B/A5hvZjg03ulWdnvBLYpnJslqzylG9E0IL87g==", 2247 - "dependencies": { 2248 - "@opentelemetry/core": "1.23.0", 2249 - "@opentelemetry/resources": "1.23.0" 2250 - }, 2251 - "engines": { 2252 - "node": ">=14" 2253 - }, 2254 - "peerDependencies": { 2255 - "@opentelemetry/api": ">=1.4.0 <1.9.0", 2256 - "@opentelemetry/api-logs": ">=0.39.1" 2257 - } 2258 - }, 2259 - "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { 2260 - "version": "1.23.0", 2261 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 2262 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 2263 - "dependencies": { 2264 - "@opentelemetry/core": "1.23.0", 2265 - "@opentelemetry/semantic-conventions": "1.23.0" 2266 - }, 2267 - "engines": { 2268 - "node": ">=14" 2269 - }, 2270 - "peerDependencies": { 2271 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2272 - } 2273 - }, 2274 - "node_modules/@opentelemetry/sdk-metrics": { 2275 - "version": "1.23.0", 2276 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.23.0.tgz", 2277 - "integrity": "sha512-4OkvW6+wST4h6LFG23rXSTf6nmTf201h9dzq7bE0z5R9ESEVLERZz6WXwE7PSgg1gdjlaznm1jLJf8GttypFDg==", 2278 - "dependencies": { 2279 - "@opentelemetry/core": "1.23.0", 2280 - "@opentelemetry/resources": "1.23.0", 2281 - "lodash.merge": "^4.6.2" 2282 - }, 2283 - "engines": { 2284 - "node": ">=14" 2285 - }, 2286 - "peerDependencies": { 2287 - "@opentelemetry/api": ">=1.3.0 <1.9.0" 2288 - } 2289 - }, 2290 - "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { 2291 - "version": "1.23.0", 2292 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 2293 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 2294 - "dependencies": { 2295 - "@opentelemetry/core": "1.23.0", 2296 - "@opentelemetry/semantic-conventions": "1.23.0" 2297 - }, 2298 - "engines": { 2299 - "node": ">=14" 2300 - }, 2301 - "peerDependencies": { 2302 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2303 - } 2304 - }, 2305 - "node_modules/@opentelemetry/sdk-node": { 2306 - "version": "0.50.0", 2307 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.50.0.tgz", 2308 - "integrity": "sha512-LhIXHnvcnhRYcPwG9VG4G6lJ7x4ElYF6UYHHmXA7e4ZWzSUEFmAPfR1IBWv358aD1KwffcEBu7J6zeAR7lPZag==", 2309 - "dependencies": { 2310 - "@opentelemetry/api-logs": "0.50.0", 2311 - "@opentelemetry/core": "1.23.0", 2312 - "@opentelemetry/exporter-trace-otlp-grpc": "0.50.0", 2313 - "@opentelemetry/exporter-trace-otlp-http": "0.50.0", 2314 - "@opentelemetry/exporter-trace-otlp-proto": "0.50.0", 2315 - "@opentelemetry/exporter-zipkin": "1.23.0", 2316 - "@opentelemetry/instrumentation": "0.50.0", 2317 - "@opentelemetry/resources": "1.23.0", 2318 - "@opentelemetry/sdk-logs": "0.50.0", 2319 - "@opentelemetry/sdk-metrics": "1.23.0", 2320 - "@opentelemetry/sdk-trace-base": "1.23.0", 2321 - "@opentelemetry/sdk-trace-node": "1.23.0", 2322 - "@opentelemetry/semantic-conventions": "1.23.0" 2323 - }, 2324 - "engines": { 2325 - "node": ">=14" 2326 - }, 2327 - "peerDependencies": { 2328 - "@opentelemetry/api": ">=1.3.0 <1.9.0" 2329 - } 2330 - }, 2331 - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/context-async-hooks": { 2332 - "version": "1.23.0", 2333 - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.23.0.tgz", 2334 - "integrity": "sha512-wazGJZDRevibOJ+VgyrT+9+8sybZAxpZx2G7vy30OAtk92OpZCg7HgNxT11NUx0VBDWcRx1dOatMYGOVplQ7QA==", 2335 - "engines": { 2336 - "node": ">=14" 2337 - }, 2338 - "peerDependencies": { 2339 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2340 - } 2341 - }, 2342 - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/propagator-b3": { 2343 - "version": "1.23.0", 2344 - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.23.0.tgz", 2345 - "integrity": "sha512-cZ6rl8y2bdxYQ4e+zP2CQ+QmuPebaLBLO1skjFpj3eEu7zar+6hBzUP3llMOUupkQeQSwXz+4c8dZ26OhYfG/g==", 2346 - "dependencies": { 2347 - "@opentelemetry/core": "1.23.0" 2348 - }, 2349 - "engines": { 2350 - "node": ">=14" 2351 - }, 2352 - "peerDependencies": { 2353 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2354 - } 2355 - }, 2356 - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/propagator-jaeger": { 2357 - "version": "1.23.0", 2358 - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.23.0.tgz", 2359 - "integrity": "sha512-6iArixfgIl3ZgzeltQ5jyiKbjZygM+MbM84pXi1HL0Qs4x4Ck5rM6wEtjhZffFnlDMWEkEqrnM0xF6bTfbiMAQ==", 2360 - "dependencies": { 2361 - "@opentelemetry/core": "1.23.0" 2362 - }, 2363 - "engines": { 2364 - "node": ">=14" 2365 - }, 2366 - "peerDependencies": { 2367 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2368 - } 2369 - }, 2370 - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": { 2371 - "version": "1.23.0", 2372 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 2373 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 2374 - "dependencies": { 2375 - "@opentelemetry/core": "1.23.0", 2376 - "@opentelemetry/semantic-conventions": "1.23.0" 2377 - }, 2378 - "engines": { 2379 - "node": ">=14" 2380 - }, 2381 - "peerDependencies": { 2382 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2383 - } 2384 - }, 2385 - "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-trace-node": { 2386 - "version": "1.23.0", 2387 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.23.0.tgz", 2388 - "integrity": "sha512-dwnin5Go2r6VzJZkVc9JBPupssWp7j2EFto+S7qRkwQ00WDykWeq3x2Skk7I1Jr448FeBSvGCQVPgV5e6s6O3w==", 2389 - "dependencies": { 2390 - "@opentelemetry/context-async-hooks": "1.23.0", 2391 - "@opentelemetry/core": "1.23.0", 2392 - "@opentelemetry/propagator-b3": "1.23.0", 2393 - "@opentelemetry/propagator-jaeger": "1.23.0", 2394 - "@opentelemetry/sdk-trace-base": "1.23.0", 2395 - "semver": "^7.5.2" 2396 - }, 2397 - "engines": { 2398 - "node": ">=14" 2399 - }, 2400 - "peerDependencies": { 2401 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2402 - } 2403 - }, 2404 - "node_modules/@opentelemetry/sdk-trace-base": { 2405 - "version": "1.23.0", 2406 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.23.0.tgz", 2407 - "integrity": "sha512-PzBmZM8hBomUqvCddF/5Olyyviayka44O5nDWq673np3ctnvwMOvNrsUORZjKja1zJbwEuD9niAGbnVrz3jwRQ==", 2408 - "dependencies": { 2409 - "@opentelemetry/core": "1.23.0", 2410 - "@opentelemetry/resources": "1.23.0", 2411 - "@opentelemetry/semantic-conventions": "1.23.0" 2412 - }, 2413 - "engines": { 2414 - "node": ">=14" 2415 - }, 2416 - "peerDependencies": { 2417 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2418 - } 2419 - }, 2420 - "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { 2421 - "version": "1.23.0", 2422 - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.23.0.tgz", 2423 - "integrity": "sha512-iPRLfVfcEQynYGo7e4Di+ti+YQTAY0h5mQEUJcHlU9JOqpb4x965O6PZ+wMcwYVY63G96KtdS86YCM1BF1vQZg==", 2424 - "dependencies": { 2425 - "@opentelemetry/core": "1.23.0", 2426 - "@opentelemetry/semantic-conventions": "1.23.0" 2427 - }, 2428 - "engines": { 2429 - "node": ">=14" 2430 - }, 2431 - "peerDependencies": { 2432 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2433 - } 2434 - }, 2435 - "node_modules/@opentelemetry/sdk-trace-node": { 2436 - "version": "1.24.1", 2437 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.24.1.tgz", 2438 - "integrity": "sha512-/FZX8uWaGIAwsDhqI8VvQ+qWtfMNlXjaFYGc+vmxgdRFppCSSIRwrPyIhJO1qx61okyYhoyxVEZAfoiNxrfJCg==", 2439 - "dependencies": { 2440 - "@opentelemetry/context-async-hooks": "1.24.1", 2441 - "@opentelemetry/core": "1.24.1", 2442 - "@opentelemetry/propagator-b3": "1.24.1", 2443 - "@opentelemetry/propagator-jaeger": "1.24.1", 2444 - "@opentelemetry/sdk-trace-base": "1.24.1", 2445 - "semver": "^7.5.2" 2446 - }, 2447 - "engines": { 2448 - "node": ">=14" 2449 - }, 2450 - "peerDependencies": { 2451 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2452 - } 2453 - }, 2454 - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/core": { 2455 - "version": "1.24.1", 2456 - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.1.tgz", 2457 - "integrity": "sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==", 2458 - "dependencies": { 2459 - "@opentelemetry/semantic-conventions": "1.24.1" 2460 - }, 2461 - "engines": { 2462 - "node": ">=14" 2463 - }, 2464 - "peerDependencies": { 2465 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2466 - } 2467 - }, 2468 - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/sdk-trace-base": { 2469 - "version": "1.24.1", 2470 - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.1.tgz", 2471 - "integrity": "sha512-zz+N423IcySgjihl2NfjBf0qw1RWe11XIAWVrTNOSSI6dtSPJiVom2zipFB2AEEtJWpv0Iz6DY6+TjnyTV5pWg==", 2472 - "dependencies": { 2473 - "@opentelemetry/core": "1.24.1", 2474 - "@opentelemetry/resources": "1.24.1", 2475 - "@opentelemetry/semantic-conventions": "1.24.1" 2476 - }, 2477 - "engines": { 2478 - "node": ">=14" 2479 - }, 2480 - "peerDependencies": { 2481 - "@opentelemetry/api": ">=1.0.0 <1.9.0" 2482 - } 2483 - }, 2484 - "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/semantic-conventions": { 2485 - "version": "1.24.1", 2486 - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.1.tgz", 2487 - "integrity": "sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==", 2488 - "engines": { 2489 - "node": ">=14" 2490 - } 2491 - }, 2492 - "node_modules/@opentelemetry/semantic-conventions": { 2493 - "version": "1.23.0", 2494 - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.23.0.tgz", 2495 - "integrity": "sha512-MiqFvfOzfR31t8cc74CTP1OZfz7MbqpAnLCra8NqQoaHJX6ncIRTdYOQYBDQ2uFISDq0WY8Y9dDTWvsgzzBYRg==", 2496 - "engines": { 2497 - "node": ">=14" 2498 - } 2499 - }, 2500 1774 "node_modules/@pkgjs/parseargs": { 2501 1775 "version": "0.11.0", 2502 1776 "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", ··· 2507 1781 "node": ">=14" 2508 1782 } 2509 1783 }, 2510 - "node_modules/@protobufjs/aspromise": { 2511 - "version": "1.1.2", 2512 - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 2513 - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" 2514 - }, 2515 - "node_modules/@protobufjs/base64": { 2516 - "version": "1.1.2", 2517 - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 2518 - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 2519 - }, 2520 - "node_modules/@protobufjs/codegen": { 2521 - "version": "2.0.4", 2522 - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 2523 - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 2524 - }, 2525 - "node_modules/@protobufjs/eventemitter": { 2526 - "version": "1.1.0", 2527 - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 2528 - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" 2529 - }, 2530 - "node_modules/@protobufjs/fetch": { 2531 - "version": "1.1.0", 2532 - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 2533 - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", 2534 - "dependencies": { 2535 - "@protobufjs/aspromise": "^1.1.1", 2536 - "@protobufjs/inquire": "^1.1.0" 2537 - } 2538 - }, 2539 - "node_modules/@protobufjs/float": { 2540 - "version": "1.0.2", 2541 - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 2542 - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" 2543 - }, 2544 - "node_modules/@protobufjs/inquire": { 2545 - "version": "1.1.0", 2546 - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 2547 - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" 2548 - }, 2549 - "node_modules/@protobufjs/path": { 2550 - "version": "1.1.2", 2551 - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 2552 - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" 2553 - }, 2554 - "node_modules/@protobufjs/pool": { 2555 - "version": "1.1.0", 2556 - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 2557 - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" 2558 - }, 2559 - "node_modules/@protobufjs/utf8": { 2560 - "version": "1.1.0", 2561 - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 2562 - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" 2563 - }, 2564 1784 "node_modules/@radix-ui/number": { 2565 1785 "version": "1.0.1", 2566 1786 "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz", ··· 6107 5327 "tslib": "^2.4.0" 6108 5328 } 6109 5329 }, 6110 - "node_modules/@trpc/server": { 6111 - "version": "10.45.2", 6112 - "resolved": "https://registry.npmjs.org/@trpc/server/-/server-10.45.2.tgz", 6113 - "integrity": "sha512-wOrSThNNE4HUnuhJG6PfDRp4L2009KDVxsd+2VYH8ro6o/7/jwYZ8Uu5j+VaW+mOmc8EHerHzGcdbGNQSAUPgg==", 6114 - "funding": [ 6115 - "https://trpc.io/sponsor" 6116 - ], 6117 - "peer": true 6118 - }, 6119 5330 "node_modules/@types/acorn": { 6120 5331 "version": "4.0.6", 6121 5332 "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", ··· 6123 5334 "dependencies": { 6124 5335 "@types/estree": "*" 6125 5336 } 6126 - }, 6127 - "node_modules/@types/aws-lambda": { 6128 - "version": "8.10.138", 6129 - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.138.tgz", 6130 - "integrity": "sha512-71EHMl70TPWIAsFuHd85NHq6S6T2OOjiisPTrH7RgcjzpJpPh4RQJv7PvVvIxc6PIp8CLV7F9B+TdjcAES5vcA==" 6131 5337 }, 6132 5338 "node_modules/@types/debug": { 6133 5339 "version": "4.1.12", ··· 6226 5432 "dependencies": { 6227 5433 "@types/react": "*" 6228 5434 } 6229 - }, 6230 - "node_modules/@types/shimmer": { 6231 - "version": "1.0.5", 6232 - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", 6233 - "integrity": "sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==" 6234 5435 }, 6235 5436 "node_modules/@types/unist": { 6236 5437 "version": "3.0.2", ··· 6422 5623 "node": ">=14.6" 6423 5624 } 6424 5625 }, 5626 + "node_modules/@vercel/sdk": { 5627 + "version": "1.3.1", 5628 + "resolved": "https://registry.npmjs.org/@vercel/sdk/-/sdk-1.3.1.tgz", 5629 + "integrity": "sha512-lTzG17DIDEJlWaGRNVyLZ17p8NRMOE2U98Kg96r1q79LGC8nPthoWhxupHXxGk3eAjjsvp8OA3bncKEyCHcofg==", 5630 + "peerDependencies": { 5631 + "zod": ">= 3" 5632 + } 5633 + }, 6425 5634 "node_modules/acorn": { 6426 5635 "version": "8.11.3", 6427 5636 "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", ··· 6431 5640 }, 6432 5641 "engines": { 6433 5642 "node": ">=0.4.0" 6434 - } 6435 - }, 6436 - "node_modules/acorn-import-assertions": { 6437 - "version": "1.9.0", 6438 - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", 6439 - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", 6440 - "peerDependencies": { 6441 - "acorn": "^8" 6442 5643 } 6443 5644 }, 6444 5645 "node_modules/acorn-jsx": { ··· 6491 5692 "version": "5.0.1", 6492 5693 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 6493 5694 "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 5695 + "dev": true, 6494 5696 "engines": { 6495 5697 "node": ">=8" 6496 5698 } ··· 6499 5701 "version": "4.3.0", 6500 5702 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 6501 5703 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 5704 + "dev": true, 6502 5705 "dependencies": { 6503 5706 "color-convert": "^2.0.1" 6504 5707 }, ··· 7152 6355 "node": ">=18" 7153 6356 } 7154 6357 }, 7155 - "node_modules/cjs-module-lexer": { 7156 - "version": "1.3.1", 7157 - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", 7158 - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==" 7159 - }, 7160 6358 "node_modules/cli-color": { 7161 6359 "version": "2.0.4", 7162 6360 "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", ··· 7178 6376 "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", 7179 6377 "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" 7180 6378 }, 7181 - "node_modules/cliui": { 7182 - "version": "8.0.1", 7183 - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 7184 - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 7185 - "dependencies": { 7186 - "string-width": "^4.2.0", 7187 - "strip-ansi": "^6.0.1", 7188 - "wrap-ansi": "^7.0.0" 7189 - }, 7190 - "engines": { 7191 - "node": ">=12" 7192 - } 7193 - }, 7194 6379 "node_modules/clsx": { 7195 6380 "version": "2.1.1", 7196 6381 "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", ··· 7221 6406 "version": "2.0.1", 7222 6407 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 7223 6408 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 6409 + "dev": true, 7224 6410 "dependencies": { 7225 6411 "color-name": "~1.1.4" 7226 6412 }, ··· 7231 6417 "node_modules/color-name": { 7232 6418 "version": "1.1.4", 7233 6419 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 7234 - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 6420 + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 6421 + "dev": true 7235 6422 }, 7236 6423 "node_modules/colorjs.io": { 7237 6424 "version": "0.5.2", ··· 8060 7247 "version": "3.1.2", 8061 7248 "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", 8062 7249 "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", 7250 + "dev": true, 8063 7251 "engines": { 8064 7252 "node": ">=6" 8065 7253 } ··· 8766 7954 "url": "https://github.com/sponsors/sindresorhus" 8767 7955 } 8768 7956 }, 8769 - "node_modules/flat": { 8770 - "version": "6.0.1", 8771 - "resolved": "https://registry.npmjs.org/flat/-/flat-6.0.1.tgz", 8772 - "integrity": "sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==", 8773 - "bin": { 8774 - "flat": "cli.js" 8775 - }, 8776 - "engines": { 8777 - "node": ">=18" 8778 - } 8779 - }, 8780 7957 "node_modules/flat-cache": { 8781 7958 "version": "3.2.0", 8782 7959 "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", ··· 8940 8117 "dev": true, 8941 8118 "funding": { 8942 8119 "url": "https://github.com/sponsors/ljharb" 8943 - } 8944 - }, 8945 - "node_modules/get-caller-file": { 8946 - "version": "2.0.5", 8947 - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 8948 - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 8949 - "engines": { 8950 - "node": "6.* || 8.* || >= 10.*" 8951 8120 } 8952 8121 }, 8953 8122 "node_modules/get-intrinsic": { ··· 9616 8785 "url": "https://github.com/sponsors/sindresorhus" 9617 8786 } 9618 8787 }, 9619 - "node_modules/import-in-the-middle": { 9620 - "version": "1.7.1", 9621 - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", 9622 - "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", 9623 - "dependencies": { 9624 - "acorn": "^8.8.2", 9625 - "acorn-import-assertions": "^1.9.0", 9626 - "cjs-module-lexer": "^1.2.2", 9627 - "module-details-from-path": "^1.0.3" 9628 - } 9629 - }, 9630 8788 "node_modules/imurmurhash": { 9631 8789 "version": "0.1.4", 9632 8790 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", ··· 9800 8958 "version": "2.13.1", 9801 8959 "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", 9802 8960 "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", 8961 + "dev": true, 9803 8962 "dependencies": { 9804 8963 "hasown": "^2.0.0" 9805 8964 }, ··· 9871 9030 "version": "3.0.0", 9872 9031 "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 9873 9032 "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 9033 + "dev": true, 9874 9034 "engines": { 9875 9035 "node": ">=8" 9876 9036 } ··· 10387 9547 "url": "https://github.com/sponsors/sindresorhus" 10388 9548 } 10389 9549 }, 10390 - "node_modules/lodash.camelcase": { 10391 - "version": "4.3.0", 10392 - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", 10393 - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" 10394 - }, 10395 9550 "node_modules/lodash.includes": { 10396 9551 "version": "4.3.0", 10397 9552 "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", ··· 10431 9586 "node_modules/lodash.merge": { 10432 9587 "version": "4.6.2", 10433 9588 "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 10434 - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" 9589 + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 9590 + "dev": true 10435 9591 }, 10436 9592 "node_modules/lodash.once": { 10437 9593 "version": "4.1.1", ··· 10445 9601 "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", 10446 9602 "dev": true 10447 9603 }, 10448 - "node_modules/long": { 10449 - "version": "5.2.3", 10450 - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", 10451 - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" 10452 - }, 10453 9604 "node_modules/longest-streak": { 10454 9605 "version": "3.1.0", 10455 9606 "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", ··· 11727 10878 "url": "https://github.com/sponsors/isaacs" 11728 10879 } 11729 10880 }, 11730 - "node_modules/module-details-from-path": { 11731 - "version": "1.0.3", 11732 - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", 11733 - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" 11734 - }, 11735 10881 "node_modules/ms": { 11736 10882 "version": "2.1.2", 11737 10883 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", ··· 12249 11395 "node_modules/path-parse": { 12250 11396 "version": "1.0.7", 12251 11397 "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 12252 - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 11398 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 11399 + "dev": true 12253 11400 }, 12254 11401 "node_modules/path-scurry": { 12255 11402 "version": "1.11.1", ··· 12609 11756 "prosemirror-transform": "^1.1.0" 12610 11757 } 12611 11758 }, 12612 - "node_modules/protobufjs": { 12613 - "version": "7.3.0", 12614 - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.0.tgz", 12615 - "integrity": "sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g==", 12616 - "hasInstallScript": true, 12617 - "dependencies": { 12618 - "@protobufjs/aspromise": "^1.1.2", 12619 - "@protobufjs/base64": "^1.1.2", 12620 - "@protobufjs/codegen": "^2.0.4", 12621 - "@protobufjs/eventemitter": "^1.1.0", 12622 - "@protobufjs/fetch": "^1.1.0", 12623 - "@protobufjs/float": "^1.0.2", 12624 - "@protobufjs/inquire": "^1.1.0", 12625 - "@protobufjs/path": "^1.1.2", 12626 - "@protobufjs/pool": "^1.1.0", 12627 - "@protobufjs/utf8": "^1.1.0", 12628 - "@types/node": ">=13.7.0", 12629 - "long": "^5.0.0" 12630 - }, 12631 - "engines": { 12632 - "node": ">=12.0.0" 12633 - } 12634 - }, 12635 11759 "node_modules/proxy-from-env": { 12636 11760 "version": "1.1.0", 12637 11761 "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", ··· 13241 12365 "react-dom": ">=16.0 <19.0" 13242 12366 } 13243 12367 }, 13244 - "node_modules/require-directory": { 13245 - "version": "2.1.1", 13246 - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 13247 - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 13248 - "engines": { 13249 - "node": ">=0.10.0" 13250 - } 13251 - }, 13252 12368 "node_modules/require-from-string": { 13253 12369 "version": "2.0.2", 13254 12370 "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", ··· 13259 12375 "node": ">=0.10.0" 13260 12376 } 13261 12377 }, 13262 - "node_modules/require-in-the-middle": { 13263 - "version": "7.3.0", 13264 - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.3.0.tgz", 13265 - "integrity": "sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==", 13266 - "dependencies": { 13267 - "debug": "^4.1.1", 13268 - "module-details-from-path": "^1.0.3", 13269 - "resolve": "^1.22.1" 13270 - }, 13271 - "engines": { 13272 - "node": ">=8.6.0" 13273 - } 13274 - }, 13275 12378 "node_modules/resolve": { 13276 12379 "version": "1.22.8", 13277 12380 "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", 13278 12381 "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", 12382 + "dev": true, 13279 12383 "dependencies": { 13280 12384 "is-core-module": "^2.13.0", 13281 12385 "path-parse": "^1.0.7", ··· 13565 12669 "node": ">=8" 13566 12670 } 13567 12671 }, 13568 - "node_modules/shimmer": { 13569 - "version": "1.2.1", 13570 - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", 13571 - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" 13572 - }, 13573 12672 "node_modules/side-channel": { 13574 12673 "version": "1.0.6", 13575 12674 "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", ··· 13689 12788 "version": "4.2.3", 13690 12789 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 13691 12790 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 12791 + "dev": true, 13692 12792 "dependencies": { 13693 12793 "emoji-regex": "^8.0.0", 13694 12794 "is-fullwidth-code-point": "^3.0.0", ··· 13722 12822 "node_modules/string-width/node_modules/emoji-regex": { 13723 12823 "version": "8.0.0", 13724 12824 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 13725 - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 12825 + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 12826 + "dev": true 13726 12827 }, 13727 12828 "node_modules/string.prototype.matchall": { 13728 12829 "version": "4.0.11", ··· 13816 12917 "version": "6.0.1", 13817 12918 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 13818 12919 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 12920 + "dev": true, 13819 12921 "dependencies": { 13820 12922 "ansi-regex": "^5.0.1" 13821 12923 }, ··· 13995 13097 "version": "1.0.0", 13996 13098 "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 13997 13099 "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 13100 + "dev": true, 13998 13101 "engines": { 13999 13102 "node": ">= 0.4" 14000 13103 }, ··· 14377 13480 }, 14378 13481 "funding": { 14379 13482 "url": "https://github.com/sponsors/ljharb" 14380 - } 14381 - }, 14382 - "node_modules/undici": { 14383 - "version": "6.18.1", 14384 - "resolved": "https://registry.npmjs.org/undici/-/undici-6.18.1.tgz", 14385 - "integrity": "sha512-/0BWqR8rJNRysS5lqVmfc7eeOErcOP4tZpATVjJOojjHZ71gSYVAtFhEmadcIjwMIUehh5NFyKGsXCnXIajtbA==", 14386 - "engines": { 14387 - "node": ">=18.17" 14388 13483 } 14389 13484 }, 14390 13485 "node_modules/undici-types": { ··· 15238 14333 "@esbuild/win32-x64": "0.17.19" 15239 14334 } 15240 14335 }, 15241 - "node_modules/wrap-ansi": { 15242 - "version": "7.0.0", 15243 - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 15244 - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 15245 - "dependencies": { 15246 - "ansi-styles": "^4.0.0", 15247 - "string-width": "^4.1.0", 15248 - "strip-ansi": "^6.0.0" 15249 - }, 15250 - "engines": { 15251 - "node": ">=10" 15252 - }, 15253 - "funding": { 15254 - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 15255 - } 15256 - }, 15257 14336 "node_modules/wrap-ansi-cjs": { 15258 14337 "name": "wrap-ansi", 15259 14338 "version": "7.0.0", ··· 15369 14448 "yjs": "^13.0.0" 15370 14449 } 15371 14450 }, 15372 - "node_modules/y18n": { 15373 - "version": "5.0.8", 15374 - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 15375 - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 15376 - "engines": { 15377 - "node": ">=10" 15378 - } 15379 - }, 15380 14451 "node_modules/yallist": { 15381 14452 "version": "5.0.0", 15382 14453 "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", ··· 15398 14469 "node": ">= 14" 15399 14470 } 15400 14471 }, 15401 - "node_modules/yargs": { 15402 - "version": "17.7.2", 15403 - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 15404 - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 15405 - "dependencies": { 15406 - "cliui": "^8.0.1", 15407 - "escalade": "^3.1.1", 15408 - "get-caller-file": "^2.0.5", 15409 - "require-directory": "^2.1.1", 15410 - "string-width": "^4.2.3", 15411 - "y18n": "^5.0.5", 15412 - "yargs-parser": "^21.1.1" 15413 - }, 15414 - "engines": { 15415 - "node": ">=12" 15416 - } 15417 - }, 15418 - "node_modules/yargs-parser": { 15419 - "version": "21.1.1", 15420 - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 15421 - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 15422 - "engines": { 15423 - "node": ">=12" 15424 - } 15425 - }, 15426 14472 "node_modules/yjs": { 15427 14473 "version": "13.6.15", 15428 14474 "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.15.tgz", ··· 15466 14512 "version": "3.23.8", 15467 14513 "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", 15468 14514 "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", 15469 - "dev": true, 15470 14515 "funding": { 15471 14516 "url": "https://github.com/sponsors/colinhacks" 15472 14517 }
+1
package.json
··· 26 26 "@types/mdx": "^2.0.13", 27 27 "@vercel/analytics": "^1.3.1", 28 28 "@vercel/kv": "^1.0.1", 29 + "@vercel/sdk": "^1.3.1", 29 30 "base64-js": "^1.5.1", 30 31 "colorjs.io": "^0.5.2", 31 32 "drizzle-orm": "^0.30.10",
-12
src/hooks/useRSVPData.ts
··· 1 - import { getRSVPData } from "actions/getRSVPData"; 2 - import { useReplicache } from "src/replicache"; 3 - import useSWR from "swr"; 4 - 5 - export function useRSVPData() { 6 - let { permission_token } = useReplicache(); 7 - return useSWR(`rsvp_data`, () => 8 - getRSVPData( 9 - permission_token.permission_token_rights.map((pr) => pr.entity_set), 10 - ), 11 - ); 12 - }
+15 -5
supabase/database.types.ts
··· 37 37 custom_domain_routes: { 38 38 Row: { 39 39 domain: string 40 + edit_permission_token: string 40 41 id: string 41 - permission_token: string 42 42 route: string 43 + view_permission_token: string 43 44 } 44 45 Insert: { 45 46 domain: string 47 + edit_permission_token: string 46 48 id?: string 47 - permission_token: string 48 49 route: string 50 + view_permission_token: string 49 51 } 50 52 Update: { 51 53 domain?: string 54 + edit_permission_token?: string 52 55 id?: string 53 - permission_token?: string 54 56 route?: string 57 + view_permission_token?: string 55 58 } 56 59 Relationships: [ 57 60 { ··· 62 65 referencedColumns: ["domain"] 63 66 }, 64 67 { 65 - foreignKeyName: "custom_domain_routes_permission_token_fkey" 66 - columns: ["permission_token"] 68 + foreignKeyName: "custom_domain_routes_edit_permission_token_fkey" 69 + columns: ["edit_permission_token"] 70 + isOneToOne: false 71 + referencedRelation: "permission_tokens" 72 + referencedColumns: ["id"] 73 + }, 74 + { 75 + foreignKeyName: "custom_domain_routes_view_permission_token_fkey" 76 + columns: ["view_permission_token"] 67 77 isOneToOne: false 68 78 referencedRelation: "permission_tokens" 69 79 referencedColumns: ["id"]
-2
supabase/migrations/20250117172835_add_custom_domain_tables.sql
··· 14 14 15 15 alter table "public"."custom_domains" enable row level security; 16 16 17 - alter table "public"."phone_rsvps_to_entity" add column "plus_ones" smallint not null default '0'::smallint; 18 - 19 17 CREATE UNIQUE INDEX custom_domain_routes_domain_route_key ON public.custom_domain_routes USING btree (domain, route); 20 18 21 19 CREATE UNIQUE INDEX custom_domain_routes_pkey ON public.custom_domain_routes USING btree (id);
+15
supabase/migrations/20250122165617_add_edit_tokens_to_custom_domain_routes.sql
··· 1 + alter table "public"."custom_domain_routes" drop constraint "custom_domain_routes_permission_token_fkey"; 2 + 3 + alter table "public"."custom_domain_routes" drop column "permission_token"; 4 + 5 + alter table "public"."custom_domain_routes" add column "edit_permission_token" uuid not null; 6 + 7 + alter table "public"."custom_domain_routes" add column "view_permission_token" uuid not null; 8 + 9 + alter table "public"."custom_domain_routes" add constraint "custom_domain_routes_edit_permission_token_fkey" FOREIGN KEY (edit_permission_token) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; 10 + 11 + alter table "public"."custom_domain_routes" validate constraint "custom_domain_routes_edit_permission_token_fkey"; 12 + 13 + alter table "public"."custom_domain_routes" add constraint "custom_domain_routes_view_permission_token_fkey" FOREIGN KEY (view_permission_token) REFERENCES permission_tokens(id) ON UPDATE CASCADE ON DELETE CASCADE not valid; 14 + 15 + alter table "public"."custom_domain_routes" validate constraint "custom_domain_routes_view_permission_token_fkey";
+1 -1
tailwind.config.js
··· 53 53 xs: ".75rem", 54 54 sm: ".875rem", 55 55 base: "1rem", 56 - lg: "1.25rem", 56 + lg: "1.125rem", 57 57 xl: "1.625rem", 58 58 "2xl": "2rem", 59 59 },