zentao-api 0.6.5 → 0.6.7
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 +29 -2
- package/dist/browser/zentao-api.global.js +26 -18
- package/dist/client/index.d.ts +30 -3
- package/dist/client/index.js +303 -27
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/misc/environment.d.ts +0 -2
- package/dist/misc/environment.js +43 -19
- package/dist/misc/errors.d.ts +6 -0
- package/dist/misc/errors.js +9 -0
- package/dist/misc/zentao-version.d.ts +11 -0
- package/dist/misc/zentao-version.js +35 -0
- package/dist/modules/define.d.ts +4 -3
- package/dist/modules/define.js +4 -3
- package/dist/modules/generated.d.ts +2240 -59
- package/dist/modules/generated.js +1230 -50
- package/dist/modules/override.d.ts +2 -0
- package/dist/modules/override.js +39 -66
- package/dist/modules/query.d.ts +13 -10
- package/dist/modules/query.js +30 -26
- package/dist/modules/registry-store.js +3 -0
- package/dist/modules/registry.d.ts +0 -9702
- package/dist/modules/registry.js +0 -4
- package/dist/modules/resolve.js +1 -1
- package/dist/profiles/index.d.ts +3 -1
- package/dist/profiles/index.js +13 -4
- package/dist/request/index.d.ts +15 -4
- package/dist/request/index.js +39 -7
- package/dist/types/client.d.ts +8 -3
- package/dist/types/module.d.ts +13 -2
- package/dist/types/options.d.ts +9 -0
- package/dist/types/profile.d.ts +2 -0
- package/dist/types/response.d.ts +9 -0
- package/dist/utils/doc-helper/index.d.ts +1 -2
- package/dist/utils/doc-helper/index.js +0 -1
- package/dist/utils/doc-helper/inline.d.ts +0 -1
- package/dist/utils/doc-helper/inline.js +3 -81
- package/dist/utils/doc-helper/shared.d.ts +0 -5
- package/dist/utils/doc-helper/shared.js +0 -34
- package/dist/utils/doc-helper/types.d.ts +1 -13
- package/dist/version.js +2 -2
- package/package.json +9 -8
- package/dist/utils/doc-helper/html.d.ts +0 -3
- package/dist/utils/doc-helper/html.js +0 -442
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* ```ts
|
|
21
21
|
* defineModuleActions('bug', {
|
|
22
22
|
* name: 'assignTo',
|
|
23
|
+
* minVersion: ['22.0', 'biz13.0', 'max8.0', 'ipd5.0'],
|
|
23
24
|
* display: '指派 Bug',
|
|
24
25
|
* type: 'action',
|
|
25
26
|
* method: 'put',
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
* actions: [
|
|
45
46
|
* {
|
|
46
47
|
* name: 'list',
|
|
48
|
+
* minVersion: ['22.0', 'biz13.0', 'max8.0', 'ipd5.0'],
|
|
47
49
|
* type: 'list',
|
|
48
50
|
* method: 'get',
|
|
49
51
|
* path: '/customs',
|
package/dist/modules/override.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { extendModuleAction } from './define.js';
|
|
1
|
+
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';
|
|
@@ -24,6 +24,7 @@ import { isRecord } from '../utils/index.js';
|
|
|
24
24
|
* ```ts
|
|
25
25
|
* defineModuleActions('bug', {
|
|
26
26
|
* name: 'assignTo',
|
|
27
|
+
* minVersion: ['22.0', 'biz13.0', 'max8.0', 'ipd5.0'],
|
|
27
28
|
* display: '指派 Bug',
|
|
28
29
|
* type: 'action',
|
|
29
30
|
* method: 'put',
|
|
@@ -48,6 +49,7 @@ import { isRecord } from '../utils/index.js';
|
|
|
48
49
|
* actions: [
|
|
49
50
|
* {
|
|
50
51
|
* name: 'list',
|
|
52
|
+
* minVersion: ['22.0', 'biz13.0', 'max8.0', 'ipd5.0'],
|
|
51
53
|
* type: 'list',
|
|
52
54
|
* method: 'get',
|
|
53
55
|
* path: '/customs',
|
|
@@ -90,14 +92,6 @@ export function applyBuiltinOverrides() {
|
|
|
90
92
|
}
|
|
91
93
|
return action;
|
|
92
94
|
});
|
|
93
|
-
// 修改 task/list URL 定义
|
|
94
|
-
extendModuleAction('task', 'list', (action) => {
|
|
95
|
-
action.path = '/executions/{executionID}/tasks';
|
|
96
|
-
action.pathParams = {
|
|
97
|
-
executionID: '执行ID',
|
|
98
|
-
};
|
|
99
|
-
return action;
|
|
100
|
-
});
|
|
101
95
|
// 修改 acl 字段默认值为 open
|
|
102
96
|
[
|
|
103
97
|
['product', 'create'],
|
|
@@ -113,31 +107,10 @@ export function applyBuiltinOverrides() {
|
|
|
113
107
|
return action;
|
|
114
108
|
});
|
|
115
109
|
});
|
|
116
|
-
// execution
|
|
110
|
+
// execution/create 补充 OpenAPI 尚未声明的里程碑字段
|
|
117
111
|
extendModuleAction('execution', 'create', (action) => {
|
|
118
112
|
const properties = action.requestBody.schema?.properties;
|
|
119
113
|
if (properties) {
|
|
120
|
-
if (!properties.type) {
|
|
121
|
-
properties.type = {
|
|
122
|
-
type: 'string',
|
|
123
|
-
description: '类型(sprint 迭代,敏捷项目用 | stage 阶段,瀑布/IPD 用 | kanban 看板)',
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
if (!properties.attribute) {
|
|
127
|
-
properties.attribute = {
|
|
128
|
-
type: 'string',
|
|
129
|
-
description: [
|
|
130
|
-
'阶段属性:mix - 综合(父阶段可挂不同类型子阶段)',
|
|
131
|
-
'request - 需求(不关联需求、不测、不构建、不导入 Bug)',
|
|
132
|
-
'design - 设计(不测、不构建、不 DevOps)',
|
|
133
|
-
'dev - 开发(功能完整,可需求、任务、测试、构建)',
|
|
134
|
-
'qa - 测试(同上,偏测试)',
|
|
135
|
-
'release - 发布(同上,偏发布)',
|
|
136
|
-
'review - 总结评审(最严:不关联需求、不测、不构建)',
|
|
137
|
-
'other - 其他(无上述专项限制)'
|
|
138
|
-
].join(' | '),
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
114
|
if (!properties.milestone) {
|
|
142
115
|
properties.milestone = {
|
|
143
116
|
type: 'integer',
|
|
@@ -145,13 +118,6 @@ export function applyBuiltinOverrides() {
|
|
|
145
118
|
format: 'int32'
|
|
146
119
|
};
|
|
147
120
|
}
|
|
148
|
-
if (!properties.parent) {
|
|
149
|
-
properties.parent = {
|
|
150
|
-
type: 'integer',
|
|
151
|
-
description: '父级项目',
|
|
152
|
-
format: 'int32'
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
121
|
}
|
|
156
122
|
return action;
|
|
157
123
|
});
|
|
@@ -179,34 +145,6 @@ export function applyBuiltinOverrides() {
|
|
|
179
145
|
}
|
|
180
146
|
return action;
|
|
181
147
|
});
|
|
182
|
-
// 修改 BUG 列表选项
|
|
183
|
-
extendModuleAction('bug', 'list', (action) => {
|
|
184
|
-
const params = action.params;
|
|
185
|
-
const browseTypeParam = params?.find((param) => param.name === 'browseType');
|
|
186
|
-
if (browseTypeParam && browseTypeParam.options?.length) {
|
|
187
|
-
const options = browseTypeParam.options;
|
|
188
|
-
const assignedtomeOption = options.find(x => x.value === 'assignedtome');
|
|
189
|
-
if (assignedtomeOption) {
|
|
190
|
-
browseTypeParam.options = [
|
|
191
|
-
...options.filter(x => x !== assignedtomeOption),
|
|
192
|
-
{
|
|
193
|
-
...assignedtomeOption,
|
|
194
|
-
value: 'assigntome',
|
|
195
|
-
}
|
|
196
|
-
];
|
|
197
|
-
}
|
|
198
|
-
if (!browseTypeParam.options.some(x => x.value === 'resolvedbyme')) {
|
|
199
|
-
browseTypeParam.options = [
|
|
200
|
-
...browseTypeParam.options,
|
|
201
|
-
{
|
|
202
|
-
value: 'resolvedbyme',
|
|
203
|
-
label: '由我解决',
|
|
204
|
-
}
|
|
205
|
-
];
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return action;
|
|
209
|
-
});
|
|
210
148
|
// 获取文档详情时支持将文档原始 JSON 内容转换为 Markdown
|
|
211
149
|
extendModuleAction('doc', 'get', (action) => {
|
|
212
150
|
const oldGetter = action.resultGetter;
|
|
@@ -239,4 +177,39 @@ export function applyBuiltinOverrides() {
|
|
|
239
177
|
};
|
|
240
178
|
return action;
|
|
241
179
|
});
|
|
180
|
+
// 定义获取需求层级操作
|
|
181
|
+
defineModuleActions('story', {
|
|
182
|
+
name: 'getGrades',
|
|
183
|
+
minVersion: ['22.5', 'biz13.5', 'max8.5', 'ipd5.5'],
|
|
184
|
+
display: '获取需求层级选项',
|
|
185
|
+
type: 'list',
|
|
186
|
+
method: 'get',
|
|
187
|
+
path: '/storygrades',
|
|
188
|
+
resultType: 'list',
|
|
189
|
+
resultGetter: 'grades',
|
|
190
|
+
});
|
|
191
|
+
// 需求创建时支持设置需求层级
|
|
192
|
+
extendModuleAction('story', 'create', (action) => {
|
|
193
|
+
const properties = action.requestBody.schema?.properties;
|
|
194
|
+
if (properties && !properties.grade) {
|
|
195
|
+
properties.grade = {
|
|
196
|
+
type: 'integer',
|
|
197
|
+
description: '需求层级,可用的需求层级可以通过 story-getGrades 操作获取',
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return action;
|
|
201
|
+
});
|
|
202
|
+
// 创建和修改任务时,任务类型字段
|
|
203
|
+
['create', 'update'].forEach((actionName) => {
|
|
204
|
+
extendModuleAction('task', actionName, (action) => {
|
|
205
|
+
const properties = action.requestBody.schema?.properties;
|
|
206
|
+
if (properties && !properties.type) {
|
|
207
|
+
properties.type = {
|
|
208
|
+
type: 'string',
|
|
209
|
+
description: '任务类型(枚举:design 设计 | devel 开发 | request 需求 | test 测试 | study 研究 | discuss 讨论 | ui 界面 | affair 事务 | misc 其他)',
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
return action;
|
|
213
|
+
});
|
|
214
|
+
});
|
|
242
215
|
}
|
package/dist/modules/query.d.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import type { ModuleAction, ModuleActionParam, ModuleActionParamRole, ModuleDefinition } from '../types/index.js';
|
|
1
|
+
import type { ModuleAction, ModuleActionParam, ModuleActionParamRole, ModuleDefinition, ModuleQueryOptions } from '../types/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* 获取模块定义。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* 模块名匹配大小写不敏感。未传版本时返回注册表内部的已深冻结引用(O(1) 查询、零拷贝),
|
|
6
6
|
* 任何写入尝试在严格模式下会抛 `TypeError`;如需修改请使用 {@link defineModules}。
|
|
7
7
|
*
|
|
8
8
|
* @param moduleName - 模块名。
|
|
9
|
-
* @
|
|
9
|
+
* @param options - 可选版本过滤;不传时保留完整注册表引用,传入时返回冻结的过滤视图。
|
|
10
|
+
* @returns 已注册的模块定义;模块未注册或过滤后没有动作时返回 `undefined`。
|
|
10
11
|
*/
|
|
11
|
-
export declare function getModule(moduleName: string): ModuleDefinition | undefined;
|
|
12
|
+
export declare function getModule(moduleName: string, options?: ModuleQueryOptions): ModuleDefinition | undefined;
|
|
12
13
|
/**
|
|
13
14
|
* 获取指定模块下的某个动作。
|
|
14
15
|
*
|
|
15
16
|
* 解析顺序:
|
|
16
17
|
* 1. `actionName === 'ls'` 时映射为 `list`(仅作为别名,不会修改注册表)。
|
|
17
18
|
* 2. 在该模块的动作中按名称大小写不敏感匹配。
|
|
18
|
-
* 3. 当请求的动作不是基础 CRUD(`list`/`get`/`create`/`update`/`delete`)时,
|
|
19
|
-
* 额外允许命中 `type === 'action'` 的自定义动作(即使名字不在基础 CRUD 中)。
|
|
20
19
|
*
|
|
21
20
|
* 返回值同样是已深冻结的引用,请勿尝试修改。
|
|
22
21
|
*
|
|
23
22
|
* @param moduleName - 模块名(大小写不敏感)。
|
|
24
23
|
* @param actionName - 动作名(大小写不敏感);支持 `ls` 作为 `list` 的别名。
|
|
24
|
+
* @param options - 可选版本过滤。
|
|
25
25
|
* @returns 匹配到的动作定义;模块未注册或动作不存在时返回 `undefined`。
|
|
26
26
|
*/
|
|
27
|
-
export declare function getModuleAction(moduleName: string, actionName: string): ModuleAction | undefined;
|
|
27
|
+
export declare function getModuleAction(moduleName: string, actionName: string, options?: ModuleQueryOptions): ModuleAction | undefined;
|
|
28
28
|
/**
|
|
29
29
|
* 获取指定模块下的某个动作的参数。
|
|
30
30
|
*
|
|
@@ -32,9 +32,10 @@ export declare function getModuleAction(moduleName: string, actionName: string):
|
|
|
32
32
|
* @param actionName - 动作名(大小写不敏感);支持 `ls` 作为 `list` 的别名。
|
|
33
33
|
* @param options - 选项。
|
|
34
34
|
* @param options.roles - 角色,可选 `path`、`query`、`body`。
|
|
35
|
+
* @param options.version - 可选禅道版本;不支持该动作时返回空数组,不做参数级版本过滤。
|
|
35
36
|
* @returns 动作参数。
|
|
36
37
|
*/
|
|
37
|
-
export declare function getModuleActionParams(moduleName: string, actionName: string, options?: {
|
|
38
|
+
export declare function getModuleActionParams(moduleName: string, actionName: string, options?: ModuleQueryOptions & {
|
|
38
39
|
roles?: ModuleActionParamRole[];
|
|
39
40
|
}): ModuleActionParam[];
|
|
40
41
|
/**
|
|
@@ -43,15 +44,17 @@ export declare function getModuleActionParams(moduleName: string, actionName: st
|
|
|
43
44
|
* 顺序与模块写入注册表的顺序一致;包括内置模块和通过 {@link defineModules} 追加的用户模块。
|
|
44
45
|
*
|
|
45
46
|
* @returns 模块名数组(保留原始大小写)。
|
|
47
|
+
* @param options - 可选版本过滤,仅保留含有支持动作的模块。
|
|
46
48
|
*/
|
|
47
|
-
export declare function getModuleNames(): string[];
|
|
49
|
+
export declare function getModuleNames(options?: ModuleQueryOptions): string[];
|
|
48
50
|
/**
|
|
49
51
|
* 判断模块名是否已注册。
|
|
50
52
|
*
|
|
51
53
|
* @param moduleName - 模块名;匹配大小写不敏感。
|
|
54
|
+
* @param options - 可选版本过滤。
|
|
52
55
|
* @returns 已注册返回 `true`,否则 `false`。
|
|
53
56
|
*/
|
|
54
|
-
export declare function isModuleName(moduleName: string): boolean;
|
|
57
|
+
export declare function isModuleName(moduleName: string, options?: ModuleQueryOptions): boolean;
|
|
55
58
|
/**
|
|
56
59
|
* 获取对象属性。
|
|
57
60
|
*
|
package/dist/modules/query.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
+
import { parseZentaoVersion, supportsZentaoVersion } from '../misc/zentao-version.js';
|
|
1
2
|
import { objectProps } from './object-props.js';
|
|
2
3
|
import { getModuleMapState, getModulesState } from './registry-store.js';
|
|
3
4
|
/**
|
|
4
5
|
* 获取模块定义。
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
+
* 模块名匹配大小写不敏感。未传版本时返回注册表内部的已深冻结引用(O(1) 查询、零拷贝),
|
|
7
8
|
* 任何写入尝试在严格模式下会抛 `TypeError`;如需修改请使用 {@link defineModules}。
|
|
8
9
|
*
|
|
9
10
|
* @param moduleName - 模块名。
|
|
10
|
-
* @
|
|
11
|
+
* @param options - 可选版本过滤;不传时保留完整注册表引用,传入时返回冻结的过滤视图。
|
|
12
|
+
* @returns 已注册的模块定义;模块未注册或过滤后没有动作时返回 `undefined`。
|
|
11
13
|
*/
|
|
12
|
-
export function getModule(moduleName) {
|
|
13
|
-
|
|
14
|
+
export function getModule(moduleName, options = {}) {
|
|
15
|
+
const version = options.version === undefined ? undefined : parseZentaoVersion(options.version);
|
|
16
|
+
const module = getModuleMapState().get(moduleName.toLowerCase());
|
|
17
|
+
if (!version || !module)
|
|
18
|
+
return module;
|
|
19
|
+
const actions = module.actions.filter(action => supportsZentaoVersion(version, action.minVersion));
|
|
20
|
+
return actions.length ? Object.freeze({ ...module, actions: Object.freeze(actions) }) : undefined;
|
|
14
21
|
}
|
|
15
22
|
/**
|
|
16
23
|
* 获取指定模块下的某个动作。
|
|
@@ -18,30 +25,20 @@ export function getModule(moduleName) {
|
|
|
18
25
|
* 解析顺序:
|
|
19
26
|
* 1. `actionName === 'ls'` 时映射为 `list`(仅作为别名,不会修改注册表)。
|
|
20
27
|
* 2. 在该模块的动作中按名称大小写不敏感匹配。
|
|
21
|
-
* 3. 当请求的动作不是基础 CRUD(`list`/`get`/`create`/`update`/`delete`)时,
|
|
22
|
-
* 额外允许命中 `type === 'action'` 的自定义动作(即使名字不在基础 CRUD 中)。
|
|
23
28
|
*
|
|
24
29
|
* 返回值同样是已深冻结的引用,请勿尝试修改。
|
|
25
30
|
*
|
|
26
31
|
* @param moduleName - 模块名(大小写不敏感)。
|
|
27
32
|
* @param actionName - 动作名(大小写不敏感);支持 `ls` 作为 `list` 的别名。
|
|
33
|
+
* @param options - 可选版本过滤。
|
|
28
34
|
* @returns 匹配到的动作定义;模块未注册或动作不存在时返回 `undefined`。
|
|
29
35
|
*/
|
|
30
|
-
export function getModuleAction(moduleName, actionName) {
|
|
31
|
-
const module = getModule(moduleName);
|
|
36
|
+
export function getModuleAction(moduleName, actionName, options) {
|
|
37
|
+
const module = getModule(moduleName, options);
|
|
32
38
|
if (!module)
|
|
33
39
|
return undefined;
|
|
34
40
|
const normalized = actionName === 'ls' ? 'list' : actionName;
|
|
35
|
-
|
|
36
|
-
if (direct)
|
|
37
|
-
return direct;
|
|
38
|
-
const crud = new Set(['list', 'get', 'create', 'update', 'delete']);
|
|
39
|
-
if (!crud.has(normalized)) {
|
|
40
|
-
const custom = module.actions.find((action) => action.type === 'action' && String(action.name).toLowerCase() === normalized.toLowerCase());
|
|
41
|
-
if (custom)
|
|
42
|
-
return custom;
|
|
43
|
-
}
|
|
44
|
-
return undefined;
|
|
41
|
+
return module.actions.find((action) => String(action.name).toLowerCase() === normalized.toLowerCase());
|
|
45
42
|
}
|
|
46
43
|
/**
|
|
47
44
|
* 获取指定模块下的某个动作的参数。
|
|
@@ -50,12 +47,13 @@ export function getModuleAction(moduleName, actionName) {
|
|
|
50
47
|
* @param actionName - 动作名(大小写不敏感);支持 `ls` 作为 `list` 的别名。
|
|
51
48
|
* @param options - 选项。
|
|
52
49
|
* @param options.roles - 角色,可选 `path`、`query`、`body`。
|
|
50
|
+
* @param options.version - 可选禅道版本;不支持该动作时返回空数组,不做参数级版本过滤。
|
|
53
51
|
* @returns 动作参数。
|
|
54
52
|
*/
|
|
55
53
|
export function getModuleActionParams(moduleName, actionName, options) {
|
|
56
54
|
const { roles } = options ?? {};
|
|
57
55
|
const params = [];
|
|
58
|
-
const action = getModuleAction(moduleName, actionName);
|
|
56
|
+
const action = getModuleAction(moduleName, actionName, options);
|
|
59
57
|
if (!action) {
|
|
60
58
|
return [];
|
|
61
59
|
}
|
|
@@ -82,12 +80,13 @@ export function getModuleActionParams(moduleName, actionName, options) {
|
|
|
82
80
|
if (schema.type === 'object') {
|
|
83
81
|
const requiredSet = new Set(schema.required ? schema.required.map(x => x.toLowerCase()) : []);
|
|
84
82
|
Object.entries(schema.properties).forEach(([name, property]) => {
|
|
83
|
+
const propertyType = property.type;
|
|
85
84
|
params.push({
|
|
85
|
+
...property,
|
|
86
86
|
name,
|
|
87
87
|
role: 'body',
|
|
88
88
|
required: property.required ?? requiredSet.has(name.toLowerCase()),
|
|
89
|
-
type:
|
|
90
|
-
...property,
|
|
89
|
+
type: propertyType === 'integer' ? 'number' : propertyType ?? 'string',
|
|
91
90
|
});
|
|
92
91
|
});
|
|
93
92
|
}
|
|
@@ -108,18 +107,23 @@ export function getModuleActionParams(moduleName, actionName, options) {
|
|
|
108
107
|
* 顺序与模块写入注册表的顺序一致;包括内置模块和通过 {@link defineModules} 追加的用户模块。
|
|
109
108
|
*
|
|
110
109
|
* @returns 模块名数组(保留原始大小写)。
|
|
110
|
+
* @param options - 可选版本过滤,仅保留含有支持动作的模块。
|
|
111
111
|
*/
|
|
112
|
-
export function getModuleNames() {
|
|
113
|
-
|
|
112
|
+
export function getModuleNames(options = {}) {
|
|
113
|
+
const version = options.version === undefined ? undefined : parseZentaoVersion(options.version);
|
|
114
|
+
return getModulesState()
|
|
115
|
+
.filter(module => !version || module.actions.some(action => supportsZentaoVersion(version, action.minVersion)))
|
|
116
|
+
.map(module => module.name);
|
|
114
117
|
}
|
|
115
118
|
/**
|
|
116
119
|
* 判断模块名是否已注册。
|
|
117
120
|
*
|
|
118
121
|
* @param moduleName - 模块名;匹配大小写不敏感。
|
|
122
|
+
* @param options - 可选版本过滤。
|
|
119
123
|
* @returns 已注册返回 `true`,否则 `false`。
|
|
120
124
|
*/
|
|
121
|
-
export function isModuleName(moduleName) {
|
|
122
|
-
return
|
|
125
|
+
export function isModuleName(moduleName, options) {
|
|
126
|
+
return getModule(moduleName, options) !== undefined;
|
|
123
127
|
}
|
|
124
128
|
/**
|
|
125
129
|
* 获取对象属性。
|
|
@@ -128,5 +132,5 @@ export function isModuleName(moduleName) {
|
|
|
128
132
|
* @returns 对象属性。
|
|
129
133
|
*/
|
|
130
134
|
export function getObjectProps(objectType) {
|
|
131
|
-
return objectProps[objectType];
|
|
135
|
+
return objectProps[objectType] ?? {};
|
|
132
136
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ZentaoError } from '../misc/errors.js';
|
|
2
|
+
import { validateMinVersion } from '../misc/zentao-version.js';
|
|
2
3
|
import { isRecord } from '../utils/object.js';
|
|
3
4
|
import { BUILTIN_MODULES } from './generated.js';
|
|
4
5
|
// 动作类型到 HTTP 方法 / 结果形态的默认推导表:当动作未显式声明 method / resultType 时按 type 补齐。
|
|
@@ -99,6 +100,7 @@ export function normalizeAction(action) {
|
|
|
99
100
|
return action;
|
|
100
101
|
}
|
|
101
102
|
export function freezeAction(action) {
|
|
103
|
+
validateAction(action);
|
|
102
104
|
return deepFreeze(normalizeAction(action));
|
|
103
105
|
}
|
|
104
106
|
export function freezeModule(module) {
|
|
@@ -146,6 +148,7 @@ export function validateAction(action) {
|
|
|
146
148
|
if (!action || typeof action.name !== 'string' || typeof action.path !== 'string') {
|
|
147
149
|
throw new ZentaoError('E_INVALID_ACTION_DEFINITION');
|
|
148
150
|
}
|
|
151
|
+
validateMinVersion(action.minVersion);
|
|
149
152
|
// method / resultType 可省略(由 normalizeAction 按 type 推导),但显式给出时必须是字符串。
|
|
150
153
|
if (action.method !== undefined && typeof action.method !== 'string') {
|
|
151
154
|
throw new ZentaoError('E_INVALID_ACTION_DEFINITION');
|