network-speed-js 1.0.0 → 1.0.2

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  <div align="center">
4
4
 
5
- 一个基于 **Performance API** 的现代化网速测试 SDK,支持内外网自动检测、资源监听和完整的 TypeScript 类型支持。
5
+ 一个基于 **Performance API** 的现代化网速测试 SDK,支持内外网自动检测、资源监听和完整的 TS 类型支持。
6
6
 
7
7
  **框架无关 · 开箱即用 · 准确可靠**
8
8
 
@@ -471,7 +471,7 @@ location /speed-test.bin {
471
471
  add_header Pragma "no-cache";
472
472
  add_header Expires "0";
473
473
 
474
- # 设置内容类型
474
+ # 设置内容类型(根据实际文件类型调整)
475
475
  add_header Content-Type "application/octet-stream";
476
476
 
477
477
  # 启用 CORS
@@ -489,10 +489,17 @@ dd if=/dev/urandom of=speed-test.bin bs=1024 count=500
489
489
 
490
490
  **测速文件建议:**
491
491
  - 文件大小:200KB ~ 1MB
492
+ - 文件类型:任意(.bin、.jpg、.png、.json、.txt 等)
492
493
  - 禁用缓存
493
494
  - 启用 CORS
494
495
  - 使用 CDN 分发
495
496
 
497
+ **支持的资源类型:**
498
+ - ✅ 二进制文件(.bin)
499
+ - ✅ 图片文件(.jpg、.png、.webp)
500
+ - ✅ 文本文件(.txt、.json)
501
+ - ✅ 任何可通过 HTTP 访问的资源
502
+
496
503
  ### 配置项详解
497
504
 
498
505
  #### intranetUrl
@@ -0,0 +1,21 @@
1
+ import type { ResourceSpeedInfo } from './types';
2
+ /**
3
+ * 计算单个资源的下载速度
4
+ */
5
+ export declare function calcSpeedByResource(entry: PerformanceResourceTiming): ResourceSpeedInfo | null;
6
+ /**
7
+ * 获取所有资源的测速信息
8
+ */
9
+ export declare function getAllResourcesSpeeds(): ResourceSpeedInfo[];
10
+ /**
11
+ * 清除指定URL的性能记录
12
+ */
13
+ export declare function clearPerformanceEntry(url: string): void;
14
+ /**
15
+ * 评估网络类型
16
+ */
17
+ export declare function evaluateNetworkType(speedMbps: number, thresholds?: {
18
+ fast: number;
19
+ medium: number;
20
+ }): 'fast' | 'medium' | 'slow' | 'unknown';
21
+ //# sourceMappingURL=performance-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance-utils.d.ts","sourceRoot":"","sources":["../../src/core/performance-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,yBAAyB,GAC/B,iBAAiB,GAAG,IAAI,CAoB1B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,iBAAiB,EAAE,CAU3D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAKvD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,UAAU;;;CAA0B,GACnC,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CASxC"}
@@ -0,0 +1,34 @@
1
+ import type { SpeedTestOptions, SpeedTestResult, ResourceSpeedInfo } from './types';
2
+ /**
3
+ * 网速测试 SDK
4
+ */
5
+ export declare class NetworkSpeedSDK {
6
+ private tester;
7
+ constructor(options?: SpeedTestOptions);
8
+ /**
9
+ * 执行网速测试
10
+ */
11
+ test(): Promise<SpeedTestResult>;
12
+ /**
13
+ * 获取所有已加载资源的速度信息
14
+ */
15
+ getAllResourcesSpeeds(): ResourceSpeedInfo[];
16
+ /**
17
+ * 监听特定资源的性能数据
18
+ */
19
+ observeResource(urlPattern: string, callback: (entry: PerformanceResourceTiming) => void): () => void;
20
+ /**
21
+ * 更新配置
22
+ */
23
+ updateOptions(options: Partial<SpeedTestOptions>): void;
24
+ /**
25
+ * 销毁SDK实例
26
+ */
27
+ destroy(): void;
28
+ }
29
+ /**
30
+ * 创建SDK实例的工厂函数
31
+ */
32
+ export declare function createNetworkSpeedSDK(options?: SpeedTestOptions): NetworkSpeedSDK;
33
+ export default NetworkSpeedSDK;
34
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/core/sdk.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEpF;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAc;gBAEhB,OAAO,GAAE,gBAAqB;IAI1C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC;IAItC;;OAEG;IACH,qBAAqB,IAAI,iBAAiB,EAAE;IAI5C;;OAEG;IACH,eAAe,CACb,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,GACnD,MAAM,IAAI;IAIb;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAIvD;;OAEG;IACH,OAAO,IAAI,IAAI;CAGhB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAEjF;AAGD,eAAe,eAAe,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { SpeedTestResult, SpeedTestOptions, PerformanceEntryCallback } from './types';
2
+ /**
3
+ * 网速测试核心类
4
+ */
5
+ export declare class SpeedTester {
6
+ private options;
7
+ private observer;
8
+ constructor(options?: SpeedTestOptions);
9
+ /**
10
+ * 执行测速
11
+ */
12
+ test(): Promise<SpeedTestResult>;
13
+ /**
14
+ * 自动检测内外网并测速
15
+ */
16
+ private testWithAutoDetect;
17
+ /**
18
+ * 测试单个URL
19
+ */
20
+ private testSingleUrl;
21
+ /**
22
+ * 监听特定资源的性能数据
23
+ */
24
+ observeResource(urlPattern: string, callback: PerformanceEntryCallback): () => void;
25
+ /**
26
+ * 更新配置
27
+ */
28
+ updateOptions(options: Partial<SpeedTestOptions>): void;
29
+ /**
30
+ * 销毁实例
31
+ */
32
+ destroy(): void;
33
+ }
34
+ //# sourceMappingURL=speed-tester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"speed-tester.d.ts","sourceRoot":"","sources":["../../src/core/speed-tester.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,QAAQ,CAAoC;gBAExC,OAAO,GAAE,gBAAqB;IAU1C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC;IAQtC;;OAEG;YACW,kBAAkB;IAehC;;OAEG;IACH,OAAO,CAAC,aAAa;IAuErB;;OAEG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,wBAAwB,GAAG,MAAM,IAAI;IAkBnF;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAIvD;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * 网速测试结果
3
+ */
4
+ export interface SpeedTestResult {
5
+ /** 下载速度 (Mbps) */
6
+ speedMbps: number;
7
+ /** 下载速度 (KB/s) */
8
+ speedKBps: number;
9
+ /** 网络类型评估 */
10
+ networkType: 'fast' | 'medium' | 'slow' | 'unknown';
11
+ /** 是否为内网 */
12
+ isIntranet: boolean;
13
+ /** 测试耗时 (ms) */
14
+ duration: number;
15
+ /** 传输大小 (bytes) */
16
+ transferSize: number;
17
+ /** 测试资源URL */
18
+ resourceUrl: string;
19
+ }
20
+ /**
21
+ * 资源测速信息
22
+ */
23
+ export interface ResourceSpeedInfo {
24
+ /** 资源名称 */
25
+ name: string;
26
+ /** 下载速度 (Mbps) */
27
+ speedMbps: number;
28
+ /** 下载速度 (KB/s) */
29
+ speedKBps: number;
30
+ /** 下载时间 (ms) */
31
+ downloadTime: number;
32
+ /** 传输大小 (bytes) */
33
+ transferSize: number;
34
+ }
35
+ /**
36
+ * SDK配置选项
37
+ */
38
+ export interface SpeedTestOptions {
39
+ /** 内网测速资源URL */
40
+ intranetUrl?: string;
41
+ /** 外网测速资源URL */
42
+ internetUrl?: string;
43
+ /** 超时时间 (ms) */
44
+ timeout?: number;
45
+ /** 是否自动检测内外网 */
46
+ autoDetect?: boolean;
47
+ /** 网速评估阈值 (Mbps) */
48
+ thresholds?: {
49
+ fast: number;
50
+ medium: number;
51
+ };
52
+ }
53
+ /**
54
+ * Performance Observer 回调参数
55
+ */
56
+ export interface PerformanceEntryCallback {
57
+ (entry: PerformanceResourceTiming): void;
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa;IACb,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;IACpD,YAAY;IACZ,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oBAAoB;IACpB,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,CAAC,KAAK,EAAE,yBAAyB,GAAG,IAAI,CAAC;CAC1C"}
@@ -0,0 +1,4 @@
1
+ export * from './core/sdk';
2
+ export type { SpeedTestResult, SpeedTestOptions, ResourceSpeedInfo, PerformanceEntryCallback, } from './core/types';
3
+ export { calcSpeedByResource, getAllResourcesSpeeds, evaluateNetworkType, } from './core/performance-utils';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAG3B,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC"}
@@ -1,36 +1,33 @@
1
- var h = Object.defineProperty;
2
- var S = (t, e, r) => e in t ? h(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
3
- var u = (t, e, r) => S(t, typeof e != "symbol" ? e + "" : e, r);
4
- function d(t) {
1
+ function f(t) {
5
2
  const e = t.responseEnd - t.responseStart;
6
3
  if (e <= 0 || t.transferSize === 0)
7
4
  return null;
8
- const r = t.transferSize * 8 / e / 1e3, s = t.transferSize / e;
5
+ const r = t.transferSize * 8 / e / 1e3, n = t.transferSize / e;
9
6
  return {
10
7
  name: t.name,
11
8
  speedMbps: Number(r.toFixed(2)),
12
- speedKBps: Number(s.toFixed(2)),
9
+ speedKBps: Number(n.toFixed(2)),
13
10
  downloadTime: Number(e.toFixed(2)),
14
11
  transferSize: t.transferSize
15
12
  };
16
13
  }
17
- function y() {
14
+ function p() {
18
15
  return performance.getEntriesByType("resource").filter(
19
16
  (e) => e instanceof PerformanceResourceTiming && e.transferSize > 0
20
- ).map(d).filter((e) => e !== null);
17
+ ).map(f).filter((e) => e !== null);
21
18
  }
22
- function b(t) {
19
+ function m(t) {
23
20
  performance.getEntriesByName(t).forEach(() => {
24
21
  performance.clearResourceTimings();
25
22
  });
26
23
  }
27
- function w(t, e = { fast: 10, medium: 2 }) {
24
+ function h(t, e = { fast: 10, medium: 2 }) {
28
25
  return t >= e.fast ? "fast" : t >= e.medium ? "medium" : t > 0 ? "slow" : "unknown";
29
26
  }
30
- class T {
27
+ class b {
28
+ options;
29
+ observer = null;
31
30
  constructor(e = {}) {
32
- u(this, "options");
33
- u(this, "observer", null);
34
31
  this.options = {
35
32
  intranetUrl: e.intranetUrl || "",
36
33
  internetUrl: e.internetUrl || "",
@@ -61,50 +58,58 @@ class T {
61
58
  * 测试单个URL
62
59
  */
63
60
  testSingleUrl(e, r) {
64
- return new Promise((s, i) => {
65
- const n = `${e}?t=${Date.now()}`;
66
- b(n);
67
- const c = new PerformanceObserver((f) => {
68
- for (const l of f.getEntries())
69
- if (l.entryType === "resource" && l.name.includes(e)) {
70
- const o = d(l);
71
- if (o) {
72
- const m = {
73
- speedMbps: o.speedMbps,
74
- speedKBps: o.speedKBps,
75
- networkType: w(
76
- o.speedMbps,
61
+ return new Promise((n, c) => {
62
+ const o = `${e}?t=${Date.now()}`;
63
+ m(o);
64
+ const u = new PerformanceObserver((s) => {
65
+ for (const a of s.getEntries())
66
+ if (a.entryType === "resource" && a.name.includes(e)) {
67
+ const i = f(a);
68
+ if (i) {
69
+ const d = {
70
+ speedMbps: i.speedMbps,
71
+ speedKBps: i.speedKBps,
72
+ networkType: h(
73
+ i.speedMbps,
77
74
  this.options.thresholds
78
75
  ),
79
76
  isIntranet: r,
80
- duration: o.downloadTime,
81
- transferSize: o.transferSize,
77
+ duration: i.downloadTime,
78
+ transferSize: i.transferSize,
82
79
  resourceUrl: e
83
80
  };
84
- c.disconnect(), s(m);
81
+ u.disconnect(), n(d);
85
82
  }
86
83
  }
87
84
  });
88
- c.observe({ entryTypes: ["resource"] });
89
- const a = new Image(), p = setTimeout(() => {
90
- c.disconnect(), i(new Error(`测速超时: ${e}`));
85
+ u.observe({ entryTypes: ["resource"] });
86
+ const l = setTimeout(() => {
87
+ u.disconnect(), c(new Error(`测速超时: ${e}`));
91
88
  }, this.options.timeout);
92
- a.onload = () => {
93
- clearTimeout(p);
94
- }, a.onerror = () => {
95
- clearTimeout(p), c.disconnect(), i(new Error(`资源加载失败: ${e}`));
96
- }, a.src = n;
89
+ fetch(o, {
90
+ method: "GET",
91
+ cache: "no-store"
92
+ // 禁用缓存
93
+ }).then((s) => {
94
+ if (!s.ok)
95
+ throw new Error(`HTTP error! status: ${s.status}`);
96
+ return s.blob();
97
+ }).then(() => {
98
+ clearTimeout(l);
99
+ }).catch((s) => {
100
+ clearTimeout(l), u.disconnect(), c(new Error(`资源加载失败: ${s.message}`));
101
+ });
97
102
  });
98
103
  }
99
104
  /**
100
105
  * 监听特定资源的性能数据
101
106
  */
102
107
  observeResource(e, r) {
103
- const s = new PerformanceObserver((i) => {
104
- for (const n of i.getEntries())
105
- n.entryType === "resource" && n.name.includes(e) && r(n);
108
+ const n = new PerformanceObserver((c) => {
109
+ for (const o of c.getEntries())
110
+ o.entryType === "resource" && o.name.includes(e) && r(o);
106
111
  });
107
- return s.observe({ entryTypes: ["resource"] }), () => s.disconnect();
112
+ return n.observe({ entryTypes: ["resource"] }), () => n.disconnect();
108
113
  }
109
114
  /**
110
115
  * 更新配置
@@ -119,10 +124,10 @@ class T {
119
124
  this.observer && (this.observer.disconnect(), this.observer = null);
120
125
  }
121
126
  }
122
- class g {
127
+ class S {
128
+ tester;
123
129
  constructor(e = {}) {
124
- u(this, "tester");
125
- this.tester = new T(e);
130
+ this.tester = new b(e);
126
131
  }
127
132
  /**
128
133
  * 执行网速测试
@@ -134,7 +139,7 @@ class g {
134
139
  * 获取所有已加载资源的速度信息
135
140
  */
136
141
  getAllResourcesSpeeds() {
137
- return y();
142
+ return p();
138
143
  }
139
144
  /**
140
145
  * 监听特定资源的性能数据
@@ -155,13 +160,13 @@ class g {
155
160
  this.tester.destroy();
156
161
  }
157
162
  }
158
- function E(t) {
159
- return new g(t);
163
+ function y(t) {
164
+ return new S(t);
160
165
  }
161
166
  export {
162
- g as NetworkSpeedSDK,
163
- d as calcSpeedByResource,
164
- E as createNetworkSpeedSDK,
165
- w as evaluateNetworkType,
166
- y as getAllResourcesSpeeds
167
+ S as NetworkSpeedSDK,
168
+ f as calcSpeedByResource,
169
+ y as createNetworkSpeedSDK,
170
+ h as evaluateNetworkType,
171
+ p as getAllResourcesSpeeds
167
172
  };
@@ -1 +1 @@
1
- (function(r,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(r=typeof globalThis<"u"?globalThis:r||self,s(r.NetworkSpeedJS={}))})(this,function(r){"use strict";var v=Object.defineProperty;var U=(r,s,n)=>s in r?v(r,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):r[s]=n;var d=(r,s,n)=>U(r,typeof s!="symbol"?s+"":s,n);function s(t){const e=t.responseEnd-t.responseStart;if(e<=0||t.transferSize===0)return null;const o=t.transferSize*8/e/1e3,i=t.transferSize/e;return{name:t.name,speedMbps:Number(o.toFixed(2)),speedKBps:Number(i.toFixed(2)),downloadTime:Number(e.toFixed(2)),transferSize:t.transferSize}}function n(){return performance.getEntriesByType("resource").filter(e=>e instanceof PerformanceResourceTiming&&e.transferSize>0).map(s).filter(e=>e!==null)}function y(t){performance.getEntriesByName(t).forEach(()=>{performance.clearResourceTimings()})}function m(t,e={fast:10,medium:2}){return t>=e.fast?"fast":t>=e.medium?"medium":t>0?"slow":"unknown"}class w{constructor(e={}){d(this,"options");d(this,"observer",null);this.options={intranetUrl:e.intranetUrl||"",internetUrl:e.internetUrl||"",timeout:e.timeout||1e4,autoDetect:e.autoDetect??!0,thresholds:e.thresholds||{fast:10,medium:2}}}async test(){return this.options.autoDetect?this.testWithAutoDetect():this.testSingleUrl(this.options.internetUrl,!1)}async testWithAutoDetect(){if(this.options.intranetUrl)try{return await this.testSingleUrl(this.options.intranetUrl,!0)}catch{console.log("内网测速失败,切换到外网测速")}return this.testSingleUrl(this.options.internetUrl,!1)}testSingleUrl(e,o){return new Promise((i,a)=>{const c=`${e}?t=${Date.now()}`;y(c);const l=new PerformanceObserver(T=>{for(const p of T.getEntries())if(p.entryType==="resource"&&p.name.includes(e)){const u=s(p);if(u){const g={speedMbps:u.speedMbps,speedKBps:u.speedKBps,networkType:m(u.speedMbps,this.options.thresholds),isIntranet:o,duration:u.downloadTime,transferSize:u.transferSize,resourceUrl:e};l.disconnect(),i(g)}}});l.observe({entryTypes:["resource"]});const f=new Image,S=setTimeout(()=>{l.disconnect(),a(new Error(`测速超时: ${e}`))},this.options.timeout);f.onload=()=>{clearTimeout(S)},f.onerror=()=>{clearTimeout(S),l.disconnect(),a(new Error(`资源加载失败: ${e}`))},f.src=c})}observeResource(e,o){const i=new PerformanceObserver(a=>{for(const c of a.getEntries())c.entryType==="resource"&&c.name.includes(e)&&o(c)});return i.observe({entryTypes:["resource"]}),()=>i.disconnect()}updateOptions(e){this.options={...this.options,...e}}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null)}}class h{constructor(e={}){d(this,"tester");this.tester=new w(e)}async test(){return this.tester.test()}getAllResourcesSpeeds(){return n()}observeResource(e,o){return this.tester.observeResource(e,o)}updateOptions(e){this.tester.updateOptions(e)}destroy(){this.tester.destroy()}}function b(t){return new h(t)}r.NetworkSpeedSDK=h,r.calcSpeedByResource=s,r.createNetworkSpeedSDK=b,r.evaluateNetworkType=m,r.getAllResourcesSpeeds=n,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
1
+ (function(r,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(r=typeof globalThis<"u"?globalThis:r||self,s(r.NetworkSpeedJS={}))})(this,(function(r){"use strict";function s(t){const e=t.responseEnd-t.responseStart;if(e<=0||t.transferSize===0)return null;const n=t.transferSize*8/e/1e3,i=t.transferSize/e;return{name:t.name,speedMbps:Number(n.toFixed(2)),speedKBps:Number(i.toFixed(2)),downloadTime:Number(e.toFixed(2)),transferSize:t.transferSize}}function f(){return performance.getEntriesByType("resource").filter(e=>e instanceof PerformanceResourceTiming&&e.transferSize>0).map(s).filter(e=>e!==null)}function S(t){performance.getEntriesByName(t).forEach(()=>{performance.clearResourceTimings()})}function p(t,e={fast:10,medium:2}){return t>=e.fast?"fast":t>=e.medium?"medium":t>0?"slow":"unknown"}class y{options;observer=null;constructor(e={}){this.options={intranetUrl:e.intranetUrl||"",internetUrl:e.internetUrl||"",timeout:e.timeout||1e4,autoDetect:e.autoDetect??!0,thresholds:e.thresholds||{fast:10,medium:2}}}async test(){return this.options.autoDetect?this.testWithAutoDetect():this.testSingleUrl(this.options.internetUrl,!1)}async testWithAutoDetect(){if(this.options.intranetUrl)try{return await this.testSingleUrl(this.options.intranetUrl,!0)}catch{console.log("内网测速失败,切换到外网测速")}return this.testSingleUrl(this.options.internetUrl,!1)}testSingleUrl(e,n){return new Promise((i,a)=>{const c=`${e}?t=${Date.now()}`;S(c);const l=new PerformanceObserver(o=>{for(const d of o.getEntries())if(d.entryType==="resource"&&d.name.includes(e)){const u=s(d);if(u){const w={speedMbps:u.speedMbps,speedKBps:u.speedKBps,networkType:p(u.speedMbps,this.options.thresholds),isIntranet:n,duration:u.downloadTime,transferSize:u.transferSize,resourceUrl:e};l.disconnect(),i(w)}}});l.observe({entryTypes:["resource"]});const h=setTimeout(()=>{l.disconnect(),a(new Error(`测速超时: ${e}`))},this.options.timeout);fetch(c,{method:"GET",cache:"no-store"}).then(o=>{if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);return o.blob()}).then(()=>{clearTimeout(h)}).catch(o=>{clearTimeout(h),l.disconnect(),a(new Error(`资源加载失败: ${o.message}`))})})}observeResource(e,n){const i=new PerformanceObserver(a=>{for(const c of a.getEntries())c.entryType==="resource"&&c.name.includes(e)&&n(c)});return i.observe({entryTypes:["resource"]}),()=>i.disconnect()}updateOptions(e){this.options={...this.options,...e}}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null)}}class m{tester;constructor(e={}){this.tester=new y(e)}async test(){return this.tester.test()}getAllResourcesSpeeds(){return f()}observeResource(e,n){return this.tester.observeResource(e,n)}updateOptions(e){this.tester.updateOptions(e)}destroy(){this.tester.destroy()}}function b(t){return new m(t)}r.NetworkSpeedSDK=m,r.calcSpeedByResource=s,r.createNetworkSpeedSDK=b,r.evaluateNetworkType=p,r.getAllResourcesSpeeds=f,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "network-speed-js",
3
3
  "private": false,
4
4
  "description": "A framework-agnostic network speed testing SDK based on Performance API with intranet/internet auto-detection support",
5
- "version": "1.0.0",
5
+ "version": "1.0.2",
6
6
  "author": "Sunny-117",
7
7
  "license": "MIT",
8
8
  "keywords": [
@@ -28,15 +28,19 @@
28
28
  ],
29
29
  "exports": {
30
30
  ".": {
31
+ "types": "./dist/index.d.ts",
31
32
  "import": "./dist/network-speed-js.js",
32
- "require": "./dist/network-speed-js.umd.js",
33
- "types": "./dist/index.d.ts"
33
+ "require": "./dist/network-speed-js.umd.js"
34
34
  }
35
35
  },
36
36
  "scripts": {
37
37
  "dev": "vite",
38
- "build": "vite build",
38
+ "build": "npm run build:lib && npm run build:types",
39
+ "build:lib": "vite build --mode lib",
40
+ "build:types": "tsc --project tsconfig.build.json",
41
+ "build:demo": "vite build",
39
42
  "preview": "vite preview",
43
+ "deploy": "sh deploy.sh",
40
44
  "prepublishOnly": "npm run build"
41
45
  },
42
46
  "peerDependencies": {
@@ -47,10 +51,10 @@
47
51
  },
48
52
  "devDependencies": {
49
53
  "@types/node": "^25.0.10",
50
- "@vitejs/plugin-vue": "^4.5.2",
51
- "typescript": "^5.2.2",
52
- "vite": "^5.0.8",
53
- "vue-tsc": "^1.8.25"
54
+ "@vitejs/plugin-vue": "^6.0.3",
55
+ "typescript": "^5.9.3",
56
+ "vite": "^7.3.1",
57
+ "vue-tsc": "^3.2.3"
54
58
  },
55
59
  "repository": {
56
60
  "type": "git",