@mt0926/node-network-devtools 0.1.0

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.
Files changed (73) hide show
  1. package/BUILD.md +204 -0
  2. package/LICENSE +21 -0
  3. package/README.md +310 -0
  4. package/README.zh-CN.md +310 -0
  5. package/dist/esm/adapters/nextjs.js +123 -0
  6. package/dist/esm/adapters/nextjs.js.map +1 -0
  7. package/dist/esm/cdp/cdp-bridge.js +312 -0
  8. package/dist/esm/cdp/cdp-bridge.js.map +1 -0
  9. package/dist/esm/cli.js +203 -0
  10. package/dist/esm/cli.js.map +1 -0
  11. package/dist/esm/config.js +136 -0
  12. package/dist/esm/config.js.map +1 -0
  13. package/dist/esm/context/context-manager.js +126 -0
  14. package/dist/esm/context/context-manager.js.map +1 -0
  15. package/dist/esm/gui/browser-launcher.js +165 -0
  16. package/dist/esm/gui/browser-launcher.js.map +1 -0
  17. package/dist/esm/gui/event-bridge.js +192 -0
  18. package/dist/esm/gui/event-bridge.js.map +1 -0
  19. package/dist/esm/gui/port-utils.js +80 -0
  20. package/dist/esm/gui/port-utils.js.map +1 -0
  21. package/dist/esm/gui/server.js +227 -0
  22. package/dist/esm/gui/server.js.map +1 -0
  23. package/dist/esm/gui/websocket-hub.js +326 -0
  24. package/dist/esm/gui/websocket-hub.js.map +1 -0
  25. package/dist/esm/index.js +90 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/interceptors/http-patcher.js +203 -0
  28. package/dist/esm/interceptors/http-patcher.js.map +1 -0
  29. package/dist/esm/interceptors/undici-patcher.js +324 -0
  30. package/dist/esm/interceptors/undici-patcher.js.map +1 -0
  31. package/dist/esm/register.js +132 -0
  32. package/dist/esm/register.js.map +1 -0
  33. package/dist/esm/store/ring-buffer.js +236 -0
  34. package/dist/esm/store/ring-buffer.js.map +1 -0
  35. package/dist/esm/test-setup.js +7 -0
  36. package/dist/esm/test-setup.js.map +1 -0
  37. package/dist/gui/assets/index.css +1 -0
  38. package/dist/gui/assets/index.js +40 -0
  39. package/dist/gui/index.html +14 -0
  40. package/dist/types/adapters/nextjs.d.ts +80 -0
  41. package/dist/types/adapters/nextjs.d.ts.map +1 -0
  42. package/dist/types/cdp/cdp-bridge.d.ts +86 -0
  43. package/dist/types/cdp/cdp-bridge.d.ts.map +1 -0
  44. package/dist/types/cli.d.ts +8 -0
  45. package/dist/types/cli.d.ts.map +1 -0
  46. package/dist/types/config.d.ts +57 -0
  47. package/dist/types/config.d.ts.map +1 -0
  48. package/dist/types/context/context-manager.d.ts +96 -0
  49. package/dist/types/context/context-manager.d.ts.map +1 -0
  50. package/dist/types/gui/browser-launcher.d.ts +52 -0
  51. package/dist/types/gui/browser-launcher.d.ts.map +1 -0
  52. package/dist/types/gui/event-bridge.d.ts +36 -0
  53. package/dist/types/gui/event-bridge.d.ts.map +1 -0
  54. package/dist/types/gui/port-utils.d.ts +25 -0
  55. package/dist/types/gui/port-utils.d.ts.map +1 -0
  56. package/dist/types/gui/server.d.ts +50 -0
  57. package/dist/types/gui/server.d.ts.map +1 -0
  58. package/dist/types/gui/websocket-hub.d.ts +67 -0
  59. package/dist/types/gui/websocket-hub.d.ts.map +1 -0
  60. package/dist/types/index.d.ts +44 -0
  61. package/dist/types/index.d.ts.map +1 -0
  62. package/dist/types/interceptors/http-patcher.d.ts +32 -0
  63. package/dist/types/interceptors/http-patcher.d.ts.map +1 -0
  64. package/dist/types/interceptors/undici-patcher.d.ts +37 -0
  65. package/dist/types/interceptors/undici-patcher.d.ts.map +1 -0
  66. package/dist/types/register.d.ts +18 -0
  67. package/dist/types/register.d.ts.map +1 -0
  68. package/dist/types/store/ring-buffer.d.ts +148 -0
  69. package/dist/types/store/ring-buffer.d.ts.map +1 -0
  70. package/dist/types/test-setup.d.ts +7 -0
  71. package/dist/types/test-setup.d.ts.map +1 -0
  72. package/package.json +103 -0
  73. package/templates/instrumentation.ts +32 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * 自动注册入口
