@catchmexz/fedin-vibe-mcp-server 0.1.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.
Files changed (83) hide show
  1. package/LICENSE +202 -0
  2. package/dist/common/errors.js +69 -0
  3. package/dist/common/modularTemplates.js +483 -0
  4. package/dist/common/pipelineTemplates.js +19 -0
  5. package/dist/common/types.js +42 -0
  6. package/dist/common/utils.js +347 -0
  7. package/dist/common/version.js +1 -0
  8. package/dist/index.js +217 -0
  9. package/dist/operations/appstack/appOrchestrations.js +235 -0
  10. package/dist/operations/appstack/appTags.js +147 -0
  11. package/dist/operations/appstack/appTemplates.js +67 -0
  12. package/dist/operations/appstack/applications.js +154 -0
  13. package/dist/operations/appstack/changeOrders.js +293 -0
  14. package/dist/operations/appstack/changeRequests.js +263 -0
  15. package/dist/operations/appstack/deploymentResources.js +265 -0
  16. package/dist/operations/appstack/globalVars.js +200 -0
  17. package/dist/operations/appstack/releaseWorkflows.js +178 -0
  18. package/dist/operations/appstack/variableGroups.js +216 -0
  19. package/dist/operations/codeup/branches.js +144 -0
  20. package/dist/operations/codeup/changeRequestComments.js +89 -0
  21. package/dist/operations/codeup/changeRequests.js +203 -0
  22. package/dist/operations/codeup/compare.js +26 -0
  23. package/dist/operations/codeup/files.js +483 -0
  24. package/dist/operations/codeup/repositories.js +83 -0
  25. package/dist/operations/codeup/types.js +372 -0
  26. package/dist/operations/flow/hostGroup.js +48 -0
  27. package/dist/operations/flow/pipeline.js +530 -0
  28. package/dist/operations/flow/pipelineJob.js +113 -0
  29. package/dist/operations/flow/serviceConnection.js +23 -0
  30. package/dist/operations/flow/types.js +377 -0
  31. package/dist/operations/git/git-repository.js +334 -0
  32. package/dist/operations/git/index.js +210 -0
  33. package/dist/operations/organization/members.js +94 -0
  34. package/dist/operations/organization/organization.js +73 -0
  35. package/dist/operations/organization/types.js +111 -0
  36. package/dist/operations/packages/artifacts.js +64 -0
  37. package/dist/operations/packages/repositories.js +35 -0
  38. package/dist/operations/packages/types.js +56 -0
  39. package/dist/operations/projex/project.js +206 -0
  40. package/dist/operations/projex/sprint.js +90 -0
  41. package/dist/operations/projex/types.js +390 -0
  42. package/dist/operations/projex/workitem.js +452 -0
  43. package/dist/tool-handlers/appstack-change-orders.js +55 -0
  44. package/dist/tool-handlers/appstack-change-requests.js +49 -0
  45. package/dist/tool-handlers/appstack-deployment-resources.js +43 -0
  46. package/dist/tool-handlers/appstack-global-vars.js +43 -0
  47. package/dist/tool-handlers/appstack-orchestrations.js +49 -0
  48. package/dist/tool-handlers/appstack-tags.js +43 -0
  49. package/dist/tool-handlers/appstack-templates.js +19 -0
  50. package/dist/tool-handlers/appstack-variable-groups.js +55 -0
  51. package/dist/tool-handlers/appstack.js +37 -0
  52. package/dist/tool-handlers/code-management.js +174 -0
  53. package/dist/tool-handlers/git/branch-operations.js +1 -0
  54. package/dist/tool-handlers/git/clone-repository.js +36 -0
  55. package/dist/tool-handlers/git/create-branch.js +26 -0
  56. package/dist/tool-handlers/git/get-repository-status.js +33 -0
  57. package/dist/tool-handlers/git/pull-repository.js +27 -0
  58. package/dist/tool-handlers/git/push-repository.js +37 -0
  59. package/dist/tool-handlers/git/switch-branch.js +25 -0
  60. package/dist/tool-handlers/index.js +43 -0
  61. package/dist/tool-handlers/organization.js +90 -0
  62. package/dist/tool-handlers/packages.js +32 -0
  63. package/dist/tool-handlers/pipeline.js +272 -0
  64. package/dist/tool-handlers/project-management.js +152 -0
  65. package/dist/tool-handlers/service-connections.js +16 -0
  66. package/dist/tool-registry/appstack-change-orders.js +40 -0
  67. package/dist/tool-registry/appstack-change-requests.js +35 -0
  68. package/dist/tool-registry/appstack-deployment-resources.js +30 -0
  69. package/dist/tool-registry/appstack-global-vars.js +30 -0
  70. package/dist/tool-registry/appstack-orchestrations.js +35 -0
  71. package/dist/tool-registry/appstack-tags.js +30 -0
  72. package/dist/tool-registry/appstack-templates.js +10 -0
  73. package/dist/tool-registry/appstack-variable-groups.js +40 -0
  74. package/dist/tool-registry/appstack.js +25 -0
  75. package/dist/tool-registry/code-management.js +89 -0
  76. package/dist/tool-registry/git-repository.js +41 -0
  77. package/dist/tool-registry/index.js +6 -0
  78. package/dist/tool-registry/organization.js +65 -0
  79. package/dist/tool-registry/packages.js +21 -0
  80. package/dist/tool-registry/pipeline.js +157 -0
  81. package/dist/tool-registry/project-management.js +108 -0
  82. package/dist/tool-registry/service-connections.js +10 -0
  83. package/package.json +39 -0
