@be-link/ecommerce-backend-bff-service-node-sdk 0.0.1
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 +115 -0
- package/bff/modules/BaseService.d.ts +41 -0
- package/bff/modules/BaseService.js +41 -0
- package/bff/modules/demo/service.d.ts +22 -0
- package/bff/modules/demo/service.js +49 -0
- package/bff/modules/demo/types.d.ts +28 -0
- package/bff/modules/demo/types.js +2 -0
- package/bff/modules/example/service.d.ts +46 -0
- package/bff/modules/example/service.js +89 -0
- package/bff/modules/example/types.d.ts +133 -0
- package/bff/modules/example/types.js +2 -0
- package/bff/request/client.d.ts +45 -0
- package/bff/request/client.js +62 -0
- package/bff/request/strategy.d.ts +51 -0
- package/bff/request/strategy.js +188 -0
- package/errors/index.d.ts +27 -0
- package/errors/index.js +52 -0
- package/index.d.ts +54 -0
- package/index.js +58 -0
- package/package.json +30 -0
- package/types/index.d.ts +57 -0
- package/types/index.js +2 -0
- package/utils/env.d.ts +23 -0
- package/utils/env.js +40 -0
- package/utils/http.d.ts +5 -0
- package/utils/http.js +39 -0
- package/utils/string.d.ts +12 -0
- package/utils/string.js +20 -0
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# EcommerceBackendBffService SDK
|
|
2
|
+
|
|
3
|
+
EcommerceBackendBffService Node.js SDK - 统一平台 SDK,支持 Web/H5 和微信小程序
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- ✅ **统一命名空间结构**:与后端 SDK 保持一致的类型定义
|
|
8
|
+
- ✅ **自动生成 Swagger 文档**:使用 tsoa 自动生成 OpenAPI 3.0 文档
|
|
9
|
+
- ✅ **多平台支持**:自动检测并适配 Web/H5 和微信小程序环境
|
|
10
|
+
- ✅ **类型安全**:完整的 TypeScript 类型定义
|
|
11
|
+
- ✅ **标准响应格式**:统一的 `StandardResponse<T>` 响应结构
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @be-link/ecommerce-backend-bff-service-node-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 使用
|
|
20
|
+
|
|
21
|
+
### Web/H5 环境
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { EcommerceBackendBffSDK } from '@be-link/ecommerce-backend-bff-service-node-sdk'
|
|
25
|
+
|
|
26
|
+
const sdk = new EcommerceBackendBffSDK({
|
|
27
|
+
getToken: async () => localStorage.getItem('token') || '',
|
|
28
|
+
getUserId: async () => localStorage.getItem('userId') || '',
|
|
29
|
+
environment: 'production'
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// 使用服务
|
|
33
|
+
const result = await sdk.demo.demoFunc({ demoParam: 'test' })
|
|
34
|
+
console.log(result.data) // 业务数据
|
|
35
|
+
console.log(result.message) // 响应消息
|
|
36
|
+
console.log(result.requestId) // 请求 ID
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 微信小程序环境
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { EcommerceBackendBffSDK } from '@be-link/ecommerce-backend-bff-service-node-sdk'
|
|
43
|
+
|
|
44
|
+
const sdk = new EcommerceBackendBffSDK({
|
|
45
|
+
getToken: async () => wx.getStorageSync('token') || '',
|
|
46
|
+
getUserId: async () => wx.getStorageSync('userId') || '',
|
|
47
|
+
environment: 'test'
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// 使用服务
|
|
51
|
+
const result = await sdk.example.getUserProfile({ id: 'user123' })
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 使用类型定义
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import {
|
|
58
|
+
EcommerceBackendBffSDK,
|
|
59
|
+
DemoControllerTypes,
|
|
60
|
+
ExampleServiceTypes
|
|
61
|
+
} from '@be-link/ecommerce-backend-bff-service-node-sdk'
|
|
62
|
+
|
|
63
|
+
// 使用命名空间类型
|
|
64
|
+
type DemoRequest = DemoControllerTypes.Request.demoFunc
|
|
65
|
+
type DemoResponse = DemoControllerTypes.Response.demoFunc
|
|
66
|
+
|
|
67
|
+
type UserProfile = ExampleServiceTypes.Response.getUserProfile
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 开发
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# 构建
|
|
74
|
+
npm run build
|
|
75
|
+
|
|
76
|
+
# 生成 Swagger 文档
|
|
77
|
+
npm run swagger
|
|
78
|
+
|
|
79
|
+
# 构建并生成文档
|
|
80
|
+
npm run build:swagger
|
|
81
|
+
|
|
82
|
+
# 运行测试
|
|
83
|
+
npm test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 文档
|
|
87
|
+
|
|
88
|
+
- [目录结构说明](./DIRECTORY_STRUCTURE.md) - 项目目录结构和组织方式
|
|
89
|
+
- [架构说明](./ARCHITECTURE.md) - 系统架构和设计理念
|
|
90
|
+
- [Swagger 文档](./SWAGGER.md) - API 文档生成和使用指南
|
|
91
|
+
- [类型兼容性](./TYPES_COMPATIBILITY.md) - 类型定义和兼容性说明
|
|
92
|
+
- [SDK vs Server](./SDK_VS_SERVER.md) - SDK 和 Server 的区别
|
|
93
|
+
|
|
94
|
+
## API 文档
|
|
95
|
+
|
|
96
|
+
生成的 Swagger 文档位于 `dist/swagger.json`,可以使用以下方式查看:
|
|
97
|
+
|
|
98
|
+
1. **Swagger UI**:
|
|
99
|
+
```bash
|
|
100
|
+
npm install -g swagger-ui-watcher
|
|
101
|
+
swagger-ui-watcher packages/sdk/dist/swagger.json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
2. **在线工具**:访问 [Swagger Editor](https://editor.swagger.io/) 并导入 `swagger.json`
|
|
105
|
+
|
|
106
|
+
3. **VS Code 插件**:安装 [Swagger Viewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)
|
|
107
|
+
|
|
108
|
+
## 添加新服务
|
|
109
|
+
|
|
110
|
+
查看 [DIRECTORY_STRUCTURE.md](./DIRECTORY_STRUCTURE.md) 了解如何添加新的服务模块。
|
|
111
|
+
|
|
112
|
+
## License
|
|
113
|
+
|
|
114
|
+
ISC
|
|
115
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { HttpClient } from '../request/client';
|
|
2
|
+
/**
|
|
3
|
+
* BaseService 基类
|
|
4
|
+
* 所有服务类都应该继承此类
|
|
5
|
+
* 提供通过 HttpClient 发起 API 请求的通用功能
|
|
6
|
+
*/
|
|
7
|
+
export default abstract class BaseService {
|
|
8
|
+
/**
|
|
9
|
+
* 服务的 URL 前缀路径(例如 '/api/v1/user')
|
|
10
|
+
* 必须由子类定义
|
|
11
|
+
*/
|
|
12
|
+
protected abstract prefixUrl: string;
|
|
13
|
+
/**
|
|
14
|
+
* 用于发起请求的 HttpClient 实例
|
|
15
|
+
* 通过构造函数注入
|
|
16
|
+
*/
|
|
17
|
+
protected http: HttpClient;
|
|
18
|
+
/**
|
|
19
|
+
* 使用 HttpClient 初始化 BaseService
|
|
20
|
+
* @param http - 用于发起 API 请求的 HttpClient 实例
|
|
21
|
+
*/
|
|
22
|
+
constructor(http: HttpClient);
|
|
23
|
+
/**
|
|
24
|
+
* 将函数引用转换为短横线命名的 API 路径
|
|
25
|
+
* @param func - 函数引用(通常是服务类的方法)
|
|
26
|
+
* @returns 从函数名派生的短横线命名路径段
|
|
27
|
+
* @example
|
|
28
|
+
* getPath(this.getUserProfile) // 返回 'get-user-profile'
|
|
29
|
+
*/
|
|
30
|
+
protected getPath(func: Function): string;
|
|
31
|
+
/**
|
|
32
|
+
* 通过组合 prefixUrl 和方法路径执行 API 请求
|
|
33
|
+
* @param func - 用于派生 API 路径的函数引用
|
|
34
|
+
* @param data - 请求负载数据(可选)
|
|
35
|
+
* @returns Promise,解析为响应数据
|
|
36
|
+
* @throws SdkError 如果请求失败
|
|
37
|
+
* @example
|
|
38
|
+
* await this.request(this.getUserProfile, { id: '123' })
|
|
39
|
+
*/
|
|
40
|
+
protected request<T>(func: Function, data?: any): Promise<T>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const string_1 = require("../../utils/string");
|
|
4
|
+
/**
|
|
5
|
+
* BaseService 基类
|
|
6
|
+
* 所有服务类都应该继承此类
|
|
7
|
+
* 提供通过 HttpClient 发起 API 请求的通用功能
|
|
8
|
+
*/
|
|
9
|
+
class BaseService {
|
|
10
|
+
/**
|
|
11
|
+
* 使用 HttpClient 初始化 BaseService
|
|
12
|
+
* @param http - 用于发起 API 请求的 HttpClient 实例
|
|
13
|
+
*/
|
|
14
|
+
constructor(http) {
|
|
15
|
+
this.http = http;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 将函数引用转换为短横线命名的 API 路径
|
|
19
|
+
* @param func - 函数引用(通常是服务类的方法)
|
|
20
|
+
* @returns 从函数名派生的短横线命名路径段
|
|
21
|
+
* @example
|
|
22
|
+
* getPath(this.getUserProfile) // 返回 'get-user-profile'
|
|
23
|
+
*/
|
|
24
|
+
getPath(func) {
|
|
25
|
+
return (0, string_1.camelToKebabCase)(func.name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 通过组合 prefixUrl 和方法路径执行 API 请求
|
|
29
|
+
* @param func - 用于派生 API 路径的函数引用
|
|
30
|
+
* @param data - 请求负载数据(可选)
|
|
31
|
+
* @returns Promise,解析为响应数据
|
|
32
|
+
* @throws SdkError 如果请求失败
|
|
33
|
+
* @example
|
|
34
|
+
* await this.request(this.getUserProfile, { id: '123' })
|
|
35
|
+
*/
|
|
36
|
+
async request(func, data) {
|
|
37
|
+
const path = `${this.prefixUrl}/${this.getPath(func)}`;
|
|
38
|
+
return this.http.request({ path, data });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.default = BaseService;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Service } from './types';
|
|
2
|
+
import BaseService from '../BaseService';
|
|
3
|
+
import type { StandardResponse } from '../../../types';
|
|
4
|
+
/**
|
|
5
|
+
* DemoService - Demo 服务模块
|
|
6
|
+
* 提供 Demo 相关的 API 方法
|
|
7
|
+
*/
|
|
8
|
+
declare class DemoService extends BaseService {
|
|
9
|
+
protected prefixUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* Demo 方法
|
|
12
|
+
* @param request - 请求参数
|
|
13
|
+
* @returns Promise,解析为标准响应格式
|
|
14
|
+
* @example
|
|
15
|
+
* const result = await sdk.demo.demoFunc({ demoParam: 'test' })
|
|
16
|
+
* console.log(result.data) // 业务数据
|
|
17
|
+
* console.log(result.message) // 响应消息
|
|
18
|
+
* console.log(result.requestId) // 请求 ID
|
|
19
|
+
*/
|
|
20
|
+
demoFunc(request: Service.Request.demoFunc): Promise<StandardResponse<Service.Response.demoFunc>>;
|
|
21
|
+
}
|
|
22
|
+
export default DemoService;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
9
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const tsoa_1 = require("tsoa");
|
|
16
|
+
const BaseService_1 = __importDefault(require("../BaseService"));
|
|
17
|
+
/**
|
|
18
|
+
* DemoService - Demo 服务模块
|
|
19
|
+
* 提供 Demo 相关的 API 方法
|
|
20
|
+
*/
|
|
21
|
+
let DemoService = class DemoService extends BaseService_1.default {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this.prefixUrl = '/demo';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Demo 方法
|
|
28
|
+
* @param request - 请求参数
|
|
29
|
+
* @returns Promise,解析为标准响应格式
|
|
30
|
+
* @example
|
|
31
|
+
* const result = await sdk.demo.demoFunc({ demoParam: 'test' })
|
|
32
|
+
* console.log(result.data) // 业务数据
|
|
33
|
+
* console.log(result.message) // 响应消息
|
|
34
|
+
* console.log(result.requestId) // 请求 ID
|
|
35
|
+
*/
|
|
36
|
+
demoFunc(request) {
|
|
37
|
+
return this.request(this.demoFunc, request);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, tsoa_1.OperationId)('示例接口'),
|
|
42
|
+
(0, tsoa_1.Post)('demo-func'),
|
|
43
|
+
__param(0, (0, tsoa_1.Body)())
|
|
44
|
+
], DemoService.prototype, "demoFunc", null);
|
|
45
|
+
DemoService = __decorate([
|
|
46
|
+
(0, tsoa_1.Route)('demo'),
|
|
47
|
+
(0, tsoa_1.Tags)('Demo')
|
|
48
|
+
], DemoService);
|
|
49
|
+
exports.default = DemoService;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare namespace Service {
|
|
2
|
+
namespace Entity { }
|
|
3
|
+
namespace Request {
|
|
4
|
+
/**
|
|
5
|
+
* 获取配置请求参数
|
|
6
|
+
*/
|
|
7
|
+
interface demoFunc {
|
|
8
|
+
/** 参数 */
|
|
9
|
+
demoParam: string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
namespace Response {
|
|
13
|
+
interface demoFunc {
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Config Controller 接口定义
|
|
18
|
+
*/
|
|
19
|
+
interface DemoController {
|
|
20
|
+
/**
|
|
21
|
+
* 示例接口
|
|
22
|
+
* @param request 请求参数
|
|
23
|
+
* @param req 请求上下文
|
|
24
|
+
* @returns 响应数据
|
|
25
|
+
*/
|
|
26
|
+
demoFunc(request: Service.Request.demoFunc, req: any): Promise<Service.Response.demoFunc>;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import BaseService from '../BaseService';
|
|
2
|
+
import type { StandardResponse } from '../../../types';
|
|
3
|
+
import { Service } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* ExampleService - 演示如何创建服务模块
|
|
6
|
+
* 此服务提供用户资料和订单管理的示例方法
|
|
7
|
+
*/
|
|
8
|
+
export declare class ExampleService extends BaseService {
|
|
9
|
+
/**
|
|
10
|
+
* 此服务的 API 路径前缀
|
|
11
|
+
* 此服务中的所有方法都将使用此前缀
|
|
12
|
+
*/
|
|
13
|
+
protected prefixUrl: string;
|
|
14
|
+
/**
|
|
15
|
+
* 根据 ID 获取用户资料
|
|
16
|
+
* @param request - 请求参数
|
|
17
|
+
* @returns Promise,解析为标准响应格式,包含用户资料数据
|
|
18
|
+
* @example
|
|
19
|
+
* const result = await exampleService.getUserProfile({ id: 'user123' })
|
|
20
|
+
* console.log(result.data) // 用户资料数据
|
|
21
|
+
* console.log(result.message) // 响应消息
|
|
22
|
+
* console.log(result.requestId) // 请求 ID
|
|
23
|
+
*/
|
|
24
|
+
getUserProfile(request: Service.Request.getUserProfile): Promise<StandardResponse<Service.Response.getUserProfile>>;
|
|
25
|
+
/**
|
|
26
|
+
* 更新用户资料
|
|
27
|
+
* @param request - 请求参数
|
|
28
|
+
* @returns Promise,解析为标准响应格式
|
|
29
|
+
* @example
|
|
30
|
+
* const result = await exampleService.updateProfile({ name: 'John Doe', email: 'john@example.com' })
|
|
31
|
+
* console.log(result.message) // 'success'
|
|
32
|
+
* console.log(result.success) // true
|
|
33
|
+
*/
|
|
34
|
+
updateProfile(request: Service.Request.updateProfile): Promise<StandardResponse<Service.Response.updateProfile>>;
|
|
35
|
+
/**
|
|
36
|
+
* 获取分页订单列表
|
|
37
|
+
* @param request - 请求参数
|
|
38
|
+
* @returns Promise,解析为标准响应格式,包含订单列表数据
|
|
39
|
+
* @example
|
|
40
|
+
* const result = await exampleService.getOrderList({ page: 1, pageSize: 20 })
|
|
41
|
+
* console.log(result.data.orders) // 订单列表
|
|
42
|
+
* console.log(result.data.total) // 总数
|
|
43
|
+
* console.log(result.requestId) // 请求 ID
|
|
44
|
+
*/
|
|
45
|
+
getOrderList(request: Service.Request.getOrderList): Promise<StandardResponse<Service.Response.getOrderList>>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
9
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ExampleService = void 0;
|
|
16
|
+
const tsoa_1 = require("tsoa");
|
|
17
|
+
const BaseService_1 = __importDefault(require("../BaseService"));
|
|
18
|
+
/**
|
|
19
|
+
* ExampleService - 演示如何创建服务模块
|
|
20
|
+
* 此服务提供用户资料和订单管理的示例方法
|
|
21
|
+
*/
|
|
22
|
+
let ExampleService = class ExampleService extends BaseService_1.default {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
/**
|
|
26
|
+
* 此服务的 API 路径前缀
|
|
27
|
+
* 此服务中的所有方法都将使用此前缀
|
|
28
|
+
*/
|
|
29
|
+
this.prefixUrl = '/api/v1/user';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 根据 ID 获取用户资料
|
|
33
|
+
* @param request - 请求参数
|
|
34
|
+
* @returns Promise,解析为标准响应格式,包含用户资料数据
|
|
35
|
+
* @example
|
|
36
|
+
* const result = await exampleService.getUserProfile({ id: 'user123' })
|
|
37
|
+
* console.log(result.data) // 用户资料数据
|
|
38
|
+
* console.log(result.message) // 响应消息
|
|
39
|
+
* console.log(result.requestId) // 请求 ID
|
|
40
|
+
*/
|
|
41
|
+
async getUserProfile(request) {
|
|
42
|
+
return this.request(this.getUserProfile, request);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 更新用户资料
|
|
46
|
+
* @param request - 请求参数
|
|
47
|
+
* @returns Promise,解析为标准响应格式
|
|
48
|
+
* @example
|
|
49
|
+
* const result = await exampleService.updateProfile({ name: 'John Doe', email: 'john@example.com' })
|
|
50
|
+
* console.log(result.message) // 'success'
|
|
51
|
+
* console.log(result.success) // true
|
|
52
|
+
*/
|
|
53
|
+
async updateProfile(request) {
|
|
54
|
+
return this.request(this.updateProfile, request);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 获取分页订单列表
|
|
58
|
+
* @param request - 请求参数
|
|
59
|
+
* @returns Promise,解析为标准响应格式,包含订单列表数据
|
|
60
|
+
* @example
|
|
61
|
+
* const result = await exampleService.getOrderList({ page: 1, pageSize: 20 })
|
|
62
|
+
* console.log(result.data.orders) // 订单列表
|
|
63
|
+
* console.log(result.data.total) // 总数
|
|
64
|
+
* console.log(result.requestId) // 请求 ID
|
|
65
|
+
*/
|
|
66
|
+
async getOrderList(request) {
|
|
67
|
+
return this.request(this.getOrderList, request);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
exports.ExampleService = ExampleService;
|
|
71
|
+
__decorate([
|
|
72
|
+
(0, tsoa_1.OperationId)('获取用户资料'),
|
|
73
|
+
(0, tsoa_1.Post)('get-user-profile'),
|
|
74
|
+
__param(0, (0, tsoa_1.Body)())
|
|
75
|
+
], ExampleService.prototype, "getUserProfile", null);
|
|
76
|
+
__decorate([
|
|
77
|
+
(0, tsoa_1.OperationId)('更新用户资料'),
|
|
78
|
+
(0, tsoa_1.Post)('update-profile'),
|
|
79
|
+
__param(0, (0, tsoa_1.Body)())
|
|
80
|
+
], ExampleService.prototype, "updateProfile", null);
|
|
81
|
+
__decorate([
|
|
82
|
+
(0, tsoa_1.OperationId)('获取订单列表'),
|
|
83
|
+
(0, tsoa_1.Post)('get-order-list'),
|
|
84
|
+
__param(0, (0, tsoa_1.Body)())
|
|
85
|
+
], ExampleService.prototype, "getOrderList", null);
|
|
86
|
+
exports.ExampleService = ExampleService = __decorate([
|
|
87
|
+
(0, tsoa_1.Route)('api/v1/user'),
|
|
88
|
+
(0, tsoa_1.Tags)('User')
|
|
89
|
+
], ExampleService);
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example Service 的类型定义
|
|
3
|
+
* 使用命名空间组织类型,与后端 SDK 保持一致
|
|
4
|
+
*/
|
|
5
|
+
export declare namespace Service {
|
|
6
|
+
/**
|
|
7
|
+
* 实体定义
|
|
8
|
+
*/
|
|
9
|
+
namespace Entity {
|
|
10
|
+
/**
|
|
11
|
+
* 用户资料数据结构
|
|
12
|
+
*/
|
|
13
|
+
interface UserProfile {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
email: string;
|
|
17
|
+
phone?: string;
|
|
18
|
+
avatar?: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 订单项结构
|
|
24
|
+
*/
|
|
25
|
+
interface Order {
|
|
26
|
+
id: string;
|
|
27
|
+
userId: string;
|
|
28
|
+
orderNumber: string;
|
|
29
|
+
status: string;
|
|
30
|
+
totalAmount: number;
|
|
31
|
+
items: OrderItem[];
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 订单项详情
|
|
37
|
+
*/
|
|
38
|
+
interface OrderItem {
|
|
39
|
+
id: string;
|
|
40
|
+
productId: string;
|
|
41
|
+
productName: string;
|
|
42
|
+
quantity: number;
|
|
43
|
+
price: number;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 请求参数定义
|
|
48
|
+
*/
|
|
49
|
+
namespace Request {
|
|
50
|
+
/**
|
|
51
|
+
* 获取用户资料的请求参数
|
|
52
|
+
*/
|
|
53
|
+
interface getUserProfile {
|
|
54
|
+
/** 用户 ID */
|
|
55
|
+
id: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 更新用户资料的请求负载
|
|
59
|
+
*/
|
|
60
|
+
interface updateProfile {
|
|
61
|
+
name?: string;
|
|
62
|
+
email?: string;
|
|
63
|
+
phone?: string;
|
|
64
|
+
avatar?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 获取订单列表的请求负载
|
|
68
|
+
*/
|
|
69
|
+
interface getOrderList {
|
|
70
|
+
page: number;
|
|
71
|
+
pageSize?: number;
|
|
72
|
+
status?: string;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 响应数据定义
|
|
77
|
+
*/
|
|
78
|
+
namespace Response {
|
|
79
|
+
/**
|
|
80
|
+
* 获取用户资料的响应
|
|
81
|
+
*/
|
|
82
|
+
interface getUserProfile {
|
|
83
|
+
id: string;
|
|
84
|
+
name: string;
|
|
85
|
+
email: string;
|
|
86
|
+
phone?: string;
|
|
87
|
+
avatar?: string;
|
|
88
|
+
createdAt: string;
|
|
89
|
+
updatedAt: string;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 更新用户资料的响应
|
|
93
|
+
*/
|
|
94
|
+
interface updateProfile {
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 订单列表的响应结构
|
|
98
|
+
*/
|
|
99
|
+
interface getOrderList {
|
|
100
|
+
orders: Entity.Order[];
|
|
101
|
+
total: number;
|
|
102
|
+
page: number;
|
|
103
|
+
pageSize: number;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Example Controller 接口定义
|
|
108
|
+
* 用于后端 Server 实现
|
|
109
|
+
*/
|
|
110
|
+
interface ExampleController {
|
|
111
|
+
/**
|
|
112
|
+
* 获取用户资料
|
|
113
|
+
* @param request 请求参数
|
|
114
|
+
* @param req 请求上下文
|
|
115
|
+
* @returns 用户资料数据
|
|
116
|
+
*/
|
|
117
|
+
getUserProfile(request: Service.Request.getUserProfile, req: any): Promise<Service.Response.getUserProfile>;
|
|
118
|
+
/**
|
|
119
|
+
* 更新用户资料
|
|
120
|
+
* @param request 请求参数
|
|
121
|
+
* @param req 请求上下文
|
|
122
|
+
* @returns 响应数据
|
|
123
|
+
*/
|
|
124
|
+
updateProfile(request: Service.Request.updateProfile, req: any): Promise<Service.Response.updateProfile>;
|
|
125
|
+
/**
|
|
126
|
+
* 获取订单列表
|
|
127
|
+
* @param request 请求参数
|
|
128
|
+
* @param req 请求上下文
|
|
129
|
+
* @returns 订单列表数据
|
|
130
|
+
*/
|
|
131
|
+
getOrderList(request: Service.Request.getOrderList, req: any): Promise<Service.Response.getOrderList>;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SdkOptions } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* HttpClient 工厂类,管理平台特定的请求策略
|
|
4
|
+
* 自动检测运行时环境并创建相应的策略
|
|
5
|
+
*/
|
|
6
|
+
export declare class HttpClient {
|
|
7
|
+
/**
|
|
8
|
+
* 请求策略实例(Web 或小程序)
|
|
9
|
+
*/
|
|
10
|
+
private strategy;
|
|
11
|
+
/**
|
|
12
|
+
* 标识 SDK 是否运行在微信小程序环境中
|
|
13
|
+
*/
|
|
14
|
+
readonly isMiniProgram: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* SDK 配置选项,包含凭证回调函数
|
|
17
|
+
*/
|
|
18
|
+
private options;
|
|
19
|
+
/**
|
|
20
|
+
* 运行环境配置
|
|
21
|
+
*/
|
|
22
|
+
private environment;
|
|
23
|
+
/**
|
|
24
|
+
* 使用 SDK 选项初始化 HttpClient
|
|
25
|
+
* 自动检测平台并创建相应的请求策略
|
|
26
|
+
* @param options - SDK 配置,包含 getToken、getUserId 回调函数和 environment
|
|
27
|
+
*/
|
|
28
|
+
constructor(options: SdkOptions);
|
|
29
|
+
/**
|
|
30
|
+
* 工厂方法,根据平台创建相应的请求策略
|
|
31
|
+
* @returns BaseRequestStrategy 实例(WebRequestStrategy 或 MiniProgramRequestStrategy)
|
|
32
|
+
*/
|
|
33
|
+
private createStrategy;
|
|
34
|
+
/**
|
|
35
|
+
* 执行 API 请求,自动获取凭证并构造请求头
|
|
36
|
+
* @param opts - 请求选项,包含路径、数据和可选的自定义请求头
|
|
37
|
+
* @returns Promise,解析为响应数据
|
|
38
|
+
* @throws SdkError 如果请求失败
|
|
39
|
+
*/
|
|
40
|
+
request<T>(opts: {
|
|
41
|
+
path: string;
|
|
42
|
+
data?: any;
|
|
43
|
+
headers?: Record<string, string>;
|
|
44
|
+
}): Promise<T>;
|
|
45
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpClient = void 0;
|
|
4
|
+
const strategy_1 = require("./strategy");
|
|
5
|
+
const env_1 = require("../../utils/env");
|
|
6
|
+
/**
|
|
7
|
+
* HttpClient 工厂类,管理平台特定的请求策略
|
|
8
|
+
* 自动检测运行时环境并创建相应的策略
|
|
9
|
+
*/
|
|
10
|
+
class HttpClient {
|
|
11
|
+
/**
|
|
12
|
+
* 使用 SDK 选项初始化 HttpClient
|
|
13
|
+
* 自动检测平台并创建相应的请求策略
|
|
14
|
+
* @param options - SDK 配置,包含 getToken、getUserId 回调函数和 environment
|
|
15
|
+
*/
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.environment = options.environment;
|
|
19
|
+
this.isMiniProgram = (0, env_1.isMiniProgram)();
|
|
20
|
+
this.strategy = this.createStrategy();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 工厂方法,根据平台创建相应的请求策略
|
|
24
|
+
* @returns BaseRequestStrategy 实例(WebRequestStrategy 或 MiniProgramRequestStrategy)
|
|
25
|
+
*/
|
|
26
|
+
createStrategy() {
|
|
27
|
+
if (this.isMiniProgram) {
|
|
28
|
+
return new strategy_1.MiniProgramRequestStrategy(this.environment);
|
|
29
|
+
}
|
|
30
|
+
return new strategy_1.WebRequestStrategy(this.environment);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 执行 API 请求,自动获取凭证并构造请求头
|
|
34
|
+
* @param opts - 请求选项,包含路径、数据和可选的自定义请求头
|
|
35
|
+
* @returns Promise,解析为响应数据
|
|
36
|
+
* @throws SdkError 如果请求失败
|
|
37
|
+
*/
|
|
38
|
+
async request(opts) {
|
|
39
|
+
// 并发获取凭证,带错误处理
|
|
40
|
+
const [token, userId] = await Promise.all([
|
|
41
|
+
Promise.resolve(this.options.getToken()).catch(() => ''),
|
|
42
|
+
Promise.resolve(this.options.getUserId()).catch(() => ''),
|
|
43
|
+
]);
|
|
44
|
+
// 生成唯一的请求 ID
|
|
45
|
+
const requestId = `b-${crypto.randomUUID()}`;
|
|
46
|
+
// 构造标准请求头
|
|
47
|
+
const standardHeaders = {
|
|
48
|
+
'Content-Type': 'application/json',
|
|
49
|
+
'X-Request-Id': requestId,
|
|
50
|
+
'x-belink-authorization': token,
|
|
51
|
+
'x-belink-userId': userId,
|
|
52
|
+
};
|
|
53
|
+
// 合并自定义请求头(自定义请求头优先)
|
|
54
|
+
const headers = {
|
|
55
|
+
...standardHeaders,
|
|
56
|
+
...(opts.headers || {}),
|
|
57
|
+
};
|
|
58
|
+
// 委托给平台特定的策略
|
|
59
|
+
return this.strategy.request(opts.path, opts.data, headers);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.HttpClient = HttpClient;
|