From e899918ec49774c2eb273ee96152916a89ed9a6e Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Sun, 13 Oct 2024 22:31:34 +0000 Subject: [PATCH 01/11] activate v3_singleFetch --- app/entry.server.tsx | 6 +- app/root.tsx | 6 +- app/routes/_auth+/forgot-password.tsx | 6 +- app/routes/_auth+/login.tsx | 6 +- app/routes/_auth+/onboarding.tsx | 6 +- app/routes/_auth+/onboarding_.$provider.tsx | 8 +- app/routes/_auth+/reset-password.server.ts | 4 +- app/routes/_auth+/reset-password.tsx | 6 +- app/routes/_auth+/signup.tsx | 6 +- app/routes/_auth+/verify.server.ts | 4 +- app/routes/admin+/cache.tsx | 5 +- app/routes/admin+/cache_.lru.$cacheKey.ts | 6 +- app/routes/admin+/cache_.sqlite.$cacheKey.ts | 6 +- app/routes/admin+/cache_.sqlite.server.ts | 4 +- app/routes/resources+/theme-switch.tsx | 4 +- .../settings+/profile.change-email.server.tsx | 4 +- app/routes/settings+/profile.change-email.tsx | 8 +- app/routes/settings+/profile.connections.tsx | 6 +- app/routes/settings+/profile.index.tsx | 14 +- app/routes/settings+/profile.password.tsx | 6 +- .../settings+/profile.password_.create.tsx | 6 +- app/routes/settings+/profile.photo.tsx | 6 +- app/routes/settings+/profile.tsx | 4 +- .../settings+/profile.two-factor.disable.tsx | 3 +- .../settings+/profile.two-factor.index.tsx | 3 +- .../settings+/profile.two-factor.verify.tsx | 6 +- app/routes/users+/$username.tsx | 4 +- .../$username_+/__note-editor.server.tsx | 4 +- .../users+/$username_+/notes.$noteId.tsx | 9 +- .../$username_+/notes.$noteId_.edit.tsx | 4 +- app/routes/users+/$username_+/notes.new.tsx | 4 +- app/routes/users+/$username_+/notes.tsx | 4 +- app/routes/users+/index.tsx | 17 +- app/utils/permissions.server.ts | 6 +- package-lock.json | 283 ++++++++---------- package.json | 10 +- server/index.ts | 4 +- vite.config.ts | 7 + 38 files changed, 244 insertions(+), 261 deletions(-) diff --git a/app/entry.server.tsx b/app/entry.server.tsx index ed4e4b815..364ea5249 100644 --- a/app/entry.server.tsx +++ b/app/entry.server.tsx @@ -15,7 +15,7 @@ import { getInstanceInfo } from './utils/litefs.server.ts' import { NonceProvider } from './utils/nonce-provider.ts' import { makeTimings } from './utils/timing.server.ts' -const ABORT_DELAY = 5000 +export const streamTimeout = 5000 init() global.ENV = getEnv() @@ -53,7 +53,7 @@ export default async function handleRequest(...args: DocRequestArgs) { const { pipe, abort } = renderToPipeableStream( - + , { [callbackName]: () => { @@ -78,7 +78,7 @@ export default async function handleRequest(...args: DocRequestArgs) { }, ) - setTimeout(abort, ABORT_DELAY) + setTimeout(abort, streamTimeout + 5000) }) } diff --git a/app/root.tsx b/app/root.tsx index f21f11216..cec03914a 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,5 +1,5 @@ import { - json, + data as dataResponse, type LoaderFunctionArgs, type HeadersFunction, type LinksFunction, @@ -117,7 +117,7 @@ export async function loader({ request }: LoaderFunctionArgs) { const { toast, headers: toastHeaders } = await getToast(request) const honeyProps = honeypot.getInputProps() - return json( + return dataResponse( { user, requestInfo: { @@ -158,7 +158,7 @@ function Document({ children: React.ReactNode nonce: string theme?: Theme - env?: Record + env?: Record allowIndexing?: boolean }) { return ( diff --git a/app/routes/_auth+/forgot-password.tsx b/app/routes/_auth+/forgot-password.tsx index f863eeb00..2743ca014 100644 --- a/app/routes/_auth+/forgot-password.tsx +++ b/app/routes/_auth+/forgot-password.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import * as E from '@react-email/components' import { - json, + data as dataResponse, redirect, type ActionFunctionArgs, type MetaFunction, @@ -54,7 +54,7 @@ export async function action({ request }: ActionFunctionArgs) { async: true, }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -84,7 +84,7 @@ export async function action({ request }: ActionFunctionArgs) { if (response.status === 'success') { return redirect(redirectTo.toString()) } else { - return json( + return dataResponse( { result: submission.reply({ formErrors: [response.error.message] }) }, { status: 500 }, ) diff --git a/app/routes/_auth+/login.tsx b/app/routes/_auth+/login.tsx index e15d84b72..259caf1c2 100644 --- a/app/routes/_auth+/login.tsx +++ b/app/routes/_auth+/login.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction, @@ -37,7 +37,7 @@ const LoginFormSchema = z.object({ export async function loader({ request }: LoaderFunctionArgs) { await requireAnonymous(request) - return json({}) + return {} } export async function action({ request }: ActionFunctionArgs) { @@ -64,7 +64,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success' || !submission.value.session) { - return json( + return dataResponse( { result: submission.reply({ hideFields: ['password'] }) }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/onboarding.tsx b/app/routes/_auth+/onboarding.tsx index 042476141..f42550efc 100644 --- a/app/routes/_auth+/onboarding.tsx +++ b/app/routes/_auth+/onboarding.tsx @@ -1,7 +1,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { - json, + data as dataResponse, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -61,7 +61,7 @@ async function requireOnboardingEmail(request: Request) { export async function loader({ request }: LoaderFunctionArgs) { const email = await requireOnboardingEmail(request) - return json({ email }) + return { email } } export async function action({ request }: ActionFunctionArgs) { @@ -93,7 +93,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success' || !submission.value.session) { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/onboarding_.$provider.tsx b/app/routes/_auth+/onboarding_.$provider.tsx index 9cbdc51a2..e85018c4e 100644 --- a/app/routes/_auth+/onboarding_.$provider.tsx +++ b/app/routes/_auth+/onboarding_.$provider.tsx @@ -7,7 +7,7 @@ import { import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { redirect, - json, + data as dataResponse, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction, @@ -95,7 +95,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) { const formError = connectionSession.get(authenticator.sessionErrorKey) const hasError = typeof formError === 'string' - return json({ + return { email, status: 'idle', submission: { @@ -103,7 +103,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) { initialValue: prefilledProfile ?? {}, error: { '': hasError ? [formError] : [] }, } as SubmissionResult, - }) + } } export async function action({ request, params }: ActionFunctionArgs) { @@ -143,7 +143,7 @@ export async function action({ request, params }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/reset-password.server.ts b/app/routes/_auth+/reset-password.server.ts index 1c25b4dc5..86f6e92d6 100644 --- a/app/routes/_auth+/reset-password.server.ts +++ b/app/routes/_auth+/reset-password.server.ts @@ -1,5 +1,5 @@ import { invariant } from '@epic-web/invariant' -import { json, redirect } from '@remix-run/node' +import { data as dataResponse, redirect } from '@remix-run/node' import { prisma } from '#app/utils/db.server.ts' import { verifySessionStorage } from '#app/utils/verification.server.ts' import { resetPasswordUsernameSessionKey } from './reset-password.tsx' @@ -18,7 +18,7 @@ export async function handleVerification({ submission }: VerifyFunctionArgs) { // we don't want to say the user is not found if the email is not found // because that would allow an attacker to check if an email is registered if (!user) { - return json( + return dataResponse( { result: submission.reply({ fieldErrors: { code: ['Invalid code'] } }) }, { status: 400 }, ) diff --git a/app/routes/_auth+/reset-password.tsx b/app/routes/_auth+/reset-password.tsx index 38e4763a2..6bf0a66b8 100644 --- a/app/routes/_auth+/reset-password.tsx +++ b/app/routes/_auth+/reset-password.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, type ActionFunctionArgs, type LoaderFunctionArgs, @@ -41,7 +41,7 @@ async function requireResetPasswordUsername(request: Request) { export async function loader({ request }: LoaderFunctionArgs) { const resetPasswordUsername = await requireResetPasswordUsername(request) - return json({ resetPasswordUsername }) + return { resetPasswordUsername } } export async function action({ request }: ActionFunctionArgs) { @@ -51,7 +51,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: ResetPasswordSchema, }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/signup.tsx b/app/routes/_auth+/signup.tsx index 6d475a3d2..7fbf32423 100644 --- a/app/routes/_auth+/signup.tsx +++ b/app/routes/_auth+/signup.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import * as E from '@react-email/components' import { - json, + data as dataResponse, redirect, type ActionFunctionArgs, type MetaFunction, @@ -56,7 +56,7 @@ export async function action({ request }: ActionFunctionArgs) { async: true, }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -78,7 +78,7 @@ export async function action({ request }: ActionFunctionArgs) { if (response.status === 'success') { return redirect(redirectTo.toString()) } else { - return json( + return dataResponse( { result: submission.reply({ formErrors: [response.error.message] }), }, diff --git a/app/routes/_auth+/verify.server.ts b/app/routes/_auth+/verify.server.ts index dccd55aa3..710b5cc41 100644 --- a/app/routes/_auth+/verify.server.ts +++ b/app/routes/_auth+/verify.server.ts @@ -1,6 +1,6 @@ import { type Submission } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' -import { json } from '@remix-run/node' +import { data as dataResponse } from '@remix-run/node' import { z } from 'zod' import { handleVerification as handleChangeEmailVerification } from '#app/routes/settings+/profile.change-email.server.tsx' import { twoFAVerificationType } from '#app/routes/settings+/profile.two-factor.tsx' @@ -161,7 +161,7 @@ export async function validateRequest( }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/admin+/cache.tsx b/app/routes/admin+/cache.tsx index 741e85849..6ccdd0462 100644 --- a/app/routes/admin+/cache.tsx +++ b/app/routes/admin+/cache.tsx @@ -1,7 +1,6 @@ import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -58,7 +57,7 @@ export async function loader({ request }: LoaderFunctionArgs) { } else { cacheKeys = await getAllCacheKeys(limit) } - return json({ cacheKeys, instance, instances, currentInstanceInfo }) + return { cacheKeys, instance, instances, currentInstanceInfo } } export async function action({ request }: ActionFunctionArgs) { @@ -87,7 +86,7 @@ export async function action({ request }: ActionFunctionArgs) { throw new Error(`Unknown cache type: ${type}`) } } - return json({ success: true }) + return { success: true } } export default function CacheAdminRoute() { diff --git a/app/routes/admin+/cache_.lru.$cacheKey.ts b/app/routes/admin+/cache_.lru.$cacheKey.ts index 2b793d094..b3a15f0e5 100644 --- a/app/routes/admin+/cache_.lru.$cacheKey.ts +++ b/app/routes/admin+/cache_.lru.$cacheKey.ts @@ -1,5 +1,5 @@ import { invariantResponse } from '@epic-web/invariant' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { lruCache } from '#app/utils/cache.server.ts' import { getAllInstances, @@ -19,7 +19,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) { const { cacheKey } = params invariantResponse(cacheKey, 'cacheKey is required') - return json({ + return { instance: { hostname: instance, region: allInstances[instance], @@ -27,5 +27,5 @@ export async function loader({ request, params }: LoaderFunctionArgs) { }, cacheKey, value: lruCache.get(cacheKey), - }) + } } diff --git a/app/routes/admin+/cache_.sqlite.$cacheKey.ts b/app/routes/admin+/cache_.sqlite.$cacheKey.ts index 39bcb0776..c59cf5fc9 100644 --- a/app/routes/admin+/cache_.sqlite.$cacheKey.ts +++ b/app/routes/admin+/cache_.sqlite.$cacheKey.ts @@ -1,5 +1,5 @@ import { invariantResponse } from '@epic-web/invariant' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { cache } from '#app/utils/cache.server.ts' import { getAllInstances, @@ -19,7 +19,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) { const { cacheKey } = params invariantResponse(cacheKey, 'cacheKey is required') - return json({ + return { instance: { hostname: instance, region: allInstances[instance], @@ -27,5 +27,5 @@ export async function loader({ request, params }: LoaderFunctionArgs) { }, cacheKey, value: cache.get(cacheKey), - }) + } } diff --git a/app/routes/admin+/cache_.sqlite.server.ts b/app/routes/admin+/cache_.sqlite.server.ts index a9c8f80eb..026ef7068 100644 --- a/app/routes/admin+/cache_.sqlite.server.ts +++ b/app/routes/admin+/cache_.sqlite.server.ts @@ -1,4 +1,4 @@ -import { json, redirect, type ActionFunctionArgs } from '@remix-run/node' +import { redirect, type ActionFunctionArgs } from '@remix-run/node' import { z } from 'zod' import { cache } from '#app/utils/cache.server.ts' import { @@ -54,5 +54,5 @@ export async function action({ request }: ActionFunctionArgs) { // @ts-expect-error - we don't reliably know the type of cacheValue await cache.set(key, cacheValue) } - return json({ success: true }) + return { success: true } } diff --git a/app/routes/resources+/theme-switch.tsx b/app/routes/resources+/theme-switch.tsx index 5ea2aea9d..9b6f9c114 100644 --- a/app/routes/resources+/theme-switch.tsx +++ b/app/routes/resources+/theme-switch.tsx @@ -1,7 +1,7 @@ import { useForm, getFormProps } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' -import { json, type ActionFunctionArgs } from '@remix-run/node' +import { data as dataResponse, type ActionFunctionArgs } from '@remix-run/node' import { redirect, useFetcher, useFetchers } from '@remix-run/react' import { ServerOnly } from 'remix-utils/server-only' import { z } from 'zod' @@ -32,7 +32,7 @@ export async function action({ request }: ActionFunctionArgs) { if (redirectTo) { return redirect(redirectTo, responseInit) } else { - return json({ result: submission.reply() }, responseInit) + return dataResponse({ result: submission.reply() }, responseInit) } } diff --git a/app/routes/settings+/profile.change-email.server.tsx b/app/routes/settings+/profile.change-email.server.tsx index 0a0eebc0a..acdc9965d 100644 --- a/app/routes/settings+/profile.change-email.server.tsx +++ b/app/routes/settings+/profile.change-email.server.tsx @@ -1,6 +1,6 @@ import { invariant } from '@epic-web/invariant' import * as E from '@react-email/components' -import { json } from '@remix-run/node' +import { data as dataResponse } from '@remix-run/node' import { requireRecentVerification, type VerifyFunctionArgs, @@ -26,7 +26,7 @@ export async function handleVerification({ ) const newEmail = verifySession.get(newEmailAddressSessionKey) if (!newEmail) { - return json( + return dataResponse( { result: submission.reply({ formErrors: [ diff --git a/app/routes/settings+/profile.change-email.tsx b/app/routes/settings+/profile.change-email.tsx index e68758873..e7346307f 100644 --- a/app/routes/settings+/profile.change-email.tsx +++ b/app/routes/settings+/profile.change-email.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, type ActionFunctionArgs, type LoaderFunctionArgs, @@ -47,7 +47,7 @@ export async function loader({ request }: LoaderFunctionArgs) { const params = new URLSearchParams({ redirectTo: request.url }) throw redirect(`/login?${params}`) } - return json({ user }) + return { user } } export async function action({ request }: ActionFunctionArgs) { @@ -70,7 +70,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -97,7 +97,7 @@ export async function action({ request }: ActionFunctionArgs) { }, }) } else { - return json( + return dataResponse( { result: submission.reply({ formErrors: [response.error.message] }) }, { status: 500 }, ) diff --git a/app/routes/settings+/profile.connections.tsx b/app/routes/settings+/profile.connections.tsx index 91c479563..4255bdb9a 100644 --- a/app/routes/settings+/profile.connections.tsx +++ b/app/routes/settings+/profile.connections.tsx @@ -1,7 +1,7 @@ import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, type LoaderFunctionArgs, type ActionFunctionArgs, type SerializeFrom, @@ -81,7 +81,7 @@ export async function loader({ request }: LoaderFunctionArgs) { }) } - return json( + return dataResponse( { connections, canDeleteConnections: await userCanDeleteConnections(userId), @@ -120,7 +120,7 @@ export async function action({ request }: ActionFunctionArgs) { title: 'Deleted', description: 'Your connection has been deleted.', }) - return json({ status: 'success' } as const, { headers: toastHeaders }) + return dataResponse({ status: 'success' } as const, { headers: toastHeaders }) } export default function Connections() { diff --git a/app/routes/settings+/profile.index.tsx b/app/routes/settings+/profile.index.tsx index 380cfa226..21b479c14 100644 --- a/app/routes/settings+/profile.index.tsx +++ b/app/routes/settings+/profile.index.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, type LoaderFunctionArgs, type ActionFunctionArgs, } from '@remix-run/node' @@ -64,11 +64,11 @@ export async function loader({ request }: LoaderFunctionArgs) { where: { userId }, }) - return json({ + return { user, hasPassword: Boolean(password), isTwoFactorEnabled: Boolean(twoFactorVerification), - }) + } } type ProfileActionArgs = { @@ -194,7 +194,7 @@ async function profileUpdateAction({ userId, formData }: ProfileActionArgs) { }), }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -211,9 +211,9 @@ async function profileUpdateAction({ userId, formData }: ProfileActionArgs) { }, }) - return json({ + return { result: submission.reply(), - }) + } } function UpdateProfile() { @@ -288,7 +288,7 @@ async function signOutOfSessionsAction({ request, userId }: ProfileActionArgs) { id: { not: sessionId }, }, }) - return json({ status: 'success' } as const) + return { status: 'success' } as const } function SignOutOfSessions() { diff --git a/app/routes/settings+/profile.password.tsx b/app/routes/settings+/profile.password.tsx index afdf7af9e..99a5f176a 100644 --- a/app/routes/settings+/profile.password.tsx +++ b/app/routes/settings+/profile.password.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -58,7 +58,7 @@ async function requirePassword(userId: string) { export async function loader({ request }: LoaderFunctionArgs) { const userId = await requireUserId(request) await requirePassword(userId) - return json({}) + return {} } export async function action({ request }: ActionFunctionArgs) { @@ -83,7 +83,7 @@ export async function action({ request }: ActionFunctionArgs) { ), }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply({ hideFields: ['currentPassword', 'newPassword', 'confirmNewPassword'], diff --git a/app/routes/settings+/profile.password_.create.tsx b/app/routes/settings+/profile.password_.create.tsx index 24770f815..d1b7c1046 100644 --- a/app/routes/settings+/profile.password_.create.tsx +++ b/app/routes/settings+/profile.password_.create.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -38,7 +38,7 @@ async function requireNoPassword(userId: string) { export async function loader({ request }: LoaderFunctionArgs) { const userId = await requireUserId(request) await requireNoPassword(userId) - return json({}) + return {} } export async function action({ request }: ActionFunctionArgs) { @@ -50,7 +50,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: CreatePasswordForm, }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply({ hideFields: ['password', 'confirmPassword'], diff --git a/app/routes/settings+/profile.photo.tsx b/app/routes/settings+/profile.photo.tsx index 5a9718bbe..f731d7c85 100644 --- a/app/routes/settings+/profile.photo.tsx +++ b/app/routes/settings+/profile.photo.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData, @@ -70,7 +70,7 @@ export async function loader({ request }: LoaderFunctionArgs) { }, }) invariantResponse(user, 'User not found', { status: 404 }) - return json({ user }) + return { user } } export async function action({ request }: ActionFunctionArgs) { @@ -96,7 +96,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/settings+/profile.tsx b/app/routes/settings+/profile.tsx index 711aa90b6..2739aebd0 100644 --- a/app/routes/settings+/profile.tsx +++ b/app/routes/settings+/profile.tsx @@ -1,6 +1,6 @@ import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { data as dataResponse, type LoaderFunctionArgs } from '@remix-run/node' import { Link, Outlet, useMatches } from '@remix-run/react' import { z } from 'zod' import { Spacer } from '#app/components/spacer.tsx' @@ -25,7 +25,7 @@ export async function loader({ request }: LoaderFunctionArgs) { select: { username: true }, }) invariantResponse(user, 'User not found', { status: 404 }) - return json({}) + return {} } const BreadcrumbHandleMatch = z.object({ diff --git a/app/routes/settings+/profile.two-factor.disable.tsx b/app/routes/settings+/profile.two-factor.disable.tsx index f1530991e..0d012969c 100644 --- a/app/routes/settings+/profile.two-factor.disable.tsx +++ b/app/routes/settings+/profile.two-factor.disable.tsx @@ -1,6 +1,5 @@ import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, type LoaderFunctionArgs, type ActionFunctionArgs, } from '@remix-run/node' @@ -22,7 +21,7 @@ export const handle: BreadcrumbHandle & SEOHandle = { export async function loader({ request }: LoaderFunctionArgs) { await requireRecentVerification(request) - return json({}) + return {} } export async function action({ request }: ActionFunctionArgs) { diff --git a/app/routes/settings+/profile.two-factor.index.tsx b/app/routes/settings+/profile.two-factor.index.tsx index e080ddaa3..56285799e 100644 --- a/app/routes/settings+/profile.two-factor.index.tsx +++ b/app/routes/settings+/profile.two-factor.index.tsx @@ -1,6 +1,5 @@ import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -24,7 +23,7 @@ export async function loader({ request }: LoaderFunctionArgs) { where: { target_type: { type: twoFAVerificationType, target: userId } }, select: { id: true }, }) - return json({ is2FAEnabled: Boolean(verification) }) + return { is2FAEnabled: Boolean(verification) } } export async function action({ request }: ActionFunctionArgs) { diff --git a/app/routes/settings+/profile.two-factor.verify.tsx b/app/routes/settings+/profile.two-factor.verify.tsx index 762d8bce6..002e99ed4 100644 --- a/app/routes/settings+/profile.two-factor.verify.tsx +++ b/app/routes/settings+/profile.two-factor.verify.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - json, + data as dataResponse, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -73,7 +73,7 @@ export async function loader({ request }: LoaderFunctionArgs) { issuer, }) const qrCode = await QRCode.toDataURL(otpUri) - return json({ otpUri, qrCode }) + return { otpUri, qrCode } } export async function action({ request }: ActionFunctionArgs) { @@ -102,7 +102,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/$username.tsx b/app/routes/users+/$username.tsx index 443133b75..8fc5fb5af 100644 --- a/app/routes/users+/$username.tsx +++ b/app/routes/users+/$username.tsx @@ -1,5 +1,5 @@ import { invariantResponse } from '@epic-web/invariant' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { Form, Link, useLoaderData, type MetaFunction } from '@remix-run/react' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' import { Spacer } from '#app/components/spacer.tsx' @@ -25,7 +25,7 @@ export async function loader({ params }: LoaderFunctionArgs) { invariantResponse(user, 'User not found', { status: 404 }) - return json({ user, userJoinedDisplay: user.createdAt.toLocaleDateString() }) + return { user, userJoinedDisplay: user.createdAt.toLocaleDateString() } } export default function ProfileRoute() { diff --git a/app/routes/users+/$username_+/__note-editor.server.tsx b/app/routes/users+/$username_+/__note-editor.server.tsx index 8b1796cee..2a1b2315c 100644 --- a/app/routes/users+/$username_+/__note-editor.server.tsx +++ b/app/routes/users+/$username_+/__note-editor.server.tsx @@ -2,7 +2,7 @@ import { parseWithZod } from '@conform-to/zod' import { createId as cuid } from '@paralleldrive/cuid2' import { unstable_createMemoryUploadHandler as createMemoryUploadHandler, - json, + data as dataResponse, unstable_parseMultipartFormData as parseMultipartFormData, redirect, type ActionFunctionArgs, @@ -88,7 +88,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/$username_+/notes.$noteId.tsx b/app/routes/users+/$username_+/notes.$noteId.tsx index 57e0d3e42..624be37be 100644 --- a/app/routes/users+/$username_+/notes.$noteId.tsx +++ b/app/routes/users+/$username_+/notes.$noteId.tsx @@ -2,7 +2,7 @@ import { getFormProps, useForm } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { - json, + data as dataResponse, type LoaderFunctionArgs, type ActionFunctionArgs, } from '@remix-run/node' @@ -52,10 +52,7 @@ export async function loader({ params }: LoaderFunctionArgs) { const date = new Date(note.updatedAt) const timeAgo = formatDistanceToNow(date) - return json({ - note, - timeAgo, - }) + return { note, timeAgo } } const DeleteFormSchema = z.object({ @@ -70,7 +67,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: DeleteFormSchema, }) if (submission.status !== 'success') { - return json( + return dataResponse( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/$username_+/notes.$noteId_.edit.tsx b/app/routes/users+/$username_+/notes.$noteId_.edit.tsx index 0d1481769..fb12f6027 100644 --- a/app/routes/users+/$username_+/notes.$noteId_.edit.tsx +++ b/app/routes/users+/$username_+/notes.$noteId_.edit.tsx @@ -1,5 +1,5 @@ import { invariantResponse } from '@epic-web/invariant' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { useLoaderData } from '@remix-run/react' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' import { requireUserId } from '#app/utils/auth.server.ts' @@ -28,7 +28,7 @@ export async function loader({ params, request }: LoaderFunctionArgs) { }, }) invariantResponse(note, 'Not found', { status: 404 }) - return json({ note: note }) + return { note: note } } export default function NoteEdit() { diff --git a/app/routes/users+/$username_+/notes.new.tsx b/app/routes/users+/$username_+/notes.new.tsx index ecc8580d4..62a0de79b 100644 --- a/app/routes/users+/$username_+/notes.new.tsx +++ b/app/routes/users+/$username_+/notes.new.tsx @@ -1,4 +1,4 @@ -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { requireUserId } from '#app/utils/auth.server.ts' import { NoteEditor } from './__note-editor.tsx' @@ -6,7 +6,7 @@ export { action } from './__note-editor.server.tsx' export async function loader({ request }: LoaderFunctionArgs) { await requireUserId(request) - return json({}) + return {} } export default NoteEditor diff --git a/app/routes/users+/$username_+/notes.tsx b/app/routes/users+/$username_+/notes.tsx index 58134a381..3ff8e55b7 100644 --- a/app/routes/users+/$username_+/notes.tsx +++ b/app/routes/users+/$username_+/notes.tsx @@ -1,5 +1,5 @@ import { invariantResponse } from '@epic-web/invariant' -import { json, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { Link, NavLink, Outlet, useLoaderData } from '@remix-run/react' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' import { Icon } from '#app/components/ui/icon.tsx' @@ -21,7 +21,7 @@ export async function loader({ params }: LoaderFunctionArgs) { invariantResponse(owner, 'Owner not found', { status: 404 }) - return json({ owner }) + return { owner } } export default function NotesRoute() { diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx index c0703327c..932abb06e 100644 --- a/app/routes/users+/index.tsx +++ b/app/routes/users+/index.tsx @@ -1,4 +1,8 @@ -import { json, redirect, type LoaderFunctionArgs } from '@remix-run/node' +import { + data as dataResponse, + redirect, + type LoaderFunctionArgs, +} from '@remix-run/node' import { Link, useLoaderData } from '@remix-run/react' import { z } from 'zod' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' @@ -41,11 +45,14 @@ export async function loader({ request }: LoaderFunctionArgs) { const result = UserSearchResultsSchema.safeParse(rawUsers) if (!result.success) { - return json({ status: 'error', error: result.error.message } as const, { - status: 400, - }) + return dataResponse( + { status: 'error', error: result.error.message } as const, + { + status: 400, + }, + ) } - return json({ status: 'idle', users: result.data } as const) + return { status: 'idle', users: result.data } as const } export default function UsersRoute() { diff --git a/app/utils/permissions.server.ts b/app/utils/permissions.server.ts index d96fa9164..55b569d43 100644 --- a/app/utils/permissions.server.ts +++ b/app/utils/permissions.server.ts @@ -1,4 +1,4 @@ -import { json } from '@remix-run/node' +import { data as dataResponse } from '@remix-run/node' import { requireUserId } from './auth.server.ts' import { prisma } from './db.server.ts' import { type PermissionString, parsePermissionString } from './user.ts' @@ -28,7 +28,7 @@ export async function requireUserWithPermission( }, }) if (!user) { - throw json( + throw dataResponse( { error: 'Unauthorized', requiredPermission: permissionData, @@ -47,7 +47,7 @@ export async function requireUserWithRole(request: Request, name: string) { where: { id: userId, roles: { some: { name } } }, }) if (!user) { - throw json( + throw dataResponse( { error: 'Unauthorized', requiredRole: name, diff --git a/package-lock.json b/package-lock.json index 7cf1bdd01..5832f19b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,9 +24,9 @@ "@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-tooltip": "^1.1.2", "@react-email/components": "0.0.21", - "@remix-run/express": "2.10.3", - "@remix-run/node": "2.10.3", - "@remix-run/react": "2.10.3", + "@remix-run/express": "2.13.1", + "@remix-run/node": "2.13.1", + "@remix-run/react": "2.13.1", "@sentry/profiling-node": "^8.18.0", "@sentry/remix": "^8.18.0", "address": "^2.0.3", @@ -76,8 +76,8 @@ "@epic-web/config": "^1.12.0", "@faker-js/faker": "^8.4.1", "@playwright/test": "^1.45.2", - "@remix-run/dev": "2.10.3", - "@remix-run/testing": "2.10.3", + "@remix-run/dev": "2.13.1", + "@remix-run/testing": "2.13.1", "@sentry/vite-plugin": "^2.21.1", "@sly-cli/sly": "^1.13.0", "@testing-library/dom": "^10.3.2", @@ -3648,11 +3648,10 @@ } }, "node_modules/@remix-run/dev": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.10.3.tgz", - "integrity": "sha512-ZbSslRCPVsXispbu1t/khMrMwJ34R695tGujnya696nAW0v8rocVhEwaUpvR2iwnvGKN372gv4SdJrjnYz45kw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/dev/-/dev-2.13.1.tgz", + "integrity": "sha512-7+06Dail6zMyRlRvgrZ4cmQjs2gUb+M24iP4jbmql+0B7VAAPwzCRU0x+BF5z8GSef13kDrH3iXv/BQ2O2yOgw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/core": "^7.21.8", "@babel/generator": "^7.21.5", @@ -3664,9 +3663,9 @@ "@babel/types": "^7.22.5", "@mdx-js/mdx": "^2.3.0", "@npmcli/package-json": "^4.0.1", - "@remix-run/node": "2.10.3", - "@remix-run/router": "1.18.0", - "@remix-run/server-runtime": "2.10.3", + "@remix-run/node": "2.13.1", + "@remix-run/router": "1.20.0", + "@remix-run/server-runtime": "2.13.1", "@types/mdx": "^2.0.5", "@vanilla-extract/integration": "^6.2.0", "arg": "^5.0.1", @@ -3680,7 +3679,7 @@ "esbuild-plugins-node-modules-polyfill": "^1.6.0", "execa": "5.1.1", "exit-hook": "2.2.1", - "express": "^4.19.2", + "express": "^4.20.0", "fs-extra": "^10.0.0", "get-port": "^5.1.1", "gunzip-maybe": "^1.4.2", @@ -3706,7 +3705,7 @@ "set-cookie-parser": "^2.6.0", "tar-fs": "^2.1.1", "tsconfig-paths": "^4.0.0", - "ws": "^7.4.5" + "ws": "^7.5.10" }, "bin": { "remix": "dist/cli.js" @@ -3715,8 +3714,8 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@remix-run/react": "^2.10.3", - "@remix-run/serve": "^2.10.3", + "@remix-run/react": "^2.13.1", + "@remix-run/serve": "^2.13.1", "typescript": "^5.1.0", "vite": "^5.1.0", "wrangler": "^3.28.2" @@ -4336,18 +4335,17 @@ } }, "node_modules/@remix-run/express": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.10.3.tgz", - "integrity": "sha512-EkSBQAz3ykoGTrCEP2hC1TOn9tQ3zlcWYeJnECinZzzHQ0ERHP6cKlEYV+pOmY1oRDxn8lMxVa+OL+krDA+xbA==", - "license": "MIT", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/express/-/express-2.13.1.tgz", + "integrity": "sha512-yl3/BSJ8eyvwUyWCLDq3NlS81mZFll9hnADNuSCCBrQgkMhEx7stk5JUmWdvmcmGqHw04Ahkq07ZqJeD4F1FMA==", "dependencies": { - "@remix-run/node": "2.10.3" + "@remix-run/node": "2.13.1" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "express": "^4.19.2", + "express": "^4.20.0", "typescript": "^5.1.0" }, "peerDependenciesMeta": { @@ -4357,12 +4355,11 @@ } }, "node_modules/@remix-run/node": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.10.3.tgz", - "integrity": "sha512-LBqsgADJKW7tYdJZZi2wu20gfMm6UcOXbvb5U70P2jCNxjJvuIw1gXVvNXRJKAdxPKLonjm8cSpfoI6HeQKEDg==", - "license": "MIT", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/node/-/node-2.13.1.tgz", + "integrity": "sha512-2ly7bENj2n2FNBdEN60ZEbNCs5dAOex/QJoo6EZ8RNFfUQxVKAZkMwfQ4ETV2SLWDgkRLj3Jo5n/dx7O2ZGhGw==", "dependencies": { - "@remix-run/server-runtime": "2.10.3", + "@remix-run/server-runtime": "2.13.1", "@remix-run/web-fetch": "^4.4.2", "@web3-storage/multipart-parser": "^1.0.0", "cookie-signature": "^1.1.0", @@ -4383,16 +4380,15 @@ } }, "node_modules/@remix-run/react": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.10.3.tgz", - "integrity": "sha512-nqXlUJzG3zgllsMio20AICbSsF8va0jOnMakl/+oJpFbQqCyFkvYqr+BViBc4Befp5VK54jqJzDnY4kL9zwNvA==", - "license": "MIT", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/react/-/react-2.13.1.tgz", + "integrity": "sha512-kZevCoKMz0ZDOOzTnG95yfM7M9ju38FkWNY1wtxCy+NnUJYrmTerGQtiBsJgMzYD6i29+w4EwoQsdqys7DmMSg==", "dependencies": { - "@remix-run/router": "1.18.0", - "@remix-run/server-runtime": "2.10.3", - "react-router": "6.25.0", - "react-router-dom": "6.25.0", - "turbo-stream": "2.2.0" + "@remix-run/router": "1.20.0", + "@remix-run/server-runtime": "2.13.1", + "react-router": "6.27.0", + "react-router-dom": "6.27.0", + "turbo-stream": "2.4.0" }, "engines": { "node": ">=18.0.0" @@ -4409,27 +4405,25 @@ } }, "node_modules/@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", - "license": "MIT", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz", + "integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==", "engines": { "node": ">=14.0.0" } }, "node_modules/@remix-run/server-runtime": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.10.3.tgz", - "integrity": "sha512-vUl5jONUI6Lj0ICg9FSRFhoPzQdZ/7dpT1m7ID13DF5BEeF3t/9uCJS61XXWgQ/JEu7YRiwvZiwSRTrgM7zeWw==", - "license": "MIT", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/server-runtime/-/server-runtime-2.13.1.tgz", + "integrity": "sha512-2DfBPRcHKVzE4bCNsNkKB50BhCCKF73x+jiS836OyxSIAL+x0tguV2AEjmGXefEXc5AGGzoxkus0AUUEYa29Vg==", "dependencies": { - "@remix-run/router": "1.18.0", + "@remix-run/router": "1.20.0", "@types/cookie": "^0.6.0", "@web3-storage/multipart-parser": "^1.0.0", "cookie": "^0.6.0", "set-cookie-parser": "^2.4.8", "source-map": "^0.7.3", - "turbo-stream": "2.2.0" + "turbo-stream": "2.4.0" }, "engines": { "node": ">=18.0.0" @@ -4444,16 +4438,15 @@ } }, "node_modules/@remix-run/testing": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@remix-run/testing/-/testing-2.10.3.tgz", - "integrity": "sha512-9Pd6W4fWDbIdkzboYrBlkXGPK8/sZT5qta+QEy0TZZrRZw6FXnYrPgDpjBZAieY4ocRH1zl3Prkm4J9iroNUCg==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/@remix-run/testing/-/testing-2.13.1.tgz", + "integrity": "sha512-vbvJx0HS71g3cUzlm+aZ5v2Lf5FbltP0Spv6MsyDMHSWNYV+ciO4w4jTrVuykDZx8seZRbG40M9xDEJuDplegw==", "dev": true, - "license": "MIT", "dependencies": { - "@remix-run/node": "2.10.3", - "@remix-run/react": "2.10.3", - "@remix-run/router": "1.18.0", - "react-router-dom": "6.25.0" + "@remix-run/node": "2.13.1", + "@remix-run/react": "2.13.1", + "@remix-run/router": "1.20.0", + "react-router-dom": "6.27.0" }, "engines": { "node": ">=18.0.0" @@ -8584,10 +8577,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "license": "MIT", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -8597,7 +8589,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -8611,7 +8603,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -8620,7 +8611,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -8628,8 +8618,7 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/boolbase": { "version": "1.0.0", @@ -9383,7 +9372,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -9862,7 +9850,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -10137,10 +10124,9 @@ "license": "MIT" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -10431,8 +10417,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -11161,7 +11146,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -11264,37 +11248,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "license": "MIT", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -11320,6 +11303,14 @@ "express": "4 || 5 || ^5.0.0-beta.1" } }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/express/node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -11475,13 +11466,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "license": "MIT", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -11496,7 +11486,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -11504,8 +11493,7 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/find-up": { "version": "5.0.0", @@ -11621,7 +11609,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -12256,7 +12243,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -12321,7 +12307,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -14091,7 +14076,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -14106,10 +14090,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "license": "MIT" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -14794,7 +14780,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", "bin": { "mime": "cli.js" }, @@ -15864,7 +15849,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -16292,7 +16276,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -16338,10 +16321,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "license": "MIT" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/path-type": { "version": "4.0.0", @@ -17407,12 +17389,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "license": "BSD-3-Clause", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -17473,7 +17454,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -17482,7 +17462,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -17497,7 +17476,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -17630,12 +17608,11 @@ } }, "node_modules/react-router": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.0.tgz", - "integrity": "sha512-bziKjCcDbcxgWS9WlWFcQIVZ2vJHnCP6DGpQDT0l+0PFDasfJKgzf9CM22eTyhFsZkjk8ApCdKjJwKtzqH80jQ==", - "license": "MIT", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz", + "integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==", "dependencies": { - "@remix-run/router": "1.18.0" + "@remix-run/router": "1.20.0" }, "engines": { "node": ">=14.0.0" @@ -17645,13 +17622,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.0.tgz", - "integrity": "sha512-BhcczgDWWgvGZxjDDGuGHrA8HrsSudilqTaRSBYLWDayvo1ClchNIDVt5rldqp6e7Dro5dEFx9Mzc+r292lN0w==", - "license": "MIT", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz", + "integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==", "dependencies": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.0" + "@remix-run/router": "1.20.0", + "react-router": "6.27.0" }, "engines": { "node": ">=14.0.0" @@ -18406,10 +18382,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "license": "MIT", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -18433,7 +18408,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -18441,25 +18415,30 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "license": "MIT", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -18513,8 +18492,7 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -19705,7 +19683,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", "engines": { "node": ">=0.6" } @@ -20303,10 +20280,9 @@ } }, "node_modules/turbo-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.2.0.tgz", - "integrity": "sha512-FKFg7A0To1VU4CH9YmSMON5QphK0BXjSoiC7D9yMh+mEEbXLUP9qJ4hEt1qcjKtzncs1OpcnjZO8NgrlVbZH+g==", - "license": "ISC" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", + "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==" }, "node_modules/type-check": { "version": "0.4.0", @@ -20337,7 +20313,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -20787,7 +20762,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -22140,11 +22114,10 @@ "license": "ISC" }, "node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.3.0" }, diff --git a/package.json b/package.json index c81d1cab3..4c4b1c4e2 100644 --- a/package.json +++ b/package.json @@ -61,9 +61,9 @@ "@radix-ui/react-toast": "^1.2.1", "@radix-ui/react-tooltip": "^1.1.2", "@react-email/components": "0.0.21", - "@remix-run/express": "2.10.3", - "@remix-run/node": "2.10.3", - "@remix-run/react": "2.10.3", + "@remix-run/express": "2.13.1", + "@remix-run/node": "2.13.1", + "@remix-run/react": "2.13.1", "@sentry/profiling-node": "^8.18.0", "@sentry/remix": "^8.18.0", "address": "^2.0.3", @@ -113,8 +113,8 @@ "@epic-web/config": "^1.12.0", "@faker-js/faker": "^8.4.1", "@playwright/test": "^1.45.2", - "@remix-run/dev": "2.10.3", - "@remix-run/testing": "2.10.3", + "@remix-run/dev": "2.13.1", + "@remix-run/testing": "2.13.1", "@sentry/vite-plugin": "^2.21.1", "@sly-cli/sly": "^1.13.0", "@testing-library/dom": "^10.3.2", diff --git a/server/index.ts b/server/index.ts index 45aec8c56..ff62f01df 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,6 +1,6 @@ import crypto from 'node:crypto' import { createRequestHandler } from '@remix-run/express' -import { type ServerBuild } from '@remix-run/node' +import { installGlobals, type ServerBuild } from '@remix-run/node' import Sentry from '@sentry/remix' import { ip as ipAddress } from 'address' import chalk from 'chalk' @@ -12,6 +12,8 @@ import getPort, { portNumbers } from 'get-port' import helmet from 'helmet' import morgan from 'morgan' +installGlobals({ nativeFetch: true }) + const MODE = process.env.NODE_ENV ?? 'development' const IS_PROD = MODE === 'production' const IS_DEV = MODE === 'development' diff --git a/vite.config.ts b/vite.config.ts index 242db8308..ad8d9c210 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,12 @@ import { flatRoutes } from 'remix-flat-routes' import { defineConfig } from 'vite' import { envOnlyMacros } from 'vite-env-only' +declare module '@remix-run/server-runtime' { + interface Future { + v3_singleFetch: true + } +} + const MODE = process.env.NODE_ENV export default defineConfig({ @@ -41,6 +47,7 @@ export default defineConfig({ : remix({ ignoredRouteFiles: ['**/*'], serverModuleFormat: 'esm', + future: { v3_singleFetch: true }, routes: async (defineRoutes) => { return flatRoutes('routes', defineRoutes, { ignoredRouteFiles: [ From d0a9ff51298dfe7eada7e8506850b3bdf3dd3d3e Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Mon, 14 Oct 2024 00:17:24 +0000 Subject: [PATCH 02/11] mv installGlobals --> vite conf --- index.js | 3 +-- server/index.ts | 4 +--- vite.config.ts | 3 +++ 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index fb09291ab..24525b284 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,6 @@ import 'dotenv/config' import * as fs from 'node:fs' -import chalk from 'chalk' -import closeWithGrace from 'close-with-grace' + import sourceMapSupport from 'source-map-support' sourceMapSupport.install({ diff --git a/server/index.ts b/server/index.ts index ff62f01df..45aec8c56 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,6 +1,6 @@ import crypto from 'node:crypto' import { createRequestHandler } from '@remix-run/express' -import { installGlobals, type ServerBuild } from '@remix-run/node' +import { type ServerBuild } from '@remix-run/node' import Sentry from '@sentry/remix' import { ip as ipAddress } from 'address' import chalk from 'chalk' @@ -12,8 +12,6 @@ import getPort, { portNumbers } from 'get-port' import helmet from 'helmet' import morgan from 'morgan' -installGlobals({ nativeFetch: true }) - const MODE = process.env.NODE_ENV ?? 'development' const IS_PROD = MODE === 'production' const IS_DEV = MODE === 'development' diff --git a/vite.config.ts b/vite.config.ts index ad8d9c210..b9bb0cd7a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,5 @@ import { vitePlugin as remix } from '@remix-run/dev' +import { installGlobals } from '@remix-run/node' import { sentryVitePlugin } from '@sentry/vite-plugin' import { glob } from 'glob' import { flatRoutes } from 'remix-flat-routes' @@ -11,6 +12,8 @@ declare module '@remix-run/server-runtime' { } } +installGlobals({ nativeFetch: true }) + const MODE = process.env.NODE_ENV export default defineConfig({ From 56603cc9ca56f7caee6b109d968cb3d275ace7b3 Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 18:52:17 +0000 Subject: [PATCH 03/11] Fix: playwright failures --- app/routes/_auth+/auth.$provider.ts | 6 +----- index.js | 2 ++ vite.config.ts | 3 --- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/routes/_auth+/auth.$provider.ts b/app/routes/_auth+/auth.$provider.ts index 7231920c7..eb524cc03 100644 --- a/app/routes/_auth+/auth.$provider.ts +++ b/app/routes/_auth+/auth.$provider.ts @@ -1,14 +1,10 @@ -import { redirect, type ActionFunctionArgs } from '@remix-run/node' +import { type ActionFunctionArgs } from '@remix-run/node' import { authenticator } from '#app/utils/auth.server.ts' import { handleMockAction } from '#app/utils/connections.server.ts' import { ProviderNameSchema } from '#app/utils/connections.tsx' import { getReferrerRoute } from '#app/utils/misc.tsx' import { getRedirectCookieHeader } from '#app/utils/redirect-cookie.server.ts' -export async function loader() { - return redirect('/login') -} - export async function action({ request, params }: ActionFunctionArgs) { const providerName = ProviderNameSchema.parse(params.provider) diff --git a/index.js b/index.js index 24525b284..2e7b40149 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,9 @@ import 'dotenv/config' import * as fs from 'node:fs' +//import { installGlobals } from '@remix-run/node' import sourceMapSupport from 'source-map-support' +//installGlobals({ nativeFetch: true }) sourceMapSupport.install({ retrieveSourceMap: function (source) { diff --git a/vite.config.ts b/vite.config.ts index b9bb0cd7a..ad8d9c210 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,4 @@ import { vitePlugin as remix } from '@remix-run/dev' -import { installGlobals } from '@remix-run/node' import { sentryVitePlugin } from '@sentry/vite-plugin' import { glob } from 'glob' import { flatRoutes } from 'remix-flat-routes' @@ -12,8 +11,6 @@ declare module '@remix-run/server-runtime' { } } -installGlobals({ nativeFetch: true }) - const MODE = process.env.NODE_ENV export default defineConfig({ From e6eca57e607d737e76a6db25cbc4e00a58c0a05f Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 19:20:58 +0000 Subject: [PATCH 04/11] add installGlobals --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 2e7b40149..8317efc79 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,9 @@ import 'dotenv/config' import * as fs from 'node:fs' -//import { installGlobals } from '@remix-run/node' +import { installGlobals } from '@remix-run/node' import sourceMapSupport from 'source-map-support' -//installGlobals({ nativeFetch: true }) +installGlobals({ nativeFetch: true }) sourceMapSupport.install({ retrieveSourceMap: function (source) { From c2d22440dda5fa1bc4c52e3bc42c1a0c63f9d9d3 Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 19:25:09 +0000 Subject: [PATCH 05/11] Fix: eslint --- app/routes/settings+/profile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes/settings+/profile.tsx b/app/routes/settings+/profile.tsx index 2739aebd0..81af9f204 100644 --- a/app/routes/settings+/profile.tsx +++ b/app/routes/settings+/profile.tsx @@ -1,6 +1,6 @@ import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' -import { data as dataResponse, type LoaderFunctionArgs } from '@remix-run/node' +import { type LoaderFunctionArgs } from '@remix-run/node' import { Link, Outlet, useMatches } from '@remix-run/react' import { z } from 'zod' import { Spacer } from '#app/components/spacer.tsx' From b4d40b6ce6c3d93e7263b679900244f37fc38a83 Mon Sep 17 00:00:00 2001 From: Hakim Gueye <64654633+hakimLyon@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:39:51 +0000 Subject: [PATCH 06/11] format Co-authored-by: Kent C. Dodds --- app/routes/users+/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx index 932abb06e..5022cdd7e 100644 --- a/app/routes/users+/index.tsx +++ b/app/routes/users+/index.tsx @@ -47,9 +47,7 @@ export async function loader({ request }: LoaderFunctionArgs) { if (!result.success) { return dataResponse( { status: 'error', error: result.error.message } as const, - { - status: 400, - }, + { status: 400 }, ) } return { status: 'idle', users: result.data } as const From cb2f5c9fe96b661843ec869f81648cb7c934a843 Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 21:45:08 +0000 Subject: [PATCH 07/11] import as data --- app/root.tsx | 4 ++-- app/routes/_auth+/forgot-password.tsx | 6 +++--- app/routes/_auth+/login.tsx | 4 ++-- app/routes/_auth+/onboarding.tsx | 4 ++-- app/routes/_auth+/onboarding_.$provider.tsx | 4 ++-- app/routes/_auth+/reset-password.server.ts | 4 ++-- app/routes/_auth+/reset-password.tsx | 4 ++-- app/routes/_auth+/signup.tsx | 6 +++--- app/routes/_auth+/verify.server.ts | 4 ++-- app/routes/resources+/theme-switch.tsx | 4 ++-- .../settings+/profile.change-email.server.tsx | 4 ++-- app/routes/settings+/profile.change-email.tsx | 6 +++--- app/routes/settings+/profile.connections.tsx | 6 +++--- app/routes/settings+/profile.index.tsx | 4 ++-- app/routes/settings+/profile.password.tsx | 4 ++-- app/routes/settings+/profile.password_.create.tsx | 4 ++-- app/routes/settings+/profile.photo.tsx | 4 ++-- app/routes/settings+/profile.two-factor.verify.tsx | 4 ++-- .../users+/$username_+/__note-editor.server.tsx | 4 ++-- app/routes/users+/$username_+/notes.$noteId.tsx | 4 ++-- app/routes/users+/index.tsx | 13 ++++--------- app/utils/permissions.server.ts | 6 +++--- 22 files changed, 51 insertions(+), 56 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index cec03914a..2f20d19d4 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,5 +1,5 @@ import { - data as dataResponse, + data, type LoaderFunctionArgs, type HeadersFunction, type LinksFunction, @@ -117,7 +117,7 @@ export async function loader({ request }: LoaderFunctionArgs) { const { toast, headers: toastHeaders } = await getToast(request) const honeyProps = honeypot.getInputProps() - return dataResponse( + return data( { user, requestInfo: { diff --git a/app/routes/_auth+/forgot-password.tsx b/app/routes/_auth+/forgot-password.tsx index 2743ca014..285f1fa87 100644 --- a/app/routes/_auth+/forgot-password.tsx +++ b/app/routes/_auth+/forgot-password.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import * as E from '@react-email/components' import { - data as dataResponse, + data, redirect, type ActionFunctionArgs, type MetaFunction, @@ -54,7 +54,7 @@ export async function action({ request }: ActionFunctionArgs) { async: true, }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -84,7 +84,7 @@ export async function action({ request }: ActionFunctionArgs) { if (response.status === 'success') { return redirect(redirectTo.toString()) } else { - return dataResponse( + return data( { result: submission.reply({ formErrors: [response.error.message] }) }, { status: 500 }, ) diff --git a/app/routes/_auth+/login.tsx b/app/routes/_auth+/login.tsx index 259caf1c2..14810f633 100644 --- a/app/routes/_auth+/login.tsx +++ b/app/routes/_auth+/login.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction, @@ -64,7 +64,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success' || !submission.value.session) { - return dataResponse( + return data( { result: submission.reply({ hideFields: ['password'] }) }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/onboarding.tsx b/app/routes/_auth+/onboarding.tsx index f42550efc..a087363f0 100644 --- a/app/routes/_auth+/onboarding.tsx +++ b/app/routes/_auth+/onboarding.tsx @@ -1,7 +1,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { - data as dataResponse, + data, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -93,7 +93,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success' || !submission.value.session) { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/onboarding_.$provider.tsx b/app/routes/_auth+/onboarding_.$provider.tsx index e85018c4e..46f5cc981 100644 --- a/app/routes/_auth+/onboarding_.$provider.tsx +++ b/app/routes/_auth+/onboarding_.$provider.tsx @@ -7,7 +7,7 @@ import { import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { redirect, - data as dataResponse, + data, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction, @@ -143,7 +143,7 @@ export async function action({ request, params }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/reset-password.server.ts b/app/routes/_auth+/reset-password.server.ts index 86f6e92d6..39c4caa85 100644 --- a/app/routes/_auth+/reset-password.server.ts +++ b/app/routes/_auth+/reset-password.server.ts @@ -1,5 +1,5 @@ import { invariant } from '@epic-web/invariant' -import { data as dataResponse, redirect } from '@remix-run/node' +import { data, redirect } from '@remix-run/node' import { prisma } from '#app/utils/db.server.ts' import { verifySessionStorage } from '#app/utils/verification.server.ts' import { resetPasswordUsernameSessionKey } from './reset-password.tsx' @@ -18,7 +18,7 @@ export async function handleVerification({ submission }: VerifyFunctionArgs) { // we don't want to say the user is not found if the email is not found // because that would allow an attacker to check if an email is registered if (!user) { - return dataResponse( + return data( { result: submission.reply({ fieldErrors: { code: ['Invalid code'] } }) }, { status: 400 }, ) diff --git a/app/routes/_auth+/reset-password.tsx b/app/routes/_auth+/reset-password.tsx index 6bf0a66b8..a78e3057e 100644 --- a/app/routes/_auth+/reset-password.tsx +++ b/app/routes/_auth+/reset-password.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, type ActionFunctionArgs, type LoaderFunctionArgs, @@ -51,7 +51,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: ResetPasswordSchema, }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/_auth+/signup.tsx b/app/routes/_auth+/signup.tsx index 7fbf32423..ea65f5596 100644 --- a/app/routes/_auth+/signup.tsx +++ b/app/routes/_auth+/signup.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import * as E from '@react-email/components' import { - data as dataResponse, + data, redirect, type ActionFunctionArgs, type MetaFunction, @@ -56,7 +56,7 @@ export async function action({ request }: ActionFunctionArgs) { async: true, }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -78,7 +78,7 @@ export async function action({ request }: ActionFunctionArgs) { if (response.status === 'success') { return redirect(redirectTo.toString()) } else { - return dataResponse( + return data( { result: submission.reply({ formErrors: [response.error.message] }), }, diff --git a/app/routes/_auth+/verify.server.ts b/app/routes/_auth+/verify.server.ts index 710b5cc41..337df0d12 100644 --- a/app/routes/_auth+/verify.server.ts +++ b/app/routes/_auth+/verify.server.ts @@ -1,6 +1,6 @@ import { type Submission } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' -import { data as dataResponse } from '@remix-run/node' +import { data } from '@remix-run/node' import { z } from 'zod' import { handleVerification as handleChangeEmailVerification } from '#app/routes/settings+/profile.change-email.server.tsx' import { twoFAVerificationType } from '#app/routes/settings+/profile.two-factor.tsx' @@ -161,7 +161,7 @@ export async function validateRequest( }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/resources+/theme-switch.tsx b/app/routes/resources+/theme-switch.tsx index 9b6f9c114..21a165cec 100644 --- a/app/routes/resources+/theme-switch.tsx +++ b/app/routes/resources+/theme-switch.tsx @@ -1,7 +1,7 @@ import { useForm, getFormProps } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' -import { data as dataResponse, type ActionFunctionArgs } from '@remix-run/node' +import { data, type ActionFunctionArgs } from '@remix-run/node' import { redirect, useFetcher, useFetchers } from '@remix-run/react' import { ServerOnly } from 'remix-utils/server-only' import { z } from 'zod' @@ -32,7 +32,7 @@ export async function action({ request }: ActionFunctionArgs) { if (redirectTo) { return redirect(redirectTo, responseInit) } else { - return dataResponse({ result: submission.reply() }, responseInit) + return data({ result: submission.reply() }, responseInit) } } diff --git a/app/routes/settings+/profile.change-email.server.tsx b/app/routes/settings+/profile.change-email.server.tsx index acdc9965d..675cc617b 100644 --- a/app/routes/settings+/profile.change-email.server.tsx +++ b/app/routes/settings+/profile.change-email.server.tsx @@ -1,6 +1,6 @@ import { invariant } from '@epic-web/invariant' import * as E from '@react-email/components' -import { data as dataResponse } from '@remix-run/node' +import { data } from '@remix-run/node' import { requireRecentVerification, type VerifyFunctionArgs, @@ -26,7 +26,7 @@ export async function handleVerification({ ) const newEmail = verifySession.get(newEmailAddressSessionKey) if (!newEmail) { - return dataResponse( + return data( { result: submission.reply({ formErrors: [ diff --git a/app/routes/settings+/profile.change-email.tsx b/app/routes/settings+/profile.change-email.tsx index e7346307f..00893a936 100644 --- a/app/routes/settings+/profile.change-email.tsx +++ b/app/routes/settings+/profile.change-email.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, type ActionFunctionArgs, type LoaderFunctionArgs, @@ -70,7 +70,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) @@ -97,7 +97,7 @@ export async function action({ request }: ActionFunctionArgs) { }, }) } else { - return dataResponse( + return data( { result: submission.reply({ formErrors: [response.error.message] }) }, { status: 500 }, ) diff --git a/app/routes/settings+/profile.connections.tsx b/app/routes/settings+/profile.connections.tsx index 4255bdb9a..d0f48ef52 100644 --- a/app/routes/settings+/profile.connections.tsx +++ b/app/routes/settings+/profile.connections.tsx @@ -1,7 +1,7 @@ import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, type LoaderFunctionArgs, type ActionFunctionArgs, type SerializeFrom, @@ -81,7 +81,7 @@ export async function loader({ request }: LoaderFunctionArgs) { }) } - return dataResponse( + return data( { connections, canDeleteConnections: await userCanDeleteConnections(userId), @@ -120,7 +120,7 @@ export async function action({ request }: ActionFunctionArgs) { title: 'Deleted', description: 'Your connection has been deleted.', }) - return dataResponse({ status: 'success' } as const, { headers: toastHeaders }) + return data({ status: 'success' } as const, { headers: toastHeaders }) } export default function Connections() { diff --git a/app/routes/settings+/profile.index.tsx b/app/routes/settings+/profile.index.tsx index 21b479c14..f3b91b1ca 100644 --- a/app/routes/settings+/profile.index.tsx +++ b/app/routes/settings+/profile.index.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, type LoaderFunctionArgs, type ActionFunctionArgs, } from '@remix-run/node' @@ -194,7 +194,7 @@ async function profileUpdateAction({ userId, formData }: ProfileActionArgs) { }), }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/settings+/profile.password.tsx b/app/routes/settings+/profile.password.tsx index 99a5f176a..f239936a2 100644 --- a/app/routes/settings+/profile.password.tsx +++ b/app/routes/settings+/profile.password.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -83,7 +83,7 @@ export async function action({ request }: ActionFunctionArgs) { ), }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply({ hideFields: ['currentPassword', 'newPassword', 'confirmNewPassword'], diff --git a/app/routes/settings+/profile.password_.create.tsx b/app/routes/settings+/profile.password_.create.tsx index d1b7c1046..ff4bba618 100644 --- a/app/routes/settings+/profile.password_.create.tsx +++ b/app/routes/settings+/profile.password_.create.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -50,7 +50,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: CreatePasswordForm, }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply({ hideFields: ['password', 'confirmPassword'], diff --git a/app/routes/settings+/profile.photo.tsx b/app/routes/settings+/profile.photo.tsx index f731d7c85..8b0839811 100644 --- a/app/routes/settings+/profile.photo.tsx +++ b/app/routes/settings+/profile.photo.tsx @@ -3,7 +3,7 @@ import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, unstable_createMemoryUploadHandler, unstable_parseMultipartFormData, @@ -96,7 +96,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/settings+/profile.two-factor.verify.tsx b/app/routes/settings+/profile.two-factor.verify.tsx index 002e99ed4..a8e7f4381 100644 --- a/app/routes/settings+/profile.two-factor.verify.tsx +++ b/app/routes/settings+/profile.two-factor.verify.tsx @@ -2,7 +2,7 @@ import { getFormProps, getInputProps, useForm } from '@conform-to/react' import { getZodConstraint, parseWithZod } from '@conform-to/zod' import { type SEOHandle } from '@nasa-gcn/remix-seo' import { - data as dataResponse, + data, redirect, type LoaderFunctionArgs, type ActionFunctionArgs, @@ -102,7 +102,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/$username_+/__note-editor.server.tsx b/app/routes/users+/$username_+/__note-editor.server.tsx index 2a1b2315c..0ccc5410c 100644 --- a/app/routes/users+/$username_+/__note-editor.server.tsx +++ b/app/routes/users+/$username_+/__note-editor.server.tsx @@ -2,7 +2,7 @@ import { parseWithZod } from '@conform-to/zod' import { createId as cuid } from '@paralleldrive/cuid2' import { unstable_createMemoryUploadHandler as createMemoryUploadHandler, - data as dataResponse, + data, unstable_parseMultipartFormData as parseMultipartFormData, redirect, type ActionFunctionArgs, @@ -88,7 +88,7 @@ export async function action({ request }: ActionFunctionArgs) { }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/$username_+/notes.$noteId.tsx b/app/routes/users+/$username_+/notes.$noteId.tsx index 624be37be..54cd0bd6b 100644 --- a/app/routes/users+/$username_+/notes.$noteId.tsx +++ b/app/routes/users+/$username_+/notes.$noteId.tsx @@ -2,7 +2,7 @@ import { getFormProps, useForm } from '@conform-to/react' import { parseWithZod } from '@conform-to/zod' import { invariantResponse } from '@epic-web/invariant' import { - data as dataResponse, + data, type LoaderFunctionArgs, type ActionFunctionArgs, } from '@remix-run/node' @@ -67,7 +67,7 @@ export async function action({ request }: ActionFunctionArgs) { schema: DeleteFormSchema, }) if (submission.status !== 'success') { - return dataResponse( + return data( { result: submission.reply() }, { status: submission.status === 'error' ? 400 : 200 }, ) diff --git a/app/routes/users+/index.tsx b/app/routes/users+/index.tsx index 5022cdd7e..7c321af60 100644 --- a/app/routes/users+/index.tsx +++ b/app/routes/users+/index.tsx @@ -1,8 +1,4 @@ -import { - data as dataResponse, - redirect, - type LoaderFunctionArgs, -} from '@remix-run/node' +import { data, redirect, type LoaderFunctionArgs } from '@remix-run/node' import { Link, useLoaderData } from '@remix-run/react' import { z } from 'zod' import { GeneralErrorBoundary } from '#app/components/error-boundary.tsx' @@ -45,10 +41,9 @@ export async function loader({ request }: LoaderFunctionArgs) { const result = UserSearchResultsSchema.safeParse(rawUsers) if (!result.success) { - return dataResponse( - { status: 'error', error: result.error.message } as const, - { status: 400 }, - ) + return data({ status: 'error', error: result.error.message } as const, { + status: 400, + }) } return { status: 'idle', users: result.data } as const } diff --git a/app/utils/permissions.server.ts b/app/utils/permissions.server.ts index 55b569d43..74aa5aa82 100644 --- a/app/utils/permissions.server.ts +++ b/app/utils/permissions.server.ts @@ -1,4 +1,4 @@ -import { data as dataResponse } from '@remix-run/node' +import { data } from '@remix-run/node' import { requireUserId } from './auth.server.ts' import { prisma } from './db.server.ts' import { type PermissionString, parsePermissionString } from './user.ts' @@ -28,7 +28,7 @@ export async function requireUserWithPermission( }, }) if (!user) { - throw dataResponse( + throw data( { error: 'Unauthorized', requiredPermission: permissionData, @@ -47,7 +47,7 @@ export async function requireUserWithRole(request: Request, name: string) { where: { id: userId, roles: { some: { name } } }, }) if (!user) { - throw dataResponse( + throw data( { error: 'Unauthorized', requiredRole: name, From 6b40b78b4f41bd7e1943c7a8dfd86d48edc3837a Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 21:45:24 +0000 Subject: [PATCH 08/11] remove installGlobals --- index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.js b/index.js index 8317efc79..24525b284 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,7 @@ import 'dotenv/config' import * as fs from 'node:fs' -import { installGlobals } from '@remix-run/node' import sourceMapSupport from 'source-map-support' -installGlobals({ nativeFetch: true }) sourceMapSupport.install({ retrieveSourceMap: function (source) { From 5044ab5fdd0862b51220a70ab4560e5f5087bb3b Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Wed, 16 Oct 2024 21:53:10 +0000 Subject: [PATCH 09/11] fix typecheck --- app/routes/settings+/profile.index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/routes/settings+/profile.index.tsx b/app/routes/settings+/profile.index.tsx index f3b91b1ca..65eafda82 100644 --- a/app/routes/settings+/profile.index.tsx +++ b/app/routes/settings+/profile.index.tsx @@ -200,14 +200,14 @@ async function profileUpdateAction({ userId, formData }: ProfileActionArgs) { ) } - const data = submission.value + const { username, name } = submission.value await prisma.user.update({ select: { username: true }, where: { id: userId }, data: { - name: data.name, - username: data.username, + name: name, + username: username, }, }) From 359f4942f9109ae897291845fb19907b803e3e4b Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Sun, 20 Oct 2024 09:03:19 +0000 Subject: [PATCH 10/11] rename auth.$provider to auth_.$provider --- app/routes/_auth+/{auth.$provider.ts => auth_.$provider.ts} | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) rename app/routes/_auth+/{auth.$provider.ts => auth_.$provider.ts} (88%) diff --git a/app/routes/_auth+/auth.$provider.ts b/app/routes/_auth+/auth_.$provider.ts similarity index 88% rename from app/routes/_auth+/auth.$provider.ts rename to app/routes/_auth+/auth_.$provider.ts index eb524cc03..7231920c7 100644 --- a/app/routes/_auth+/auth.$provider.ts +++ b/app/routes/_auth+/auth_.$provider.ts @@ -1,10 +1,14 @@ -import { type ActionFunctionArgs } from '@remix-run/node' +import { redirect, type ActionFunctionArgs } from '@remix-run/node' import { authenticator } from '#app/utils/auth.server.ts' import { handleMockAction } from '#app/utils/connections.server.ts' import { ProviderNameSchema } from '#app/utils/connections.tsx' import { getReferrerRoute } from '#app/utils/misc.tsx' import { getRedirectCookieHeader } from '#app/utils/redirect-cookie.server.ts' +export async function loader() { + return redirect('/login') +} + export async function action({ request, params }: ActionFunctionArgs) { const providerName = ProviderNameSchema.parse(params.provider) From bc898bc80fabcc11dffe5a65b3415d2babe554b0 Mon Sep 17 00:00:00 2001 From: Hakim Gueye Date: Mon, 21 Oct 2024 23:48:12 +0000 Subject: [PATCH 11/11] enable v3_singleFetch --- vite.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/vite.config.ts b/vite.config.ts index 602849bd9..0ff2cf83d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -53,6 +53,7 @@ export default defineConfig({ v3_lazyRouteDiscovery: true, v3_relativeSplatPath: true, v3_throwAbortReason: true, + v3_singleFetch: true, }, routes: async (defineRoutes) => { return flatRoutes('routes', defineRoutes, {