@@ -0,0 +1,483 @@
1
+ import { yunxiaoRequest, buildUrl, pathEscape } from "../../common/utils.js";
2
+ import { FileContentSchema, CreateFileResponseSchema, DeleteFileResponseSchema, FileInfoSchema } from "./types.js";
3
+ import * as fs from 'fs';
4
+ import pkg from 'fs-extra';
5
+ import * as path from 'path';
6
+ import minimatch from "minimatch";
7
+ const { removeSync } = pkg;
8
+ function readGitignore(projectPath) {
9
+ const gitignorePath = path.join(projectPath, ".gitignore");
10
+ try {
11
+ const gitignoreContent = fs.readFileSync(gitignorePath, "utf-8");
12
+ const originIgnorePatterns = gitignoreContent
13
+ .split("\n")
14
+ .filter((line) => line.trim() !== "" && !line.startsWith("#"))
15
+ .map((pattern) => pattern.trim());
16
+ originIgnorePatterns.push(".git");
17
+ return originIgnorePatterns;
18
+ }
19
+ catch (error) {
20
+ console.warn("No .gitignore file found or error reading it");
21
+ return [];
22
+ }
23
+ }
24
+ function shouldIgnoreFile(filePath, ignorePatterns) {
25
+ const relativePath = path.relative(process.cwd(), filePath);
26
+ return ignorePatterns.some((pattern) => minimatch(relativePath, pattern) ||
27
+ minimatch(path.basename(filePath), pattern));
28
+ }
29
+ // 检测文件是否为二进制文件
30
+ function isBinaryFile(filePath) {
31
+ const binaryExtensions = [
32
+ ".jpg",
33
+ ".jpeg",
34
+ ".png",
35
+ ".gif",
36
+ ".bmp",
37
+ ".webp",
38
+ ".svg",
39
+ ".ico",
40
+ ".pdf",
41
+ ".doc",
42
+ ".docx",
43
+ ".xls",
44
+ ".xlsx",
45
+ ".ppt",
46
+ ".pptx",
47
+ ".zip",
48
+ ".rar",
49
+ ".7z",
50
+ ".tar",
51
+ ".gz",
52
+ ".mp3",
53
+ ".mp4",
54
+ ".avi",
55
+ ".mov",
56
+ ".wmv",
57
+ ".exe",
58
+ ".dll",
59
+ ".so",
60
+ ".dylib",
61
+ ".woff",
62
+ ".woff2",
63
+ ".ttf",
64
+ ".eot"
65
+ ];
66
+ const ext = path.extname(filePath).toLowerCase();
67
+ return binaryExtensions.includes(ext);
68
+ }
69
+ function getAllFiles(dir, ignorePatterns) {
70
+ const files = [];
71
+ function traverseDirectory(currentPath) {
72
+ const entries = fs.readdirSync(currentPath);
73
+ for (const entry of entries) {
74
+ const fullPath = path.join(currentPath, entry);
75
+ const stat = fs.statSync(fullPath);
76
+ if (stat.isDirectory()) {
77
+ // 递归遍历子目录
78
+ if (!shouldIgnoreFile(fullPath, ignorePatterns)) {
79
+ traverseDirectory(fullPath);
80
+ }
81
+ }
82
+ else {
83
+ // 检查是否应该忽略文件
84
+ if (!shouldIgnoreFile(fullPath, ignorePatterns)) {
85
+ try {
86
+ const relativePath = path.relative(dir, fullPath);
87
+ let content;
88
+ let encoding = "text";
89
+ if (isBinaryFile(fullPath)) {
90
+ // 二进制文件使用base64编码
91
+ content = fs.readFileSync(fullPath).toString("base64");
92
+ encoding = "base64";
93
+ }
94
+ else {
95
+ // 文本文件使用utf-8编码
96
+ content = fs.readFileSync(fullPath, "utf-8");
97
+ encoding = "text";
98
+ }
99
+ files.push({
100
+ path: relativePath,
101
+ content: content,
102
+ encoding: encoding
103
+ });
104
+ }
105
+ catch (error) {
106
+ // 对于无法读取的文件,跳过
107
+ console.warn(`Could not read file: ${fullPath}`, error);
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ traverseDirectory(dir);
114
+ return files;
115
+ }
116
+ // Common helper function to handle repositoryId and filePath encoding
117
+ function handlePathEncoding(repositoryId, filePath) {
118
+ let encodedRepoId = repositoryId;
119
+ let encodedFilePath = filePath;
120
+ // 自动处理repositoryId中未编码的斜杠
121
+ if (repositoryId.includes("/")) {
122
+ // 发现未编码的斜杠,自动进行URL编码
123
+ const parts = repositoryId.split("/", 2);
124
+ if (parts.length === 2) {
125
+ const encodedRepoName = encodeURIComponent(parts[1]);
126
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
127
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
128
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
129
+ }
130
+ }
131
+ // 确保filePath已被URL编码
132
+ if (filePath.includes("/")) {
133
+ const startsWithSlash = filePath.startsWith("/");
134
+ if (startsWithSlash) {
135
+ encodedFilePath = encodedFilePath.substring(1);
136
+ }
137
+ encodedFilePath = encodeURIComponent(filePath);
138
+ }
139
+ return { encodedRepoId, encodedFilePath };
140
+ }
141
+ export async function clearProjectPath(projectPath) {
142
+ try {
143
+ // 检查路径是否存在
144
+ if (!fs.existsSync(projectPath)) {
145
+ console.warn(`目录不存在: ${projectPath}`);
146
+ return;
147
+ }
148
+ // 确保是一个目录
149
+ const stats = fs.statSync(projectPath);
150
+ if (!stats.isDirectory()) {
151
+ throw new Error(`提供的路径不是一个目录: ${projectPath}`);
152
+ }
153
+ // 读取目录内容
154
+ const files = fs.readdirSync(projectPath);
155
+ // 遍历并删除所有文件和子目录
156
+ for (const file of files) {
157
+ const currentPath = path.join(projectPath, file);
158
+ removeSync(currentPath);
159
+ }
160
+ console.log(`已成功清空目录: ${projectPath}`);
161
+ }
162
+ catch (error) {
163
+ if (error instanceof Error) {
164
+ console.error(`清空目录时发生错误: ${error.message}`);
165
+ }
166
+ else {
167
+ console.error(`清空目录时发生未知错误: ${String(error)}`);
168
+ }
169
+ throw error;
170
+ }
171
+ }
172
+ /**
173
+ * 查询文件内容
174
+ * @param organizationId
175
+ * @param repositoryId
176
+ * @param filePath
177
+ * @param ref
178
+ */
179
+ export async function getFileBlobsFunc(organizationId, repositoryId, filePath, ref) {
180
+ // const { encodedRepoId, encodedFilePath } = handlePathEncoding(repositoryId, filePath);
181
+ let encodedRepoId = repositoryId;
182
+ let encodedFilePath = filePath;
183
+ // 自动处理repositoryId中未编码的斜杠
184
+ if (repositoryId.includes("/")) {
185
+ // 发现未编码的斜杠,自动进行URL编码
186
+ const parts = repositoryId.split("/", 2);
187
+ if (parts.length === 2) {
188
+ const encodedRepoName = encodeURIComponent(parts[1]);
189
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
190
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
191
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
192
+ }
193
+ }
194
+ // 确保filePath已被URL编码
195
+ if (filePath.includes("/")) {
196
+ encodedFilePath = encodeURIComponent(filePath);
197
+ }
198
+ const baseUrl = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}/files/${encodedFilePath}`;
199
+ // 构建查询参数
200
+ const queryParams = {
201
+ ref: ref
202
+ };
203
+ // 使用buildUrl函数构建包含查询参数的URL
204
+ const url = buildUrl(baseUrl, queryParams);
205
+ const response = await yunxiaoRequest(url, {
206
+ method: "GET"
207
+ });
208
+ return FileContentSchema.parse(response);
209
+ }
210
+ /**
211
+ * 创建文件
212
+ * @param organizationId
213
+ * @param repositoryId
214
+ * @param filePath
215
+ * @param content
216
+ * @param commitMessage
217
+ * @param branch
218
+ * @param encoding
219
+ */
220
+ export async function createFileFunc(organizationId, repositoryId, filePath, content, commitMessage, branch, encoding) {
221
+ let encodedRepoId = repositoryId;
222
+ let encodedFilePath = filePath;
223
+ if (repositoryId.includes("/")) {
224
+ // 发现未编码的斜杠,自动进行URL编码
225
+ const parts = repositoryId.split("/", 2);
226
+ if (parts.length === 2) {
227
+ const encodedRepoName = encodeURIComponent(parts[1]);
228
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
229
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
230
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
231
+ }
232
+ }
233
+ // 确保filePath已被URL编码
234
+ if (filePath.includes("/")) {
235
+ encodedFilePath = pathEscape(filePath);
236
+ }
237
+ const url = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}/files`;
238
+ const body = {
239
+ branch: branch,
240
+ filePath: encodedFilePath,
241
+ content: content,
242
+ commitMessage: commitMessage,
243
+ encoding: encoding || "text" // 默认使用text编码
244
+ };
245
+ const response = await yunxiaoRequest(url, {
246
+ method: "POST",
247
+ body: body
248
+ });
249
+ return CreateFileResponseSchema.parse(response);
250
+ }
251
+ export async function pushFilesFunc(organizationId, repositoryId, commitMessage, projectPath) {
252
+ // 读取 .gitignore 模式
253
+ // const ignorePatterns = readGitignore(projectPath);
254
+ const ignorePatterns = [
255
+ 'dist',
256
+ '.next',
257
+ 'node_modules',
258
+ '.git',
259
+ '.vercel',
260
+ '.cache',
261
+ 'build',
262
+ 'out',
263
+ '.nuxt',
264
+ '.svelte-kit',
265
+ 'package-lock.json',
266
+ '.DS_Store'
267
+ ];
268
+ // 获取所有文件
269
+ const files = getAllFiles(projectPath, ignorePatterns);
270
+ const remoteFileList = await listFilesFunc(organizationId, repositoryId, undefined, "master", "RECURSIVE");
271
+ const remoteFilePathArr = remoteFileList.map((i) => i.path);
272
+ const shouldCreateFiles = files.filter((file) => !remoteFilePathArr.includes(file.path));
273
+ const shouldUpdateFiles = files.filter((file) => remoteFilePathArr.includes(file.path));
274
+ const shouldDeleteFiles = remoteFileList.filter((remoteFile) => !files.some((file) => file.path === remoteFile.path));
275
+ const createFilesSuccess = [];
276
+ const createFileErrors = [];
277
+ const updateFilesSuccess = [];
278
+ const updateFileErrors = [];
279
+ const deleteFilesSuccess = [];
280
+ const deleteFileErrors = [];
281
+ for (let i of shouldCreateFiles) {
282
+ console.error("[创建文件]:", i.path);
283
+ try {
284
+ const result = await createFileFunc(organizationId, repositoryId, i.path, i.content, commitMessage, "master", i.encoding);
285
+ createFilesSuccess.push(result.filePath);
286
+ }
287
+ catch (error) {
288
+ createFileErrors.push(error.message);
289
+ }
290
+ }
291
+ for (let i of shouldUpdateFiles) {
292
+ console.error("[更新文件]:", i.path);
293
+ try {
294
+ const result = await updateFileFunc(organizationId, repositoryId, i.path, i.content, commitMessage, "master", i.encoding);
295
+ updateFilesSuccess.push(result.filePath);
296
+ }
297
+ catch (error) {
298
+ updateFileErrors.push(error.message);
299
+ }
300
+ }
301
+ for (let i of shouldDeleteFiles) {
302
+ console.error("[删除文件]:", i.path);
303
+ try {
304
+ const result = await deleteFileFunc(organizationId, repositoryId, i.path, commitMessage, "master");
305
+ deleteFilesSuccess.push(result.filePath);
306
+ }
307
+ catch (error) {
308
+ deleteFileErrors.push(error.message);
309
+ }
310
+ }
311
+ return {
312
+ createFilesSuccess,
313
+ createFileErrors,
314
+ updateFilesSuccess,
315
+ updateFileErrors,
316
+ deleteFilesSuccess,
317
+ deleteFileErrors
318
+ };
319
+ }
320
+ /**
321
+ * 拉取整个代码库文件
322
+ * @param organizationId
323
+ * @param repositoryId
324
+ * @param projectPath
325
+ */
326
+ export async function pullFilesFunc(organizationId, repositoryId, currntProjectPath) {
327
+ // 拉取之前 需要将当前projectPath路径下的所有代码文件清空
328
+ await clearProjectPath(currntProjectPath);
329
+ const allRemoteFilesPath = await listFilesFunc(organizationId, repositoryId, undefined, "master", "RECURSIVE");
330
+ const allFiles = [];
331
+ for (let i of allRemoteFilesPath) {
332
+ try {
333
+ const fileBlob = await getFileBlobsFunc(organizationId, repositoryId, i.path, "master");
334
+ allFiles.push(fileBlob);
335
+ // 写入文件到本地目录
336
+ const fullPath = path.join(currntProjectPath, i.path);
337
+ // 确保目录存在
338
+ const fileDir = path.dirname(fullPath);
339
+ fs.mkdirSync(fileDir, { recursive: true });
340
+ // 根据编码写入文件
341
+ if (fileBlob.encoding === 'base64') {
342
+ const buffer = Buffer.from(fileBlob.content || '', 'base64');
343
+ fs.writeFileSync(fullPath, buffer);
344
+ }
345
+ else {
346
+ fs.writeFileSync(fullPath, fileBlob.content || '', 'utf-8');
347
+ }
348
+ }
349
+ catch (error) {
350
+ console.error('[获取文件内容失败]:', error);
351
+ }
352
+ }
353
+ return allRemoteFilesPath;
354
+ }
355
+ /**
356
+ * 更新文件内容
357
+ * @param organizationId
358
+ * @param repositoryId
359
+ * @param filePath
360
+ * @param content
361
+ * @param commitMessage
362
+ * @param branch
363
+ * @param encoding
364
+ */
365
+ export async function updateFileFunc(organizationId, repositoryId, filePath, content, commitMessage, branch, encoding) {
366
+ //const { encodedRepoId, encodedFilePath } = handlePathEncoding(repositoryId, filePath);
367
+ let encodedRepoId = repositoryId;
368
+ let encodedFilePath = filePath;
369
+ // 自动处理repositoryId中未编码的斜杠
370
+ if (repositoryId.includes("/")) {
371
+ // 发现未编码的斜杠,自动进行URL编码
372
+ const parts = repositoryId.split("/", 2);
373
+ if (parts.length === 2) {
374
+ const encodedRepoName = encodeURIComponent(parts[1]);
375
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
376
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
377
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
378
+ }
379
+ }
380
+ // 确保filePath已被URL编码
381
+ if (filePath.includes("/")) {
382
+ const pathToEncode = filePath.startsWith("/")
383
+ ? filePath.substring(1)
384
+ : filePath;
385
+ encodedFilePath = encodeURIComponent(pathToEncode);
386
+ }
387
+ const url = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}/files/${encodedFilePath}`;
388
+ const body = {
389
+ branch: branch,
390
+ commitMessage: commitMessage,
391
+ content: content,
392
+ encoding: encoding || "text" // 默认使用text编码
393
+ };
394
+ const response = await yunxiaoRequest(url, {
395
+ method: "PUT",
396
+ body: body
397
+ });
398
+ return CreateFileResponseSchema.parse(response);
399
+ }
400
+ /**
401
+ * 删除文件
402
+ * @param organizationId
403
+ * @param repositoryId
404
+ * @param filePath
405
+ * @param commitMessage
406
+ * @param branch
407
+ */
408
+ export async function deleteFileFunc(organizationId, repositoryId, filePath, commitMessage, branch) {
409
+ let encodedRepoId = repositoryId;
410
+ let encodedFilePath = filePath;
411
+ if (repositoryId.includes("/")) {
412
+ // 发现未编码的斜杠,自动进行URL编码
413
+ const parts = repositoryId.split("/", 2);
414
+ if (parts.length === 2) {
415
+ const encodedRepoName = encodeURIComponent(parts[1]);
416
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
417
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
418
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
419
+ }
420
+ }
421
+ // 确保filePath已被URL编码
422
+ if (filePath.includes("/")) {
423
+ encodedFilePath = encodeURIComponent(filePath);
424
+ }
425
+ const baseUrl = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}/files/${encodedFilePath}`;
426
+ // 构建查询参数
427
+ const queryParams = {
428
+ branch: branch,
429
+ commitMessage: commitMessage
430
+ };
431
+ // 使用buildUrl函数构建包含查询参数的URL
432
+ const url = buildUrl(baseUrl, queryParams);
433
+ const response = await yunxiaoRequest(url, {
434
+ method: "DELETE"
435
+ });
436
+ return DeleteFileResponseSchema.parse(response);
437
+ }
438
+ /**
439
+ * 查询文件树
440
+ * @param organizationId
441
+ * @param repositoryId
442
+ * @param path
443
+ * @param ref
444
+ * @param type
445
+ */
446
+ export async function listFilesFunc(organizationId, repositoryId, path, ref, type // Possible values: DIRECT, RECURSIVE, FLATTEN
447
+ ) {
448
+ // 自动处理repositoryId中未编码的斜杠
449
+ let encodedRepoId = repositoryId;
450
+ if (repositoryId.includes("/")) {
451
+ // 发现未编码的斜杠,自动进行URL编码
452
+ const parts = repositoryId.split("/", 2);
453
+ if (parts.length === 2) {
454
+ const encodedRepoName = encodeURIComponent(parts[1]);
455
+ // 移除编码中的+号(空格被编码为+,但我们需要%20)
456
+ const formattedEncodedName = encodedRepoName.replace(/\+/g, "%20");
457
+ encodedRepoId = `${parts[0]}%2F${formattedEncodedName}`;
458
+ }
459
+ }
460
+ const baseUrl = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}/files/tree`;
461
+ // 构建查询参数
462
+ const queryParams = {};
463
+ if (path) {
464
+ queryParams.path = path;
465
+ }
466
+ if (ref) {
467
+ queryParams.ref = ref;
468
+ }
469
+ if (type) {
470
+ queryParams.type = type;
471
+ }
472
+ // 使用buildUrl函数构建包含查询参数的URL
473
+ const url = buildUrl(baseUrl, queryParams);
474
+ const response = await yunxiaoRequest(url, {
475
+ method: "GET"
476
+ });
477
+ // 确保响应是数组
478
+ if (!Array.isArray(response)) {
479
+ return [];
480
+ }
481
+ // 解析每个文件信息对象
482
+ return response.map((fileInfo) => FileInfoSchema.parse(fileInfo));
483
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * 代码库(Repository)相关操作
3
+ *
4
+ * 概念说明:
5
+ * - 代码库(Repository)是云效平台中的代码管理单元,属于CodeUp产品
6
+ * - 代码库与项目(Project)是不同的概念,项目属于项目管理领域
7
+ * - 代码库用于存储和管理源代码,而项目用于管理工作项、迭代等
8
+ * - 请勿混淆这两个概念,它们是不同的资源类型
9
+ */
10
+ import { yunxiaoRequest, buildUrl, handleRepositoryIdEncoding } from "../../common/utils.js";
11
+ import { RepositorySchema } from "./types.js";
12
+ /**
13
+ * 创建仓库
14
+ * @param organizationId
15
+ * @param name
16
+ * @param description
17
+ */
18
+ export async function createRepositoryFunc(organizationId, name, description) {
19
+ const url = `/oapi/v1/codeup/organizations/${organizationId}/repositories?createParentPath=true`;
20
+ const response = await yunxiaoRequest(url, {
21
+ method: "POST",
22
+ body: {
23
+ name,
24
+ description,
25
+ namespaceId: 1670786,
26
+ path: name
27
+ }
28
+ });
29
+ return RepositorySchema.parse(response);
30
+ }
31
+ /**
32
+ * 查询仓库详情
33
+ * @param organizationId
34
+ * @param repositoryId
35
+ */
36
+ export async function getRepositoryFunc(organizationId, repositoryId) {
37
+ const encodedRepoId = handleRepositoryIdEncoding(repositoryId);
38
+ const url = `/oapi/v1/codeup/organizations/${organizationId}/repositories/${encodedRepoId}`;
39
+ const response = await yunxiaoRequest(url, {
40
+ method: "GET"
41
+ });
42
+ return RepositorySchema.parse(response);
43
+ }
44
+ /**
45
+ * 查询仓库列表
46
+ * @param organizationId
47
+ * @param page
48
+ * @param perPage
49
+ * @param orderBy
50
+ * @param sort
51
+ * @param search
52
+ * @param archived
53
+ */
54
+ export async function listRepositoriesFunc(organizationId, page, perPage, orderBy, sort, search, archived) {
55
+ const baseUrl = `/oapi/v1/codeup/organizations/${organizationId}/repositories`;
56
+ const queryParams = {};
57
+ if (page !== undefined) {
58
+ queryParams.page = page;
59
+ }
60
+ if (perPage !== undefined) {
61
+ queryParams.perPage = perPage;
62
+ }
63
+ if (orderBy !== undefined) {
64
+ queryParams.orderBy = orderBy;
65
+ }
66
+ if (sort !== undefined) {
67
+ queryParams.sort = sort;
68
+ }
69
+ if (search !== undefined) {
70
+ queryParams.search = search;
71
+ }
72
+ if (archived !== undefined) {
73
+ queryParams.archived = String(archived); // Convert boolean to string
74
+ }
75
+ const url = buildUrl(baseUrl, queryParams);
76
+ const response = await yunxiaoRequest(url, {
77
+ method: "GET"
78
+ });
79
+ if (!Array.isArray(response)) {
80
+ return [];
81
+ }
82
+ return response.map((repo) => RepositorySchema.parse(repo));
83
+ }