From 365a097ddf0a3ecea547fc3f6b89c809df2846c6 Mon Sep 17 00:00:00 2001 From: kesoji <6465251+kesoji@users.noreply.github.com> Date: Sat, 1 Feb 2025 16:57:31 +0900 Subject: [PATCH] feat: can handle bigint data --- src/client/context/RDTContext.tsx | 3 ++- src/client/hof.ts | 4 ++++ src/shared/bigint-util.ts | 17 +++++++++++++++++ src/shared/send-event.ts | 3 ++- test-apps/react-router-vite/app/root.tsx | 6 +++--- .../react-router-vite/app/routes/_index.tsx | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 src/shared/bigint-util.ts diff --git a/src/client/context/RDTContext.tsx b/src/client/context/RDTContext.tsx index b1b21d3..c979c82 100644 --- a/src/client/context/RDTContext.tsx +++ b/src/client/context/RDTContext.tsx @@ -1,6 +1,7 @@ import type { Dispatch } from "react" import type React from "react" import { createContext, useEffect, useMemo, useReducer } from "react" +import { bigIntReplacer } from "../../shared/bigint-util.js" import { useRemoveBody } from "../hooks/detached/useRemoveBody.js" import { checkIsDetached, checkIsDetachedOwner, checkIsDetachedWindow } from "../utils/detached.js" import { tryParseJson } from "../utils/sanitize.js" @@ -126,7 +127,7 @@ export const RDTContextProvider = ({ children, config }: ContextProps) => { // Store user settings for dev tools into local storage setStorageItem(REACT_ROUTER_DEV_TOOLS_SETTINGS, JSON.stringify(settings)) // Store general state into local storage - setStorageItem(REACT_ROUTER_DEV_TOOLS_STATE, JSON.stringify(rest)) + setStorageItem(REACT_ROUTER_DEV_TOOLS_STATE, JSON.stringify(rest, bigIntReplacer)) }, [state]) return {children} diff --git a/src/client/hof.ts b/src/client/hof.ts index 2375b1d..be08156 100644 --- a/src/client/hof.ts +++ b/src/client/hof.ts @@ -1,7 +1,11 @@ import type { ClientActionFunctionArgs, ClientLoaderFunctionArgs, LinksFunction } from "react-router" +import { convertBigIntToString } from "../shared/bigint-util" import type { RequestEvent } from "../shared/request-event" const sendEventToDevServer = (req: RequestEvent) => { + if (req.data) { + req.data = convertBigIntToString(req.data) + } import.meta.hot?.send("request-event", req) } diff --git a/src/shared/bigint-util.ts b/src/shared/bigint-util.ts new file mode 100644 index 0000000..68bc6e2 --- /dev/null +++ b/src/shared/bigint-util.ts @@ -0,0 +1,17 @@ +export const bigIntReplacer = (key: any, value: any) => (typeof value === "bigint" ? value.toString() : value) + +export const convertBigIntToString = (data: any): any => { + if (typeof data === "bigint") { + return data.toString() + } + + if (Array.isArray(data)) { + return data.map((item) => convertBigIntToString(item)) + } + + if (data !== null && typeof data === "object") { + return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, convertBigIntToString(value)])) + } + + return data +} diff --git a/src/shared/send-event.ts b/src/shared/send-event.ts index f65ce59..b77d546 100644 --- a/src/shared/send-event.ts +++ b/src/shared/send-event.ts @@ -1,3 +1,4 @@ +import { bigIntReplacer } from "./bigint-util" import type { RequestEvent } from "./request-event" export const sendEvent = (event: RequestEvent) => { @@ -9,7 +10,7 @@ export const sendEvent = (event: RequestEvent) => { if (port) { fetch(`http://localhost:${port}/react-router-devtools-request`, { method: "POST", - body: JSON.stringify({ routine: "request-event", ...event }), + body: JSON.stringify({ routine: "request-event", ...event }, bigIntReplacer), }) .then(async (res) => { // avoid memory leaks diff --git a/test-apps/react-router-vite/app/root.tsx b/test-apps/react-router-vite/app/root.tsx index 7a4394c..a488c0d 100644 --- a/test-apps/react-router-vite/app/root.tsx +++ b/test-apps/react-router-vite/app/root.tsx @@ -28,7 +28,7 @@ export const loader = ({context, devTools }: LoaderFunctionArgs) => { }); const start =devTools?.tracing.start("test")!; devTools?.tracing.end("test", start); - return data({ message: "Hello World", mainPromise }, { headers: { "Cache-Control": "max-age=3600, private" } }); + return data({ message: "Hello World", mainPromise, bigInt: BigInt(10) }, { headers: { "Cache-Control": "max-age=3600, private" } }); } export const action =async ({devTools}: ActionFunctionArgs) => { @@ -39,7 +39,7 @@ export const action =async ({devTools}: ActionFunctionArgs) => { }, 2000); }); devTools?.tracing.end("action submission", start!) - return ({ message: "Hello World" }); + return ({ message: "Hello World", bigInt: BigInt(10) }); } export default function App() { @@ -65,4 +65,4 @@ export default function App() { ); -} \ No newline at end of file +} diff --git a/test-apps/react-router-vite/app/routes/_index.tsx b/test-apps/react-router-vite/app/routes/_index.tsx index 87ed214..2a87b26 100644 --- a/test-apps/react-router-vite/app/routes/_index.tsx +++ b/test-apps/react-router-vite/app/routes/_index.tsx @@ -38,7 +38,7 @@ export const loader = async ({ request, context,devTools, params }: LoaderFunct resolve("test1"); }, 3500); }); - return { message: "Hello World!", test, test1, data }; + return { message: "Hello World!", test, test1, data, bigInt: BigInt(10) }; }; export const clientLoader = async ({ request, serverLoader, devTools }: ClientLoaderFunctionArgs) => {