@yuhere/js-jsonrpc2 2.1.3 → 2.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/htdoc/assets/{index-hcP2-9jw.css → index-BAZmvr5x.css} +13 -0
- package/htdoc/assets/{index-BEVUmX2-.js → index-sVQlhxjI.js} +54 -13
- package/htdoc/assets/index-sVQlhxjI.js.map +1 -0
- package/htdoc/index.html +2 -2
- package/package.json +2 -2
- package/webui/src/components/TestPanel.tsx +53 -10
- package/webui/src/styles/geek.css +13 -0
- package/htdoc/assets/index-BEVUmX2-.js.map +0 -1
package/htdoc/index.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>JSON-RPC 2.0</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-sVQlhxjI.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BAZmvr5x.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuhere/js-jsonrpc2",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "A TypeScript JSON-RPC 2.0 server library with schema validation, authorization, dependency injection, and multiple transports.",
|
|
5
5
|
"homepage": "https://github.com/yuhere/js-jsonrpc2#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"js-jsonrpc2": "./dist/cli.js"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
|
-
"build": "npm run build:lib && npm run build:webui",
|
|
43
|
+
"build": "clean && npm run build:lib && npm run build:webui",
|
|
44
44
|
"build:lib": "tsc -p tsconfig.build.json && tsc-esm-fix",
|
|
45
45
|
"build:webui": "tsc -p webui//tsconfig.json && vite build --config webui/vite.config.ts",
|
|
46
46
|
"dev": "run-p dev:lib dev:webui",
|
|
@@ -20,6 +20,12 @@ const COPY_OPTIONS: { value: CopyKind; label: string }[] = [
|
|
|
20
20
|
{ value: 'fetch', label: '复制 fetch' },
|
|
21
21
|
];
|
|
22
22
|
|
|
23
|
+
/** 格式化耗时:<1s 用 ms,否则用 s */
|
|
24
|
+
function formatElapsed(ms: number): string {
|
|
25
|
+
if (ms < 1000) return `${ms.toFixed(0)} ms`;
|
|
26
|
+
return `${(ms / 1000).toFixed(2)} s`;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
export function TestPanel({
|
|
24
30
|
method,
|
|
25
31
|
detail,
|
|
@@ -32,6 +38,7 @@ export function TestPanel({
|
|
|
32
38
|
|
|
33
39
|
const [values, setValues] = useState<unknown[]>([]);
|
|
34
40
|
const [output, setOutput] = useState('');
|
|
41
|
+
const [elapsed, setElapsed] = useState<{ total: number; firstFrame?: number } | null>(null);
|
|
35
42
|
const [running, setRunning] = useState(false);
|
|
36
43
|
const [copyKind, setCopyKind] = useState<CopyKind>('curl');
|
|
37
44
|
const [copied, setCopied] = useState(false);
|
|
@@ -44,6 +51,7 @@ export function TestPanel({
|
|
|
44
51
|
if (!method) return;
|
|
45
52
|
setValues(paramSchemas.map(sampleFromSchema));
|
|
46
53
|
setOutput('');
|
|
54
|
+
setElapsed(null);
|
|
47
55
|
}, [method, paramSchemas]);
|
|
48
56
|
|
|
49
57
|
useEffect(() => {
|
|
@@ -76,29 +84,46 @@ export function TestPanel({
|
|
|
76
84
|
if (!method) return;
|
|
77
85
|
setRunning(true);
|
|
78
86
|
setOutput('');
|
|
87
|
+
setElapsed(null);
|
|
88
|
+
|
|
89
|
+
const startedAt = performance.now();
|
|
79
90
|
try {
|
|
80
91
|
const result = await rpc.call(method, ...values);
|
|
92
|
+
|
|
93
|
+
// 首帧/响应到达耗时
|
|
94
|
+
const firstFrameAt = performance.now() - startedAt;
|
|
95
|
+
|
|
81
96
|
if (isStreamResult(result)) {
|
|
82
97
|
let idx = 0;
|
|
83
98
|
const lines: string[] = [];
|
|
99
|
+
|
|
100
|
+
// 每帧记录到达时间
|
|
84
101
|
for await (const value of result) {
|
|
85
|
-
|
|
102
|
+
const now = performance.now() - startedAt;
|
|
103
|
+
lines.push(
|
|
104
|
+
`[${idx}] (+${formatElapsed(now)}) ${JSON.stringify(value, null, 2)}`,
|
|
105
|
+
);
|
|
86
106
|
idx++;
|
|
87
107
|
setOutput(lines.join('\n'));
|
|
88
108
|
}
|
|
89
|
-
if (idx === 0) setOutput('(流已结束,无数据)');
|
|
90
|
-
else lines.push(`(流已结束,共 ${idx} 帧)`), setOutput(lines.join('\n'));
|
|
91
|
-
} else {
|
|
92
|
-
setOutput(JSON.stringify(result, null, 2));
|
|
93
|
-
}
|
|
94
109
|
|
|
95
|
-
|
|
110
|
+
const totalAt = performance.now() - startedAt;
|
|
111
|
+
if (idx === 0) {
|
|
112
|
+
lines.push(`(流已结束,无数据,总耗时 ${formatElapsed(totalAt)})`);
|
|
113
|
+
} else {
|
|
114
|
+
lines.push(`(流已结束,共 ${idx} 帧,总耗时 ${formatElapsed(totalAt)})`);
|
|
115
|
+
}
|
|
116
|
+
setOutput(lines.join('\n'));
|
|
117
|
+
setElapsed({ total: totalAt, firstFrame: firstFrameAt });
|
|
96
118
|
} else {
|
|
97
|
-
const
|
|
119
|
+
const totalAt = performance.now() - startedAt;
|
|
98
120
|
setOutput(JSON.stringify(result, null, 2));
|
|
121
|
+
setElapsed({ total: totalAt });
|
|
99
122
|
}
|
|
100
123
|
} catch (e) {
|
|
124
|
+
const totalAt = performance.now() - startedAt;
|
|
101
125
|
setOutput(formatError(e));
|
|
126
|
+
setElapsed({ total: totalAt });
|
|
102
127
|
} finally {
|
|
103
128
|
setRunning(false);
|
|
104
129
|
requestAnimationFrame(() =>
|
|
@@ -211,12 +236,30 @@ export function TestPanel({
|
|
|
211
236
|
>
|
|
212
237
|
重置为示例
|
|
213
238
|
</button>
|
|
214
|
-
<button
|
|
239
|
+
<button
|
|
240
|
+
onClick={() => {
|
|
241
|
+
setOutput('');
|
|
242
|
+
setElapsed(null);
|
|
243
|
+
}}
|
|
244
|
+
disabled={!output && !elapsed}
|
|
245
|
+
>
|
|
215
246
|
清空输出
|
|
216
247
|
</button>
|
|
217
248
|
</div>
|
|
218
249
|
|
|
219
|
-
<h3
|
|
250
|
+
<h3>
|
|
251
|
+
结果{isStreamReturn && <span className="hint">(流式)</span>}
|
|
252
|
+
{elapsed && (
|
|
253
|
+
<span className="elapsed-badge">
|
|
254
|
+
{' '}⏱ {formatElapsed(elapsed.total)}
|
|
255
|
+
{elapsed.firstFrame !== undefined && (
|
|
256
|
+
<span className="hint">
|
|
257
|
+
{' '}· 首帧 {formatElapsed(elapsed.firstFrame)}
|
|
258
|
+
</span>
|
|
259
|
+
)}
|
|
260
|
+
</span>
|
|
261
|
+
)}
|
|
262
|
+
</h3>
|
|
220
263
|
<pre className="output" ref={outRef}>
|
|
221
264
|
{output || '(尚未执行)'}
|
|
222
265
|
</pre>
|
|
@@ -726,4 +726,17 @@ textarea:focus {
|
|
|
726
726
|
.split-button {
|
|
727
727
|
display: inline-flex;
|
|
728
728
|
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/* ---- 耗时徽章(TestPanel 结果区) ---- */
|
|
732
|
+
.elapsed-badge {
|
|
733
|
+
color: var(--syn-number);
|
|
734
|
+
font-size: 12px;
|
|
735
|
+
font-weight: normal;
|
|
736
|
+
letter-spacing: 0;
|
|
737
|
+
text-transform: none;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.elapsed-badge .hint {
|
|
741
|
+
font-size: 11px;
|
|
729
742
|
}
|