3
+ *
4
+ * 使用方式:node -r node-network-devtools/register your-script.js
5
+ * 或:node --import node-network-devtools/register your-script.js
6
+ *
7
+ * 注意:Network 面板功能需要:
8
+ * - Node.js 20.18.0+ 版本
9
+ * - --experimental-network-inspection 标志
10
+ * - Chrome DevTools 目前还不支持显示 Network 事件(功能待实现)
11
+ */
12
+ import { getConfig } from './config.js';
13
+ import { getCDPBridge } from './cdp/cdp-bridge.js';
14
+ import { getRequestStore } from './store/ring-buffer.js';
15
+ import { getGUIServer } from './gui/server.js';
16
+ import { getEventBridge } from './gui/event-bridge.js';
17
+ export { getConfig, getRequestStore, getCDPBridge, getGUIServer, getEventBridge };
18
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAuC,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AA4HvD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * 环形缓冲区请求存储
3
+ *
4
+ * 高效存储和查询请求数据,自动覆盖旧条目
5
+ */
6
+ /**
7
+ * 响应数据
8
+ */
9
+ export interface ResponseData {
10
+ statusCode: number;
11
+ statusMessage: string;
12
+ headers: Record<string, string | string[]>;
13
+ body?: Buffer | string;
14
+ bodyTruncated?: boolean;
15
+ }
16
+ /**
17
+ * 错误数据
18
+ */
19
+ export interface ErrorData {
20
+ code: string;
21
+ message: string;
22
+ stack?: string;
23
+ }
24
+ /**
25
+ * 时序数据
26
+ */
27
+ export interface TimingData {
28
+ start: number;
29
+ dnsLookup?: number;
30
+ tcpConnection?: number;
31
+ tlsHandshake?: number;
32
+ firstByte?: number;
33
+ download?: number;
34
+ total: number;
35
+ }
36
+ /**
37
+ * 请求数据
38
+ */
39
+ export interface RequestData {
40
+ id: string;
41
+ traceId?: string;
42
+ url: string;
43
+ method: string;
44
+ headers: Record<string, string | string[]>;
45
+ body?: Buffer | string;
46
+ bodyTruncated?: boolean;
47
+ stackTrace: string;
48
+ timestamp: number;
49
+ response?: ResponseData;
50
+ error?: ErrorData;
51
+ timing?: TimingData;
52
+ }
53
+ /**
54
+ * 查询过滤器
55
+ */
56
+ export interface QueryFilter {
57
+ urlPattern?: RegExp | string;
58
+ statusCode?: number;
59
+ statusCodeMin?: number;
60
+ statusCodeMax?: number;
61
+ method?: string;
62
+ traceId?: string;
63
+ }
64
+ /**
65
+ * 请求存储接口
66
+ */
67
+ export interface IRequestStore {
68
+ add(request: RequestData): void;
69
+ updateResponse(id: string, response: ResponseData): void;
70
+ updateTiming(id: string, timing: TimingData): void;
71
+ updateError(id: string, error: ErrorData): void;
72
+ get(id: string): RequestData | undefined;
73
+ getByTraceId(traceId: string): RequestData[];
74
+ query(filter: QueryFilter): RequestData[];
75
+ clear(): void;
76
+ getAll(): RequestData[];
77
+ size(): number;
78
+ }
79
+ /**
80
+ * 环形缓冲区实现
81
+ */
82
+ declare class RingBufferStore implements IRequestStore {
83
+ private buffer;
84
+ private maxSize;
85
+ private maxBodySize;
86
+ private writeIndex;
87
+ private count;
88
+ private idMap;
89
+ constructor(maxSize?: number, maxBodySize?: number);
90
+ /**
91
+ * 截断过大的 body
92
+ */
93
+ private truncateBody;
94
+ /**
95
+ * 添加请求
96
+ */
97
+ add(request: RequestData): void;
98
+ /**
99
+ * 更新响应数据
100
+ */
101
+ updateResponse(id: string, response: ResponseData): void;
102
+ /**
103
+ * 更新时序数据
104
+ */
105
+ updateTiming(id: string, timing: TimingData): void;
106
+ /**
107
+ * 更新错误数据
108
+ */
109
+ updateError(id: string, error: ErrorData): void;
110
+ /**
111
+ * 根据 ID 获取请求
112
+ */
113
+ get(id: string): RequestData | undefined;
114
+ /**
115
+ * 根据 TraceID 获取所有相关请求
116
+ */
117
+ getByTraceId(traceId: string): RequestData[];
118
+ /**
119
+ * 查询请求
120
+ */
121
+ query(filter: QueryFilter): RequestData[];
122
+ /**
123
+ * 清空所有请求
124
+ */
125
+ clear(): void;
126
+ /**
127
+ * 获取所有请求(按时间倒序)
128
+ */
129
+ getAll(): RequestData[];
130
+ /**
131
+ * 获取当前存储的请求数量
132
+ */
133
+ size(): number;
134
+ }
135
+ /**
136
+ * 获取全局请求存储实例
137
+ */
138
+ export declare function getRequestStore(): IRequestStore;
139
+ /**
140
+ * 重置全局请求存储(用于测试)
141
+ */
142
+ export declare function resetRequestStore(): void;
143
+ /**
144
+ * 创建新的请求存储实例(用于测试)
145
+ */
146
+ export declare function createRequestStore(maxSize?: number, maxBodySize?: number): IRequestStore;
147
+ export { RingBufferStore as RequestStore };
148
+ //# sourceMappingURL=ring-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ring-buffer.d.ts","sourceRoot":"","sources":["../../../src/store/ring-buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Vitest 测试设置文件
3
+ *
4
+ * 这个文件在每个测试文件运行前执行
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=test-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../../src/test-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,103 @@
1
+ {
2
+ "name": "@mt0926/node-network-devtools",
3
+ "version": "0.1.0",
4
+ "description": "🔍 Node.js network request monitoring tool with Chrome DevTools integration and built-in Web GUI",
5
+ "type": "module",
6
+ "main": "./dist/esm/index.js",
7
+ "module": "./dist/esm/index.js",
8
+ "types": "./dist/types/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/esm/index.js",
12
+ "types": "./dist/types/index.d.ts"
13
+ },
14
+ "./register": {
15
+ "import": "./dist/esm/register.js"
16
+ }
17
+ },
18
+ "bin": {
19
+ "node-network-devtools": "./dist/esm/cli.js",
20
+ "nnd": "./dist/esm/cli.js"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "templates",
25
+ "README.md",
26
+ "LICENSE",
27
+ "BUILD.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "pnpm build:esm && pnpm build:types && pnpm build:gui",
31
+ "build:esm": "tsc -p tsconfig.esm.json",
32
+ "build:types": "tsc -p tsconfig.types.json",
33
+ "build:gui": "cd packages/gui && pnpm build",
34
+ "test": "vitest run",
35
+ "test:http": "npx tsx --test src/interceptors/http-patcher.node-test.mjs",
36
+ "test:undici": "npx tsx --test src/interceptors/undici-patcher.node-test.mjs",
37
+ "test:all": "pnpm test && pnpm test:http && pnpm test:undici",
38
+ "test:watch": "vitest",
39
+ "test:coverage": "vitest run --coverage",
40
+ "clean": "rimraf dist",
41
+ "format": "prettier --write \"src/**/*.{ts,js,json}\" \"packages/**/*.{ts,tsx,js,json}\"",
42
+ "format:check": "prettier --check \"src/**/*.{ts,js,json}\" \"packages/**/*.{ts,tsx,js,json}\"",
43
+ "prepublishOnly": "pnpm clean && pnpm build && pnpm test:all",
44
+ "prepack": "pnpm build",
45
+ "release:patch": "npm version patch && git push --follow-tags",
46
+ "release:minor": "npm version minor && git push --follow-tags",
47
+ "release:major": "npm version major && git push --follow-tags",
48
+ "setup": "node scripts/update-placeholders.js"
49
+ },
50
+ "keywords": [
51
+ "nodejs",
52
+ "network",
53
+ "devtools",
54
+ "debugging",
55
+ "chrome",
56
+ "cdp",
57
+ "fetch",
58
+ "http",
59
+ "inspector",
60
+ "monitoring",
61
+ "interceptor",
62
+ "websocket",
63
+ "gui",
64
+ "nextjs",
65
+ "express",
66
+ "request",
67
+ "response",
68
+ "trace"
69
+ ],
70
+ "author": "ddddd xx630133368@gmail.com",
71
+ "license": "MIT",
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "https://github.com/dong0926/node-network-devtools.git"
75
+ },
76
+ "bugs": {
77
+ "url": "https://github.com/dong0926/node-network-devtools/issues"
78
+ },
79
+ "homepage": "https://github.com/dong0926/node-network-devtools#readme",
80
+ "engines": {
81
+ "node": ">=18.0.0"
82
+ },
83
+ "devDependencies": {
84
+ "@types/node": "^20.10.0",
85
+ "@types/ws": "^8.5.13",
86
+ "fast-check": "^3.15.0",
87
+ "prettier": "^3.1.0",
88
+ "rimraf": "^5.0.5",
89
+ "tsx": "^4.21.0",
90
+ "typescript": "^5.3.0",
91
+ "vitest": "^1.1.0"
92
+ },
93
+ "dependencies": {
94
+ "@mswjs/interceptors": "^0.40.0",
95
+ "nanoid": "^5.0.4",
96
+ "open": "^10.1.0",
97
+ "undici": "^7.18.2",
98
+ "ws": "^8.18.0"
99
+ },
100
+ "optionalDependencies": {
101
+ "puppeteer": "^23.0.0"
102
+ }
103
+ }
@@ -0,0 +1,32 @@
1
+ // instrumentation.ts
2
+ // 将此文件放在 Next.js 项目根目录(与 app 或 pages 目录同级)
3
+ //
4
+ // 使用说明:
5
+ // 1. 复制此文件到你的 Next.js 项目根目录
6
+ // 2. 确保已安装 node-network-devtools: pnpm add node-network-devtools
7
+ // 3. 使用 --inspect 标志启动 Next.js: NODE_OPTIONS='--inspect' pnpm dev
8
+ // 4. 打开 Chrome DevTools (chrome://inspect) 查看网络请求
9
+
10
+ export async function register() {
11
+ // 仅在 Node.js 服务端运行时初始化
12
+ if (process.env.NEXT_RUNTIME === 'nodejs') {
13
+ try {
14
+ // 动态导入以避免客户端打包问题
15
+ const { install, setConfig } = await import('node-network-devtools');
16
+
17
+ // 可选:自定义配置
18
+ // setConfig({
19
+ // maxRequests: 500, // 最大存储请求数
20
+ // maxBodySize: 512 * 1024, // 最大 body 大小(512KB)
21
+ // redactHeaders: ['authorization', 'cookie', 'x-api-key'], // 脱敏的头
22
+ // });
23
+
24
+ await install();
25
+
26
+ console.log('[node-network-devtools] 已在 Next.js 服务端初始化');
27
+ console.log('[node-network-devtools] 打开 chrome://inspect 查看网络请求');
28
+ } catch (error) {
29
+ console.warn('[node-network-devtools] 初始化失败:', error);
30
+ }
31
+ }
32
+ }