shennian 0.1.27 → 0.1.28
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/dist/src/region.d.ts +5 -8
- package/dist/src/region.d.ts.map +1 -1
- package/dist/src/region.js +68 -28
- package/dist/src/region.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/src/region.d.ts
CHANGED
|
@@ -3,15 +3,12 @@ export declare const SERVERS: Record<Region, {
|
|
|
3
3
|
url: string;
|
|
4
4
|
label: string;
|
|
5
5
|
}>;
|
|
6
|
-
export type ServerProbe = {
|
|
7
|
-
region: Region;
|
|
8
|
-
url: string;
|
|
9
|
-
label: string;
|
|
10
|
-
latencyMs: number | null;
|
|
11
|
-
};
|
|
12
6
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* Detect the best server region and return its URL.
|
|
8
|
+
*
|
|
9
|
+
* Strategy: timezone as primary signal, IP geolocation as supplement.
|
|
10
|
+
* - Chinese timezone → cn immediately (covers servers with UTC too via IP fallback).
|
|
11
|
+
* - Non-Chinese timezone → try IP to detect if physically in China.
|
|
15
12
|
*/
|
|
16
13
|
export declare function detectAndChooseServer(): Promise<string>;
|
|
17
14
|
export declare function urlToRegion(url: string): Region;
|
package/dist/src/region.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../src/region.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAA;AAEpC,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAGlE,CAAA;
|
|
1
|
+
{"version":3,"file":"region.d.ts","sourceRoot":"","sources":["../../src/region.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAA;AAEpC,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAGlE,CAAA;AA6CD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,MAAM,CAAC,CAyC7D;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD"}
|
package/dist/src/region.js
CHANGED
|
@@ -3,14 +3,29 @@ export const SERVERS = {
|
|
|
3
3
|
cn: { url: 'https://shennian.net', label: 'China (shennian.net)' },
|
|
4
4
|
global: { url: 'https://shennian.ai', label: 'Global (shennian.ai)' },
|
|
5
5
|
};
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
const CN_TIMEZONES = [
|
|
7
|
+
'Asia/Shanghai', 'Asia/Chongqing', 'Asia/Chungking',
|
|
8
|
+
'Asia/Harbin', 'Asia/Urumqi', 'PRC',
|
|
9
|
+
];
|
|
10
|
+
function inferRegionByTimezone() {
|
|
11
|
+
try {
|
|
12
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
13
|
+
if (CN_TIMEZONES.includes(tz))
|
|
14
|
+
return 'cn';
|
|
15
|
+
}
|
|
16
|
+
catch { /* Intl unavailable */ }
|
|
17
|
+
return 'global';
|
|
18
|
+
}
|
|
19
|
+
async function detectRegionByIP(timeoutMs = 1500) {
|
|
8
20
|
const controller = new AbortController();
|
|
9
21
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
10
|
-
const start = performance.now();
|
|
11
22
|
try {
|
|
12
|
-
|
|
13
|
-
|
|
23
|
+
const res = await Promise.any([
|
|
24
|
+
fetch(`${SERVERS.cn.url}/geo`, { signal: controller.signal }),
|
|
25
|
+
fetch(`${SERVERS.global.url}/geo`, { signal: controller.signal }),
|
|
26
|
+
]);
|
|
27
|
+
const data = await res.json();
|
|
28
|
+
return data.country === 'CN' ? 'cn' : 'global';
|
|
14
29
|
}
|
|
15
30
|
catch {
|
|
16
31
|
return null;
|
|
@@ -19,37 +34,62 @@ async function measureLatency(url, timeoutMs = 5000) {
|
|
|
19
34
|
clearTimeout(timer);
|
|
20
35
|
}
|
|
21
36
|
}
|
|
22
|
-
async function
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return a.latencyMs - b.latencyMs;
|
|
36
|
-
});
|
|
37
|
+
async function verifyReachable(url, timeoutMs = 3000) {
|
|
38
|
+
const controller = new AbortController();
|
|
39
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
40
|
+
try {
|
|
41
|
+
await fetch(`${url}/health`, { signal: controller.signal });
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
}
|
|
37
50
|
}
|
|
38
51
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
52
|
+
* Detect the best server region and return its URL.
|
|
53
|
+
*
|
|
54
|
+
* Strategy: timezone as primary signal, IP geolocation as supplement.
|
|
55
|
+
* - Chinese timezone → cn immediately (covers servers with UTC too via IP fallback).
|
|
56
|
+
* - Non-Chinese timezone → try IP to detect if physically in China.
|
|
41
57
|
*/
|
|
42
58
|
export async function detectAndChooseServer() {
|
|
43
59
|
console.log(chalk.gray(' Detecting best server...'));
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
const tzRegion = inferRegionByTimezone();
|
|
61
|
+
if (tzRegion === 'cn') {
|
|
62
|
+
const reachable = await verifyReachable(SERVERS.cn.url);
|
|
63
|
+
if (reachable) {
|
|
64
|
+
console.log(chalk.gray(` Using ${SERVERS.cn.label} (timezone: China)`));
|
|
65
|
+
return SERVERS.cn.url;
|
|
66
|
+
}
|
|
67
|
+
const fallback = await verifyReachable(SERVERS.global.url);
|
|
68
|
+
if (fallback) {
|
|
69
|
+
console.log(chalk.gray(` Using ${SERVERS.global.label} (cn unreachable, fallback)`));
|
|
70
|
+
return SERVERS.global.url;
|
|
71
|
+
}
|
|
47
72
|
console.error(chalk.red(' Error: cannot reach any server.'));
|
|
48
73
|
process.exit(1);
|
|
49
74
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
// Non-CN timezone: check IP to catch servers in China with UTC timezone
|
|
76
|
+
const ipRegion = await detectRegionByIP();
|
|
77
|
+
const region = ipRegion ?? tzRegion;
|
|
78
|
+
const reachable = await verifyReachable(SERVERS[region].url);
|
|
79
|
+
if (reachable) {
|
|
80
|
+
const source = ipRegion ? 'IP geolocation' : 'timezone';
|
|
81
|
+
console.log(chalk.gray(` Using ${SERVERS[region].label} (${source})`));
|
|
82
|
+
return SERVERS[region].url;
|
|
83
|
+
}
|
|
84
|
+
// Fallback to the other server
|
|
85
|
+
const other = region === 'cn' ? 'global' : 'cn';
|
|
86
|
+
const fallback = await verifyReachable(SERVERS[other].url);
|
|
87
|
+
if (fallback) {
|
|
88
|
+
console.log(chalk.gray(` Using ${SERVERS[other].label} (fallback)`));
|
|
89
|
+
return SERVERS[other].url;
|
|
90
|
+
}
|
|
91
|
+
console.error(chalk.red(' Error: cannot reach any server.'));
|
|
92
|
+
process.exit(1);
|
|
53
93
|
}
|
|
54
94
|
export function urlToRegion(url) {
|
|
55
95
|
return url.includes('shennian.net') ? 'cn' : 'global';
|
package/dist/src/region.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../src/region.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,MAAM,CAAC,MAAM,OAAO,GAAmD;IACrE,EAAE,EAAM,EAAE,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,uBAAuB,EAAE;IACvE,MAAM,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAG,KAAK,EAAE,sBAAsB,EAAE;CACvE,CAAA;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"region.js","sourceRoot":"","sources":["../../src/region.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,MAAM,CAAC,MAAM,OAAO,GAAmD;IACrE,EAAE,EAAM,EAAE,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,uBAAuB,EAAE;IACvE,MAAM,EAAE,EAAE,GAAG,EAAE,qBAAqB,EAAG,KAAK,EAAE,sBAAsB,EAAE;CACvE,CAAA;AAED,MAAM,YAAY,GAAG;IACnB,eAAe,EAAE,gBAAgB,EAAE,gBAAgB;IACnD,aAAa,EAAE,aAAa,EAAE,KAAK;CACpC,CAAA;AAED,SAAS,qBAAqB;IAC5B,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAA;QAC3D,IAAI,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAA;IAC5C,CAAC;IAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,CAAC;IAClC,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,SAAS,GAAG,IAAI;IAC9C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;IAC7D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC5B,KAAK,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;YAC7D,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;SAClE,CAAC,CAAA;QACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAA0B,CAAA;QACrD,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,SAAS,GAAG,IAAI;IAC1D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAA;IAC7D,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,GAAG,SAAS,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3D,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;IACrB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAA;IAErD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IAExC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;QACvD,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,EAAE,CAAC,KAAK,oBAAoB,CAAC,CAAC,CAAA;YACxE,OAAO,OAAO,CAAC,EAAE,CAAC,GAAG,CAAA;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC1D,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,CAAC,KAAK,6BAA6B,CAAC,CAAC,CAAA;YACrF,OAAO,OAAO,CAAC,MAAM,CAAC,GAAG,CAAA;QAC3B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAA;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,wEAAwE;IACxE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,EAAE,CAAA;IACzC,MAAM,MAAM,GAAG,QAAQ,IAAI,QAAQ,CAAA;IAEnC,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAA;IAC5D,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAA;QACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,CAAA;QACvE,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAA;IAC5B,CAAC;IAED,+BAA+B;IAC/B,MAAM,KAAK,GAAW,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA;IACvD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1D,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAA;QACrE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAA;IAC3B,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAA;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAA;AACvD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAA;AAC5B,CAAC"}
|