@be-link/shield-for-tcb-node-sdk 1.0.1 → 1.0.3

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
@@ -10,7 +10,96 @@ npm install @be-link/shield-for-tcb-node-sdk
10
10
  pnpm add @be-link/shield-for-tcb-node-sdk
11
11
  ```
12
12
 
13
- ## 使用
13
+ ## V2 SDK(推荐)
14
+
15
+ V2 SDK 从 MySQL 数据源读取配置,支持按 service + key 获取配置,并提供自动类型解析。
16
+
17
+ ### 基本使用
18
+
19
+ ```typescript
20
+ import { backendConfigServiceV2 } from '@be-link/shield-for-tcb-node-sdk'
21
+ ```
22
+
23
+ ### 获取服务列表
24
+
25
+ ```typescript
26
+ const services = await backendConfigServiceV2.getServices('local')
27
+ // 返回: ['BackendUser', 'Trade', 'User', ...]
28
+ ```
29
+
30
+ ### 获取服务的配置键列表
31
+
32
+ ```typescript
33
+ const keys = await backendConfigServiceV2.getServiceKeys('TestService', 'local')
34
+ // 返回: ['TestServiceKey1', 'TestServiceKey2', 'TestServiceKey3', ...]
35
+ ```
36
+
37
+ ### 获取单个配置
38
+
39
+ ```typescript
40
+ // 原始格式(包含元数据)
41
+ const config = await backendConfigServiceV2.fetchConfig({
42
+ service: 'TestService',
43
+ key: 'TestServiceKey1',
44
+ env: 'local'
45
+ })
46
+ // 返回: { config_key: 'TestServiceKey1', value: 'xxx', value_type: 'string', updated_at: '...' }
47
+
48
+ // 自动解析类型(推荐)
49
+ const host = await backendConfigServiceV2.getConfigValue<string>('TestService', 'TestServiceKey1', 'local')
50
+ // 返回: '127.0.0.1'
51
+
52
+ const port = await backendConfigServiceV2.getConfigValue<number>('TestService', 'TestServiceKey1', 'local')
53
+ // 返回: 1234(自动解析为数字)
54
+
55
+ const enabled = await backendConfigServiceV2.getConfigValue<boolean>('TestService', 'TestServiceKey1', 'local')
56
+ // 返回: true/false(自动解析为布尔值)
57
+
58
+ const jsonConfig = await backendConfigServiceV2.getConfigValue<object>('BackendUser', 'TestServiceKey1', 'local')
59
+ // 返回: { ... }(自动 JSON 解析)
60
+ ```
61
+
62
+ ### 批量获取配置
63
+
64
+ ```typescript
65
+ // 原始格式
66
+ const configs = await backendConfigServiceV2.fetchConfigs({
67
+ service: 'TestService',
68
+ keys: ['TestServiceKey1', 'TestServiceKey2'],
69
+ env: 'local'
70
+ })
71
+ // 返回: { 'TestServiceKey1': { value: 'xxx', value_type: 'string' }, ... }
72
+
73
+ // 自动解析类型(推荐)
74
+ const values = await backendConfigServiceV2.getConfigValues(
75
+ 'TestService',
76
+ ['TestServiceKey1', 'TestServiceKey2', 'TestServiceKey3'],
77
+ 'local'
78
+ )
79
+ // 返回: {
80
+ // }
81
+ ```
82
+
83
+ ### 环境变量
84
+
85
+ | 变量名 | 说明 | 示例 |
86
+ |--------|------|------|
87
+ | `SHIELD_SDK_HOST` | 覆盖 SDK 请求地址(本地开发用) | `http://localhost:8090` |
88
+ | `CONTAINER_ENV` | 容器环境,默认 `SCF`(云函数),设置为其他值使用内网地址 | `ECS` |
89
+ | `NODE_ENV` | 环境标识,`prod` 使用生产环境地址 | `local` / `ppe` / `prod` |
90
+
91
+ ### 本地开发
92
+
93
+ ```bash
94
+ # 设置本地服务地址
95
+ export SHIELD_SDK_HOST=http://localhost:8090
96
+ ```
97
+
98
+ ---
99
+
100
+ ## V1 SDK(旧版)
101
+
102
+ V1 SDK 从 YAML 文件读取配置,保持向后兼容。
14
103
 
