zentao-api 0.2.0-beta.1 → 0.2.0

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
@@ -1,14 +1,24 @@
1
1
  # zentao-api
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/zentao-api)](https://www.npmjs.com/package/zentao-api)
4
+ [![license](https://img.shields.io/npm/l/zentao-api)](./LICENSE)
5
+ [![node](https://img.shields.io/node/v/zentao-api)](https://nodejs.org)
6
+
7
+ Browser & Node.js SDK for [ZenTao](https://www.zentao.net) (禅道) API v2.
8
+
3
9
  `zentao-api` 是一个面向禅道 API v2 的轻量 JavaScript/TypeScript SDK,可用于 Node.js 18+、浏览器打包工具以及 CDN/script 标签场景。
4
10
 
5
- ## 安装
11
+ ---
12
+
13
+ ## 安装 / Install
6
14
 
7
15
  ```sh
8
16
  npm install zentao-api
9
17
  ```
10
18
 
11
- ## 客户端
19
+ ## 快速开始 / Quick Start
20
+
21
+ ### 创建客户端
12
22
 
13
23
  ```ts
14
24
  import { ZentaoClient } from 'zentao-api';
@@ -23,14 +33,16 @@ const products = await client.get('/products');
23
33
 
24
34
  `baseUrl` 是禅道站点根地址。SDK 会在内部追加 `/api.php/v2`。
25
35
 
26
- 如果还没有 token:
36
+ ### 账号密码登录
37
+
38
+ 如果还没有 token,可以使用账号密码登录:
27
39
 
28
40
  ```ts
29
41
  const client = new ZentaoClient('https://zentao.example.com');
30
42
  const token = await client.login('admin', 'password');
31
43
  ```
32
44
 
33
- ## 全局客户端与模块请求
45
+ ### 全局客户端与模块请求
34
46
 
35
47
  ```ts
36
48
  import { ZentaoClient, request, setGlobalOptions } from 'zentao-api';
@@ -51,51 +63,71 @@ const result = await request('product/list', {});
51
63
  const result = await request('bug/list', { product: 1 }, { limit: '10' });
52
64
  ```
53
65
 
54
- ## 真实环境测试
66
+ ### 从本地 Profile 恢复
55
67
 
56
- 真实环境测试不会包含在默认 `bun test` `bun run check` 中,需要显式运行:
68
+ SDK 支持将登录信息持久化到本地(Node.js: `~/.config/zentao/zentao.json`,浏览器: `localStorage`),后续可直接恢复客户端:
57
69
 
58
- ```sh
59
- bun run test:real
70
+ ```ts
71
+ const client = await ZentaoClient.fromProfile();
72
+ // 或指定 profile key
73
+ const client = await ZentaoClient.fromProfile('admin@https://zentao.example.com');
60
74
  ```
61
75
 
62
- 如果需要保留本轮测试创建出的临时数据以便手动检查:
76
+ ## API 概览
63
77
 
64
- ```sh
65
- bun run test:real -- --keep-test-data
66
- ```
78
+ ### ZentaoClient
67
79
 
68
- 也可以用环境变量开启同样的行为:
80
+ | 方法 | 说明 |
81
+ |------|------|
82
+ | `client.get<T>(path)` | GET 请求 |
83
+ | `client.post<T>(path, body)` | POST 请求 |
84
+ | `client.put<T>(path, body)` | PUT 请求 |
85
+ | `client.delete<T>(path)` | DELETE 请求 |
86
+ | `client.login(account, password)` | 账号密码登录,返回 token |
87
+ | `client.request(path, options?)` | 通用请求(底层方法) |
88
+ | `ZentaoClient.init(options)` | 创建全局单例客户端 |
89
+ | `ZentaoClient.create(options)` | 工厂方法创建客户端 |
90
+ | `ZentaoClient.fromProfile(key?)` | 从持久化 profile 恢复客户端 |
69
91
 
70
- ```sh
71
- ZENTAO_KEEP_TEST_DATA=true bun run test:real
72
- ```
92
+ ### 模块请求
73
93
 
74
- 测试会优先读取 `.env.local`,如果不存在则读取 `env.local`。支持的变量:
94
+ | 函数 | 说明 |
95
+ |------|------|
96
+ | `request(name, params?, options?)` | 按 `"module/action"` 格式调用已注册模块 |
97
+ | `defineModules(modules, options?)` | 注册或扩展模块定义 |
98
+ | `defineModuleActions(module, actions)` | 为已有模块追加或替换动作 |
99
+ | `getModule(name)` | 获取模块定义 |
100
+ | `getModuleAction(module, action)` | 获取指定动作定义 |
101
+ | `setGlobalOptions(options)` | 设置全局默认选项 |
102
+ | `getGlobalOptions()` | 获取当前全局选项 |
75
103
 
76
- ```ini
77
- ZENTAO_URL=https://zentao.example.com
78
- ZENTAO_ACCOUNT=admin
79
- ZENTAO_PASSWORD=password
80
- # 或直接提供 Token
81
- ZENTAO_TOKEN=your-token
82
- # 可选
83
- ZENTAO_REVIEWER=admin
84
- ZENTAO_KEEP_TEST_DATA=false
85
- ZENTAO_TIMEOUT=30000
86
- ZENTAO_INSECURE=false
87
- ```
104
+ ## 错误处理
88
105
 
89
- `ZENTAO_REVIEWER` 用于启用了需求评审规则的环境;未设置时会复用 `ZENTAO_ACCOUNT`。
106
+ SDK 所有传输层错误均通过 `ZentaoError` 抛出,包含稳定的错误码:
90
107
 
91
- 运行时会先打印脱敏后的环境信息,然后创建一个名称带 `zentao-api-real-` 前缀的临时产品。后续每个 API 步骤都会打印步骤名、接口名和关键结果。测试会围绕这个产品执行一条可回收的真实写入流程:验证产品详情/列表/更新,创建并查询 3 个需求,创建/更新/查询产品计划并把需求关联到计划,创建/更新项目和执行,基于需求创建 3 个任务并验证任务列表、详情、优先级修改、启动、完成和删除,再创建 3 个 Bug 并验证列表、详情、描述修改和解决。默认清理阶段会按任务、Bug、执行、项目、需求、计划、产品的逆序尽量删除所有临时数据;传入 `--keep-test-data` 时会跳过最终清理并打印保留数据的关键 ID。
108
+ ```ts
109
+ import { ZentaoError } from 'zentao-api';
110
+
111
+ try {
112
+ await client.get('/products');
113
+ } catch (error) {
114
+ if (error instanceof ZentaoError) {
115
+ console.error(error.code); // e.g. 'E_HTTP_ERROR', 'E_TIMEOUT', 'E_NETWORK_ERROR'
116
+ console.error(error.message);
117
+ }
118
+ }
119
+ ```
120
+
121
+ > **注意**:服务端返回 `{ status: "fail" }` 时 SDK 不会抛出异常,按原始响应内容返回。仅 HTTP/网络/超时等传输层错误会抛出 `ZentaoError`。
92
122
 
93
123
  ## 扩展模块
94
124
 
95
- 生成的模块定义来自 `scripts/update-registry.ts`。你可以在调用 `request()` 前扩展模块,或新增、替换动作。同名模块默认合并定义:同名动作会替换,未知动作会追加;需要整体替换模块时传入 `{ relace: true }`。
125
+ 生成的模块定义来自 `scripts/update-registry.ts`。你可以在调用 `request()` 前扩展模块,或新增、替换动作。
126
+
127
+ ### 新增模块
96
128
 
97
129
  ```ts
98
- import { defineModuleActions, defineModules } from 'zentao-api';
130
+ import { defineModules } from 'zentao-api';
99
131
 
100
132
  defineModules({
101
133
  name: 'custom',
@@ -110,19 +142,47 @@ defineModules({
110
142
  },
111
143
  ],
112
144
  });
145
+ ```
146
+
147
+ ### 为已有模块追加动作
148
+
149
+ ```ts
150
+ import { defineModuleActions } from 'zentao-api';
113
151
 
114
152
  defineModuleActions('bug', {
115
153
  name: 'archive',
116
154
  type: 'action',
117
155
  method: 'PUT',
118
156
  path: '/bugs/{bugID}/archive',
119
- pathParams: { bugID: 1 },
157
+ pathParams: { bugID: 'Bug ID' },
120
158
  resultType: 'text',
121
159
  });
122
160
  ```
123
161
 
162
+ ### 合并与替换
163
+
164
+ 同名模块默认**合并**定义:同名动作会替换,未知动作会追加。如需**整体替换**模块,传入 `{ replace: true }`:
165
+
166
+ ```ts
167
+ defineModules(myModule, { replace: true });
168
+ ```
169
+
124
170
  如果扩展定义拆分在多个文件中,请在应用启动入口中显式导入这些文件,确保它们在调用 `request()` 前完成注册。
125
171
 
172
+ ## TypeScript 支持
173
+
174
+ SDK 提供完整的 TypeScript 类型定义,所有公共类型均可直接导入:
175
+
176
+ ```ts
177
+ import type {
178
+ ZentaoClientOptions,
179
+ ModuleDefinition,
180
+ ModuleAction,
181
+ ResponseData,
182
+ RequestOptions,
183
+ } from 'zentao-api';
184
+ ```
185
+
126
186
  ## 浏览器
127
187
 
128
188
  浏览器打包工具可以正常导入这个包:
@@ -134,13 +194,77 @@ import { ZentaoClient } from 'zentao-api';
134
194
  如果使用 script 标签,请使用浏览器构建包,并从 `window.ZentaoAPI` 读取 API:
135
195
 
136
196
  ```html
137
- <script src="https://cdn.jsdelivr.net/npm/zentao-api@1.0.0/dist/browser/zentao-api.global.js"></script>
197
+ <script src="https://cdn.jsdelivr.net/npm/zentao-api@latest/dist/browser/zentao-api.global.js"></script>
138
198
  <script>
139
199
  console.log(window.ZentaoAPI.VERSION, window.ZentaoAPI.BUILD);
140
200
  const client = new window.ZentaoAPI.ZentaoClient('https://zentao.example.com');
141
201
  </script>
142
202
  ```
143
203
 
144
- 浏览器直接请求要求禅道服务器允许 CORS。浏览器代码也会把 token 暴露给前端;如果这不可接受,请使用后端代理。
204
+ > **CORS**:浏览器直接请求要求禅道服务器允许 CORS。浏览器代码也会把 token 暴露给前端;如果这不可接受,请使用后端代理。
205
+ >
206
+ > **TLS**:`insecure` TLS 选项仅适用于 Node.js,在浏览器运行时会抛出错误。
207
+
208
+ ## 测试
209
+
210
+ ```sh
211
+ bun test # 单元测试
212
+ bun run test:coverage # 含覆盖率的单元测试
213
+ bun run check # 完整 CI 流程:测试 + 类型检查 + 注册表 + 构建 + 冒烟测试
214
+ ```
215
+
216
+ ### 真实环境测试
217
+
218
+ 真实环境测试需要连接到运行中的禅道实例,不包含在默认 `bun test` 中:
219
+
220
+ ```sh
221
+ bun run test:real
222
+ bun run test:real -- --keep-test-data # 保留临时数据以便手动检查
223
+ ```
224
+
225
+ 测试会优先读取 `.env.local`,如果不存在则读取 `env.local`。支持的环境变量:
226
+
227
+ | 变量 | 说明 | 默认值 |
228
+ |------|------|--------|
229
+ | `ZENTAO_URL` | 禅道站点地址 | *(必填)* |
230
+ | `ZENTAO_ACCOUNT` | 登录账号 | *(必填)* |
231
+ | `ZENTAO_PASSWORD` | 登录密码 | *(必填)* |
232
+ | `ZENTAO_TOKEN` | 直接提供 Token(替代账号密码) | — |
233
+ | `ZENTAO_REVIEWER` | 需求评审人(未设置时复用 `ZENTAO_ACCOUNT`) | — |
234
+ | `ZENTAO_KEEP_TEST_DATA` | 保留临时测试数据 | `false` |
235
+ | `ZENTAO_TIMEOUT` | 请求超时(ms) | `30000` |
236
+ | `ZENTAO_INSECURE` | 跳过 TLS 证书验证 | `false` |
237
+
238
+ ## 项目结构
239
+
240
+ ```
241
+ zentao-api/
242
+ ├── src/
243
+ │ ├── client/ # ZentaoClient 核心实现
244
+ │ ├── modules/ # 模块注册表与解析逻辑
245
+ │ │ ├── generated.ts # 自动生成,勿手动编辑
246
+ │ │ ├── registry.ts # 运行时注册表
247
+ │ │ └── resolve.ts # 路径模板与参数解析
248
+ │ ├── request/ # 高阶请求函数
249
+ │ ├── profiles/ # 本地 profile 持久化
250
+ │ ├── misc/ # 错误、全局选项、环境检测
251
+ │ ├── types/ # TypeScript 类型定义
252
+ │ ├── utils/ # 通用工具函数
253
+ │ └── index.ts # 公共 API 入口
254
+ ├── scripts/ # 构建与代码生成脚本
255
+ ├── tests/ # 单元测试与真实环境测试
256
+ ├── data/ # OpenAPI 规范文件
257
+ └── dist/ # 构建产物
258
+ ```
259
+
260
+ ## 贡献
261
+
262
+ 欢迎贡献代码!请确保提交前通过完整检查:
263
+
264
+ ```sh
265
+ bun run check
266
+ ```
267
+
268
+ ## 许可证 / License
145
269
 
146
- `insecure` TLS 选项仅适用于 Node.js,在浏览器运行时会抛出错误。
270
+ [MIT](./LICENSE)