zentao-api 0.6.9 → 0.7.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.
@@ -507,9 +507,6 @@ export declare const BUILTIN_MODULES: ({
507
507
  };
508
508
  desc: {
509
509
  type: string;
510
- items: {
511
- type: string;
512
- };
513
510
  description: string;
514
511
  };
515
512
  QD: {
@@ -824,9 +821,6 @@ export declare const BUILTIN_MODULES: ({
824
821
  };
825
822
  desc: {
826
823
  type: string;
827
- items: {
828
- type: string;
829
- };
830
824
  description: string;
831
825
  };
832
826
  QD: {
@@ -582,10 +582,7 @@ export const BUILTIN_MODULES = [
582
582
  "description": "评审人"
583
583
  },
584
584
  "desc": {
585
- "type": "array",
586
- "items": {
587
- "type": "string"
588
- },
585
+ "type": "string",
589
586
  "description": "产品描述"
590
587
  },
591
588
  "QD": {
@@ -802,10 +799,7 @@ export const BUILTIN_MODULES = [
802
799
  "description": "评审人"
803
800
  },
804
801
  "desc": {
805
- "type": "array",
806
- "items": {
807
- "type": "string"
808
- },
802
+ "type": "string",
809
803
  "description": "产品描述"
810
804
  },
811
805
  "QD": {
@@ -2,6 +2,27 @@ import { extendModuleAction, defineModuleActions } from './define.js';
2
2
  import { extractResult } from './resolve.js';
3
3
  import { snapshotToMarkdown } from '../utils/doc-helper/markdown.js';
4
4
  import { isRecord } from '../utils/index.js';
5
+ import { request } from '../request/index.js';
6
+ import { ZentaoError } from '../misc/errors.js';
7
+ /** 这些内置写接口要求 JSON,不能把 HTTP 200 的 PHP/SQL 错误文本视为成功。 */
8
+ const requestJSON = async ({ request: command, body, bodyType, client, timeout, insecure }) => {
9
+ const response = await client.request(command.path, {
10
+ method: command.action.method.toUpperCase(),
11
+ query: command.query, body, bodyType, timeout, insecure, responseType: 'response',
12
+ });
13
+ const responseText = await response.text();
14
+ try {
15
+ return JSON.parse(responseText);
16
+ }
17
+ catch {
18
+ return {
19
+ status: 'fail',
20
+ message: `Invalid JSON response from ${command.module}/${command.action.name}.`,
21
+ httpStatus: response.status,
22
+ responseText,
23
+ };
24
+ }
25
+ };
5
26
  /**
6
27
  * 内置覆盖 / 扩展定义。
7
28
  *
@@ -64,6 +85,9 @@ import { isRecord } from '../utils/index.js';
64
85
  * @internal
65
86
  */
66
87
  export function applyBuiltinOverrides() {
88
+ for (const [moduleName, actionName] of [['product', 'create'], ['product', 'update'], ['feedback', 'close']]) {
89
+ extendModuleAction(moduleName, actionName, { request: requestJSON });
90
+ }
67
91
  // 创建执行时,需要添加产品字段
68
92
  extendModuleAction('execution', 'create', (action) => {
69
93
  const required = action.requestBody.schema?.required;
@@ -101,8 +125,8 @@ export function applyBuiltinOverrides() {
101
125
  schema.properties.reviewer ??= {
102
126
  type: 'array',
103
127
  items: { type: 'string' },
104
- description: '评审人员',
105
128
  };
129
+ schema.properties.reviewer.description = '评审人员,如果无需评审则不传';
106
130
  if (schema.required) {
107
131
  schema.required = schema.required.filter(name => name !== 'reviewer');
108
132
  }
@@ -121,6 +145,50 @@ export function applyBuiltinOverrides() {
121
145
  });
122
146
  });
123
147
  });
148
+ // confirmClose 是控制器参数,留在 JSON body 中会被误当成反馈表字段。
149
+ extendModuleAction('feedback', 'close', {
150
+ beforeRequest: async (command) => {
151
+ const data = { ...command.data };
152
+ const query = { ...command.query };
153
+ if (Object.hasOwn(data, 'confirmClose')) {
154
+ query.confirmClose = data.confirmClose;
155
+ delete data.confirmClose;
156
+ }
157
+ return { data, query };
158
+ },
159
+ });
160
+ // 确认表单会重置缺省字段;仅补齐可写字段,不回传详情中的其他属性。
161
+ extendModuleAction('bug', 'confirm', {
162
+ request: async ({ request: command, body, bodyType, client, timeout, insecure, options }) => {
163
+ const data = { ...body };
164
+ const fields = ['status', 'assignedTo', 'type', 'pri', 'deadline', 'mailto'];
165
+ const missing = fields.filter(field => data[field] === undefined);
166
+ if (missing.length) {
167
+ const response = await request('bug/get', { id: command.id }, {
168
+ client, timeout, insecure, throwOnFail: true,
169
+ forceRefreshConfig: options.forceRefreshConfig,
170
+ skipVersionCheckOnConfigError: options.skipVersionCheckOnConfigError,
171
+ });
172
+ const current = response.data;
173
+ if (!isRecord(current) || missing.some(field => current[field] === undefined)) {
174
+ throw new ZentaoError('E_API_FAILED', { message: 'Bug details are incomplete; confirmation was not sent.' });
175
+ }
176
+ for (const field of missing) {
177
+ data[field] = field === 'mailto' && typeof current[field] === 'string'
178
+ ? current[field].split(',').filter(Boolean)
179
+ : current[field];
180
+ }
181
+ }
182
+ if (typeof data.status !== 'string' || !data.status.trim()) {
183
+ throw new ZentaoError('E_INVALID_PARAM', { param: 'status', value: String(data.status) });
184
+ }
185
+ // 已关闭 Bug 的指派人是特殊标记,API 会把它当成账号校验,需调用方明确指定。
186
+ if (data.assignedTo === 'closed') {
187
+ throw new ZentaoError('E_INVALID_PARAM', { param: 'assignedTo', value: 'closed' });
188
+ }
189
+ return requestJSON({ request: command, body: data, bodyType, client, timeout, insecure, options });
190
+ },
191
+ });
124
192
  // 修改 acl 字段默认值为 open
125
193
  [
126
194
  ['product', 'create'],
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
- const fallbackBuild = "2026-09-12T05:43:34.253Z";
2
- const fallbackVersion = "0.6.9";
1
+ const fallbackBuild = "2026-09-15T08:27:14.702Z";
2
+ const fallbackVersion = "0.7.0";
3
3
  /**
4
4
  * 构建标识,由构建脚本通过 `__ZENTAO_API_BUILD__` 注入。
5
5
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zentao-api",
3
- "version": "0.6.9",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "Browser and Node.js SDK for ZenTao API",
6
6
  "license": "MIT",