15
104
  ```typescript
16
105
  import { backendConfigService, frontendConfigService } from '@be-link/shield-for-tcb-node-sdk'
@@ -21,13 +110,22 @@ const config = await backendConfigService.fetchConfig({ key: 'your-key', type: '
21
110
  // 前端使用(跳过异常处理,直接抛出原始错误)
22
111
  const frontendConfig = await frontendConfigService.fetchConfig({ key: 'your-key', type: 'json' })
23
112
 
24
- // 获取全局动态配置
25
- const globalConfig = await backendConfigService.fetchGlobalDynamicConfig()
26
-
27
- // 获取 COS 临时密钥
28
- const cosTempSecret = await backendConfigService.getCosTempSecret()
29
113
  ```
30
114
 
115
+ ---
116
+
117
+ ## V1 vs V2 对比
118
+
119
+ | 特性 | V1 SDK | V2 SDK |
120
+ |------|--------|--------|
121
+ | 数据源 | YAML 文件 | MySQL |
122
+ | 获取方式 | 按 key | 按 service + key |
123
+ | 类型解析 | 手动指定 type | 自动根据 value_type 解析 |
124
+ | 批量获取 | ❌ | ✅ |
125
+ | 配置管理 | ❌ | ✅(通过管理后台) |
126
+ | 版本追踪 | ❌ | ✅ |
127
+ | 审计日志 | ❌ | ✅ |
128
+
31
129
  ## 发布流程
32
130
 
33
131
  ### 自动发布(推荐)
package/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export { backendConfigService } from './modules/config/service';
2
2
  export type { Service as ConfigControllerTypes } from './modules/config/types';
3
+ export { backendConfigServiceV2, ConfigServiceV2 } from './modules/config/serviceV2';
4
+ export type { ServiceV2 as ConfigControllerTypesV2 } from './modules/config/typesV2';
package/index.js CHANGED
@@ -1,5 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.backendConfigService = void 0;
3
+ exports.ConfigServiceV2 = exports.backendConfigServiceV2 = exports.backendConfigService = void 0;
4
+ // V1 SDK (YAML 数据源)
4
5
  var service_1 = require("./modules/config/service");
5
6
  Object.defineProperty(exports, "backendConfigService", { enumerable: true, get: function () { return service_1.backendConfigService; } });
7
+ // V2 SDK (MySQL 数据源)
8
+ var serviceV2_1 = require("./modules/config/serviceV2");
9
+ Object.defineProperty(exports, "backendConfigServiceV2", { enumerable: true, get: function () { return serviceV2_1.backendConfigServiceV2; } });
10
+ Object.defineProperty(exports, "ConfigServiceV2", { enumerable: true, get: function () { return serviceV2_1.ConfigServiceV2; } });
@@ -9,6 +9,12 @@ export default abstract class BaseService {
9
9
  protected readonly publicDevHost = "https://ecommerce-dev.wejourney.top";
10
10
  protected readonly publicProdHost = "https://ecommerce-release.wejourney.top";
11
11
  constructor();
12
+ /** 获取 Host */
13
+ protected getHost(): string;
14
+ /** 获取 Host (V2,支持环境变量覆盖) */
15
+ protected getHostV2(): string;
12
16
  /** 获取API URL */
13
17
  protected getApiUrl(func: Function): string;
18
+ /** 获取API URL (V2,支持环境变量覆盖) */
19
+ protected getApiUrlV2(path: string): string;
14
20
  }
@@ -16,16 +16,32 @@ class BaseService {
16
16
  /** 如果是云函数环境, 默认走公网访问 */
17
17
  this.isPublicEnv = (process.env.CONTAINER_ENV || 'SCF') === 'SCF';
18
18
  }
19
- /** 获取API URL */
20
- getApiUrl(func) {
21
- const host = this.isPublicEnv
19
+ /** 获取 Host */
20
+ getHost() {
21
+ return this.isPublicEnv
22
22
  ? env_1.default.isProduction()
23
23
  ? this.publicProdHost
24
24
  : this.publicDevHost
25
25
  : env_1.default.isProduction()
26
26
  ? this.natProdHost
27
27
  : this.natDevHost;
28
- return `${host}${this.prefixUrl}/${(0, string_1.camelToKebabCase)(func.name)}`;
28
+ }
29
+ /** 获取 Host (V2,支持环境变量覆盖) */
30
+ getHostV2() {
31
+ // 支持通过环境变量覆盖 host(用于本地测试)
32
+ const overrideHost = process.env.SHIELD_SDK_HOST;
33
+ if (overrideHost) {
34
+ return overrideHost;
35
+ }
36
+ return this.getHost();
37
+ }
38
+ /** 获取API URL */
39
+ getApiUrl(func) {
40
+ return `${this.getHost()}${this.prefixUrl}/${(0, string_1.camelToKebabCase)(func.name)}`;
41
+ }
42
+ /** 获取API URL (V2,支持环境变量覆盖) */
43
+ getApiUrlV2(path) {
44
+ return `${this.getHostV2()}${this.prefixUrl}${path}`;
29
45
  }
30
46
  }
