devops-mcp-server-extension 1.0.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/LICENSE +218 -0
- package/README.md +527 -0
- package/README.zh-cn.md +503 -0
- package/dist/common/errors.js +77 -0
- package/dist/common/modularTemplates.js +483 -0
- package/dist/common/pipelineTemplates.js +19 -0
- package/dist/common/toolsetManager.js +123 -0
- package/dist/common/toolsets.js +23 -0
- package/dist/common/types.js +60 -0
- package/dist/common/utils.js +381 -0
- package/dist/common/version.js +1 -0
- package/dist/index.js +225 -0
- package/dist/operations/appstack/appOrchestrations.js +260 -0
- package/dist/operations/appstack/appTags.js +168 -0
- package/dist/operations/appstack/appTemplates.js +72 -0
- package/dist/operations/appstack/applications.js +171 -0
- package/dist/operations/appstack/changeOrders.js +320 -0
- package/dist/operations/appstack/changeRequests.js +288 -0
- package/dist/operations/appstack/deploymentResources.js +286 -0
- package/dist/operations/appstack/globalVars.js +221 -0
- package/dist/operations/appstack/releaseWorkflows.js +695 -0
- package/dist/operations/appstack/variableGroups.js +245 -0
- package/dist/operations/codeup/branches.js +157 -0
- package/dist/operations/codeup/changeRequestComments.js +140 -0
- package/dist/operations/codeup/changeRequests.js +230 -0
- package/dist/operations/codeup/commits.js +121 -0
- package/dist/operations/codeup/compare.js +30 -0
- package/dist/operations/codeup/files.js +249 -0
- package/dist/operations/codeup/repositories.js +71 -0
- package/dist/operations/codeup/types.js +414 -0
- package/dist/operations/flow/hostGroup.js +52 -0
- package/dist/operations/flow/pipeline.js +609 -0
- package/dist/operations/flow/pipelineJob.js +126 -0
- package/dist/operations/flow/resourceMember.js +137 -0
- package/dist/operations/flow/serviceConnection.js +27 -0
- package/dist/operations/flow/tag.js +191 -0
- package/dist/operations/flow/types.js +523 -0
- package/dist/operations/flow/vmDeployOrder.js +171 -0
- package/dist/operations/organization/members.js +106 -0
- package/dist/operations/organization/organization.js +110 -0
- package/dist/operations/organization/types.js +111 -0
- package/dist/operations/packages/artifacts.js +71 -0
- package/dist/operations/packages/repositories.js +39 -0
- package/dist/operations/packages/types.js +56 -0
- package/dist/operations/projex/effort.js +122 -0
- package/dist/operations/projex/project.js +243 -0
- package/dist/operations/projex/sprint.js +103 -0
- package/dist/operations/projex/types.js +618 -0
- package/dist/operations/projex/workitem.js +826 -0
- package/dist/operations/testhub/testcases.js +240 -0
- package/dist/operations/testhub/testplans.js +128 -0
- package/dist/tool-handlers/appstack-app-release-workflows.js +103 -0
- package/dist/tool-handlers/appstack-change-orders.js +55 -0
- package/dist/tool-handlers/appstack-change-requests.js +49 -0
- package/dist/tool-handlers/appstack-deployment-resources.js +31 -0
- package/dist/tool-handlers/appstack-global-vars.js +37 -0
- package/dist/tool-handlers/appstack-orchestrations.js +49 -0
- package/dist/tool-handlers/appstack-release-workflows.js +37 -0
- package/dist/tool-handlers/appstack-tags.js +37 -0
- package/dist/tool-handlers/appstack-templates.js +19 -0
- package/dist/tool-handlers/appstack-variable-groups.js +55 -0
- package/dist/tool-handlers/appstack.js +37 -0
- package/dist/tool-handlers/base.js +25 -0
- package/dist/tool-handlers/code-management.js +150 -0
- package/dist/tool-handlers/commit.js +31 -0
- package/dist/tool-handlers/effort.js +103 -0
- package/dist/tool-handlers/index.js +119 -0
- package/dist/tool-handlers/organization.js +72 -0
- package/dist/tool-handlers/packages.js +32 -0
- package/dist/tool-handlers/pipeline.js +289 -0
- package/dist/tool-handlers/project-management.js +201 -0
- package/dist/tool-handlers/resourceMember.js +43 -0
- package/dist/tool-handlers/service-connections.js +16 -0
- package/dist/tool-handlers/tag.js +64 -0
- package/dist/tool-handlers/test-management.js +74 -0
- package/dist/tool-handlers/vmDeployOrder.js +50 -0
- package/dist/tool-registry/appstack-app-release-workflows.js +80 -0
- package/dist/tool-registry/appstack-change-orders.js +40 -0
- package/dist/tool-registry/appstack-change-requests.js +35 -0
- package/dist/tool-registry/appstack-deployment-resources.js +20 -0
- package/dist/tool-registry/appstack-global-vars.js +25 -0
- package/dist/tool-registry/appstack-orchestrations.js +35 -0
- package/dist/tool-registry/appstack-release-workflows.js +25 -0
- package/dist/tool-registry/appstack-tags.js +25 -0
- package/dist/tool-registry/appstack-templates.js +10 -0
- package/dist/tool-registry/appstack-variable-groups.js +40 -0
- package/dist/tool-registry/appstack.js +25 -0
- package/dist/tool-registry/base.js +19 -0
- package/dist/tool-registry/code-management.js +109 -0
- package/dist/tool-registry/commit.js +20 -0
- package/dist/tool-registry/effort.js +39 -0
- package/dist/tool-registry/index.js +7 -0
- package/dist/tool-registry/organization.js +65 -0
- package/dist/tool-registry/packages.js +21 -0
- package/dist/tool-registry/pipeline.js +190 -0
- package/dist/tool-registry/project-management.js +143 -0
- package/dist/tool-registry/resourceMember.js +29 -0
- package/dist/tool-registry/service-connections.js +10 -0
- package/dist/tool-registry/tag.js +44 -0
- package/dist/tool-registry/test-management.js +59 -0
- package/dist/tool-registry/vmDeployOrder.js +34 -0
- package/package.json +52 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { yunxiaoRequest, isRegionEdition } from "../../common/utils.js";
|
|
3
|
+
import { resolveOrganizationId } from "../organization/organization.js";
|
|
4
|
+
import { EffortRecordSchema, EstimatedEffortSchema, IdentifierDTOSchema, ListCurrentUserEffortRecordsSchema, ListEffortRecordsSchema, CreateEffortRecordRequestSchema, ListEstimatedEffortsSchema, CreateEstimatedEffortRequestSchema } from "./types.js";
|
|
5
|
+
// List current user effort records
|
|
6
|
+
export async function listCurrentUserEffortRecords(params) {
|
|
7
|
+
const validatedParams = ListCurrentUserEffortRecordsSchema.parse(params);
|
|
8
|
+
const finalOrgId = await resolveOrganizationId(validatedParams.organizationId);
|
|
9
|
+
const url = isRegionEdition()
|
|
10
|
+
? `/oapi/v1/projex/effortRecords`
|
|
11
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/effortRecords`;
|
|
12
|
+
const queryParams = {
|
|
13
|
+
startDate: validatedParams.startDate,
|
|
14
|
+
endDate: validatedParams.endDate
|
|
15
|
+
};
|
|
16
|
+
const response = await yunxiaoRequest(`${url}?startDate=${queryParams.startDate}&endDate=${queryParams.endDate}`, {
|
|
17
|
+
method: "GET"
|
|
18
|
+
});
|
|
19
|
+
return z.array(EffortRecordSchema).parse(response);
|
|
20
|
+
}
|
|
21
|
+
// List effort records
|
|
22
|
+
export async function listEffortRecords(params) {
|
|
23
|
+
const validatedParams = ListEffortRecordsSchema.parse(params);
|
|
24
|
+
const finalOrgId = await resolveOrganizationId(validatedParams.organizationId);
|
|
25
|
+
const url = isRegionEdition()
|
|
26
|
+
? `/oapi/v1/projex/workitems/${validatedParams.id}/effortRecords`
|
|
27
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${validatedParams.id}/effortRecords`;
|
|
28
|
+
const response = await yunxiaoRequest(url, {
|
|
29
|
+
method: "GET"
|
|
30
|
+
});
|
|
31
|
+
return z.array(EffortRecordSchema).parse(response);
|
|
32
|
+
}
|
|
33
|
+
// Create effort record
|
|
34
|
+
export async function createEffortRecord(params) {
|
|
35
|
+
const validatedParams = CreateEffortRecordRequestSchema.parse({
|
|
36
|
+
actualTime: params.actualTime,
|
|
37
|
+
description: params.description,
|
|
38
|
+
gmtEnd: params.gmtEnd,
|
|
39
|
+
gmtStart: params.gmtStart,
|
|
40
|
+
operatorId: params.operatorId,
|
|
41
|
+
workType: params.workType
|
|
42
|
+
});
|
|
43
|
+
const finalOrgId = await resolveOrganizationId(params.organizationId);
|
|
44
|
+
const url = isRegionEdition()
|
|
45
|
+
? `/oapi/v1/projex/workitems/${params.id}/effortRecords`
|
|
46
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${params.id}/effortRecords`;
|
|
47
|
+
const response = await yunxiaoRequest(url, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: validatedParams
|
|
50
|
+
});
|
|
51
|
+
return IdentifierDTOSchema.parse(response);
|
|
52
|
+
}
|
|
53
|
+
// List estimated efforts
|
|
54
|
+
export async function listEstimatedEfforts(params) {
|
|
55
|
+
const validatedParams = ListEstimatedEffortsSchema.parse(params);
|
|
56
|
+
const finalOrgId = await resolveOrganizationId(validatedParams.organizationId);
|
|
57
|
+
const url = isRegionEdition()
|
|
58
|
+
? `/oapi/v1/projex/workitems/${validatedParams.id}/estimatedEfforts`
|
|
59
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${validatedParams.id}/estimatedEfforts`;
|
|
60
|
+
const response = await yunxiaoRequest(url, {
|
|
61
|
+
method: "GET"
|
|
62
|
+
});
|
|
63
|
+
return z.array(EstimatedEffortSchema).parse(response);
|
|
64
|
+
}
|
|
65
|
+
// Create estimated effort
|
|
66
|
+
export async function createEstimatedEffort(params) {
|
|
67
|
+
const validatedParams = CreateEstimatedEffortRequestSchema.parse({
|
|
68
|
+
description: params.description,
|
|
69
|
+
operatorId: params.operatorId,
|
|
70
|
+
owner: params.owner,
|
|
71
|
+
spentTime: params.spentTime,
|
|
72
|
+
workType: params.workType
|
|
73
|
+
});
|
|
74
|
+
const finalOrgId = await resolveOrganizationId(params.organizationId);
|
|
75
|
+
const url = isRegionEdition()
|
|
76
|
+
? `/oapi/v1/projex/workitems/${params.id}/estimatedEfforts`
|
|
77
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${params.id}/estimatedEfforts`;
|
|
78
|
+
const response = await yunxiaoRequest(url, {
|
|
79
|
+
method: "POST",
|
|
80
|
+
body: validatedParams
|
|
81
|
+
});
|
|
82
|
+
return IdentifierDTOSchema.parse(response);
|
|
83
|
+
}
|
|
84
|
+
// Update effort record
|
|
85
|
+
export async function updateEffortRecord(params) {
|
|
86
|
+
const validatedParams = CreateEffortRecordRequestSchema.parse({
|
|
87
|
+
actualTime: params.actualTime,
|
|
88
|
+
description: params.description,
|
|
89
|
+
gmtEnd: params.gmtEnd,
|
|
90
|
+
gmtStart: params.gmtStart,
|
|
91
|
+
operatorId: params.operatorId,
|
|
92
|
+
workType: params.workType
|
|
93
|
+
});
|
|
94
|
+
const finalOrgId = await resolveOrganizationId(params.organizationId);
|
|
95
|
+
const url = isRegionEdition()
|
|
96
|
+
? `/oapi/v1/projex/workitems/${params.workitemId}/effortRecords/${params.id}`
|
|
97
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${params.workitemId}/effortRecords/${params.id}`;
|
|
98
|
+
const response = await yunxiaoRequest(url, {
|
|
99
|
+
method: "PUT",
|
|
100
|
+
body: validatedParams
|
|
101
|
+
});
|
|
102
|
+
return response;
|
|
103
|
+
}
|
|
104
|
+
// Update estimated effort
|
|
105
|
+
export async function updateEstimatedEffort(params) {
|
|
106
|
+
const validatedParams = CreateEstimatedEffortRequestSchema.parse({
|
|
107
|
+
description: params.description,
|
|
108
|
+
operatorId: params.operatorId,
|
|
109
|
+
owner: params.owner,
|
|
110
|
+
spentTime: params.spentTime,
|
|
111
|
+
workType: params.workType
|
|
112
|
+
});
|
|
113
|
+
const finalOrgId = await resolveOrganizationId(params.organizationId);
|
|
114
|
+
const url = isRegionEdition()
|
|
115
|
+
? `/oapi/v1/projex/workitems/${params.workitemId}/estimatedEfforts/${params.id}`
|
|
116
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/workitems/${params.workitemId}/estimatedEfforts/${params.id}`;
|
|
117
|
+
const response = await yunxiaoRequest(url, {
|
|
118
|
+
method: "PUT",
|
|
119
|
+
body: validatedParams
|
|
120
|
+
});
|
|
121
|
+
return response;
|
|
122
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 项目(Project)相关操作
|
|
3
|
+
*
|
|
4
|
+
* 概念说明:
|
|
5
|
+
* - 项目(Project)是云效平台中的项目管理单元,包含工作项、迭代等管理概念
|
|
6
|
+
* - 项目与代码库(Repository)是不同的概念,代码库属于CodeUp产品,用于代码管理
|
|
7
|
+
* - 一个项目可以关联多个代码库,但两者是不同的资源类型
|
|
8
|
+
*/
|
|
9
|
+
import { yunxiaoRequest, isRegionEdition } from "../../common/utils.js";
|
|
10
|
+
import { resolveOrganizationId } from "../organization/organization.js";
|
|
11
|
+
import { ProjectInfoSchema, ProjectMemberSchema } from "./types.js";
|
|
12
|
+
/**
|
|
13
|
+
* 获取项目详情
|
|
14
|
+
* @param organizationId
|
|
15
|
+
* @param id
|
|
16
|
+
*/
|
|
17
|
+
export async function getProjectFunc(organizationId, id) {
|
|
18
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
19
|
+
const url = isRegionEdition()
|
|
20
|
+
? `/oapi/v1/projex/projects/${id}`
|
|
21
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${id}`;
|
|
22
|
+
const response = await yunxiaoRequest(url, {
|
|
23
|
+
method: "GET",
|
|
24
|
+
});
|
|
25
|
+
return ProjectInfoSchema.parse(response);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 搜索项目
|
|
29
|
+
* @param organizationId
|
|
30
|
+
* @param name
|
|
31
|
+
* @param status
|
|
32
|
+
* @param createdAfter
|
|
33
|
+
* @param createdBefore
|
|
34
|
+
* @param creator
|
|
35
|
+
* @param adminUserId
|
|
36
|
+
* @param logicalStatus
|
|
37
|
+
* @param advancedConditions
|
|
38
|
+
* @param extraConditions
|
|
39
|
+
* @param orderBy
|
|
40
|
+
* @param page
|
|
41
|
+
* @param perPage
|
|
42
|
+
* @param sort
|
|
43
|
+
* @param scenarioFilter
|
|
44
|
+
* @param userId
|
|
45
|
+
*/
|
|
46
|
+
export async function searchProjectsFunc(organizationId, name, status, createdAfter, createdBefore, creator, adminUserId, // Project administrator user ID
|
|
47
|
+
logicalStatus, advancedConditions, extraConditions, // Should be constructed using buildExtraConditions for common filters
|
|
48
|
+
orderBy, // Possible values: "gmtCreate", "name"
|
|
49
|
+
page, perPage, sort, // Possible values: "desc", "asc"
|
|
50
|
+
scenarioFilter, // Common project filter scenarios
|
|
51
|
+
userId // User ID to use with scenarioFilter
|
|
52
|
+
) {
|
|
53
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
54
|
+
const url = isRegionEdition()
|
|
55
|
+
? `/oapi/v1/projex/projects:search`
|
|
56
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects:search`;
|
|
57
|
+
const payload = {};
|
|
58
|
+
if (scenarioFilter && userId) {
|
|
59
|
+
extraConditions = buildExtraConditions(scenarioFilter, userId);
|
|
60
|
+
}
|
|
61
|
+
const conditions = buildProjectConditions({
|
|
62
|
+
name,
|
|
63
|
+
status,
|
|
64
|
+
createdAfter,
|
|
65
|
+
createdBefore,
|
|
66
|
+
creator,
|
|
67
|
+
adminUserId,
|
|
68
|
+
logicalStatus,
|
|
69
|
+
advancedConditions
|
|
70
|
+
});
|
|
71
|
+
if (conditions) {
|
|
72
|
+
payload.conditions = conditions;
|
|
73
|
+
}
|
|
74
|
+
if (extraConditions) {
|
|
75
|
+
payload.extraConditions = extraConditions;
|
|
76
|
+
}
|
|
77
|
+
if (orderBy) {
|
|
78
|
+
payload.orderBy = orderBy;
|
|
79
|
+
}
|
|
80
|
+
if (page !== undefined) {
|
|
81
|
+
payload.page = page;
|
|
82
|
+
}
|
|
83
|
+
if (perPage !== undefined) {
|
|
84
|
+
payload.perPage = perPage;
|
|
85
|
+
}
|
|
86
|
+
if (sort) {
|
|
87
|
+
payload.sort = sort;
|
|
88
|
+
}
|
|
89
|
+
const response = await yunxiaoRequest(url, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
body: payload,
|
|
92
|
+
});
|
|
93
|
+
if (!Array.isArray(response)) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
return response.map(project => ProjectInfoSchema.parse(project));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 构建项目过滤条件(源API所需参数conditions是一个固定的JSON结构)
|
|
100
|
+
* @param args
|
|
101
|
+
*/
|
|
102
|
+
function buildProjectConditions(args) {
|
|
103
|
+
if (args.advancedConditions) {
|
|
104
|
+
return args.advancedConditions;
|
|
105
|
+
}
|
|
106
|
+
const filterConditions = [];
|
|
107
|
+
if (args.name) {
|
|
108
|
+
filterConditions.push({
|
|
109
|
+
className: "string",
|
|
110
|
+
fieldIdentifier: "name",
|
|
111
|
+
format: "input",
|
|
112
|
+
operator: "CONTAINS",
|
|
113
|
+
toValue: null,
|
|
114
|
+
value: [args.name],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (args.status) {
|
|
118
|
+
const statusValues = args.status.split(",");
|
|
119
|
+
const values = statusValues.map(v => v.trim());
|
|
120
|
+
filterConditions.push({
|
|
121
|
+
className: "status",
|
|
122
|
+
fieldIdentifier: "status",
|
|
123
|
+
format: "list",
|
|
124
|
+
operator: "CONTAINS",
|
|
125
|
+
toValue: null,
|
|
126
|
+
value: values,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (args.createdAfter) {
|
|
130
|
+
const createdBefore = args.createdBefore ? `${args.createdBefore} 23:59:59` : null;
|
|
131
|
+
filterConditions.push({
|
|
132
|
+
className: "date",
|
|
133
|
+
fieldIdentifier: "gmtCreate",
|
|
134
|
+
format: "input",
|
|
135
|
+
operator: "BETWEEN",
|
|
136
|
+
toValue: createdBefore,
|
|
137
|
+
value: [`${args.createdAfter} 00:00:00`],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
if (args.creator) {
|
|
141
|
+
const creatorValues = args.creator.split(",");
|
|
142
|
+
const values = creatorValues.map(v => v.trim());
|
|
143
|
+
filterConditions.push({
|
|
144
|
+
className: "user",
|
|
145
|
+
fieldIdentifier: "creator",
|
|
146
|
+
format: "list",
|
|
147
|
+
operator: "CONTAINS",
|
|
148
|
+
toValue: null,
|
|
149
|
+
value: values,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
if (args.adminUserId) {
|
|
153
|
+
const adminValues = args.adminUserId.split(",");
|
|
154
|
+
const values = adminValues.map(v => v.trim());
|
|
155
|
+
filterConditions.push({
|
|
156
|
+
className: "user",
|
|
157
|
+
fieldIdentifier: "project.admin",
|
|
158
|
+
format: "multiList",
|
|
159
|
+
operator: "CONTAINS",
|
|
160
|
+
toValue: null,
|
|
161
|
+
value: values,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (args.logicalStatus) {
|
|
165
|
+
filterConditions.push({
|
|
166
|
+
className: "string",
|
|
167
|
+
fieldIdentifier: "logicalStatus",
|
|
168
|
+
format: "list",
|
|
169
|
+
operator: "CONTAINS",
|
|
170
|
+
toValue: null,
|
|
171
|
+
value: [args.logicalStatus],
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (filterConditions.length === 0) {
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const conditions = {
|
|
178
|
+
conditionGroups: [filterConditions],
|
|
179
|
+
};
|
|
180
|
+
return JSON.stringify(conditions);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* 获取项目成员列表
|
|
184
|
+
* @param organizationId 组织ID
|
|
185
|
+
* @param id 项目唯一标识
|
|
186
|
+
* @param name 名称过滤
|
|
187
|
+
* @param roleId 角色ID过滤,如 project.admin 表示管理员
|
|
188
|
+
*/
|
|
189
|
+
export async function listProjectMembersFunc(organizationId, id, name, roleId) {
|
|
190
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
191
|
+
const url = isRegionEdition()
|
|
192
|
+
? `/oapi/v1/projex/projects/${id}/members`
|
|
193
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${id}/members`;
|
|
194
|
+
const params = {};
|
|
195
|
+
if (name) {
|
|
196
|
+
params.name = name;
|
|
197
|
+
}
|
|
198
|
+
if (roleId) {
|
|
199
|
+
params.roleId = roleId;
|
|
200
|
+
}
|
|
201
|
+
const queryString = Object.keys(params).length > 0
|
|
202
|
+
? '?' + Object.entries(params).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&')
|
|
203
|
+
: '';
|
|
204
|
+
const response = await yunxiaoRequest(url + queryString, {
|
|
205
|
+
method: "GET",
|
|
206
|
+
});
|
|
207
|
+
if (!Array.isArray(response)) {
|
|
208
|
+
return [];
|
|
209
|
+
}
|
|
210
|
+
return response.map(member => ProjectMemberSchema.parse(member));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 项目额外过滤条件
|
|
214
|
+
* @param scenario The filter scenario: "manage" (projects I manage), "participate" (projects I participate in), "favorite" (projects I favorited)
|
|
215
|
+
* @param userId The user ID to filter by
|
|
216
|
+
* @returns JSON string for extraConditions parameter
|
|
217
|
+
*/
|
|
218
|
+
export function buildExtraConditions(scenario, userId) {
|
|
219
|
+
let fieldIdentifier;
|
|
220
|
+
switch (scenario) {
|
|
221
|
+
case "manage":
|
|
222
|
+
fieldIdentifier = "project.admin";
|
|
223
|
+
break;
|
|
224
|
+
case "participate":
|
|
225
|
+
fieldIdentifier = "users";
|
|
226
|
+
break;
|
|
227
|
+
case "favorite":
|
|
228
|
+
fieldIdentifier = "collectMembers";
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
throw new Error(`Unknown scenario: ${scenario}`);
|
|
232
|
+
}
|
|
233
|
+
const conditions = {
|
|
234
|
+
conditionGroups: [[{
|
|
235
|
+
className: "user",
|
|
236
|
+
fieldIdentifier: fieldIdentifier,
|
|
237
|
+
format: "multiList",
|
|
238
|
+
operator: "CONTAINS",
|
|
239
|
+
value: [userId]
|
|
240
|
+
}]]
|
|
241
|
+
};
|
|
242
|
+
return JSON.stringify(conditions);
|
|
243
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { yunxiaoRequest, buildUrl, isRegionEdition } from "../../common/utils.js";
|
|
3
|
+
import { resolveOrganizationId } from "../organization/organization.js";
|
|
4
|
+
import { SprintInfoSchema } from "./types.js";
|
|
5
|
+
// Create Sprint Response Schema
|
|
6
|
+
const CreateSprintResponseSchema = z.object({
|
|
7
|
+
id: z.string().describe("Created sprint ID"),
|
|
8
|
+
});
|
|
9
|
+
export async function getSprintFunc(organizationId, projectId, id) {
|
|
10
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
11
|
+
const url = isRegionEdition()
|
|
12
|
+
? `/oapi/v1/projex/projects/${projectId}/sprints/${id}`
|
|
13
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${projectId}/sprints/${id}`;
|
|
14
|
+
const response = await yunxiaoRequest(url, {
|
|
15
|
+
method: "GET",
|
|
16
|
+
});
|
|
17
|
+
return SprintInfoSchema.parse(response);
|
|
18
|
+
}
|
|
19
|
+
export async function listSprintsFunc(organizationId, id, status, page, perPage) {
|
|
20
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
21
|
+
const baseUrl = isRegionEdition()
|
|
22
|
+
? `/oapi/v1/projex/projects/${id}/sprints`
|
|
23
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${id}/sprints`;
|
|
24
|
+
const queryParams = {};
|
|
25
|
+
if (status !== undefined && status.length > 0) {
|
|
26
|
+
queryParams.status = status.join(',');
|
|
27
|
+
}
|
|
28
|
+
if (page !== undefined) {
|
|
29
|
+
queryParams.page = page;
|
|
30
|
+
}
|
|
31
|
+
if (perPage !== undefined) {
|
|
32
|
+
queryParams.perPage = perPage;
|
|
33
|
+
}
|
|
34
|
+
const url = buildUrl(baseUrl, queryParams);
|
|
35
|
+
const response = await yunxiaoRequest(url, {
|
|
36
|
+
method: "GET",
|
|
37
|
+
});
|
|
38
|
+
if (!Array.isArray(response)) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return response.map(sprint => SprintInfoSchema.parse(sprint));
|
|
42
|
+
}
|
|
43
|
+
export async function createSprintFunc(organizationId, projectId, name, owners, startDate, endDate, description, capacityHours, operatorId) {
|
|
44
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
45
|
+
const url = isRegionEdition()
|
|
46
|
+
? `/oapi/v1/projex/projects/${projectId}/sprints`
|
|
47
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${projectId}/sprints`;
|
|
48
|
+
const requestBody = {
|
|
49
|
+
name,
|
|
50
|
+
owners,
|
|
51
|
+
};
|
|
52
|
+
if (startDate !== undefined) {
|
|
53
|
+
requestBody.startDate = startDate;
|
|
54
|
+
}
|
|
55
|
+
if (endDate !== undefined) {
|
|
56
|
+
requestBody.endDate = endDate;
|
|
57
|
+
}
|
|
58
|
+
if (description !== undefined) {
|
|
59
|
+
requestBody.description = description;
|
|
60
|
+
}
|
|
61
|
+
if (capacityHours !== undefined) {
|
|
62
|
+
requestBody.capacityHours = capacityHours;
|
|
63
|
+
}
|
|
64
|
+
if (operatorId !== undefined) {
|
|
65
|
+
requestBody.operatorId = operatorId;
|
|
66
|
+
}
|
|
67
|
+
const response = await yunxiaoRequest(url, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
body: requestBody,
|
|
70
|
+
});
|
|
71
|
+
return CreateSprintResponseSchema.parse(response);
|
|
72
|
+
}
|
|
73
|
+
export async function updateSprintFunc(organizationId, projectId, id, name, owners, startDate, endDate, description, capacityHours, operatorId) {
|
|
74
|
+
const finalOrgId = await resolveOrganizationId(organizationId);
|
|
75
|
+
const url = isRegionEdition()
|
|
76
|
+
? `/oapi/v1/projex/projects/${projectId}/sprints/${id}`
|
|
77
|
+
: `/oapi/v1/projex/organizations/${finalOrgId}/projects/${projectId}/sprints/${id}`;
|
|
78
|
+
const requestBody = {
|
|
79
|
+
name,
|
|
80
|
+
};
|
|
81
|
+
if (owners !== undefined) {
|
|
82
|
+
requestBody.owners = owners;
|
|
83
|
+
}
|
|
84
|
+
if (startDate !== undefined) {
|
|
85
|
+
requestBody.startDate = startDate;
|
|
86
|
+
}
|
|
87
|
+
if (endDate !== undefined) {
|
|
88
|
+
requestBody.endDate = endDate;
|
|
89
|
+
}
|
|
90
|
+
if (description !== undefined) {
|
|
91
|
+
requestBody.description = description;
|
|
92
|
+
}
|
|
93
|
+
if (capacityHours !== undefined) {
|
|
94
|
+
requestBody.capacityHours = capacityHours;
|
|
95
|
+
}
|
|
96
|
+
if (operatorId !== undefined) {
|
|
97
|
+
requestBody.operatorId = operatorId;
|
|
98
|
+
}
|
|
99
|
+
await yunxiaoRequest(url, {
|
|
100
|
+
method: "PUT",
|
|
101
|
+
body: requestBody,
|
|
102
|
+
});
|
|
103
|
+
}
|