@microbt/environment 1.2.10 → 1.2.12
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/.codex/plan//346/226/260/345/242/236-eu-cinmoore-/345/237/237/345/220/215/346/224/257/346/214/201.md +28 -0
- package/.codex/plan//346/226/260/345/242/236-eu-cinmoore-/347/216/257/345/242/203/347/255/226/347/225/245.md +21 -0
- package/README.md +9 -0
- package/dist/esm/environment/factory.js +2 -0
- package/dist/esm/environment/index.d.ts +0 -15
- package/dist/esm/environment/index.js +7 -27
- package/dist/esm/environment/strategies/eu-cinmoore.d.ts +7 -0
- package/dist/esm/environment/strategies/eu-cinmoore.js +42 -0
- package/dist/esm/gateway/factory.js +2 -0
- package/dist/esm/gateway/index.d.ts +1 -5
- package/dist/esm/gateway/index.js +10 -29
- package/dist/esm/gateway/strategies/eu-cinmoore.com.d.ts +4 -0
- package/dist/esm/gateway/strategies/eu-cinmoore.com.js +19 -0
- package/dist/esm/gateway/strategies/index.d.ts +1 -0
- package/dist/esm/gateway/strategies/index.js +1 -0
- package/dist/esm/global.d.ts +0 -1
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 新增 eu-cinmoore 域名支持
|
|
2
|
+
|
|
3
|
+
## 上下文
|
|
4
|
+
- 任务描述:需要基于新的域名规范, 更新environment 和 gateway 相关的代码. 新增了一批, 测试环境: iot-api-test.eu-cinmoore.com, iot-test.eu-cinmoore.com, 生产环境: api.eu-cinmoore.com, iot-api.eu-cinmoore.com, iot.eu-cinmoore.com
|
|
5
|
+
- 开始时间:2026-01-12 20:45:15
|
|
6
|
+
- 需求评分:7/10
|
|
7
|
+
|
|
8
|
+
## 选定方案
|
|
9
|
+
方案 1:新增独立域名策略(最小改动)
|
|
10
|
+
|
|
11
|
+
## 执行计划
|
|
12
|
+
1. 扩展支持域名列表(`src/environment/index.ts`)。
|
|
13
|
+
2. 注册环境策略(`src/environment/factory.ts`)。
|
|
14
|
+
3. 新增网关 URL 策略(`src/gateway/strategies/eu-cinmoore.com.ts`)。
|
|
15
|
+
4. 导出并注册网关策略(`src/gateway/strategies/index.ts`, `src/gateway/factory.ts`)。
|
|
16
|
+
5. 补充 environment 单测(`src/environment/index.test.ts`)。
|
|
17
|
+
6. 补充 gateway 单测(`src/gateway/index.test.ts`)。
|
|
18
|
+
7. 更新 README 说明(`README.md`)。
|
|
19
|
+
|
|
20
|
+
## 执行日志
|
|
21
|
+
- 2026-01-12 20:51:20 步骤1:完成 ✅(新增 eu-cinmoore.com 支持域名)
|
|
22
|
+
- 2026-01-12 20:51:20 步骤2:完成 ✅(注册环境策略)
|
|
23
|
+
- 2026-01-12 20:51:20 步骤3:完成 ✅(新增 EuCinmoore URL 策略)
|
|
24
|
+
- 2026-01-12 20:51:20 步骤4:完成 ✅(导出并注册 URL 策略)
|
|
25
|
+
- 2026-01-12 20:51:20 步骤5:完成 ✅(补充 environment 单测)
|
|
26
|
+
- 2026-01-12 20:51:20 步骤6:完成 ✅(补充 gateway 单测)
|
|
27
|
+
- 2026-01-12 20:51:20 步骤7:完成 ✅(更新 README 示例)
|
|
28
|
+
- 2026-01-12 20:54:19 测试:`npm test -- --watchman=false --runInBand` ✅
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 新增 eu-cinmoore 环境策略
|
|
2
|
+
|
|
3
|
+
## 上下文
|
|
4
|
+
- 任务描述:environment 也对称的加一个 strategy 吧. 后续单独维护.
|
|
5
|
+
- 开始时间:2026-01-12 21:05:27
|
|
6
|
+
- 需求评分:8/10
|
|
7
|
+
|
|
8
|
+
## 选定方案
|
|
9
|
+
方案 1:新增独立环境策略,逻辑保持一致
|
|
10
|
+
|
|
11
|
+
## 执行计划
|
|
12
|
+
1. 新增 EuCinmoore 环境策略类(`src/environment/strategies/eu-cinmoore.ts`)。
|
|
13
|
+
2. 工厂切换映射到新策略(`src/environment/factory.ts`)。
|
|
14
|
+
3. 测试确认(复用现有 eu-cinmoore 测试)。
|
|
15
|
+
4. 更新计划记录。
|
|
16
|
+
|
|
17
|
+
## 执行日志
|
|
18
|
+
- 2026-01-12 21:06:08 步骤1:完成 ✅(新增 EuCinmoore 环境策略类)
|
|
19
|
+
- 2026-01-12 21:06:08 步骤2:完成 ✅(工厂映射切换)
|
|
20
|
+
- 2026-01-12 21:06:08 步骤3:完成 ✅(复用现有测试覆盖)
|
|
21
|
+
- 2026-01-12 21:06:46 测试:`npm test -- --watchman=false --runInBand` ✅
|
package/README.md
CHANGED
|
@@ -82,6 +82,15 @@ baseUrl({ name: 'iot-api', path: '/saas' }); // => '//iot-api-cn-dev.superacme.c
|
|
|
82
82
|
// 美区 AWS 生产环境
|
|
83
83
|
// location.host: 'mall-us-aws.superacme.com'
|
|
84
84
|
baseUrl({ name: 'api' }); // => '//api-us-aws.superacme.com'
|
|
85
|
+
|
|
86
|
+
// Eu-Cinmoore 测试环境
|
|
87
|
+
// location.host: 'iot-test.eu-cinmoore.com'
|
|
88
|
+
baseUrl({ name: 'iot-api' }); // => '//iot-api-test.eu-cinmoore.com'
|
|
89
|
+
baseUrl({ name: 'iot-api', path: '/saas' }); // => '//iot-api-test.eu-cinmoore.com/saas'
|
|
90
|
+
|
|
91
|
+
// Eu-Cinmoore 生产环境
|
|
92
|
+
// location.host: 'iot.eu-cinmoore.com'
|
|
93
|
+
baseUrl({ name: 'iot-api' }); // => '//iot-api.eu-cinmoore.com'
|
|
85
94
|
```
|
|
86
95
|
|
|
87
96
|
## 混合应用相关函数
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/environment/factory.ts
|
|
2
2
|
import { CinmooreEnvironmentStrategy } from "./strategies/cinmoore";
|
|
3
3
|
import { CinvueEnvironmentStrategy } from "./strategies/cinvue";
|
|
4
|
+
import { EuCinmooreEnvironmentStrategy } from "./strategies/eu-cinmoore";
|
|
4
5
|
import { FronAIEnvironmentStrategy } from "./strategies/fronai";
|
|
5
6
|
import { LocalEnvironmentStrategy } from "./strategies/local";
|
|
6
7
|
import { Safio365EnvironmentStrategy } from "./strategies/safio365";
|
|
@@ -24,6 +25,7 @@ EnvironmentStrategyFactory.strategies = /* @__PURE__ */ new Map();
|
|
|
24
25
|
EnvironmentStrategyFactory.localStrategy = new LocalEnvironmentStrategy();
|
|
25
26
|
(() => {
|
|
26
27
|
_EnvironmentStrategyFactory.strategies.set("cinmoore.com", new CinmooreEnvironmentStrategy());
|
|
28
|
+
_EnvironmentStrategyFactory.strategies.set("eu-cinmoore.com", new EuCinmooreEnvironmentStrategy());
|
|
27
29
|
_EnvironmentStrategyFactory.strategies.set("cinmoore.cn", new CinmooreEnvironmentStrategy());
|
|
28
30
|
_EnvironmentStrategyFactory.strategies.set("cinvue.com", new CinvueEnvironmentStrategy());
|
|
29
31
|
_EnvironmentStrategyFactory.strategies.set("fronai.cn", new FronAIEnvironmentStrategy());
|
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
export declare const SUPPORTED_DOMAINS: string[];
|
|
2
|
-
/**
|
|
3
|
-
* 验证域名是否在支持列表中
|
|
4
|
-
* @param domain 要验证的域名
|
|
5
|
-
* @returns 有效的域名
|
|
6
|
-
* @throws 如果域名不在支持列表中
|
|
7
|
-
*/
|
|
8
|
-
export declare function validateDomain(domain: string): string;
|
|
9
|
-
/**
|
|
10
|
-
* 验证传入的域名是否有效
|
|
11
|
-
* 对于支持 region 的域名,必须是包含环境信息的完整域名(如二级域名)
|
|
12
|
-
* 对于不支持 region 的域名,根域名也是有效的
|
|
13
|
-
* @param domain 要验证的域名
|
|
14
|
-
* @returns 是否为有效域名
|
|
15
|
-
*/
|
|
16
|
-
export declare function validateDomainWithRegion(domain: string): boolean;
|
|
17
2
|
export declare function environment(): string;
|
|
18
3
|
export declare function region(): string;
|
|
19
4
|
export declare function isAWSDomain(): boolean;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { EnvironmentStrategyFactory } from "./factory";
|
|
3
3
|
var SUPPORTED_DOMAINS = [
|
|
4
4
|
"superacme.com",
|
|
5
|
+
"eu-cinmoore.com",
|
|
5
6
|
"cinmoore.com",
|
|
6
7
|
"cinmoore.cn",
|
|
7
8
|
"safio365.com",
|
|
@@ -13,35 +14,16 @@ var SUPPORTED_DOMAINS = [
|
|
|
13
14
|
"127.0.0.1",
|
|
14
15
|
"localhost"
|
|
15
16
|
];
|
|
16
|
-
function validateDomain(domain) {
|
|
17
|
-
const validDomain = SUPPORTED_DOMAINS.find((d) => domain.endsWith(d));
|
|
18
|
-
if (!validDomain) {
|
|
19
|
-
throw new Error(`Unsupported domain: ${domain}`);
|
|
20
|
-
}
|
|
21
|
-
return validDomain;
|
|
22
|
-
}
|
|
23
|
-
function validateDomainWithRegion(domain) {
|
|
24
|
-
try {
|
|
25
|
-
const validBaseDomain = validateDomain(domain);
|
|
26
|
-
const strategy = EnvironmentStrategyFactory.getStrategy(validBaseDomain);
|
|
27
|
-
if (!strategy.features.supportRegion) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
if (domain === validBaseDomain) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
const extractedRegion = strategy.getRegion(domain);
|
|
34
|
-
return extractedRegion !== "unknown";
|
|
35
|
-
} catch (e) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
17
|
function getCurrentDomain() {
|
|
40
18
|
if (typeof location === "undefined") {
|
|
41
19
|
throw new Error("location is not defined");
|
|
42
20
|
}
|
|
43
21
|
const host = location.host;
|
|
44
|
-
|
|
22
|
+
const domain = SUPPORTED_DOMAINS.find((d) => host.endsWith(d));
|
|
23
|
+
if (!domain) {
|
|
24
|
+
throw new Error(`Unsupported domain: ${host}`);
|
|
25
|
+
}
|
|
26
|
+
return domain;
|
|
45
27
|
}
|
|
46
28
|
function environment() {
|
|
47
29
|
try {
|
|
@@ -77,7 +59,5 @@ export {
|
|
|
77
59
|
SUPPORTED_DOMAINS,
|
|
78
60
|
environment,
|
|
79
61
|
isAWSDomain,
|
|
80
|
-
region
|
|
81
|
-
validateDomain,
|
|
82
|
-
validateDomainWithRegion
|
|
62
|
+
region
|
|
83
63
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/environment/strategies/eu-cinmoore.ts
|
|
2
|
+
var EuCinmooreEnvironmentStrategy = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.features = {
|
|
5
|
+
supportEnv: true,
|
|
6
|
+
supportRegion: false,
|
|
7
|
+
supportAWS: false
|
|
8
|
+
};
|
|
9
|
+
this.ENV_PATTERNS = {
|
|
10
|
+
// 匹配 -dev、-dev1、-dev-1、-dev. 等
|
|
11
|
+
dev: /-dev(?:\d*)?(?:-|\.|\b|$)/,
|
|
12
|
+
// 匹配 -test、-test1、-test-1、-test. 等
|
|
13
|
+
test: /-test(?:\d*)?(?:-|\.|\b|$)/,
|
|
14
|
+
// 匹配 -pre、-pre1、-pre-1、-pre. 等
|
|
15
|
+
pre: /-pre(?:\d*)?(?:-|\.|\b|$)/,
|
|
16
|
+
// 匹配 -gray、-gray1、-gray-1、-gray. 等
|
|
17
|
+
gray: /-gray(?:\d*)?(?:-|\.|\b|$)/,
|
|
18
|
+
// 本地环境
|
|
19
|
+
local: /^(localhost|127\.0\.0\.1|0\.0\.0\.0)(?::\d+)?$/
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
getEnvironment(host) {
|
|
23
|
+
if (this.ENV_PATTERNS.local.test(host)) {
|
|
24
|
+
return "local";
|
|
25
|
+
}
|
|
26
|
+
for (const [env, pattern] of Object.entries(this.ENV_PATTERNS)) {
|
|
27
|
+
if (pattern.test(host)) {
|
|
28
|
+
return env;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return "prod";
|
|
32
|
+
}
|
|
33
|
+
getRegion() {
|
|
34
|
+
return "unknown";
|
|
35
|
+
}
|
|
36
|
+
isAWS() {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
export {
|
|
41
|
+
EuCinmooreEnvironmentStrategy
|
|
42
|
+
};
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
CinmooreCnURLStrategy,
|
|
4
4
|
CinmooreComURLStrategy,
|
|
5
5
|
CinvueURLStrategy,
|
|
6
|
+
EuCinmooreComURLStrategy,
|
|
6
7
|
FronAiURLStrategy,
|
|
7
8
|
Safio365URLStrategy,
|
|
8
9
|
SensforgeURLStrategy,
|
|
@@ -23,6 +24,7 @@ URLStrategyFactory.strategies = /* @__PURE__ */ new Map();
|
|
|
23
24
|
(() => {
|
|
24
25
|
_URLStrategyFactory.strategies.set("cinmoore.cn", new CinmooreCnURLStrategy());
|
|
25
26
|
_URLStrategyFactory.strategies.set("cinmoore.com", new CinmooreComURLStrategy());
|
|
27
|
+
_URLStrategyFactory.strategies.set("eu-cinmoore.com", new EuCinmooreComURLStrategy());
|
|
26
28
|
_URLStrategyFactory.strategies.set("cinvue.com", new CinvueURLStrategy());
|
|
27
29
|
_URLStrategyFactory.strategies.set("fronai.cn", new FronAiURLStrategy());
|
|
28
30
|
_URLStrategyFactory.strategies.set("safio365.com", new Safio365URLStrategy());
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 根据当前域名生成基于 name 和 path 的 baseUrl
|
|
3
3
|
*
|
|
4
4
|
* @param params 配置参数
|
|
5
5
|
* @param params.name - 必填,API 服务名称(例如:'api', 'iot-api')
|
|
6
6
|
* @param params.path - 可选,API 路径(例如:'/saas')
|
|
7
|
-
* @param params.domain - 可选,指定域名(必须符合SUPPORTED_DOMAINS约束)
|
|
8
7
|
* @returns 生成的 URL。如果生成失败则返回传入的 path 值
|
|
9
8
|
*
|
|
10
9
|
* @example
|
|
@@ -12,7 +11,6 @@
|
|
|
12
11
|
* // 中国区开发环境
|
|
13
12
|
* baseUrl({ name: 'api' }) // => '//api-cn-dev.superacme.com'
|
|
14
13
|
* baseUrl({ name: 'iot-api', path: '/saas' }) // => '//iot-api-cn-dev.superacme.com/saas'
|
|
15
|
-
* baseUrl({ name: 'api', domain: 'superacme.com' }) // => '//api-cn-dev.superacme.com'
|
|
16
14
|
*
|
|
17
15
|
* // 美区 AWS 环境
|
|
18
16
|
* // location.host: 'mall-us-aws.superacme.com'
|
|
@@ -21,7 +19,6 @@
|
|
|
21
19
|
* // Safio365 域名系列
|
|
22
20
|
* // location.host: 'iot-dev.safio365.com'
|
|
23
21
|
* baseUrl({ name: 'iot-api', path: '/saas' }) // => '//iot-api-dev.safio365.com/saas'
|
|
24
|
-
* baseUrl({ name: 'iot-api', domain: 'safio365.com' }) // => '//iot-api-dev.safio365.com/saas'
|
|
25
22
|
*
|
|
26
23
|
* // Sensforge 域名系列
|
|
27
24
|
* // location.host: 'api-dev.sensforge.com'
|
|
@@ -33,5 +30,4 @@
|
|
|
33
30
|
export declare function baseUrl(params: {
|
|
34
31
|
name: string;
|
|
35
32
|
path?: string;
|
|
36
|
-
domain?: string;
|
|
37
33
|
}): string | undefined;
|
|
@@ -1,56 +1,37 @@
|
|
|
1
1
|
// src/gateway/index.ts
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
environment,
|
|
5
|
-
isAWSDomain,
|
|
6
|
-
region,
|
|
7
|
-
validateDomain,
|
|
8
|
-
validateDomainWithRegion
|
|
9
|
-
} from "../environment/index";
|
|
2
|
+
import { environment, isAWSDomain, region, SUPPORTED_DOMAINS } from "../environment/index";
|
|
10
3
|
import { URLStrategyFactory } from "./factory";
|
|
11
4
|
function getCurrentDomain() {
|
|
12
5
|
const host = location.host;
|
|
13
|
-
|
|
6
|
+
const domain = SUPPORTED_DOMAINS.find((domain2) => host.endsWith(domain2));
|
|
7
|
+
if (!domain) {
|
|
8
|
+
throw new Error(`Unsupported domain: ${host}`);
|
|
9
|
+
}
|
|
10
|
+
return domain;
|
|
14
11
|
}
|
|
15
12
|
function baseUrl(params) {
|
|
16
13
|
try {
|
|
17
14
|
if (!params.name) {
|
|
18
15
|
throw new Error("name parameter is required");
|
|
19
16
|
}
|
|
20
|
-
|
|
21
|
-
if (params.domain) {
|
|
22
|
-
if (!validateDomainWithRegion(params.domain)) {
|
|
23
|
-
const baseDomain = validateDomain(params.domain);
|
|
24
|
-
const strategy2 = EnvironmentStrategyFactory.getStrategy(baseDomain);
|
|
25
|
-
if (strategy2.features.supportRegion) {
|
|
26
|
-
throw new Error(
|
|
27
|
-
`Domain '${params.domain}' requires region information. Cannot determine region from root domain. Please provide a subdomain like 'api-cn-dev.${params.domain}' instead.`
|
|
28
|
-
);
|
|
29
|
-
} else {
|
|
30
|
-
throw new Error(`Invalid domain '${params.domain}'.`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
domain = validateDomain(params.domain);
|
|
34
|
-
} else {
|
|
35
|
-
domain = getCurrentDomain();
|
|
36
|
-
}
|
|
17
|
+
const domain = getCurrentDomain();
|
|
37
18
|
const strategy = URLStrategyFactory.getStrategy(domain);
|
|
38
19
|
const urlParams = {
|
|
39
20
|
name: params.name,
|
|
40
21
|
path: params.path || ""
|
|
41
22
|
};
|
|
42
23
|
if (strategy.features.supportEnv) {
|
|
43
|
-
const env =
|
|
24
|
+
const env = environment();
|
|
44
25
|
if (env === "unknown") {
|
|
45
26
|
return params.path;
|
|
46
27
|
}
|
|
47
28
|
urlParams.env = env;
|
|
48
29
|
}
|
|
49
30
|
if (strategy.features.supportRegion) {
|
|
50
|
-
urlParams.region =
|
|
31
|
+
urlParams.region = region();
|
|
51
32
|
}
|
|
52
33
|
if (strategy.features.supportAWS) {
|
|
53
|
-
urlParams.isAWS =
|
|
34
|
+
urlParams.isAWS = isAWSDomain();
|
|
54
35
|
}
|
|
55
36
|
return strategy.generateURL(urlParams);
|
|
56
37
|
} catch (error) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/gateway/strategies/eu-cinmoore.com.ts
|
|
2
|
+
var EuCinmooreComURLStrategy = class {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.features = {
|
|
5
|
+
supportEnv: true,
|
|
6
|
+
supportRegion: false,
|
|
7
|
+
supportAWS: false
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
generateURL({ name, env = "prod", path = "" }) {
|
|
11
|
+
if (env === "prod" || !env) {
|
|
12
|
+
return `//${name}.eu-cinmoore.com${path}`;
|
|
13
|
+
}
|
|
14
|
+
return `//${name}-${env}.eu-cinmoore.com${path}`;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
EuCinmooreComURLStrategy
|
|
19
|
+
};
|
package/dist/esm/global.d.ts
CHANGED