31
47
  exports.default = BaseService;
@@ -0,0 +1,58 @@
1
+ import { ServiceV2 } from './typesV2';
2
+ import BaseService from '../BaseService';
3
+ /**
4
+ * V2 配置服务
5
+ * 从 MySQL 数据源读取配置,支持按 service + key 获取
6
+ */
7
+ export declare class ConfigServiceV2 extends BaseService implements ServiceV2.ConfigController {
8
+ protected prefixUrl: string;
9
+ /**
10
+ * 获取单个配置
11
+ * @param req 请求参数
12
+ * @returns 配置数据,如果配置不存在返回 null
13
+ */
14
+ fetchConfig(req: ServiceV2.Request.FetchConfig): Promise<ServiceV2.Response.FetchConfigResponse | null>;
15
+ /**
16
+ * 批量获取配置
17
+ * @param req 请求参数
18
+ * @returns 配置数据映射
19
+ */
20
+ fetchConfigs(req: ServiceV2.Request.FetchConfigs): Promise<ServiceV2.Response.FetchConfigsResponse>;
21
+ /**
22
+ * 获取所有服务列表
23
+ * @param env 环境名称(可选,默认使用当前环境)
24
+ * @returns 服务名称列表
25
+ */
26
+ getServices(env?: string): Promise<ServiceV2.Response.GetServicesResponse>;
27
+ /**
28
+ * 获取指定服务的配置键列表
29
+ * @param serviceName 服务名称
30
+ * @param env 环境名称(可选,默认使用当前环境)
31
+ * @returns 配置键列表
32
+ */
33
+ getServiceKeys(serviceName: string, env?: string): Promise<ServiceV2.Response.GetServiceKeysResponse>;
34
+ /**
35
+ * 获取配置值(自动解析类型)
36
+ * @param service 服务名称
37
+ * @param key 配置键
38
+ * @param env 环境(可选)
39
+ * @returns 解析后的配置值
40
+ */
41
+ getConfigValue<T = any>(service: string, key: string, env?: string): Promise<T | null>;
42
+ /**
43
+ * 批量获取配置值(自动解析类型)
44
+ * @param service 服务名称
45
+ * @param keys 配置键列表(可选,不传则获取该服务所有配置)
46
+ * @param env 环境(可选)
47
+ * @returns 解析后的配置值映射
48
+ */
49
+ getConfigValues<T = any>(service: string, keys?: string[], env?: string): Promise<Record<string, T>>;
50
+ /**
51
+ * 获取指定服务的所有配置
52
+ * @param service 服务名称
53
+ * @param env 环境(可选)
54
+ * @returns 该服务所有配置(自动解析类型)
55
+ */
56
+ fetchAllConfigs<T = any>(service: string, env?: string): Promise<Record<string, T>>;
57
+ }
58
+ export declare const backendConfigServiceV2: ConfigServiceV2;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.backendConfigServiceV2 = exports.ConfigServiceV2 = void 0;
7
+ const http_1 = require("../../utils/http");
8
+ const BaseService_1 = __importDefault(require("../BaseService"));
9
+ /**
10
+ * V2 配置服务
11
+ * 从 MySQL 数据源读取配置,支持按 service + key 获取
12
+ */
13
+ class ConfigServiceV2 extends BaseService_1.default {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.prefixUrl = '/v2/shield/config';
17
+ }
18
+ /**
19
+ * 获取单个配置
20
+ * @param req 请求参数
21
+ * @returns 配置数据,如果配置不存在返回 null
22
+ */
23
+ fetchConfig(req) {
24
+ return (0, http_1.callApi)(this.getApiUrlV2('/fetch'), req, {
25
+ skipErrorHandling: true,
26
+ }).catch(() => null);
27
+ }
28
+ /**
29
+ * 批量获取配置
30
+ * @param req 请求参数
31
+ * @returns 配置数据映射
32
+ */
33
+ fetchConfigs(req) {
34
+ return (0, http_1.callApi)(this.getApiUrlV2('/fetch-batch'), req);
35
+ }
36
+ /**
37
+ * 获取所有服务列表
38
+ * @param env 环境名称(可选,默认使用当前环境)
39
+ * @returns 服务名称列表
40
+ */
41
+ async getServices(env) {
42
+ const query = env ? `?env=${encodeURIComponent(env)}` : '';
43
+ return (0, http_1.getApi)(this.getApiUrlV2('/services') + query);
44
+ }
45
+ /**
46
+ * 获取指定服务的配置键列表
47
+ * @param serviceName 服务名称
48
+ * @param env 环境名称(可选,默认使用当前环境)
49
+ * @returns 配置键列表
50
+ */
51
+ async getServiceKeys(serviceName, env) {
52
+ const query = env ? `?env=${encodeURIComponent(env)}` : '';
53
+ return (0, http_1.getApi)(this.getApiUrlV2(`/services/${serviceName}/keys`) + query);
54
+ }
55
+ /**
56
+ * 获取配置值(自动解析类型)
57
+ * @param service 服务名称
58
+ * @param key 配置键
59
+ * @param env 环境(可选)
60
+ * @returns 解析后的配置值
61
+ */
62
+ async getConfigValue(service, key, env) {
63
+ const result = await this.fetchConfig({ service, key, env });
64
+ if (!result) {
65
+ return null;
66
+ }
67
+ // 根据类型解析值
68
+ switch (result.value_type) {
69
+ case 'number':
70
+ return Number(result.value);
71
+ case 'boolean':
72
+ return (result.value === 'true' || result.value === '1');
73
+ case 'object':
74
+ case 'array':
75
+ try {
76
+ return JSON.parse(result.value);
77
+ }
78
+ catch {
79
+ return result.value;
80
+ }
81
+ default:
82
+ return result.value;
83
+ }
84
+ }
85
+ /**
86
+ * 批量获取配置值(自动解析类型)
87
+ * @param service 服务名称
88
+ * @param keys 配置键列表(可选,不传则获取该服务所有配置)
89
+ * @param env 环境(可选)
90
+ * @returns 解析后的配置值映射
91
+ */
92
+ async getConfigValues(service, keys, env) {
93
+ const result = await this.fetchConfigs({ service, keys, env });
94
+ const parsed = {};
95
+ for (const [key, item] of Object.entries(result)) {
96
+ switch (item.value_type) {
97
+ case 'number':
98
+ parsed[key] = Number(item.value);
99
+ break;
100
+ case 'boolean':
101
+ parsed[key] = (item.value === 'true' || item.value === '1');
102
+ break;
103
+ case 'object':
104
+ case 'array':
105
+ try {
106
+ parsed[key] = JSON.parse(item.value);
107
+ }
108
+ catch {
109
+ parsed[key] = item.value;
110
+ }
111
+ break;
112
+ default:
113
+ parsed[key] = item.value;
114
+ }
115
+ }
116
+ return parsed;
117
+ }
118
+ /**
119
+ * 获取指定服务的所有配置
120
+ * @param service 服务名称
121
+ * @param env 环境(可选)
122
+ * @returns 该服务所有配置(自动解析类型)
123
+ */
124
+ async fetchAllConfigs(service, env) {
125
+ return this.getConfigValues(service, undefined, env);
126
+ }
127
+ }
128
+ exports.ConfigServiceV2 = ConfigServiceV2;
129
+ // 导出单例
130
+ exports.backendConfigServiceV2 = new ConfigServiceV2();
@@ -0,0 +1,109 @@
1
+ export declare namespace ServiceV2 {
2
+ namespace Entity {
3
+ /**
4
+ * 配置项
5
+ */
6
+ interface ConfigItem {
7
+ config_key: string;
8
+ value: string;
9
+ value_type: 'string' | 'number' | 'boolean' | 'object' | 'array';
10
+ updated_at: string;
11
+ }
12
+ /**
13
+ * 批量配置项
14
+ */
15
+ interface BatchConfigItem {
16
+ value: string;
17
+ value_type: 'string' | 'number' | 'boolean' | 'object' | 'array';
18
+ }
19
+ }
20
+ namespace Request {
21
+ /**
22
+ * 获取单个配置请求参数
23
+ */
24
+ interface FetchConfig {
25
+ service: string;
26
+ key: string;
27
+ env?: string;
28
+ }
29
+ /**
30
+ * 批量获取配置请求参数
31
+ */
32
+ interface FetchConfigs {
33
+ service: string;
34
+ keys?: string[];
35
+ env?: string;
36
+ }
37
+ /**
38
+ * 获取服务列表请求参数
39
+ */
40
+ interface GetServices {
41
+ env?: string;
42
+ }
43
+ /**
44
+ * 获取服务配置键列表请求参数
45
+ */
46
+ interface GetServiceKeys {
47
+ serviceName: string;
48
+ env?: string;
49
+ }
50
+ }
51
+ namespace Response {
52
+ /**
53
+ * 获取单个配置响应
54
+ */
55
+ interface FetchConfigResponse {
56
+ config_key: string;
57
+ value: string;
58
+ value_type: 'string' | 'number' | 'boolean' | 'object' | 'array';
59
+ updated_at: string;
60
+ }
61
+ /**
62
+ * 批量获取配置响应
63
+ */
64
+ interface FetchConfigsResponse {
65
+ [key: string]: {
66
+ value: string;
67
+ value_type: 'string' | 'number' | 'boolean' | 'object' | 'array';
68
+ };
69
+ }
70
+ /**
71
+ * 获取服务列表响应
72
+ */
73
+ type GetServicesResponse = string[];
74
+ /**
75
+ * 获取服务配置键列表响应
76
+ */
77
+ type GetServiceKeysResponse = string[];
78
+ }
79
+ /**
80
+ * V2 配置控制器接口
81
+ */
82
+ interface ConfigController {
83
+ /**
84
+ * 获取单个配置
85
+ * @param req 请求参数
86
+ * @returns 配置数据
87
+ */
88
+ fetchConfig(req: Request.FetchConfig): Promise<Response.FetchConfigResponse | null>;
89
+ /**
90
+ * 批量获取配置
91
+ * @param req 请求参数
92
+ * @returns 配置数据映射
93
+ */
94
+ fetchConfigs(req: Request.FetchConfigs): Promise<Response.FetchConfigsResponse>;
95
+ /**
96
+ * 获取所有服务列表
97
+ * @param env 环境名称
98
+ * @returns 服务列表
99
+ */
100
+ getServices(env?: string): Promise<Response.GetServicesResponse>;
101
+ /**
102
+ * 获取指定服务的配置键列表
103
+ * @param serviceName 服务名称
104
+ * @param env 环境名称
105
+ * @returns 配置键列表
106
+ */
107
+ getServiceKeys(serviceName: string, env?: string): Promise<Response.GetServiceKeysResponse>;
108
+ }
109
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@be-link/shield-for-tcb-node-sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "ShieldForTCB Node.js SDK",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/utils/http.d.ts CHANGED
@@ -1,5 +1,12 @@
1
1
  type CallApiOptions = {
2
2
  skipErrorHandling?: boolean;
3
3
  };
4
+ type GetApiOptions = {
5
+ skipErrorHandling?: boolean;
6
+ };
4
7
  export declare function callApi<T extends (args: any) => Promise<any>>(url: string, request?: Parameters<T>[0], options?: CallApiOptions): Promise<Awaited<ReturnType<T>>>;
8
+ /**
9
+ * GET 请求 API
10
+ */
11
+ export declare function getApi<T extends (args: any) => Promise<any>>(url: string, options?: GetApiOptions): Promise<Awaited<ReturnType<T>>>;
5
12
  export {};
package/utils/http.js CHANGED
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.callApi = callApi;
40
+ exports.getApi = getApi;
40
41
  const axios_1 = __importDefault(require("axios"));
41
42
  const uuid_1 = require("uuid");
42
43
  const axios_retry_1 = __importDefault(require("axios-retry"));
@@ -99,3 +100,33 @@ async function callApi(url, request, options) {
99
100
  throw error;
100
101
  }
101
102
  }
103
+ /**
104
+ * GET 请求 API
105
+ */
106
+ async function getApi(url, options) {
107
+ const requestId = (0, uuid_1.v4)();
108
+ try {
109
+ console.info(`准备发起shield-for-tcb GET请求[${requestId}]: ${url}`);
110
+ const response = await axios_1.default.get(url, {
111
+ headers: { 'x-request-id': requestId, 'content-type': 'application/json' },
112
+ });
113
+ const responseData = response.data;
114
+ return responseData.data;
115
+ }
116
+ catch (error) {
117
+ if (options?.skipErrorHandling) {
118
+ throw error;
119
+ }
120
+ const axiosError = error;
121
+ if (axiosError.response) {
122
+ const response = axiosError.response;
123
+ const data = response.data;
124
+ console.error(`shield-for-tcb GET异常: ${axiosError.message}, requestId: ${requestId}`);
125
+ console.info('响应信息', data.message);
126
+ console.error('异常堆栈', JSON.stringify(error.stack));
127
+ throw axiosError;
128
+ }
129
+ console.error(`shield-for-tcb GET未知异常: ${axiosError.message}`, error.stack);
130
+ throw error;
131
+ }
132
+ }