This commit is contained in:
David Nguyen
2025-02-07 00:58:50 +11:00
parent e5cc6455dd
commit 8373af3f41
34 changed files with 193 additions and 143 deletions

View File

@ -1,4 +1,5 @@
import { Outlet, redirect } from 'react-router';
import { Outlet } from 'react-router';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { getLimits } from '@documenso/ee/server-only/limits/client';
import { LimitsProvider } from '@documenso/ee/server-only/limits/provider/client';
@ -11,29 +12,25 @@ import { VerifyEmailBanner } from '~/components/general/verify-email-banner';
import type { Route } from './+types/_layout';
export const loader = async ({ request, context }: Route.LoaderArgs) => {
const { session } = context;
if (!session) {
throw redirect('/signin');
}
export const loader = async ({ request }: Route.LoaderArgs) => {
const { user, teams, currentTeam } = getLoaderSession();
const requestHeaders = Object.fromEntries(request.headers.entries());
// Todo: Should only load this on first render.
const [limits, banner] = await Promise.all([
getLimits({ headers: requestHeaders, teamId: session.currentTeam?.id }),
getLimits({ headers: requestHeaders, teamId: currentTeam?.id }),
getSiteSettings().then((settings) =>
settings.find((setting) => setting.id === SITE_SETTINGS_BANNER_ID),
),
]);
return {
user: session.user,
teams: session.teams,
user,
teams,
banner,
limits,
teamId: session.currentTeam?.id,
teamId: currentTeam?.id,
};
};

View File

@ -1,16 +1,14 @@
import { Trans } from '@lingui/macro';
import { BarChart3, FileStack, Settings, Trophy, Users, Wallet2 } from 'lucide-react';
import { Link, Outlet, redirect, useLocation } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
import type { Route } from './+types/_layout';
export function loader({ context }: Route.LoaderArgs) {
const { user } = getRequiredLoaderSession(context);
export function loader() {
const { user } = getLoaderSession();
if (!user || !isAdmin(user)) {
throw redirect('/documents');

View File

@ -3,7 +3,7 @@ import { useLingui } from '@lingui/react';
import { DocumentStatus, TeamMemberRole } from '@prisma/client';
import { ChevronLeft, Clock9, Users2 } from 'lucide-react';
import { Link, redirect } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { useSession } from '@documenso/lib/client-only/providers/session';
@ -34,8 +34,8 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/$id._index';
export async function loader({ params, context }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderSession(context);
export async function loader({ params }: Route.LoaderArgs) {
const { user, currentTeam: team } = getLoaderSession();
const { id } = params;

View File

@ -2,7 +2,7 @@ import { Plural, Trans } from '@lingui/macro';
import { DocumentStatus as InternalDocumentStatus, TeamMemberRole } from '@prisma/client';
import { ChevronLeft, Users2 } from 'lucide-react';
import { Link, redirect } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
@ -17,8 +17,8 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/$id.edit';
export async function loader({ params, context }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderSession(context);
export async function loader({ params }: Route.LoaderArgs) {
const { user, currentTeam: team } = getLoaderSession();
const { id } = params;

View File

@ -5,7 +5,7 @@ import type { Recipient } from '@prisma/client';
import { ChevronLeft } from 'lucide-react';
import { DateTime } from 'luxon';
import { Link, redirect } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document';
@ -22,10 +22,10 @@ import { DocumentLogsTable } from '~/components/tables/document-logs-table';
import type { Route } from './+types/$id.logs';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const { id } = params;
const { user, currentTeam: team } = getRequiredLoaderSession(context);
const { user, currentTeam: team } = getLoaderSession();
const documentId = Number(id);

View File

@ -4,7 +4,7 @@ import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import type { TemplateDirectLink } from '@prisma/client';
import { TemplateType } from '@prisma/client';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { useSession } from '@documenso/lib/client-only/providers/session';
import { getUserPublicProfile } from '@documenso/lib/server-only/user/get-user-public-profile';
@ -43,8 +43,8 @@ const teamProfileText = {
templatesSubtitle: msg`Show templates in your team public profile for your audience to sign and get started quickly`,
};
export async function loader({ context }: Route.LoaderArgs) {
const { user } = getRequiredLoaderSession(context);
export async function loader() {
const { user } = getLoaderSession();
const { profile } = await getUserPublicProfile({
userId: user.id,

View File

@ -1,13 +1,13 @@
import { redirect } from 'react-router';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { formatDocumentsPath } from '@documenso/lib/utils/teams';
import type { Route } from './+types/_index';
export function loader({ context }: Route.LoaderArgs) {
if (!context.session?.currentTeam) {
export function loader() {
const { currentTeam } = getLoaderSession();
if (!currentTeam) {
throw redirect('/documents');
}
throw redirect(formatDocumentsPath(context.session.currentTeam.url));
throw redirect(formatDocumentsPath(currentTeam.url));
}

View File

@ -3,7 +3,7 @@ import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { ChevronLeft } from 'lucide-react';
import { Link, Outlet, isRouteErrorResponse, redirect, useNavigate } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { AppErrorCode } from '@documenso/lib/errors/app-error';
@ -14,8 +14,8 @@ import { TeamProvider } from '~/providers/team';
import type { Route } from './+types/_layout';
export const loader = ({ context }: Route.LoaderArgs) => {
const { currentTeam } = getRequiredLoaderSession(context);
export const loader = () => {
const { currentTeam } = getLoaderSession();
if (!currentTeam) {
throw redirect('/documents');

View File

@ -1,16 +1,14 @@
import { Trans } from '@lingui/macro';
import { Outlet } from 'react-router';
import { getRequiredLoaderTeamSession } from 'server/utils/get-loader-session';
import { getLoaderTeamSession } from 'server/utils/get-loader-session';
import { canExecuteTeamAction } from '@documenso/lib/utils/teams';
import { TeamSettingsNavDesktop } from '~/components/general/teams/team-settings-nav-desktop';
import { TeamSettingsNavMobile } from '~/components/general/teams/team-settings-nav-mobile';
import type { Route } from '../+types/_layout';
export function loader({ context }: Route.LoaderArgs) {
const { currentTeam: team } = getRequiredLoaderTeamSession(context);
export function loader() {
const { currentTeam: team } = getLoaderTeamSession();
if (!team || !canExecuteTeamAction('MANAGE_TEAM', team.currentTeamMember.role)) {
throw new Response(null, { status: 401 }); // Unauthorized.

View File

@ -1,7 +1,7 @@
import { Plural, Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { DateTime } from 'luxon';
import { getRequiredLoaderTeamSession } from 'server/utils/get-loader-session';
import { getLoaderTeamSession } from 'server/utils/get-loader-session';
import type Stripe from 'stripe';
import { match } from 'ts-pattern';
@ -15,8 +15,8 @@ import { TeamSettingsBillingInvoicesTable } from '~/components/tables/team-setti
import type { Route } from './+types/billing';
export async function loader({ context }: Route.LoaderArgs) {
const { currentTeam: team } = getRequiredLoaderTeamSession(context);
export async function loader() {
const { currentTeam: team } = getLoaderTeamSession();
let teamSubscription: Stripe.Subscription | null = null;

View File

@ -1,13 +1,11 @@
import { getRequiredLoaderTeamSession } from 'server/utils/get-loader-session';
import { getLoaderTeamSession } from 'server/utils/get-loader-session';
import { getTeamPublicProfile } from '@documenso/lib/server-only/team/get-team-public-profile';
import PublicProfilePage from '~/routes/_authenticated+/settings+/public-profile+/index';
import type { Route } from './+types/public-profile';
export async function loader({ context }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderTeamSession(context);
export async function loader() {
const { user, currentTeam: team } = getLoaderTeamSession();
const { profile } = await getTeamPublicProfile({
userId: user.id,

View File

@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { DateTime } from 'luxon';
import { getRequiredLoaderTeamSession } from 'server/utils/get-loader-session';
import { getLoaderTeamSession } from 'server/utils/get-loader-session';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { getTeamTokens } from '@documenso/lib/server-only/public-api/get-all-team-tokens';
@ -12,8 +12,8 @@ import { ApiTokenForm } from '~/components/forms/token';
import type { Route } from './+types/tokens';
export async function loader({ context }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderTeamSession(context);
export async function loader() {
const { user, currentTeam: team } = getLoaderTeamSession();
const tokens = await getTeamTokens({ userId: user.id, teamId: team.id }).catch(() => null);

View File

@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro';
import { DocumentSigningOrder, SigningStatus } from '@prisma/client';
import { ChevronLeft, LucideEdit } from 'lucide-react';
import { Link, redirect, useNavigate } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { formatDocumentsPath, formatTemplatesPath } from '@documenso/lib/utils/teams';
@ -24,8 +24,8 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/$id._index';
export async function loader({ params, context }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderSession(context);
export async function loader({ params }: Route.LoaderArgs) {
const { user, currentTeam: team } = getLoaderSession();
const { id } = params;

View File

@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro';
import { ChevronLeft } from 'lucide-react';
import { Link, redirect } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
@ -15,8 +15,8 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import { TemplateDirectLinkDialogWrapper } from '../../../components/dialogs/template-direct-link-dialog-wrapper';
import type { Route } from './+types/$id.edit';
export async function loader({ context, params }: Route.LoaderArgs) {
const { user, currentTeam: team } = getRequiredLoaderSession(context);
export async function loader({ params }: Route.LoaderArgs) {
const { user, currentTeam: team } = getLoaderSession();
const { id } = params;

View File

@ -1,9 +1,10 @@
import { redirect } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import type { Route } from './+types/_index';
export function loader() {
const session = getOptionalLoaderSession();
export function loader({ context }: Route.LoaderArgs) {
if (context.session) {
if (session) {
throw redirect('/documents');
}

View File

@ -6,24 +6,15 @@ import { ChevronLeft } from 'lucide-react';
import { Link, Outlet } from 'react-router';
import LogoIcon from '@documenso/assets/logo_icon.png';
import { useSession } from '@documenso/lib/client-only/providers/session';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
import { Header as AuthenticatedHeader } from '~/components/general/app-header';
import { Logo } from '~/components/general/branding-logo';
import { BrandingLogo } from '~/components/general/branding-logo';
import type { Route } from './+types/_layout';
export function loader({ context }: Route.LoaderArgs) {
const { session } = context;
return {
session,
};
}
export default function PublicProfileLayout({ loaderData }: Route.ComponentProps) {
const { session } = loaderData;
export default function PublicProfileLayout() {
const session = useSession();
const [scrollY, setScrollY] = useState(0);
@ -53,7 +44,7 @@ export default function PublicProfileLayout({ loaderData }: Route.ComponentProps
to="/"
className="focus-visible:ring-ring ring-offset-background rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 md:inline"
>
<Logo className="hidden h-6 w-auto sm:block" />
<BrandingLogo className="hidden h-6 w-auto sm:block" />
<img
src={LogoIcon}

View File

@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro';
import { ChevronLeft } from 'lucide-react';
import { Link, Outlet } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { Button } from '@documenso/ui/primitives/button';
@ -8,10 +9,12 @@ import { Header as AuthenticatedHeader } from '~/components/general/app-header';
import type { Route } from './+types/_layout';
export function loader({ context }: Route.LoaderArgs) {
export function loader() {
const session = getOptionalLoaderSession();
return {
user: context.session?.user,
teams: context.session?.teams || [],
user: session?.user,
teams: session?.teams || [],
};
}

View File

@ -1,6 +1,7 @@
import { Plural } from '@lingui/macro';
import { UsersIcon } from 'lucide-react';
import { redirect } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { useOptionalSession } from '@documenso/lib/client-only/providers/session';
@ -16,7 +17,9 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/_index';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
@ -45,7 +48,7 @@ export async function loader({ params, context }: Route.LoaderArgs) {
// Ensure typesafety when we add more options.
const isAccessAuthValid = match(derivedRecipientAccessAuth)
.with(DocumentAccessAuth.ACCOUNT, () => context.session?.user !== null)
.with(DocumentAccessAuth.ACCOUNT, () => session?.user !== null)
.with(null, () => true)
.exhaustive();
@ -67,6 +70,7 @@ export default function DirectTemplatePage() {
const data = useSuperLoaderData<typeof loader>();
// Should not be possible for directLink to be null.
if (!data.isAccessAuthValid) {
return <DirectTemplateAuthPageView />;
}

View File

@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro';
import { DocumentStatus, SigningStatus } from '@prisma/client';
import { Clock8 } from 'lucide-react';
import { Link, redirect } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import signingCelebration from '@documenso/assets/images/signing-celebration.png';
import { useOptionalSession } from '@documenso/lib/client-only/providers/session';
@ -25,14 +26,16 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/_index';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
throw new Response('Not Found', { status: 404 });
}
const user = context.session?.user;
const user = session?.user;
const [document, fields, recipient, completedFields] = await Promise.all([
getDocumentAndSenderByToken({

View File

@ -3,6 +3,7 @@ import { useLingui } from '@lingui/react';
import { DocumentStatus, FieldType, RecipientRole } from '@prisma/client';
import { CheckCircle2, Clock8, FileSearch } from 'lucide-react';
import { Link } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import signingCelebration from '@documenso/assets/images/signing-celebration.png';
@ -27,14 +28,16 @@ import { DocumentSigningAuthPageView } from '~/components/general/document-signi
import type { Route } from './+types/complete';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
throw new Response('Not Found', { status: 404 });
}
const user = context.session?.user;
const user = session?.user;
const document = await getDocumentAndSenderByToken({
token,

View File

@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro';
import { FieldType } from '@prisma/client';
import { XCircle } from 'lucide-react';
import { Link } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { useOptionalSession } from '@documenso/lib/client-only/providers/session';
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
@ -16,14 +17,16 @@ import { truncateTitle } from '~/utils/truncate-title';
import type { Route } from './+types/rejected';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
throw new Response('Not Found', { status: 404 });
}
const user = context.session?.user;
const user = session?.user;
const document = await getDocumentAndSenderByToken({
token,

View File

@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro';
import type { Team } from '@prisma/client';
import { DocumentStatus } from '@prisma/client';
import { Link, redirect } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
@ -12,7 +13,9 @@ import { Button } from '@documenso/ui/primitives/button';
import type { Route } from './+types/waiting';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
@ -34,7 +37,7 @@ export async function loader({ params, context }: Route.LoaderArgs) {
let isOwnerOrTeamMember = false;
const user = context.session?.user;
const user = session?.user;
let team: Team | null = null;
if (user) {

View File

@ -1,5 +1,6 @@
import { Trans } from '@lingui/macro';
import { Link, redirect } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import {
IS_GOOGLE_SSO_ENABLED,
@ -10,14 +11,14 @@ import { env } from '@documenso/lib/utils/env';
import { SignInForm } from '~/components/forms/signin';
import type { Route } from './+types/signin';
export function meta() {
return [{ title: 'Sign In' }];
}
export function loader({ context }: Route.LoaderArgs) {
if (context.session) {
export function loader() {
const session = getOptionalLoaderSession();
if (session) {
throw redirect('/documents');
}
}

View File

@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro';
import { TeamMemberInviteStatus } from '@prisma/client';
import { DateTime } from 'luxon';
import { Link } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt';
import { declineTeamInvitation } from '@documenso/lib/server-only/team/decline-team-invitation';
@ -11,7 +12,9 @@ import { Button } from '@documenso/ui/primitives/button';
import type { Route } from './+types/team.decline.$token';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
@ -71,7 +74,7 @@ export async function loader({ params, context }: Route.LoaderArgs) {
} as const;
}
const isSessionUserTheInvitedUser = user.id === context.session?.user.id;
const isSessionUserTheInvitedUser = user.id === session?.user.id;
return {
state: 'Success',

View File

@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro';
import { TeamMemberInviteStatus } from '@prisma/client';
import { DateTime } from 'luxon';
import { Link } from 'react-router';
import { getOptionalLoaderSession } from 'server/utils/get-loader-session';
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt';
import { acceptTeamInvitation } from '@documenso/lib/server-only/team/accept-team-invitation';
@ -11,7 +12,9 @@ import { Button } from '@documenso/ui/primitives/button';
import type { Route } from './+types/team.invite.$token';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
const session = getOptionalLoaderSession();
const { token } = params;
if (!token) {
@ -74,7 +77,7 @@ export async function loader({ params, context }: Route.LoaderArgs) {
} as const;
}
const isSessionUserTheInvitedUser = user.id === context.session?.user.id;
const isSessionUserTheInvitedUser = user.id === session?.user.id;
return {
state: 'Success',

View File

@ -1,5 +1,5 @@
import { data } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
@ -17,7 +17,7 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/direct.$url';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
if (!params.url) {
throw new Response('Not found', { status: 404 });
}
@ -48,7 +48,7 @@ export async function loader({ params, context }: Route.LoaderArgs) {
);
}
const { user } = getRequiredLoaderSession(context);
const { user } = getLoaderSession();
const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({
documentAuth: template.authOptions,

View File

@ -1,6 +1,6 @@
import { DocumentStatus } from '@prisma/client';
import { data } from 'react-router';
import { getRequiredLoaderSession } from 'server/utils/get-loader-session';
import { getLoaderSession } from 'server/utils/get-loader-session';
import { match } from 'ts-pattern';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
@ -20,14 +20,14 @@ import { superLoaderJson, useSuperLoaderData } from '~/utils/super-json-loader';
import type { Route } from './+types/sign.$url';
export async function loader({ params, context }: Route.LoaderArgs) {
export async function loader({ params }: Route.LoaderArgs) {
if (!params.url) {
throw new Response('Not found', { status: 404 });
}
const token = params.url;
const { user } = getRequiredLoaderSession(context);
const { user } = getLoaderSession();
const [document, fields, recipient] = await Promise.all([
getDocumentAndSenderByToken({