From 302ce9561b43cfe7a9b32c1d001f5e253557bd73 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 16 Aug 2024 17:26:12 +0900 Subject: [PATCH 01/21] feat: add auth cookie session storage --- .gitignore | 5 ++++- app/constants/types/auth.ts | 4 ++++ app/constants/types/env.ts | 19 +++++++++++++++++++ functions/[[path]].ts | 26 ++++++++++++++++++++++++-- 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 app/constants/types/auth.ts create mode 100644 app/constants/types/env.ts diff --git a/.gitignore b/.gitignore index 2f2b56c..f190f13 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,7 @@ node_modules # macOS .DS_Store -*storybook.log \ No newline at end of file +*storybook.log + +# env +.dev.vars \ No newline at end of file diff --git a/app/constants/types/auth.ts b/app/constants/types/auth.ts new file mode 100644 index 0000000..cb5bd58 --- /dev/null +++ b/app/constants/types/auth.ts @@ -0,0 +1,4 @@ +export interface AuthSessionData { + accessToken: string; + refreshToken: string; +} diff --git a/app/constants/types/env.ts b/app/constants/types/env.ts new file mode 100644 index 0000000..a0011e1 --- /dev/null +++ b/app/constants/types/env.ts @@ -0,0 +1,19 @@ +import type { + LoaderFunctionArgs, + LoaderFunction, + SessionData, + SessionStorage, +} from '@remix-run/cloudflare'; + +export interface Env { + KV_NAMESPACE: KVNamespace; + AUTH_COOKIE_SESSION_SECRET: string; +} + +export type LoaderFunctionWithContext = ( + args: LoaderFunctionArgs & { + context: Env & { + authSessionStorage: SessionStorage; + }; + }, +) => ReturnType; diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 9440dce..fbb5401 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -1,8 +1,30 @@ +import { + createWorkersKVSessionStorage, + createCookie, +} from '@remix-run/cloudflare'; import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; +import type { AuthSessionData } from '@/constants/types/auth'; +import type { Env } from '@/constants/types/env'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` -// eslint-disable-next-line import/no-unresolved +// eslint-disable-next-line import/no-unresolved, import/order import * as build from '../build/server'; -export const onRequest = createPagesFunctionHandler({ build }); +export const onRequest = createPagesFunctionHandler({ + build, + getLoadContext: ({ context }) => { + const sessionCookie = createCookie('__auth_session', { + secrets: [context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET], + sameSite: true, + }); + const authSessionStorage = createWorkersKVSessionStorage({ + cookie: sessionCookie, + kv: context.cloudflare.env.KV_NAMESPACE, + }); + return { + ...context.cloudflare.env, + authSessionStorage, + }; + }, +}); From 1a1578cf42f91cd7383d18f8199acb2508d972d3 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 16 Aug 2024 18:09:41 +0900 Subject: [PATCH 02/21] refactor: add `AuthSessionStorage` type --- app/constants/types/auth.ts | 4 ++++ app/constants/types/env.ts | 14 +++++--------- functions/[[path]].ts | 9 +++++++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/constants/types/auth.ts b/app/constants/types/auth.ts index cb5bd58..8fa8da8 100644 --- a/app/constants/types/auth.ts +++ b/app/constants/types/auth.ts @@ -1,4 +1,8 @@ +import type { SessionStorage } from '@remix-run/cloudflare'; + export interface AuthSessionData { accessToken: string; refreshToken: string; } + +export type AuthSessionStorage = SessionStorage; diff --git a/app/constants/types/env.ts b/app/constants/types/env.ts index a0011e1..af4d09e 100644 --- a/app/constants/types/env.ts +++ b/app/constants/types/env.ts @@ -1,19 +1,15 @@ -import type { - LoaderFunctionArgs, - LoaderFunction, - SessionData, - SessionStorage, -} from '@remix-run/cloudflare'; +import type { LoaderFunctionArgs, LoaderFunction } from '@remix-run/cloudflare'; +import type { AuthSessionStorage } from './auth'; -export interface Env { +export type Env = { KV_NAMESPACE: KVNamespace; AUTH_COOKIE_SESSION_SECRET: string; -} +}; export type LoaderFunctionWithContext = ( args: LoaderFunctionArgs & { context: Env & { - authSessionStorage: SessionStorage; + authSessionStorage: AuthSessionStorage; }; }, ) => ReturnType; diff --git a/functions/[[path]].ts b/functions/[[path]].ts index fbb5401..031b003 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -3,7 +3,10 @@ import { createCookie, } from '@remix-run/cloudflare'; import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; -import type { AuthSessionData } from '@/constants/types/auth'; +import type { + AuthSessionData, + AuthSessionStorage, +} from '@/constants/types/auth'; import type { Env } from '@/constants/types/env'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -13,7 +16,9 @@ import * as build from '../build/server'; export const onRequest = createPagesFunctionHandler({ build, - getLoadContext: ({ context }) => { + getLoadContext: ({ + context, + }): Env & { authSessionStorage: AuthSessionStorage } => { const sessionCookie = createCookie('__auth_session', { secrets: [context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET], sameSite: true, From 4133accbd38a54d2b7ebe7dd485aed30e0162e74 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 30 Aug 2024 16:59:17 +0900 Subject: [PATCH 03/21] feat: add api base code --- .gitignore | 8 +- app/constants/api.ts | 34 + app/constants/types/api.ts | 25 + app/constants/types/auth.ts | 7 +- app/constants/types/env.ts | 15 - app/utils/api.server.ts | 154 ++ app/utils/auth.server.ts | 90 ++ app/vite-env.d.ts | 9 + functions/[[path]].ts | 80 +- package.json | 32 +- pnpm-lock.yaml | 2717 +++++++++++++++++++---------------- 11 files changed, 1904 insertions(+), 1267 deletions(-) create mode 100644 app/constants/api.ts create mode 100644 app/constants/types/api.ts delete mode 100644 app/constants/types/env.ts create mode 100644 app/utils/api.server.ts create mode 100644 app/utils/auth.server.ts create mode 100644 app/vite-env.d.ts diff --git a/.gitignore b/.gitignore index f190f13..ce5df80 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,15 @@ node_modules /.cache /build -.env +.wrangler # macOS .DS_Store *storybook.log # env -.dev.vars \ No newline at end of file +.env +.env.local +.dev.vars + +wrangler.toml \ No newline at end of file diff --git a/app/constants/api.ts b/app/constants/api.ts new file mode 100644 index 0000000..6c5dff0 --- /dev/null +++ b/app/constants/api.ts @@ -0,0 +1,34 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +interface ClientError { + status?: number; + message?: string; + path: string; + /** TODO: 서버 쪽 schema 전달되면 타입 수정 */ + serverError?: any; + request?: any; + clientError?: any; +} + +export class ApiError extends Error { + public status?: number; + + public path: string; + + /** TODO: 서버 쪽 schema 전달되면 타입 수정 */ + public serverError?: any; + + public request?: any; + + public clientError?: any; + + constructor(error: ClientError) { + super(error.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해주세요.'); + this.name = 'ApiError'; + this.status = error.status ?? error.serverError?.status; + this.path = error.path; + this.serverError = error.serverError; + this.request = error.request; + this.clientError = error.clientError; + } +} diff --git a/app/constants/types/api.ts b/app/constants/types/api.ts new file mode 100644 index 0000000..e67ae36 --- /dev/null +++ b/app/constants/types/api.ts @@ -0,0 +1,25 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export interface ApiRequest { + pathParams?: (string | number)[]; + headers?: Record; + params?: Record; + body?: any; +} + +export interface ApiInfo { + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + endpoint: `/${string}`; + needToLogin: boolean; + baseUrl?: string; + errorMessage?: { + messageByStatus?: Record; + }; + request: (variables: Variables) => ApiRequest; + _resultType?: Result; +} + +export type FetchApi = ( + apiInfo: ApiInfo, + variables: Variables, +) => Promise; diff --git a/app/constants/types/auth.ts b/app/constants/types/auth.ts index 8fa8da8..deec05a 100644 --- a/app/constants/types/auth.ts +++ b/app/constants/types/auth.ts @@ -1,8 +1,13 @@ -import type { SessionStorage } from '@remix-run/cloudflare'; +import type { Session, SessionStorage } from '@remix-run/cloudflare'; export interface AuthSessionData { accessToken: string; + /** ISO String (ex: 2024-08-16T15:59:55.762599902Z) */ + accessTokenExpiresAt: string; refreshToken: string; + /** ISO String (ex: 2024-08-16T15:59:55.762599902Z) */ + refreshTokenExpiresAt: string; } export type AuthSessionStorage = SessionStorage; +export type AuthSession = Session; diff --git a/app/constants/types/env.ts b/app/constants/types/env.ts deleted file mode 100644 index af4d09e..0000000 --- a/app/constants/types/env.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { LoaderFunctionArgs, LoaderFunction } from '@remix-run/cloudflare'; -import type { AuthSessionStorage } from './auth'; - -export type Env = { - KV_NAMESPACE: KVNamespace; - AUTH_COOKIE_SESSION_SECRET: string; -}; - -export type LoaderFunctionWithContext = ( - args: LoaderFunctionArgs & { - context: Env & { - authSessionStorage: AuthSessionStorage; - }; - }, -) => ReturnType; diff --git a/app/utils/api.server.ts b/app/utils/api.server.ts new file mode 100644 index 0000000..38956af --- /dev/null +++ b/app/utils/api.server.ts @@ -0,0 +1,154 @@ +import { getAuthToken } from './auth.server'; +import { ApiError } from '@/constants/api'; +import type { ApiInfo } from '@/constants/types/api'; +import type { AuthSession } from '@/constants/types/auth'; + +const COMMON_ERROR: { + errorByStatus: Record< + number, + { + message: string; + } + >; +} = { + errorByStatus: { + 401: { + message: '로그인이 필요합니다', + }, + }, +}; + +export const api = + () => + ( + apiInfo: Omit, '_resultType'>, + ): ApiInfo => + apiInfo; + +export const fetchApi = async ( + apiInfo: ApiInfo, + variables: Variables, + apiUrl: string, + authSession?: AuthSession, +): Promise => { + const baseUrl = apiInfo.baseUrl ?? apiUrl; + const url = `${baseUrl}${apiInfo.endpoint}`; + const parsedRequest = apiInfo.request(variables); + + const pathString = + parsedRequest.pathParams?.reduce( + (prev, cur) => `${prev}/${cur}`, + '', + ) ?? ''; + + const params = parsedRequest.params ?? {}; + const queryString = Object.keys(params).reduce( + (prev, cur) => + `${prev}${ + params[cur] !== null && params[cur] !== undefined + ? `&${cur}=${params[cur]}` + : '' + }`, + '', + ); + + const fetchUrl = `${url}${pathString}${ + queryString ? `?${queryString.slice(1)}` : '' + }`; + + try { + const token = authSession ? await getAuthToken(authSession, apiUrl) : null; + + if (!token?.accessToken && apiInfo.needToLogin) { + throw new ApiError({ + status: 401, + path: fetchUrl, + request: parsedRequest, + ...COMMON_ERROR.errorByStatus[401], + }); + } + + const authorizationHeader = token?.accessToken + ? { + Authorization: `Bearer ${token.accessToken}`, + } + : undefined; + + const response = await fetch(fetchUrl, { + method: apiInfo.method, + body: + // eslint-disable-next-line no-nested-ternary + parsedRequest.body !== undefined + ? parsedRequest.body instanceof FormData + ? parsedRequest.body + : JSON.stringify(parsedRequest.body) + : undefined, + headers: { + 'Content-Type': + parsedRequest.body instanceof FormData + ? 'multipart/form-data' + : 'application/json', + ...authorizationHeader, + ...parsedRequest.headers, + }, + }); + + // `Result`가 `null`인 경우가 있지만 이는 try-catch에 의한 것으로, 타입 체계상에서는 분기처리할 수 없음 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let result: any; + try { + result = await response.json(); + } catch (error) { + console.log(error, `${apiInfo.method} ${apiInfo.endpoint}`); + result = null; + } + + if (response.ok) { + return result; + } + + // TODO: 서버 쪽 schema 전달되면 타입 수정 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const serverError: any = result; + + const error: { + message?: string; + } = {}; + + // common error message (by status) - 3rd priority + error.message = + COMMON_ERROR.errorByStatus[response.status]?.message ?? error.message; + + // error message by status - 2nd priority + error.message = + apiInfo.errorMessage?.messageByStatus?.[response.status]?.message ?? + error.message; + + // error message from server - 1st priority + if (serverError.message) { + error.message = serverError.message ?? error.message; + } + + throw new ApiError({ + ...error, + status: response.status, + path: apiInfo.endpoint, + serverError: result, + request: parsedRequest, + }); + } catch (error) { + // 이미 처리된 에러는 그대로 반환 + if (error instanceof ApiError) { + console.log(error.serverError); + throw error; + } + + // TODO: Sentry 등 에러 로깅 솔루션 추가 + console.error(error, apiInfo.request(variables), fetchUrl); + throw new ApiError({ + path: apiInfo.endpoint, + request: parsedRequest, + clientError: error, + }); + } +}; diff --git a/app/utils/auth.server.ts b/app/utils/auth.server.ts new file mode 100644 index 0000000..2fcef13 --- /dev/null +++ b/app/utils/auth.server.ts @@ -0,0 +1,90 @@ +import type { AuthSession, AuthSessionData } from '@/constants/types/auth'; + +export const clearAuthToken = async (authSession: AuthSession) => { + authSession.unset('accessToken'); + authSession.unset('accessTokenExpiresAt'); + authSession.unset('refreshToken'); + authSession.unset('refreshTokenExpiresAt'); +}; + +export const updateAuthToken = async ( + authSession: AuthSession, + newToken: Partial, +) => { + (Object.keys(newToken) as (keyof typeof newToken)[]).forEach((key) => { + if (newToken[key]) { + authSession.set(key, newToken[key]); + } + }); +}; + +export const getAuthToken = async ( + authSession: AuthSession, + apiUrl: string, +): Promise<{ + accessToken: string; + refreshToken: string; +} | null> => { + const accessToken = authSession.get('accessToken'); + const accessTokenExpiresAtString = authSession.get('accessTokenExpiresAt'); + const refreshToken = authSession.get('refreshToken'); + const refreshTokenExpiresAtString = authSession.get('refreshTokenExpiresAt'); + + if ( + accessToken === undefined || + refreshToken === undefined || + accessTokenExpiresAtString === undefined || + refreshTokenExpiresAtString === undefined + ) { + await clearAuthToken(authSession); + return null; + } + + const accessTokenExpiresAt = new Date(accessTokenExpiresAtString); + const refreshTokenExpiresAt = new Date(refreshTokenExpiresAtString); + + const now = new Date(); + + // access token 만료 (서버 응답 시간 등을 고려해 1분 여유 포함) + if (accessTokenExpiresAt.getTime() + 1000 * 60 >= now.getTime()) { + // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) + if (refreshTokenExpiresAt.getTime() + 1000 * 60 < now.getTime()) { + try { + const response = await fetch(`${apiUrl}/token/access`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + refreshToken, + }), + }); + const result = await response.json<{ + accessToken: string; + accessTokenExpiresAt: string; + }>(); + + await updateAuthToken(authSession, { + accessToken: result.accessToken, + accessTokenExpiresAt: result.accessTokenExpiresAt, + }); + + return { + accessToken: result.accessToken, + refreshToken, + }; + } catch (error) { + console.error(error); + } + } + + // refresh token 만료, 또는 서버 오류 + await clearAuthToken(authSession); + return null; + } + + return { + accessToken, + refreshToken, + }; +}; diff --git a/app/vite-env.d.ts b/app/vite-env.d.ts new file mode 100644 index 0000000..7ed3a44 --- /dev/null +++ b/app/vite-env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_KAKAO_CLIENT_ID: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 031b003..4d374ad 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -3,33 +3,65 @@ import { createCookie, } from '@remix-run/cloudflare'; import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; -import type { - AuthSessionData, - AuthSessionStorage, -} from '@/constants/types/auth'; -import type { Env } from '@/constants/types/env'; +import type { FetchApi } from '@/constants/types/api'; +import type { AuthSession, AuthSessionData } from '@/constants/types/auth'; +import { fetchApi } from '@/utils/api.server'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` // eslint-disable-next-line import/no-unresolved, import/order import * as build from '../build/server'; -export const onRequest = createPagesFunctionHandler({ - build, - getLoadContext: ({ - context, - }): Env & { authSessionStorage: AuthSessionStorage } => { - const sessionCookie = createCookie('__auth_session', { - secrets: [context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET], - sameSite: true, - }); - const authSessionStorage = createWorkersKVSessionStorage({ - cookie: sessionCookie, - kv: context.cloudflare.env.KV_NAMESPACE, - }); - return { - ...context.cloudflare.env, - authSessionStorage, - }; - }, -}); +type ContextEnv = { + readonly KV_NAMESPACE: KVNamespace; + readonly AUTH_COOKIE_SESSION_SECRET: string; + readonly API_URL: string; +}; + +declare module '@remix-run/cloudflare' { + interface AppLoadContext extends ContextEnv { + authSession: AuthSession; + fetchApi: FetchApi; + } +} + +export const onRequest = async ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + context: EventContext, +): Promise => { + const authSessionCookie = createCookie('__auth_session', { + secrets: [context.env.AUTH_COOKIE_SESSION_SECRET], + sameSite: true, + }); + const authSessionStorage = createWorkersKVSessionStorage({ + cookie: authSessionCookie, + kv: context.env.KV_NAMESPACE, + }); + const authSession = await authSessionStorage.getSession( + context.request.headers.get('Cookie'), + ); + + const handleRequest = createPagesFunctionHandler({ + build, + getLoadContext: ({ context: loadContext }) => ({ + ...loadContext.cloudflare.env, + authSession, + fetchApi: async (apiInfo, variables) => + fetchApi( + apiInfo, + variables, + loadContext.cloudflare.env.API_URL, + authSession, + ), + }), + }); + + const response = await handleRequest(context); + + response.headers.append( + 'Set-Cookie', + await authSessionStorage.commitSession(authSession), + ); + + return response; +}; diff --git a/package.json b/package.json index 50a3aff..4656002 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "module", "scripts": { "build": "remix vite:build", - "dev": "remix vite:dev", + "dev": "wrangler pages download config ort-web --force && remix vite:build && wrangler pages dev --live-reload ./build/client", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc", @@ -16,10 +16,10 @@ "build-storybook": "storybook build" }, "dependencies": { - "@remix-run/cloudflare": "2.10.2", - "@remix-run/cloudflare-pages": "2.10.2", - "@remix-run/react": "2.10.2", - "@remix-run/serve": "2.10.2", + "@remix-run/cloudflare": "2.11.2", + "@remix-run/cloudflare-pages": "2.11.2", + "@remix-run/react": "2.11.2", + "@remix-run/serve": "2.11.2", "@vanilla-extract/css": "1.15.3", "isbot": "4.4.0", "react": "18.3.1", @@ -28,15 +28,15 @@ "devDependencies": { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", - "@remix-run/dev": "2.10.2", - "@remix-run/testing": "2.10.2", - "@storybook/addon-essentials": "8.2.5", - "@storybook/addon-interactions": "8.2.5", - "@storybook/addon-links": "8.2.5", - "@storybook/blocks": "8.2.5", - "@storybook/react": "8.2.5", - "@storybook/react-vite": "8.2.5", - "@storybook/test": "8.2.5", + "@remix-run/dev": "2.11.2", + "@remix-run/testing": "2.11.2", + "@storybook/addon-essentials": "8.2.9", + "@storybook/addon-interactions": "8.2.9", + "@storybook/addon-links": "8.2.9", + "@storybook/blocks": "8.2.9", + "@storybook/react": "8.2.9", + "@storybook/react-vite": "8.2.9", + "@storybook/test": "8.2.9", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@typescript-eslint/eslint-plugin": "7.16.0", @@ -54,11 +54,11 @@ "husky": "9.1.1", "lint-staged": "15.2.7", "prettier": "3.3.3", - "storybook": "8.2.5", + "storybook": "8.2.9", "typescript": "5.5.3", "vite": "5.3.3", "vite-tsconfig-paths": "4.3.2", - "wrangler": "3.66.0" + "wrangler": "3.72.2" }, "engines": { "node": ">=20.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dad78ef..d4a56c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,17 +9,17 @@ importers: .: dependencies: '@remix-run/cloudflare': - specifier: 2.10.2 - version: 2.10.2(@cloudflare/workers-types@4.20240722.0)(typescript@5.5.3) + specifier: 2.11.2 + version: 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) '@remix-run/cloudflare-pages': - specifier: 2.10.2 - version: 2.10.2(@cloudflare/workers-types@4.20240722.0)(typescript@5.5.3) + specifier: 2.11.2 + version: 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) '@remix-run/react': - specifier: 2.10.2 - version: 2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + specifier: 2.11.2 + version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@remix-run/serve': - specifier: 2.10.2 - version: 2.10.2(typescript@5.5.3) + specifier: 2.11.2 + version: 2.11.2(typescript@5.5.3) '@vanilla-extract/css': specifier: 1.15.3 version: 1.15.3 @@ -35,37 +35,37 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.3.0 - version: 19.3.0(@types/node@20.14.12)(typescript@5.5.3) + version: 19.3.0(@types/node@22.5.0)(typescript@5.5.3) '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 '@remix-run/dev': - specifier: 2.10.2 - version: 2.10.2(@remix-run/react@2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.10.2(typescript@5.5.3))(@types/node@20.14.12)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12))(wrangler@3.66.0(@cloudflare/workers-types@4.20240722.0)) + specifier: 2.11.2 + version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.0)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1)) '@remix-run/testing': - specifier: 2.10.2 - version: 2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + specifier: 2.11.2 + version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@storybook/addon-essentials': - specifier: 8.2.5 - version: 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + specifier: 8.2.9 + version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-interactions': - specifier: 8.2.5 - version: 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + specifier: 8.2.9 + version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-links': - specifier: 8.2.5 - version: 8.2.5(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + specifier: 8.2.9 + version: 8.2.9(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/blocks': - specifier: 8.2.5 - version: 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + specifier: 8.2.9 + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/react': - specifier: 8.2.5 - version: 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3) + specifier: 8.2.9 + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) '@storybook/react-vite': - specifier: 8.2.5 - version: 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.19.0)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12)) + specifier: 8.2.9 + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) '@storybook/test': - specifier: 8.2.5 - version: 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + specifier: 8.2.9 + version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/react': specifier: 18.3.3 version: 18.3.3 @@ -80,10 +80,10 @@ importers: version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) '@vanilla-extract/vite-plugin': specifier: 4.0.13 - version: 4.0.13(@types/node@20.14.12)(vite@5.3.3(@types/node@20.14.12)) + version: 4.0.13(@types/node@22.5.0)(vite@5.3.3(@types/node@22.5.0)) autoprefixer: specifier: 10.4.19 - version: 10.4.19(postcss@8.4.39) + version: 10.4.19(postcss@8.4.41) eslint: specifier: 8.57.0 version: 8.57.0 @@ -118,20 +118,20 @@ importers: specifier: 3.3.3 version: 3.3.3 storybook: - specifier: 8.2.5 - version: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + specifier: 8.2.9 + version: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) typescript: specifier: 5.5.3 version: 5.5.3 vite: specifier: 5.3.3 - version: 5.3.3(@types/node@20.14.12) + version: 5.3.3(@types/node@22.5.0) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12)) + version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) wrangler: - specifier: 3.66.0 - version: 3.66.0(@cloudflare/workers-types@4.20240722.0) + specifier: 3.72.2 + version: 3.72.2(@cloudflare/workers-types@4.20240821.1) packages: @@ -146,16 +146,16 @@ packages: resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.24.9': - resolution: {integrity: sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==} + '@babel/compat-data@7.25.4': + resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.9': - resolution: {integrity: sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==} + '@babel/core@7.25.2': + resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.24.10': - resolution: {integrity: sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==} + '@babel/generator@7.25.5': + resolution: {integrity: sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.24.7': @@ -166,18 +166,18 @@ packages: resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.24.8': - resolution: {integrity: sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==} + '@babel/helper-compilation-targets@7.25.2': + resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.24.8': - resolution: {integrity: sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==} + '@babel/helper-create-class-features-plugin@7.25.4': + resolution: {integrity: sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.24.7': - resolution: {integrity: sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==} + '@babel/helper-create-regexp-features-plugin@7.25.2': + resolution: {integrity: sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -187,18 +187,6 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-environment-visitor@7.24.7': - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.24.7': - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.24.7': - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.24.8': resolution: {integrity: sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==} engines: {node: '>=6.9.0'} @@ -207,8 +195,8 @@ packages: resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.24.9': - resolution: {integrity: sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==} + '@babel/helper-module-transforms@7.25.2': + resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -221,14 +209,14 @@ packages: resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.24.7': - resolution: {integrity: sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==} + '@babel/helper-remap-async-to-generator@7.25.0': + resolution: {integrity: sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.24.7': - resolution: {integrity: sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==} + '@babel/helper-replace-supers@7.25.0': + resolution: {integrity: sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -241,10 +229,6 @@ packages: resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.24.7': - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.8': resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} engines: {node: '>=6.9.0'} @@ -257,31 +241,37 @@ packages: resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.24.7': - resolution: {integrity: sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==} + '@babel/helper-wrap-function@7.25.0': + resolution: {integrity: sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.24.8': - resolution: {integrity: sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==} + '@babel/helpers@7.25.0': + resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} engines: {node: '>=6.9.0'} '@babel/highlight@7.24.7': resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.24.8': - resolution: {integrity: sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==} + '@babel/parser@7.25.4': + resolution: {integrity: sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7': - resolution: {integrity: sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.3': + resolution: {integrity: sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7': - resolution: {integrity: sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.0': + resolution: {integrity: sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0': + resolution: {integrity: sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -292,8 +282,8 @@ packages: peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7': - resolution: {integrity: sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.0': + resolution: {integrity: sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -412,8 +402,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-typescript@7.24.7': - resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} + '@babel/plugin-syntax-typescript@7.25.4': + resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -430,8 +420,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.24.7': - resolution: {integrity: sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==} + '@babel/plugin-transform-async-generator-functions@7.25.4': + resolution: {integrity: sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -448,14 +438,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.24.7': - resolution: {integrity: sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==} + '@babel/plugin-transform-block-scoping@7.25.0': + resolution: {integrity: sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.24.7': - resolution: {integrity: sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==} + '@babel/plugin-transform-class-properties@7.25.4': + resolution: {integrity: sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -466,8 +456,8 @@ packages: peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.24.8': - resolution: {integrity: sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==} + '@babel/plugin-transform-classes@7.25.4': + resolution: {integrity: sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -496,6 +486,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0': + resolution: {integrity: sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/plugin-transform-dynamic-import@7.24.7': resolution: {integrity: sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==} engines: {node: '>=6.9.0'} @@ -514,8 +510,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-flow-strip-types@7.24.7': - resolution: {integrity: sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==} + '@babel/plugin-transform-flow-strip-types@7.25.2': + resolution: {integrity: sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -526,8 +522,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.24.7': - resolution: {integrity: sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==} + '@babel/plugin-transform-function-name@7.25.1': + resolution: {integrity: sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -538,8 +534,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.24.7': - resolution: {integrity: sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==} + '@babel/plugin-transform-literals@7.25.2': + resolution: {integrity: sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -568,8 +564,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.24.7': - resolution: {integrity: sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==} + '@babel/plugin-transform-modules-systemjs@7.25.0': + resolution: {integrity: sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -634,8 +630,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.24.7': - resolution: {integrity: sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==} + '@babel/plugin-transform-private-methods@7.25.4': + resolution: {integrity: sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -694,8 +690,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typescript@7.24.8': - resolution: {integrity: sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==} + '@babel/plugin-transform-typescript@7.25.2': + resolution: {integrity: sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -718,14 +714,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.24.7': - resolution: {integrity: sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==} + '@babel/plugin-transform-unicode-sets-regex@7.25.4': + resolution: {integrity: sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.24.8': - resolution: {integrity: sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==} + '@babel/preset-env@7.25.4': + resolution: {integrity: sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -756,20 +752,20 @@ packages: '@babel/regjsgen@0.8.0': resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - '@babel/runtime@7.24.8': - resolution: {integrity: sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==} + '@babel/runtime@7.25.4': + resolution: {integrity: sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==} engines: {node: '>=6.9.0'} - '@babel/template@7.24.7': - resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} + '@babel/template@7.25.0': + resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.8': - resolution: {integrity: sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==} + '@babel/traverse@7.25.4': + resolution: {integrity: sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==} engines: {node: '>=6.9.0'} - '@babel/types@7.24.9': - resolution: {integrity: sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==} + '@babel/types@7.25.4': + resolution: {integrity: sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==} engines: {node: '>=6.9.0'} '@base2/pretty-print-object@1.0.1': @@ -782,38 +778,42 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} - '@cloudflare/workerd-darwin-64@1.20240718.0': - resolution: {integrity: sha512-BsPZcSCgoGnufog2GIgdPuiKicYTNyO/Dp++HbpLRH+yQdX3x4aWx83M+a0suTl1xv76dO4g9aw7SIB6OSgIyQ==} + '@cloudflare/workerd-darwin-64@1.20240821.1': + resolution: {integrity: sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20240718.0': - resolution: {integrity: sha512-nlr4gaOO5gcJerILJQph3+2rnas/nx/lYsuaot1ntHu4LAPBoQo1q/Pucj2cSIav4UiMzTbDmoDwPlls4Kteog==} + '@cloudflare/workerd-darwin-arm64@1.20240821.1': + resolution: {integrity: sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@cloudflare/workerd-linux-64@1.20240718.0': - resolution: {integrity: sha512-LJ/k3y47pBcjax0ee4K+6ZRrSsqWlfU4lbU8Dn6u5tSC9yzwI4YFNXDrKWInB0vd7RT3w4Yqq1S6ZEbfRrqVUg==} + '@cloudflare/workerd-linux-64@1.20240821.1': + resolution: {integrity: sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20240718.0': - resolution: {integrity: sha512-zBEZvy88EcAMGRGfuVtS00Yl7lJdUM9sH7i651OoL+q0Plv9kphlCC0REQPwzxrEYT1qibSYtWcD9IxQGgx2/g==} + '@cloudflare/workerd-linux-arm64@1.20240821.1': + resolution: {integrity: sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@cloudflare/workerd-windows-64@1.20240718.0': - resolution: {integrity: sha512-YpCRvvT47XanFum7C3SedOZKK6BfVhqmwdAAVAQFyc4gsCdegZo0JkUkdloC/jwuWlbCACOG2HTADHOqyeolzQ==} + '@cloudflare/workerd-windows-64@1.20240821.1': + resolution: {integrity: sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw==} engines: {node: '>=16'} cpu: [x64] os: [win32] - '@cloudflare/workers-types@4.20240722.0': - resolution: {integrity: sha512-/N072r7w7jNCgciRtImOQnHODn8CNwl3NHGO2lmC5bCsgevTRNeNj6B2IjS+OgEfo0qFoBgLejISl6ot9QvGvA==} + '@cloudflare/workers-shared@0.3.0': + resolution: {integrity: sha512-cqtLW1QiBC/ABaZIhAdyGCsnHHY6pAb6hsVUZg82Co2gQtf/faxRYV1FgpCwUYroTdk6A66xUMSTmFqreKCJow==} + engines: {node: '>=16.7.0'} + + '@cloudflare/workers-types@4.20240821.1': + resolution: {integrity: sha512-icAkbnAqgVl6ef9lgLTom8na+kj2RBw2ViPAQ586hbdj0xZcnrjK7P46Eu08OU9D/lNDgN2sKU/sxhe2iK/gIg==} '@commitlint/cli@19.3.0': resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==} @@ -848,8 +848,8 @@ packages: resolution: {integrity: sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==} engines: {node: '>=v18'} - '@commitlint/load@19.2.0': - resolution: {integrity: sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==} + '@commitlint/load@19.4.0': + resolution: {integrity: sha512-I4lCWaEZYQJ1y+Y+gdvbGAx9pYPavqZAZ3/7/8BpWh+QjscAn8AjsUpLV2PycBsEx7gupq5gM4BViV9xwTIJuw==} engines: {node: '>=v18'} '@commitlint/message@19.0.0': @@ -860,8 +860,8 @@ packages: resolution: {integrity: sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==} engines: {node: '>=v18'} - '@commitlint/read@19.2.1': - resolution: {integrity: sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==} + '@commitlint/read@19.4.0': + resolution: {integrity: sha512-r95jLOEZzKDakXtnQub+zR3xjdnrl2XzerPwm7ch1/cc5JGq04tyaNpa6ty0CRCWdVrk4CZHhqHozb8yZwy2+g==} engines: {node: '>=v18'} '@commitlint/resolve-extends@19.1.0': @@ -907,6 +907,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.23.1': + resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.17.19': resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -925,6 +931,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.23.1': + resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.17.19': resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} @@ -943,6 +955,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.23.1': + resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.17.19': resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} @@ -961,6 +979,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.23.1': + resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.17.19': resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} @@ -979,6 +1003,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.23.1': + resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.17.19': resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} @@ -997,6 +1027,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.23.1': + resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.17.19': resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} @@ -1015,6 +1051,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.23.1': + resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.17.19': resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} @@ -1033,6 +1075,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.23.1': + resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.17.19': resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} @@ -1051,6 +1099,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.23.1': + resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.17.19': resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} @@ -1069,6 +1123,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.23.1': + resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.17.19': resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} @@ -1087,6 +1147,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.23.1': + resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.17.19': resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} @@ -1105,6 +1171,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.23.1': + resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.17.19': resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} @@ -1123,6 +1195,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.23.1': + resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.17.19': resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} @@ -1141,6 +1219,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.23.1': + resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.17.19': resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} @@ -1159,6 +1243,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.23.1': + resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.17.19': resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} @@ -1177,6 +1267,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.23.1': + resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.17.19': resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} @@ -1195,6 +1291,12 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.23.1': + resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.17.19': resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -1213,6 +1315,18 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.23.1': + resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.1': + resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.17.19': resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} @@ -1231,6 +1345,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.23.1': + resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.17.19': resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} @@ -1249,6 +1369,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.23.1': + resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.17.19': resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} @@ -1267,6 +1393,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.23.1': + resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.17.19': resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} @@ -1285,6 +1417,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.23.1': + resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.17.19': resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} @@ -1303,6 +1441,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.23.1': + resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1424,8 +1568,8 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@remix-run/cloudflare-pages@2.10.2': - resolution: {integrity: sha512-HaOdGkSMhe4zg1M8KDNNKb7VgBIHGpi0/90aLdYmzvZy+yeR0NOdrQh4P6gAYGCGSzqttuPOEIr4laXtBKI7Yg==} + '@remix-run/cloudflare-pages@2.11.2': + resolution: {integrity: sha512-Sa/LED9qPJfpk6IgJvXiUIzjCRC2B6dyfOH286YttoKOGmEiMaXYt4KTEssyiT8LY7nR3IPsprA8kohjpRujhg==} engines: {node: '>=18.0.0'} peerDependencies: '@cloudflare/workers-types': ^4.0.0 @@ -1434,8 +1578,8 @@ packages: typescript: optional: true - '@remix-run/cloudflare@2.10.2': - resolution: {integrity: sha512-pYDezNSGKVmkpfuHSAN/x9I7518ohJNsZj/WN8S4Y7tZAD2n202EzAX0pJeg6HpqIcqIgr18WiqVwCbx9UvLAg==} + '@remix-run/cloudflare@2.11.2': + resolution: {integrity: sha512-XYn0owvpOJgH7nAVaOqj/M6MbngMFk9zPhllUNShGCjW86CD+PUAy+PdcCvsjiCKfYa6axPZ3ZHajGM/vr1gLQ==} engines: {node: '>=18.0.0'} peerDependencies: '@cloudflare/workers-types': ^4.0.0 @@ -1444,13 +1588,13 @@ packages: typescript: optional: true - '@remix-run/dev@2.10.2': - resolution: {integrity: sha512-7hHC9WY65IJ5ex9Vrv9PkSg15mmYH63unxPDAR74hSfSkectMgsWtMChzdx7Kp/CzN2rttt3cxPwZnAu6PXJUw==} + '@remix-run/dev@2.11.2': + resolution: {integrity: sha512-9DGb2UOIO4jOdws04Z+KmCeEBqbP36XvJZdcd4w16wDGI0I1ZY1c5ro58tB/7zPwN40s9MD9UzCYm6P+EkdeAg==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: - '@remix-run/react': ^2.10.2 - '@remix-run/serve': ^2.10.2 + '@remix-run/react': ^2.11.2 + '@remix-run/serve': ^2.11.2 typescript: ^5.1.0 vite: ^5.1.0 wrangler: ^3.28.2 @@ -1464,8 +1608,8 @@ packages: wrangler: optional: true - '@remix-run/express@2.10.2': - resolution: {integrity: sha512-er8b1aLULkM3KHTrU97ovBy5KDu53gCE7VjbqefHG9ZYLMZPOifawmCUaNAirhpkxW/nb08gyJo/5c+WYRrsuQ==} + '@remix-run/express@2.11.2': + resolution: {integrity: sha512-ebyvHJKRBDgQGNBMxsILt21IwMTjGxQxlr0VNxRJo5rNd5CcuULpx/PPmsBc1gsc/Jx9aUXpT7a9l0UEOc6+jw==} engines: {node: '>=18.0.0'} peerDependencies: express: ^4.19.2 @@ -1474,8 +1618,8 @@ packages: typescript: optional: true - '@remix-run/node@2.10.2': - resolution: {integrity: sha512-Ni4yMQCf6avK2fz91/luuS3wnHzqtbxsdc19es1gAWEnUKfeCwqq5v1R0kzNwrXyh5NYCRhxaegzVH3tGsdYFg==} + '@remix-run/node@2.11.2': + resolution: {integrity: sha512-gRNFM61EOYWNmYgf+pvBt6MrirWlkDz1G6RQsJNowtRqbYoy05AdDe5HiHGF5w8ZMAZVeXnZiwbL0Nt7ykYBCA==} engines: {node: '>=18.0.0'} peerDependencies: typescript: ^5.1.0 @@ -1483,8 +1627,8 @@ packages: typescript: optional: true - '@remix-run/react@2.10.2': - resolution: {integrity: sha512-0Fx3AYNjfn6Z/0xmIlVC7exmof20M429PwuApWF1H8YXwdkI+cxLfivRzTa1z7vS55tshurqQum98jQQaUDjoA==} + '@remix-run/react@2.11.2': + resolution: {integrity: sha512-SjjuK3aD/9wnIC5r0ZBNCpVSwEwt67YOQM7DCXhHiS8BtCvAxWEC4k4t8CvO9IwBG0gczqxzSqASH7U1RVtWqw==} engines: {node: '>=18.0.0'} peerDependencies: react: ^18.0.0 @@ -1494,17 +1638,17 @@ packages: typescript: optional: true - '@remix-run/router@1.17.1': - resolution: {integrity: sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==} + '@remix-run/router@1.19.1': + resolution: {integrity: sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==} engines: {node: '>=14.0.0'} - '@remix-run/serve@2.10.2': - resolution: {integrity: sha512-ryWW5XK4Ww2mx1yhZPIycNqniZhzwybj61DIPO4cJxThvUkYgXf+Wdzq4jhva2B99naAiu18Em0nwh8VZxFMew==} + '@remix-run/serve@2.11.2': + resolution: {integrity: sha512-f1ETbCAlkSO3kg1zcQyLVHxI2r1TXqV2nfPgX/5+7QmA1dEHJD3OhvSmbvopwSMSfi1jzuyRbJo04yK4aJ8ztg==} engines: {node: '>=18.0.0'} hasBin: true - '@remix-run/server-runtime@2.10.2': - resolution: {integrity: sha512-c6CzKw4WBP4FkPnz63ua7g73/P1v34Uho2C44SZZf8IOVCGzEM9liLq6slDivn0m/UbyQnXThdXmsVjFcobmZg==} + '@remix-run/server-runtime@2.11.2': + resolution: {integrity: sha512-abG6ENj0X3eHqDxqO2thWM2NSEiPnqyt58z1BbiQCv+t8g0Zuqd5QHbB4wzdNvfS0vKhg+jJiigcJneAc4sZzw==} engines: {node: '>=18.0.0'} peerDependencies: typescript: ^5.1.0 @@ -1512,8 +1656,8 @@ packages: typescript: optional: true - '@remix-run/testing@2.10.2': - resolution: {integrity: sha512-snSVgF1yCuyBKICfASIKCoyY+rW+QcnLWWN9nIl2n8c9NhHldlE4PRMBfRYjg1lQsik6yzzC+aPX+Yk+hjDbSQ==} + '@remix-run/testing@2.11.2': + resolution: {integrity: sha512-Wmi/TXWlngkbLFFDYbWPB2WH7jZDcd55MIZyRmBIVtva7mSzK5GKX+LWdoaTFcL6IxXvJtOszuJpneC0Sf75HA==} engines: {node: '>=18.0.0'} peerDependencies: react: ^18.0.0 @@ -1547,83 +1691,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.19.0': - resolution: {integrity: sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w==} + '@rollup/rollup-android-arm-eabi@4.21.1': + resolution: {integrity: sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.19.0': - resolution: {integrity: sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw==} + '@rollup/rollup-android-arm64@4.21.1': + resolution: {integrity: sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.19.0': - resolution: {integrity: sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA==} + '@rollup/rollup-darwin-arm64@4.21.1': + resolution: {integrity: sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.19.0': - resolution: {integrity: sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg==} + '@rollup/rollup-darwin-x64@4.21.1': + resolution: {integrity: sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.19.0': - resolution: {integrity: sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw==} + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + resolution: {integrity: sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.19.0': - resolution: {integrity: sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ==} + '@rollup/rollup-linux-arm-musleabihf@4.21.1': + resolution: {integrity: sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.19.0': - resolution: {integrity: sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug==} + '@rollup/rollup-linux-arm64-gnu@4.21.1': + resolution: {integrity: sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.19.0': - resolution: {integrity: sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ==} + '@rollup/rollup-linux-arm64-musl@4.21.1': + resolution: {integrity: sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.19.0': - resolution: {integrity: sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + resolution: {integrity: sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.19.0': - resolution: {integrity: sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg==} + '@rollup/rollup-linux-riscv64-gnu@4.21.1': + resolution: {integrity: sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.19.0': - resolution: {integrity: sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA==} + '@rollup/rollup-linux-s390x-gnu@4.21.1': + resolution: {integrity: sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.19.0': - resolution: {integrity: sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA==} + '@rollup/rollup-linux-x64-gnu@4.21.1': + resolution: {integrity: sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.19.0': - resolution: {integrity: sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A==} + '@rollup/rollup-linux-x64-musl@4.21.1': + resolution: {integrity: sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.19.0': - resolution: {integrity: sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg==} + '@rollup/rollup-win32-arm64-msvc@4.21.1': + resolution: {integrity: sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.19.0': - resolution: {integrity: sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q==} + '@rollup/rollup-win32-ia32-msvc@4.21.1': + resolution: {integrity: sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.19.0': - resolution: {integrity: sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag==} + '@rollup/rollup-win32-x64-msvc@4.21.1': + resolution: {integrity: sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==} cpu: [x64] os: [win32] @@ -1634,87 +1778,87 @@ packages: resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@storybook/addon-actions@8.2.5': - resolution: {integrity: sha512-8kevyvbvEdo0qn+hL/ub/RVsCGlWvCgL6ZAsZm50aWl1GXPpXj3nggKnyJwgAGUQzDC0CDPlNpSOP4ri3NY8tw==} + '@storybook/addon-actions@8.2.9': + resolution: {integrity: sha512-eh2teOqjga7aoClDVV+/b1gHJqsPwjiU1t+Hg/l4i2CkaBUNdYMEL90nR6fgReOdvvL5YhcPwJ8w38f9TrQcoQ==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-backgrounds@8.2.5': - resolution: {integrity: sha512-FZowGG+58qWHePjE6tGTTjT+m4/ZTI1uZD7GA++phdi5m8V/LGwJl8zBNZqUha/ygJ0i3Yvnj4tclWDSa8wtnQ==} + '@storybook/addon-backgrounds@8.2.9': + resolution: {integrity: sha512-eGmZAd742ORBbQ6JepzBCko/in62T4Xg9j9LVa+Cvz/7L1C/RQSuU6sUwbRAsXaz+PMVDksPDCUUNsXl3zUL7w==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-controls@8.2.5': - resolution: {integrity: sha512-8IoeEmiOyg5aTIyW4gdUUV/xJZk8y5bACkNhDTIepyfTZLoVNsVXS1tjqrG4EXQR6dNY4XV9dDIUIRI11/K6tQ==} + '@storybook/addon-controls@8.2.9': + resolution: {integrity: sha512-vaSE78KOE7SO0GrW4e+mdQphSNpvCX/FGybIRxyaKX9h8smoyUwRNHVyCS3ROHTwH324QWu7GDzsOVrnyXOv0A==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-docs@8.2.5': - resolution: {integrity: sha512-fJ2Aam6rQO5BVRIDrA4gVxxnVmMCkk4wC6RDi8oSTOcjM0FRl3ktv+6gPbNWq/+b8dqU23Y4wSyM4UUAIP0PAA==} + '@storybook/addon-docs@8.2.9': + resolution: {integrity: sha512-flDOxFIGmXg+6lVdwTLMOKsGob1WrT7rG98mn1SNW0Nxhg3Wg+9pQuq1GLxEzKtAgSflmu+xcBRfYhsogyDXkw==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-essentials@8.2.5': - resolution: {integrity: sha512-SmA4QOiI9/d9bycagStm1gtlt2iR1EpWXJnhct4oqcj5nxmp+jviyhv1Pb+Rm/zKNE5qcaI4AcRDRVTJRUwESw==} + '@storybook/addon-essentials@8.2.9': + resolution: {integrity: sha512-B2d3eznGZvPIyCVtYX0UhrYcEfK+3Y2sACmEWpSwtk8KXomFEsZnD95m397BYDRw3/X6qeSLWxqgMfqDTEDeMA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-highlight@8.2.5': - resolution: {integrity: sha512-fgzmilW3jGD68xYiR8sRjOB+joETc6/2+Fmj4S85BNnKy2ViXc1D+LHIw1id5/oT9MNN1i62D517EXRZkPakGw==} + '@storybook/addon-highlight@8.2.9': + resolution: {integrity: sha512-qdcazeNQoo9QKIq+LJJZZXvFZoLn+i4uhbt1Uf9WtW6oU/c1qxORGVD7jc3zsxbQN9nROVPbJ76sfthogxeqWA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-interactions@8.2.5': - resolution: {integrity: sha512-YVdpU/VRrRvX3BUiYxno6jDttbbQxngOkgcY8u+LLXbo3LfFLeXwpUmJXvGOrIU1wDHsZ4FAPBS/beFntcFhBw==} + '@storybook/addon-interactions@8.2.9': + resolution: {integrity: sha512-oSxBkqpmp1Vm9v/G8mZeFNXD8k6T1NMgzUWzAx7R5m31rfObhoi5Fo1bKQT5BAhSSsdjjd7owTAFKdhwSotSKg==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-links@8.2.5': - resolution: {integrity: sha512-jcD1/KXSqEE/QkQtBx3beD7UQJ3NQLEqYjCiF6UzsdFzcbfgAlfL5fKv8Lh/g8VynPcQzpfhMnSkj445EmF9hQ==} + '@storybook/addon-links@8.2.9': + resolution: {integrity: sha512-RhJzUNdDb7lbliwXb64HMwieIeJ+OQ2Ditue1vmSox6NsSd+pshR+okHpAyoP1+fW+dahNENwAS2Kt2QiI78FA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.5 + storybook: ^8.2.9 peerDependenciesMeta: react: optional: true - '@storybook/addon-measure@8.2.5': - resolution: {integrity: sha512-rC/kukXM+3Sd1U5Wboozs82p3rLaHBRCmQfk3bFhWyGKvbYWEWmSr7w0DLH8/X7pi1u8IMSqeRll7tDJrEXeaw==} + '@storybook/addon-measure@8.2.9': + resolution: {integrity: sha512-XUfQtYRKWB2dfbPRmHuos816wt1JrLbtRld5ZC8J8ljeqZ4hFBPTQcgI5GAzZqjQuclLC0KuhlA/0bKxdxMMGA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-outline@8.2.5': - resolution: {integrity: sha512-YRS60tyZH79FfH9NEOndGVG/AmlXdYMd3nT2XfMBPZ+uTay/hcUzp6/wVsL+ucyVXi0avHbyNjY+iFP6m/MhRw==} + '@storybook/addon-outline@8.2.9': + resolution: {integrity: sha512-p22kI4W7MT0YJOCmg/FfhfH+NpZEDA5tgwstjazSg4ertyhaxziMwWZWiK2JCg0gOAfRJjoYjHz+6/u56iXwgQ==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-toolbars@8.2.5': - resolution: {integrity: sha512-XqjJxpXjTKurL81QF+Xa69J/8TSstXvLWVqeX+132C0//Yq3VeUir87hvI2qw/qbQT9sGeRX72vqKhoxS+kvIQ==} + '@storybook/addon-toolbars@8.2.9': + resolution: {integrity: sha512-9LMZZ2jRD86Jh6KXedDbAYs4eHj9HtJA9VhSEE2wiqMGwXozpySi7B1GWniNzmFfcgMQ4JHfmD/OrBVTK7Ca/w==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/addon-viewport@8.2.5': - resolution: {integrity: sha512-QH2A+rzoMf8dcREOUpAsx1vvP7w3MQ8HbZCawk7KdkW/KS0L8zhkHfsNL9cfLcgCJA0wtOmRPD25ZVGoxUAHSA==} + '@storybook/addon-viewport@8.2.9': + resolution: {integrity: sha512-lyM24+DJEt8R0YZkJKee34NQWv0REACU6lYDalqJNdKS1sEwzLGWxg1hZXnw2JFdBID9NGVvyYU2w6LDozOB0g==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/blocks@8.2.5': - resolution: {integrity: sha512-SJXo9NxgdXEeFA4OgfMaffjOxFBrMFIq/27F6/Z+JEs6lHZhayaBsofFcVbKEtivsg9+MbOLnN1TbwgnjjRw5g==} + '@storybook/blocks@8.2.9': + resolution: {integrity: sha512-5276q/s/UL8arwftuBXovUNHqYo/HPQFMGXEmjVVAMXUyFjzEAfKj3+xU897J6AuL+7XVZG32WnqA+X6LJMrcQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.5 + storybook: ^8.2.9 peerDependenciesMeta: react: optional: true react-dom: optional: true - '@storybook/builder-vite@8.2.5': - resolution: {integrity: sha512-5CiJY+vJKt8FpEK0MVAXrIj4UDahi4fxPoUYcxawaYHTCpspaxFtLrHuNQkDbyDSjBednIMOIAm8ei2pha3Z6Q==} + '@storybook/builder-vite@8.2.9': + resolution: {integrity: sha512-MHD3ezRjKkJkOl0u7CRQoQD/LKd28YMWIcaz4YrV6ygokc0c3RFTlOefICQFgboc+1RwIUowxN1CJ2kJ7p4SWw==} peerDependencies: '@preact/preset-vite': '*' - storybook: ^8.2.5 + storybook: ^8.2.9 typescript: '>= 4.3.x' vite: ^4.0.0 || ^5.0.0 vite-plugin-glimmerx: '*' @@ -1726,21 +1870,21 @@ packages: vite-plugin-glimmerx: optional: true - '@storybook/codemod@8.2.5': - resolution: {integrity: sha512-bUCvOqW3LUjz6epmTfocWBm0S7Ae52xmHvhVqgAUsKp9bVw2CGt9uaPR8dVE4IfI1yJZKRjf3u7Y60OTfWew4g==} + '@storybook/codemod@8.2.9': + resolution: {integrity: sha512-3yRx1lFMm1FXWVv+CKDiYM4gOQPEfpcZAQrjfcumxSDUrB091pnU1PeI92Prj3vCdi4+0oPNuN4yDGNUYTMP/A==} - '@storybook/components@8.2.5': - resolution: {integrity: sha512-/cqAzQ1w9tK44BvKDNkY3MxcqoDaMvZeI5c4rGh/nYMjulXV4cAOTSlVK07XfkOJENj/wHHSDz8tZTrl2FhmuQ==} + '@storybook/components@8.2.9': + resolution: {integrity: sha512-OkkcZ/f/6o3GdFEEK9ZHKIGHWUHmavZUYs5xaSgU64bOrA2aqEFtfeWWitZYTv3Euhk8MVLWfyEMDfez0AlvDg==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/core@8.2.5': - resolution: {integrity: sha512-KjaeIkbdcog4Jmx3MoSjQZpfESin1qHEcFiLoOkICOpuKsj37xdMFcuSre8IbcVGCJPkt1RvEmfeu1N90jOgww==} + '@storybook/core@8.2.9': + resolution: {integrity: sha512-wSER8FpA6Il/jPyDfKm3yohxDtuhisNPTonMVzd3ulNWR4zERLddyO3HrHJJwdqYHLNk4SBFzwMGpQZVws1y0w==} - '@storybook/csf-plugin@8.2.5': - resolution: {integrity: sha512-YpkvfDbKyilI54QMz/NyHGOlXxVeE+3LTKLx4GV/JrnGW+EtqQTYNaWWnTsesX0AsUICBAvxqyO9HtFtRjeL+Q==} + '@storybook/csf-plugin@8.2.9': + resolution: {integrity: sha512-QQCFb3g12VQQEraDV1UfCmniGhQZKyT6oEt1Im6dzzPJj9NQk+6BjWoDep33CZhBHWoLryrMQd2fjuHxnFRNEA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 '@storybook/csf@0.0.1': resolution: {integrity: sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==} @@ -1751,65 +1895,65 @@ packages: '@storybook/global@5.0.0': resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - '@storybook/icons@1.2.9': - resolution: {integrity: sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==} + '@storybook/icons@1.2.10': + resolution: {integrity: sha512-310apKdDcjbbX2VSLWPwhEwAgjxTzVagrwucVZIdGPErwiAppX8KvBuWZgPo+rQLVrtH8S+pw1dbUwjcE6d7og==} engines: {node: '>=14.0.0'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/instrumenter@8.2.5': - resolution: {integrity: sha512-HeETFUYYZDM3A76oO8p7V1nCrxdAglhO+3FtPa2EqSWueYISANyOOTu/8NIW3EbKP3GsfWi509ofQhsLBHy9dQ==} + '@storybook/instrumenter@8.2.9': + resolution: {integrity: sha512-+DNjTbsMzlDggsvkhRuOy7aGvQJ4oLCPgunP5Se/3yBjG+M2bYDa0EmC5jC2nwZ3ffpuvbzaVe7fWf7R8W9F2Q==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/manager-api@8.2.5': - resolution: {integrity: sha512-4UHRlpcbYF2UiO9tonafnJMC2wJXWjTXivHjuf3ehbJXmopkNe/4zLtNTRyf3Hozf4CuYtNotw0tXflBrGlIlw==} + '@storybook/manager-api@8.2.9': + resolution: {integrity: sha512-mkYvUlfqDw+0WbxIynh5TcrotmoXlumEsOA4+45zuNea8XpEgj5cNBUCnmfEO6yQ85swqkS8YYbMpg1cZyu/Vw==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/preview-api@8.2.5': - resolution: {integrity: sha512-C5A3MtubUM5Tq1An1gIqiEmiBX4ybaTzAeBuohsqToPmWHvM2uIdSl6XpTyQQJowkvrqBKjchqZUy/2mynX4lQ==} + '@storybook/preview-api@8.2.9': + resolution: {integrity: sha512-D8/t+a78OJqQAcT/ABa1C4YM/OaLGQ9IvCsp3Q9ruUqDCwuZBj8bG3D4477dlY4owX2ycC0rWYu3VvuK0EmJjA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/react-dom-shim@8.2.5': - resolution: {integrity: sha512-r+ZppgZR1AmM+2E9GRIaL/JjD3C/kl8sexD1mrGN4PBzrqqy6BNedHroWvf9JmfAvD/bp55peJ+LWAsSU/NvQQ==} + '@storybook/react-dom-shim@8.2.9': + resolution: {integrity: sha512-uCAjSQEsNk8somVn1j/I1G9G/uUax5byHseIIV0Eq3gVXttGd7gaWcP+TDHtqIaenWHx4l+hCSuCesxiLWmx4Q==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/react-vite@8.2.5': - resolution: {integrity: sha512-6Y4SdCfX0fvOVRJygFXrohiGQyEw2ByKqhQ/3Mw/jX2nIbauKWrGi56g7l8DBbaUJ122gN44xBsz+5KGCH8UGQ==} + '@storybook/react-vite@8.2.9': + resolution: {integrity: sha512-Lw6FzcAaL7jX8Y8EsDzg32Lp0NdeNJZpj0LVwX5sLOQQA6w4i3PqlFINXDY28qCGo6wqKT+w44zhgwUcU5V0Ow==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.5 + storybook: ^8.2.9 vite: ^4.0.0 || ^5.0.0 - '@storybook/react@8.2.5': - resolution: {integrity: sha512-Wgr7a8ZHSDIJyKNDEYdwwu+AEkaG1yM7UBBmROr8WrYHgKaC49ekEgY0i3bck6HArUvu3A6Z448mJTMY+XtK5Q==} + '@storybook/react@8.2.9': + resolution: {integrity: sha512-F2xZcTDxxjpbqt7eP8rEHmlksiKmE/qtPusEWEY4N4jK01kN+ncxSl8gkJpUohMEmAnVC5t/1v/sU57xv1DYpg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.2.5 + storybook: ^8.2.9 typescript: '>= 4.2.x' peerDependenciesMeta: typescript: optional: true - '@storybook/test@8.2.5': - resolution: {integrity: sha512-8fo5qh3dNTlcUsnpYB5klcsnjIhEpkyVC+KCqapDI/iFD6qDmZXzbEcP/HsVMICwGTanr2kFCmf5c8kfAiOMew==} + '@storybook/test@8.2.9': + resolution: {integrity: sha512-O5JZ5S8UVVR7V0ru5AiF/uRO+srAVwji0Iik7ihy8gw3V91WQNMmJh2KkdhG0R1enYeBsYZlipOm+AW7f/MmOA==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 - '@storybook/theming@8.2.5': - resolution: {integrity: sha512-EEOSmW55MeLB3iskf5uUqffsqu003tTta8XQ1Xg8em3gePxPsjqzQtly1Ws5PtRg1Zvt1Zc6NKHwabiVzxothA==} + '@storybook/theming@8.2.9': + resolution: {integrity: sha512-OL0NFvowPX85N5zIYdgeKKaFm7V4Vgtci093vL3cDZT13LGH6GuEzJKkUFGuUGNPFlJc+EgTj0o6PYKrOLyQ6w==} peerDependencies: - storybook: ^8.2.5 + storybook: ^8.2.9 '@testing-library/dom@10.1.0': resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} @@ -1944,11 +2088,11 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@18.19.42': - resolution: {integrity: sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==} + '@types/node@18.19.46': + resolution: {integrity: sha512-vnRgMS7W6cKa1/0G3/DTtQYpVrZ8c0Xm6UkLaVFrb9jtcVC3okokW09Ki1Qdrj9ISokszD69nY4WDLRlvHlhAA==} - '@types/node@20.14.12': - resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==} + '@types/node@22.5.0': + resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -1977,11 +2121,11 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - '@types/unist@2.0.10': - resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.2': - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} @@ -2080,14 +2224,17 @@ packages: '@vanilla-extract/css@1.15.3': resolution: {integrity: sha512-mxoskDAxdQAspbkmQRxBvolUi1u1jnyy9WZGm+GeH8V2wwhEvndzl1QoK7w8JfA0WFevTxbev5d+i+xACZlPhA==} + '@vanilla-extract/css@1.15.5': + resolution: {integrity: sha512-N1nQebRWnXvlcmu9fXKVUs145EVwmWtMD95bpiEKtvehHDpUhmO1l2bauS7FGYKbi3dU1IurJbGpQhBclTr1ng==} + '@vanilla-extract/integration@6.5.0': resolution: {integrity: sha512-E2YcfO8vA+vs+ua+gpvy1HRqvgWbI+MTlUpxA8FvatOvybuNcWAY0CKwQ/Gpj7rswYKtC6C7+xw33emM6/ImdQ==} - '@vanilla-extract/integration@7.1.7': - resolution: {integrity: sha512-xKwrCtmiBq6QzRNj+IOg5cAMRQRXkFnnvcE374MROJPnVvDX0d+lrIQapFGt64F0H8Gjk4kVl4slvCiV3ECQ4w==} + '@vanilla-extract/integration@7.1.9': + resolution: {integrity: sha512-bkikYnUdEiUoUZGX3tErmkpU43M4Q0McZcSUHutP/pQCeuDB29t8brLOLzdkahwD+RteX2/R3ukmIm3lAYzUnA==} - '@vanilla-extract/private@1.0.5': - resolution: {integrity: sha512-6YXeOEKYTA3UV+RC8DeAjFk+/okoNz/h88R+McnzA2zpaVqTR/Ep+vszkWYlGBcMNO7vEkqbq5nT/JMMvhi+tw==} + '@vanilla-extract/private@1.0.6': + resolution: {integrity: sha512-ytsG/JLweEjw7DBuZ/0JCN4WAQgM9erfSTdS1NQY778hFQSZ6cfCDEZZ0sgVm4k54uNz6ImKB33AYvSR//fjxw==} '@vanilla-extract/vite-plugin@4.0.13': resolution: {integrity: sha512-JeACJlPtsWp/73Ke1Px/QvDA8M3GlBt4ZjWytSm7rYoKv1qEANSnvAZsAevIp56tTMJaqs++R3L7OkmnFeKhlw==} @@ -2162,9 +2309,9 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-escapes@6.2.1: - resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} - engines: {node: '>=14.16'} + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -2264,8 +2411,8 @@ packages: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} - astring@1.8.6: - resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true autoprefixer@10.4.19: @@ -2279,8 +2426,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.9.1: - resolution: {integrity: sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==} + axe-core@4.10.0: + resolution: {integrity: sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==} engines: {node: '>=4'} axobject-query@3.1.1: @@ -2296,8 +2443,8 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.10.4: - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} + babel-plugin-polyfill-corejs3@0.10.6: + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -2349,8 +2496,8 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - browserslist@4.23.2: - resolution: {integrity: sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==} + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -2384,8 +2531,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001643: - resolution: {integrity: sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==} + caniuse-lite@1.0.30001653: + resolution: {integrity: sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==} capnp-ts@0.7.0: resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} @@ -2393,8 +2540,8 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} chalk@2.4.2: @@ -2450,9 +2597,9 @@ packages: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} - cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} @@ -2564,8 +2711,8 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} - core-js-compat@3.37.1: - resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} + core-js-compat@3.38.1: + resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2655,8 +2802,8 @@ packages: supports-color: optional: true - debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -2766,11 +2913,11 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.0: - resolution: {integrity: sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==} + electron-to-chromium@1.5.13: + resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} - emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2798,6 +2945,10 @@ packages: engines: {node: '>=4'} hasBin: true + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + err-code@2.0.3: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} @@ -2841,14 +2992,14 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} - esbuild-plugins-node-modules-polyfill@1.6.4: - resolution: {integrity: sha512-x3MCOvZrKDGAfqAYS/pZUUSwiN+XH7x84A+Prup0CZBJKuGfuGkTAC4g01D6JPs/GCM9wzZVfd8bmiy+cP/iXA==} + esbuild-plugins-node-modules-polyfill@1.6.5: + resolution: {integrity: sha512-gppYvODLbtGhnQV7CPcJ67N/RccaBskIs7zNApUYoj2+rwSFPSlA8Mdxqm5AUDGrPki75dRPNOd2/+HK39YRvg==} engines: {node: '>=14.0.0'} peerDependencies: - esbuild: ^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 + esbuild: '>=0.14.0 <=0.23.0' - esbuild-register@3.5.0: - resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==} + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} peerDependencies: esbuild: '>=0.12 <1' @@ -2867,6 +3018,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.23.1: + resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -2897,8 +3053,8 @@ packages: eslint: '*' eslint-plugin-import: '*' - eslint-module-utils@2.8.1: - resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + eslint-module-utils@2.8.2: + resolution: {integrity: sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -3148,15 +3304,15 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - flow-parser@0.241.0: - resolution: {integrity: sha512-82yKXpz7iWknWFsognZUf5a6mBQLnVrYoYSU9Nbu7FTOpKlu3v9ehpiI9mYXuaIO3J0ojX1b83M/InXvld9HUw==} + flow-parser@0.244.0: + resolution: {integrity: sha512-Dkc88m5k8bx1VvHTO9HEJ7tvMcSb3Zvcv1PY4OHK7pHdtdY2aUjhmPy6vpjVJ2uUUOIybRlb91sXE8g4doChtA==} engines: {node: '>=0.4.0'} for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - foreground-child@3.2.1: - resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} format@0.2.2: @@ -3415,8 +3571,8 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} import-fresh@3.3.0: @@ -3500,8 +3656,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.15.0: - resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} is-data-view@1.0.1: @@ -3791,8 +3947,8 @@ packages: engines: {node: '>=18.12.0'} hasBin: true - listr2@8.2.3: - resolution: {integrity: sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==} + listr2@8.2.4: + resolution: {integrity: sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==} engines: {node: '>=18.0.0'} loader-utils@3.3.1: @@ -3856,8 +4012,8 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} engines: {node: '>=18'} longest-streak@3.1.0: @@ -3891,8 +4047,8 @@ packages: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} - magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} @@ -3909,8 +4065,8 @@ packages: resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} engines: {node: '>=0.10.0'} - markdown-to-jsx@7.4.7: - resolution: {integrity: sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==} + markdown-to-jsx@7.5.0: + resolution: {integrity: sha512-RrBNcMHiFPcz/iqIj0n3wclzHXjwS7mzjBNWecKKVhNTIxQepIix6Il/wZCn2Cg5Y1ow2Qi84+eJrryFRWBEWw==} engines: {node: '>= 10'} peerDependencies: react: '>= 0.14.0' @@ -4063,8 +4219,8 @@ packages: micromark@3.2.0: resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} - micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -4102,12 +4258,16 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - miniflare@3.20240718.0: - resolution: {integrity: sha512-TKgSeyqPBeT8TBLxbDJOKPWlq/wydoJRHjAyDdgxbw59N6wbP8JucK6AU1vXCfu21eKhrEin77ssXOpbfekzPA==} + miniflare@3.20240821.0: + resolution: {integrity: sha512-4BhLGpssQxM/O6TZmJ10GkT3wBJK6emFkZ3V87/HyvQmVt8zMxEBvyw5uv6kdtp+7F54Nw6IKFJjPUL8rFVQrQ==} engines: {node: '>=16.13'} hasBin: true @@ -4253,8 +4413,8 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nypm@0.3.9: - resolution: {integrity: sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==} + nypm@0.3.11: + resolution: {integrity: sha512-E5GqaAYSnbb6n1qZyik2wjPDZON43FqOJO59+3OkWrnmQtjggrMOVnsyzfjxp/tS6nlYJBA4zRA5jSM2YaadMg==} engines: {node: ^14.16.0 || >=16.10.0} hasBin: true @@ -4324,6 +4484,10 @@ packages: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -4481,8 +4645,8 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} - pkg-types@1.1.3: - resolution: {integrity: sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==} + pkg-types@1.2.0: + resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} polished@4.3.1: resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} @@ -4539,15 +4703,15 @@ packages: peerDependencies: postcss: ^8.0.0 - postcss-selector-parser@6.1.1: - resolution: {integrity: sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==} + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.39: - resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} + postcss@8.4.41: + resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -4690,15 +4854,15 @@ packages: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} - react-router-dom@6.24.1: - resolution: {integrity: sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==} + react-router-dom@6.26.1: + resolution: {integrity: sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.24.1: - resolution: {integrity: sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==} + react-router@6.26.1: + resolution: {integrity: sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -4819,9 +4983,9 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} - restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} @@ -4854,8 +5018,8 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@4.19.0: - resolution: {integrity: sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA==} + rollup@4.21.1: + resolution: {integrity: sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -4911,8 +5075,8 @@ packages: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} - set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + set-cookie-parser@2.7.0: + resolution: {integrity: sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==} set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -4998,8 +5162,8 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.18: - resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -5024,8 +5188,8 @@ packages: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} engines: {node: '>=4', npm: '>=6'} - storybook@8.2.5: - resolution: {integrity: sha512-nfcly5CY3D6KuHbsfhScPaGeraRA9EJhO9GF00/dnI0GXW4ILS8Kwket515IkKAuKcdjdZis6maEuosbG//Kbg==} + storybook@8.2.9: + resolution: {integrity: sha512-S7Q/Yt4A+nu1O23rg39lQvBqL2Vg+PKXbserDWUR4LFJtfmoZ2xGO8oFIhJmvvhjUBvolw1q7QDeswPq2i0sGw==} hasBin: true stream-shift@1.0.3: @@ -5232,8 +5396,8 @@ packages: tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} tsutils@3.21.0: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -5241,15 +5405,15 @@ packages: peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - turbo-stream@2.2.0: - resolution: {integrity: sha512-FKFg7A0To1VU4CH9YmSMON5QphK0BXjSoiC7D9yMh+mEEbXLUP9qJ4hEt1qcjKtzncs1OpcnjZO8NgrlVbZH+g==} + turbo-stream@2.3.0: + resolution: {integrity: sha512-PhEr9mdexoVv+rJkQ3c8TjrN3DUghX37GNJkSMksoPR4KrXIPnM2MnqRt07sViIqX9IdlhrgtTSyjoVOASq6cg==} type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} engines: {node: '>=4'} type-fest@0.20.2: @@ -5298,12 +5462,15 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici@5.28.4: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} - undici@6.19.4: - resolution: {integrity: sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==} + undici@6.19.8: + resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} engines: {node: '>=18.17'} unenv-nightly@1.10.0-1717606461.a117952: @@ -5385,8 +5552,8 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unplugin@1.12.0: - resolution: {integrity: sha512-KeczzHl2sATPQUx1gzo+EnUkmN4VmGBYRRVOZSGvGITE9rGHRDGqft6ONceP3vgXcyJ2XjX5axG5jMWUwNCYLw==} + unplugin@1.12.2: + resolution: {integrity: sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==} engines: {node: '>=14.0.0'} update-browserslist-db@1.1.0: @@ -5498,8 +5665,8 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + which-builtin-type@1.1.4: + resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} engines: {node: '>= 0.4'} which-collection@1.0.2: @@ -5524,17 +5691,17 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workerd@1.20240718.0: - resolution: {integrity: sha512-w7lOLRy0XecQTg/ujTLWBiJJuoQvzB3CdQ6/8Wgex3QxFhV9Pbnh3UbwIuUfMw3OCCPQc4o7y+1P+mISAgp6yg==} + workerd@1.20240821.1: + resolution: {integrity: sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA==} engines: {node: '>=16'} hasBin: true - wrangler@3.66.0: - resolution: {integrity: sha512-5fEyXsP8qvrUeR13kCfA3OG1z/ABx+/a8hzIA55nCUM2/tjI67ZkfeN1VdOmG6cipZDvs4HfN8rp7j+e+21nKA==} + wrangler@3.72.2: + resolution: {integrity: sha512-7nxkJ4md+KtESNJ/0DwTM7bHZP+uNRpJT5gMDT9WllP9UVzYdtXCTF+p4CHtxIReUpe6pOi7tb05hK9/Q6WaiA==} engines: {node: '>=16.17.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20240718.0 + '@cloudflare/workers-types': ^4.20240821.1 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -5603,6 +5770,11 @@ packages: engines: {node: '>= 14'} hasBin: true + yaml@2.5.0: + resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + engines: {node: '>= 14'} + hasBin: true + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -5642,186 +5814,165 @@ snapshots: '@babel/highlight': 7.24.7 picocolors: 1.0.1 - '@babel/compat-data@7.24.9': {} + '@babel/compat-data@7.25.4': {} - '@babel/core@7.24.9': + '@babel/core@7.25.2': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.10 - '@babel/helper-compilation-targets': 7.24.8 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) - '@babel/helpers': 7.24.8 - '@babel/parser': 7.24.8 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/generator': 7.25.5 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helpers': 7.25.0 + '@babel/parser': 7.25.4 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 convert-source-map: 2.0.0 - debug: 4.3.5 + debug: 4.3.6 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.24.10': + '@babel/generator@7.25.5': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 '@babel/helper-annotate-as-pure@7.24.7': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/helper-compilation-targets@7.24.8': + '@babel/helper-compilation-targets@7.25.2': dependencies: - '@babel/compat-data': 7.24.9 + '@babel/compat-data': 7.25.4 '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.2 + browserslist: 4.23.3 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.24.8(@babel/core@7.24.9)': + '@babel/helper-create-class-features-plugin@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 '@babel/helper-member-expression-to-functions': 7.24.8 '@babel/helper-optimise-call-expression': 7.24.7 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.9) + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 + '@babel/traverse': 7.25.4 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.24.9)': + '@babel/helper-create-regexp-features-plugin@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 regexpu-core: 5.3.2 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.9)': + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-compilation-targets': 7.24.8 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - debug: 4.3.5 + debug: 4.3.6 lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.24.7': - dependencies: - '@babel/types': 7.24.9 - - '@babel/helper-function-name@7.24.7': - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.9 - - '@babel/helper-hoist-variables@7.24.7': - dependencies: - '@babel/types': 7.24.9 - '@babel/helper-member-expression-to-functions@7.24.8': dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.24.7': dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.24.9(@babel/core@7.24.9)': + '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 + '@babel/core': 7.25.2 '@babel/helper-module-imports': 7.24.7 '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.4 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 '@babel/helper-plugin-utils@7.24.8': {} - '@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.24.9)': + '@babel/helper-remap-async-to-generator@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-wrap-function': 7.24.7 + '@babel/helper-wrap-function': 7.25.0 + '@babel/traverse': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.24.7(@babel/core@7.24.9)': + '@babel/helper-replace-supers@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 + '@babel/core': 7.25.2 '@babel/helper-member-expression-to-functions': 7.24.8 '@babel/helper-optimise-call-expression': 7.24.7 + '@babel/traverse': 7.25.4 transitivePeerDependencies: - supports-color '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/helper-split-export-declaration@7.24.7': - dependencies: - '@babel/types': 7.24.9 - '@babel/helper-string-parser@7.24.8': {} '@babel/helper-validator-identifier@7.24.7': {} '@babel/helper-validator-option@7.24.8': {} - '@babel/helper-wrap-function@7.24.7': + '@babel/helper-wrap-function@7.25.0': dependencies: - '@babel/helper-function-name': 7.24.7 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/helpers@7.24.8': + '@babel/helpers@7.25.0': dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.9 + '@babel/template': 7.25.0 + '@babel/types': 7.25.4 '@babel/highlight@7.24.7': dependencies: @@ -5830,605 +5981,623 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.0.1 - '@babel/parser@7.24.8': + '@babel/parser@7.25.4': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.24.9) + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.9)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.9)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.9)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.9)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.9)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.9)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.9)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.9)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.9)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.9)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.9)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-async-generator-functions@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-environment-visitor': 7.24.7 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.9) + '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/traverse': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-module-imports': 7.24.7 '@babel/helper-plugin-utils': 7.24.8 - '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.9) + '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-block-scoping@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-class-properties@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-classes@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-compilation-targets': 7.24.8 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 + '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.9) - '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) + '@babel/traverse': 7.25.4 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/template': 7.24.7 + '@babel/template': 7.25.0 - '@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) + + '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7 '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-flow-strip-types@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.24.9) + '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-function-name@7.25.1(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-compilation-targets': 7.24.8 - '@babel/helper-function-name': 7.24.7 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 + '@babel/traverse': 7.25.4 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-literals@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-literals@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-simple-access': 7.24.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-modules-systemjs@7.25.0(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.4 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-module-transforms': 7.24.9(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-compilation-targets': 7.24.8 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.9) + '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-transform-optional-chaining@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-optional-chaining@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-private-methods@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-spread@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-spread@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-typescript@7.24.8(@babel/core@7.24.9)': + '@babel/plugin-transform-typescript@7.25.2(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.8(@babel/core@7.24.9) + '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-transform-unicode-sets-regex@7.24.7(@babel/core@7.24.9)': + '@babel/plugin-transform-unicode-sets-regex@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 - '@babel/preset-env@7.24.8(@babel/core@7.24.9)': + '@babel/preset-env@7.25.4(@babel/core@7.25.2)': dependencies: - '@babel/compat-data': 7.24.9 - '@babel/core': 7.24.9 - '@babel/helper-compilation-targets': 7.24.8 + '@babel/compat-data': 7.25.4 + '@babel/core': 7.25.2 + '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-option': 7.24.8 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.9) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.9) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.9) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.9) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.9) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.9) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.9) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.9) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.9) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.9) - '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-async-generator-functions': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-block-scoping': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-classes': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-destructuring': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-function-name': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-literals': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-modules-systemjs': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-typeof-symbol': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-unicode-sets-regex': 7.24.7(@babel/core@7.24.9) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.9) - babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.9) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.9) - babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.9) - core-js-compat: 3.37.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.3(@babel/core@7.25.2) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.2) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.25.2) + '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-async-generator-functions': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoping': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-class-properties': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-classes': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-destructuring': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-function-name': 7.25.1(@babel/core@7.25.2) + '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-literals': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-modules-systemjs': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-private-methods': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-typeof-symbol': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-unicode-sets-regex': 7.25.4(@babel/core@7.25.2) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.25.2) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.2) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.2) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.2) + core-js-compat: 3.38.1 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.24.7(@babel/core@7.24.9)': + '@babel/preset-flow@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-option': 7.24.8 - '@babel/plugin-transform-flow-strip-types': 7.24.7(@babel/core@7.24.9) + '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.25.2) - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.9)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 esutils: 2.0.3 - '@babel/preset-typescript@7.24.7(@babel/core@7.24.9)': + '@babel/preset-typescript@7.24.7(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-option': 7.24.8 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-typescript': 7.24.8(@babel/core@7.24.9) + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - '@babel/register@7.24.6(@babel/core@7.24.9)': + '@babel/register@7.24.6(@babel/core@7.25.2)': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 @@ -6437,32 +6606,29 @@ snapshots: '@babel/regjsgen@0.8.0': {} - '@babel/runtime@7.24.8': + '@babel/runtime@7.25.4': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.24.7': + '@babel/template@7.25.0': dependencies: '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 - '@babel/traverse@7.24.8': + '@babel/traverse@7.25.4': dependencies: '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.10 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 - debug: 4.3.5 + '@babel/generator': 7.25.5 + '@babel/parser': 7.25.4 + '@babel/template': 7.25.0 + '@babel/types': 7.25.4 + debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.24.9': + '@babel/types@7.25.4': dependencies: '@babel/helper-string-parser': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 @@ -6478,29 +6644,31 @@ snapshots: dependencies: mime: 3.0.0 - '@cloudflare/workerd-darwin-64@1.20240718.0': + '@cloudflare/workerd-darwin-64@1.20240821.1': optional: true - '@cloudflare/workerd-darwin-arm64@1.20240718.0': + '@cloudflare/workerd-darwin-arm64@1.20240821.1': optional: true - '@cloudflare/workerd-linux-64@1.20240718.0': + '@cloudflare/workerd-linux-64@1.20240821.1': optional: true - '@cloudflare/workerd-linux-arm64@1.20240718.0': + '@cloudflare/workerd-linux-arm64@1.20240821.1': optional: true - '@cloudflare/workerd-windows-64@1.20240718.0': + '@cloudflare/workerd-windows-64@1.20240821.1': optional: true - '@cloudflare/workers-types@4.20240722.0': {} + '@cloudflare/workers-shared@0.3.0': {} - '@commitlint/cli@19.3.0(@types/node@20.14.12)(typescript@5.5.3)': + '@cloudflare/workers-types@4.20240821.1': {} + + '@commitlint/cli@19.3.0(@types/node@22.5.0)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.14.12)(typescript@5.5.3) - '@commitlint/read': 19.2.1 + '@commitlint/load': 19.4.0(@types/node@22.5.0)(typescript@5.5.3) + '@commitlint/read': 19.4.0 '@commitlint/types': 19.0.3 execa: 8.0.1 yargs: 17.7.2 @@ -6546,7 +6714,7 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.14.12)(typescript@5.5.3)': + '@commitlint/load@19.4.0(@types/node@22.5.0)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -6554,7 +6722,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.5.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.12)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@22.5.0)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -6570,7 +6738,7 @@ snapshots: conventional-changelog-angular: 7.0.0 conventional-commits-parser: 5.0.0 - '@commitlint/read@19.2.1': + '@commitlint/read@19.4.0': dependencies: '@commitlint/top-level': 19.0.0 '@commitlint/types': 19.0.3 @@ -6625,6 +6793,9 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true + '@esbuild/aix-ppc64@0.23.1': + optional: true + '@esbuild/android-arm64@0.17.19': optional: true @@ -6634,6 +6805,9 @@ snapshots: '@esbuild/android-arm64@0.21.5': optional: true + '@esbuild/android-arm64@0.23.1': + optional: true + '@esbuild/android-arm@0.17.19': optional: true @@ -6643,6 +6817,9 @@ snapshots: '@esbuild/android-arm@0.21.5': optional: true + '@esbuild/android-arm@0.23.1': + optional: true + '@esbuild/android-x64@0.17.19': optional: true @@ -6652,6 +6829,9 @@ snapshots: '@esbuild/android-x64@0.21.5': optional: true + '@esbuild/android-x64@0.23.1': + optional: true + '@esbuild/darwin-arm64@0.17.19': optional: true @@ -6661,6 +6841,9 @@ snapshots: '@esbuild/darwin-arm64@0.21.5': optional: true + '@esbuild/darwin-arm64@0.23.1': + optional: true + '@esbuild/darwin-x64@0.17.19': optional: true @@ -6670,6 +6853,9 @@ snapshots: '@esbuild/darwin-x64@0.21.5': optional: true + '@esbuild/darwin-x64@0.23.1': + optional: true + '@esbuild/freebsd-arm64@0.17.19': optional: true @@ -6679,6 +6865,9 @@ snapshots: '@esbuild/freebsd-arm64@0.21.5': optional: true + '@esbuild/freebsd-arm64@0.23.1': + optional: true + '@esbuild/freebsd-x64@0.17.19': optional: true @@ -6688,6 +6877,9 @@ snapshots: '@esbuild/freebsd-x64@0.21.5': optional: true + '@esbuild/freebsd-x64@0.23.1': + optional: true + '@esbuild/linux-arm64@0.17.19': optional: true @@ -6697,6 +6889,9 @@ snapshots: '@esbuild/linux-arm64@0.21.5': optional: true + '@esbuild/linux-arm64@0.23.1': + optional: true + '@esbuild/linux-arm@0.17.19': optional: true @@ -6706,6 +6901,9 @@ snapshots: '@esbuild/linux-arm@0.21.5': optional: true + '@esbuild/linux-arm@0.23.1': + optional: true + '@esbuild/linux-ia32@0.17.19': optional: true @@ -6715,6 +6913,9 @@ snapshots: '@esbuild/linux-ia32@0.21.5': optional: true + '@esbuild/linux-ia32@0.23.1': + optional: true + '@esbuild/linux-loong64@0.17.19': optional: true @@ -6724,6 +6925,9 @@ snapshots: '@esbuild/linux-loong64@0.21.5': optional: true + '@esbuild/linux-loong64@0.23.1': + optional: true + '@esbuild/linux-mips64el@0.17.19': optional: true @@ -6733,6 +6937,9 @@ snapshots: '@esbuild/linux-mips64el@0.21.5': optional: true + '@esbuild/linux-mips64el@0.23.1': + optional: true + '@esbuild/linux-ppc64@0.17.19': optional: true @@ -6742,6 +6949,9 @@ snapshots: '@esbuild/linux-ppc64@0.21.5': optional: true + '@esbuild/linux-ppc64@0.23.1': + optional: true + '@esbuild/linux-riscv64@0.17.19': optional: true @@ -6751,6 +6961,9 @@ snapshots: '@esbuild/linux-riscv64@0.21.5': optional: true + '@esbuild/linux-riscv64@0.23.1': + optional: true + '@esbuild/linux-s390x@0.17.19': optional: true @@ -6760,6 +6973,9 @@ snapshots: '@esbuild/linux-s390x@0.21.5': optional: true + '@esbuild/linux-s390x@0.23.1': + optional: true + '@esbuild/linux-x64@0.17.19': optional: true @@ -6769,6 +6985,9 @@ snapshots: '@esbuild/linux-x64@0.21.5': optional: true + '@esbuild/linux-x64@0.23.1': + optional: true + '@esbuild/netbsd-x64@0.17.19': optional: true @@ -6778,6 +6997,12 @@ snapshots: '@esbuild/netbsd-x64@0.21.5': optional: true + '@esbuild/netbsd-x64@0.23.1': + optional: true + + '@esbuild/openbsd-arm64@0.23.1': + optional: true + '@esbuild/openbsd-x64@0.17.19': optional: true @@ -6787,6 +7012,9 @@ snapshots: '@esbuild/openbsd-x64@0.21.5': optional: true + '@esbuild/openbsd-x64@0.23.1': + optional: true + '@esbuild/sunos-x64@0.17.19': optional: true @@ -6796,6 +7024,9 @@ snapshots: '@esbuild/sunos-x64@0.21.5': optional: true + '@esbuild/sunos-x64@0.23.1': + optional: true + '@esbuild/win32-arm64@0.17.19': optional: true @@ -6805,6 +7036,9 @@ snapshots: '@esbuild/win32-arm64@0.21.5': optional: true + '@esbuild/win32-arm64@0.23.1': + optional: true + '@esbuild/win32-ia32@0.17.19': optional: true @@ -6814,6 +7048,9 @@ snapshots: '@esbuild/win32-ia32@0.21.5': optional: true + '@esbuild/win32-ia32@0.23.1': + optional: true + '@esbuild/win32-x64@0.17.19': optional: true @@ -6823,6 +7060,9 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true + '@esbuild/win32-x64@0.23.1': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -6833,10 +7073,10 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.5 + debug: 4.3.6 espree: 9.6.1 globals: 13.24.0 - ignore: 5.3.1 + ignore: 5.3.2 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -6851,7 +7091,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.5 + debug: 4.3.6 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -6873,13 +7113,13 @@ snapshots: dependencies: '@sinclair/typebox': 0.27.8 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.3) - vite: 5.3.3(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) optionalDependencies: typescript: 5.5.3 @@ -6985,39 +7225,39 @@ snapshots: '@pkgr/core@0.1.1': {} - '@remix-run/cloudflare-pages@2.10.2(@cloudflare/workers-types@4.20240722.0)(typescript@5.5.3)': + '@remix-run/cloudflare-pages@2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3)': dependencies: - '@cloudflare/workers-types': 4.20240722.0 - '@remix-run/cloudflare': 2.10.2(@cloudflare/workers-types@4.20240722.0)(typescript@5.5.3) + '@cloudflare/workers-types': 4.20240821.1 + '@remix-run/cloudflare': 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 - '@remix-run/cloudflare@2.10.2(@cloudflare/workers-types@4.20240722.0)(typescript@5.5.3)': + '@remix-run/cloudflare@2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3)': dependencies: '@cloudflare/kv-asset-handler': 0.1.3 - '@cloudflare/workers-types': 4.20240722.0 - '@remix-run/server-runtime': 2.10.2(typescript@5.5.3) + '@cloudflare/workers-types': 4.20240821.1 + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 - '@remix-run/dev@2.10.2(@remix-run/react@2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.10.2(typescript@5.5.3))(@types/node@20.14.12)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12))(wrangler@3.66.0(@cloudflare/workers-types@4.20240722.0))': + '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.0)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1))': dependencies: - '@babel/core': 7.24.9 - '@babel/generator': 7.24.10 - '@babel/parser': 7.24.8 - '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.9) - '@babel/preset-typescript': 7.24.7(@babel/core@7.24.9) - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/core': 7.25.2 + '@babel/generator': 7.25.5 + '@babel/parser': 7.25.4 + '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 '@mdx-js/mdx': 2.3.0 '@npmcli/package-json': 4.0.1 - '@remix-run/node': 2.10.2(typescript@5.5.3) - '@remix-run/react': 2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) - '@remix-run/router': 1.17.1 - '@remix-run/server-runtime': 2.10.2(typescript@5.5.3) + '@remix-run/node': 2.11.2(typescript@5.5.3) + '@remix-run/react': 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@remix-run/router': 1.19.1 + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0(@types/node@20.14.12) + '@vanilla-extract/integration': 6.5.0(@types/node@22.5.0) arg: 5.0.2 cacache: 17.1.4 chalk: 4.1.2 @@ -7026,7 +7266,7 @@ snapshots: dotenv: 16.4.5 es-module-lexer: 1.5.4 esbuild: 0.17.6 - esbuild-plugins-node-modules-polyfill: 1.6.4(esbuild@0.17.6) + esbuild-plugins-node-modules-polyfill: 1.6.5(esbuild@0.17.6) execa: 5.1.1 exit-hook: 2.2.1 express: 4.19.2 @@ -7042,25 +7282,25 @@ snapshots: picocolors: 1.0.1 picomatch: 2.3.1 pidtree: 0.6.0 - postcss: 8.4.39 - postcss-discard-duplicates: 5.1.0(postcss@8.4.39) - postcss-load-config: 4.0.2(postcss@8.4.39) - postcss-modules: 6.0.0(postcss@8.4.39) + postcss: 8.4.41 + postcss-discard-duplicates: 5.1.0(postcss@8.4.41) + postcss-load-config: 4.0.2(postcss@8.4.41) + postcss-modules: 6.0.0(postcss@8.4.41) prettier: 2.8.8 pretty-ms: 7.0.1 react-refresh: 0.14.2 remark-frontmatter: 4.0.1 remark-mdx-frontmatter: 1.1.1 semver: 7.6.3 - set-cookie-parser: 2.6.0 + set-cookie-parser: 2.7.0 tar-fs: 2.1.1 tsconfig-paths: 4.2.0 ws: 7.5.10 optionalDependencies: - '@remix-run/serve': 2.10.2(typescript@5.5.3) + '@remix-run/serve': 2.11.2(typescript@5.5.3) typescript: 5.5.3 - vite: 5.3.3(@types/node@20.14.12) - wrangler: 3.66.0(@cloudflare/workers-types@4.20240722.0) + vite: 5.3.3(@types/node@22.5.0) + wrangler: 3.72.2(@cloudflare/workers-types@4.20240821.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7076,43 +7316,43 @@ snapshots: - ts-node - utf-8-validate - '@remix-run/express@2.10.2(express@4.19.2)(typescript@5.5.3)': + '@remix-run/express@2.11.2(express@4.19.2)(typescript@5.5.3)': dependencies: - '@remix-run/node': 2.10.2(typescript@5.5.3) + '@remix-run/node': 2.11.2(typescript@5.5.3) express: 4.19.2 optionalDependencies: typescript: 5.5.3 - '@remix-run/node@2.10.2(typescript@5.5.3)': + '@remix-run/node@2.11.2(typescript@5.5.3)': dependencies: - '@remix-run/server-runtime': 2.10.2(typescript@5.5.3) + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) '@remix-run/web-fetch': 4.4.2 '@web3-storage/multipart-parser': 1.0.0 cookie-signature: 1.2.1 source-map-support: 0.5.21 stream-slice: 0.1.2 - undici: 6.19.4 + undici: 6.19.8 optionalDependencies: typescript: 5.5.3 - '@remix-run/react@2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': + '@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@remix-run/router': 1.17.1 - '@remix-run/server-runtime': 2.10.2(typescript@5.5.3) + '@remix-run/router': 1.19.1 + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router: 6.24.1(react@18.3.1) - react-router-dom: 6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - turbo-stream: 2.2.0 + react-router: 6.26.1(react@18.3.1) + react-router-dom: 6.26.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + turbo-stream: 2.3.0 optionalDependencies: typescript: 5.5.3 - '@remix-run/router@1.17.1': {} + '@remix-run/router@1.19.1': {} - '@remix-run/serve@2.10.2(typescript@5.5.3)': + '@remix-run/serve@2.11.2(typescript@5.5.3)': dependencies: - '@remix-run/express': 2.10.2(express@4.19.2)(typescript@5.5.3) - '@remix-run/node': 2.10.2(typescript@5.5.3) + '@remix-run/express': 2.11.2(express@4.19.2)(typescript@5.5.3) + '@remix-run/node': 2.11.2(typescript@5.5.3) chokidar: 3.6.0 compression: 1.7.4 express: 4.19.2 @@ -7123,25 +7363,25 @@ snapshots: - supports-color - typescript - '@remix-run/server-runtime@2.10.2(typescript@5.5.3)': + '@remix-run/server-runtime@2.11.2(typescript@5.5.3)': dependencies: - '@remix-run/router': 1.17.1 + '@remix-run/router': 1.19.1 '@types/cookie': 0.6.0 '@web3-storage/multipart-parser': 1.0.0 cookie: 0.6.0 - set-cookie-parser: 2.6.0 + set-cookie-parser: 2.7.0 source-map: 0.7.4 - turbo-stream: 2.2.0 + turbo-stream: 2.3.0 optionalDependencies: typescript: 5.5.3 - '@remix-run/testing@2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': + '@remix-run/testing@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@remix-run/node': 2.10.2(typescript@5.5.3) - '@remix-run/react': 2.10.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) - '@remix-run/router': 1.17.1 + '@remix-run/node': 2.11.2(typescript@5.5.3) + '@remix-run/react': 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@remix-run/router': 1.19.1 react: 18.3.1 - react-router-dom: 6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-router-dom: 6.26.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: @@ -7175,136 +7415,136 @@ snapshots: dependencies: web-streams-polyfill: 3.3.3 - '@rollup/pluginutils@5.1.0(rollup@4.19.0)': + '@rollup/pluginutils@5.1.0(rollup@4.21.1)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.19.0 + rollup: 4.21.1 - '@rollup/rollup-android-arm-eabi@4.19.0': + '@rollup/rollup-android-arm-eabi@4.21.1': optional: true - '@rollup/rollup-android-arm64@4.19.0': + '@rollup/rollup-android-arm64@4.21.1': optional: true - '@rollup/rollup-darwin-arm64@4.19.0': + '@rollup/rollup-darwin-arm64@4.21.1': optional: true - '@rollup/rollup-darwin-x64@4.19.0': + '@rollup/rollup-darwin-x64@4.21.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.19.0': + '@rollup/rollup-linux-arm-gnueabihf@4.21.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.19.0': + '@rollup/rollup-linux-arm-musleabihf@4.21.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.19.0': + '@rollup/rollup-linux-arm64-gnu@4.21.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.19.0': + '@rollup/rollup-linux-arm64-musl@4.21.1': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.19.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.19.0': + '@rollup/rollup-linux-riscv64-gnu@4.21.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.19.0': + '@rollup/rollup-linux-s390x-gnu@4.21.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.19.0': + '@rollup/rollup-linux-x64-gnu@4.21.1': optional: true - '@rollup/rollup-linux-x64-musl@4.19.0': + '@rollup/rollup-linux-x64-musl@4.21.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.19.0': + '@rollup/rollup-win32-arm64-msvc@4.21.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.19.0': + '@rollup/rollup-win32-ia32-msvc@4.21.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.19.0': + '@rollup/rollup-win32-x64-msvc@4.21.1': optional: true '@sinclair/typebox@0.27.8': {} '@sindresorhus/merge-streams@2.3.0': {} - '@storybook/addon-actions@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-actions@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 dequal: 2.0.3 polished: 4.3.1 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) uuid: 9.0.1 - '@storybook/addon-backgrounds@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-backgrounds@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - '@storybook/addon-controls@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-controls@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: dequal: 2.0.3 lodash: 4.17.21 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - '@storybook/addon-docs@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-docs@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 '@mdx-js/react': 3.0.1(@types/react@18.3.3)(react@18.3.1) - '@storybook/blocks': 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/csf-plugin': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/blocks': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/global': 5.0.0 - '@storybook/react-dom-shim': 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/react': 18.3.3 fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) rehype-external-links: 3.0.0 rehype-slug: 6.0.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color - '@storybook/addon-essentials@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': - dependencies: - '@storybook/addon-actions': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-backgrounds': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-controls': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-docs': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-highlight': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-measure': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-outline': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-toolbars': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/addon-viewport': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + '@storybook/addon-essentials@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + dependencies: + '@storybook/addon-actions': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-backgrounds': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-controls': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-docs': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-highlight': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-measure': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-outline': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-toolbars': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-viewport': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color - '@storybook/addon-highlight@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-highlight@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/addon-interactions@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-interactions@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/test': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/instrumenter': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/test': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) polished: 4.3.1 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 transitivePeerDependencies: - '@jest/globals' @@ -7313,50 +7553,50 @@ snapshots: - jest - vitest - '@storybook/addon-links@8.2.5(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-links@8.2.9(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/csf': 0.1.11 '@storybook/global': 5.0.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 optionalDependencies: react: 18.3.1 - '@storybook/addon-measure@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-measure@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) tiny-invariant: 1.3.3 - '@storybook/addon-outline@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-outline@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - '@storybook/addon-toolbars@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-toolbars@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/addon-viewport@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/addon-viewport@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: memoizerific: 1.11.3 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/blocks@8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/blocks@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/csf': 0.1.11 '@storybook/global': 5.0.0 - '@storybook/icons': 1.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/icons': 1.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/lodash': 4.17.7 color-convert: 2.0.1 dequal: 2.0.3 lodash: 4.17.21 - markdown-to-jsx: 7.4.7(react@18.3.1) + markdown-to-jsx: 7.5.0(react@18.3.1) memoizerific: 1.11.3 polished: 4.3.1 react-colorful: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) telejson: 7.2.0 ts-dedent: 2.2.0 util-deprecate: 1.0.2 @@ -7364,35 +7604,35 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-vite@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12))': + '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': dependencies: - '@storybook/csf-plugin': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/find-cache-dir': 3.2.1 browser-assert: 1.2.1 es-module-lexer: 1.5.4 express: 4.19.2 find-cache-dir: 3.3.2 fs-extra: 11.2.0 - magic-string: 0.30.10 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + magic-string: 0.30.11 + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - vite: 5.3.3(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@storybook/codemod@8.2.5': + '@storybook/codemod@8.2.9': dependencies: - '@babel/core': 7.24.9 - '@babel/preset-env': 7.24.8(@babel/core@7.24.9) - '@babel/types': 7.24.9 - '@storybook/core': 8.2.5 + '@babel/core': 7.25.2 + '@babel/preset-env': 7.25.4(@babel/core@7.25.2) + '@babel/types': 7.25.4 + '@storybook/core': 8.2.9 '@storybook/csf': 0.1.11 '@types/cross-spawn': 6.0.6 cross-spawn: 7.0.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) lodash: 4.17.21 prettier: 3.3.3 recast: 0.23.9 @@ -7402,18 +7642,18 @@ snapshots: - supports-color - utf-8-validate - '@storybook/components@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/components@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/core@8.2.5': + '@storybook/core@8.2.9': dependencies: '@storybook/csf': 0.1.11 '@types/express': 4.17.21 - '@types/node': 18.19.42 + '@types/node': 18.19.46 browser-assert: 1.2.1 esbuild: 0.21.5 - esbuild-register: 3.5.0(esbuild@0.21.5) + esbuild-register: 3.6.0(esbuild@0.21.5) express: 4.19.2 process: 0.11.10 recast: 0.23.9 @@ -7424,10 +7664,10 @@ snapshots: - supports-color - utf-8-validate - '@storybook/csf-plugin@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/csf-plugin@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) - unplugin: 1.12.0 + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) + unplugin: 1.12.2 '@storybook/csf@0.0.1': dependencies: @@ -7439,47 +7679,47 @@ snapshots: '@storybook/global@5.0.0': {} - '@storybook/icons@1.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/icons@1.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/instrumenter@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/instrumenter@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/global': 5.0.0 '@vitest/utils': 1.6.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) util: 0.12.5 - '@storybook/manager-api@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/manager-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/preview-api@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/preview-api@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/react-dom-shim@8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/react-dom-shim@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/react-vite@8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.19.0)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12))': + '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12)) - '@rollup/pluginutils': 5.1.0(rollup@4.19.0) - '@storybook/builder-vite': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12)) - '@storybook/react': 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) + '@rollup/pluginutils': 5.1.0(rollup@4.21.1) + '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) + '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) find-up: 5.0.0 - magic-string: 0.30.10 + magic-string: 0.30.11 react: 18.3.1 react-docgen: 7.0.3 react-dom: 18.3.1(react@18.3.1) resolve: 1.22.8 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) tsconfig-paths: 4.2.0 - vite: 5.3.3(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) transitivePeerDependencies: - '@preact/preset-vite' - rollup @@ -7487,17 +7727,17 @@ snapshots: - typescript - vite-plugin-glimmerx - '@storybook/react@8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))(typescript@5.5.3)': + '@storybook/react@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)': dependencies: - '@storybook/components': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/components': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/preview-api': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/react-dom-shim': 8.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) - '@storybook/theming': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/manager-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/preview-api': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 18.19.42 + '@types/node': 18.19.46 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -7509,23 +7749,23 @@ snapshots: react-dom: 18.3.1(react@18.3.1) react-element-to-jsx-string: 15.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) semver: 7.6.3 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 type-fest: 2.19.0 util-deprecate: 1.0.2 optionalDependencies: typescript: 5.5.3 - '@storybook/test@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/test@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: '@storybook/csf': 0.1.11 - '@storybook/instrumenter': 8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9))) + '@storybook/instrumenter': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@testing-library/dom': 10.1.0 '@testing-library/jest-dom': 6.4.5 '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) util: 0.12.5 transitivePeerDependencies: - '@jest/globals' @@ -7534,14 +7774,14 @@ snapshots: - jest - vitest - '@storybook/theming@8.2.5(storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)))': + '@storybook/theming@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: - storybook: 8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) '@testing-library/dom@10.1.0': dependencies: '@babel/code-frame': 7.24.7 - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.25.4 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -7552,7 +7792,7 @@ snapshots: '@testing-library/jest-dom@6.4.5': dependencies: '@adobe/css-tools': 4.4.0 - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.25.4 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 @@ -7572,43 +7812,43 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.24.8 - '@babel/types': 7.24.9 + '@babel/parser': 7.25.4 + '@babel/types': 7.25.4 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.24.9 + '@babel/types': 7.25.4 '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 18.19.42 + '@types/node': 18.19.46 '@types/connect@3.4.38': dependencies: - '@types/node': 18.19.42 + '@types/node': 18.19.46 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 '@types/cookie@0.6.0': {} '@types/cross-spawn@6.0.6': dependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 '@types/debug@4.1.12': dependencies: @@ -7630,7 +7870,7 @@ snapshots: '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 18.19.42 + '@types/node': 18.19.46 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -7647,15 +7887,15 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.14.12 + '@types/node': 22.5.0 '@types/hast@2.3.10': dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 '@types/hast@3.0.4': dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 '@types/http-errors@2.0.4': {} @@ -7667,7 +7907,7 @@ snapshots: '@types/mdast@3.0.15': dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 '@types/mdx@2.0.13': {} @@ -7679,15 +7919,15 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 - '@types/node@18.19.42': + '@types/node@18.19.46': dependencies: undici-types: 5.26.5 - '@types/node@20.14.12': + '@types/node@22.5.0': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/prop-types@15.7.12': {} @@ -7711,17 +7951,17 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 18.19.42 + '@types/node': 18.19.46 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 18.19.42 + '@types/node': 18.19.46 '@types/send': 0.17.4 - '@types/unist@2.0.10': {} + '@types/unist@2.0.11': {} - '@types/unist@3.0.2': {} + '@types/unist@3.0.3': {} '@types/uuid@9.0.8': {} @@ -7735,7 +7975,7 @@ snapshots: '@typescript-eslint/visitor-keys': 7.16.0 eslint: 8.57.0 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 5.3.2 natural-compare: 1.4.0 ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: @@ -7749,7 +7989,7 @@ snapshots: '@typescript-eslint/types': 7.16.0 '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3) '@typescript-eslint/visitor-keys': 7.16.0 - debug: 4.3.5 + debug: 4.3.6 eslint: 8.57.0 optionalDependencies: typescript: 5.5.3 @@ -7770,7 +8010,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 7.16.0(typescript@5.5.3) '@typescript-eslint/utils': 7.16.0(eslint@8.57.0)(typescript@5.5.3) - debug: 4.3.5 + debug: 4.3.6 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: @@ -7786,7 +8026,7 @@ snapshots: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.5 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.3 @@ -7800,7 +8040,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.16.0 '@typescript-eslint/visitor-keys': 7.16.0 - debug: 4.3.5 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -7851,14 +8091,14 @@ snapshots: '@vanilla-extract/babel-plugin-debug-ids@1.0.6': dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 transitivePeerDependencies: - supports-color '@vanilla-extract/css@1.15.3': dependencies: '@emotion/hash': 0.9.2 - '@vanilla-extract/private': 1.0.5 + '@vanilla-extract/private': 1.0.6 css-what: 6.1.0 cssesc: 3.0.0 csstype: 3.1.3 @@ -7871,21 +8111,38 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@6.5.0(@types/node@20.14.12)': + '@vanilla-extract/css@1.15.5': dependencies: - '@babel/core': 7.24.9 - '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.9) + '@emotion/hash': 0.9.2 + '@vanilla-extract/private': 1.0.6 + css-what: 6.1.0 + cssesc: 3.0.0 + csstype: 3.1.3 + dedent: 1.5.3 + deep-object-diff: 1.1.9 + deepmerge: 4.3.1 + lru-cache: 10.4.3 + media-query-parser: 2.0.2 + modern-ahocorasick: 1.0.1 + picocolors: 1.0.1 + transitivePeerDependencies: + - babel-plugin-macros + + '@vanilla-extract/integration@6.5.0(@types/node@22.5.0)': + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) '@vanilla-extract/babel-plugin-debug-ids': 1.0.6 '@vanilla-extract/css': 1.15.3 - esbuild: 0.17.19 + esbuild: 0.17.6 eval: 0.1.8 find-up: 5.0.0 javascript-stringify: 2.1.0 lodash: 4.17.21 mlly: 1.7.1 outdent: 0.8.0 - vite: 5.3.3(@types/node@20.14.12) - vite-node: 1.6.0(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) + vite-node: 1.6.0(@types/node@22.5.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7897,20 +8154,20 @@ snapshots: - supports-color - terser - '@vanilla-extract/integration@7.1.7(@types/node@20.14.12)': + '@vanilla-extract/integration@7.1.9(@types/node@22.5.0)': dependencies: - '@babel/core': 7.24.9 - '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) '@vanilla-extract/babel-plugin-debug-ids': 1.0.6 - '@vanilla-extract/css': 1.15.3 + '@vanilla-extract/css': 1.15.5 dedent: 1.5.3 - esbuild: 0.21.5 + esbuild: 0.23.1 eval: 0.1.8 find-up: 5.0.0 javascript-stringify: 2.1.0 mlly: 1.7.1 - vite: 5.3.3(@types/node@20.14.12) - vite-node: 1.6.0(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) + vite-node: 1.6.0(@types/node@22.5.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7922,12 +8179,12 @@ snapshots: - supports-color - terser - '@vanilla-extract/private@1.0.5': {} + '@vanilla-extract/private@1.0.6': {} - '@vanilla-extract/vite-plugin@4.0.13(@types/node@20.14.12)(vite@5.3.3(@types/node@20.14.12))': + '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.0)(vite@5.3.3(@types/node@22.5.0))': dependencies: - '@vanilla-extract/integration': 7.1.7(@types/node@20.14.12) - vite: 5.3.3(@types/node@20.14.12) + '@vanilla-extract/integration': 7.1.9(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7943,7 +8200,7 @@ snapshots: dependencies: '@vitest/spy': 1.6.0 '@vitest/utils': 1.6.0 - chai: 4.4.1 + chai: 4.5.0 '@vitest/spy@1.6.0': dependencies: @@ -8022,7 +8279,9 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-escapes@6.2.1: {} + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 ansi-regex@5.0.1: {} @@ -8145,55 +8404,55 @@ snapshots: ast-types@0.16.1: dependencies: - tslib: 2.6.3 + tslib: 2.7.0 - astring@1.8.6: {} + astring@1.9.0: {} - autoprefixer@10.4.19(postcss@8.4.39): + autoprefixer@10.4.19(postcss@8.4.41): dependencies: - browserslist: 4.23.2 - caniuse-lite: 1.0.30001643 + browserslist: 4.23.3 + caniuse-lite: 1.0.30001653 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 - postcss: 8.4.39 + postcss: 8.4.41 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - axe-core@4.9.1: {} + axe-core@4.10.0: {} axobject-query@3.1.1: dependencies: deep-equal: 2.2.3 - babel-core@7.0.0-bridge.0(@babel/core@7.24.9): + babel-core@7.0.0-bridge.0(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.9 + '@babel/core': 7.25.2 - babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.9): + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.25.2): dependencies: - '@babel/compat-data': 7.24.9 - '@babel/core': 7.24.9 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.9) + '@babel/compat-data': 7.25.4 + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.9): + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.9 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.9) - core-js-compat: 3.37.1 + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) + core-js-compat: 3.38.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.24.9): + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.2): dependencies: - '@babel/core': 7.24.9 - '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.9) + '@babel/core': 7.25.2 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.2) transitivePeerDependencies: - supports-color @@ -8253,12 +8512,12 @@ snapshots: dependencies: pako: 0.2.9 - browserslist@4.23.2: + browserslist@4.23.3: dependencies: - caniuse-lite: 1.0.30001643 - electron-to-chromium: 1.5.0 + caniuse-lite: 1.0.30001653 + electron-to-chromium: 1.5.13 node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.2) + update-browserslist-db: 1.1.0(browserslist@4.23.3) buffer-from@1.1.2: {} @@ -8298,18 +8557,18 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001643: {} + caniuse-lite@1.0.30001653: {} capnp-ts@0.7.0: dependencies: - debug: 4.3.5 - tslib: 2.6.3 + debug: 4.3.6 + tslib: 2.7.0 transitivePeerDependencies: - supports-color ccount@2.0.1: {} - chai@4.4.1: + chai@4.5.0: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -8317,7 +8576,7 @@ snapshots: get-func-name: 2.0.2 loupe: 2.3.7 pathval: 1.1.1 - type-detect: 4.0.8 + type-detect: 4.1.0 chalk@2.4.2: dependencies: @@ -8375,9 +8634,9 @@ snapshots: dependencies: restore-cursor: 3.1.0 - cli-cursor@4.0.0: + cli-cursor@5.0.0: dependencies: - restore-cursor: 4.0.0 + restore-cursor: 5.1.0 cli-spinners@2.9.2: {} @@ -8480,15 +8739,15 @@ snapshots: cookie@0.6.0: {} - core-js-compat@3.37.1: + core-js-compat@3.38.1: dependencies: - browserslist: 4.23.2 + browserslist: 4.23.3 core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.12)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): + cosmiconfig-typescript-loader@5.0.0(@types/node@22.5.0)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.6 typescript: 5.5.3 @@ -8556,7 +8815,7 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.3.5: + debug@4.3.6: dependencies: ms: 2.1.2 @@ -8568,7 +8827,7 @@ snapshots: deep-eql@4.1.4: dependencies: - type-detect: 4.0.8 + type-detect: 4.1.0 deep-equal@2.2.3: dependencies: @@ -8660,9 +8919,9 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.0: {} + electron-to-chromium@1.5.13: {} - emoji-regex@10.3.0: {} + emoji-regex@10.4.0: {} emoji-regex@8.0.0: {} @@ -8683,6 +8942,8 @@ snapshots: envinfo@7.13.0: {} + environment@1.1.0: {} + err-code@2.0.3: {} error-ex@1.3.2: @@ -8795,16 +9056,16 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 - esbuild-plugins-node-modules-polyfill@1.6.4(esbuild@0.17.6): + esbuild-plugins-node-modules-polyfill@1.6.5(esbuild@0.17.6): dependencies: '@jspm/core': 2.0.1 esbuild: 0.17.6 local-pkg: 0.5.0 resolve.exports: 2.0.2 - esbuild-register@3.5.0(esbuild@0.21.5): + esbuild-register@3.6.0(esbuild@0.21.5): dependencies: - debug: 4.3.5 + debug: 4.3.6 esbuild: 0.21.5 transitivePeerDependencies: - supports-color @@ -8885,6 +9146,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esbuild@0.23.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.1 + '@esbuild/android-arm': 0.23.1 + '@esbuild/android-arm64': 0.23.1 + '@esbuild/android-x64': 0.23.1 + '@esbuild/darwin-arm64': 0.23.1 + '@esbuild/darwin-x64': 0.23.1 + '@esbuild/freebsd-arm64': 0.23.1 + '@esbuild/freebsd-x64': 0.23.1 + '@esbuild/linux-arm': 0.23.1 + '@esbuild/linux-arm64': 0.23.1 + '@esbuild/linux-ia32': 0.23.1 + '@esbuild/linux-loong64': 0.23.1 + '@esbuild/linux-mips64el': 0.23.1 + '@esbuild/linux-ppc64': 0.23.1 + '@esbuild/linux-riscv64': 0.23.1 + '@esbuild/linux-s390x': 0.23.1 + '@esbuild/linux-x64': 0.23.1 + '@esbuild/netbsd-x64': 0.23.1 + '@esbuild/openbsd-arm64': 0.23.1 + '@esbuild/openbsd-x64': 0.23.1 + '@esbuild/sunos-x64': 0.23.1 + '@esbuild/win32-arm64': 0.23.1 + '@esbuild/win32-ia32': 0.23.1 + '@esbuild/win32-x64': 0.23.1 + escalade@3.1.2: {} escape-html@1.0.3: {} @@ -8904,21 +9192,21 @@ snapshots: eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 - is-core-module: 2.15.0 + is-core-module: 2.15.1 resolve: 1.22.8 transitivePeerDependencies: - supports-color eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: - debug: 4.3.5 + debug: 4.3.6 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.6 - is-core-module: 2.15.0 + is-core-module: 2.15.1 is-glob: 4.0.3 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -8926,7 +9214,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -8947,9 +9235,9 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 - is-core-module: 2.15.0 + is-core-module: 2.15.1 is-glob: 4.0.3 minimatch: 3.1.2 object.fromentries: 2.0.8 @@ -8970,7 +9258,7 @@ snapshots: array-includes: 3.1.8 array.prototype.flatmap: 1.3.2 ast-types-flow: 0.0.8 - axe-core: 4.9.1 + axe-core: 4.10.0 axobject-query: 3.1.1 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 @@ -9053,7 +9341,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.5 + debug: 4.3.6 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -9067,7 +9355,7 @@ snapshots: glob-parent: 6.0.2 globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.3.1 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -9120,7 +9408,7 @@ snapshots: estree-util-to-js@1.2.0: dependencies: '@types/estree-jsx': 1.0.5 - astring: 1.8.6 + astring: 1.9.0 source-map: 0.7.4 estree-util-value-to-estree@1.3.0: @@ -9130,7 +9418,7 @@ snapshots: estree-util-visit@1.2.1: dependencies: '@types/estree-jsx': 1.0.5 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 estree-walker@0.6.1: {} @@ -9146,7 +9434,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 require-like: 0.1.2 event-target-shim@5.0.1: {} @@ -9227,7 +9515,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.7 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} @@ -9307,13 +9595,13 @@ snapshots: flatted@3.3.1: {} - flow-parser@0.241.0: {} + flow-parser@0.244.0: {} for-each@0.3.3: dependencies: is-callable: 1.2.7 - foreground-child@3.2.1: + foreground-child@3.3.0: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 @@ -9411,7 +9699,7 @@ snapshots: consola: 3.2.3 defu: 6.1.4 node-fetch-native: 1.6.4 - nypm: 0.3.9 + nypm: 0.3.11 ohash: 1.1.3 pathe: 1.1.2 tar: 6.2.1 @@ -9441,7 +9729,7 @@ snapshots: glob@10.4.5: dependencies: - foreground-child: 3.2.1 + foreground-child: 3.3.0 jackspeak: 3.4.3 minimatch: 9.0.5 minipass: 7.1.2 @@ -9477,7 +9765,7 @@ snapshots: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -9485,7 +9773,7 @@ snapshots: dependencies: '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 path-type: 5.0.0 slash: 5.1.0 unicorn-magic: 0.1.0 @@ -9544,7 +9832,7 @@ snapshots: '@types/estree': 1.0.5 '@types/estree-jsx': 1.0.5 '@types/hast': 2.3.10 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 comma-separated-tokens: 2.0.3 estree-util-attach-comments: 2.1.1 estree-util-is-identifier-name: 2.1.0 @@ -9589,13 +9877,13 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.39): + icss-utils@5.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.39 + postcss: 8.4.41 ieee754@1.2.1: {} - ignore@5.3.1: {} + ignore@5.3.2: {} import-fresh@3.3.0: dependencies: @@ -9669,7 +9957,7 @@ snapshots: is-callable@1.2.7: {} - is-core-module@2.15.0: + is-core-module@2.15.1: dependencies: hasown: 2.0.2 @@ -9819,30 +10107,30 @@ snapshots: dependencies: argparse: 2.0.1 - jscodeshift@0.15.2(@babel/preset-env@7.24.8(@babel/core@7.24.9)): - dependencies: - '@babel/core': 7.24.9 - '@babel/parser': 7.24.8 - '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.9) - '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.24.9) - '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.9) - '@babel/preset-flow': 7.24.7(@babel/core@7.24.9) - '@babel/preset-typescript': 7.24.7(@babel/core@7.24.9) - '@babel/register': 7.24.6(@babel/core@7.24.9) - babel-core: 7.0.0-bridge.0(@babel/core@7.24.9) + jscodeshift@0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)): + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.4 + '@babel/plugin-transform-class-properties': 7.25.4(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-private-methods': 7.25.4(@babel/core@7.25.2) + '@babel/preset-flow': 7.24.7(@babel/core@7.25.2) + '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) + '@babel/register': 7.24.6(@babel/core@7.25.2) + babel-core: 7.0.0-bridge.0(@babel/core@7.25.2) chalk: 4.1.2 - flow-parser: 0.241.0 + flow-parser: 0.244.0 graceful-fs: 4.2.11 - micromatch: 4.0.7 + micromatch: 4.0.8 neo-async: 2.6.2 node-dir: 0.1.17 recast: 0.23.9 temp: 0.8.4 write-file-atomic: 2.4.3 optionalDependencies: - '@babel/preset-env': 7.24.8(@babel/core@7.24.9) + '@babel/preset-env': 7.25.4(@babel/core@7.25.2) transitivePeerDependencies: - supports-color @@ -9916,23 +10204,23 @@ snapshots: dependencies: chalk: 5.3.0 commander: 12.1.0 - debug: 4.3.5 + debug: 4.3.6 execa: 8.0.1 lilconfig: 3.1.2 - listr2: 8.2.3 - micromatch: 4.0.7 + listr2: 8.2.4 + micromatch: 4.0.8 pidtree: 0.6.0 string-argv: 0.3.2 yaml: 2.4.5 transitivePeerDependencies: - supports-color - listr2@8.2.3: + listr2@8.2.4: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 eventemitter3: 5.0.1 - log-update: 6.0.0 + log-update: 6.1.0 rfdc: 1.4.1 wrap-ansi: 9.0.0 @@ -9941,7 +10229,7 @@ snapshots: local-pkg@0.5.0: dependencies: mlly: 1.7.1 - pkg-types: 1.1.3 + pkg-types: 1.2.0 locate-path@3.0.0: dependencies: @@ -9987,10 +10275,10 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-update@6.0.0: + log-update@6.1.0: dependencies: - ansi-escapes: 6.2.1 - cli-cursor: 4.0.0 + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 slice-ansi: 7.1.0 strip-ansi: 7.1.0 wrap-ansi: 9.0.0 @@ -10023,7 +10311,7 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.10: + magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -10040,20 +10328,20 @@ snapshots: markdown-extensions@1.1.1: {} - markdown-to-jsx@7.4.7(react@18.3.1): + markdown-to-jsx@7.5.0(react@18.3.1): dependencies: react: 18.3.1 mdast-util-definitions@5.1.2: dependencies: '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-visit: 4.1.2 mdast-util-from-markdown@1.3.1: dependencies: '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 decode-named-character-reference: 1.0.2 mdast-util-to-string: 3.2.0 micromark: 3.2.0 @@ -10088,7 +10376,7 @@ snapshots: '@types/estree-jsx': 1.0.5 '@types/hast': 2.3.10 '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 ccount: 2.0.1 mdast-util-from-markdown: 1.3.1 mdast-util-to-markdown: 1.5.0 @@ -10139,7 +10427,7 @@ snapshots: mdast-util-to-markdown@1.5.0: dependencies: '@types/mdast': 3.0.15 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 longest-streak: 3.1.0 mdast-util-phrasing: 3.0.1 mdast-util-to-string: 3.2.0 @@ -10153,7 +10441,7 @@ snapshots: media-query-parser@2.0.2: dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.25.4 media-typer@0.3.0: {} @@ -10328,7 +10616,7 @@ snapshots: dependencies: '@types/acorn': 4.0.6 '@types/estree': 1.0.5 - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 estree-util-visit: 1.2.1 micromark-util-symbol: 1.1.0 micromark-util-types: 1.1.0 @@ -10365,7 +10653,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.5 + debug: 4.3.6 decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -10384,7 +10672,7 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@4.0.7: + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 @@ -10407,9 +10695,11 @@ snapshots: mimic-fn@4.0.0: {} + mimic-function@5.0.1: {} + min-indent@1.0.1: {} - miniflare@3.20240718.0: + miniflare@3.20240821.0: dependencies: '@cspotcode/source-map-support': 0.8.1 acorn: 8.12.1 @@ -10419,7 +10709,7 @@ snapshots: glob-to-regexp: 0.4.1 stoppable: 1.1.0 undici: 5.28.4 - workerd: 1.20240718.0 + workerd: 1.20240821.1 ws: 8.18.0 youch: 3.3.3 zod: 3.23.8 @@ -10471,7 +10761,7 @@ snapshots: dependencies: acorn: 8.12.1 pathe: 1.1.2 - pkg-types: 1.1.3 + pkg-types: 1.2.0 ufo: 1.5.4 modern-ahocorasick@1.0.1: {} @@ -10519,7 +10809,7 @@ snapshots: normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.1 - is-core-module: 2.15.0 + is-core-module: 2.15.1 semver: 7.6.3 validate-npm-package-license: 3.0.4 @@ -10555,13 +10845,13 @@ snapshots: dependencies: path-key: 4.0.0 - nypm@0.3.9: + nypm@0.3.11: dependencies: citty: 0.1.6 consola: 3.2.3 execa: 8.0.1 pathe: 1.1.2 - pkg-types: 1.1.3 + pkg-types: 1.2.0 ufo: 1.5.4 object-assign@4.1.1: {} @@ -10637,6 +10927,10 @@ snapshots: dependencies: mimic-fn: 4.0.0 + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -10704,7 +10998,7 @@ snapshots: parse-entities@4.0.1: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 @@ -10785,7 +11079,7 @@ snapshots: dependencies: find-up: 4.1.0 - pkg-types@1.1.3: + pkg-types@1.2.0: dependencies: confbox: 0.1.7 mlly: 1.7.1 @@ -10793,62 +11087,62 @@ snapshots: polished@4.3.1: dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.25.4 possible-typed-array-names@1.0.0: {} - postcss-discard-duplicates@5.1.0(postcss@8.4.39): + postcss-discard-duplicates@5.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.39 + postcss: 8.4.41 - postcss-load-config@4.0.2(postcss@8.4.39): + postcss-load-config@4.0.2(postcss@8.4.41): dependencies: lilconfig: 3.1.2 - yaml: 2.4.5 + yaml: 2.5.0 optionalDependencies: - postcss: 8.4.39 + postcss: 8.4.41 - postcss-modules-extract-imports@3.1.0(postcss@8.4.39): + postcss-modules-extract-imports@3.1.0(postcss@8.4.41): dependencies: - postcss: 8.4.39 + postcss: 8.4.41 - postcss-modules-local-by-default@4.0.5(postcss@8.4.39): + postcss-modules-local-by-default@4.0.5(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.39) - postcss: 8.4.39 - postcss-selector-parser: 6.1.1 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.39): + postcss-modules-scope@3.2.0(postcss@8.4.41): dependencies: - postcss: 8.4.39 - postcss-selector-parser: 6.1.1 + postcss: 8.4.41 + postcss-selector-parser: 6.1.2 - postcss-modules-values@4.0.0(postcss@8.4.39): + postcss-modules-values@4.0.0(postcss@8.4.41): dependencies: - icss-utils: 5.1.0(postcss@8.4.39) - postcss: 8.4.39 + icss-utils: 5.1.0(postcss@8.4.41) + postcss: 8.4.41 - postcss-modules@6.0.0(postcss@8.4.39): + postcss-modules@6.0.0(postcss@8.4.41): dependencies: generic-names: 4.0.0 - icss-utils: 5.1.0(postcss@8.4.39) + icss-utils: 5.1.0(postcss@8.4.41) lodash.camelcase: 4.3.0 - postcss: 8.4.39 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.39) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.39) - postcss-modules-scope: 3.2.0(postcss@8.4.39) - postcss-modules-values: 4.0.0(postcss@8.4.39) + postcss: 8.4.41 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.41) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.41) + postcss-modules-scope: 3.2.0(postcss@8.4.41) + postcss-modules-values: 4.0.0(postcss@8.4.41) string-hash: 1.1.3 - postcss-selector-parser@6.1.1: + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.4.39: + postcss@8.4.41: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -10957,9 +11251,9 @@ snapshots: react-docgen@7.0.3: dependencies: - '@babel/core': 7.24.9 - '@babel/traverse': 7.24.8 - '@babel/types': 7.24.9 + '@babel/core': 7.25.2 + '@babel/traverse': 7.25.4 + '@babel/types': 7.25.4 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 '@types/doctrine': 0.0.9 @@ -10994,16 +11288,16 @@ snapshots: react-refresh@0.14.2: {} - react-router-dom@6.24.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + react-router-dom@6.26.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/router': 1.17.1 + '@remix-run/router': 1.19.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-router: 6.24.1(react@18.3.1) + react-router: 6.26.1(react@18.3.1) - react-router@6.24.1(react@18.3.1): + react-router@6.26.1(react@18.3.1): dependencies: - '@remix-run/router': 1.17.1 + '@remix-run/router': 1.19.1 react: 18.3.1 react@18.3.1: @@ -11036,7 +11330,7 @@ snapshots: esprima: 4.0.1 source-map: 0.6.1 tiny-invariant: 1.3.3 - tslib: 2.6.3 + tslib: 2.7.0 redent@3.0.0: dependencies: @@ -11051,7 +11345,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 globalthis: 1.0.4 - which-builtin-type: 1.1.3 + which-builtin-type: 1.1.4 regenerate-unicode-properties@10.1.1: dependencies: @@ -11063,7 +11357,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.24.8 + '@babel/runtime': 7.25.4 regexp.prototype.flags@1.5.2: dependencies: @@ -11156,13 +11450,13 @@ snapshots: resolve@1.22.8: dependencies: - is-core-module: 2.15.0 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 resolve@2.0.0-next.5: dependencies: - is-core-module: 2.15.0 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -11171,10 +11465,10 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 - restore-cursor@4.0.0: + restore-cursor@5.1.0: dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 + onetime: 7.0.0 + signal-exit: 4.1.0 retry@0.12.0: {} @@ -11204,26 +11498,26 @@ snapshots: dependencies: estree-walker: 0.6.1 - rollup@4.19.0: + rollup@4.21.1: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.19.0 - '@rollup/rollup-android-arm64': 4.19.0 - '@rollup/rollup-darwin-arm64': 4.19.0 - '@rollup/rollup-darwin-x64': 4.19.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.19.0 - '@rollup/rollup-linux-arm-musleabihf': 4.19.0 - '@rollup/rollup-linux-arm64-gnu': 4.19.0 - '@rollup/rollup-linux-arm64-musl': 4.19.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.19.0 - '@rollup/rollup-linux-riscv64-gnu': 4.19.0 - '@rollup/rollup-linux-s390x-gnu': 4.19.0 - '@rollup/rollup-linux-x64-gnu': 4.19.0 - '@rollup/rollup-linux-x64-musl': 4.19.0 - '@rollup/rollup-win32-arm64-msvc': 4.19.0 - '@rollup/rollup-win32-ia32-msvc': 4.19.0 - '@rollup/rollup-win32-x64-msvc': 4.19.0 + '@rollup/rollup-android-arm-eabi': 4.21.1 + '@rollup/rollup-android-arm64': 4.21.1 + '@rollup/rollup-darwin-arm64': 4.21.1 + '@rollup/rollup-darwin-x64': 4.21.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.1 + '@rollup/rollup-linux-arm-musleabihf': 4.21.1 + '@rollup/rollup-linux-arm64-gnu': 4.21.1 + '@rollup/rollup-linux-arm64-musl': 4.21.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.1 + '@rollup/rollup-linux-riscv64-gnu': 4.21.1 + '@rollup/rollup-linux-s390x-gnu': 4.21.1 + '@rollup/rollup-linux-x64-gnu': 4.21.1 + '@rollup/rollup-linux-x64-musl': 4.21.1 + '@rollup/rollup-win32-arm64-msvc': 4.21.1 + '@rollup/rollup-win32-ia32-msvc': 4.21.1 + '@rollup/rollup-win32-x64-msvc': 4.21.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -11295,7 +11589,7 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.6.0: {} + set-cookie-parser@2.7.0: {} set-function-length@1.2.2: dependencies: @@ -11370,16 +11664,16 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.18 + spdx-license-ids: 3.0.20 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.18 + spdx-license-ids: 3.0.20 - spdx-license-ids@3.0.18: {} + spdx-license-ids@3.0.20: {} split2@4.2.0: {} @@ -11400,12 +11694,12 @@ snapshots: stoppable@1.1.0: {} - storybook@8.2.5(@babel/preset-env@7.24.8(@babel/core@7.24.9)): + storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)): dependencies: - '@babel/core': 7.24.9 - '@babel/types': 7.24.9 - '@storybook/codemod': 8.2.5 - '@storybook/core': 8.2.5 + '@babel/core': 7.25.2 + '@babel/types': 7.25.4 + '@storybook/codemod': 8.2.9 + '@storybook/core': 8.2.9 '@types/semver': 7.5.8 '@yarnpkg/fslib': 2.10.3 '@yarnpkg/libzip': 2.3.0 @@ -11420,7 +11714,7 @@ snapshots: fs-extra: 11.2.0 giget: 1.2.3 globby: 14.0.2 - jscodeshift: 0.15.2(@babel/preset-env@7.24.8(@babel/core@7.24.9)) + jscodeshift: 0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)) leven: 3.1.0 ora: 5.4.1 prettier: 3.3.3 @@ -11458,7 +11752,7 @@ snapshots: string-width@7.2.0: dependencies: - emoji-regex: 10.3.0 + emoji-regex: 10.4.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 @@ -11555,7 +11849,7 @@ snapshots: synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.3 + tslib: 2.7.0 tapable@2.2.1: {} @@ -11654,20 +11948,20 @@ snapshots: tslib@1.14.1: {} - tslib@2.6.3: {} + tslib@2.7.0: {} tsutils@3.21.0(typescript@5.5.3): dependencies: tslib: 1.14.1 typescript: 5.5.3 - turbo-stream@2.2.0: {} + turbo-stream@2.3.0: {} type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - type-detect@4.0.8: {} + type-detect@4.1.0: {} type-fest@0.20.2: {} @@ -11725,11 +12019,13 @@ snapshots: undici-types@5.26.5: {} + undici-types@6.19.8: {} + undici@5.28.4: dependencies: '@fastify/busboy': 2.1.1 - undici@6.19.4: {} + undici@6.19.8: {} unenv-nightly@1.10.0-1717606461.a117952: dependencies: @@ -11755,7 +12051,7 @@ snapshots: unified@10.1.2: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 bail: 2.0.2 extend: 3.0.2 is-buffer: 2.0.5 @@ -11779,48 +12075,48 @@ snapshots: unist-util-is@5.2.1: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-is@6.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-position-from-estree@1.1.2: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-position@4.0.4: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-remove-position@4.0.2: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-visit: 4.1.2 unist-util-stringify-position@3.0.3: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-visit-parents@5.1.3: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-is: 5.2.1 unist-util-visit-parents@6.0.1: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit@4.1.2: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-is: 5.2.1 unist-util-visit-parents: 5.1.3 unist-util-visit@5.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 @@ -11828,16 +12124,16 @@ snapshots: unpipe@1.0.0: {} - unplugin@1.12.0: + unplugin@1.12.2: dependencies: acorn: 8.12.1 chokidar: 3.6.0 webpack-sources: 3.2.3 webpack-virtual-modules: 0.6.2 - update-browserslist-db@1.1.0(browserslist@4.23.2): + update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: - browserslist: 4.23.2 + browserslist: 4.23.3 escalade: 3.1.2 picocolors: 1.0.1 @@ -11877,23 +12173,23 @@ snapshots: vfile-message@3.1.4: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 unist-util-stringify-position: 3.0.3 vfile@5.3.7: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 is-buffer: 2.0.5 unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 - vite-node@1.6.0(@types/node@20.14.12): + vite-node@1.6.0(@types/node@22.5.0): dependencies: cac: 6.7.14 - debug: 4.3.5 + debug: 4.3.6 pathe: 1.1.2 picocolors: 1.0.1 - vite: 5.3.3(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) transitivePeerDependencies: - '@types/node' - less @@ -11904,24 +12200,24 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.12)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)): dependencies: - debug: 4.3.5 + debug: 4.3.6 globrex: 0.1.2 tsconfck: 3.1.1(typescript@5.5.3) optionalDependencies: - vite: 5.3.3(@types/node@20.14.12) + vite: 5.3.3(@types/node@22.5.0) transitivePeerDependencies: - supports-color - typescript - vite@5.3.3(@types/node@20.14.12): + vite@5.3.3(@types/node@22.5.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.39 - rollup: 4.19.0 + postcss: 8.4.41 + rollup: 4.21.1 optionalDependencies: - '@types/node': 20.14.12 + '@types/node': 22.5.0 fsevents: 2.3.3 walk-up-path@3.0.1: {} @@ -11950,7 +12246,7 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.1.3: + which-builtin-type@1.1.4: dependencies: function.prototype.name: 1.1.6 has-tostringtag: 1.0.2 @@ -11990,24 +12286,25 @@ snapshots: word-wrap@1.2.5: {} - workerd@1.20240718.0: + workerd@1.20240821.1: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20240718.0 - '@cloudflare/workerd-darwin-arm64': 1.20240718.0 - '@cloudflare/workerd-linux-64': 1.20240718.0 - '@cloudflare/workerd-linux-arm64': 1.20240718.0 - '@cloudflare/workerd-windows-64': 1.20240718.0 + '@cloudflare/workerd-darwin-64': 1.20240821.1 + '@cloudflare/workerd-darwin-arm64': 1.20240821.1 + '@cloudflare/workerd-linux-64': 1.20240821.1 + '@cloudflare/workerd-linux-arm64': 1.20240821.1 + '@cloudflare/workerd-windows-64': 1.20240821.1 - wrangler@3.66.0(@cloudflare/workers-types@4.20240722.0): + wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 + '@cloudflare/workers-shared': 0.3.0 '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) blake3-wasm: 2.1.5 chokidar: 3.6.0 date-fns: 3.6.0 esbuild: 0.17.19 - miniflare: 3.20240718.0 + miniflare: 3.20240821.0 nanoid: 3.3.7 path-to-regexp: 6.2.2 resolve: 1.22.8 @@ -12015,10 +12312,10 @@ snapshots: selfsigned: 2.4.1 source-map: 0.6.1 unenv: unenv-nightly@1.10.0-1717606461.a117952 - workerd: 1.20240718.0 + workerd: 1.20240821.1 xxhash-wasm: 1.0.2 optionalDependencies: - '@cloudflare/workers-types': 4.20240722.0 + '@cloudflare/workers-types': 4.20240821.1 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil @@ -12067,6 +12364,8 @@ snapshots: yaml@2.4.5: {} + yaml@2.5.0: {} + yargs-parser@21.1.1: {} yargs@17.7.2: From 758b41d9cc968aeb4d82317c8c1558f9a65abd4d Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 30 Aug 2024 17:09:41 +0900 Subject: [PATCH 04/21] refactor: remove unnecessary `if` & treat nullish `serverError` --- app/utils/api.server.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/utils/api.server.ts b/app/utils/api.server.ts index 38956af..7fb8963 100644 --- a/app/utils/api.server.ts +++ b/app/utils/api.server.ts @@ -125,9 +125,7 @@ export const fetchApi = async ( error.message; // error message from server - 1st priority - if (serverError.message) { - error.message = serverError.message ?? error.message; - } + error.message = serverError?.message ?? error.message; throw new ApiError({ ...error, From 89377ab4ef55a51852c59e90647a6be9e75b82d7 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 30 Aug 2024 17:43:16 +0900 Subject: [PATCH 05/21] build: update `pnpm-lock.yaml` --- pnpm-lock.yaml | 484 ++++++++++++++++++++++++------------------------- 1 file changed, 242 insertions(+), 242 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa1919b..7170ef4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,13 +38,13 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.3.0 - version: 19.3.0(@types/node@22.5.0)(typescript@5.5.3) + version: 19.3.0(@types/node@22.5.1)(typescript@5.5.3) '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 '@remix-run/dev': specifier: 2.11.2 - version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.0)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1)) + version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.1)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1)) '@remix-run/testing': specifier: 2.11.2 version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) @@ -65,7 +65,7 @@ importers: version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) '@storybook/react-vite': specifier: 8.2.9 - version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) '@storybook/test': specifier: 8.2.9 version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -86,7 +86,7 @@ importers: version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) '@vanilla-extract/vite-plugin': specifier: 4.0.13 - version: 4.0.13(@types/node@22.5.0)(vite@5.3.3(@types/node@22.5.0)) + version: 4.0.13(@types/node@22.5.1)(vite@5.3.3(@types/node@22.5.1)) autoprefixer: specifier: 10.4.19 version: 10.4.19(postcss@8.4.41) @@ -131,10 +131,10 @@ importers: version: 5.5.3 vite: specifier: 5.3.3 - version: 5.3.3(@types/node@22.5.0) + version: 5.3.3(@types/node@22.5.1) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) + version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) wrangler: specifier: 3.72.2 version: 3.72.2(@cloudflare/workers-types@4.20240821.1) @@ -160,8 +160,8 @@ packages: resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.25.5': - resolution: {integrity: sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==} + '@babel/generator@7.25.6': + resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} engines: {node: '>=6.9.0'} '@babel/helper-annotate-as-pure@7.24.7': @@ -251,16 +251,16 @@ packages: resolution: {integrity: sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.25.0': - resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==} + '@babel/helpers@7.25.6': + resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} engines: {node: '>=6.9.0'} '@babel/highlight@7.24.7': resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.25.4': - resolution: {integrity: sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==} + '@babel/parser@7.25.6': + resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} engines: {node: '>=6.0.0'} hasBin: true @@ -338,14 +338,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.24.7': - resolution: {integrity: sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==} + '@babel/plugin-syntax-import-assertions@7.25.6': + resolution: {integrity: sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.24.7': - resolution: {integrity: sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==} + '@babel/plugin-syntax-import-attributes@7.25.6': + resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -758,20 +758,20 @@ packages: '@babel/regjsgen@0.8.0': resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - '@babel/runtime@7.25.4': - resolution: {integrity: sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==} + '@babel/runtime@7.25.6': + resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} '@babel/template@7.25.0': resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.25.4': - resolution: {integrity: sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==} + '@babel/traverse@7.25.6': + resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} engines: {node: '>=6.9.0'} - '@babel/types@7.25.4': - resolution: {integrity: sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==} + '@babel/types@7.25.6': + resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} engines: {node: '>=6.9.0'} '@base2/pretty-print-object@1.0.1': @@ -850,8 +850,8 @@ packages: resolution: {integrity: sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==} engines: {node: '>=v18'} - '@commitlint/lint@19.2.2': - resolution: {integrity: sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==} + '@commitlint/lint@19.4.1': + resolution: {integrity: sha512-Ws4YVAZ0jACTv6VThumITC1I5AG0UyXMGua3qcf55JmXIXm/ejfaVKykrqx7RyZOACKVAs8uDRIsEsi87JZ3+Q==} engines: {node: '>=v18'} '@commitlint/load@19.4.0': @@ -874,8 +874,8 @@ packages: resolution: {integrity: sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==} engines: {node: '>=v18'} - '@commitlint/rules@19.0.3': - resolution: {integrity: sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==} + '@commitlint/rules@19.4.1': + resolution: {integrity: sha512-AgctfzAONoVxmxOXRyxXIq7xEPrd7lK/60h2egp9bgGUMZK9v0+YqLOA+TH+KqCa63ZoCr8owP2YxoSSu7IgnQ==} engines: {node: '>=v18'} '@commitlint/to-lines@19.0.0': @@ -1697,83 +1697,83 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.21.1': - resolution: {integrity: sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==} + '@rollup/rollup-android-arm-eabi@4.21.2': + resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.21.1': - resolution: {integrity: sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==} + '@rollup/rollup-android-arm64@4.21.2': + resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.21.1': - resolution: {integrity: sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==} + '@rollup/rollup-darwin-arm64@4.21.2': + resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.21.1': - resolution: {integrity: sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==} + '@rollup/rollup-darwin-x64@4.21.2': + resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.21.1': - resolution: {integrity: sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==} + '@rollup/rollup-linux-arm-gnueabihf@4.21.2': + resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.21.1': - resolution: {integrity: sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==} + '@rollup/rollup-linux-arm-musleabihf@4.21.2': + resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.21.1': - resolution: {integrity: sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==} + '@rollup/rollup-linux-arm64-gnu@4.21.2': + resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.21.1': - resolution: {integrity: sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==} + '@rollup/rollup-linux-arm64-musl@4.21.2': + resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': - resolution: {integrity: sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': + resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.21.1': - resolution: {integrity: sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==} + '@rollup/rollup-linux-riscv64-gnu@4.21.2': + resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.21.1': - resolution: {integrity: sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==} + '@rollup/rollup-linux-s390x-gnu@4.21.2': + resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.21.1': - resolution: {integrity: sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==} + '@rollup/rollup-linux-x64-gnu@4.21.2': + resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.21.1': - resolution: {integrity: sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==} + '@rollup/rollup-linux-x64-musl@4.21.2': + resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.21.1': - resolution: {integrity: sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==} + '@rollup/rollup-win32-arm64-msvc@4.21.2': + resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.21.1': - resolution: {integrity: sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==} + '@rollup/rollup-win32-ia32-msvc@4.21.2': + resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.21.1': - resolution: {integrity: sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==} + '@rollup/rollup-win32-x64-msvc@4.21.2': + resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==} cpu: [x64] os: [win32] @@ -2094,11 +2094,11 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@18.19.46': - resolution: {integrity: sha512-vnRgMS7W6cKa1/0G3/DTtQYpVrZ8c0Xm6UkLaVFrb9jtcVC3okokW09Ki1Qdrj9ISokszD69nY4WDLRlvHlhAA==} + '@types/node@18.19.47': + resolution: {integrity: sha512-1f7dB3BL/bpd9tnDJrrHb66Y+cVrhxSOTGorRNdHwYTUlTay3HuTDPKo9a/4vX9pMQkhYBcAbL4jQdNlhCFP9A==} - '@types/node@22.5.0': - resolution: {integrity: sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==} + '@types/node@22.5.1': + resolution: {integrity: sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==} '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -2540,8 +2540,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001653: - resolution: {integrity: sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==} + caniuse-lite@1.0.30001655: + resolution: {integrity: sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==} capnp-ts@0.7.0: resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} @@ -3001,11 +3001,11 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} - esbuild-plugins-node-modules-polyfill@1.6.5: - resolution: {integrity: sha512-gppYvODLbtGhnQV7CPcJ67N/RccaBskIs7zNApUYoj2+rwSFPSlA8Mdxqm5AUDGrPki75dRPNOd2/+HK39YRvg==} + esbuild-plugins-node-modules-polyfill@1.6.6: + resolution: {integrity: sha512-0wDvliv65SCaaGtmoITnmXqqiUzU+ggFupnOgkEo2B9cQ+CUt58ql2+EY6dYoEsoqiHRu2NuTrFUJGMJEgMmLw==} engines: {node: '>=14.0.0'} peerDependencies: - esbuild: '>=0.14.0 <=0.23.0' + esbuild: '>=0.14.0 ^0.23.0' esbuild-register@3.6.0: resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} @@ -3032,8 +3032,8 @@ packages: engines: {node: '>=18'} hasBin: true - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} escape-html@1.0.3: @@ -3313,8 +3313,8 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - flow-parser@0.244.0: - resolution: {integrity: sha512-Dkc88m5k8bx1VvHTO9HEJ7tvMcSb3Zvcv1PY4OHK7pHdtdY2aUjhmPy6vpjVJ2uUUOIybRlb91sXE8g4doChtA==} + flow-parser@0.245.0: + resolution: {integrity: sha512-xUBkkpIDfDZHAebnDEX65FCVitJUctab82KFmtP5SY4cGly1vbuYNe6Muyp0NLXrgmBChVdoC2T+3/RUHi4Mww==} engines: {node: '>=0.4.0'} for-each@0.3.3: @@ -3417,8 +3417,8 @@ packages: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} - get-tsconfig@4.7.6: - resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} + get-tsconfig@4.8.0: + resolution: {integrity: sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==} giget@1.2.3: resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} @@ -5027,8 +5027,8 @@ packages: rollup-pluginutils@2.8.2: resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} - rollup@4.21.1: - resolution: {integrity: sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==} + rollup@4.21.2: + resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -5833,14 +5833,14 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.5 + '@babel/generator': 7.25.6 '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.0 - '@babel/parser': 7.25.4 + '@babel/helpers': 7.25.6 + '@babel/parser': 7.25.6 '@babel/template': 7.25.0 - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 convert-source-map: 2.0.0 debug: 4.3.6 gensync: 1.0.0-beta.2 @@ -5849,21 +5849,21 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.25.5': + '@babel/generator@7.25.6': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 '@babel/helper-annotate-as-pure@7.24.7': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -5883,7 +5883,7 @@ snapshots: '@babel/helper-optimise-call-expression': 7.24.7 '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -5908,15 +5908,15 @@ snapshots: '@babel/helper-member-expression-to-functions@7.24.8': dependencies: - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color '@babel/helper-module-imports@7.24.7': dependencies: - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -5926,13 +5926,13 @@ snapshots: '@babel/helper-module-imports': 7.24.7 '@babel/helper-simple-access': 7.24.7 '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@babel/helper-plugin-utils@7.24.8': {} @@ -5941,7 +5941,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-annotate-as-pure': 7.24.7 '@babel/helper-wrap-function': 7.25.0 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -5950,21 +5950,21 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-member-expression-to-functions': 7.24.8 '@babel/helper-optimise-call-expression': 7.24.7 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color '@babel/helper-skip-transparent-expression-wrappers@7.24.7': dependencies: - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color @@ -5977,15 +5977,15 @@ snapshots: '@babel/helper-wrap-function@7.25.0': dependencies: '@babel/template': 7.25.0 - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 transitivePeerDependencies: - supports-color - '@babel/helpers@7.25.0': + '@babel/helpers@7.25.6': dependencies: '@babel/template': 7.25.0 - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@babel/highlight@7.24.7': dependencies: @@ -5994,15 +5994,15 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.0.1 - '@babel/parser@7.25.4': + '@babel/parser@7.25.6': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.3(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -6029,7 +6029,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -6072,12 +6072,12 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.25.2)': + '@babel/plugin-syntax-import-assertions@7.25.6(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.25.2)': + '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 @@ -6159,7 +6159,7 @@ snapshots: '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2) '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -6206,7 +6206,7 @@ snapshots: '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2) - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6278,7 +6278,7 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-compilation-targets': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -6327,7 +6327,7 @@ snapshots: '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.4 + '@babel/traverse': 7.25.6 transitivePeerDependencies: - supports-color @@ -6512,8 +6512,8 @@ snapshots: '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2) '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-assertions': 7.25.6(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.25.2) '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) @@ -6594,7 +6594,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 esutils: 2.0.3 '@babel/preset-typescript@7.24.7(@babel/core@7.25.2)': @@ -6619,29 +6619,29 @@ snapshots: '@babel/regjsgen@0.8.0': {} - '@babel/runtime@7.25.4': + '@babel/runtime@7.25.6': dependencies: regenerator-runtime: 0.14.1 '@babel/template@7.25.0': dependencies: '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.4 - '@babel/types': 7.25.4 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 - '@babel/traverse@7.25.4': + '@babel/traverse@7.25.6': dependencies: '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.5 - '@babel/parser': 7.25.4 + '@babel/generator': 7.25.6 + '@babel/parser': 7.25.6 '@babel/template': 7.25.0 - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.25.4': + '@babel/types@7.25.6': dependencies: '@babel/helper-string-parser': 7.24.8 '@babel/helper-validator-identifier': 7.24.7 @@ -6676,11 +6676,11 @@ snapshots: '@cloudflare/workers-types@4.20240821.1': {} - '@commitlint/cli@19.3.0(@types/node@22.5.0)(typescript@5.5.3)': + '@commitlint/cli@19.3.0(@types/node@22.5.1)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 - '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.4.0(@types/node@22.5.0)(typescript@5.5.3) + '@commitlint/lint': 19.4.1 + '@commitlint/load': 19.4.0(@types/node@22.5.1)(typescript@5.5.3) '@commitlint/read': 19.4.0 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -6720,14 +6720,14 @@ snapshots: '@commitlint/types': 19.0.3 semver: 7.6.3 - '@commitlint/lint@19.2.2': + '@commitlint/lint@19.4.1': dependencies: '@commitlint/is-ignored': 19.2.2 '@commitlint/parse': 19.0.3 - '@commitlint/rules': 19.0.3 + '@commitlint/rules': 19.4.1 '@commitlint/types': 19.0.3 - '@commitlint/load@19.4.0(@types/node@22.5.0)(typescript@5.5.3)': + '@commitlint/load@19.4.0(@types/node@22.5.1)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -6735,7 +6735,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.5.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@22.5.0)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@22.5.1)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -6768,7 +6768,7 @@ snapshots: lodash.mergewith: 4.6.2 resolve-from: 5.0.0 - '@commitlint/rules@19.0.3': + '@commitlint/rules@19.4.1': dependencies: '@commitlint/ensure': 19.0.3 '@commitlint/message': 19.0.0 @@ -7126,13 +7126,13 @@ snapshots: dependencies: '@sinclair/typebox': 0.27.8 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.3) - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) optionalDependencies: typescript: 5.5.3 @@ -7253,16 +7253,16 @@ snapshots: optionalDependencies: typescript: 5.5.3 - '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.0)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1))': + '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.1)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1))': dependencies: '@babel/core': 7.25.2 - '@babel/generator': 7.25.5 - '@babel/parser': 7.25.4 + '@babel/generator': 7.25.6 + '@babel/parser': 7.25.6 '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.25.2) '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 '@mdx-js/mdx': 2.3.0 '@npmcli/package-json': 4.0.1 '@remix-run/node': 2.11.2(typescript@5.5.3) @@ -7270,7 +7270,7 @@ snapshots: '@remix-run/router': 1.19.1 '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0(@types/node@22.5.0) + '@vanilla-extract/integration': 6.5.0(@types/node@22.5.1) arg: 5.0.2 cacache: 17.1.4 chalk: 4.1.2 @@ -7279,7 +7279,7 @@ snapshots: dotenv: 16.4.5 es-module-lexer: 1.5.4 esbuild: 0.17.6 - esbuild-plugins-node-modules-polyfill: 1.6.5(esbuild@0.17.6) + esbuild-plugins-node-modules-polyfill: 1.6.6(esbuild@0.17.6) execa: 5.1.1 exit-hook: 2.2.1 express: 4.19.2 @@ -7312,7 +7312,7 @@ snapshots: optionalDependencies: '@remix-run/serve': 2.11.2(typescript@5.5.3) typescript: 5.5.3 - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) wrangler: 3.72.2(@cloudflare/workers-types@4.20240821.1) transitivePeerDependencies: - '@types/node' @@ -7428,60 +7428,60 @@ snapshots: dependencies: web-streams-polyfill: 3.3.3 - '@rollup/pluginutils@5.1.0(rollup@4.21.1)': + '@rollup/pluginutils@5.1.0(rollup@4.21.2)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.21.1 + rollup: 4.21.2 - '@rollup/rollup-android-arm-eabi@4.21.1': + '@rollup/rollup-android-arm-eabi@4.21.2': optional: true - '@rollup/rollup-android-arm64@4.21.1': + '@rollup/rollup-android-arm64@4.21.2': optional: true - '@rollup/rollup-darwin-arm64@4.21.1': + '@rollup/rollup-darwin-arm64@4.21.2': optional: true - '@rollup/rollup-darwin-x64@4.21.1': + '@rollup/rollup-darwin-x64@4.21.2': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.21.1': + '@rollup/rollup-linux-arm-gnueabihf@4.21.2': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.21.1': + '@rollup/rollup-linux-arm-musleabihf@4.21.2': optional: true - '@rollup/rollup-linux-arm64-gnu@4.21.1': + '@rollup/rollup-linux-arm64-gnu@4.21.2': optional: true - '@rollup/rollup-linux-arm64-musl@4.21.1': + '@rollup/rollup-linux-arm64-musl@4.21.2': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.21.1': + '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.21.1': + '@rollup/rollup-linux-riscv64-gnu@4.21.2': optional: true - '@rollup/rollup-linux-s390x-gnu@4.21.1': + '@rollup/rollup-linux-s390x-gnu@4.21.2': optional: true - '@rollup/rollup-linux-x64-gnu@4.21.1': + '@rollup/rollup-linux-x64-gnu@4.21.2': optional: true - '@rollup/rollup-linux-x64-musl@4.21.1': + '@rollup/rollup-linux-x64-musl@4.21.2': optional: true - '@rollup/rollup-win32-arm64-msvc@4.21.1': + '@rollup/rollup-win32-arm64-msvc@4.21.2': optional: true - '@rollup/rollup-win32-ia32-msvc@4.21.1': + '@rollup/rollup-win32-ia32-msvc@4.21.2': optional: true - '@rollup/rollup-win32-x64-msvc@4.21.1': + '@rollup/rollup-win32-x64-msvc@4.21.2': optional: true '@sinclair/typebox@0.27.8': {} @@ -7617,7 +7617,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': + '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': dependencies: '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/find-cache-dir': 3.2.1 @@ -7629,7 +7629,7 @@ snapshots: magic-string: 0.30.11 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: @@ -7639,7 +7639,7 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/preset-env': 7.25.4(@babel/core@7.25.2) - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@storybook/core': 8.2.9 '@storybook/csf': 0.1.11 '@types/cross-spawn': 6.0.6 @@ -7663,7 +7663,7 @@ snapshots: dependencies: '@storybook/csf': 0.1.11 '@types/express': 4.17.21 - '@types/node': 18.19.46 + '@types/node': 18.19.47 browser-assert: 1.2.1 esbuild: 0.21.5 esbuild-register: 3.6.0(esbuild@0.21.5) @@ -7718,11 +7718,11 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0))': + '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) - '@rollup/pluginutils': 5.1.0(rollup@4.21.1) - '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) + '@rollup/pluginutils': 5.1.0(rollup@4.21.2) + '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) find-up: 5.0.0 magic-string: 0.30.11 @@ -7732,7 +7732,7 @@ snapshots: resolve: 1.22.8 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) tsconfig-paths: 4.2.0 - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) transitivePeerDependencies: - '@preact/preset-vite' - rollup @@ -7750,7 +7750,7 @@ snapshots: '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 18.19.46 + '@types/node': 18.19.47 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -7794,7 +7794,7 @@ snapshots: '@testing-library/dom@10.1.0': dependencies: '@babel/code-frame': 7.24.7 - '@babel/runtime': 7.25.4 + '@babel/runtime': 7.25.6 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -7805,7 +7805,7 @@ snapshots: '@testing-library/jest-dom@6.4.5': dependencies: '@adobe/css-tools': 4.4.0 - '@babel/runtime': 7.25.4 + '@babel/runtime': 7.25.6 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 @@ -7825,43 +7825,43 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.25.4 - '@babel/types': 7.25.4 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.25.4 - '@babel/types': 7.25.4 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 18.19.46 + '@types/node': 18.19.47 '@types/connect@3.4.38': dependencies: - '@types/node': 18.19.46 + '@types/node': 18.19.47 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 '@types/cookie@0.6.0': {} '@types/cross-spawn@6.0.6': dependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 '@types/debug@4.1.12': dependencies: @@ -7883,7 +7883,7 @@ snapshots: '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 18.19.46 + '@types/node': 18.19.47 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -7900,7 +7900,7 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.5.0 + '@types/node': 22.5.1 '@types/hast@2.3.10': dependencies: @@ -7932,13 +7932,13 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 - '@types/node@18.19.46': + '@types/node@18.19.47': dependencies: undici-types: 5.26.5 - '@types/node@22.5.0': + '@types/node@22.5.1': dependencies: undici-types: 6.19.8 @@ -7964,12 +7964,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 18.19.46 + '@types/node': 18.19.47 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 18.19.46 + '@types/node': 18.19.47 '@types/send': 0.17.4 '@types/unist@2.0.11': {} @@ -8143,7 +8143,7 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@6.5.0(@types/node@22.5.0)': + '@vanilla-extract/integration@6.5.0(@types/node@22.5.1)': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) @@ -8156,8 +8156,8 @@ snapshots: lodash: 4.17.21 mlly: 1.7.1 outdent: 0.8.0 - vite: 5.3.3(@types/node@22.5.0) - vite-node: 1.6.0(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) + vite-node: 1.6.0(@types/node@22.5.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8169,7 +8169,7 @@ snapshots: - supports-color - terser - '@vanilla-extract/integration@7.1.9(@types/node@22.5.0)': + '@vanilla-extract/integration@7.1.9(@types/node@22.5.1)': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) @@ -8181,8 +8181,8 @@ snapshots: find-up: 5.0.0 javascript-stringify: 2.1.0 mlly: 1.7.1 - vite: 5.3.3(@types/node@22.5.0) - vite-node: 1.6.0(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) + vite-node: 1.6.0(@types/node@22.5.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8196,10 +8196,10 @@ snapshots: '@vanilla-extract/private@1.0.6': {} - '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.0)(vite@5.3.3(@types/node@22.5.0))': + '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.1)(vite@5.3.3(@types/node@22.5.1))': dependencies: - '@vanilla-extract/integration': 7.1.9(@types/node@22.5.0) - vite: 5.3.3(@types/node@22.5.0) + '@vanilla-extract/integration': 7.1.9(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8426,7 +8426,7 @@ snapshots: autoprefixer@10.4.19(postcss@8.4.41): dependencies: browserslist: 4.23.3 - caniuse-lite: 1.0.30001653 + caniuse-lite: 1.0.30001655 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 @@ -8529,7 +8529,7 @@ snapshots: browserslist@4.23.3: dependencies: - caniuse-lite: 1.0.30001653 + caniuse-lite: 1.0.30001655 electron-to-chromium: 1.5.13 node-releases: 2.0.18 update-browserslist-db: 1.1.0(browserslist@4.23.3) @@ -8572,7 +8572,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001653: {} + caniuse-lite@1.0.30001655: {} capnp-ts@0.7.0: dependencies: @@ -8760,9 +8760,9 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@22.5.0)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): + cosmiconfig-typescript-loader@5.0.0(@types/node@22.5.1)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.6 typescript: 5.5.3 @@ -9071,7 +9071,7 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 - esbuild-plugins-node-modules-polyfill@1.6.5(esbuild@0.17.6): + esbuild-plugins-node-modules-polyfill@1.6.6(esbuild@0.17.6): dependencies: '@jspm/core': 2.0.1 esbuild: 0.17.6 @@ -9188,7 +9188,7 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 - escalade@3.1.2: {} + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -9220,7 +9220,7 @@ snapshots: eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 - get-tsconfig: 4.7.6 + get-tsconfig: 4.8.0 is-core-module: 2.15.1 is-glob: 4.0.3 transitivePeerDependencies: @@ -9449,7 +9449,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 require-like: 0.1.2 event-target-shim@5.0.1: {} @@ -9610,7 +9610,7 @@ snapshots: flatted@3.3.1: {} - flow-parser@0.244.0: {} + flow-parser@0.245.0: {} for-each@0.3.3: dependencies: @@ -9704,7 +9704,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.2.4 - get-tsconfig@4.7.6: + get-tsconfig@4.8.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -10125,7 +10125,7 @@ snapshots: jscodeshift@0.15.2(@babel/preset-env@7.25.4(@babel/core@7.25.2)): dependencies: '@babel/core': 7.25.2 - '@babel/parser': 7.25.4 + '@babel/parser': 7.25.6 '@babel/plugin-transform-class-properties': 7.25.4(@babel/core@7.25.2) '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.2) @@ -10136,7 +10136,7 @@ snapshots: '@babel/register': 7.24.6(@babel/core@7.25.2) babel-core: 7.0.0-bridge.0(@babel/core@7.25.2) chalk: 4.1.2 - flow-parser: 0.244.0 + flow-parser: 0.245.0 graceful-fs: 4.2.11 micromatch: 4.0.8 neo-async: 2.6.2 @@ -10456,7 +10456,7 @@ snapshots: media-query-parser@2.0.2: dependencies: - '@babel/runtime': 7.25.4 + '@babel/runtime': 7.25.6 media-typer@0.3.0: {} @@ -11102,7 +11102,7 @@ snapshots: polished@4.3.1: dependencies: - '@babel/runtime': 7.25.4 + '@babel/runtime': 7.25.6 possible-typed-array-names@1.0.0: {} @@ -11267,8 +11267,8 @@ snapshots: react-docgen@7.0.3: dependencies: '@babel/core': 7.25.2 - '@babel/traverse': 7.25.4 - '@babel/types': 7.25.4 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.20.6 '@types/doctrine': 0.0.9 @@ -11372,7 +11372,7 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.25.4 + '@babel/runtime': 7.25.6 regexp.prototype.flags@1.5.2: dependencies: @@ -11513,26 +11513,26 @@ snapshots: dependencies: estree-walker: 0.6.1 - rollup@4.21.1: + rollup@4.21.2: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.21.1 - '@rollup/rollup-android-arm64': 4.21.1 - '@rollup/rollup-darwin-arm64': 4.21.1 - '@rollup/rollup-darwin-x64': 4.21.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.21.1 - '@rollup/rollup-linux-arm-musleabihf': 4.21.1 - '@rollup/rollup-linux-arm64-gnu': 4.21.1 - '@rollup/rollup-linux-arm64-musl': 4.21.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.21.1 - '@rollup/rollup-linux-riscv64-gnu': 4.21.1 - '@rollup/rollup-linux-s390x-gnu': 4.21.1 - '@rollup/rollup-linux-x64-gnu': 4.21.1 - '@rollup/rollup-linux-x64-musl': 4.21.1 - '@rollup/rollup-win32-arm64-msvc': 4.21.1 - '@rollup/rollup-win32-ia32-msvc': 4.21.1 - '@rollup/rollup-win32-x64-msvc': 4.21.1 + '@rollup/rollup-android-arm-eabi': 4.21.2 + '@rollup/rollup-android-arm64': 4.21.2 + '@rollup/rollup-darwin-arm64': 4.21.2 + '@rollup/rollup-darwin-x64': 4.21.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.21.2 + '@rollup/rollup-linux-arm-musleabihf': 4.21.2 + '@rollup/rollup-linux-arm64-gnu': 4.21.2 + '@rollup/rollup-linux-arm64-musl': 4.21.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.21.2 + '@rollup/rollup-linux-riscv64-gnu': 4.21.2 + '@rollup/rollup-linux-s390x-gnu': 4.21.2 + '@rollup/rollup-linux-x64-gnu': 4.21.2 + '@rollup/rollup-linux-x64-musl': 4.21.2 + '@rollup/rollup-win32-arm64-msvc': 4.21.2 + '@rollup/rollup-win32-ia32-msvc': 4.21.2 + '@rollup/rollup-win32-x64-msvc': 4.21.2 fsevents: 2.3.3 run-parallel@1.2.0: @@ -11712,7 +11712,7 @@ snapshots: storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)): dependencies: '@babel/core': 7.25.2 - '@babel/types': 7.25.4 + '@babel/types': 7.25.6 '@storybook/codemod': 8.2.9 '@storybook/core': 8.2.9 '@types/semver': 7.5.8 @@ -12149,7 +12149,7 @@ snapshots: update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: browserslist: 4.23.3 - escalade: 3.1.2 + escalade: 3.2.0 picocolors: 1.0.1 uri-js@4.4.1: @@ -12200,13 +12200,13 @@ snapshots: unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 - vite-node@1.6.0(@types/node@22.5.0): + vite-node@1.6.0(@types/node@22.5.1): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 picocolors: 1.0.1 - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) transitivePeerDependencies: - '@types/node' - less @@ -12217,24 +12217,24 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.0)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)): dependencies: debug: 4.3.6 globrex: 0.1.2 tsconfck: 3.1.1(typescript@5.5.3) optionalDependencies: - vite: 5.3.3(@types/node@22.5.0) + vite: 5.3.3(@types/node@22.5.1) transitivePeerDependencies: - supports-color - typescript - vite@5.3.3(@types/node@22.5.0): + vite@5.3.3(@types/node@22.5.1): dependencies: esbuild: 0.21.5 postcss: 8.4.41 - rollup: 4.21.1 + rollup: 4.21.2 optionalDependencies: - '@types/node': 22.5.0 + '@types/node': 22.5.1 fsevents: 2.3.3 walk-up-path@3.0.1: {} @@ -12388,7 +12388,7 @@ snapshots: yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.2 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 From fb4c64b842a9ffe209c3bac0c162b56a3abeeaad Mon Sep 17 00:00:00 2001 From: aube-dev Date: Thu, 5 Sep 2024 02:19:01 +0900 Subject: [PATCH 06/21] feat: use cloudflare env only & modify dev proxy plugin --- .../KakaoLoginButton/KakaoLoginButton.tsx | 19 +- app/contexts/EnvContext.tsx | 4 + app/hooks/useEnv.tsx | 21 ++ app/root.tsx | 45 ++- app/routes/oauth.kakao.tsx | 15 + app/routes/oauth.kakao.tsx.tsx | 18 - app/vite-env.d.ts | 9 - functions/[[path]].ts | 55 +-- package.json | 8 +- pnpm-lock.yaml | 314 ++++++++++-------- server/README.md | 67 ++++ {app => server}/constants/api.ts | 0 server/constants/env.ts | 20 ++ {app => server}/constants/types/api.ts | 0 {app => server}/constants/types/auth.ts | 0 .../remixCloudflareDevProxyVitePlugin.ts | 193 +++++++++++ .../api.server.ts => server/utils/api.ts | 8 +- .../auth.server.ts => server/utils/auth.ts | 2 +- server/utils/cloudflare.ts | 69 ++++ tsconfig.json | 3 +- vite.config.ts | 8 +- 21 files changed, 627 insertions(+), 251 deletions(-) create mode 100644 app/contexts/EnvContext.tsx create mode 100644 app/hooks/useEnv.tsx create mode 100644 app/routes/oauth.kakao.tsx delete mode 100644 app/routes/oauth.kakao.tsx.tsx delete mode 100644 app/vite-env.d.ts create mode 100644 server/README.md rename {app => server}/constants/api.ts (100%) create mode 100644 server/constants/env.ts rename {app => server}/constants/types/api.ts (100%) rename {app => server}/constants/types/auth.ts (100%) create mode 100644 server/plugins/remixCloudflareDevProxyVitePlugin.ts rename app/utils/api.server.ts => server/utils/api.ts (95%) rename app/utils/auth.server.ts => server/utils/auth.ts (97%) create mode 100644 server/utils/cloudflare.ts diff --git a/app/components/KakaoLoginButton/KakaoLoginButton.tsx b/app/components/KakaoLoginButton/KakaoLoginButton.tsx index eded8da..9ca08d5 100644 --- a/app/components/KakaoLoginButton/KakaoLoginButton.tsx +++ b/app/components/KakaoLoginButton/KakaoLoginButton.tsx @@ -1,15 +1,18 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useState } from 'react'; +import useEnv from '@/hooks/useEnv'; import { getUUID } from '@/utils/random'; -const clientId = 'f5aa2f20e42d783654b8e8c01bfc6312'; -//redirectUri는 등록된 redirectUri중에 임의로 사용했습니다. -const redirectUri = 'http://localhost:5173/oauth/kakao'; - const KakaoLoginButton: React.FC = () => { - const kakaoAuthUrl = useMemo(() => { + const env = useEnv(); + const [kakaoAuthUrl, setKakaoAuthUrl] = useState(''); + + useEffect(() => { const userUUID = getUUID(); - return `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&state=${userUUID}`; - }, []); + const redirectUri = window.location.origin + '/oauth/kakao'; + setKakaoAuthUrl( + `https://kauth.kakao.com/oauth/authorize?client_id=${env.KAKAO_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&state=${userUUID}`, + ); + }, [env.KAKAO_CLIENT_ID]); return ( diff --git a/app/contexts/EnvContext.tsx b/app/contexts/EnvContext.tsx new file mode 100644 index 0000000..ceb7313 --- /dev/null +++ b/app/contexts/EnvContext.tsx @@ -0,0 +1,4 @@ +import { createContext } from 'react'; +import { type ClientEnv } from '@server/constants/env'; + +export const EnvContext = createContext(null); diff --git a/app/hooks/useEnv.tsx b/app/hooks/useEnv.tsx new file mode 100644 index 0000000..c470b07 --- /dev/null +++ b/app/hooks/useEnv.tsx @@ -0,0 +1,21 @@ +import { useContext } from 'react'; +import { EnvContext } from '@/contexts/EnvContext'; +import { type ClientEnv, clientEnvSchema } from '@server/constants/env'; + +/** + * 클라이언트용 환경 변수를 얻는 hook + * @example + * ``` + * const env = useEnv(); + * console.log(env.KAKAO_CLIENT_ID); + * ``` + */ +const useEnv = (): ClientEnv => { + const envFromContext = useContext(EnvContext); + + const env = clientEnvSchema.parse(envFromContext); + + return env; +}; + +export default useEnv; diff --git a/app/root.tsx b/app/root.tsx index ecbfa15..2854c90 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,31 +1,42 @@ +import { json, type LoaderFunctionArgs } from '@remix-run/cloudflare'; import { Links, Meta, Outlet, Scripts, ScrollRestoration, + useLoaderData, } from '@remix-run/react'; -import { type ReactNode } from 'react'; +import { EnvContext } from '@/contexts/EnvContext'; import './root.css'; import '@/styles/theme.css'; -export const Layout = ({ children }: { children: ReactNode }) => ( - - - - - - - - - {children} - - - - -); +export const loader = async (args: LoaderFunctionArgs) => + json({ + env: args.context.clientEnv, + }); -const App = () => ; +const App = () => { + const data = useLoaderData(); + + return ( + + + + + + + + + + + + + + + + ); +}; export default App; diff --git a/app/routes/oauth.kakao.tsx b/app/routes/oauth.kakao.tsx new file mode 100644 index 0000000..c182ef8 --- /dev/null +++ b/app/routes/oauth.kakao.tsx @@ -0,0 +1,15 @@ +import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; + +export const loader = async ({ request }: LoaderFunctionArgs) => { + const url = new URL(request.url); + const code = url.searchParams.get('code'); + const state = url.searchParams.get('state'); + + console.log(code, state); + + return null; +}; + +const KakaoRedirect = () =>
카카오 로그인 중...
; + +export default KakaoRedirect; diff --git a/app/routes/oauth.kakao.tsx.tsx b/app/routes/oauth.kakao.tsx.tsx deleted file mode 100644 index e7eeba1..0000000 --- a/app/routes/oauth.kakao.tsx.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { LoaderFunction, json } from '@remix-run/cloudflare'; - -export const loader: LoaderFunction = async ({ request }) => { - const url = new URL(request.url); - const code = url.searchParams.get('code'); - const state = url.searchParams.get('state'); - - // 이 아래의 try문 지우고 이어서 하면 됩니다 - try { - console.log(code, state); - } catch { - console.log(json); - } -}; - -const KakaoRedirect = () =>
카카오 로그인 중...
; - -export default KakaoRedirect; diff --git a/app/vite-env.d.ts b/app/vite-env.d.ts deleted file mode 100644 index 7ed3a44..0000000 --- a/app/vite-env.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/// - -interface ImportMetaEnv { - readonly VITE_KAKAO_CLIENT_ID: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 4d374ad..2e242ff 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -1,59 +1,34 @@ -import { - createWorkersKVSessionStorage, - createCookie, -} from '@remix-run/cloudflare'; import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; -import type { FetchApi } from '@/constants/types/api'; -import type { AuthSession, AuthSessionData } from '@/constants/types/auth'; -import { fetchApi } from '@/utils/api.server'; +import { + clientEnvSchema, + type ContextEnv, + serverEnvSchema, +} from '@server/constants/env'; +import { getLoadContext, makeAuthSession } from '@server/utils/cloudflare'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` // eslint-disable-next-line import/no-unresolved, import/order import * as build from '../build/server'; -type ContextEnv = { - readonly KV_NAMESPACE: KVNamespace; - readonly AUTH_COOKIE_SESSION_SECRET: string; - readonly API_URL: string; -}; - -declare module '@remix-run/cloudflare' { - interface AppLoadContext extends ContextEnv { - authSession: AuthSession; - fetchApi: FetchApi; - } -} - export const onRequest = async ( // eslint-disable-next-line @typescript-eslint/no-explicit-any context: EventContext, ): Promise => { - const authSessionCookie = createCookie('__auth_session', { - secrets: [context.env.AUTH_COOKIE_SESSION_SECRET], - sameSite: true, - }); - const authSessionStorage = createWorkersKVSessionStorage({ - cookie: authSessionCookie, - kv: context.env.KV_NAMESPACE, - }); - const authSession = await authSessionStorage.getSession( + clientEnvSchema.parse(context.env); + serverEnvSchema.parse(context.env); + + const { authSessionStorage, authSession } = await makeAuthSession( + { + authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: context.env.KV_NAMESPACE, + }, context.request.headers.get('Cookie'), ); const handleRequest = createPagesFunctionHandler({ build, - getLoadContext: ({ context: loadContext }) => ({ - ...loadContext.cloudflare.env, - authSession, - fetchApi: async (apiInfo, variables) => - fetchApi( - apiInfo, - variables, - loadContext.cloudflare.env.API_URL, - authSession, - ), - }), + getLoadContext: (args) => getLoadContext(authSession, args), }); const response = await handleRequest(context); diff --git a/package.json b/package.json index ec2bddf..00a2421 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "module", "scripts": { "build": "remix vite:build", - "dev": "wrangler pages download config ort-web --force && remix vite:build && wrangler pages dev --live-reload ./build/client", + "dev": "wrangler pages download config ort-web --force && remix vite:dev", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc", @@ -24,12 +24,14 @@ "isbot": "4.4.0", "react": "18.3.1", "react-dom": "18.3.1", - "uuid": "10.0.0" + "uuid": "10.0.0", + "zod": "3.23.8" }, "devDependencies": { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", "@remix-run/dev": "2.11.2", + "@remix-run/node": "2.11.2", "@remix-run/testing": "2.11.2", "@storybook/addon-essentials": "8.2.9", "@storybook/addon-interactions": "8.2.9", @@ -40,6 +42,7 @@ "@storybook/test": "8.2.9", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", + "@types/set-cookie-parser": "2.4.10", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "7.16.0", "@typescript-eslint/parser": "7.16.0", @@ -56,6 +59,7 @@ "husky": "9.1.1", "lint-staged": "15.2.7", "prettier": "3.3.3", + "set-cookie-parser": "2.7.0", "storybook": "8.2.9", "typescript": "5.5.3", "vite": "5.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7170ef4..b85e08a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,10 +10,10 @@ importers: dependencies: '@remix-run/cloudflare': specifier: 2.11.2 - version: 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) + version: 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) '@remix-run/cloudflare-pages': specifier: 2.11.2 - version: 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) + version: 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) '@remix-run/react': specifier: 2.11.2 version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) @@ -35,16 +35,22 @@ importers: uuid: specifier: 10.0.0 version: 10.0.0 + zod: + specifier: 3.23.8 + version: 3.23.8 devDependencies: '@commitlint/cli': specifier: 19.3.0 - version: 19.3.0(@types/node@22.5.1)(typescript@5.5.3) + version: 19.3.0(@types/node@22.5.3)(typescript@5.5.3) '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 '@remix-run/dev': specifier: 2.11.2 - version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.1)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1)) + version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) + '@remix-run/node': + specifier: 2.11.2 + version: 2.11.2(typescript@5.5.3) '@remix-run/testing': specifier: 2.11.2 version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) @@ -65,7 +71,7 @@ importers: version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) '@storybook/react-vite': specifier: 8.2.9 - version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) '@storybook/test': specifier: 8.2.9 version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -75,6 +81,9 @@ importers: '@types/react-dom': specifier: 18.3.0 version: 18.3.0 + '@types/set-cookie-parser': + specifier: 2.4.10 + version: 2.4.10 '@types/uuid': specifier: 10.0.0 version: 10.0.0 @@ -86,10 +95,10 @@ importers: version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) '@vanilla-extract/vite-plugin': specifier: 4.0.13 - version: 4.0.13(@types/node@22.5.1)(vite@5.3.3(@types/node@22.5.1)) + version: 4.0.13(@types/node@22.5.3)(vite@5.3.3(@types/node@22.5.3)) autoprefixer: specifier: 10.4.19 - version: 10.4.19(postcss@8.4.41) + version: 10.4.19(postcss@8.4.45) eslint: specifier: 8.57.0 version: 8.57.0 @@ -123,6 +132,9 @@ importers: prettier: specifier: 3.3.3 version: 3.3.3 + set-cookie-parser: + specifier: 2.7.0 + version: 2.7.0 storybook: specifier: 8.2.9 version: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) @@ -131,13 +143,13 @@ importers: version: 5.5.3 vite: specifier: 5.3.3 - version: 5.3.3(@types/node@22.5.1) + version: 5.3.3(@types/node@22.5.3) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) + version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) wrangler: specifier: 3.72.2 - version: 3.72.2(@cloudflare/workers-types@4.20240821.1) + version: 3.72.2(@cloudflare/workers-types@4.20240903.0) packages: @@ -818,8 +830,8 @@ packages: resolution: {integrity: sha512-cqtLW1QiBC/ABaZIhAdyGCsnHHY6pAb6hsVUZg82Co2gQtf/faxRYV1FgpCwUYroTdk6A66xUMSTmFqreKCJow==} engines: {node: '>=16.7.0'} - '@cloudflare/workers-types@4.20240821.1': - resolution: {integrity: sha512-icAkbnAqgVl6ef9lgLTom8na+kj2RBw2ViPAQ586hbdj0xZcnrjK7P46Eu08OU9D/lNDgN2sKU/sxhe2iK/gIg==} + '@cloudflare/workers-types@4.20240903.0': + resolution: {integrity: sha512-a4mqgtVsPWg3JNNlQdLRE0Z6/mHr/uXa1ANDw6Zd7in438UCbeb+j7Z954Sf93G24jExpAn9VZ8kUUml0RwZbQ==} '@commitlint/cli@19.3.0': resolution: {integrity: sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==} @@ -2094,11 +2106,11 @@ packages: '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - '@types/node@18.19.47': - resolution: {integrity: sha512-1f7dB3BL/bpd9tnDJrrHb66Y+cVrhxSOTGorRNdHwYTUlTay3HuTDPKo9a/4vX9pMQkhYBcAbL4jQdNlhCFP9A==} + '@types/node@18.19.49': + resolution: {integrity: sha512-ALCeIR6n0nQ7j0FUF1ycOhrp6+XutJWqEu/vtdEqXFUQwkBfgUA5cEg3ZNmjWGF/ZYA/FcF9QMkL55Ar0O6UrA==} - '@types/node@22.5.1': - resolution: {integrity: sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==} + '@types/node@22.5.3': + resolution: {integrity: sha512-njripolh85IA9SQGTAqbmnNZTdxv7X/4OYGPz8tgy5JDr8MP+uDBa921GpYEoDDnwm0Hmn5ZPeJgiiSTPoOzkQ==} '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -2127,6 +2139,9 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/set-cookie-parser@2.4.10': + resolution: {integrity: sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -3062,8 +3077,8 @@ packages: eslint: '*' eslint-plugin-import: '*' - eslint-module-utils@2.8.2: - resolution: {integrity: sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==} + eslint-module-utils@2.9.0: + resolution: {integrity: sha512-McVbYmwA3NEKwRQY5g4aWMdcZE5xZxV8i8l7CqJSrameuGSQJtSWaL/LxTEzSKKaCcOhlpDR8XEfYXWPrdo/ZQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -3313,8 +3328,8 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - flow-parser@0.245.0: - resolution: {integrity: sha512-xUBkkpIDfDZHAebnDEX65FCVitJUctab82KFmtP5SY4cGly1vbuYNe6Muyp0NLXrgmBChVdoC2T+3/RUHi4Mww==} + flow-parser@0.245.1: + resolution: {integrity: sha512-KaVIjRdCY+APtxQijfV1c7GN1bofByIlR7E6omQLW0sghkA8hh8uufQOqTf3oAAVTExsSLafmdL/QwyvE/gdEg==} engines: {node: '>=0.4.0'} for-each@0.3.3: @@ -4626,8 +4641,8 @@ packages: periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -4719,8 +4734,8 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.41: - resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} + postcss@8.4.45: + resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -5385,8 +5400,8 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} - tsconfck@3.1.1: - resolution: {integrity: sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ==} + tsconfck@3.1.3: + resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -5561,9 +5576,14 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unplugin@1.12.2: - resolution: {integrity: sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==} + unplugin@1.13.1: + resolution: {integrity: sha512-6Kq1iSSwg7KyjcThRUks9LuqDAKvtnioxbL9iEtB9ctTyBA5OmrB8gZd/d225VJu1w3UpUsKV7eGrvf59J7+VA==} engines: {node: '>=14.0.0'} + peerDependencies: + webpack-sources: ^3 + peerDependenciesMeta: + webpack-sources: + optional: true update-browserslist-db@1.1.0: resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} @@ -5668,10 +5688,6 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} - webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} @@ -5783,8 +5799,8 @@ packages: engines: {node: '>= 14'} hasBin: true - yaml@2.5.0: - resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} engines: {node: '>= 14'} hasBin: true @@ -5825,7 +5841,7 @@ snapshots: '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 - picocolors: 1.0.1 + picocolors: 1.1.0 '@babel/compat-data@7.25.4': {} @@ -5992,7 +6008,7 @@ snapshots: '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.1 + picocolors: 1.1.0 '@babel/parser@7.25.6': dependencies: @@ -6674,13 +6690,13 @@ snapshots: '@cloudflare/workers-shared@0.3.0': {} - '@cloudflare/workers-types@4.20240821.1': {} + '@cloudflare/workers-types@4.20240903.0': {} - '@commitlint/cli@19.3.0(@types/node@22.5.1)(typescript@5.5.3)': + '@commitlint/cli@19.3.0(@types/node@22.5.3)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.4.1 - '@commitlint/load': 19.4.0(@types/node@22.5.1)(typescript@5.5.3) + '@commitlint/load': 19.4.0(@types/node@22.5.3)(typescript@5.5.3) '@commitlint/read': 19.4.0 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -6727,7 +6743,7 @@ snapshots: '@commitlint/rules': 19.4.1 '@commitlint/types': 19.0.3 - '@commitlint/load@19.4.0(@types/node@22.5.1)(typescript@5.5.3)': + '@commitlint/load@19.4.0(@types/node@22.5.3)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -6735,7 +6751,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.5.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@22.5.1)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@22.5.3)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -7126,13 +7142,13 @@ snapshots: dependencies: '@sinclair/typebox': 0.27.8 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.3) - vite: 5.3.3(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) optionalDependencies: typescript: 5.5.3 @@ -7238,22 +7254,22 @@ snapshots: '@pkgr/core@0.1.1': {} - '@remix-run/cloudflare-pages@2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3)': + '@remix-run/cloudflare-pages@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': dependencies: - '@cloudflare/workers-types': 4.20240821.1 - '@remix-run/cloudflare': 2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3) + '@cloudflare/workers-types': 4.20240903.0 + '@remix-run/cloudflare': 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 - '@remix-run/cloudflare@2.11.2(@cloudflare/workers-types@4.20240821.1)(typescript@5.5.3)': + '@remix-run/cloudflare@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': dependencies: '@cloudflare/kv-asset-handler': 0.1.3 - '@cloudflare/workers-types': 4.20240821.1 + '@cloudflare/workers-types': 4.20240903.0 '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 - '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.1)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))(wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1))': + '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0))': dependencies: '@babel/core': 7.25.2 '@babel/generator': 7.25.6 @@ -7270,7 +7286,7 @@ snapshots: '@remix-run/router': 1.19.1 '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) '@types/mdx': 2.0.13 - '@vanilla-extract/integration': 6.5.0(@types/node@22.5.1) + '@vanilla-extract/integration': 6.5.0(@types/node@22.5.3) arg: 5.0.2 cacache: 17.1.4 chalk: 4.1.2 @@ -7292,13 +7308,13 @@ snapshots: lodash.debounce: 4.0.8 minimatch: 9.0.5 ora: 5.4.1 - picocolors: 1.0.1 + picocolors: 1.1.0 picomatch: 2.3.1 pidtree: 0.6.0 - postcss: 8.4.41 - postcss-discard-duplicates: 5.1.0(postcss@8.4.41) - postcss-load-config: 4.0.2(postcss@8.4.41) - postcss-modules: 6.0.0(postcss@8.4.41) + postcss: 8.4.45 + postcss-discard-duplicates: 5.1.0(postcss@8.4.45) + postcss-load-config: 4.0.2(postcss@8.4.45) + postcss-modules: 6.0.0(postcss@8.4.45) prettier: 2.8.8 pretty-ms: 7.0.1 react-refresh: 0.14.2 @@ -7312,8 +7328,8 @@ snapshots: optionalDependencies: '@remix-run/serve': 2.11.2(typescript@5.5.3) typescript: 5.5.3 - vite: 5.3.3(@types/node@22.5.1) - wrangler: 3.72.2(@cloudflare/workers-types@4.20240821.1) + vite: 5.3.3(@types/node@22.5.3) + wrangler: 3.72.2(@cloudflare/workers-types@4.20240903.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -7529,6 +7545,7 @@ snapshots: ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color + - webpack-sources '@storybook/addon-essentials@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: @@ -7545,6 +7562,7 @@ snapshots: ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color + - webpack-sources '@storybook/addon-highlight@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: @@ -7617,7 +7635,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': + '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': dependencies: '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/find-cache-dir': 3.2.1 @@ -7629,11 +7647,12 @@ snapshots: magic-string: 0.30.11 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - vite: 5.3.3(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: - supports-color + - webpack-sources '@storybook/codemod@8.2.9': dependencies: @@ -7663,7 +7682,7 @@ snapshots: dependencies: '@storybook/csf': 0.1.11 '@types/express': 4.17.21 - '@types/node': 18.19.47 + '@types/node': 18.19.49 browser-assert: 1.2.1 esbuild: 0.21.5 esbuild-register: 3.6.0(esbuild@0.21.5) @@ -7680,7 +7699,9 @@ snapshots: '@storybook/csf-plugin@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': dependencies: storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - unplugin: 1.12.2 + unplugin: 1.13.1 + transitivePeerDependencies: + - webpack-sources '@storybook/csf@0.0.1': dependencies: @@ -7718,11 +7739,11 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1))': + '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) '@rollup/pluginutils': 5.1.0(rollup@4.21.2) - '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)) + '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) find-up: 5.0.0 magic-string: 0.30.11 @@ -7732,13 +7753,14 @@ snapshots: resolve: 1.22.8 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) tsconfig-paths: 4.2.0 - vite: 5.3.3(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) transitivePeerDependencies: - '@preact/preset-vite' - rollup - supports-color - typescript - vite-plugin-glimmerx + - webpack-sources '@storybook/react@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)': dependencies: @@ -7750,7 +7772,7 @@ snapshots: '@storybook/theming': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 - '@types/node': 18.19.47 + '@types/node': 18.19.49 acorn: 7.4.1 acorn-jsx: 5.3.2(acorn@7.4.1) acorn-walk: 7.2.0 @@ -7847,21 +7869,21 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 18.19.47 + '@types/node': 18.19.49 '@types/connect@3.4.38': dependencies: - '@types/node': 18.19.47 + '@types/node': 18.19.49 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 '@types/cookie@0.6.0': {} '@types/cross-spawn@6.0.6': dependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 '@types/debug@4.1.12': dependencies: @@ -7883,7 +7905,7 @@ snapshots: '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 18.19.47 + '@types/node': 18.19.49 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -7900,7 +7922,7 @@ snapshots: '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.5.1 + '@types/node': 22.5.3 '@types/hast@2.3.10': dependencies: @@ -7932,13 +7954,13 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 - '@types/node@18.19.47': + '@types/node@18.19.49': dependencies: undici-types: 5.26.5 - '@types/node@22.5.1': + '@types/node@22.5.3': dependencies: undici-types: 6.19.8 @@ -7964,14 +7986,18 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 18.19.47 + '@types/node': 18.19.49 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 18.19.47 + '@types/node': 18.19.49 '@types/send': 0.17.4 + '@types/set-cookie-parser@2.4.10': + dependencies: + '@types/node': 22.5.3 + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -8122,7 +8148,7 @@ snapshots: deepmerge: 4.3.1 media-query-parser: 2.0.2 modern-ahocorasick: 1.0.1 - picocolors: 1.0.1 + picocolors: 1.1.0 transitivePeerDependencies: - babel-plugin-macros @@ -8139,25 +8165,25 @@ snapshots: lru-cache: 10.4.3 media-query-parser: 2.0.2 modern-ahocorasick: 1.0.1 - picocolors: 1.0.1 + picocolors: 1.1.0 transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@6.5.0(@types/node@22.5.1)': + '@vanilla-extract/integration@6.5.0(@types/node@22.5.3)': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) '@vanilla-extract/babel-plugin-debug-ids': 1.0.6 '@vanilla-extract/css': 1.15.3 - esbuild: 0.17.6 + esbuild: 0.17.19 eval: 0.1.8 find-up: 5.0.0 javascript-stringify: 2.1.0 lodash: 4.17.21 mlly: 1.7.1 outdent: 0.8.0 - vite: 5.3.3(@types/node@22.5.1) - vite-node: 1.6.0(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) + vite-node: 1.6.0(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8169,7 +8195,7 @@ snapshots: - supports-color - terser - '@vanilla-extract/integration@7.1.9(@types/node@22.5.1)': + '@vanilla-extract/integration@7.1.9(@types/node@22.5.3)': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) @@ -8181,8 +8207,8 @@ snapshots: find-up: 5.0.0 javascript-stringify: 2.1.0 mlly: 1.7.1 - vite: 5.3.3(@types/node@22.5.1) - vite-node: 1.6.0(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) + vite-node: 1.6.0(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8196,10 +8222,10 @@ snapshots: '@vanilla-extract/private@1.0.6': {} - '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.1)(vite@5.3.3(@types/node@22.5.1))': + '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.3)(vite@5.3.3(@types/node@22.5.3))': dependencies: - '@vanilla-extract/integration': 7.1.9(@types/node@22.5.1) - vite: 5.3.3(@types/node@22.5.1) + '@vanilla-extract/integration': 7.1.9(@types/node@22.5.3) + vite: 5.3.3(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8423,14 +8449,14 @@ snapshots: astring@1.9.0: {} - autoprefixer@10.4.19(postcss@8.4.41): + autoprefixer@10.4.19(postcss@8.4.45): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001655 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.1 - postcss: 8.4.41 + picocolors: 1.1.0 + postcss: 8.4.45 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -8760,9 +8786,9 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@22.5.1)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): + cosmiconfig-typescript-loader@5.0.0(@types/node@22.5.3)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.6 typescript: 5.5.3 @@ -9217,7 +9243,7 @@ snapshots: debug: 4.3.6 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.8.0 @@ -9229,7 +9255,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.9.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -9250,7 +9276,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.9.0(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.16.0(eslint@8.57.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -9449,7 +9475,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 require-like: 0.1.2 event-target-shim@5.0.1: {} @@ -9610,7 +9636,7 @@ snapshots: flatted@3.3.1: {} - flow-parser@0.245.0: {} + flow-parser@0.245.1: {} for-each@0.3.3: dependencies: @@ -9892,9 +9918,9 @@ snapshots: dependencies: safer-buffer: 2.1.2 - icss-utils@5.1.0(postcss@8.4.41): + icss-utils@5.1.0(postcss@8.4.45): dependencies: - postcss: 8.4.41 + postcss: 8.4.45 ieee754@1.2.1: {} @@ -10136,7 +10162,7 @@ snapshots: '@babel/register': 7.24.6(@babel/core@7.25.2) babel-core: 7.0.0-bridge.0(@babel/core@7.25.2) chalk: 4.1.2 - flow-parser: 0.245.0 + flow-parser: 0.245.1 graceful-fs: 4.2.11 micromatch: 4.0.8 neo-async: 2.6.2 @@ -11076,7 +11102,7 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 - picocolors@1.0.1: {} + picocolors@1.1.0: {} picomatch@2.3.1: {} @@ -11106,48 +11132,48 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-discard-duplicates@5.1.0(postcss@8.4.41): + postcss-discard-duplicates@5.1.0(postcss@8.4.45): dependencies: - postcss: 8.4.41 + postcss: 8.4.45 - postcss-load-config@4.0.2(postcss@8.4.41): + postcss-load-config@4.0.2(postcss@8.4.45): dependencies: lilconfig: 3.1.2 - yaml: 2.5.0 + yaml: 2.5.1 optionalDependencies: - postcss: 8.4.41 + postcss: 8.4.45 - postcss-modules-extract-imports@3.1.0(postcss@8.4.41): + postcss-modules-extract-imports@3.1.0(postcss@8.4.45): dependencies: - postcss: 8.4.41 + postcss: 8.4.45 - postcss-modules-local-by-default@4.0.5(postcss@8.4.41): + postcss-modules-local-by-default@4.0.5(postcss@8.4.45): dependencies: - icss-utils: 5.1.0(postcss@8.4.41) - postcss: 8.4.41 + icss-utils: 5.1.0(postcss@8.4.45) + postcss: 8.4.45 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.0(postcss@8.4.41): + postcss-modules-scope@3.2.0(postcss@8.4.45): dependencies: - postcss: 8.4.41 + postcss: 8.4.45 postcss-selector-parser: 6.1.2 - postcss-modules-values@4.0.0(postcss@8.4.41): + postcss-modules-values@4.0.0(postcss@8.4.45): dependencies: - icss-utils: 5.1.0(postcss@8.4.41) - postcss: 8.4.41 + icss-utils: 5.1.0(postcss@8.4.45) + postcss: 8.4.45 - postcss-modules@6.0.0(postcss@8.4.41): + postcss-modules@6.0.0(postcss@8.4.45): dependencies: generic-names: 4.0.0 - icss-utils: 5.1.0(postcss@8.4.41) + icss-utils: 5.1.0(postcss@8.4.45) lodash.camelcase: 4.3.0 - postcss: 8.4.41 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.41) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.41) - postcss-modules-scope: 3.2.0(postcss@8.4.41) - postcss-modules-values: 4.0.0(postcss@8.4.41) + postcss: 8.4.45 + postcss-modules-extract-imports: 3.1.0(postcss@8.4.45) + postcss-modules-local-by-default: 4.0.5(postcss@8.4.45) + postcss-modules-scope: 3.2.0(postcss@8.4.45) + postcss-modules-values: 4.0.0(postcss@8.4.45) string-hash: 1.1.3 postcss-selector-parser@6.1.2: @@ -11157,10 +11183,10 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.41: + postcss@8.4.45: dependencies: nanoid: 3.3.7 - picocolors: 1.0.1 + picocolors: 1.1.0 source-map-js: 1.2.0 prelude-ls@1.2.1: {} @@ -11944,7 +11970,7 @@ snapshots: ts-dedent@2.2.0: {} - tsconfck@3.1.1(typescript@5.5.3): + tsconfck@3.1.3(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 @@ -12139,18 +12165,16 @@ snapshots: unpipe@1.0.0: {} - unplugin@1.12.2: + unplugin@1.13.1: dependencies: acorn: 8.12.1 - chokidar: 3.6.0 - webpack-sources: 3.2.3 webpack-virtual-modules: 0.6.2 update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: browserslist: 4.23.3 escalade: 3.2.0 - picocolors: 1.0.1 + picocolors: 1.1.0 uri-js@4.4.1: dependencies: @@ -12200,13 +12224,13 @@ snapshots: unist-util-stringify-position: 3.0.3 vfile-message: 3.1.4 - vite-node@1.6.0(@types/node@22.5.1): + vite-node@1.6.0(@types/node@22.5.3): dependencies: cac: 6.7.14 debug: 4.3.6 pathe: 1.1.2 - picocolors: 1.0.1 - vite: 5.3.3(@types/node@22.5.1) + picocolors: 1.1.0 + vite: 5.3.3(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - less @@ -12217,24 +12241,24 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.1)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)): dependencies: debug: 4.3.6 globrex: 0.1.2 - tsconfck: 3.1.1(typescript@5.5.3) + tsconfck: 3.1.3(typescript@5.5.3) optionalDependencies: - vite: 5.3.3(@types/node@22.5.1) + vite: 5.3.3(@types/node@22.5.3) transitivePeerDependencies: - supports-color - typescript - vite@5.3.3(@types/node@22.5.1): + vite@5.3.3(@types/node@22.5.3): dependencies: esbuild: 0.21.5 - postcss: 8.4.41 + postcss: 8.4.45 rollup: 4.21.2 optionalDependencies: - '@types/node': 22.5.1 + '@types/node': 22.5.3 fsevents: 2.3.3 walk-up-path@3.0.1: {} @@ -12251,8 +12275,6 @@ snapshots: web-streams-polyfill@3.3.3: {} - webpack-sources@3.2.3: {} - webpack-virtual-modules@0.6.2: {} which-boxed-primitive@1.0.2: @@ -12311,7 +12333,7 @@ snapshots: '@cloudflare/workerd-linux-arm64': 1.20240821.1 '@cloudflare/workerd-windows-64': 1.20240821.1 - wrangler@3.72.2(@cloudflare/workers-types@4.20240821.1): + wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 '@cloudflare/workers-shared': 0.3.0 @@ -12332,7 +12354,7 @@ snapshots: workerd: 1.20240821.1 xxhash-wasm: 1.0.2 optionalDependencies: - '@cloudflare/workers-types': 4.20240821.1 + '@cloudflare/workers-types': 4.20240903.0 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil @@ -12381,7 +12403,7 @@ snapshots: yaml@2.4.5: {} - yaml@2.5.0: {} + yaml@2.5.1: {} yargs-parser@21.1.1: {} diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..3aa2c1c --- /dev/null +++ b/server/README.md @@ -0,0 +1,67 @@ +## About + +`server` 디렉토리는 Cloudflare 런타임 환경에 돌아갈 기능 등 서버와 관련이 있는 코드가 있는 곳이다. + +## ⚠️ Caution: Absolute Path + +`server` 내에서는 절대 경로(absolute path)를 사용하여 import하면 안 된다. + +Vite 플러그인 등 절대 경로가 적용되기 전에 평가되어야 하는 코드가 있기 때문에, 절대 경로를 사용하면 module resolution 오류가 발생한다. + +```typescript +// error +import { clientEnvSchema } from '@server/constants/env'; + +// ok +import { clientEnvSchema } from '../constants/env'; +``` + +그러나 `server` 외부에서는 사용해도 대부분 괜찮다. + +```typescript +// app/hooks/useEnv.tsx + +// ok +import { type ClientEnv, clientEnvSchema } from '@server/constants/env'; +``` + +## `remixCloudflareDevProxyVitePlugin` + +Cloudflare Pages는 일반적인 Node 환경이 아니기에, `wrangler`로 실행해야 실제 배포 환경에 맞게 실행해볼 수 있다. + +그러나 Remix.js는 `wrangler`를 사용하려면 먼저 빌드를 한 뒤 빌드 결과물을 실행해야 하기에, 개발 중 Live Reload가 동작하지 않는다. + +[`@remix-run/dev`의 `cloudflareDevProxyVitePlugin`을 사용하면](https://remix.run/docs/en/main/guides/vite#cloudflare-proxy) `wrangler`를 사용하지 않고도 Vite 개발 환경에서 Cloudflare Pages 환경에 맞게 쓰인 코드를 문제 없이 실행할 수 있지만, 현재 프로젝트 구성상 문제가 있다. + +우리 프로젝트는 `authSessionStorage`라는 cookie session storage를 생성한 뒤, `loader` 또는 `action`의 Response가 반환되기 직전에 `commitSession`을 실행해서 `Set-Cookie` header를 설정하도록 되어 있다. + +```typescript +// functions/[[path]].ts + +const handleRequest = createPagesFunctionHandler({ + build, + getLoadContext: (args) => getLoadContext(authSession, args), +}); + +const response = await handleRequest(context); + +response.headers.append( + 'Set-Cookie', + await authSessionStorage.commitSession(authSession), +); +``` + +그러나 `cloudflareDevProxyVitePlugin`은 `getLoadContext`만 parameter로 받고 있어 `Response`에 접근할 수 없기에, 모든 Remix.js의 endpoint에서 매번 `commitSession`을 수행해야만 한다. + +따라서 기존 플러그인 코드를 직접 수정하여 `commitSession`을 수행하도록 만들었다. + +```typescript +// server/plugins/remixCloudflareDevProxyVitePlugin.ts + +const res = await handler(req, loadContext); + +res.headers.append( + 'Set-Cookie', + await authSessionStorage.commitSession(authSession), +); +``` diff --git a/app/constants/api.ts b/server/constants/api.ts similarity index 100% rename from app/constants/api.ts rename to server/constants/api.ts diff --git a/server/constants/env.ts b/server/constants/env.ts new file mode 100644 index 0000000..225a688 --- /dev/null +++ b/server/constants/env.ts @@ -0,0 +1,20 @@ +import { z } from 'zod'; + +export const clientEnvSchema = z.object({ + KAKAO_CLIENT_ID: z.string(), +}); + +export const serverEnvSchema = z.object({ + AUTH_COOKIE_SESSION_SECRET: z.string(), + API_URL: z.string(), +}); + +export type ClientEnv = Readonly>; + +export type ServerEnv = Readonly>; + +export type CloudflareEnv = { + readonly KV_NAMESPACE: KVNamespace; +}; + +export type ContextEnv = ClientEnv & ServerEnv & CloudflareEnv; diff --git a/app/constants/types/api.ts b/server/constants/types/api.ts similarity index 100% rename from app/constants/types/api.ts rename to server/constants/types/api.ts diff --git a/app/constants/types/auth.ts b/server/constants/types/auth.ts similarity index 100% rename from app/constants/types/auth.ts rename to server/constants/types/auth.ts diff --git a/server/plugins/remixCloudflareDevProxyVitePlugin.ts b/server/plugins/remixCloudflareDevProxyVitePlugin.ts new file mode 100644 index 0000000..80e2ba7 --- /dev/null +++ b/server/plugins/remixCloudflareDevProxyVitePlugin.ts @@ -0,0 +1,193 @@ +/** + * `cloudflareDevProxyVitePlugin` 코드 원문을 가져와 수정 + * https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/cloudflare-proxy-plugin.ts + */ + +import { once } from 'node:events'; +import type { IncomingHttpHeaders, ServerResponse } from 'node:http'; +import { Readable } from 'node:stream'; +import { createRequestHandler, type ServerBuild } from '@remix-run/cloudflare'; +import { createReadableStreamFromReadable } from '@remix-run/node'; +import { splitCookiesString } from 'set-cookie-parser'; +import type * as Vite from 'vite'; +import { type GetPlatformProxyOptions } from 'wrangler'; +import type { ContextEnv } from '../constants/env'; +import { getLoadContext, makeAuthSession } from '../utils/cloudflare'; + +function invariant(value: boolean, message?: string): asserts value; + +function invariant( + value: T | null | undefined, + message?: string, +): asserts value is T; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function invariant(value: any, message?: string) { + if (value === false || value === null || typeof value === 'undefined') { + console.error( + 'The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new', + ); + throw new Error(message); + } +} + +function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers { + const headers = new Headers(); + + for (const [key, values] of Object.entries(nodeHeaders)) { + if (values) { + if (Array.isArray(values)) { + for (const value of values) { + headers.append(key, value); + } + } else { + headers.set(key, values); + } + } + } + + return headers; +} + +// Based on `createRemixRequest` in packages/remix-express/server.ts +export function fromNodeRequest( + nodeReq: Vite.Connect.IncomingMessage, +): Request { + const origin = + nodeReq.headers.origin && 'null' !== nodeReq.headers.origin + ? nodeReq.headers.origin + : `http://${nodeReq.headers.host}`; + // Use `req.originalUrl` so Remix is aware of the full path + invariant( + nodeReq.originalUrl, + 'Expected `nodeReq.originalUrl` to be defined', + ); + const url = new URL(nodeReq.originalUrl, origin); + const init: RequestInit = { + method: nodeReq.method, + headers: fromNodeHeaders(nodeReq.headers), + }; + + if (nodeReq.method !== 'GET' && nodeReq.method !== 'HEAD') { + init.body = createReadableStreamFromReadable(nodeReq); + (init as { duplex: 'half' }).duplex = 'half'; + } + + return new Request(url.href, init); +} + +// Adapted from solid-start's `handleNodeResponse`: +// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185 +export async function toNodeRequest(res: Response, nodeRes: ServerResponse) { + nodeRes.statusCode = res.status; + nodeRes.statusMessage = res.statusText; + + const cookiesStrings = []; + + for (const [name, value] of res.headers) { + if (name === 'set-cookie') { + cookiesStrings.push(...splitCookiesString(value)); + } else nodeRes.setHeader(name, value); + } + + if (cookiesStrings.length) { + nodeRes.setHeader('set-cookie', cookiesStrings); + } + + if (res.body) { + // https://github.com/microsoft/TypeScript/issues/29867 + const responseBody = res.body as unknown as AsyncIterable; + const readable = Readable.from(responseBody); + readable.pipe(nodeRes); + await once(readable, 'end'); + } else { + nodeRes.end(); + } +} + +const serverBuildId = 'virtual:remix/server-build'; + +type CfProperties = Record; + +function importWrangler() { + try { + return import('wrangler'); + } catch (_) { + throw Error('Could not import `wrangler`. Do you have it installed?'); + } +} + +const NAME = 'vite-plugin-remix-cloudflare-proxy'; + +export const remixCloudflareDevProxyVitePlugin = ( + options: GetPlatformProxyOptions = {}, +): Vite.Plugin => ({ + name: NAME, + config: () => ({ + ssr: { + resolve: { + externalConditions: ['workerd', 'worker'], + }, + }, + }), + configResolved: (viteConfig) => { + const pluginIndex = (name: string) => + viteConfig.plugins.findIndex((plugin) => plugin.name === name); + const remixIndex = pluginIndex('remix'); + if (remixIndex >= 0 && remixIndex < pluginIndex(NAME)) { + throw new Error( + `The "${NAME}" plugin should be placed before the Remix plugin in your Vite config file`, + ); + } + }, + configureServer: async (viteDevServer) => { + const { getPlatformProxy } = await importWrangler(); + // Do not include `dispose` in Cloudflare context + const { dispose: _dispose, ...cloudflare } = await getPlatformProxy< + ContextEnv, + Cf + >(options); + const context = { cloudflare }; + return () => { + if (!viteDevServer.config.server.middlewareMode) { + viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => { + try { + const build = (await viteDevServer.ssrLoadModule( + serverBuildId, + )) as ServerBuild; + + const handler = createRequestHandler(build, 'development'); + const req = fromNodeRequest(nodeReq); + + // auth session 생성 + const { authSessionStorage, authSession } = await makeAuthSession( + { + authCookieSessionSecret: + context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: context.cloudflare.env.KV_NAMESPACE, + }, + nodeReq.headers.cookie, + ); + + const loadContext = await getLoadContext(authSession, { + request: req, + context, + }); + + const res = await handler(req, loadContext); + + // 자동 commit + res.headers.append( + 'Set-Cookie', + await authSessionStorage.commitSession(authSession), + ); + + await toNodeRequest(res, nodeRes); + } catch (error) { + next(error); + } + }); + } + }; + }, +}); diff --git a/app/utils/api.server.ts b/server/utils/api.ts similarity index 95% rename from app/utils/api.server.ts rename to server/utils/api.ts index 7fb8963..6a35712 100644 --- a/app/utils/api.server.ts +++ b/server/utils/api.ts @@ -1,7 +1,7 @@ -import { getAuthToken } from './auth.server'; -import { ApiError } from '@/constants/api'; -import type { ApiInfo } from '@/constants/types/api'; -import type { AuthSession } from '@/constants/types/auth'; +import { ApiError } from '../constants/api'; +import type { ApiInfo } from '../constants/types/api'; +import type { AuthSession } from '../constants/types/auth'; +import { getAuthToken } from './auth'; const COMMON_ERROR: { errorByStatus: Record< diff --git a/app/utils/auth.server.ts b/server/utils/auth.ts similarity index 97% rename from app/utils/auth.server.ts rename to server/utils/auth.ts index 2fcef13..fc48462 100644 --- a/app/utils/auth.server.ts +++ b/server/utils/auth.ts @@ -1,4 +1,4 @@ -import type { AuthSession, AuthSessionData } from '@/constants/types/auth'; +import type { AuthSession, AuthSessionData } from '../constants/types/auth'; export const clearAuthToken = async (authSession: AuthSession) => { authSession.unset('accessToken'); diff --git a/server/utils/cloudflare.ts b/server/utils/cloudflare.ts new file mode 100644 index 0000000..17fc747 --- /dev/null +++ b/server/utils/cloudflare.ts @@ -0,0 +1,69 @@ +import { + createCookie, + createWorkersKVSessionStorage, +} from '@remix-run/cloudflare'; +import { type GetLoadContextFunction } from '@remix-run/cloudflare-pages'; +import { type PlatformProxy } from 'wrangler'; +import { + type CloudflareEnv, + type ContextEnv, + type ClientEnv, + type ServerEnv, + clientEnvSchema, + serverEnvSchema, +} from '../constants/env'; +import type { FetchApi } from '../constants/types/api'; +import type { AuthSession, AuthSessionData } from '../constants/types/auth'; +import { fetchApi } from '../utils/api'; + +declare module '@remix-run/cloudflare' { + interface AppLoadContext extends ServerEnv, CloudflareEnv { + readonly clientEnv: ClientEnv; + readonly authSession: AuthSession; + readonly fetchApi: FetchApi; + } +} + +export const getLoadContext: ( + authSession: AuthSession, + args: { + request: Request; + context: { + cloudflare: Omit, 'dispose'>; + }; + }, +) => ReturnType> = async ( + authSession, + { context }, +) => { + const clientEnv = clientEnvSchema.parse(context.cloudflare.env); + serverEnvSchema.parse(context.cloudflare.env); + + return { + ...context.cloudflare.env, + clientEnv, + authSession, + fetchApi: async (apiInfo, variables) => + fetchApi(apiInfo, variables, context.cloudflare.env.API_URL, authSession), + }; +}; + +export const makeAuthSession = async ( + env: { + authCookieSessionSecret: string; + kvNamespace: KVNamespace; + }, + cookieHeader?: string | null, +) => { + const authSessionCookie = createCookie('__auth_session', { + secrets: [env.authCookieSessionSecret], + sameSite: true, + }); + const authSessionStorage = createWorkersKVSessionStorage({ + cookie: authSessionCookie, + kv: env.kvNamespace, + }); + const authSession = await authSessionStorage.getSession(cookieHeader); + + return { authSessionStorage, authSession }; +}; diff --git a/tsconfig.json b/tsconfig.json index fc3bed6..36cfdd6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,7 +25,8 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "@/*": ["./app/*"] + "@/*": ["./app/*"], + "@server/*": ["./server/*"] }, // Vite takes care of building everything, not tsc. diff --git a/vite.config.ts b/vite.config.ts index 7e9818f..2050f25 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,14 +1,12 @@ -import { - vitePlugin as remix, - cloudflareDevProxyVitePlugin as remixCloudflareDevProxy, -} from '@remix-run/dev'; +import { vitePlugin as remix } from '@remix-run/dev'; import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; +import { remixCloudflareDevProxyVitePlugin } from './server/plugins/remixCloudflareDevProxyVitePlugin'; export default defineConfig({ plugins: [ - remixCloudflareDevProxy(), + remixCloudflareDevProxyVitePlugin(), remix({ future: { v3_fetcherPersist: true, From 0030e9031888b3393207a483fd4b2085235246dc Mon Sep 17 00:00:00 2001 From: aube-dev Date: Thu, 5 Sep 2024 02:36:49 +0900 Subject: [PATCH 07/21] feat: add `.infisical.json` --- .infisical.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .infisical.json diff --git a/.infisical.json b/.infisical.json new file mode 100644 index 0000000..fccde44 --- /dev/null +++ b/.infisical.json @@ -0,0 +1,5 @@ +{ + "workspaceId": "6a0e9b92-038c-4045-beeb-7d9914ef86fb", + "defaultEnvironment": "dev", + "gitBranchToEnvironmentMapping": null +} From 53ed9a1a38d49bbe69a97abb02b36377c59dbd9b Mon Sep 17 00:00:00 2001 From: aube-dev Date: Sat, 14 Sep 2024 17:17:34 +0900 Subject: [PATCH 08/21] feat: add api base code (incomplete) --- .eslintrc.cjs | 50 +++++ .storybook/preview.tsx | 2 +- app/apis/auth.ts | 22 ++ .../KakaoLoginButton/KakaoLoginButton.tsx | 10 +- app/contexts/EnvContext.tsx | 2 +- app/hooks/useEnv.tsx | 2 +- app/hooks/useErrorToast.ts | 16 ++ app/hooks/useTypedFetcher.ts | 37 ++++ app/root.css.ts | 60 +++++- app/root.tsx | 47 ++++- app/routes/oauth.kakao.tsx | 20 +- functions/[[path]].ts | 7 +- package.json | 5 +- pnpm-lock.yaml | 71 ++++++- public/loading-lottie.json | 1 + server/README.md | 67 ------ server/constants/api.ts | 124 +++++++++-- server/constants/env.ts | 12 +- server/constants/types/api.ts | 25 --- server/index.ts | 27 +++ .../remixCloudflareDevProxyVitePlugin.ts | 193 ------------------ server/types/api.ts | 76 +++++++ server/{constants => }/types/auth.ts | 2 +- server/types/env.ts | 12 ++ server/utils/api.ts | 169 ++++++++------- server/utils/auth.ts | 61 ++++-- server/utils/cloudflare.ts | 62 ++++-- server/vite/index.ts | 1 + server/vite/invariant.ts | 18 ++ server/vite/nodeAdapter.ts | 83 ++++++++ .../vite/remixCloudflareDevProxyVitePlugin.ts | 95 +++++++++ tsconfig.json | 2 +- vite.config.ts | 2 +- 33 files changed, 931 insertions(+), 452 deletions(-) create mode 100644 app/apis/auth.ts create mode 100644 app/hooks/useErrorToast.ts create mode 100644 app/hooks/useTypedFetcher.ts create mode 100644 public/loading-lottie.json delete mode 100644 server/README.md delete mode 100644 server/constants/types/api.ts create mode 100644 server/index.ts delete mode 100644 server/plugins/remixCloudflareDevProxyVitePlugin.ts create mode 100644 server/types/api.ts rename server/{constants => }/types/auth.ts (85%) create mode 100644 server/types/env.ts create mode 100644 server/vite/index.ts create mode 100644 server/vite/invariant.ts create mode 100644 server/vite/nodeAdapter.ts create mode 100644 server/vite/remixCloudflareDevProxyVitePlugin.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 314b8b4..e268a3c 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -109,6 +109,12 @@ module.exports = { ], format: ['PascalCase'], }, + { + selector: 'typeParameter', + format: ['PascalCase'], + prefix: ['_'], + filter: '^_', + }, { selector: ['enumMember'], format: ['UPPER_CASE'], @@ -117,6 +123,12 @@ module.exports = { selector: ['objectLiteralProperty'], format: null, }, + { + selector: 'variable', + format: ['camelCase'], + prefix: ['api_', 'unstable_'], + filter: '(^api_|^unstable_)', + }, ], }, }, @@ -128,6 +140,24 @@ module.exports = { node: true, }, }, + + { + files: ['./server/**/*.{ts,tsx}'], + rules: { + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + // https://github.com/vitejs/vite/issues/10063 + group: ['@/*', '@server/*', 'app/*', 'server/*'], + message: 'server 디렉토리 안에서는 상대 경로를 사용해 주세요.', + }, + ], + }, + ], + }, + }, ], rules: { @@ -142,5 +172,25 @@ module.exports = { ], 'arrow-body-style': ['warn', 'as-needed'], 'prettier/prettier': 'warn', + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['..*'], + message: '다른 경로에 있는 모듈은 절대 경로로 불러와 주세요.', + }, + { + group: ['app/*', 'server/*'], + message: '`@/`, `@server` 등 올바른 절대 경로를 사용해 주세요.', + }, + { + group: ['@remix-run/react'], + importNames: ['useFetcher'], + message: '`@/hooks/useTypedFetcher`를 사용해 주세요.', + }, + ], + }, + ], }, }; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index b98f735..1939e66 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,6 +1,6 @@ import { createRemixStub } from '@remix-run/testing'; import type { Preview } from '@storybook/react'; -import '../app/root.css'; +import '@/root.css'; const preview: Preview = { parameters: { diff --git a/app/apis/auth.ts b/app/apis/auth.ts new file mode 100644 index 0000000..0606980 --- /dev/null +++ b/app/apis/auth.ts @@ -0,0 +1,22 @@ +import { Api } from '@server'; + +export const api_loginWithKakao = new Api< + { code: string; state: string }, + { + userId: number; + accessToken: string; + accessTokenExpiresAt: string; + refreshToken: string; + refreshTokenExpiresAt: string; + } +>({ + method: 'POST', + endpoint: '/login/oauth2/code/kakao', + needToLogin: false, + request: (variables) => ({ + queryParams: { + code: variables.code, + state: variables.state, + }, + }), +}); diff --git a/app/components/KakaoLoginButton/KakaoLoginButton.tsx b/app/components/KakaoLoginButton/KakaoLoginButton.tsx index 9ca08d5..6191d99 100644 --- a/app/components/KakaoLoginButton/KakaoLoginButton.tsx +++ b/app/components/KakaoLoginButton/KakaoLoginButton.tsx @@ -1,18 +1,18 @@ import React, { useEffect, useState } from 'react'; import useEnv from '@/hooks/useEnv'; -import { getUUID } from '@/utils/random'; const KakaoLoginButton: React.FC = () => { const env = useEnv(); const [kakaoAuthUrl, setKakaoAuthUrl] = useState(''); useEffect(() => { - const userUUID = getUUID(); - const redirectUri = window.location.origin + '/oauth/kakao'; + const redirectUri = + window.location.origin.replace('localhost', '127.0.0.1') + '/oauth/kakao'; setKakaoAuthUrl( - `https://kauth.kakao.com/oauth/authorize?client_id=${env.KAKAO_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&state=${userUUID}`, + `${env.API_URL}/oauth2/authorization/kakao?redirect_to=${redirectUri}`, ); - }, [env.KAKAO_CLIENT_ID]); + // setKakaoAuthUrl('http://146.56.161.252:8080/oauth2/authorization/kakao'); + }, [env.API_URL]); return (
diff --git a/app/contexts/EnvContext.tsx b/app/contexts/EnvContext.tsx index ceb7313..7323636 100644 --- a/app/contexts/EnvContext.tsx +++ b/app/contexts/EnvContext.tsx @@ -1,4 +1,4 @@ import { createContext } from 'react'; -import { type ClientEnv } from '@server/constants/env'; +import { type ClientEnv } from '@server'; export const EnvContext = createContext(null); diff --git a/app/hooks/useEnv.tsx b/app/hooks/useEnv.tsx index c470b07..07b1c39 100644 --- a/app/hooks/useEnv.tsx +++ b/app/hooks/useEnv.tsx @@ -1,6 +1,6 @@ import { useContext } from 'react'; import { EnvContext } from '@/contexts/EnvContext'; -import { type ClientEnv, clientEnvSchema } from '@server/constants/env'; +import { type ClientEnv, clientEnvSchema } from '@server'; /** * 클라이언트용 환경 변수를 얻는 hook diff --git a/app/hooks/useErrorToast.ts b/app/hooks/useErrorToast.ts new file mode 100644 index 0000000..710ad77 --- /dev/null +++ b/app/hooks/useErrorToast.ts @@ -0,0 +1,16 @@ +import { create } from 'zustand'; +import { type FrontendErrorResponse } from '@server'; + +interface ErrorToastStore { + error: FrontendErrorResponse | null; + setError: (newError: FrontendErrorResponse) => void; + clearError: () => void; +} + +const useErrorToast = create()((set) => ({ + error: null, + setError: (newError) => set({ error: newError }), + clearError: () => set({ error: null }), +})); + +export default useErrorToast; diff --git a/app/hooks/useTypedFetcher.ts b/app/hooks/useTypedFetcher.ts new file mode 100644 index 0000000..c5892dc --- /dev/null +++ b/app/hooks/useTypedFetcher.ts @@ -0,0 +1,37 @@ +import { type TypedResponse } from '@remix-run/cloudflare'; +// `useTypedFetcher`를 사용하라는 규칙인데 이 파일이 바로 그 구현체이므로 무시 +// eslint-disable-next-line no-restricted-imports +import { useFetcher } from '@remix-run/react'; +import { useEffect } from 'react'; +import useErrorToast from './useErrorToast'; +import { + type FrontendErrorResponse, + type FrontendSuccessResponse, + type JsonValue, +} from '@server'; + +const useTypedFetcher = < + T extends ( + ...params: unknown[] + ) => Promise< + | TypedResponse> + | TypedResponse> + >, +>( + ...params: Parameters> +) => { + const fetcher = useFetcher(...params); + const { setError } = useErrorToast(); + + useEffect(() => { + if (fetcher.data !== undefined && !fetcher.data.isSuccess) { + setError(fetcher.data); + } + // `fetcher.data` 외 다른 것이 변할 때는 실행되면 안 됨 + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fetcher.data]); + + return fetcher; +}; + +export default useTypedFetcher; diff --git a/app/root.css.ts b/app/root.css.ts index 9f159bb..5433cc0 100644 --- a/app/root.css.ts +++ b/app/root.css.ts @@ -1,4 +1,7 @@ -import { globalFontFace, globalStyle } from '@vanilla-extract/css'; +import { globalFontFace, globalStyle, style } from '@vanilla-extract/css'; +import { textStyle } from './styles/text.css'; +import { themeVars } from './styles/theme.css'; +import { rgba } from './utils/style'; import SUITVariable from '@/assets/SUIT-Variable.woff2'; globalFontFace('SUIT-Variable', { @@ -25,3 +28,58 @@ globalStyle('body', { globalStyle('h1, h2, h3, h4, h5, h6, p', { margin: 0, }); + +export const loadingToast = style({ + position: 'fixed', + bottom: '32px', + left: '50%', + transform: 'translate(-50%, 0)', + backgroundColor: '#121212', + borderRadius: '12px', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + paddingRight: '12px', + gap: '10px', + width: '180px', + height: '50px', +}); + +export const loadingLottie = style({ + width: '43px', + height: '43px', +}); + +export const loadingToastText = style([ + textStyle.subtitle2SB, + { color: themeVars.color.grayscale.white.hex }, +]); + +export const errorToastWrap = style({ + position: 'fixed', + bottom: '32px', + left: '50%', + transform: 'translate(-50%, 0)', + padding: '0 24px', + width: '100%', + maxWidth: '648px', +}); + +export const errorToast = style({ + backgroundColor: rgba(themeVars.color.system.caution.rgb, 0.7), + borderRadius: '12px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + padding: '12px 24px', +}); + +export const errorToastText = style([ + textStyle.subtitle2SB, + { + color: themeVars.color.grayscale.white.hex, + textAlign: 'center', + wordBreak: 'keep-all', + }, +]); diff --git a/app/root.tsx b/app/root.tsx index 2854c90..cf55a44 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,3 +1,4 @@ +import { DotLottieReact } from '@lottiefiles/dotlottie-react'; import { json, type LoaderFunctionArgs } from '@remix-run/cloudflare'; import { Links, @@ -5,11 +6,15 @@ import { Outlet, Scripts, ScrollRestoration, + useFetchers, useLoaderData, + useRouteError, } from '@remix-run/react'; +import { useEffect, useRef } from 'react'; +import useErrorToast from './hooks/useErrorToast'; +import * as styles from './root.css'; import { EnvContext } from '@/contexts/EnvContext'; -import './root.css'; import '@/styles/theme.css'; export const loader = async (args: LoaderFunctionArgs) => @@ -19,6 +24,24 @@ export const loader = async (args: LoaderFunctionArgs) => const App = () => { const data = useLoaderData(); + const fetchers = useFetchers(); + const { error, clearError } = useErrorToast(); + const errorToastRemovalTimeoutIdRef = useRef(null); + + useEffect(() => { + if (error) { + if (errorToastRemovalTimeoutIdRef.current) { + clearTimeout(errorToastRemovalTimeoutIdRef.current); + } + const timeoutId = setTimeout(() => { + clearError(); + }, 5000); + errorToastRemovalTimeoutIdRef.current = timeoutId; + } + + // `error` 외 다른 것이 바뀔 때는 호출되지 않아야 함 + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [error]); return ( @@ -31,6 +54,21 @@ const App = () => { + {fetchers.length > 0 && ( +
+
+ +
+ 서버 통신 중... +
+ )} + {error && ( +
+
+ {error.message} +
+
+ )}
@@ -39,4 +77,11 @@ const App = () => { ); }; +export const ErrorBoundary = () => { + const error = useRouteError(); + console.log('ErrorBoundary', error); + + return

Error

; +}; + export default App; diff --git a/app/routes/oauth.kakao.tsx b/app/routes/oauth.kakao.tsx index c182ef8..d3be852 100644 --- a/app/routes/oauth.kakao.tsx +++ b/app/routes/oauth.kakao.tsx @@ -1,15 +1,23 @@ import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; export const loader = async ({ request }: LoaderFunctionArgs) => { - const url = new URL(request.url); - const code = url.searchParams.get('code'); - const state = url.searchParams.get('state'); - - console.log(code, state); + const cookieHeader = request.headers; + console.log(cookieHeader); return null; }; -const KakaoRedirect = () =>
카카오 로그인 중...
; +const KakaoRedirect = () => { + console.log('kakaoredirect'); + + return ( +
+ {/*

{fetcher.state}

+ + + */} +
+ ); +}; export default KakaoRedirect; diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 2e242ff..8facdd0 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -3,12 +3,13 @@ import { clientEnvSchema, type ContextEnv, serverEnvSchema, -} from '@server/constants/env'; -import { getLoadContext, makeAuthSession } from '@server/utils/cloudflare'; + getLoadContext, + makeAuthSession, +} from '@server'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` -// eslint-disable-next-line import/no-unresolved, import/order +// eslint-disable-next-line import/no-unresolved, import/order, no-restricted-imports import * as build from '../build/server'; export const onRequest = async ( diff --git a/package.json b/package.json index 00a2421..98101fc 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build-storybook": "storybook build" }, "dependencies": { + "@lottiefiles/dotlottie-react": "0.8.12", "@remix-run/cloudflare": "2.11.2", "@remix-run/cloudflare-pages": "2.11.2", "@remix-run/react": "2.11.2", @@ -25,7 +26,8 @@ "react": "18.3.1", "react-dom": "18.3.1", "uuid": "10.0.0", - "zod": "3.23.8" + "zod": "3.23.8", + "zustand": "4.5.5" }, "devDependencies": { "@commitlint/cli": "19.3.0", @@ -40,6 +42,7 @@ "@storybook/react": "8.2.9", "@storybook/react-vite": "8.2.9", "@storybook/test": "8.2.9", + "@types/eslint": "8.56.12", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@types/set-cookie-parser": "2.4.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b85e08a..9ca046e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@lottiefiles/dotlottie-react': + specifier: 0.8.12 + version: 0.8.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@remix-run/cloudflare': specifier: 2.11.2 version: 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) @@ -38,6 +41,9 @@ importers: zod: specifier: 3.23.8 version: 3.23.8 + zustand: + specifier: 4.5.5 + version: 4.5.5(@types/react@18.3.3)(react@18.3.1) devDependencies: '@commitlint/cli': specifier: 19.3.0 @@ -75,6 +81,9 @@ importers: '@storybook/test': specifier: 8.2.9 version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@types/eslint': + specifier: 8.56.12 + version: 8.56.12 '@types/react': specifier: 18.3.3 version: 18.3.3 @@ -113,7 +122,7 @@ importers: version: 6.9.0(eslint@8.57.0) eslint-plugin-prettier: specifier: 5.2.1 - version: 5.2.1(eslint@8.57.0)(prettier@3.3.3) + version: 5.2.1(@types/eslint@8.56.12)(eslint@8.57.0)(prettier@3.3.3) eslint-plugin-react: specifier: 7.34.3 version: 7.34.3(eslint@8.57.0) @@ -1541,6 +1550,15 @@ packages: '@jspm/core@2.0.1': resolution: {integrity: sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==} + '@lottiefiles/dotlottie-react@0.8.12': + resolution: {integrity: sha512-6S9q5mH2l8JDnKAruAq4NP7bzHVzJNUt8UsXONfveSyJPUgT5hGw5b5vCjW19Ra3hgN/d69qUtRLHfmyRAgblQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@lottiefiles/dotlottie-web@0.33.0': + resolution: {integrity: sha512-/KerIs0UkmwuDKYWlNGWYSSZkZaLNXXHqg6qCnP7P2JuzgI4bHRmlIk3+LoJjl/jWqd3WyI4t5oRV6ch0sQwvg==} + '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} @@ -2049,6 +2067,9 @@ packages: '@types/escodegen@0.0.6': resolution: {integrity: sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==} + '@types/eslint@8.56.12': + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -5594,6 +5615,11 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5826,6 +5852,21 @@ packages: zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zustand@4.5.5: + resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} + engines: {node: '>=12.7.0'} + peerDependencies: + '@types/react': '>=16.8' + immer: '>=9.0.6' + react: '>=16.8' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -7176,6 +7217,14 @@ snapshots: '@jspm/core@2.0.1': {} + '@lottiefiles/dotlottie-react@0.8.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@lottiefiles/dotlottie-web': 0.33.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@lottiefiles/dotlottie-web@0.33.0': {} + '@mdx-js/mdx@2.3.0': dependencies: '@types/estree-jsx': 1.0.5 @@ -7895,6 +7944,11 @@ snapshots: '@types/escodegen@0.0.6': {} + '@types/eslint@8.56.12': + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.5 @@ -9313,12 +9367,14 @@ snapshots: safe-regex-test: 1.0.3 string.prototype.includes: 2.0.0 - eslint-plugin-prettier@5.2.1(eslint@8.57.0)(prettier@3.3.3): + eslint-plugin-prettier@5.2.1(@types/eslint@8.56.12)(eslint@8.57.0)(prettier@3.3.3): dependencies: eslint: 8.57.0 prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.9.1 + optionalDependencies: + '@types/eslint': 8.56.12 eslint-plugin-react-hooks@4.6.2(eslint@8.57.0): dependencies: @@ -12180,6 +12236,10 @@ snapshots: dependencies: punycode: 2.3.1 + use-sync-external-store@1.2.2(react@18.3.1): + dependencies: + react: 18.3.1 + util-deprecate@1.0.2: {} util@0.12.5: @@ -12429,4 +12489,11 @@ snapshots: zod@3.23.8: {} + zustand@4.5.5(@types/react@18.3.3)(react@18.3.1): + dependencies: + use-sync-external-store: 1.2.2(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 + react: 18.3.1 + zwitch@2.0.4: {} diff --git a/public/loading-lottie.json b/public/loading-lottie.json new file mode 100644 index 0000000..0578ca1 --- /dev/null +++ b/public/loading-lottie.json @@ -0,0 +1 @@ +{"v":"5.6.10","fr":30,"ip":0,"op":26,"w":600,"h":600,"nm":"圆环-1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"形状图层 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[230,230],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":80,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":25}],"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":150,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"形状图层 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[230,230],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.302314070159,0.302314070159,0.302314070159,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":30,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"黑底","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[300,300,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[400,400],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":40,"ix":4},"nm":"矩形路径 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.074509803922,0.074509803922,0.074509803922,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"矩形 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/server/README.md b/server/README.md deleted file mode 100644 index 3aa2c1c..0000000 --- a/server/README.md +++ /dev/null @@ -1,67 +0,0 @@ -## About - -`server` 디렉토리는 Cloudflare 런타임 환경에 돌아갈 기능 등 서버와 관련이 있는 코드가 있는 곳이다. - -## ⚠️ Caution: Absolute Path - -`server` 내에서는 절대 경로(absolute path)를 사용하여 import하면 안 된다. - -Vite 플러그인 등 절대 경로가 적용되기 전에 평가되어야 하는 코드가 있기 때문에, 절대 경로를 사용하면 module resolution 오류가 발생한다. - -```typescript -// error -import { clientEnvSchema } from '@server/constants/env'; - -// ok -import { clientEnvSchema } from '../constants/env'; -``` - -그러나 `server` 외부에서는 사용해도 대부분 괜찮다. - -```typescript -// app/hooks/useEnv.tsx - -// ok -import { type ClientEnv, clientEnvSchema } from '@server/constants/env'; -``` - -## `remixCloudflareDevProxyVitePlugin` - -Cloudflare Pages는 일반적인 Node 환경이 아니기에, `wrangler`로 실행해야 실제 배포 환경에 맞게 실행해볼 수 있다. - -그러나 Remix.js는 `wrangler`를 사용하려면 먼저 빌드를 한 뒤 빌드 결과물을 실행해야 하기에, 개발 중 Live Reload가 동작하지 않는다. - -[`@remix-run/dev`의 `cloudflareDevProxyVitePlugin`을 사용하면](https://remix.run/docs/en/main/guides/vite#cloudflare-proxy) `wrangler`를 사용하지 않고도 Vite 개발 환경에서 Cloudflare Pages 환경에 맞게 쓰인 코드를 문제 없이 실행할 수 있지만, 현재 프로젝트 구성상 문제가 있다. - -우리 프로젝트는 `authSessionStorage`라는 cookie session storage를 생성한 뒤, `loader` 또는 `action`의 Response가 반환되기 직전에 `commitSession`을 실행해서 `Set-Cookie` header를 설정하도록 되어 있다. - -```typescript -// functions/[[path]].ts - -const handleRequest = createPagesFunctionHandler({ - build, - getLoadContext: (args) => getLoadContext(authSession, args), -}); - -const response = await handleRequest(context); - -response.headers.append( - 'Set-Cookie', - await authSessionStorage.commitSession(authSession), -); -``` - -그러나 `cloudflareDevProxyVitePlugin`은 `getLoadContext`만 parameter로 받고 있어 `Response`에 접근할 수 없기에, 모든 Remix.js의 endpoint에서 매번 `commitSession`을 수행해야만 한다. - -따라서 기존 플러그인 코드를 직접 수정하여 `commitSession`을 수행하도록 만들었다. - -```typescript -// server/plugins/remixCloudflareDevProxyVitePlugin.ts - -const res = await handler(req, loadContext); - -res.headers.append( - 'Set-Cookie', - await authSessionStorage.commitSession(authSession), -); -``` diff --git a/server/constants/api.ts b/server/constants/api.ts index 6c5dff0..77097c9 100644 --- a/server/constants/api.ts +++ b/server/constants/api.ts @@ -1,34 +1,122 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -interface ClientError { - status?: number; - message?: string; - path: string; - /** TODO: 서버 쪽 schema 전달되면 타입 수정 */ - serverError?: any; - request?: any; - clientError?: any; +import type { ApiRequest, BackendError } from '../types/api'; + +export class Api { + public method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + public endpoint: `/${string}`; + public needToLogin: boolean; + public baseUrl?: string; + public errorMessage?: { + messageByStatus?: Record; + }; + public request: (variables: Variables) => ApiRequest; + + constructor(apiInfo: { + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + endpoint: `/${string}`; + needToLogin?: boolean; + baseUrl?: string; + errorMessage?: { + messageByStatus?: Record; + }; + request: (variables: Variables) => ApiRequest; + }) { + this.method = apiInfo.method; + this.endpoint = apiInfo.endpoint; + this.needToLogin = apiInfo.needToLogin ?? false; + this.baseUrl = apiInfo.baseUrl; + this.errorMessage = apiInfo.errorMessage; + this.request = apiInfo.request; + } + + getFetchInfo( + variables: Variables, + accessToken?: string, + ): { + pathname: string; + method: Api['method']; + headers: ApiRequest['headers']; + body?: string | FormData; + request: ApiRequest; + } { + const parsedRequest = this.request(variables); + + const pathString = + parsedRequest.pathParams?.reduce( + (prev, cur) => `${prev}/${cur}`, + '', + ) ?? ''; + + const params = parsedRequest.queryParams ?? {}; + const queryString = Object.keys(params).reduce( + (prev, cur) => + `${prev}${ + params[cur] !== null && params[cur] !== undefined + ? `&${cur}=${params[cur]}` + : '' + }`, + '', + ); + + const pathname = `${this.endpoint}${pathString}${ + queryString ? `?${queryString.slice(1)}` : '' + }`; + + const authorizationHeader = accessToken + ? { + Authorization: `Bearer ${accessToken}`, + } + : undefined; + + return { + pathname, + method: this.method, + headers: { + 'Content-Type': + parsedRequest.body instanceof FormData + ? 'multipart/form-data' + : 'application/json', + ...authorizationHeader, + ...parsedRequest.headers, + }, + body: + // eslint-disable-next-line no-nested-ternary + parsedRequest.body !== undefined + ? parsedRequest.body instanceof FormData + ? parsedRequest.body + : JSON.stringify(parsedRequest.body) + : undefined, + request: parsedRequest, + }; + } } export class ApiError extends Error { public status?: number; - public path: string; + public serverError?: BackendError; - /** TODO: 서버 쪽 schema 전달되면 타입 수정 */ - public serverError?: any; + public api: Api; - public request?: any; + public request: ApiRequest; - public clientError?: any; + public frontendError?: unknown; - constructor(error: ClientError) { + constructor(error: { + status?: number; + message?: string; + backendError?: BackendError; + api: Api; + request: ApiRequest; + frontendError?: any; + }) { super(error.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해주세요.'); this.name = 'ApiError'; - this.status = error.status ?? error.serverError?.status; - this.path = error.path; - this.serverError = error.serverError; + this.status = error.status ?? error.backendError?.status; + this.api = error.api; this.request = error.request; - this.clientError = error.clientError; + this.serverError = error.backendError; + this.frontendError = error.frontendError; } } diff --git a/server/constants/env.ts b/server/constants/env.ts index 225a688..6449f18 100644 --- a/server/constants/env.ts +++ b/server/constants/env.ts @@ -1,20 +1,10 @@ import { z } from 'zod'; export const clientEnvSchema = z.object({ - KAKAO_CLIENT_ID: z.string(), + API_URL: z.string(), }); export const serverEnvSchema = z.object({ AUTH_COOKIE_SESSION_SECRET: z.string(), API_URL: z.string(), }); - -export type ClientEnv = Readonly>; - -export type ServerEnv = Readonly>; - -export type CloudflareEnv = { - readonly KV_NAMESPACE: KVNamespace; -}; - -export type ContextEnv = ClientEnv & ServerEnv & CloudflareEnv; diff --git a/server/constants/types/api.ts b/server/constants/types/api.ts deleted file mode 100644 index e67ae36..0000000 --- a/server/constants/types/api.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -export interface ApiRequest { - pathParams?: (string | number)[]; - headers?: Record; - params?: Record; - body?: any; -} - -export interface ApiInfo { - method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; - endpoint: `/${string}`; - needToLogin: boolean; - baseUrl?: string; - errorMessage?: { - messageByStatus?: Record; - }; - request: (variables: Variables) => ApiRequest; - _resultType?: Result; -} - -export type FetchApi = ( - apiInfo: ApiInfo, - variables: Variables, -) => Promise; diff --git a/server/index.ts b/server/index.ts new file mode 100644 index 0000000..c8e8a80 --- /dev/null +++ b/server/index.ts @@ -0,0 +1,27 @@ +export { Api, ApiError } from './constants/api'; +export { serverEnvSchema, clientEnvSchema } from './constants/env'; + +export type { + JsonValue, + ApiRequest, + FetchApi, + BackendError, + FrontendSuccessResponse, + FrontendErrorResponse, +} from './types/api'; +export type { + AuthSession, + AuthSessionData, + AuthSessionStorage, +} from './types/auth'; +export type { + ServerEnv, + ClientEnv, + CloudflareEnv, + ContextEnv, +} from './types/env'; + +export { makeSuccessResponse, makeErrorResponse } from './utils/api'; +export { getLoadContext, makeAuthSession } from './utils/cloudflare'; + +export { remixCloudflareDevProxyVitePlugin } from './vite'; diff --git a/server/plugins/remixCloudflareDevProxyVitePlugin.ts b/server/plugins/remixCloudflareDevProxyVitePlugin.ts deleted file mode 100644 index 80e2ba7..0000000 --- a/server/plugins/remixCloudflareDevProxyVitePlugin.ts +++ /dev/null @@ -1,193 +0,0 @@ -/** - * `cloudflareDevProxyVitePlugin` 코드 원문을 가져와 수정 - * https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/cloudflare-proxy-plugin.ts - */ - -import { once } from 'node:events'; -import type { IncomingHttpHeaders, ServerResponse } from 'node:http'; -import { Readable } from 'node:stream'; -import { createRequestHandler, type ServerBuild } from '@remix-run/cloudflare'; -import { createReadableStreamFromReadable } from '@remix-run/node'; -import { splitCookiesString } from 'set-cookie-parser'; -import type * as Vite from 'vite'; -import { type GetPlatformProxyOptions } from 'wrangler'; -import type { ContextEnv } from '../constants/env'; -import { getLoadContext, makeAuthSession } from '../utils/cloudflare'; - -function invariant(value: boolean, message?: string): asserts value; - -function invariant( - value: T | null | undefined, - message?: string, -): asserts value is T; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function invariant(value: any, message?: string) { - if (value === false || value === null || typeof value === 'undefined') { - console.error( - 'The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new', - ); - throw new Error(message); - } -} - -function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers { - const headers = new Headers(); - - for (const [key, values] of Object.entries(nodeHeaders)) { - if (values) { - if (Array.isArray(values)) { - for (const value of values) { - headers.append(key, value); - } - } else { - headers.set(key, values); - } - } - } - - return headers; -} - -// Based on `createRemixRequest` in packages/remix-express/server.ts -export function fromNodeRequest( - nodeReq: Vite.Connect.IncomingMessage, -): Request { - const origin = - nodeReq.headers.origin && 'null' !== nodeReq.headers.origin - ? nodeReq.headers.origin - : `http://${nodeReq.headers.host}`; - // Use `req.originalUrl` so Remix is aware of the full path - invariant( - nodeReq.originalUrl, - 'Expected `nodeReq.originalUrl` to be defined', - ); - const url = new URL(nodeReq.originalUrl, origin); - const init: RequestInit = { - method: nodeReq.method, - headers: fromNodeHeaders(nodeReq.headers), - }; - - if (nodeReq.method !== 'GET' && nodeReq.method !== 'HEAD') { - init.body = createReadableStreamFromReadable(nodeReq); - (init as { duplex: 'half' }).duplex = 'half'; - } - - return new Request(url.href, init); -} - -// Adapted from solid-start's `handleNodeResponse`: -// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185 -export async function toNodeRequest(res: Response, nodeRes: ServerResponse) { - nodeRes.statusCode = res.status; - nodeRes.statusMessage = res.statusText; - - const cookiesStrings = []; - - for (const [name, value] of res.headers) { - if (name === 'set-cookie') { - cookiesStrings.push(...splitCookiesString(value)); - } else nodeRes.setHeader(name, value); - } - - if (cookiesStrings.length) { - nodeRes.setHeader('set-cookie', cookiesStrings); - } - - if (res.body) { - // https://github.com/microsoft/TypeScript/issues/29867 - const responseBody = res.body as unknown as AsyncIterable; - const readable = Readable.from(responseBody); - readable.pipe(nodeRes); - await once(readable, 'end'); - } else { - nodeRes.end(); - } -} - -const serverBuildId = 'virtual:remix/server-build'; - -type CfProperties = Record; - -function importWrangler() { - try { - return import('wrangler'); - } catch (_) { - throw Error('Could not import `wrangler`. Do you have it installed?'); - } -} - -const NAME = 'vite-plugin-remix-cloudflare-proxy'; - -export const remixCloudflareDevProxyVitePlugin = ( - options: GetPlatformProxyOptions = {}, -): Vite.Plugin => ({ - name: NAME, - config: () => ({ - ssr: { - resolve: { - externalConditions: ['workerd', 'worker'], - }, - }, - }), - configResolved: (viteConfig) => { - const pluginIndex = (name: string) => - viteConfig.plugins.findIndex((plugin) => plugin.name === name); - const remixIndex = pluginIndex('remix'); - if (remixIndex >= 0 && remixIndex < pluginIndex(NAME)) { - throw new Error( - `The "${NAME}" plugin should be placed before the Remix plugin in your Vite config file`, - ); - } - }, - configureServer: async (viteDevServer) => { - const { getPlatformProxy } = await importWrangler(); - // Do not include `dispose` in Cloudflare context - const { dispose: _dispose, ...cloudflare } = await getPlatformProxy< - ContextEnv, - Cf - >(options); - const context = { cloudflare }; - return () => { - if (!viteDevServer.config.server.middlewareMode) { - viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => { - try { - const build = (await viteDevServer.ssrLoadModule( - serverBuildId, - )) as ServerBuild; - - const handler = createRequestHandler(build, 'development'); - const req = fromNodeRequest(nodeReq); - - // auth session 생성 - const { authSessionStorage, authSession } = await makeAuthSession( - { - authCookieSessionSecret: - context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: context.cloudflare.env.KV_NAMESPACE, - }, - nodeReq.headers.cookie, - ); - - const loadContext = await getLoadContext(authSession, { - request: req, - context, - }); - - const res = await handler(req, loadContext); - - // 자동 commit - res.headers.append( - 'Set-Cookie', - await authSessionStorage.commitSession(authSession), - ); - - await toNodeRequest(res, nodeRes); - } catch (error) { - next(error); - } - }); - } - }; - }, -}); diff --git a/server/types/api.ts b/server/types/api.ts new file mode 100644 index 0000000..1fc671c --- /dev/null +++ b/server/types/api.ts @@ -0,0 +1,76 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import type { Api, ApiError } from '../constants/api'; + +type JsonPrimitive = string | number | boolean | null; +type JsonArray = JsonValue[] | readonly JsonValue[]; +type JsonObject = { + [K in string]: JsonValue; +} & { + [K in string]?: JsonValue; +}; +export type JsonValue = JsonPrimitive | JsonObject | JsonArray; + +export interface ApiRequest { + pathParams?: (string | number)[]; + headers?: Record; + queryParams?: Record; + body?: any; +} + +export interface BackendError { + timestamp: string; + status: number; + error: string; + path: string; +} + +export interface FrontendResponseBase { + status: number; + result: T; +} + +export interface FrontendSuccessResponse + extends FrontendResponseBase { + isSuccess: true; +} + +export interface FrontendErrorResponse + extends FrontendResponseBase { + isSuccess: false; + message: string; +} + +export type ApiSuccessReturnType = { + isSuccess: true; + response: Result; +}; +export type ApiFailureReturnType = { + isSuccess: false; + error: ApiError; +}; + +export type ApiReturnType = + | ApiSuccessReturnType + | ApiFailureReturnType; + +export interface ApiOptions { + throwOnError?: boolean; +} + +export type FetchApi = { + ( + api: Api, + variables: Variables, + options?: ApiOptions & { + throwOnError?: false; + }, + ): Promise>; + ( + api: Api, + variables: Variables, + options?: ApiOptions & { + throwOnError: true; + }, + ): Promise>; +}; diff --git a/server/constants/types/auth.ts b/server/types/auth.ts similarity index 85% rename from server/constants/types/auth.ts rename to server/types/auth.ts index deec05a..a84927f 100644 --- a/server/constants/types/auth.ts +++ b/server/types/auth.ts @@ -1,4 +1,4 @@ -import type { Session, SessionStorage } from '@remix-run/cloudflare'; +import type { SessionStorage, Session } from '@remix-run/cloudflare'; export interface AuthSessionData { accessToken: string; diff --git a/server/types/env.ts b/server/types/env.ts new file mode 100644 index 0000000..8396c58 --- /dev/null +++ b/server/types/env.ts @@ -0,0 +1,12 @@ +import type { z } from 'zod'; +import type { clientEnvSchema, serverEnvSchema } from '../constants/env'; + +export type ClientEnv = Readonly>; + +export type ServerEnv = Readonly>; + +export type CloudflareEnv = { + readonly KV_NAMESPACE: KVNamespace; +}; + +export type ContextEnv = ClientEnv & ServerEnv & CloudflareEnv; diff --git a/server/utils/api.ts b/server/utils/api.ts index 6a35712..4f91ab7 100644 --- a/server/utils/api.ts +++ b/server/utils/api.ts @@ -1,8 +1,49 @@ -import { ApiError } from '../constants/api'; -import type { ApiInfo } from '../constants/types/api'; -import type { AuthSession } from '../constants/types/auth'; +import { json, TypedResponse } from '@remix-run/cloudflare'; +import { Api, ApiError } from '../constants/api'; +import type { + ApiOptions, + ApiReturnType, + BackendError, + FrontendErrorResponse, + FrontendSuccessResponse, + JsonValue, +} from '../types/api'; +import type { AuthSession } from '../types/auth'; import { getAuthToken } from './auth'; +type Optional = Pick, K> & Omit; + +export const makeSuccessResponse = ( + info: Omit, 'status'>, 'isSuccess'>, + init?: ResponseInit, +) => + json>( + { + ...info, + isSuccess: true, + status: info.status ?? 200, + }, + { status: info.status ?? 200, ...init }, + ); + +export const makeErrorResponse = ( + info: Omit< + Optional, 'status' | 'message'>, + 'isSuccess' + >, + init?: ResponseInit, +): TypedResponse> => + json>( + { + ...info, + isSuccess: false, + status: info.status ?? 500, + message: + info.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해 주세요.', + }, + { status: info.status ?? 500, ...init }, + ); + const COMMON_ERROR: { errorByStatus: Record< number, @@ -18,79 +59,35 @@ const COMMON_ERROR: { }, }; -export const api = - () => - ( - apiInfo: Omit, '_resultType'>, - ): ApiInfo => - apiInfo; - -export const fetchApi = async ( - apiInfo: ApiInfo, +export const fetchApiImpl = async ( + api: Api, variables: Variables, apiUrl: string, authSession?: AuthSession, -): Promise => { - const baseUrl = apiInfo.baseUrl ?? apiUrl; - const url = `${baseUrl}${apiInfo.endpoint}`; - const parsedRequest = apiInfo.request(variables); - - const pathString = - parsedRequest.pathParams?.reduce( - (prev, cur) => `${prev}/${cur}`, - '', - ) ?? ''; - - const params = parsedRequest.params ?? {}; - const queryString = Object.keys(params).reduce( - (prev, cur) => - `${prev}${ - params[cur] !== null && params[cur] !== undefined - ? `&${cur}=${params[cur]}` - : '' - }`, - '', - ); - - const fetchUrl = `${url}${pathString}${ - queryString ? `?${queryString.slice(1)}` : '' - }`; - + options?: ApiOptions, +): Promise> => { try { + const baseUrl = api.baseUrl ?? apiUrl; + const token = authSession ? await getAuthToken(authSession, apiUrl) : null; - if (!token?.accessToken && apiInfo.needToLogin) { + const fetchInfo = api.getFetchInfo(variables, token?.accessToken); + + const fetchUrl = `${baseUrl}${fetchInfo.pathname}`; + + if (!token?.accessToken && api.needToLogin) { throw new ApiError({ status: 401, - path: fetchUrl, - request: parsedRequest, + api, + request: fetchInfo.request, ...COMMON_ERROR.errorByStatus[401], }); } - const authorizationHeader = token?.accessToken - ? { - Authorization: `Bearer ${token.accessToken}`, - } - : undefined; - const response = await fetch(fetchUrl, { - method: apiInfo.method, - body: - // eslint-disable-next-line no-nested-ternary - parsedRequest.body !== undefined - ? parsedRequest.body instanceof FormData - ? parsedRequest.body - : JSON.stringify(parsedRequest.body) - : undefined, - headers: { - 'Content-Type': - parsedRequest.body instanceof FormData - ? 'multipart/form-data' - : 'application/json', - ...authorizationHeader, - ...parsedRequest.headers, - }, + method: fetchInfo.method, + body: fetchInfo.body, + headers: fetchInfo.headers, }); // `Result`가 `null`인 경우가 있지만 이는 try-catch에 의한 것으로, 타입 체계상에서는 분기처리할 수 없음 @@ -99,17 +96,18 @@ export const fetchApi = async ( try { result = await response.json(); } catch (error) { - console.log(error, `${apiInfo.method} ${apiInfo.endpoint}`); + console.log(error, `${api.method} ${api.endpoint}`); result = null; } if (response.ok) { - return result; + return { + isSuccess: true, + response: result, + }; } - // TODO: 서버 쪽 schema 전달되면 타입 수정 - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const serverError: any = result; + const backendError: BackendError | null = result; const error: { message?: string; @@ -121,32 +119,45 @@ export const fetchApi = async ( // error message by status - 2nd priority error.message = - apiInfo.errorMessage?.messageByStatus?.[response.status]?.message ?? + api.errorMessage?.messageByStatus?.[response.status]?.message ?? error.message; // error message from server - 1st priority - error.message = serverError?.message ?? error.message; + error.message = backendError?.error ?? error.message; throw new ApiError({ ...error, status: response.status, - path: apiInfo.endpoint, - serverError: result, - request: parsedRequest, + api, + backendError: backendError ?? undefined, + request: fetchInfo.request, }); } catch (error) { // 이미 처리된 에러는 그대로 반환 if (error instanceof ApiError) { console.log(error.serverError); - throw error; + if (options?.throwOnError) { + throw error; + } + return { + isSuccess: false, + error: error, + }; } // TODO: Sentry 등 에러 로깅 솔루션 추가 - console.error(error, apiInfo.request(variables), fetchUrl); - throw new ApiError({ - path: apiInfo.endpoint, - request: parsedRequest, - clientError: error, + console.error(error, api, variables); + const apiError = new ApiError({ + api, + request: api.request(variables), + frontendError: error, }); + if (options?.throwOnError) { + throw apiError; + } + return { + isSuccess: false, + error: apiError, + }; } }; diff --git a/server/utils/auth.ts b/server/utils/auth.ts index fc48462..a11eff1 100644 --- a/server/utils/auth.ts +++ b/server/utils/auth.ts @@ -1,4 +1,5 @@ -import type { AuthSession, AuthSessionData } from '../constants/types/auth'; +import { Api, ApiError } from '../constants/api'; +import type { AuthSession, AuthSessionData } from '../types/auth'; export const clearAuthToken = async (authSession: AuthSession) => { authSession.unset('accessToken'); @@ -18,6 +19,18 @@ export const updateAuthToken = async ( }); }; +const api_getNewAccessToken = new Api< + { refreshToken: string }, + { accessToken: string; accessTokenExpiresAt: string } +>({ + method: 'POST', + endpoint: '/token/access', + needToLogin: false, + request: (variables) => ({ + body: { refreshToken: variables.refreshToken }, + }), +}); + export const getAuthToken = async ( authSession: AuthSession, apiUrl: string, @@ -50,29 +63,35 @@ export const getAuthToken = async ( // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) if (refreshTokenExpiresAt.getTime() + 1000 * 60 < now.getTime()) { try { - const response = await fetch(`${apiUrl}/token/access`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - refreshToken, - }), + const fetchInfo = api_getNewAccessToken.getFetchInfo({ + refreshToken, }); - const result = await response.json<{ - accessToken: string; - accessTokenExpiresAt: string; - }>(); - - await updateAuthToken(authSession, { - accessToken: result.accessToken, - accessTokenExpiresAt: result.accessTokenExpiresAt, + const response = await fetch(`${apiUrl}${fetchInfo.pathname}`, { + method: fetchInfo.method, + headers: fetchInfo.headers, + body: fetchInfo.body, }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const result = await response.json(); - return { - accessToken: result.accessToken, - refreshToken, - }; + if (response.ok) { + await updateAuthToken(authSession, { + accessToken: result.accessToken, + accessTokenExpiresAt: result.accessTokenExpiresAt, + }); + + return { + accessToken: result.accessToken, + refreshToken, + }; + } + + throw new ApiError({ + status: response.status, + backendError: result, + api: api_getNewAccessToken, + request: fetchInfo.request, + }); } catch (error) { console.error(error); } diff --git a/server/utils/cloudflare.ts b/server/utils/cloudflare.ts index 17fc747..19f18a8 100644 --- a/server/utils/cloudflare.ts +++ b/server/utils/cloudflare.ts @@ -4,22 +4,52 @@ import { } from '@remix-run/cloudflare'; import { type GetLoadContextFunction } from '@remix-run/cloudflare-pages'; import { type PlatformProxy } from 'wrangler'; -import { - type CloudflareEnv, - type ContextEnv, - type ClientEnv, - type ServerEnv, - clientEnvSchema, - serverEnvSchema, -} from '../constants/env'; -import type { FetchApi } from '../constants/types/api'; -import type { AuthSession, AuthSessionData } from '../constants/types/auth'; -import { fetchApi } from '../utils/api'; +import { clientEnvSchema, serverEnvSchema } from '../constants/env'; +import type { FetchApi } from '../types/api'; +import type { AuthSession, AuthSessionData } from '../types/auth'; +import type { + ClientEnv, + CloudflareEnv, + ContextEnv, + ServerEnv, +} from '../types/env'; +import { fetchApiImpl } from '../utils/api'; declare module '@remix-run/cloudflare' { interface AppLoadContext extends ServerEnv, CloudflareEnv { readonly clientEnv: ClientEnv; readonly authSession: AuthSession; + /** + * `ApiInfo` 객체로 백엔드 API를 호출하는 함수 + * @example + * ``` + * import { type ActionFunctionArgs } from '@remix-run/cloudflare'; + * import { api_getPost } from '@/apis/post'; + * + * export const action = async ({ context }: ActionFunctionArgs) => { + * const apiReturn = await context.fetchApi(api_getPost, { id: 4 }); + * if (!apiReturn.isSuccess) { + * return apiReturn.errorResponse; + * } + * const { response } = apiReturn; + * // ... + * }; + * ``` + * - `loader`와 같이 오류 발생 시 `ErrorBoundary`로 이동해야 하는 경우 `throwOnError` 옵션 사용 + * ``` + * import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; + * import { api_getPost } from '@/apis/post'; + * + * export const loader = async ({ context }: LoaderFunctionArgs) => { + * const { response } = await context.fetchApi( + * api_getPost, + * { id: 4 }, + * { throwOnError: true }, + * ); + * // ... + * }; + * ``` + */ readonly fetchApi: FetchApi; } } @@ -43,8 +73,14 @@ export const getLoadContext: ( ...context.cloudflare.env, clientEnv, authSession, - fetchApi: async (apiInfo, variables) => - fetchApi(apiInfo, variables, context.cloudflare.env.API_URL, authSession), + fetchApi: (async (api, variables, options) => + fetchApiImpl( + api, + variables, + context.cloudflare.env.API_URL, + authSession, + options, + )) as FetchApi, }; }; diff --git a/server/vite/index.ts b/server/vite/index.ts new file mode 100644 index 0000000..dd1d178 --- /dev/null +++ b/server/vite/index.ts @@ -0,0 +1 @@ +export { default as remixCloudflareDevProxyVitePlugin } from './remixCloudflareDevProxyVitePlugin'; diff --git a/server/vite/invariant.ts b/server/vite/invariant.ts new file mode 100644 index 0000000..955c063 --- /dev/null +++ b/server/vite/invariant.ts @@ -0,0 +1,18 @@ +// https://github.com/remix-run/remix/blob/main/packages/remix-dev/invariant.ts + +export default function invariant( + value: boolean, + message?: string, +): asserts value; + +export default function invariant( + value: T | null | undefined, + message?: string, +): asserts value is T; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function invariant(value: any, message?: string) { + if (value === false || value === null || typeof value === 'undefined') { + throw new Error(message); + } +} diff --git a/server/vite/nodeAdapter.ts b/server/vite/nodeAdapter.ts new file mode 100644 index 0000000..fe438b0 --- /dev/null +++ b/server/vite/nodeAdapter.ts @@ -0,0 +1,83 @@ +// https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/node-adapter.ts + +import { once } from 'node:events'; +import type { IncomingHttpHeaders, ServerResponse } from 'node:http'; +import { Readable } from 'node:stream'; +import { createReadableStreamFromReadable } from '@remix-run/node'; +import { splitCookiesString } from 'set-cookie-parser'; +import type * as Vite from 'vite'; +import invariant from './invariant'; + +function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers { + const headers = new Headers(); + + for (const [key, values] of Object.entries(nodeHeaders)) { + if (values) { + if (Array.isArray(values)) { + for (const value of values) { + headers.append(key, value); + } + } else { + headers.set(key, values); + } + } + } + + return headers; +} + +// Based on `createRemixRequest` in packages/remix-express/server.ts +export function fromNodeRequest( + nodeReq: Vite.Connect.IncomingMessage, +): Request { + const origin = + nodeReq.headers.origin && 'null' !== nodeReq.headers.origin + ? nodeReq.headers.origin + : `http://${nodeReq.headers.host}`; + // Use `req.originalUrl` so Remix is aware of the full path + invariant( + nodeReq.originalUrl, + 'Expected `nodeReq.originalUrl` to be defined', + ); + const url = new URL(nodeReq.originalUrl, origin); + const init: RequestInit = { + method: nodeReq.method, + headers: fromNodeHeaders(nodeReq.headers), + }; + + if (nodeReq.method !== 'GET' && nodeReq.method !== 'HEAD') { + init.body = createReadableStreamFromReadable(nodeReq); + (init as { duplex: 'half' }).duplex = 'half'; + } + + return new Request(url.href, init); +} + +// Adapted from solid-start's `handleNodeResponse`: +// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185 +export async function toNodeRequest(res: Response, nodeRes: ServerResponse) { + nodeRes.statusCode = res.status; + nodeRes.statusMessage = res.statusText; + + const cookiesStrings = []; + + for (const [name, value] of res.headers) { + if (name === 'set-cookie') { + cookiesStrings.push(...splitCookiesString(value)); + } else nodeRes.setHeader(name, value); + } + + if (cookiesStrings.length) { + nodeRes.setHeader('set-cookie', cookiesStrings); + } + + if (res.body) { + // https://github.com/microsoft/TypeScript/issues/29867 + const responseBody = res.body as unknown as AsyncIterable; + const readable = Readable.from(responseBody); + readable.pipe(nodeRes); + await once(readable, 'end'); + } else { + nodeRes.end(); + } +} diff --git a/server/vite/remixCloudflareDevProxyVitePlugin.ts b/server/vite/remixCloudflareDevProxyVitePlugin.ts new file mode 100644 index 0000000..c733870 --- /dev/null +++ b/server/vite/remixCloudflareDevProxyVitePlugin.ts @@ -0,0 +1,95 @@ +// https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/cloudflare-proxy-plugin.ts + +import { createRequestHandler, type ServerBuild } from '@remix-run/cloudflare'; +import type * as Vite from 'vite'; +import { type GetPlatformProxyOptions } from 'wrangler'; +import type { ContextEnv } from '../types/env'; +import { getLoadContext, makeAuthSession } from '../utils/cloudflare'; + +const serverBuildId = 'virtual:remix/server-build'; + +type CfProperties = Record; + +const NAME = 'vite-plugin-remix-cloudflare-proxy'; + +const remixCloudflareDevProxyVitePlugin = ( + options: GetPlatformProxyOptions = {}, +): Vite.Plugin => ({ + name: NAME, + config: () => ({ + ssr: { + resolve: { + externalConditions: ['workerd', 'worker'], + }, + }, + // https://github.com/sveltejs/kit/issues/8140 + optimizeDeps: { exclude: ['fsevents'] }, + }), + configResolved: (viteConfig) => { + const pluginIndex = (name: string) => + viteConfig.plugins.findIndex((plugin) => plugin.name === name); + const remixIndex = pluginIndex('remix'); + if (remixIndex >= 0 && remixIndex < pluginIndex(NAME)) { + throw new Error( + `The "${NAME}" plugin should be placed before the Remix plugin in your Vite config file`, + ); + } + }, + configureServer: async (viteDevServer) => { + const [{ getPlatformProxy }, { fromNodeRequest, toNodeRequest }] = + await Promise.all([ + import('wrangler'), + // Node.js 의존성은 동적으로 import + import('./nodeAdapter'), + ]); + // Do not include `dispose` in Cloudflare context + const { dispose: _dispose, ...cloudflare } = await getPlatformProxy< + ContextEnv, + Cf + >(options); + const context = { cloudflare }; + return () => { + if (!viteDevServer.config.server.middlewareMode) { + viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => { + try { + const build = (await viteDevServer.ssrLoadModule( + serverBuildId, + )) as ServerBuild; + + const handler = createRequestHandler(build, 'development'); + const req = fromNodeRequest(nodeReq); + + // auth session 생성 + const { authSessionStorage, authSession } = await makeAuthSession( + { + authCookieSessionSecret: + context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: context.cloudflare.env.KV_NAMESPACE, + }, + nodeReq.headers.cookie, + ); + + const loadContext = await getLoadContext(authSession, { + request: req, + context, + }); + + const res = await handler(req, loadContext); + + // 자동 commit + res.headers.append( + 'Set-Cookie', + await authSessionStorage.commitSession(authSession), + ); + + await toNodeRequest(res, nodeRes); + } catch (error) { + next(error); + } + }); + } + }; + }, +}); + +export default remixCloudflareDevProxyVitePlugin; diff --git a/tsconfig.json b/tsconfig.json index 36cfdd6..28f5517 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,7 @@ "baseUrl": ".", "paths": { "@/*": ["./app/*"], - "@server/*": ["./server/*"] + "@server": ["./server"] }, // Vite takes care of building everything, not tsc. diff --git a/vite.config.ts b/vite.config.ts index 2050f25..c5c75d1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,7 +2,7 @@ import { vitePlugin as remix } from '@remix-run/dev'; import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; -import { remixCloudflareDevProxyVitePlugin } from './server/plugins/remixCloudflareDevProxyVitePlugin'; +import { remixCloudflareDevProxyVitePlugin } from './server'; export default defineConfig({ plugins: [ From 72395a6a4e58d2df4d8f16a13db8279e3829e127 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Sat, 14 Sep 2024 19:20:56 +0900 Subject: [PATCH 09/21] fix: load dev proxy plugin only on dev --- vite.config.ts | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index c5c75d1..6c41b61 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,19 +2,25 @@ import { vitePlugin as remix } from '@remix-run/dev'; import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; -import { remixCloudflareDevProxyVitePlugin } from './server'; -export default defineConfig({ - plugins: [ - remixCloudflareDevProxyVitePlugin(), - remix({ - future: { - v3_fetcherPersist: true, - v3_relativeSplatPath: true, - v3_throwAbortReason: true, - }, - }), - tsconfigPaths(), - vanillaExtractPlugin(), - ], +export default defineConfig(async ({ command }) => { + const { remixCloudflareDevProxyVitePlugin } = + command === 'serve' + ? await import('./server') + : { remixCloudflareDevProxyVitePlugin: undefined }; + + return { + plugins: [ + remixCloudflareDevProxyVitePlugin?.(), + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + }, + }), + tsconfigPaths(), + vanillaExtractPlugin(), + ].filter((item) => item !== undefined), + }; }); From 364d907219d88b537a110e37161d3b03511c7ad0 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 00:07:12 +0900 Subject: [PATCH 10/21] feat: add custom dev proxy vite plugin & move `fetchApi` into `Api` model --- .eslintrc.cjs | 11 +- app/apis/auth.ts | 2 +- app/hooks/useErrorToast.ts | 6 +- app/hooks/useTypedFetcher.ts | 14 +- app/models/api.ts | 258 ++++++++++++++++++ app/routes/oauth.kakao.tsx | 23 +- {server => app}/types/api.ts | 19 +- app/utils/api.ts | 39 +++ functions/[[path]].ts | 20 +- package.json | 3 +- pnpm-lock.yaml | 34 ++- server/constants/api.ts | 122 --------- server/constants/env.ts | 2 +- server/index.ts | 15 +- server/utils/api.ts | 163 ----------- server/utils/auth.ts | 43 +-- server/utils/cloudflare.ts | 60 +--- server/vite/index.ts | 1 - server/vite/invariant.ts | 18 -- server/vite/nodeAdapter.ts | 83 ------ .../vite/remixCloudflareDevProxyVitePlugin.ts | 95 ------- vite.config.ts | 64 +++-- 22 files changed, 440 insertions(+), 655 deletions(-) create mode 100644 app/models/api.ts rename {server => app}/types/api.ts (73%) create mode 100644 app/utils/api.ts delete mode 100644 server/constants/api.ts delete mode 100644 server/utils/api.ts delete mode 100644 server/vite/index.ts delete mode 100644 server/vite/invariant.ts delete mode 100644 server/vite/nodeAdapter.ts delete mode 100644 server/vite/remixCloudflareDevProxyVitePlugin.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e268a3c..6cf947a 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -142,7 +142,11 @@ module.exports = { }, { - files: ['./server/**/*.{ts,tsx}'], + files: [ + './server/**/*.{ts,tsx}', + './vite.config.ts', + './vite.config.storybook.ts', + ], rules: { 'no-restricted-imports': [ 'error', @@ -150,8 +154,9 @@ module.exports = { patterns: [ { // https://github.com/vitejs/vite/issues/10063 - group: ['@/*', '@server/*', 'app/*', 'server/*'], - message: 'server 디렉토리 안에서는 상대 경로를 사용해 주세요.', + group: ['@/*', '@server', 'app/*', 'server/*'], + message: + 'server 디렉토리, 또는 Vite config 파일에서는 상대 경로를 사용해 주세요.', }, ], }, diff --git a/app/apis/auth.ts b/app/apis/auth.ts index 0606980..61c7990 100644 --- a/app/apis/auth.ts +++ b/app/apis/auth.ts @@ -1,4 +1,4 @@ -import { Api } from '@server'; +import { Api } from '@/models/api'; export const api_loginWithKakao = new Api< { code: string; state: string }, diff --git a/app/hooks/useErrorToast.ts b/app/hooks/useErrorToast.ts index 710ad77..06ee3df 100644 --- a/app/hooks/useErrorToast.ts +++ b/app/hooks/useErrorToast.ts @@ -1,9 +1,9 @@ import { create } from 'zustand'; -import { type FrontendErrorResponse } from '@server'; +import type { JsonValue, FrontendErrorResponse } from '@/types/api'; interface ErrorToastStore { - error: FrontendErrorResponse | null; - setError: (newError: FrontendErrorResponse) => void; + error: FrontendErrorResponse | null; + setError: (newError: FrontendErrorResponse) => void; clearError: () => void; } diff --git a/app/hooks/useTypedFetcher.ts b/app/hooks/useTypedFetcher.ts index c5892dc..416e822 100644 --- a/app/hooks/useTypedFetcher.ts +++ b/app/hooks/useTypedFetcher.ts @@ -8,8 +8,20 @@ import { type FrontendErrorResponse, type FrontendSuccessResponse, type JsonValue, -} from '@server'; +} from '@/types/api'; +/** + * `@remix-run/react`의 `useFetcher` wrapper + * - `FrontendSuccessResponse` 또는 `FrontendErrorResponse` 형태를 반환하는 `action`만 허용 + * - 에러 발생 시 에러 토스트 띄우는 로직 적용 + * @example + * ``` + * const Component = () => { + * const fetcher = useTypedFetcher(); + * // ... + * }; + * ``` + */ const useTypedFetcher = < T extends ( ...params: unknown[] diff --git a/app/models/api.ts b/app/models/api.ts new file mode 100644 index 0000000..081b277 --- /dev/null +++ b/app/models/api.ts @@ -0,0 +1,258 @@ +import { type AppLoadContext } from '@remix-run/cloudflare'; +import type { + ApiOptions, + ApiRequest, + ApiReturnType, + ApiSuccessReturnType, + BackendError, +} from '@/types/api'; +import { getAuthToken } from '@server'; + +const COMMON_ERROR: { + errorByStatus: Record< + number, + { + message: string; + } + >; +} = { + errorByStatus: { + 401: { + message: '로그인이 필요합니다', + }, + }, +}; + +export class Api { + public method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + public endpoint: `/${string}`; + public needToLogin: boolean; + public baseUrl?: string; + public errorMessage?: { + messageByStatus?: Record; + }; + public request: (variables: Variables) => ApiRequest; + + constructor(apiInfo: { + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; + endpoint: `/${string}`; + needToLogin?: boolean; + baseUrl?: string; + errorMessage?: { + messageByStatus?: Record; + }; + request: (variables: Variables) => ApiRequest; + }) { + this.method = apiInfo.method; + this.endpoint = apiInfo.endpoint; + this.needToLogin = apiInfo.needToLogin ?? false; + this.baseUrl = apiInfo.baseUrl; + this.errorMessage = apiInfo.errorMessage; + this.request = apiInfo.request; + } + + getFetchInfo( + variables: Variables, + accessToken?: string, + ): { + pathname: string; + method: Api['method']; + headers: ApiRequest['headers']; + body?: string | FormData; + request: ApiRequest; + } { + const parsedRequest = this.request(variables); + + const pathString = + parsedRequest.pathParams?.reduce( + (prev, cur) => `${prev}/${cur}`, + '', + ) ?? ''; + + const params = parsedRequest.queryParams ?? {}; + const queryString = Object.keys(params).reduce( + (prev, cur) => + `${prev}${ + params[cur] !== null && params[cur] !== undefined + ? `&${cur}=${params[cur]}` + : '' + }`, + '', + ); + + const pathname = `${this.endpoint}${pathString}${ + queryString ? `?${queryString.slice(1)}` : '' + }`; + + const authorizationHeader = accessToken + ? { + Authorization: `Bearer ${accessToken}`, + } + : undefined; + + return { + pathname, + method: this.method, + headers: { + 'Content-Type': + parsedRequest.body instanceof FormData + ? 'multipart/form-data' + : 'application/json', + ...authorizationHeader, + ...parsedRequest.headers, + }, + body: + // eslint-disable-next-line no-nested-ternary + parsedRequest.body !== undefined + ? parsedRequest.body instanceof FormData + ? parsedRequest.body + : JSON.stringify(parsedRequest.body) + : undefined, + request: parsedRequest, + }; + } + + async fetch( + variables: Variables, + context: AppLoadContext, + options?: ApiOptions & { throwOnError?: false }, + ): Promise>; + async fetch( + variables: Variables, + context: AppLoadContext, + options?: ApiOptions & { throwOnError: true }, + ): Promise>; + async fetch( + variables: Variables, + context: AppLoadContext, + options?: ApiOptions, + ): Promise> { + try { + const baseUrl = this.baseUrl ?? context.API_URL; + + const token = context.authSession + ? await getAuthToken(context.authSession, context.API_URL) + : null; + + const fetchInfo = this.getFetchInfo(variables, token?.accessToken); + + const fetchUrl = `${baseUrl}${fetchInfo.pathname}`; + + if (!token?.accessToken && this.needToLogin) { + throw new ApiError({ + status: 401, + api: this, + request: fetchInfo.request, + ...COMMON_ERROR.errorByStatus[401], + }); + } + + const response = await fetch(fetchUrl, { + method: fetchInfo.method, + body: fetchInfo.body, + headers: fetchInfo.headers, + }); + + // `Result`가 `null`인 경우가 있지만 이는 try-catch에 의한 것으로, 타입 체계상에서는 분기처리할 수 없음 + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let result: any; + try { + result = await response.json(); + } catch (error) { + console.log(error, `${this.method} ${this.endpoint}`); + result = null; + } + + if (response.ok) { + return { + isSuccess: true, + response: result, + }; + } + + const backendError: BackendError | null = result; + + const error: { + message?: string; + } = {}; + + // common error message (by status) - 3rd priority + error.message = + COMMON_ERROR.errorByStatus[response.status]?.message ?? error.message; + + // error message by status - 2nd priority + error.message = + this.errorMessage?.messageByStatus?.[response.status]?.message ?? + error.message; + + // error message from server - 1st priority + error.message = backendError?.error ?? error.message; + + throw new ApiError({ + ...error, + status: response.status, + api: this, + backendError: backendError ?? undefined, + request: fetchInfo.request, + }); + } catch (error) { + // 이미 처리된 에러는 그대로 반환 + if (error instanceof ApiError) { + console.log(error.serverError); + if (options?.throwOnError) { + throw error; + } + return { + isSuccess: false, + error: error, + }; + } + + // TODO: Sentry 등 에러 로깅 솔루션 추가 + console.error(error, this, variables); + const apiError = new ApiError({ + api: this, + request: this.request(variables), + frontendError: error, + }); + if (options?.throwOnError) { + throw apiError; + } + return { + isSuccess: false, + error: apiError, + }; + } + } +} + +export class ApiError extends Error { + public status?: number; + + public serverError?: BackendError; + + public api: Api; + + public request: ApiRequest; + + public frontendError?: unknown; + + constructor(error: { + status?: number; + message?: string; + backendError?: BackendError; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + api: Api; + request: ApiRequest; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + frontendError?: any; + }) { + super(error.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해주세요.'); + this.name = 'ApiError'; + this.status = error.status ?? error.backendError?.status; + this.api = error.api; + this.request = error.request; + this.serverError = error.backendError; + this.frontendError = error.frontendError; + } +} diff --git a/app/routes/oauth.kakao.tsx b/app/routes/oauth.kakao.tsx index d3be852..f3f4e13 100644 --- a/app/routes/oauth.kakao.tsx +++ b/app/routes/oauth.kakao.tsx @@ -1,23 +1,12 @@ -import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; +export const loader = async () => null; -export const loader = async ({ request }: LoaderFunctionArgs) => { - const cookieHeader = request.headers; - console.log(cookieHeader); - - return null; -}; - -const KakaoRedirect = () => { - console.log('kakaoredirect'); - - return ( -
- {/*

{fetcher.state}

+const KakaoRedirect = () => ( +
+ {/*

{fetcher.state}

*/} -
- ); -}; +
+); export default KakaoRedirect; diff --git a/server/types/api.ts b/app/types/api.ts similarity index 73% rename from server/types/api.ts rename to app/types/api.ts index 1fc671c..6a9ce6d 100644 --- a/server/types/api.ts +++ b/app/types/api.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { Api, ApiError } from '../constants/api'; +import type { ApiError } from '@/models/api'; type JsonPrimitive = string | number | boolean | null; type JsonArray = JsonValue[] | readonly JsonValue[]; @@ -57,20 +57,3 @@ export type ApiReturnType = export interface ApiOptions { throwOnError?: boolean; } - -export type FetchApi = { - ( - api: Api, - variables: Variables, - options?: ApiOptions & { - throwOnError?: false; - }, - ): Promise>; - ( - api: Api, - variables: Variables, - options?: ApiOptions & { - throwOnError: true; - }, - ): Promise>; -}; diff --git a/app/utils/api.ts b/app/utils/api.ts new file mode 100644 index 0000000..95f2cee --- /dev/null +++ b/app/utils/api.ts @@ -0,0 +1,39 @@ +import { json, type TypedResponse } from '@remix-run/cloudflare'; +import type { + FrontendErrorResponse, + FrontendSuccessResponse, + JsonValue, +} from '@/types/api'; + +type Optional = Pick, K> & Omit; + +export const makeSuccessResponse = ( + info: Omit, 'status'>, 'isSuccess'>, + init?: ResponseInit, +) => + json>( + { + ...info, + isSuccess: true, + status: info.status ?? 200, + }, + { status: info.status ?? 200, ...init }, + ); + +export const makeErrorResponse = ( + info: Omit< + Optional, 'status' | 'message'>, + 'isSuccess' + >, + init?: ResponseInit, +): TypedResponse> => + json>( + { + ...info, + isSuccess: false, + status: info.status ?? 500, + message: + info.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해 주세요.', + }, + { status: info.status ?? 500, ...init }, + ); diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 8facdd0..56b1a81 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -4,7 +4,7 @@ import { type ContextEnv, serverEnvSchema, getLoadContext, - makeAuthSession, + makeAuthSessionStorage, } from '@server'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -19,17 +19,23 @@ export const onRequest = async ( clientEnvSchema.parse(context.env); serverEnvSchema.parse(context.env); - const { authSessionStorage, authSession } = await makeAuthSession( - { - authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: context.env.KV_NAMESPACE, - }, + const authSessionStorage = await makeAuthSessionStorage({ + authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: context.env.KV_NAMESPACE, + }); + + const authSession = await authSessionStorage.getSession( context.request.headers.get('Cookie'), ); const handleRequest = createPagesFunctionHandler({ build, - getLoadContext: (args) => getLoadContext(authSession, args), + getLoadContext: (args) => + getLoadContext( + authSession, + () => authSessionStorage.commitSession(authSession), + args, + ), }); const response = await handleRequest(context); diff --git a/package.json b/package.json index 98101fc..fca0ef0 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "devDependencies": { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", + "@majority-elite/remix-dev-utils": "0.1.2", "@remix-run/dev": "2.11.2", - "@remix-run/node": "2.11.2", "@remix-run/testing": "2.11.2", "@storybook/addon-essentials": "8.2.9", "@storybook/addon-interactions": "8.2.9", @@ -62,7 +62,6 @@ "husky": "9.1.1", "lint-staged": "15.2.7", "prettier": "3.3.3", - "set-cookie-parser": "2.7.0", "storybook": "8.2.9", "typescript": "5.5.3", "vite": "5.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9ca046e..d4d8007 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,12 +51,12 @@ importers: '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 + '@majority-elite/remix-dev-utils': + specifier: 0.1.2 + version: 0.1.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) '@remix-run/dev': specifier: 2.11.2 version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) - '@remix-run/node': - specifier: 2.11.2 - version: 2.11.2(typescript@5.5.3) '@remix-run/testing': specifier: 2.11.2 version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) @@ -141,9 +141,6 @@ importers: prettier: specifier: 3.3.3 version: 3.3.3 - set-cookie-parser: - specifier: 2.7.0 - version: 2.7.0 storybook: specifier: 8.2.9 version: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) @@ -1559,6 +1556,21 @@ packages: '@lottiefiles/dotlottie-web@0.33.0': resolution: {integrity: sha512-/KerIs0UkmwuDKYWlNGWYSSZkZaLNXXHqg6qCnP7P2JuzgI4bHRmlIk3+LoJjl/jWqd3WyI4t5oRV6ch0sQwvg==} + '@majority-elite/remix-dev-utils@0.1.2': + resolution: {integrity: sha512-+nuPSvR4jboUs70YiNMHje2kS+wszQl0lt2bR7lGCDlzFidxuMNuMKAJgBU1lf8Seq7eFUCVpB+YltHPA5ULDQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + typescript: ^5.1.0 + vite: ^5.1.0 + wrangler: ^3.28.2 + peerDependenciesMeta: + typescript: + optional: true + vite: + optional: true + wrangler: + optional: true + '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} @@ -7225,6 +7237,16 @@ snapshots: '@lottiefiles/dotlottie-web@0.33.0': {} + '@majority-elite/remix-dev-utils@0.1.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0))': + dependencies: + '@remix-run/node': 2.11.2(typescript@5.5.3) + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) + set-cookie-parser: 2.7.0 + optionalDependencies: + typescript: 5.5.3 + vite: 5.3.3(@types/node@22.5.3) + wrangler: 3.72.2(@cloudflare/workers-types@4.20240903.0) + '@mdx-js/mdx@2.3.0': dependencies: '@types/estree-jsx': 1.0.5 diff --git a/server/constants/api.ts b/server/constants/api.ts deleted file mode 100644 index 77097c9..0000000 --- a/server/constants/api.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import type { ApiRequest, BackendError } from '../types/api'; - -export class Api { - public method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; - public endpoint: `/${string}`; - public needToLogin: boolean; - public baseUrl?: string; - public errorMessage?: { - messageByStatus?: Record; - }; - public request: (variables: Variables) => ApiRequest; - - constructor(apiInfo: { - method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'; - endpoint: `/${string}`; - needToLogin?: boolean; - baseUrl?: string; - errorMessage?: { - messageByStatus?: Record; - }; - request: (variables: Variables) => ApiRequest; - }) { - this.method = apiInfo.method; - this.endpoint = apiInfo.endpoint; - this.needToLogin = apiInfo.needToLogin ?? false; - this.baseUrl = apiInfo.baseUrl; - this.errorMessage = apiInfo.errorMessage; - this.request = apiInfo.request; - } - - getFetchInfo( - variables: Variables, - accessToken?: string, - ): { - pathname: string; - method: Api['method']; - headers: ApiRequest['headers']; - body?: string | FormData; - request: ApiRequest; - } { - const parsedRequest = this.request(variables); - - const pathString = - parsedRequest.pathParams?.reduce( - (prev, cur) => `${prev}/${cur}`, - '', - ) ?? ''; - - const params = parsedRequest.queryParams ?? {}; - const queryString = Object.keys(params).reduce( - (prev, cur) => - `${prev}${ - params[cur] !== null && params[cur] !== undefined - ? `&${cur}=${params[cur]}` - : '' - }`, - '', - ); - - const pathname = `${this.endpoint}${pathString}${ - queryString ? `?${queryString.slice(1)}` : '' - }`; - - const authorizationHeader = accessToken - ? { - Authorization: `Bearer ${accessToken}`, - } - : undefined; - - return { - pathname, - method: this.method, - headers: { - 'Content-Type': - parsedRequest.body instanceof FormData - ? 'multipart/form-data' - : 'application/json', - ...authorizationHeader, - ...parsedRequest.headers, - }, - body: - // eslint-disable-next-line no-nested-ternary - parsedRequest.body !== undefined - ? parsedRequest.body instanceof FormData - ? parsedRequest.body - : JSON.stringify(parsedRequest.body) - : undefined, - request: parsedRequest, - }; - } -} - -export class ApiError extends Error { - public status?: number; - - public serverError?: BackendError; - - public api: Api; - - public request: ApiRequest; - - public frontendError?: unknown; - - constructor(error: { - status?: number; - message?: string; - backendError?: BackendError; - api: Api; - request: ApiRequest; - frontendError?: any; - }) { - super(error.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해주세요.'); - this.name = 'ApiError'; - this.status = error.status ?? error.backendError?.status; - this.api = error.api; - this.request = error.request; - this.serverError = error.backendError; - this.frontendError = error.frontendError; - } -} diff --git a/server/constants/env.ts b/server/constants/env.ts index 6449f18..10ca9b4 100644 --- a/server/constants/env.ts +++ b/server/constants/env.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; export const clientEnvSchema = z.object({ - API_URL: z.string(), + KAKAO_CLIENT_ID: z.string(), }); export const serverEnvSchema = z.object({ diff --git a/server/index.ts b/server/index.ts index c8e8a80..2f0cbd3 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,14 +1,5 @@ -export { Api, ApiError } from './constants/api'; export { serverEnvSchema, clientEnvSchema } from './constants/env'; -export type { - JsonValue, - ApiRequest, - FetchApi, - BackendError, - FrontendSuccessResponse, - FrontendErrorResponse, -} from './types/api'; export type { AuthSession, AuthSessionData, @@ -21,7 +12,5 @@ export type { ContextEnv, } from './types/env'; -export { makeSuccessResponse, makeErrorResponse } from './utils/api'; -export { getLoadContext, makeAuthSession } from './utils/cloudflare'; - -export { remixCloudflareDevProxyVitePlugin } from './vite'; +export { getAuthToken } from './utils/auth'; +export { getLoadContext, makeAuthSessionStorage } from './utils/cloudflare'; diff --git a/server/utils/api.ts b/server/utils/api.ts deleted file mode 100644 index 4f91ab7..0000000 --- a/server/utils/api.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { json, TypedResponse } from '@remix-run/cloudflare'; -import { Api, ApiError } from '../constants/api'; -import type { - ApiOptions, - ApiReturnType, - BackendError, - FrontendErrorResponse, - FrontendSuccessResponse, - JsonValue, -} from '../types/api'; -import type { AuthSession } from '../types/auth'; -import { getAuthToken } from './auth'; - -type Optional = Pick, K> & Omit; - -export const makeSuccessResponse = ( - info: Omit, 'status'>, 'isSuccess'>, - init?: ResponseInit, -) => - json>( - { - ...info, - isSuccess: true, - status: info.status ?? 200, - }, - { status: info.status ?? 200, ...init }, - ); - -export const makeErrorResponse = ( - info: Omit< - Optional, 'status' | 'message'>, - 'isSuccess' - >, - init?: ResponseInit, -): TypedResponse> => - json>( - { - ...info, - isSuccess: false, - status: info.status ?? 500, - message: - info.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해 주세요.', - }, - { status: info.status ?? 500, ...init }, - ); - -const COMMON_ERROR: { - errorByStatus: Record< - number, - { - message: string; - } - >; -} = { - errorByStatus: { - 401: { - message: '로그인이 필요합니다', - }, - }, -}; - -export const fetchApiImpl = async ( - api: Api, - variables: Variables, - apiUrl: string, - authSession?: AuthSession, - options?: ApiOptions, -): Promise> => { - try { - const baseUrl = api.baseUrl ?? apiUrl; - - const token = authSession ? await getAuthToken(authSession, apiUrl) : null; - - const fetchInfo = api.getFetchInfo(variables, token?.accessToken); - - const fetchUrl = `${baseUrl}${fetchInfo.pathname}`; - - if (!token?.accessToken && api.needToLogin) { - throw new ApiError({ - status: 401, - api, - request: fetchInfo.request, - ...COMMON_ERROR.errorByStatus[401], - }); - } - - const response = await fetch(fetchUrl, { - method: fetchInfo.method, - body: fetchInfo.body, - headers: fetchInfo.headers, - }); - - // `Result`가 `null`인 경우가 있지만 이는 try-catch에 의한 것으로, 타입 체계상에서는 분기처리할 수 없음 - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let result: any; - try { - result = await response.json(); - } catch (error) { - console.log(error, `${api.method} ${api.endpoint}`); - result = null; - } - - if (response.ok) { - return { - isSuccess: true, - response: result, - }; - } - - const backendError: BackendError | null = result; - - const error: { - message?: string; - } = {}; - - // common error message (by status) - 3rd priority - error.message = - COMMON_ERROR.errorByStatus[response.status]?.message ?? error.message; - - // error message by status - 2nd priority - error.message = - api.errorMessage?.messageByStatus?.[response.status]?.message ?? - error.message; - - // error message from server - 1st priority - error.message = backendError?.error ?? error.message; - - throw new ApiError({ - ...error, - status: response.status, - api, - backendError: backendError ?? undefined, - request: fetchInfo.request, - }); - } catch (error) { - // 이미 처리된 에러는 그대로 반환 - if (error instanceof ApiError) { - console.log(error.serverError); - if (options?.throwOnError) { - throw error; - } - return { - isSuccess: false, - error: error, - }; - } - - // TODO: Sentry 등 에러 로깅 솔루션 추가 - console.error(error, api, variables); - const apiError = new ApiError({ - api, - request: api.request(variables), - frontendError: error, - }); - if (options?.throwOnError) { - throw apiError; - } - return { - isSuccess: false, - error: apiError, - }; - } -}; diff --git a/server/utils/auth.ts b/server/utils/auth.ts index a11eff1..e5c3413 100644 --- a/server/utils/auth.ts +++ b/server/utils/auth.ts @@ -1,4 +1,3 @@ -import { Api, ApiError } from '../constants/api'; import type { AuthSession, AuthSessionData } from '../types/auth'; export const clearAuthToken = async (authSession: AuthSession) => { @@ -19,18 +18,6 @@ export const updateAuthToken = async ( }); }; -const api_getNewAccessToken = new Api< - { refreshToken: string }, - { accessToken: string; accessTokenExpiresAt: string } ->({ - method: 'POST', - endpoint: '/token/access', - needToLogin: false, - request: (variables) => ({ - body: { refreshToken: variables.refreshToken }, - }), -}); - export const getAuthToken = async ( authSession: AuthSession, apiUrl: string, @@ -59,20 +46,21 @@ export const getAuthToken = async ( const now = new Date(); // access token 만료 (서버 응답 시간 등을 고려해 1분 여유 포함) - if (accessTokenExpiresAt.getTime() + 1000 * 60 >= now.getTime()) { + if (accessTokenExpiresAt.getTime() + 1000 * 60 <= now.getTime()) { // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) - if (refreshTokenExpiresAt.getTime() + 1000 * 60 < now.getTime()) { + if (refreshTokenExpiresAt.getTime() > now.getTime() + 1000 * 60) { try { - const fetchInfo = api_getNewAccessToken.getFetchInfo({ - refreshToken, - }); - const response = await fetch(`${apiUrl}${fetchInfo.pathname}`, { - method: fetchInfo.method, - headers: fetchInfo.headers, - body: fetchInfo.body, + const response = await fetch(`${apiUrl}/token/access`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ refreshToken }), }); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const result = await response.json(); + const result = await response.json<{ + accessToken: string; + accessTokenExpiresAt: string; + }>(); if (response.ok) { await updateAuthToken(authSession, { @@ -86,12 +74,7 @@ export const getAuthToken = async ( }; } - throw new ApiError({ - status: response.status, - backendError: result, - api: api_getNewAccessToken, - request: fetchInfo.request, - }); + console.error(response.status, result); } catch (error) { console.error(error); } diff --git a/server/utils/cloudflare.ts b/server/utils/cloudflare.ts index 19f18a8..fe7d25c 100644 --- a/server/utils/cloudflare.ts +++ b/server/utils/cloudflare.ts @@ -5,7 +5,6 @@ import { import { type GetLoadContextFunction } from '@remix-run/cloudflare-pages'; import { type PlatformProxy } from 'wrangler'; import { clientEnvSchema, serverEnvSchema } from '../constants/env'; -import type { FetchApi } from '../types/api'; import type { AuthSession, AuthSessionData } from '../types/auth'; import type { ClientEnv, @@ -13,49 +12,18 @@ import type { ContextEnv, ServerEnv, } from '../types/env'; -import { fetchApiImpl } from '../utils/api'; declare module '@remix-run/cloudflare' { interface AppLoadContext extends ServerEnv, CloudflareEnv { readonly clientEnv: ClientEnv; readonly authSession: AuthSession; - /** - * `ApiInfo` 객체로 백엔드 API를 호출하는 함수 - * @example - * ``` - * import { type ActionFunctionArgs } from '@remix-run/cloudflare'; - * import { api_getPost } from '@/apis/post'; - * - * export const action = async ({ context }: ActionFunctionArgs) => { - * const apiReturn = await context.fetchApi(api_getPost, { id: 4 }); - * if (!apiReturn.isSuccess) { - * return apiReturn.errorResponse; - * } - * const { response } = apiReturn; - * // ... - * }; - * ``` - * - `loader`와 같이 오류 발생 시 `ErrorBoundary`로 이동해야 하는 경우 `throwOnError` 옵션 사용 - * ``` - * import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; - * import { api_getPost } from '@/apis/post'; - * - * export const loader = async ({ context }: LoaderFunctionArgs) => { - * const { response } = await context.fetchApi( - * api_getPost, - * { id: 4 }, - * { throwOnError: true }, - * ); - * // ... - * }; - * ``` - */ - readonly fetchApi: FetchApi; + readonly commitSession: () => Promise; } } export const getLoadContext: ( authSession: AuthSession, + commitSession: () => Promise, args: { request: Request; context: { @@ -64,6 +32,7 @@ export const getLoadContext: ( }, ) => ReturnType> = async ( authSession, + commitSession, { context }, ) => { const clientEnv = clientEnvSchema.parse(context.cloudflare.env); @@ -73,24 +42,14 @@ export const getLoadContext: ( ...context.cloudflare.env, clientEnv, authSession, - fetchApi: (async (api, variables, options) => - fetchApiImpl( - api, - variables, - context.cloudflare.env.API_URL, - authSession, - options, - )) as FetchApi, + commitSession, }; }; -export const makeAuthSession = async ( - env: { - authCookieSessionSecret: string; - kvNamespace: KVNamespace; - }, - cookieHeader?: string | null, -) => { +export const makeAuthSessionStorage = async (env: { + authCookieSessionSecret: string; + kvNamespace: KVNamespace; +}) => { const authSessionCookie = createCookie('__auth_session', { secrets: [env.authCookieSessionSecret], sameSite: true, @@ -99,7 +58,6 @@ export const makeAuthSession = async ( cookie: authSessionCookie, kv: env.kvNamespace, }); - const authSession = await authSessionStorage.getSession(cookieHeader); - return { authSessionStorage, authSession }; + return authSessionStorage; }; diff --git a/server/vite/index.ts b/server/vite/index.ts deleted file mode 100644 index dd1d178..0000000 --- a/server/vite/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as remixCloudflareDevProxyVitePlugin } from './remixCloudflareDevProxyVitePlugin'; diff --git a/server/vite/invariant.ts b/server/vite/invariant.ts deleted file mode 100644 index 955c063..0000000 --- a/server/vite/invariant.ts +++ /dev/null @@ -1,18 +0,0 @@ -// https://github.com/remix-run/remix/blob/main/packages/remix-dev/invariant.ts - -export default function invariant( - value: boolean, - message?: string, -): asserts value; - -export default function invariant( - value: T | null | undefined, - message?: string, -): asserts value is T; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default function invariant(value: any, message?: string) { - if (value === false || value === null || typeof value === 'undefined') { - throw new Error(message); - } -} diff --git a/server/vite/nodeAdapter.ts b/server/vite/nodeAdapter.ts deleted file mode 100644 index fe438b0..0000000 --- a/server/vite/nodeAdapter.ts +++ /dev/null @@ -1,83 +0,0 @@ -// https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/node-adapter.ts - -import { once } from 'node:events'; -import type { IncomingHttpHeaders, ServerResponse } from 'node:http'; -import { Readable } from 'node:stream'; -import { createReadableStreamFromReadable } from '@remix-run/node'; -import { splitCookiesString } from 'set-cookie-parser'; -import type * as Vite from 'vite'; -import invariant from './invariant'; - -function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers { - const headers = new Headers(); - - for (const [key, values] of Object.entries(nodeHeaders)) { - if (values) { - if (Array.isArray(values)) { - for (const value of values) { - headers.append(key, value); - } - } else { - headers.set(key, values); - } - } - } - - return headers; -} - -// Based on `createRemixRequest` in packages/remix-express/server.ts -export function fromNodeRequest( - nodeReq: Vite.Connect.IncomingMessage, -): Request { - const origin = - nodeReq.headers.origin && 'null' !== nodeReq.headers.origin - ? nodeReq.headers.origin - : `http://${nodeReq.headers.host}`; - // Use `req.originalUrl` so Remix is aware of the full path - invariant( - nodeReq.originalUrl, - 'Expected `nodeReq.originalUrl` to be defined', - ); - const url = new URL(nodeReq.originalUrl, origin); - const init: RequestInit = { - method: nodeReq.method, - headers: fromNodeHeaders(nodeReq.headers), - }; - - if (nodeReq.method !== 'GET' && nodeReq.method !== 'HEAD') { - init.body = createReadableStreamFromReadable(nodeReq); - (init as { duplex: 'half' }).duplex = 'half'; - } - - return new Request(url.href, init); -} - -// Adapted from solid-start's `handleNodeResponse`: -// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185 -export async function toNodeRequest(res: Response, nodeRes: ServerResponse) { - nodeRes.statusCode = res.status; - nodeRes.statusMessage = res.statusText; - - const cookiesStrings = []; - - for (const [name, value] of res.headers) { - if (name === 'set-cookie') { - cookiesStrings.push(...splitCookiesString(value)); - } else nodeRes.setHeader(name, value); - } - - if (cookiesStrings.length) { - nodeRes.setHeader('set-cookie', cookiesStrings); - } - - if (res.body) { - // https://github.com/microsoft/TypeScript/issues/29867 - const responseBody = res.body as unknown as AsyncIterable; - const readable = Readable.from(responseBody); - readable.pipe(nodeRes); - await once(readable, 'end'); - } else { - nodeRes.end(); - } -} diff --git a/server/vite/remixCloudflareDevProxyVitePlugin.ts b/server/vite/remixCloudflareDevProxyVitePlugin.ts deleted file mode 100644 index c733870..0000000 --- a/server/vite/remixCloudflareDevProxyVitePlugin.ts +++ /dev/null @@ -1,95 +0,0 @@ -// https://github.com/remix-run/remix/blob/main/packages/remix-dev/vite/cloudflare-proxy-plugin.ts - -import { createRequestHandler, type ServerBuild } from '@remix-run/cloudflare'; -import type * as Vite from 'vite'; -import { type GetPlatformProxyOptions } from 'wrangler'; -import type { ContextEnv } from '../types/env'; -import { getLoadContext, makeAuthSession } from '../utils/cloudflare'; - -const serverBuildId = 'virtual:remix/server-build'; - -type CfProperties = Record; - -const NAME = 'vite-plugin-remix-cloudflare-proxy'; - -const remixCloudflareDevProxyVitePlugin = ( - options: GetPlatformProxyOptions = {}, -): Vite.Plugin => ({ - name: NAME, - config: () => ({ - ssr: { - resolve: { - externalConditions: ['workerd', 'worker'], - }, - }, - // https://github.com/sveltejs/kit/issues/8140 - optimizeDeps: { exclude: ['fsevents'] }, - }), - configResolved: (viteConfig) => { - const pluginIndex = (name: string) => - viteConfig.plugins.findIndex((plugin) => plugin.name === name); - const remixIndex = pluginIndex('remix'); - if (remixIndex >= 0 && remixIndex < pluginIndex(NAME)) { - throw new Error( - `The "${NAME}" plugin should be placed before the Remix plugin in your Vite config file`, - ); - } - }, - configureServer: async (viteDevServer) => { - const [{ getPlatformProxy }, { fromNodeRequest, toNodeRequest }] = - await Promise.all([ - import('wrangler'), - // Node.js 의존성은 동적으로 import - import('./nodeAdapter'), - ]); - // Do not include `dispose` in Cloudflare context - const { dispose: _dispose, ...cloudflare } = await getPlatformProxy< - ContextEnv, - Cf - >(options); - const context = { cloudflare }; - return () => { - if (!viteDevServer.config.server.middlewareMode) { - viteDevServer.middlewares.use(async (nodeReq, nodeRes, next) => { - try { - const build = (await viteDevServer.ssrLoadModule( - serverBuildId, - )) as ServerBuild; - - const handler = createRequestHandler(build, 'development'); - const req = fromNodeRequest(nodeReq); - - // auth session 생성 - const { authSessionStorage, authSession } = await makeAuthSession( - { - authCookieSessionSecret: - context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: context.cloudflare.env.KV_NAMESPACE, - }, - nodeReq.headers.cookie, - ); - - const loadContext = await getLoadContext(authSession, { - request: req, - context, - }); - - const res = await handler(req, loadContext); - - // 자동 commit - res.headers.append( - 'Set-Cookie', - await authSessionStorage.commitSession(authSession), - ); - - await toNodeRequest(res, nodeRes); - } catch (error) { - next(error); - } - }); - } - }; - }, -}); - -export default remixCloudflareDevProxyVitePlugin; diff --git a/vite.config.ts b/vite.config.ts index 6c41b61..a35d1df 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,26 +1,50 @@ +import { cloudflareDevProxyVitePlugin as remixCloudflareDevProxyVitePlugin } from '@majority-elite/remix-dev-utils'; import { vitePlugin as remix } from '@remix-run/dev'; import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; +import { + type ContextEnv, + getLoadContext, + makeAuthSessionStorage, +} from './server'; -export default defineConfig(async ({ command }) => { - const { remixCloudflareDevProxyVitePlugin } = - command === 'serve' - ? await import('./server') - : { remixCloudflareDevProxyVitePlugin: undefined }; - - return { - plugins: [ - remixCloudflareDevProxyVitePlugin?.(), - remix({ - future: { - v3_fetcherPersist: true, - v3_relativeSplatPath: true, - v3_throwAbortReason: true, - }, - }), - tsconfigPaths(), - vanillaExtractPlugin(), - ].filter((item) => item !== undefined), - }; +export default defineConfig({ + plugins: [ + remixCloudflareDevProxyVitePlugin({ + getLoadContext: async (args) => { + const authSessionStorage = await makeAuthSessionStorage({ + authCookieSessionSecret: + args.context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: args.context.cloudflare.env.KV_NAMESPACE, + }); + const authSession = await authSessionStorage.getSession( + args.request.headers.get('Cookie'), + ); + const loadContext = await getLoadContext( + authSession, + () => authSessionStorage.commitSession(authSession), + args, + ); + return loadContext; + }, + getResponse: async (req, loadContext, handler) => { + const response = await handler(req, loadContext); + response.headers.append( + 'Set-Cookie', + await loadContext.commitSession(), + ); + return response; + }, + }), + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + }, + }), + tsconfigPaths(), + vanillaExtractPlugin(), + ], }); From 13f8fde7d684484f844b62127a1961b4bb95d5dd Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 03:21:36 +0900 Subject: [PATCH 11/21] feat: modify api types & add comments --- app/models/api.ts | 26 ++++++++++- app/types/api.ts | 32 ++++++++++--- app/types/util.ts | 1 + app/utils/api.ts | 101 ++++++++++++++++++++++++++++++++++------ server/constants/env.ts | 2 +- 5 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 app/types/util.ts diff --git a/app/models/api.ts b/app/models/api.ts index 081b277..03936b6 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -112,6 +112,30 @@ export class Api { }; } + /** + * 백엔드 API를 호출하는 method + * @example + * ``` + * // Case 1: `action`에서의 일반적인 활용 + * export const action = ({ context }: ActionFunctionArgs) => { + * // ... + * const response = api_loginWithKakao.fetch({ code, state }, context); + * if (!response.isSuccess) { + * return makeErrorResponse(response.error); + * } + * const { result } = response; + * // ... + * }; + * + * // Case 2: `loader`는 Error Response를 반환하기보다 에러 자체를 throw해야 하는 경우가 대부분임 + * // 이 경우 `throwOnError` 옵션을 주면 `isSuccess`를 체크하지 않아도 자동으로 `ApiSuccessReturnType`으로 추론 + * export const loader = ({ context }: LoaderFunctionArgs) => { + * // ... + * const { result } = api_loginWithKakao.fetch({ code, state }, context); + * // ... + * }; + * ``` + */ async fetch( variables: Variables, context: AppLoadContext, @@ -166,7 +190,7 @@ export class Api { if (response.ok) { return { isSuccess: true, - response: result, + result, }; } diff --git a/app/types/api.ts b/app/types/api.ts index 6a9ce6d..4e0cae2 100644 --- a/app/types/api.ts +++ b/app/types/api.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - import type { ApiError } from '@/models/api'; type JsonPrimitive = string | number | boolean | null; @@ -15,45 +13,67 @@ export interface ApiRequest { pathParams?: (string | number)[]; headers?: Record; queryParams?: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any body?: any; } -export interface BackendError { +/** + * 백엔드 서버에서 응답하는 에러 형식 + */ +export type BackendError = { timestamp: string; status: number; error: string; path: string; -} +}; -export interface FrontendResponseBase { +interface FrontendResponseBase { status: number; result: T; } +/** + * `action`에서 요청 성공 시 응답하는 형식 + */ export interface FrontendSuccessResponse extends FrontendResponseBase { isSuccess: true; } +/** + * `action`에서 요청 실패 시 응답하는 형식 + */ export interface FrontendErrorResponse extends FrontendResponseBase { isSuccess: false; message: string; } +/** + * `Api.fetch`에서 요청 성공 시 응답하는 형식 + */ export type ApiSuccessReturnType = { isSuccess: true; - response: Result; + result: Result; }; +/** + * `Api.fetch`에서 요청 실패 시 응답하는 형식 + */ export type ApiFailureReturnType = { isSuccess: false; error: ApiError; }; +/** + * `Api.fetch`에서 응답하는 형식 + */ export type ApiReturnType = | ApiSuccessReturnType | ApiFailureReturnType; +/** + * `Api.fetch`에 줄 수 있는 옵션 목록 + */ export interface ApiOptions { throwOnError?: boolean; } diff --git a/app/types/util.ts b/app/types/util.ts new file mode 100644 index 0000000..4a4634c --- /dev/null +++ b/app/types/util.ts @@ -0,0 +1 @@ +export type Optional = Pick, K> & Omit; diff --git a/app/utils/api.ts b/app/utils/api.ts index 95f2cee..79eb74a 100644 --- a/app/utils/api.ts +++ b/app/utils/api.ts @@ -1,12 +1,26 @@ import { json, type TypedResponse } from '@remix-run/cloudflare'; +import { ApiError } from '@/models/api'; import type { + BackendError, FrontendErrorResponse, FrontendSuccessResponse, JsonValue, } from '@/types/api'; +import type { Optional } from '@/types/util'; -type Optional = Pick, K> & Omit; - +/** + * `action` 성공 시 반환할 response 생성 + * @example + * ``` + * // `status`를 넘기지 않으면 status는 200이 됨 + * const successResponse = makeSuccessResponse({ + * result: { + * id: 4, + * nickname: 'test', + * }, + * }); + * ``` + */ export const makeSuccessResponse = ( info: Omit, 'status'>, 'isSuccess'>, init?: ResponseInit, @@ -20,20 +34,79 @@ export const makeSuccessResponse = ( { status: info.status ?? 200, ...init }, ); -export const makeErrorResponse = ( +/** + * `action`에서 에러 발생 시 반환할 response 생성 + * @example + * ``` + * // Case 1: `ApiError`를 이용하는 경우 + * const response = await api_loginWithKakao.fetch(...); + * if (!response.isSuccess) { + * return makeErrorResponse(response.error); + * } + * + * // Case 2: `result`를 포함한 정보들을 직접 명시하는 경우 + * const errorResponse = makeErrorResponse({ + * result: { + * expected: 4, + * received: 5, + * }, + * status: 400, + * }); + * + * // Case 3: `result`를 명시하지 않고, 나머지 정보는 명시하는 경우 + * // 이 경우 `result`는 자동으로 `null`이 됨 + * const errorResponse = makeErrorResponse({ + * status: 404, + * message: '없는 정보입니다.', + * }); + * ``` + */ +export function makeErrorResponse( + info: ApiError, + init?: ResponseInit, +): TypedResponse>; +export function makeErrorResponse( info: Omit< Optional, 'status' | 'message'>, 'isSuccess' >, init?: ResponseInit, -): TypedResponse> => - json>( - { - ...info, - isSuccess: false, - status: info.status ?? 500, - message: - info.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해 주세요.', - }, - { status: info.status ?? 500, ...init }, - ); +): TypedResponse>; +export function makeErrorResponse( + info: Omit< + Optional, 'status' | 'message'>, + 'isSuccess' | 'result' + >, + init?: ResponseInit, +): TypedResponse>; +export function makeErrorResponse( + info: + | Omit< + Optional, 'status' | 'message' | 'result'>, + 'isSuccess' + > + | ApiError, + init?: ResponseInit, +): TypedResponse> { + return info instanceof ApiError + ? json>( + { + isSuccess: false, + status: info.status ?? 500, + message: info.message, + result: info.serverError ?? null, + }, + { status: info.status ?? 500, ...init }, + ) + : json>( + { + ...info, + isSuccess: false, + status: info.status ?? 500, + message: + info.message ?? '문제가 발생했습니다. 잠시 후 다시 시도해 주세요.', + result: info.result ?? null, + }, + { status: info.status ?? 500, ...init }, + ); +} diff --git a/server/constants/env.ts b/server/constants/env.ts index 10ca9b4..6449f18 100644 --- a/server/constants/env.ts +++ b/server/constants/env.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; export const clientEnvSchema = z.object({ - KAKAO_CLIENT_ID: z.string(), + API_URL: z.string(), }); export const serverEnvSchema = z.object({ From 54a5aa8af2d75b5ee25070ca6e1b36afe252670a Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 03:41:32 +0900 Subject: [PATCH 12/21] feat: add `AuthSessionService` --- app/models/api.ts | 9 ++- functions/[[path]].ts | 22 +++---- server/index.ts | 5 +- server/models/auth.ts | 128 +++++++++++++++++++++++++++++++++++++ server/utils/auth.ts | 92 -------------------------- server/utils/cloudflare.ts | 41 ++++++------ vite.config.ts | 22 +++---- 7 files changed, 173 insertions(+), 146 deletions(-) create mode 100644 server/models/auth.ts delete mode 100644 server/utils/auth.ts diff --git a/app/models/api.ts b/app/models/api.ts index 03936b6..c56d7cf 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -6,7 +6,6 @@ import type { ApiSuccessReturnType, BackendError, } from '@/types/api'; -import { getAuthToken } from '@server'; const COMMON_ERROR: { errorByStatus: Record< @@ -131,7 +130,11 @@ export class Api { * // 이 경우 `throwOnError` 옵션을 주면 `isSuccess`를 체크하지 않아도 자동으로 `ApiSuccessReturnType`으로 추론 * export const loader = ({ context }: LoaderFunctionArgs) => { * // ... - * const { result } = api_loginWithKakao.fetch({ code, state }, context); + * const { result } = api_loginWithKakao.fetch( + * { code, state }, + * context, + * { throwOnError: true }, + * ); * // ... * }; * ``` @@ -155,7 +158,7 @@ export class Api { const baseUrl = this.baseUrl ?? context.API_URL; const token = context.authSession - ? await getAuthToken(context.authSession, context.API_URL) + ? await context.authSessionService.getAuthToken(context) : null; const fetchInfo = this.getFetchInfo(variables, token?.accessToken); diff --git a/functions/[[path]].ts b/functions/[[path]].ts index 56b1a81..f76f89f 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -4,7 +4,7 @@ import { type ContextEnv, serverEnvSchema, getLoadContext, - makeAuthSessionStorage, + makeAuthSessionService, } from '@server'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -19,30 +19,24 @@ export const onRequest = async ( clientEnvSchema.parse(context.env); serverEnvSchema.parse(context.env); - const authSessionStorage = await makeAuthSessionStorage({ - authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: context.env.KV_NAMESPACE, - }); - - const authSession = await authSessionStorage.getSession( + const authSessionService = await makeAuthSessionService( + { + authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: context.env.KV_NAMESPACE, + }, context.request.headers.get('Cookie'), ); const handleRequest = createPagesFunctionHandler({ build, - getLoadContext: (args) => - getLoadContext( - authSession, - () => authSessionStorage.commitSession(authSession), - args, - ), + getLoadContext: (args) => getLoadContext(authSessionService, args), }); const response = await handleRequest(context); response.headers.append( 'Set-Cookie', - await authSessionStorage.commitSession(authSession), + await authSessionService.commitSession(), ); return response; diff --git a/server/index.ts b/server/index.ts index 2f0cbd3..40fe4b6 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,5 +1,7 @@ export { serverEnvSchema, clientEnvSchema } from './constants/env'; +export { AuthSessionService } from './models/auth'; + export type { AuthSession, AuthSessionData, @@ -12,5 +14,4 @@ export type { ContextEnv, } from './types/env'; -export { getAuthToken } from './utils/auth'; -export { getLoadContext, makeAuthSessionStorage } from './utils/cloudflare'; +export { getLoadContext, makeAuthSessionService } from './utils/cloudflare'; diff --git a/server/models/auth.ts b/server/models/auth.ts new file mode 100644 index 0000000..d998730 --- /dev/null +++ b/server/models/auth.ts @@ -0,0 +1,128 @@ +import { type AppLoadContext } from '@remix-run/cloudflare'; +import type { + AuthSession, + AuthSessionData, + AuthSessionStorage, +} from '../types/auth'; + +export class AuthSessionService { + private authSessionStorage: AuthSessionStorage; + private authSession: AuthSession; + + constructor( + authSessionStorage: AuthSessionStorage, + authSession: AuthSession, + ) { + this.authSessionStorage = authSessionStorage; + this.authSession = authSession; + } + + async commitSession(): Promise { + return await this.authSessionStorage.commitSession(this.authSession); + } + + async clearAuthToken() { + this.authSession.unset('accessToken'); + this.authSession.unset('accessTokenExpiresAt'); + this.authSession.unset('refreshToken'); + this.authSession.unset('refreshTokenExpiresAt'); + } + + /** + * auth token 값을 업데이트하는 method + * - `newToken`에 명시하지 않은 key는 수정되지 않음 + * @example + * ``` + * // `accessToken`, `accessTokenExpiresAt`은 수정되고, `refreshToken` 등 다른 요소는 변화 없음 + * await authSessionService.updateAuthToken({ + * accessToken, + * accessTokenExpiresAt, + * }); + * ``` + */ + async updateAuthToken(newToken: Partial) { + (Object.keys(newToken) as (keyof typeof newToken)[]).forEach((key) => { + if (newToken[key]) { + this.authSession.set(key, newToken[key]); + } + }); + } + + /** + * access token을 얻는 method + * - access token이 만료된 경우 refresh token으로 자동 업데이트 + */ + async getAuthToken(context: AppLoadContext): Promise<{ + accessToken: string; + refreshToken: string; + } | null> { + const accessToken = this.authSession.get('accessToken'); + const accessTokenExpiresAtString = this.authSession.get( + 'accessTokenExpiresAt', + ); + const refreshToken = this.authSession.get('refreshToken'); + const refreshTokenExpiresAtString = this.authSession.get( + 'refreshTokenExpiresAt', + ); + + if ( + accessToken === undefined || + refreshToken === undefined || + accessTokenExpiresAtString === undefined || + refreshTokenExpiresAtString === undefined + ) { + await this.clearAuthToken(); + return null; + } + + const accessTokenExpiresAt = new Date(accessTokenExpiresAtString); + const refreshTokenExpiresAt = new Date(refreshTokenExpiresAtString); + + const now = new Date(); + + // access token 만료 (서버 응답 시간 등을 고려해 1분 여유 포함) + if (accessTokenExpiresAt.getTime() + 1000 * 60 <= now.getTime()) { + // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) + if (refreshTokenExpiresAt.getTime() > now.getTime() + 1000 * 60) { + try { + const response = await fetch(`${context.API_URL}/token/access`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ refreshToken }), + }); + const result = await response.json<{ + accessToken: string; + accessTokenExpiresAt: string; + }>(); + + if (response.ok) { + await this.updateAuthToken({ + accessToken: result.accessToken, + accessTokenExpiresAt: result.accessTokenExpiresAt, + }); + + return { + accessToken: result.accessToken, + refreshToken, + }; + } + + console.error(response.status, result); + } catch (error) { + console.error(error); + } + } + + // refresh token 만료, 또는 서버 오류 + await this.clearAuthToken(); + return null; + } + + return { + accessToken, + refreshToken, + }; + } +} diff --git a/server/utils/auth.ts b/server/utils/auth.ts deleted file mode 100644 index e5c3413..0000000 --- a/server/utils/auth.ts +++ /dev/null @@ -1,92 +0,0 @@ -import type { AuthSession, AuthSessionData } from '../types/auth'; - -export const clearAuthToken = async (authSession: AuthSession) => { - authSession.unset('accessToken'); - authSession.unset('accessTokenExpiresAt'); - authSession.unset('refreshToken'); - authSession.unset('refreshTokenExpiresAt'); -}; - -export const updateAuthToken = async ( - authSession: AuthSession, - newToken: Partial, -) => { - (Object.keys(newToken) as (keyof typeof newToken)[]).forEach((key) => { - if (newToken[key]) { - authSession.set(key, newToken[key]); - } - }); -}; - -export const getAuthToken = async ( - authSession: AuthSession, - apiUrl: string, -): Promise<{ - accessToken: string; - refreshToken: string; -} | null> => { - const accessToken = authSession.get('accessToken'); - const accessTokenExpiresAtString = authSession.get('accessTokenExpiresAt'); - const refreshToken = authSession.get('refreshToken'); - const refreshTokenExpiresAtString = authSession.get('refreshTokenExpiresAt'); - - if ( - accessToken === undefined || - refreshToken === undefined || - accessTokenExpiresAtString === undefined || - refreshTokenExpiresAtString === undefined - ) { - await clearAuthToken(authSession); - return null; - } - - const accessTokenExpiresAt = new Date(accessTokenExpiresAtString); - const refreshTokenExpiresAt = new Date(refreshTokenExpiresAtString); - - const now = new Date(); - - // access token 만료 (서버 응답 시간 등을 고려해 1분 여유 포함) - if (accessTokenExpiresAt.getTime() + 1000 * 60 <= now.getTime()) { - // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) - if (refreshTokenExpiresAt.getTime() > now.getTime() + 1000 * 60) { - try { - const response = await fetch(`${apiUrl}/token/access`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ refreshToken }), - }); - const result = await response.json<{ - accessToken: string; - accessTokenExpiresAt: string; - }>(); - - if (response.ok) { - await updateAuthToken(authSession, { - accessToken: result.accessToken, - accessTokenExpiresAt: result.accessTokenExpiresAt, - }); - - return { - accessToken: result.accessToken, - refreshToken, - }; - } - - console.error(response.status, result); - } catch (error) { - console.error(error); - } - } - - // refresh token 만료, 또는 서버 오류 - await clearAuthToken(authSession); - return null; - } - - return { - accessToken, - refreshToken, - }; -}; diff --git a/server/utils/cloudflare.ts b/server/utils/cloudflare.ts index fe7d25c..fec2f69 100644 --- a/server/utils/cloudflare.ts +++ b/server/utils/cloudflare.ts @@ -5,7 +5,8 @@ import { import { type GetLoadContextFunction } from '@remix-run/cloudflare-pages'; import { type PlatformProxy } from 'wrangler'; import { clientEnvSchema, serverEnvSchema } from '../constants/env'; -import type { AuthSession, AuthSessionData } from '../types/auth'; +import { AuthSessionService } from '../models/auth'; +import type { AuthSessionData } from '../types/auth'; import type { ClientEnv, CloudflareEnv, @@ -16,40 +17,36 @@ import type { declare module '@remix-run/cloudflare' { interface AppLoadContext extends ServerEnv, CloudflareEnv { readonly clientEnv: ClientEnv; - readonly authSession: AuthSession; - readonly commitSession: () => Promise; + readonly authSessionService: AuthSessionService; } } -export const getLoadContext: ( - authSession: AuthSession, - commitSession: () => Promise, +export const getLoadContext = ( + authSessionService: AuthSessionService, args: { request: Request; context: { cloudflare: Omit, 'dispose'>; }; }, -) => ReturnType> = async ( - authSession, - commitSession, - { context }, -) => { - const clientEnv = clientEnvSchema.parse(context.cloudflare.env); - serverEnvSchema.parse(context.cloudflare.env); +): ReturnType> => { + const clientEnv = clientEnvSchema.parse(args.context.cloudflare.env); + serverEnvSchema.parse(args.context.cloudflare.env); return { - ...context.cloudflare.env, + ...args.context.cloudflare.env, clientEnv, - authSession, - commitSession, + authSessionService, }; }; -export const makeAuthSessionStorage = async (env: { - authCookieSessionSecret: string; - kvNamespace: KVNamespace; -}) => { +export const makeAuthSessionService = async ( + env: { + authCookieSessionSecret: string; + kvNamespace: KVNamespace; + }, + cookieHeader?: string | null, +) => { const authSessionCookie = createCookie('__auth_session', { secrets: [env.authCookieSessionSecret], sameSite: true, @@ -58,6 +55,6 @@ export const makeAuthSessionStorage = async (env: { cookie: authSessionCookie, kv: env.kvNamespace, }); - - return authSessionStorage; + const authSession = await authSessionStorage.getSession(cookieHeader); + return new AuthSessionService(authSessionStorage, authSession); }; diff --git a/vite.config.ts b/vite.config.ts index a35d1df..21e27f8 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -6,33 +6,29 @@ import tsconfigPaths from 'vite-tsconfig-paths'; import { type ContextEnv, getLoadContext, - makeAuthSessionStorage, + makeAuthSessionService, } from './server'; export default defineConfig({ plugins: [ remixCloudflareDevProxyVitePlugin({ getLoadContext: async (args) => { - const authSessionStorage = await makeAuthSessionStorage({ - authCookieSessionSecret: - args.context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: args.context.cloudflare.env.KV_NAMESPACE, - }); - const authSession = await authSessionStorage.getSession( + const authSessionService = await makeAuthSessionService( + { + authCookieSessionSecret: + args.context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, + kvNamespace: args.context.cloudflare.env.KV_NAMESPACE, + }, args.request.headers.get('Cookie'), ); - const loadContext = await getLoadContext( - authSession, - () => authSessionStorage.commitSession(authSession), - args, - ); + const loadContext = await getLoadContext(authSessionService, args); return loadContext; }, getResponse: async (req, loadContext, handler) => { const response = await handler(req, loadContext); response.headers.append( 'Set-Cookie', - await loadContext.commitSession(), + await loadContext.authSessionService.commitSession(), ); return response; }, From b3c3128fee5a6ce0e199e478b3f700b0c8fabcb1 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 03:53:57 +0900 Subject: [PATCH 13/21] feat: remove unused dependency --- package.json | 1 - pnpm-lock.yaml | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/package.json b/package.json index fca0ef0..aeff5d6 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@types/eslint": "8.56.12", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", - "@types/set-cookie-parser": "2.4.10", "@types/uuid": "10.0.0", "@typescript-eslint/eslint-plugin": "7.16.0", "@typescript-eslint/parser": "7.16.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4d8007..df969d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -90,9 +90,6 @@ importers: '@types/react-dom': specifier: 18.3.0 version: 18.3.0 - '@types/set-cookie-parser': - specifier: 2.4.10 - version: 2.4.10 '@types/uuid': specifier: 10.0.0 version: 10.0.0 @@ -2172,9 +2169,6 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - '@types/set-cookie-parser@2.4.10': - resolution: {integrity: sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==} - '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -8070,10 +8064,6 @@ snapshots: '@types/node': 18.19.49 '@types/send': 0.17.4 - '@types/set-cookie-parser@2.4.10': - dependencies: - '@types/node': 22.5.3 - '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} From 38866dd4d7ed74ca64f8cb70ead2db0852f14416 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 03:59:49 +0900 Subject: [PATCH 14/21] fix(style): fix wrong comment --- server/models/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/models/auth.ts b/server/models/auth.ts index d998730..eef6d3d 100644 --- a/server/models/auth.ts +++ b/server/models/auth.ts @@ -49,7 +49,7 @@ export class AuthSessionService { } /** - * access token을 얻는 method + * auth token을 얻는 method * - access token이 만료된 경우 refresh token으로 자동 업데이트 */ async getAuthToken(context: AppLoadContext): Promise<{ From 875eba971c600c985c2dc42cf110eb09415c3880 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 18:44:03 +0900 Subject: [PATCH 15/21] refactor: rename `ApiReturnType` & fix comments --- app/models/api.ts | 26 +++++++++++++------------- app/types/api.ts | 8 +++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/app/models/api.ts b/app/models/api.ts index c56d7cf..ef37010 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -2,8 +2,8 @@ import { type AppLoadContext } from '@remix-run/cloudflare'; import type { ApiOptions, ApiRequest, - ApiReturnType, - ApiSuccessReturnType, + ApiReturn, + ApiSuccessReturn, BackendError, } from '@/types/api'; @@ -116,21 +116,21 @@ export class Api { * @example * ``` * // Case 1: `action`에서의 일반적인 활용 - * export const action = ({ context }: ActionFunctionArgs) => { + * export const action = async ({ context }: ActionFunctionArgs) => { * // ... - * const response = api_loginWithKakao.fetch({ code, state }, context); - * if (!response.isSuccess) { - * return makeErrorResponse(response.error); + * const apiReturn = await api_loginWithKakao.fetch({ code, state }, context); + * if (!apiReturn.isSuccess) { + * return makeErrorResponse(apiReturn.error); * } - * const { result } = response; + * const { result } = apiReturn; * // ... * }; * * // Case 2: `loader`는 Error Response를 반환하기보다 에러 자체를 throw해야 하는 경우가 대부분임 - * // 이 경우 `throwOnError` 옵션을 주면 `isSuccess`를 체크하지 않아도 자동으로 `ApiSuccessReturnType`으로 추론 - * export const loader = ({ context }: LoaderFunctionArgs) => { + * // 이 경우 `throwOnError` 옵션을 주면 `isSuccess`를 체크하지 않아도 자동으로 `ApiSuccessReturn`으로 추론 + * export const loader = async ({ context }: LoaderFunctionArgs) => { * // ... - * const { result } = api_loginWithKakao.fetch( + * const { result } = await api_loginWithKakao.fetch( * { code, state }, * context, * { throwOnError: true }, @@ -143,17 +143,17 @@ export class Api { variables: Variables, context: AppLoadContext, options?: ApiOptions & { throwOnError?: false }, - ): Promise>; + ): Promise>; async fetch( variables: Variables, context: AppLoadContext, options?: ApiOptions & { throwOnError: true }, - ): Promise>; + ): Promise>; async fetch( variables: Variables, context: AppLoadContext, options?: ApiOptions, - ): Promise> { + ): Promise> { try { const baseUrl = this.baseUrl ?? context.API_URL; diff --git a/app/types/api.ts b/app/types/api.ts index 4e0cae2..382ad03 100644 --- a/app/types/api.ts +++ b/app/types/api.ts @@ -52,14 +52,14 @@ export interface FrontendErrorResponse /** * `Api.fetch`에서 요청 성공 시 응답하는 형식 */ -export type ApiSuccessReturnType = { +export type ApiSuccessReturn = { isSuccess: true; result: Result; }; /** * `Api.fetch`에서 요청 실패 시 응답하는 형식 */ -export type ApiFailureReturnType = { +export type ApiFailureReturn = { isSuccess: false; error: ApiError; }; @@ -67,9 +67,7 @@ export type ApiFailureReturnType = { /** * `Api.fetch`에서 응답하는 형식 */ -export type ApiReturnType = - | ApiSuccessReturnType - | ApiFailureReturnType; +export type ApiReturn = ApiSuccessReturn | ApiFailureReturn; /** * `Api.fetch`에 줄 수 있는 옵션 목록 From 2467fa2dd70c610ef761f162475c977c582c9d7b Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 19:18:30 +0900 Subject: [PATCH 16/21] refactor: simplify `getFetchInfo` logic --- app/models/api.ts | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/app/models/api.ts b/app/models/api.ts index ef37010..afc6063 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -63,24 +63,17 @@ export class Api { const parsedRequest = this.request(variables); const pathString = - parsedRequest.pathParams?.reduce( - (prev, cur) => `${prev}/${cur}`, - '', - ) ?? ''; + parsedRequest.pathParams && parsedRequest.pathParams.length > 0 + ? '/' + parsedRequest.pathParams.join('/') + : ''; const params = parsedRequest.queryParams ?? {}; - const queryString = Object.keys(params).reduce( - (prev, cur) => - `${prev}${ - params[cur] !== null && params[cur] !== undefined - ? `&${cur}=${params[cur]}` - : '' - }`, - '', - ); + const queryString = Object.keys(params) + .map((item) => `${item}=${params[item]}`) + .join('&'); const pathname = `${this.endpoint}${pathString}${ - queryString ? `?${queryString.slice(1)}` : '' + queryString.length > 0 ? `?${queryString}` : '' }`; const authorizationHeader = accessToken From 6068e0af945767dfe12cacd780cc83b6a73ebb1c Mon Sep 17 00:00:00 2001 From: aube-dev Date: Mon, 16 Sep 2024 19:44:21 +0900 Subject: [PATCH 17/21] feat: add regex to check `API_URL` --- server/constants/env.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/constants/env.ts b/server/constants/env.ts index 6449f18..63ff568 100644 --- a/server/constants/env.ts +++ b/server/constants/env.ts @@ -1,10 +1,14 @@ import { z } from 'zod'; export const clientEnvSchema = z.object({ - API_URL: z.string(), + API_URL: z.string().regex(/^(.*[^/])$/g, { + message: 'API 주소는 슬래시(/)로 끝나지 않아야 합니다.', + }), }); export const serverEnvSchema = z.object({ AUTH_COOKIE_SESSION_SECRET: z.string(), - API_URL: z.string(), + API_URL: z.string().regex(/^(.*[^/])$/g, { + message: 'API 주소는 슬래시(/)로 끝나지 않아야 합니다.', + }), }); From bedf7708ba05c9812174efe6ef5f0a715e055625 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Thu, 19 Sep 2024 05:54:11 +0900 Subject: [PATCH 18/21] feat: add sentry & use vite env & add kakao oauth --- .eslintrc.cjs | 6 + app/apis/auth.ts | 11 +- .../KakaoLoginButton/KakaoLoginButton.tsx | 27 +- app/contexts/AuthContext.tsx | 11 + app/contexts/EnvContext.tsx | 4 - app/entry.client.tsx | 36 + app/entry.server.tsx | 88 ++ app/hooks/useAuth.ts | 10 + app/hooks/useEnv.tsx | 21 - app/hooks/useTypedFetcher.ts | 1 - app/models/api.ts | 4 +- app/root.tsx | 40 +- app/routes/_index.tsx | 20 +- app/routes/oauth.kakao.tsx | 20 +- app/routes/oauth.tsx | 24 + app/utils/server.ts | 27 + app/vite-env.d.ts | 9 + functions/[[path]].ts | 30 +- package.json | 8 +- patches/vite@5.3.3.patch | 12 + pnpm-lock.yaml | 1276 ++++++++++++++++- server/constants/env.ts | 20 +- server/index.ts | 9 +- server/models/auth.ts | 55 +- server/types/env.ts | 8 +- server/utils/cloudflare.ts | 66 +- vite.config.ts | 95 +- 27 files changed, 1644 insertions(+), 294 deletions(-) create mode 100644 app/contexts/AuthContext.tsx delete mode 100644 app/contexts/EnvContext.tsx create mode 100644 app/entry.client.tsx create mode 100644 app/entry.server.tsx create mode 100644 app/hooks/useAuth.ts delete mode 100644 app/hooks/useEnv.tsx create mode 100644 app/routes/oauth.tsx create mode 100644 app/utils/server.ts create mode 100644 app/vite-env.d.ts create mode 100644 patches/vite@5.3.3.patch diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 6cf947a..bcdba01 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -194,6 +194,12 @@ module.exports = { importNames: ['useFetcher'], message: '`@/hooks/useTypedFetcher`를 사용해 주세요.', }, + { + group: ['@remix-run/cloudflare'], + importNames: ['redirect'], + message: + '`@/utils/server`의 `redirectWithAuthCookie`를 사용해 주세요.', + }, ], }, ], diff --git a/app/apis/auth.ts b/app/apis/auth.ts index 61c7990..a2118f4 100644 --- a/app/apis/auth.ts +++ b/app/apis/auth.ts @@ -1,7 +1,7 @@ import { Api } from '@/models/api'; -export const api_loginWithKakao = new Api< - { code: string; state: string }, +export const api_loginWithOauth = new Api< + { oauthKey: string }, { userId: number; accessToken: string; @@ -10,13 +10,12 @@ export const api_loginWithKakao = new Api< refreshTokenExpiresAt: string; } >({ - method: 'POST', - endpoint: '/login/oauth2/code/kakao', + method: 'GET', + endpoint: '/oauth2/token', needToLogin: false, request: (variables) => ({ queryParams: { - code: variables.code, - state: variables.state, + oauthKey: variables.oauthKey, }, }), }); diff --git a/app/components/KakaoLoginButton/KakaoLoginButton.tsx b/app/components/KakaoLoginButton/KakaoLoginButton.tsx index 6191d99..1dd175a 100644 --- a/app/components/KakaoLoginButton/KakaoLoginButton.tsx +++ b/app/components/KakaoLoginButton/KakaoLoginButton.tsx @@ -1,24 +1,7 @@ -import React, { useEffect, useState } from 'react'; -import useEnv from '@/hooks/useEnv'; - -const KakaoLoginButton: React.FC = () => { - const env = useEnv(); - const [kakaoAuthUrl, setKakaoAuthUrl] = useState(''); - - useEffect(() => { - const redirectUri = - window.location.origin.replace('localhost', '127.0.0.1') + '/oauth/kakao'; - setKakaoAuthUrl( - `${env.API_URL}/oauth2/authorization/kakao?redirect_to=${redirectUri}`, - ); - // setKakaoAuthUrl('http://146.56.161.252:8080/oauth2/authorization/kakao'); - }, [env.API_URL]); - - return ( -
- - - ); -}; +const KakaoLoginButton: React.FC = () => ( + + + +); export default KakaoLoginButton; diff --git a/app/contexts/AuthContext.tsx b/app/contexts/AuthContext.tsx new file mode 100644 index 0000000..6df32f8 --- /dev/null +++ b/app/contexts/AuthContext.tsx @@ -0,0 +1,11 @@ +import { createContext } from 'react'; + +export interface AuthStore { + isLoggedIn: boolean; +} + +const AuthContext = createContext({ + isLoggedIn: false, +}); + +export default AuthContext; diff --git a/app/contexts/EnvContext.tsx b/app/contexts/EnvContext.tsx deleted file mode 100644 index 7323636..0000000 --- a/app/contexts/EnvContext.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { createContext } from 'react'; -import { type ClientEnv } from '@server'; - -export const EnvContext = createContext(null); diff --git a/app/entry.client.tsx b/app/entry.client.tsx new file mode 100644 index 0000000..4a8aa9a --- /dev/null +++ b/app/entry.client.tsx @@ -0,0 +1,36 @@ +import { RemixBrowser, useLocation, useMatches } from '@remix-run/react'; +import * as Sentry from '@sentry/remix'; +import { startTransition, StrictMode, useEffect } from 'react'; +import { hydrateRoot } from 'react-dom/client'; + +Sentry.init({ + dsn: import.meta.env.SHARED_SENTRY_DSN, + tracesSampleRate: 1, + + integrations: [ + Sentry.browserTracingIntegration({ + useEffect, + useLocation, + useMatches, + }), + // https://github.com/import-js/eslint-plugin-import/issues/2969#issuecomment-1967510143 + // eslint-disable-next-line import/namespace + Sentry.replayIntegration({ + maskAllText: true, + blockAllMedia: true, + }), + ], + + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1, + environment: import.meta.env.SHARED_APP_MODE, +}); + +startTransition(() => { + hydrateRoot( + document, + + + , + ); +}); diff --git a/app/entry.server.tsx b/app/entry.server.tsx new file mode 100644 index 0000000..fc15130 --- /dev/null +++ b/app/entry.server.tsx @@ -0,0 +1,88 @@ +import type { + AppLoadContext, + EntryContext, + HandleDataRequestFunction, +} from '@remix-run/cloudflare'; +import { RemixServer } from '@remix-run/react'; +import * as Sentry from '@sentry/remix'; +import * as isbotModule from 'isbot'; +import { renderToReadableStream } from 'react-dom/server'; + +Sentry.init({ + dsn: import.meta.env.SHARED_SENTRY_DSN, + tracesSampleRate: 1, + autoInstrumentRemix: true, + environment: import.meta.env.SHARED_APP_MODE, +}); + +export const handleError = Sentry.sentryHandleError; + +export default async function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + loadContext: AppLoadContext, +) { + const body = await renderToReadableStream( + , + { + signal: request.signal, + onError(error: unknown) { + // Log streaming rendering errors from inside the shell + console.error(error); + responseStatusCode = 500; + }, + }, + ); + + if (isBotRequest(request.headers.get('user-agent'))) { + await body.allReady; + } + + responseHeaders.set('Content-Type', 'text/html'); + + const cookieHeader = await loadContext.authSessionService.commitSession(); + if (cookieHeader) { + responseHeaders.append('Set-Cookie', cookieHeader); + } + + const response = new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }); + + return response; +} + +export const handleDataRequest: HandleDataRequestFunction = async ( + response, + { context }, +) => { + const cookieHeader = await context.authSessionService.commitSession(); + if (cookieHeader) { + response.headers.append('Set-Cookie', cookieHeader); + } + return response; +}; + +// We have some Remix apps in the wild already running with isbot@3 so we need +// to maintain backwards compatibility even though we want new apps to use +// isbot@4. That way, we can ship this as a minor Semver update to @remix-run/dev. +function isBotRequest(userAgent: string | null) { + if (!userAgent) { + return false; + } + + // isbot >= 3.8.0, >4 + if ('isbot' in isbotModule && typeof isbotModule.isbot === 'function') { + return isbotModule.isbot(userAgent); + } + + // isbot < 3.8.0 + if ('default' in isbotModule && typeof isbotModule.default === 'function') { + return isbotModule.default(userAgent); + } + + return false; +} diff --git a/app/hooks/useAuth.ts b/app/hooks/useAuth.ts new file mode 100644 index 0000000..76d5aaa --- /dev/null +++ b/app/hooks/useAuth.ts @@ -0,0 +1,10 @@ +import { useContext } from 'react'; +import AuthContext from '@/contexts/AuthContext'; + +const useAuth = () => { + const authStore = useContext(AuthContext); + + return authStore; +}; + +export default useAuth; diff --git a/app/hooks/useEnv.tsx b/app/hooks/useEnv.tsx deleted file mode 100644 index 07b1c39..0000000 --- a/app/hooks/useEnv.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useContext } from 'react'; -import { EnvContext } from '@/contexts/EnvContext'; -import { type ClientEnv, clientEnvSchema } from '@server'; - -/** - * 클라이언트용 환경 변수를 얻는 hook - * @example - * ``` - * const env = useEnv(); - * console.log(env.KAKAO_CLIENT_ID); - * ``` - */ -const useEnv = (): ClientEnv => { - const envFromContext = useContext(EnvContext); - - const env = clientEnvSchema.parse(envFromContext); - - return env; -}; - -export default useEnv; diff --git a/app/hooks/useTypedFetcher.ts b/app/hooks/useTypedFetcher.ts index 416e822..c07d113 100644 --- a/app/hooks/useTypedFetcher.ts +++ b/app/hooks/useTypedFetcher.ts @@ -1,5 +1,4 @@ import { type TypedResponse } from '@remix-run/cloudflare'; -// `useTypedFetcher`를 사용하라는 규칙인데 이 파일이 바로 그 구현체이므로 무시 // eslint-disable-next-line no-restricted-imports import { useFetcher } from '@remix-run/react'; import { useEffect } from 'react'; diff --git a/app/models/api.ts b/app/models/api.ts index afc6063..b159b42 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -148,10 +148,10 @@ export class Api { options?: ApiOptions, ): Promise> { try { - const baseUrl = this.baseUrl ?? context.API_URL; + const baseUrl: string = this.baseUrl ?? import.meta.env.SERVER_API_URL; const token = context.authSession - ? await context.authSessionService.getAuthToken(context) + ? await context.authSessionService.getAuthToken() : null; const fetchInfo = this.getFetchInfo(variables, token?.accessToken); diff --git a/app/root.tsx b/app/root.tsx index cf55a44..0c72d6a 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -8,26 +8,35 @@ import { ScrollRestoration, useFetchers, useLoaderData, - useRouteError, } from '@remix-run/react'; -import { useEffect, useRef } from 'react'; -import useErrorToast from './hooks/useErrorToast'; +import { withSentry } from '@sentry/remix'; +import { useEffect, useMemo, useRef } from 'react'; import * as styles from './root.css'; -import { EnvContext } from '@/contexts/EnvContext'; +import AuthContext, { type AuthStore } from '@/contexts/AuthContext'; +import useErrorToast from '@/hooks/useErrorToast'; import '@/styles/theme.css'; -export const loader = async (args: LoaderFunctionArgs) => - json({ - env: args.context.clientEnv, - }); +export const loader = async ({ context }: LoaderFunctionArgs) => { + const authToken = await context.authSessionService.getAuthToken(); + const isLoggedIn = authToken !== null; + return json({ isLoggedIn }); +}; const App = () => { - const data = useLoaderData(); + const loaderData = useLoaderData(); + const fetchers = useFetchers(); const { error, clearError } = useErrorToast(); const errorToastRemovalTimeoutIdRef = useRef(null); + const authStoreValue = useMemo( + () => ({ + isLoggedIn: loaderData.isLoggedIn, + }), + [loaderData.isLoggedIn], + ); + useEffect(() => { if (error) { if (errorToastRemovalTimeoutIdRef.current) { @@ -52,7 +61,7 @@ const App = () => { - + {fetchers.length > 0 && (
@@ -69,7 +78,7 @@ const App = () => {
)} -
+ @@ -77,11 +86,4 @@ const App = () => { ); }; -export const ErrorBoundary = () => { - const error = useRouteError(); - console.log('ErrorBoundary', error); - - return

Error

; -}; - -export default App; +export default withSentry(App); diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index d8ff1e0..e538c92 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,5 +1,6 @@ import type { MetaFunction } from '@remix-run/cloudflare'; import KakaoLoginButton from '@/components/KakaoLoginButton'; +import useAuth from '@/hooks/useAuth'; // import Test from '@/components/Test'; export const meta: MetaFunction = () => [ @@ -11,12 +12,17 @@ export const meta: MetaFunction = () => [ }, ]; -const Index = () => ( -
-

Ort

- {/* */} - -
-); +const Index = () => { + const { isLoggedIn } = useAuth(); + + return ( +
+

Ort

+ isLoggedIn: {isLoggedIn ? 'true' : 'false'} + {/* */} + +
+ ); +}; export default Index; diff --git a/app/routes/oauth.kakao.tsx b/app/routes/oauth.kakao.tsx index f3f4e13..b8b7faa 100644 --- a/app/routes/oauth.kakao.tsx +++ b/app/routes/oauth.kakao.tsx @@ -1,12 +1,12 @@ -export const loader = async () => null; +import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; +import { redirectWithAuthCookie } from '@/utils/server'; -const KakaoRedirect = () => ( -
- {/*

{fetcher.state}

- - - */} -
-); +export const loader = async ({ request, context }: LoaderFunctionArgs) => { + const url = new URL(request.url); + const { origin } = url; -export default KakaoRedirect; + return redirectWithAuthCookie( + `${import.meta.env.SERVER_API_URL}/oauth2/authorization/kakao?redirect_to=${origin}/oauth`, + context.authSessionService, + ); +}; diff --git a/app/routes/oauth.tsx b/app/routes/oauth.tsx new file mode 100644 index 0000000..d8d1116 --- /dev/null +++ b/app/routes/oauth.tsx @@ -0,0 +1,24 @@ +import { type LoaderFunctionArgs } from '@remix-run/cloudflare'; +import { api_loginWithOauth } from '@/apis/auth'; +import { redirectWithAuthCookie } from '@/utils/server'; + +export const loader = async ({ request, context }: LoaderFunctionArgs) => { + const url = new URL(request.url); + const oauthKey = url.searchParams.get('oauthKey'); + if (!oauthKey) { + throw new Error('No oauthKey provided'); + } + + const { result } = await api_loginWithOauth.fetch({ oauthKey }, context, { + throwOnError: true, + }); + + await context.authSessionService.updateAuthToken({ + accessToken: result.accessToken, + accessTokenExpiresAt: result.accessTokenExpiresAt, + refreshToken: result.refreshToken, + refreshTokenExpiresAt: result.refreshTokenExpiresAt, + }); + + return redirectWithAuthCookie('/', context.authSessionService); +}; diff --git a/app/utils/server.ts b/app/utils/server.ts new file mode 100644 index 0000000..12a49c9 --- /dev/null +++ b/app/utils/server.ts @@ -0,0 +1,27 @@ +// eslint-disable-next-line no-restricted-imports +import { redirect as remixRedirect } from '@remix-run/cloudflare'; +import { type AuthSessionService } from '@server'; + +/** + * `@remix-run/cloudflare`의 `redirect` 재구현체 + * - 필요한 경우 `Set-Cookie` header를 주입해줌 + * >- redirect 응답 시 `entry.server.tsx`의 `handleRequest`, `handleDataRequest`를 통하지 않기 때문 ([관련 이슈](https://github.com/remix-run/remix/issues/2997)) + */ +export const redirectWithAuthCookie = async ( + url: string, + authSessionService: AuthSessionService, + init?: ResponseInit, +) => { + const authCookieHeader = await authSessionService.commitSession(); + if (authCookieHeader) { + return remixRedirect(url, { + status: 302, + ...init, + headers: { + 'Set-Cookie': authCookieHeader, + ...init?.headers, + }, + }); + } + return remixRedirect(url, init); +}; diff --git a/app/vite-env.d.ts b/app/vite-env.d.ts new file mode 100644 index 0000000..5f6c524 --- /dev/null +++ b/app/vite-env.d.ts @@ -0,0 +1,9 @@ +/// + +type ClientEnv = import('../server/types/env').Env; + +interface ImportMetaEnv extends ClientEnv {} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/functions/[[path]].ts b/functions/[[path]].ts index f76f89f..57cb5a1 100644 --- a/functions/[[path]].ts +++ b/functions/[[path]].ts @@ -1,11 +1,5 @@ import { createPagesFunctionHandler } from '@remix-run/cloudflare-pages'; -import { - clientEnvSchema, - type ContextEnv, - serverEnvSchema, - getLoadContext, - makeAuthSessionService, -} from '@server'; +import { type ContextEnv, getLoadContext } from '@server'; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - the server build file is generated by `remix vite:build` @@ -16,28 +10,16 @@ export const onRequest = async ( // eslint-disable-next-line @typescript-eslint/no-explicit-any context: EventContext, ): Promise => { - clientEnvSchema.parse(context.env); - serverEnvSchema.parse(context.env); - - const authSessionService = await makeAuthSessionService( - { - authCookieSessionSecret: context.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: context.env.KV_NAMESPACE, - }, - context.request.headers.get('Cookie'), - ); - const handleRequest = createPagesFunctionHandler({ build, - getLoadContext: (args) => getLoadContext(authSessionService, args), + getLoadContext: (args) => + getLoadContext(args, { + authCookieSessionSecret: import.meta.env + .SERVER_AUTH_COOKIE_SESSION_SECRET, + }), }); const response = await handleRequest(context); - response.headers.append( - 'Set-Cookie', - await authSessionService.commitSession(), - ); - return response; }; diff --git a/package.json b/package.json index aeff5d6..2c31ea7 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,8 @@ "@remix-run/cloudflare-pages": "2.11.2", "@remix-run/react": "2.11.2", "@remix-run/serve": "2.11.2", + "@sentry/remix": "8.30.0", + "@sentry/vite-plugin": "2.22.4", "@vanilla-extract/css": "1.15.3", "isbot": "4.4.0", "react": "18.3.1", @@ -32,7 +34,6 @@ "devDependencies": { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", - "@majority-elite/remix-dev-utils": "0.1.2", "@remix-run/dev": "2.11.2", "@remix-run/testing": "2.11.2", "@storybook/addon-essentials": "8.2.9", @@ -72,5 +73,10 @@ }, "lint-staged": { "*.{js,ts,jsx,tsx}": "eslint --max-warnings=0" + }, + "pnpm": { + "patchedDependencies": { + "vite@5.3.3": "patches/vite@5.3.3.patch" + } } } diff --git a/patches/vite@5.3.3.patch b/patches/vite@5.3.3.patch new file mode 100644 index 0000000..ceed946 --- /dev/null +++ b/patches/vite@5.3.3.patch @@ -0,0 +1,12 @@ +diff --git a/types/importMeta.d.ts b/types/importMeta.d.ts +index bd4418379951b36d96cdaa98d7e2dd4973c56989..337013f37546d7f6857e176984ebdabfc1e65925 100644 +--- a/types/importMeta.d.ts ++++ b/types/importMeta.d.ts +@@ -3,7 +3,6 @@ + // + + interface ImportMetaEnv { +- [key: string]: any + BASE_URL: string + MODE: string + DEV: boolean diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df969d7..9efb6e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + vite@5.3.3: + hash: ng7gibuvnft5mzxgmesrpubqd4 + path: patches/vite@5.3.3.patch + importers: .: @@ -23,6 +28,12 @@ importers: '@remix-run/serve': specifier: 2.11.2 version: 2.11.2(typescript@5.5.3) + '@sentry/remix': + specifier: 8.30.0 + version: 8.30.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0)(@remix-run/node@2.11.2(typescript@5.5.3))(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(react@18.3.1) + '@sentry/vite-plugin': + specifier: 2.22.4 + version: 2.22.4 '@vanilla-extract/css': specifier: 1.15.3 version: 1.15.3 @@ -51,18 +62,15 @@ importers: '@commitlint/config-conventional': specifier: 19.2.2 version: 19.2.2 - '@majority-elite/remix-dev-utils': - specifier: 0.1.2 - version: 0.1.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) '@remix-run/dev': specifier: 2.11.2 - version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) + version: 2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(ts-node@10.9.2(@types/node@22.5.3)(typescript@5.5.3))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0)) '@remix-run/testing': specifier: 2.11.2 version: 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@storybook/addon-essentials': specifier: 8.2.9 - version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3) '@storybook/addon-interactions': specifier: 8.2.9 version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -77,7 +85,7 @@ importers: version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) '@storybook/react-vite': specifier: 8.2.9 - version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) + version: 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(webpack-sources@3.2.3) '@storybook/test': specifier: 8.2.9 version: 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -101,7 +109,7 @@ importers: version: 7.16.0(eslint@8.57.0)(typescript@5.5.3) '@vanilla-extract/vite-plugin': specifier: 4.0.13 - version: 4.0.13(@types/node@22.5.3)(vite@5.3.3(@types/node@22.5.3)) + version: 4.0.13(@types/node@22.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3)) autoprefixer: specifier: 10.4.19 version: 10.4.19(postcss@8.4.45) @@ -146,10 +154,10 @@ importers: version: 5.5.3 vite: specifier: 5.3.3 - version: 5.3.3(@types/node@22.5.3) + version: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) vite-tsconfig-paths: specifier: 4.3.2 - version: 4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) + version: 4.3.2(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3)) wrangler: specifier: 3.72.2 version: 3.72.2(@cloudflare/workers-types@4.20240903.0) @@ -1553,21 +1561,6 @@ packages: '@lottiefiles/dotlottie-web@0.33.0': resolution: {integrity: sha512-/KerIs0UkmwuDKYWlNGWYSSZkZaLNXXHqg6qCnP7P2JuzgI4bHRmlIk3+LoJjl/jWqd3WyI4t5oRV6ch0sQwvg==} - '@majority-elite/remix-dev-utils@0.1.2': - resolution: {integrity: sha512-+nuPSvR4jboUs70YiNMHje2kS+wszQl0lt2bR7lGCDlzFidxuMNuMKAJgBU1lf8Seq7eFUCVpB+YltHPA5ULDQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - typescript: ^5.1.0 - vite: ^5.1.0 - wrangler: ^3.28.2 - peerDependenciesMeta: - typescript: - optional: true - vite: - optional: true - wrangler: - optional: true - '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} @@ -1605,6 +1598,194 @@ packages: resolution: {integrity: sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} + engines: {node: '>=14'} + + '@opentelemetry/api-logs@0.53.0': + resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/context-async-hooks@1.26.0': + resolution: {integrity: sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.26.0': + resolution: {integrity: sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/instrumentation-connect@0.39.0': + resolution: {integrity: sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-express@0.42.0': + resolution: {integrity: sha512-YNcy7ZfGnLsVEqGXQPT+S0G1AE46N21ORY7i7yUQyfhGAL4RBjnZUqefMI0NwqIl6nGbr1IpF0rZGoN8Q7x12Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fastify@0.39.0': + resolution: {integrity: sha512-SS9uSlKcsWZabhBp2szErkeuuBDgxOUlllwkS92dVaWRnMmwysPhcEgHKB8rUe3BHg/GnZC1eo1hbTZv4YhfoA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fs@0.15.0': + resolution: {integrity: sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-generic-pool@0.39.0': + resolution: {integrity: sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-graphql@0.43.0': + resolution: {integrity: sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-hapi@0.41.0': + resolution: {integrity: sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-http@0.53.0': + resolution: {integrity: sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-ioredis@0.43.0': + resolution: {integrity: sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-kafkajs@0.3.0': + resolution: {integrity: sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-koa@0.43.0': + resolution: {integrity: sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongodb@0.47.0': + resolution: {integrity: sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongoose@0.42.0': + resolution: {integrity: sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql2@0.41.0': + resolution: {integrity: sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql@0.41.0': + resolution: {integrity: sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-nestjs-core@0.40.0': + resolution: {integrity: sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pg@0.44.0': + resolution: {integrity: sha512-oTWVyzKqXud1BYEGX1loo2o4k4vaU1elr3vPO8NZolrBtFvQ34nx4HgUaexUDuEog00qQt+MLR5gws/p+JXMLQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis-4@0.42.0': + resolution: {integrity: sha512-NaD+t2JNcOzX/Qa7kMy68JbmoVIV37fT/fJYzLKu2Wwd+0NCxt+K2OOsOakA8GVg8lSpFdbx4V/suzZZ2Pvdjg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-undici@0.6.0': + resolution: {integrity: sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + + '@opentelemetry/instrumentation@0.43.0': + resolution: {integrity: sha512-S1uHE+sxaepgp+t8lvIDuRgyjJWisAb733198kwQTUc9ZtYQ2V2gmyCtR1x21ePGVLoMiX/NWY7WA290hwkjJQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.53.0': + resolution: {integrity: sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/redis-common@0.36.2': + resolution: {integrity: sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==} + engines: {node: '>=14'} + + '@opentelemetry/resources@1.26.0': + resolution: {integrity: sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.26.0': + resolution: {integrity: sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.26.0': + resolution: {integrity: sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.27.0': + resolution: {integrity: sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==} + engines: {node: '>=14'} + + '@opentelemetry/sql-common@0.40.1': + resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1613,6 +1794,9 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@prisma/instrumentation@5.19.1': + resolution: {integrity: sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==} + '@remix-run/cloudflare-pages@2.11.2': resolution: {integrity: sha512-Sa/LED9qPJfpk6IgJvXiUIzjCRC2B6dyfOH286YttoKOGmEiMaXYt4KTEssyiT8LY7nR3IPsprA8kohjpRujhg==} engines: {node: '>=18.0.0'} @@ -1816,6 +2000,125 @@ packages: cpu: [x64] os: [win32] + '@sentry-internal/browser-utils@8.30.0': + resolution: {integrity: sha512-pwX+awNWaxSOAsBLVLqc1+Hw+Fm1Nci9mbKFA6Ed5YzCG049PnBVQwugpmx2dcyyCqJpORhcIqb9jHdCkYmCiA==} + engines: {node: '>=14.18'} + + '@sentry-internal/feedback@8.30.0': + resolution: {integrity: sha512-ParFRxQY6helxkwUDmro77Wc5uSIC6rZos88jYMrYwFmoTJaNWf4lDzPyECfdSiSYyzSMZk4dorSUN85Ul7DCg==} + engines: {node: '>=14.18'} + + '@sentry-internal/replay-canvas@8.30.0': + resolution: {integrity: sha512-y/QqcvchhtMlVA6eOZicIfTxtZarazQZJuFW0018ynPxBTiuuWSxMCLqduulXUYsFejfD8/eKHb3BpCIFdDYjg==} + engines: {node: '>=14.18'} + + '@sentry-internal/replay@8.30.0': + resolution: {integrity: sha512-/KFre+BrovPCiovgAu5N1ErJtkDVzkJA5hV3Jw011AlxRWxrmPwu6+9sV9/rn3tqYAGyq6IggYqeIOHhLh1Ihg==} + engines: {node: '>=14.18'} + + '@sentry/babel-plugin-component-annotate@2.22.4': + resolution: {integrity: sha512-hbSq067KwmeKIEkmyzkTNJbmbtx2KRqvpiy9Q/DynI5Z46Nko/ppvgIfyFXK9DelwvEPOqZic4WXTIhO4iv3DA==} + engines: {node: '>= 14'} + + '@sentry/browser@8.30.0': + resolution: {integrity: sha512-M+tKqawH9S3CqlAIcqdZcHbcsNQkEa9MrPqPCYvXco3C4LRpNizJP2XwBiGQY2yK+fOSvbaWpPtlI938/wuRZQ==} + engines: {node: '>=14.18'} + + '@sentry/bundler-plugin-core@2.22.4': + resolution: {integrity: sha512-25NiyV3v6mdqOXlpzbbJnq0FHdAu1uTEDr+DU8CzNLjIXlq2Sr2CFZ/mhRcR6daM8OAretJdQ34lu0yHUVeE4Q==} + engines: {node: '>= 14'} + + '@sentry/cli-darwin@2.36.1': + resolution: {integrity: sha512-JOHQjVD8Kqxm1jUKioAP5ohLOITf+Dh6+DBz4gQjCNdotsvNW5m63TKROwq2oB811p+Jzv5304ujmN4cAqW1Ww==} + engines: {node: '>=10'} + os: [darwin] + + '@sentry/cli-linux-arm64@2.36.1': + resolution: {integrity: sha512-R//3ZEkbzvoStr3IA7nxBZNiBYyxOljOqAhgiTnejXHmnuwDzM3TBA2n5vKPE/kBFxboEBEw0UTzTIRb1T0bgw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux, freebsd] + + '@sentry/cli-linux-arm@2.36.1': + resolution: {integrity: sha512-gvEOKN0fWL2AVqUBKHNXPRZfJNvKTs8kQhS8cQqahZGgZHiPCI4BqW45cKMq+ZTt1UUbLmt6khx5Dz7wi+0i5A==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux, freebsd] + + '@sentry/cli-linux-i686@2.36.1': + resolution: {integrity: sha512-R7sW5Vk/HacVy2YgQoQB+PwccvFYf2CZVPSFSFm2z7MEfNe77UYHWUq+sjJ4vxWG6HDWGVmaX0fjxyDkE01JRA==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [linux, freebsd] + + '@sentry/cli-linux-x64@2.36.1': + resolution: {integrity: sha512-UMr3ik8ksA7zQfbzsfwCb+ztenLnaeAbX94Gp+bzANZwPfi/vVHf2bLyqsBs4OyVt9SPlN1bbM/RTGfMjZ3JOw==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux, freebsd] + + '@sentry/cli-win32-i686@2.36.1': + resolution: {integrity: sha512-CflvhnvxPEs5GWQuuDtYSLqPrBaPbcSJFlBuUIb+8WNzRxvVfjgw1qzfZmkQqABqiy/YEsEekllOoMFZAvCcVA==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [win32] + + '@sentry/cli-win32-x64@2.36.1': + resolution: {integrity: sha512-wWqht2xghcK3TGnooHZSzA3WSjdtno/xFjZLvWmw38rblGwgKMxLZnlxV6uDyS+OJ6CbfDTlCRay/0TIqA0N8g==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@sentry/cli@2.36.1': + resolution: {integrity: sha512-gzK5uQKDWKhyH5udoB5+oaUNrS//urWyaXgKvHKz4gFfl744HuKY9dpLPP2nMnf0zLGmGM6xJnMXLqILq0mtxw==} + engines: {node: '>= 10'} + hasBin: true + + '@sentry/core@8.30.0': + resolution: {integrity: sha512-CJ/FuWLw0QEKGKXGL/nm9eaOdajEcmPekLuHAuOCxID7N07R9l9laz3vFbAkUZ97GGDv3sYrJZgywfY3Moropg==} + engines: {node: '>=14.18'} + + '@sentry/node@8.30.0': + resolution: {integrity: sha512-Tog0Ag7sU3lNj4cPUZy1KRJXyYXZlWiwlk34KYNNxAk0vDiK6W0bF8mvS+aaUukgb7FO5A0eu9l+VApdBJOr3Q==} + engines: {node: '>=14.18'} + + '@sentry/opentelemetry@8.30.0': + resolution: {integrity: sha512-6mCIP2zvxAiEsNEoF8kv+UUD4XGWSKJU6RY5BF1U26HLitXv1fNPtzaTR96Ehv9h0zktjLfqfpVUZ7DGkdBvLA==} + engines: {node: '>=14.18'} + peerDependencies: + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.25.1 + '@opentelemetry/instrumentation': ^0.53.0 + '@opentelemetry/sdk-trace-base': ^1.26.0 + '@opentelemetry/semantic-conventions': ^1.27.0 + + '@sentry/react@8.30.0': + resolution: {integrity: sha512-ktQjXs87jdsxW0YrHci3sb6zcSzhMECWnrTVU/KGZF8UoDsk4P4xRCknijd2SSmDIjSkwzUAANR43UkCi4BTQg==} + engines: {node: '>=14.18'} + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + + '@sentry/remix@8.30.0': + resolution: {integrity: sha512-q6pwPxoMOkekKXmVaxVppn5lUAwE4cCXGALdmfeixgUl4xCFbQ0nu5T8bltvn6E9LQxbqSXNx80c/aqpwC59Ow==} + engines: {node: '>=14.18'} + hasBin: true + peerDependencies: + '@remix-run/node': 1.x || 2.x + '@remix-run/react': 1.x || 2.x + react: 16.x || 17.x || 18.x + + '@sentry/types@8.30.0': + resolution: {integrity: sha512-kgWW2BCjBmVlSQRG32GonHEVyeDbys74xf9mLPvynwHTgw3+NUlNAlEdu05xnb2ow4bCTHfbkS5G1zRgyv5k4Q==} + engines: {node: '>=14.18'} + + '@sentry/utils@8.30.0': + resolution: {integrity: sha512-wZxU2HWlzsnu8214Xy7S7cRIuD6h8Z5DnnkojJfX0i0NLooepZQk2824el1Q13AakLb7/S8CHSHXOMnCtoSduw==} + engines: {node: '>=14.18'} + + '@sentry/vite-plugin@2.22.4': + resolution: {integrity: sha512-C51PUlTv0BXN3+e9SjPHptNX3b9E0clrsaR5c//l/sFkQjuteDHKChA1gNzZSvfoa3gm9NzZAgpk3hVF2O3nBA==} + engines: {node: '>= 14'} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -2031,6 +2334,18 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} @@ -2052,6 +2367,9 @@ packages: '@types/body-parser@1.19.5': resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/connect@3.4.36': + resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} @@ -2133,6 +2451,9 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/mysql@2.15.26': + resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==} + '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} @@ -2142,6 +2463,12 @@ packages: '@types/node@22.5.3': resolution: {integrity: sha512-njripolh85IA9SQGTAqbmnNZTdxv7X/4OYGPz8tgy5JDr8MP+uDBa921GpYEoDDnwm0Hmn5ZPeJgiiSTPoOzkQ==} + '@types/pg-pool@2.0.6': + resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} + + '@types/pg@8.6.1': + resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -2169,6 +2496,9 @@ packages: '@types/serve-static@1.15.7': resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2327,6 +2657,16 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + acorn-import-assertions@1.9.0: + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -2350,6 +2690,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -2392,6 +2736,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} @@ -2640,6 +2987,9 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} @@ -2785,6 +3135,9 @@ packages: typescript: optional: true + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2925,6 +3278,10 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -3499,6 +3856,10 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} @@ -3584,6 +3945,9 @@ packages: hast-util-whitespace@2.0.1: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + hosted-git-info@6.1.1: resolution: {integrity: sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3596,6 +3960,10 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -3630,6 +3998,12 @@ packages: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} + import-in-the-middle@1.11.0: + resolution: {integrity: sha512-5DimNQGoe0pLUHbR9qK84iWaWjjbsxiqXnw6Qz64+azRgleqv9k2kTt5fw7QsOpmaGYtuxxursnPPsnTKEx10Q==} + + import-in-the-middle@1.4.2: + resolution: {integrity: sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==} + import-meta-resolve@4.1.0: resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} @@ -4101,6 +4475,10 @@ packages: magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.8: + resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} + engines: {node: '>=12'} + make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -4109,6 +4487,9 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + map-or-similar@1.5.0: resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} @@ -4325,6 +4706,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -4348,6 +4733,10 @@ packages: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} engines: {node: '>=8'} + minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} @@ -4374,6 +4763,9 @@ packages: modern-ahocorasick@1.0.1: resolution: {integrity: sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA==} + module-details-from-path@1.0.3: + resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + morgan@1.10.0: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} engines: {node: '>= 0.8.0'} @@ -4421,6 +4813,15 @@ packages: node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + node-forge@1.3.1: resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} engines: {node: '>= 6.13.0'} @@ -4539,6 +4940,11 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} + opentelemetry-instrumentation-remix@0.7.1: + resolution: {integrity: sha512-zzJ8CAsf4Pem+B1zY0NEKQcQjXIORgylPBIQMO2x1OdRc9HzBPLUp7JIlGt/RAfPsp5qaEs7QqvX9xtsrZgtFQ==} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -4668,6 +5074,17 @@ packages: periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-protocol@1.6.1: + resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + picocolors@1.1.0: resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} @@ -4765,6 +5182,22 @@ packages: resolution: {integrity: sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==} engines: {node: ^10 || ^12 || >=14} + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4809,6 +5242,10 @@ packages: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + promise-inflight@1.0.1: resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: @@ -4835,6 +5272,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@2.0.1: resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} @@ -5000,6 +5440,10 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-in-the-middle@7.4.0: + resolution: {integrity: sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==} + engines: {node: '>=8.6.0'} + require-like@0.1.2: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} @@ -5152,6 +5596,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -5411,6 +5858,9 @@ packages: toml@3.0.0: resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -5427,6 +5877,20 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tsconfck@3.1.3: resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==} engines: {node: ^18 || >=20} @@ -5603,6 +6067,9 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unplugin@1.0.1: + resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} + unplugin@1.13.1: resolution: {integrity: sha512-6Kq1iSSwg7KyjcThRUks9LuqDAKvtnioxbL9iEtB9ctTyBA5OmrB8gZd/d225VJu1w3UpUsKV7eGrvf59J7+VA==} engines: {node: '>=14.0.0'} @@ -5649,6 +6116,9 @@ packages: engines: {node: '>=8'} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -5720,9 +6190,22 @@ packages: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + + webpack-virtual-modules@0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} + webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -5844,6 +6327,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -7189,13 +7676,13 @@ snapshots: dependencies: '@sinclair/typebox': 0.27.8 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.5.3) - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) optionalDependencies: typescript: 5.5.3 @@ -7231,16 +7718,6 @@ snapshots: '@lottiefiles/dotlottie-web@0.33.0': {} - '@majority-elite/remix-dev-utils@0.1.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0))': - dependencies: - '@remix-run/node': 2.11.2(typescript@5.5.3) - '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) - set-cookie-parser: 2.7.0 - optionalDependencies: - typescript: 5.5.3 - vite: 5.3.3(@types/node@22.5.3) - wrangler: 3.72.2(@cloudflare/workers-types@4.20240903.0) - '@mdx-js/mdx@2.3.0': dependencies: '@types/estree-jsx': 1.0.5 @@ -7314,27 +7791,284 @@ snapshots: dependencies: which: 3.0.1 - '@pkgjs/parseargs@0.11.0': - optional: true + '@opentelemetry/api-logs@0.52.1': + dependencies: + '@opentelemetry/api': 1.9.0 - '@pkgr/core@0.1.1': {} + '@opentelemetry/api-logs@0.53.0': + dependencies: + '@opentelemetry/api': 1.9.0 - '@remix-run/cloudflare-pages@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/context-async-hooks@1.26.0(@opentelemetry/api@1.9.0)': dependencies: - '@cloudflare/workers-types': 4.20240903.0 - '@remix-run/cloudflare': 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) - optionalDependencies: - typescript: 5.5.3 + '@opentelemetry/api': 1.9.0 - '@remix-run/cloudflare@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': + '@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0)': dependencies: - '@cloudflare/kv-asset-handler': 0.1.3 - '@cloudflare/workers-types': 4.20240903.0 - '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/instrumentation-connect@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/connect': 3.4.36 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-express@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-fastify@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-fs@0.15.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-generic-pool@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-graphql@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-hapi@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-ioredis@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-kafkajs@0.3.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-koa@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mongodb@0.47.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mongoose@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mysql2@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mysql@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/mysql': 2.15.26 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-nestjs-core@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-pg@0.44.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) + '@types/pg': 8.6.1 + '@types/pg-pool': 2.0.6 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-redis-4@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-undici@0.6.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.4.2 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.0 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.0 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/redis-common@0.36.2': {} + + '@opentelemetry/resources@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/sdk-metrics@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/semantic-conventions@1.27.0': {} + + '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@prisma/instrumentation@5.19.1': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@remix-run/cloudflare-pages@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': + dependencies: + '@cloudflare/workers-types': 4.20240903.0 + '@remix-run/cloudflare': 2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3) + optionalDependencies: + typescript: 5.5.3 + + '@remix-run/cloudflare@2.11.2(@cloudflare/workers-types@4.20240903.0)(typescript@5.5.3)': + dependencies: + '@cloudflare/kv-asset-handler': 0.1.3 + '@cloudflare/workers-types': 4.20240903.0 + '@remix-run/server-runtime': 2.11.2(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 - '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0))': + '@remix-run/dev@2.11.2(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(@remix-run/serve@2.11.2(typescript@5.5.3))(@types/node@22.5.3)(ts-node@10.9.2(@types/node@22.5.3)(typescript@5.5.3))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(wrangler@3.72.2(@cloudflare/workers-types@4.20240903.0))': dependencies: '@babel/core': 7.25.2 '@babel/generator': 7.25.6 @@ -7378,7 +8112,7 @@ snapshots: pidtree: 0.6.0 postcss: 8.4.45 postcss-discard-duplicates: 5.1.0(postcss@8.4.45) - postcss-load-config: 4.0.2(postcss@8.4.45) + postcss-load-config: 4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@22.5.3)(typescript@5.5.3)) postcss-modules: 6.0.0(postcss@8.4.45) prettier: 2.8.8 pretty-ms: 7.0.1 @@ -7393,7 +8127,7 @@ snapshots: optionalDependencies: '@remix-run/serve': 2.11.2(typescript@5.5.3) typescript: 5.5.3 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) wrangler: 3.72.2(@cloudflare/workers-types@4.20240903.0) transitivePeerDependencies: - '@types/node' @@ -7565,6 +8299,200 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.21.2': optional: true + '@sentry-internal/browser-utils@8.30.0': + dependencies: + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry-internal/feedback@8.30.0': + dependencies: + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry-internal/replay-canvas@8.30.0': + dependencies: + '@sentry-internal/replay': 8.30.0 + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry-internal/replay@8.30.0': + dependencies: + '@sentry-internal/browser-utils': 8.30.0 + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry/babel-plugin-component-annotate@2.22.4': {} + + '@sentry/browser@8.30.0': + dependencies: + '@sentry-internal/browser-utils': 8.30.0 + '@sentry-internal/feedback': 8.30.0 + '@sentry-internal/replay': 8.30.0 + '@sentry-internal/replay-canvas': 8.30.0 + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry/bundler-plugin-core@2.22.4': + dependencies: + '@babel/core': 7.25.2 + '@sentry/babel-plugin-component-annotate': 2.22.4 + '@sentry/cli': 2.36.1 + dotenv: 16.4.5 + find-up: 5.0.0 + glob: 9.3.5 + magic-string: 0.30.8 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + '@sentry/cli-darwin@2.36.1': + optional: true + + '@sentry/cli-linux-arm64@2.36.1': + optional: true + + '@sentry/cli-linux-arm@2.36.1': + optional: true + + '@sentry/cli-linux-i686@2.36.1': + optional: true + + '@sentry/cli-linux-x64@2.36.1': + optional: true + + '@sentry/cli-win32-i686@2.36.1': + optional: true + + '@sentry/cli-win32-x64@2.36.1': + optional: true + + '@sentry/cli@2.36.1': + dependencies: + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + optionalDependencies: + '@sentry/cli-darwin': 2.36.1 + '@sentry/cli-linux-arm': 2.36.1 + '@sentry/cli-linux-arm64': 2.36.1 + '@sentry/cli-linux-i686': 2.36.1 + '@sentry/cli-linux-x64': 2.36.1 + '@sentry/cli-win32-i686': 2.36.1 + '@sentry/cli-win32-x64': 2.36.1 + transitivePeerDependencies: + - encoding + - supports-color + + '@sentry/core@8.30.0': + dependencies: + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry/node@8.30.0': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-connect': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-express': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fastify': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fs': 0.15.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-generic-pool': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-graphql': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-hapi': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-ioredis': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-kafkajs': 0.3.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-koa': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongodb': 0.47.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongoose': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql2': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-nestjs-core': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pg': 0.44.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis-4': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-undici': 0.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@prisma/instrumentation': 5.19.1 + '@sentry/core': 8.30.0 + '@sentry/opentelemetry': 8.30.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0) + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + import-in-the-middle: 1.11.0 + transitivePeerDependencies: + - supports-color + + '@sentry/opentelemetry@8.30.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + + '@sentry/react@8.30.0(react@18.3.1)': + dependencies: + '@sentry/browser': 8.30.0 + '@sentry/core': 8.30.0 + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + hoist-non-react-statics: 3.3.2 + react: 18.3.1 + + '@sentry/remix@8.30.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0)(@remix-run/node@2.11.2(typescript@5.5.3))(@remix-run/react@2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3))(react@18.3.1)': + dependencies: + '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0) + '@remix-run/node': 2.11.2(typescript@5.5.3) + '@remix-run/react': 2.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@remix-run/router': 1.19.1 + '@sentry/cli': 2.36.1 + '@sentry/core': 8.30.0 + '@sentry/node': 8.30.0 + '@sentry/opentelemetry': 8.30.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.27.0) + '@sentry/react': 8.30.0(react@18.3.1) + '@sentry/types': 8.30.0 + '@sentry/utils': 8.30.0 + glob: 10.4.5 + opentelemetry-instrumentation-remix: 0.7.1(@opentelemetry/api@1.9.0) + react: 18.3.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/core' + - '@opentelemetry/instrumentation' + - '@opentelemetry/sdk-trace-base' + - '@opentelemetry/semantic-conventions' + - encoding + - supports-color + + '@sentry/types@8.30.0': {} + + '@sentry/utils@8.30.0': + dependencies: + '@sentry/types': 8.30.0 + + '@sentry/vite-plugin@2.22.4': + dependencies: + '@sentry/bundler-plugin-core': 2.22.4 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + '@sinclair/typebox@0.27.8': {} '@sindresorhus/merge-streams@2.3.0': {} @@ -7592,12 +8520,12 @@ snapshots: storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - '@storybook/addon-docs@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/addon-docs@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3)': dependencies: '@babel/core': 7.25.2 '@mdx-js/react': 3.0.1(@types/react@18.3.3)(react@18.3.1) '@storybook/blocks': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3) '@storybook/global': 5.0.0 '@storybook/react-dom-shim': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@types/react': 18.3.3 @@ -7612,12 +8540,12 @@ snapshots: - supports-color - webpack-sources - '@storybook/addon-essentials@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/addon-essentials@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3)': dependencies: '@storybook/addon-actions': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-backgrounds': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-controls': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) - '@storybook/addon-docs': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/addon-docs': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3) '@storybook/addon-highlight': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-measure': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) '@storybook/addon-outline': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) @@ -7700,9 +8628,9 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': + '@storybook/builder-vite@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(webpack-sources@3.2.3)': dependencies: - '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2))) + '@storybook/csf-plugin': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3) '@types/find-cache-dir': 3.2.1 browser-assert: 1.2.1 es-module-lexer: 1.5.4 @@ -7712,7 +8640,7 @@ snapshots: magic-string: 0.30.11 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) ts-dedent: 2.2.0 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) optionalDependencies: typescript: 5.5.3 transitivePeerDependencies: @@ -7761,10 +8689,10 @@ snapshots: - supports-color - utf-8-validate - '@storybook/csf-plugin@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))': + '@storybook/csf-plugin@8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(webpack-sources@3.2.3)': dependencies: storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - unplugin: 1.13.1 + unplugin: 1.13.1(webpack-sources@3.2.3) transitivePeerDependencies: - webpack-sources @@ -7804,11 +8732,11 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) - '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3))': + '@storybook/react-vite@8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.21.2)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(webpack-sources@3.2.3)': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3)) '@rollup/pluginutils': 5.1.0(rollup@4.21.2) - '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)) + '@storybook/builder-vite': 8.2.9(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))(webpack-sources@3.2.3) '@storybook/react': 8.2.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)))(typescript@5.5.3) find-up: 5.0.0 magic-string: 0.30.11 @@ -7818,7 +8746,7 @@ snapshots: resolve: 1.22.8 storybook: 8.2.9(@babel/preset-env@7.25.4(@babel/core@7.25.2)) tsconfig-paths: 4.2.0 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) transitivePeerDependencies: - '@preact/preset-vite' - rollup @@ -7904,6 +8832,18 @@ snapshots: dependencies: '@testing-library/dom': 10.1.0 + '@tsconfig/node10@1.0.11': + optional: true + + '@tsconfig/node12@1.0.11': + optional: true + + '@tsconfig/node14@1.0.3': + optional: true + + '@tsconfig/node16@1.0.4': + optional: true + '@types/acorn@4.0.6': dependencies: '@types/estree': 1.0.5 @@ -7936,6 +8876,10 @@ snapshots: '@types/connect': 3.4.38 '@types/node': 18.19.49 + '@types/connect@3.4.36': + dependencies: + '@types/node': 22.5.3 + '@types/connect@3.4.38': dependencies: '@types/node': 18.19.49 @@ -8022,6 +8966,10 @@ snapshots: '@types/ms@0.7.34': {} + '@types/mysql@2.15.26': + dependencies: + '@types/node': 22.5.3 + '@types/node-forge@1.3.11': dependencies: '@types/node': 22.5.3 @@ -8034,6 +8982,16 @@ snapshots: dependencies: undici-types: 6.19.8 + '@types/pg-pool@2.0.6': + dependencies: + '@types/pg': 8.6.1 + + '@types/pg@8.6.1': + dependencies: + '@types/node': 22.5.3 + pg-protocol: 1.6.1 + pg-types: 2.2.0 + '@types/prop-types@15.7.12': {} '@types/qs@6.9.15': {} @@ -8064,6 +9022,8 @@ snapshots: '@types/node': 18.19.49 '@types/send': 0.17.4 + '@types/shimmer@1.2.0': {} + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -8248,7 +9208,7 @@ snapshots: lodash: 4.17.21 mlly: 1.7.1 outdent: 0.8.0 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) vite-node: 1.6.0(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' @@ -8273,7 +9233,7 @@ snapshots: find-up: 5.0.0 javascript-stringify: 2.1.0 mlly: 1.7.1 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) vite-node: 1.6.0(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' @@ -8288,10 +9248,10 @@ snapshots: '@vanilla-extract/private@1.0.6': {} - '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.3)(vite@5.3.3(@types/node@22.5.3))': + '@vanilla-extract/vite-plugin@4.0.13(@types/node@22.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3))': dependencies: '@vanilla-extract/integration': 7.1.9(@types/node@22.5.3) - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -8349,6 +9309,14 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + acorn-import-assertions@1.9.0(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-import-attributes@1.9.5(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + acorn-jsx@5.3.2(acorn@7.4.1): dependencies: acorn: 7.4.1 @@ -8367,6 +9335,12 @@ snapshots: acorn@8.12.1: {} + agent-base@6.0.2: + dependencies: + debug: 4.3.6 + transitivePeerDependencies: + - supports-color + aggregate-error@3.1.0: dependencies: clean-stack: 2.2.0 @@ -8411,6 +9385,9 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@4.1.3: + optional: true + arg@5.0.2: {} argparse@2.0.1: {} @@ -8735,6 +9712,8 @@ snapshots: dependencies: consola: 3.2.3 + cjs-module-lexer@1.4.1: {} + clean-stack@2.2.0: {} cli-cursor@3.1.0: @@ -8868,6 +9847,9 @@ snapshots: optionalDependencies: typescript: 5.5.3 + create-require@1.1.1: + optional: true + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -8991,6 +9973,9 @@ snapshots: diff-sequences@29.6.3: {} + diff@4.0.2: + optional: true + diff@5.2.0: {} dir-glob@3.0.1: @@ -9854,6 +10839,13 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + glob@9.3.5: + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.11.1 + global-directory@4.0.1: dependencies: ini: 4.1.1 @@ -9962,6 +10954,10 @@ snapshots: hast-util-whitespace@2.0.1: {} + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + hosted-git-info@6.1.1: dependencies: lru-cache: 7.18.3 @@ -9976,6 +10972,13 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.6 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} human-signals@5.0.0: {} @@ -9999,6 +11002,20 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-in-the-middle@1.11.0: + dependencies: + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + cjs-module-lexer: 1.4.1 + module-details-from-path: 1.0.3 + + import-in-the-middle@1.4.2: + dependencies: + acorn: 8.12.1 + acorn-import-assertions: 1.9.0(acorn@8.12.1) + cjs-module-lexer: 1.4.1 + module-details-from-path: 1.0.3 + import-meta-resolve@4.1.0: {} imurmurhash@0.1.4: {} @@ -10424,6 +11441,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magic-string@0.30.8: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@2.1.0: dependencies: pify: 4.0.1 @@ -10433,6 +11454,9 @@ snapshots: dependencies: semver: 6.3.1 + make-error@1.3.6: + optional: true + map-or-similar@1.5.0: {} markdown-extensions@1.1.1: {} @@ -10831,6 +11855,10 @@ snapshots: dependencies: brace-expansion: 1.1.11 + minimatch@8.0.4: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -10853,6 +11881,8 @@ snapshots: dependencies: yallist: 4.0.0 + minipass@4.2.8: {} + minipass@5.0.0: {} minipass@7.1.2: {} @@ -10875,6 +11905,8 @@ snapshots: modern-ahocorasick@1.0.1: {} + module-details-from-path@1.0.3: {} + morgan@1.10.0: dependencies: basic-auth: 2.0.1 @@ -10911,6 +11943,10 @@ snapshots: node-fetch-native@1.6.4: {} + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + node-forge@1.3.1: {} node-releases@2.0.18: {} @@ -11040,6 +12076,14 @@ snapshots: dependencies: mimic-function: 5.0.1 + opentelemetry-instrumentation-remix@0.7.1(@opentelemetry/api@1.9.0): + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -11170,6 +12214,18 @@ snapshots: estree-walker: 3.0.3 is-reference: 3.0.2 + pg-int8@1.0.1: {} + + pg-protocol@1.6.1: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + picocolors@1.1.0: {} picomatch@2.3.1: {} @@ -11204,12 +12260,13 @@ snapshots: dependencies: postcss: 8.4.45 - postcss-load-config@4.0.2(postcss@8.4.45): + postcss-load-config@4.0.2(postcss@8.4.45)(ts-node@10.9.2(@types/node@22.5.3)(typescript@5.5.3)): dependencies: lilconfig: 3.1.2 yaml: 2.5.1 optionalDependencies: postcss: 8.4.45 + ts-node: 10.9.2(@types/node@22.5.3)(typescript@5.5.3) postcss-modules-extract-imports@3.1.0(postcss@8.4.45): dependencies: @@ -11257,6 +12314,16 @@ snapshots: picocolors: 1.1.0 source-map-js: 1.2.0 + postgres-array@2.0.0: {} + + postgres-bytea@1.0.0: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -11291,6 +12358,8 @@ snapshots: process@0.11.10: {} + progress@2.0.3: {} + promise-inflight@1.0.1: {} promise-retry@2.0.1: @@ -11316,6 +12385,8 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 + proxy-from-env@1.1.0: {} + pump@2.0.1: dependencies: end-of-stream: 1.4.4 @@ -11545,6 +12616,14 @@ snapshots: require-from-string@2.0.2: {} + require-in-the-middle@7.4.0: + dependencies: + debug: 4.3.6 + module-details-from-path: 1.0.3 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + require-like@0.1.2: {} requireindex@1.2.0: {} @@ -11728,6 +12807,8 @@ snapshots: shebang-regex@3.0.0: {} + shimmer@1.2.1: {} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 @@ -12028,6 +13109,8 @@ snapshots: toml@3.0.0: {} + tr46@0.0.3: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -12038,6 +13121,25 @@ snapshots: ts-dedent@2.2.0: {} + ts-node@10.9.2(@types/node@22.5.3)(typescript@5.5.3): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.5.3 + acorn: 8.12.1 + acorn-walk: 8.3.3 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.5.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + tsconfck@3.1.3(typescript@5.5.3): optionalDependencies: typescript: 5.5.3 @@ -12233,10 +13335,19 @@ snapshots: unpipe@1.0.0: {} - unplugin@1.13.1: + unplugin@1.0.1: + dependencies: + acorn: 8.12.1 + chokidar: 3.6.0 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.5.0 + + unplugin@1.13.1(webpack-sources@3.2.3): dependencies: acorn: 8.12.1 webpack-virtual-modules: 0.6.2 + optionalDependencies: + webpack-sources: 3.2.3 update-browserslist-db@1.1.0(browserslist@4.23.3): dependencies: @@ -12275,6 +13386,9 @@ snapshots: kleur: 4.1.5 sade: 1.8.1 + v8-compile-cache-lib@3.0.1: + optional: true + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -12302,7 +13416,7 @@ snapshots: debug: 4.3.6 pathe: 1.1.2 picocolors: 1.1.0 - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) transitivePeerDependencies: - '@types/node' - less @@ -12313,18 +13427,18 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@22.5.3)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3)): dependencies: debug: 4.3.6 globrex: 0.1.2 tsconfck: 3.1.3(typescript@5.5.3) optionalDependencies: - vite: 5.3.3(@types/node@22.5.3) + vite: 5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3) transitivePeerDependencies: - supports-color - typescript - vite@5.3.3(@types/node@22.5.3): + vite@5.3.3(patch_hash=ng7gibuvnft5mzxgmesrpubqd4)(@types/node@22.5.3): dependencies: esbuild: 0.21.5 postcss: 8.4.45 @@ -12347,8 +13461,19 @@ snapshots: web-streams-polyfill@3.3.3: {} + webidl-conversions@3.0.1: {} + + webpack-sources@3.2.3: {} + + webpack-virtual-modules@0.5.0: {} + webpack-virtual-modules@0.6.2: {} + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -12489,6 +13614,9 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yn@3.1.1: + optional: true + yocto-queue@0.1.0: {} yocto-queue@1.1.1: {} diff --git a/server/constants/env.ts b/server/constants/env.ts index 63ff568..9ae9c34 100644 --- a/server/constants/env.ts +++ b/server/constants/env.ts @@ -1,14 +1,16 @@ import { z } from 'zod'; -export const clientEnvSchema = z.object({ - API_URL: z.string().regex(/^(.*[^/])$/g, { +// 클라이언트용은 CLIENT_, 서버용은 SERVER_, 양쪽 모두 사용하는 용도는 SHARED_ +const envSchemaObject = { + SERVER_AUTH_COOKIE_SESSION_SECRET: z.string(), + SERVER_API_URL: z.string().regex(/^(.*[^/])$/g, { message: 'API 주소는 슬래시(/)로 끝나지 않아야 합니다.', }), -}); + SHARED_SENTRY_DSN: z.string(), + SHARED_APP_MODE: z.enum(['development', 'preview', 'production']), +} satisfies Record< + `${'SERVER_' | 'CLIENT_' | 'SHARED_'}${string}`, + z.ZodString | z.ZodEnum<[string, ...string[]]> +>; -export const serverEnvSchema = z.object({ - AUTH_COOKIE_SESSION_SECRET: z.string(), - API_URL: z.string().regex(/^(.*[^/])$/g, { - message: 'API 주소는 슬래시(/)로 끝나지 않아야 합니다.', - }), -}); +export const envSchema = z.object(envSchemaObject); diff --git a/server/index.ts b/server/index.ts index 40fe4b6..6912fd0 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,4 +1,4 @@ -export { serverEnvSchema, clientEnvSchema } from './constants/env'; +export { envSchema } from './constants/env'; export { AuthSessionService } from './models/auth'; @@ -7,11 +7,6 @@ export type { AuthSessionData, AuthSessionStorage, } from './types/auth'; -export type { - ServerEnv, - ClientEnv, - CloudflareEnv, - ContextEnv, -} from './types/env'; +export type { CloudflareEnv, ContextEnv } from './types/env'; export { getLoadContext, makeAuthSessionService } from './utils/cloudflare'; diff --git a/server/models/auth.ts b/server/models/auth.ts index eef6d3d..ee4e984 100644 --- a/server/models/auth.ts +++ b/server/models/auth.ts @@ -1,4 +1,4 @@ -import { type AppLoadContext } from '@remix-run/cloudflare'; +import { type Cookie } from '@remix-run/cloudflare'; import type { AuthSession, AuthSessionData, @@ -6,19 +6,48 @@ import type { } from '../types/auth'; export class AuthSessionService { + private authSessionCookie: Cookie; private authSessionStorage: AuthSessionStorage; private authSession: AuthSession; + private nextAction: 'none' | 'commit' | 'destroy' = 'none'; constructor( + authSessionCookie: Cookie, authSessionStorage: AuthSessionStorage, authSession: AuthSession, ) { + this.authSessionCookie = authSessionCookie; this.authSessionStorage = authSessionStorage; this.authSession = authSession; } - async commitSession(): Promise { - return await this.authSessionStorage.commitSession(this.authSession); + async parseCookieHeader(cookieHeader: string | null): Promise { + return await this.authSessionCookie.parse(cookieHeader); + } + + /** + * session 수정사항을 반영하고 Set-Cookie header를 얻는 method + * - Set-Cookie를 할 필요가 없는 경우 `null` 반환 + */ + async commitSession(): Promise { + console.log('commitSession', this.nextAction); + if (this.nextAction === 'destroy') { + const cookieHeader = await this.authSessionStorage.destroySession( + this.authSession, + ); + this.nextAction = 'none'; + return cookieHeader; + } + + if (this.nextAction === 'commit') { + const cookieHeader = await this.authSessionStorage.commitSession( + this.authSession, + ); + this.nextAction = 'none'; + return cookieHeader; + } + + return null; } async clearAuthToken() { @@ -26,6 +55,7 @@ export class AuthSessionService { this.authSession.unset('accessTokenExpiresAt'); this.authSession.unset('refreshToken'); this.authSession.unset('refreshTokenExpiresAt'); + this.nextAction = 'destroy'; } /** @@ -44,6 +74,7 @@ export class AuthSessionService { (Object.keys(newToken) as (keyof typeof newToken)[]).forEach((key) => { if (newToken[key]) { this.authSession.set(key, newToken[key]); + this.nextAction = 'commit'; } }); } @@ -52,7 +83,7 @@ export class AuthSessionService { * auth token을 얻는 method * - access token이 만료된 경우 refresh token으로 자동 업데이트 */ - async getAuthToken(context: AppLoadContext): Promise<{ + async getAuthToken(): Promise<{ accessToken: string; refreshToken: string; } | null> { @@ -71,7 +102,6 @@ export class AuthSessionService { accessTokenExpiresAtString === undefined || refreshTokenExpiresAtString === undefined ) { - await this.clearAuthToken(); return null; } @@ -85,13 +115,16 @@ export class AuthSessionService { // refresh token이 만료되지 않음 (서버 응답 시간 등을 고려해 1분 여유 포함) if (refreshTokenExpiresAt.getTime() > now.getTime() + 1000 * 60) { try { - const response = await fetch(`${context.API_URL}/token/access`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + const response = await fetch( + `${import.meta.env.SERVER_API_URL}/token/access`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ refreshToken }), }, - body: JSON.stringify({ refreshToken }), - }); + ); const result = await response.json<{ accessToken: string; accessTokenExpiresAt: string; diff --git a/server/types/env.ts b/server/types/env.ts index 8396c58..279d323 100644 --- a/server/types/env.ts +++ b/server/types/env.ts @@ -1,12 +1,10 @@ import type { z } from 'zod'; -import type { clientEnvSchema, serverEnvSchema } from '../constants/env'; +import type { envSchema } from '../constants/env'; -export type ClientEnv = Readonly>; - -export type ServerEnv = Readonly>; +export type Env = z.infer; export type CloudflareEnv = { readonly KV_NAMESPACE: KVNamespace; }; -export type ContextEnv = ClientEnv & ServerEnv & CloudflareEnv; +export type ContextEnv = CloudflareEnv; diff --git a/server/utils/cloudflare.ts b/server/utils/cloudflare.ts index fec2f69..d67ca1a 100644 --- a/server/utils/cloudflare.ts +++ b/server/utils/cloudflare.ts @@ -4,42 +4,16 @@ import { } from '@remix-run/cloudflare'; import { type GetLoadContextFunction } from '@remix-run/cloudflare-pages'; import { type PlatformProxy } from 'wrangler'; -import { clientEnvSchema, serverEnvSchema } from '../constants/env'; import { AuthSessionService } from '../models/auth'; import type { AuthSessionData } from '../types/auth'; -import type { - ClientEnv, - CloudflareEnv, - ContextEnv, - ServerEnv, -} from '../types/env'; +import type { CloudflareEnv, ContextEnv } from '../types/env'; declare module '@remix-run/cloudflare' { - interface AppLoadContext extends ServerEnv, CloudflareEnv { - readonly clientEnv: ClientEnv; + interface AppLoadContext extends CloudflareEnv { readonly authSessionService: AuthSessionService; } } -export const getLoadContext = ( - authSessionService: AuthSessionService, - args: { - request: Request; - context: { - cloudflare: Omit, 'dispose'>; - }; - }, -): ReturnType> => { - const clientEnv = clientEnvSchema.parse(args.context.cloudflare.env); - serverEnvSchema.parse(args.context.cloudflare.env); - - return { - ...args.context.cloudflare.env, - clientEnv, - authSessionService, - }; -}; - export const makeAuthSessionService = async ( env: { authCookieSessionSecret: string; @@ -50,11 +24,45 @@ export const makeAuthSessionService = async ( const authSessionCookie = createCookie('__auth_session', { secrets: [env.authCookieSessionSecret], sameSite: true, + maxAge: 60 * 60 * 24 * 30, + httpOnly: true, + secure: true, }); const authSessionStorage = createWorkersKVSessionStorage({ cookie: authSessionCookie, kv: env.kvNamespace, }); const authSession = await authSessionStorage.getSession(cookieHeader); - return new AuthSessionService(authSessionStorage, authSession); + return new AuthSessionService( + authSessionCookie, + authSessionStorage, + authSession, + ); +}; + +export const getLoadContext = async ( + args: { + request: Request; + context: { + cloudflare: Omit, 'dispose'>; + }; + }, + env: { + authCookieSessionSecret: string; + }, +): Promise>>> => { + const authSessionService = await makeAuthSessionService( + { + authCookieSessionSecret: + env?.authCookieSessionSecret ?? + import.meta.env.SERVER_AUTH_COOKIE_SESSION_SECRET, + kvNamespace: args.context.cloudflare.env.KV_NAMESPACE, + }, + args.request.headers.get('cookie'), + ); + + return { + ...args.context.cloudflare.env, + authSessionService, + }; }; diff --git a/vite.config.ts b/vite.config.ts index 21e27f8..dcfd01b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,46 +1,57 @@ -import { cloudflareDevProxyVitePlugin as remixCloudflareDevProxyVitePlugin } from '@majority-elite/remix-dev-utils'; -import { vitePlugin as remix } from '@remix-run/dev'; +import { + vitePlugin as remix, + cloudflareDevProxyVitePlugin as remixCloudflareDevProxyVitePlugin, +} from '@remix-run/dev'; +import { sentryVitePlugin } from '@sentry/vite-plugin'; import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; -import { defineConfig } from 'vite'; +import { defineConfig, loadEnv } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; -import { - type ContextEnv, - getLoadContext, - makeAuthSessionService, -} from './server'; +import { z } from 'zod'; +import { type ContextEnv, envSchema, getLoadContext } from './server'; + +export default defineConfig(({ mode }) => { + const viteEnv = loadEnv(mode, process.cwd(), [ + 'CLIENT_', + 'SERVER_', + 'SHARED_', + 'SENTRY_', + ]); + + envSchema.parse(viteEnv); + + const configEnv = z + .object({ + SENTRY_AUTH_TOKEN: z.string(), + }) + .parse(viteEnv); -export default defineConfig({ - plugins: [ - remixCloudflareDevProxyVitePlugin({ - getLoadContext: async (args) => { - const authSessionService = await makeAuthSessionService( - { - authCookieSessionSecret: - args.context.cloudflare.env.AUTH_COOKIE_SESSION_SECRET, - kvNamespace: args.context.cloudflare.env.KV_NAMESPACE, - }, - args.request.headers.get('Cookie'), - ); - const loadContext = await getLoadContext(authSessionService, args); - return loadContext; - }, - getResponse: async (req, loadContext, handler) => { - const response = await handler(req, loadContext); - response.headers.append( - 'Set-Cookie', - await loadContext.authSessionService.commitSession(), - ); - return response; - }, - }), - remix({ - future: { - v3_fetcherPersist: true, - v3_relativeSplatPath: true, - v3_throwAbortReason: true, - }, - }), - tsconfigPaths(), - vanillaExtractPlugin(), - ], + return { + envPrefix: ['CLIENT_', 'SERVER_', 'SHARED_'], + plugins: [ + remixCloudflareDevProxyVitePlugin({ + getLoadContext: (args) => + getLoadContext(args, { + authCookieSessionSecret: viteEnv.SERVER_AUTH_COOKIE_SESSION_SECRET, + }), + }), + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + }, + }), + tsconfigPaths(), + vanillaExtractPlugin(), + sentryVitePlugin({ + org: 'majority-elite', + project: 'ort-frontend', + url: 'https://sentry.io/', + authToken: configEnv.SENTRY_AUTH_TOKEN, + }), + ], + build: { + sourcemap: true, + }, + }; }); From e1f051ef5e57336783d8786e68d3de1c7063558a Mon Sep 17 00:00:00 2001 From: aube-dev Date: Thu, 19 Sep 2024 22:57:44 +0900 Subject: [PATCH 19/21] refactor: remove unnecessary console --- server/models/auth.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/server/models/auth.ts b/server/models/auth.ts index ee4e984..878d161 100644 --- a/server/models/auth.ts +++ b/server/models/auth.ts @@ -30,7 +30,6 @@ export class AuthSessionService { * - Set-Cookie를 할 필요가 없는 경우 `null` 반환 */ async commitSession(): Promise { - console.log('commitSession', this.nextAction); if (this.nextAction === 'destroy') { const cookieHeader = await this.authSessionStorage.destroySession( this.authSession, From fd72176e5a92ed9902a83ffc965078f5a7dd653b Mon Sep 17 00:00:00 2001 From: aube-dev Date: Thu, 19 Sep 2024 23:14:56 +0900 Subject: [PATCH 20/21] feat: add `extraErrorDataIntegration` --- app/entry.client.tsx | 2 ++ app/entry.server.tsx | 2 ++ app/models/api.ts | 1 - 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/entry.client.tsx b/app/entry.client.tsx index 4a8aa9a..736654d 100644 --- a/app/entry.client.tsx +++ b/app/entry.client.tsx @@ -19,11 +19,13 @@ Sentry.init({ maskAllText: true, blockAllMedia: true, }), + Sentry.extraErrorDataIntegration(), ], replaysSessionSampleRate: 0.1, replaysOnErrorSampleRate: 1, environment: import.meta.env.SHARED_APP_MODE, + debug: import.meta.env.SHARED_APP_MODE === 'development', }); startTransition(() => { diff --git a/app/entry.server.tsx b/app/entry.server.tsx index fc15130..b78b0ff 100644 --- a/app/entry.server.tsx +++ b/app/entry.server.tsx @@ -13,6 +13,8 @@ Sentry.init({ tracesSampleRate: 1, autoInstrumentRemix: true, environment: import.meta.env.SHARED_APP_MODE, + debug: import.meta.env.SHARED_APP_MODE === 'development', + integrations: [Sentry.extraErrorDataIntegration()], }); export const handleError = Sentry.sentryHandleError; diff --git a/app/models/api.ts b/app/models/api.ts index b159b42..4cddacc 100644 --- a/app/models/api.ts +++ b/app/models/api.ts @@ -228,7 +228,6 @@ export class Api { }; } - // TODO: Sentry 등 에러 로깅 솔루션 추가 console.error(error, this, variables); const apiError = new ApiError({ api: this, From a7497562ac130724fabd97a96981e81bb81fe513 Mon Sep 17 00:00:00 2001 From: aube-dev Date: Fri, 20 Sep 2024 00:32:17 +0900 Subject: [PATCH 21/21] fix: remove sourcemap files after upload for safety --- vite.config.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index dcfd01b..31a0ad6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,7 +17,7 @@ export default defineConfig(({ mode }) => { 'SENTRY_', ]); - envSchema.parse(viteEnv); + const env = envSchema.parse(viteEnv); const configEnv = z .object({ @@ -31,7 +31,7 @@ export default defineConfig(({ mode }) => { remixCloudflareDevProxyVitePlugin({ getLoadContext: (args) => getLoadContext(args, { - authCookieSessionSecret: viteEnv.SERVER_AUTH_COOKIE_SESSION_SECRET, + authCookieSessionSecret: env.SERVER_AUTH_COOKIE_SESSION_SECRET, }), }), remix({ @@ -48,6 +48,9 @@ export default defineConfig(({ mode }) => { project: 'ort-frontend', url: 'https://sentry.io/', authToken: configEnv.SENTRY_AUTH_TOKEN, + sourcemaps: { + filesToDeleteAfterUpload: './build/**/*.map', + }, }), ], build: {