Skip to content

Commit d0dd78f

Browse files
aidansunburyclburlisonJoeKarow
authored
feat: use collapsable JSON viewer (#5)
Co-authored-by: Clayton Burlison <[email protected]> Co-authored-by: Joe Karow <[email protected]>
1 parent 4c7b8cc commit d0dd78f

File tree

6 files changed

+13760
-9243
lines changed

6 files changed

+13760
-9243
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,7 @@ testem.log
4545
.DS_Store
4646
Thumbs.db
4747

48-
stats.html
48+
stats.html
49+
50+
# yarn
51+
.yarn

packages/trpc-panel/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@
8888
"zustand": "^4.1.5"
8989
},
9090
"dependencies": {
91+
"@textea/json-viewer": "^3.0.0",
9192
"fuzzysort": "^2.0.4",
9293
"path": "^0.12.7",
94+
"pretty-bytes": "^6.1.0",
95+
"pretty-ms": "^8.0.0",
96+
"string-byte-length": "^1.6.0",
9397
"url": "^0.11.0",
9498
"zod-to-json-schema": "^3.20.0"
9599
}
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
import React from "react";
22
import { Response } from "./Response";
3-
import json from "json-bigint";
43

5-
export function RequestResult({ result }: { result: any }) {
6-
return <Response>{`${json.stringify(result, null, 2)}`}</Response>;
4+
5+
export function RequestResult({
6+
result,
7+
size,
8+
time,
9+
}: {
10+
result: any;
11+
size?: number;
12+
time?: number;
13+
}) {
14+
return (
15+
<Response size={size} time={time}>
16+
{result}
17+
</Response>
18+
);
719
}

packages/trpc-panel/src/react-app/components/form/ProcedureForm/Response.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,36 @@
11
import React from "react";
22
import { FormSection } from "./FormSection";
3+
import { JsonViewer } from "@textea/json-viewer";
4+
import prettyBytes from "pretty-bytes";
5+
import prettyMs from "pretty-ms";
6+
7+
export function Response({
8+
children,
9+
size,
10+
time,
11+
}: {
12+
children: string | object;
13+
size?: number;
14+
time?: number;
15+
}) {
16+
const title = size
17+
? time
18+
? `Response (${prettyBytes(size)}, ${prettyMs(time)})`
19+
: `Response (${prettyBytes(size)})`
20+
: time
21+
? `Response (${prettyMs(time)})`
22+
: `Response`;
23+
24+
if (typeof children === "object") {
25+
return (
26+
<FormSection title={title}>
27+
<JsonViewer rootName={false} value={children} quotesOnKeys={false} />
28+
</FormSection>
29+
);
30+
}
331

4-
export function Response({ children }: { children: string }) {
532
return (
6-
<FormSection title="Response">
33+
<FormSection title={title}>
734
<p className="font-mono whitespace-pre-wrap break-words">{children}</p>
835
</FormSection>
936
);

packages/trpc-panel/src/react-app/components/form/ProcedureForm/index.tsx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type { ParsedInputNode } from "@src/parse/parseNodeTypes";
1919
import { DocumentationSection } from "@src/react-app/components/form/ProcedureForm/DescriptionSection";
2020
import { Field } from "@src/react-app/components/form/Field";
2121
import { ProcedureFormContextProvider } from "@src/react-app/components/form/ProcedureForm/ProcedureFormContext";
22+
import getSize from "string-byte-length";
2223

2324
const TRPCErrorSchema = z.object({
2425
meta: z.object({
@@ -65,6 +66,9 @@ export function ProcedureForm({
6566
const [queryInput, setQueryInput] = useState<any>(null);
6667
const formRef = useRef<HTMLFormElement | null>(null);
6768
const context = trpc.useContext();
69+
const [dataSize, setDataSize] = useState<number | undefined>();
70+
const [startTime, setStartTime] = useState<number | undefined>();
71+
const [opDuration, setOpDuration] = useState<number | undefined>();
6872

6973
function getProcedure() {
7074
var cur: typeof trpc | (typeof trpc)[string] = trpc;
@@ -84,6 +88,11 @@ export function ProcedureForm({
8488
initialData: null,
8589
retry: false,
8690
refetchOnWindowFocus: false,
91+
onSuccess: (data: unknown) => {
92+
if (startTime) setOpDuration(Date.now() - startTime);
93+
setDataSize(getSize(JSON.stringify(data)));
94+
setStartTime(undefined);
95+
},
8796
});
8897
})() as UseQueryResult<any>;
8998

@@ -100,6 +109,11 @@ export function ProcedureForm({
100109
//@ts-ignore
101110
return router.useMutation({
102111
retry: false,
112+
onSuccess: (data: unknown) => {
113+
if (startTime) setOpDuration(Date.now() - startTime);
114+
setDataSize(getSize(JSON.stringify(data)));
115+
setStartTime(undefined);
116+
},
103117
});
104118
})() as UseMutationResult<any>;
105119

@@ -115,8 +129,8 @@ export function ProcedureForm({
115129
[ROOT_VALS_PROPERTY_NAME]: defaultFormValuesForNode(procedure.node),
116130
},
117131
});
118-
119132
function onSubmit(data: { [ROOT_VALS_PROPERTY_NAME]: any }) {
133+
setStartTime(Date.now());
120134
const newData = { json: data[ROOT_VALS_PROPERTY_NAME] };
121135
if (procedure.procedureType === "query") {
122136
setQueryInput(newData);
@@ -207,15 +221,17 @@ export function ProcedureForm({
207221
</div>
208222
</form>
209223
<div className="flex flex-col space-y-4">
210-
{data && <RequestResult result={data} />}
224+
{data && (
225+
<RequestResult result={data} size={dataSize} time={opDuration} />
226+
)}
211227
{!data && data !== null && (
212228
<Response>Successful request but no data was returned</Response>
213229
)}
214230
{error &&
215231
(isTrpcError(error) ? (
216232
<Error error={error} />
217233
) : (
218-
<Response>{JSON.stringify(error)}</Response>
234+
<Response>{error}</Response>
219235
))}
220236
</div>
221237
</CollapsableSection>

0 commit comments

Comments
 (0)