@spaceflow/core 0.1.1

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 (116) hide show
  1. package/CHANGELOG.md +1176 -0
  2. package/README.md +105 -0
  3. package/nest-cli.json +10 -0
  4. package/package.json +128 -0
  5. package/rspack.config.mjs +62 -0
  6. package/src/__mocks__/@opencode-ai/sdk.js +9 -0
  7. package/src/__mocks__/c12.ts +3 -0
  8. package/src/app.module.ts +18 -0
  9. package/src/config/ci.config.ts +29 -0
  10. package/src/config/config-loader.ts +101 -0
  11. package/src/config/config-reader.module.ts +16 -0
  12. package/src/config/config-reader.service.ts +133 -0
  13. package/src/config/feishu.config.ts +35 -0
  14. package/src/config/git-provider.config.ts +29 -0
  15. package/src/config/index.ts +29 -0
  16. package/src/config/llm.config.ts +110 -0
  17. package/src/config/schema-generator.service.ts +129 -0
  18. package/src/config/spaceflow.config.ts +292 -0
  19. package/src/config/storage.config.ts +33 -0
  20. package/src/extension-system/extension.interface.ts +221 -0
  21. package/src/extension-system/index.ts +1 -0
  22. package/src/index.ts +80 -0
  23. package/src/locales/en/translation.json +11 -0
  24. package/src/locales/zh-cn/translation.json +11 -0
  25. package/src/shared/claude-setup/claude-setup.module.ts +8 -0
  26. package/src/shared/claude-setup/claude-setup.service.ts +131 -0
  27. package/src/shared/claude-setup/index.ts +2 -0
  28. package/src/shared/editor-config/index.ts +23 -0
  29. package/src/shared/feishu-sdk/feishu-sdk.module.ts +77 -0
  30. package/src/shared/feishu-sdk/feishu-sdk.service.ts +130 -0
  31. package/src/shared/feishu-sdk/fieshu-card.service.ts +139 -0
  32. package/src/shared/feishu-sdk/index.ts +4 -0
  33. package/src/shared/feishu-sdk/types/card-action.ts +132 -0
  34. package/src/shared/feishu-sdk/types/card.ts +64 -0
  35. package/src/shared/feishu-sdk/types/common.ts +22 -0
  36. package/src/shared/feishu-sdk/types/index.ts +46 -0
  37. package/src/shared/feishu-sdk/types/message.ts +35 -0
  38. package/src/shared/feishu-sdk/types/module.ts +21 -0
  39. package/src/shared/feishu-sdk/types/user.ts +77 -0
  40. package/src/shared/git-provider/adapters/gitea.adapter.spec.ts +473 -0
  41. package/src/shared/git-provider/adapters/gitea.adapter.ts +499 -0
  42. package/src/shared/git-provider/adapters/github.adapter.spec.ts +341 -0
  43. package/src/shared/git-provider/adapters/github.adapter.ts +830 -0
  44. package/src/shared/git-provider/adapters/gitlab.adapter.ts +839 -0
  45. package/src/shared/git-provider/adapters/index.ts +3 -0
  46. package/src/shared/git-provider/detect-provider.spec.ts +195 -0
  47. package/src/shared/git-provider/detect-provider.ts +112 -0
  48. package/src/shared/git-provider/git-provider.interface.ts +188 -0
  49. package/src/shared/git-provider/git-provider.module.ts +73 -0
  50. package/src/shared/git-provider/git-provider.service.spec.ts +282 -0
  51. package/src/shared/git-provider/git-provider.service.ts +309 -0
  52. package/src/shared/git-provider/index.ts +7 -0
  53. package/src/shared/git-provider/parse-repo-url.spec.ts +221 -0
  54. package/src/shared/git-provider/parse-repo-url.ts +155 -0
  55. package/src/shared/git-provider/types.ts +434 -0
  56. package/src/shared/git-sdk/git-sdk-diff.utils.spec.ts +344 -0
  57. package/src/shared/git-sdk/git-sdk-diff.utils.ts +151 -0
  58. package/src/shared/git-sdk/git-sdk.module.ts +8 -0
  59. package/src/shared/git-sdk/git-sdk.service.ts +235 -0
  60. package/src/shared/git-sdk/git-sdk.types.ts +25 -0
  61. package/src/shared/git-sdk/index.ts +4 -0
  62. package/src/shared/i18n/i18n.spec.ts +96 -0
  63. package/src/shared/i18n/i18n.ts +86 -0
  64. package/src/shared/i18n/index.ts +1 -0
  65. package/src/shared/i18n/locale-detect.ts +134 -0
  66. package/src/shared/llm-jsonput/index.ts +94 -0
  67. package/src/shared/llm-jsonput/types.ts +17 -0
  68. package/src/shared/llm-proxy/adapters/claude-code.adapter.spec.ts +131 -0
  69. package/src/shared/llm-proxy/adapters/claude-code.adapter.ts +208 -0
  70. package/src/shared/llm-proxy/adapters/index.ts +4 -0
  71. package/src/shared/llm-proxy/adapters/llm-adapter.interface.ts +23 -0
  72. package/src/shared/llm-proxy/adapters/open-code.adapter.ts +342 -0
  73. package/src/shared/llm-proxy/adapters/openai.adapter.spec.ts +215 -0
  74. package/src/shared/llm-proxy/adapters/openai.adapter.ts +153 -0
  75. package/src/shared/llm-proxy/index.ts +6 -0
  76. package/src/shared/llm-proxy/interfaces/config.interface.ts +32 -0
  77. package/src/shared/llm-proxy/interfaces/index.ts +4 -0
  78. package/src/shared/llm-proxy/interfaces/message.interface.ts +48 -0
  79. package/src/shared/llm-proxy/interfaces/session.interface.ts +28 -0
  80. package/src/shared/llm-proxy/llm-proxy.module.ts +140 -0
  81. package/src/shared/llm-proxy/llm-proxy.service.spec.ts +303 -0
  82. package/src/shared/llm-proxy/llm-proxy.service.ts +132 -0
  83. package/src/shared/llm-proxy/llm-session.spec.ts +111 -0
  84. package/src/shared/llm-proxy/llm-session.ts +109 -0
  85. package/src/shared/llm-proxy/stream-logger.ts +97 -0
  86. package/src/shared/logger/index.ts +11 -0
  87. package/src/shared/logger/logger.interface.ts +93 -0
  88. package/src/shared/logger/logger.spec.ts +178 -0
  89. package/src/shared/logger/logger.ts +175 -0
  90. package/src/shared/logger/renderers/plain.renderer.ts +116 -0
  91. package/src/shared/logger/renderers/tui.renderer.ts +162 -0
  92. package/src/shared/mcp/index.ts +332 -0
  93. package/src/shared/output/index.ts +2 -0
  94. package/src/shared/output/output.module.ts +9 -0
  95. package/src/shared/output/output.service.ts +97 -0
  96. package/src/shared/package-manager/index.ts +115 -0
  97. package/src/shared/parallel/index.ts +1 -0
  98. package/src/shared/parallel/parallel-executor.ts +169 -0
  99. package/src/shared/rspack-config/index.ts +1 -0
  100. package/src/shared/rspack-config/rspack-config.ts +157 -0
  101. package/src/shared/source-utils/index.ts +130 -0
  102. package/src/shared/spaceflow-dir/index.ts +158 -0
  103. package/src/shared/storage/adapters/file.adapter.ts +113 -0
  104. package/src/shared/storage/adapters/index.ts +3 -0
  105. package/src/shared/storage/adapters/memory.adapter.ts +50 -0
  106. package/src/shared/storage/adapters/storage-adapter.interface.ts +48 -0
  107. package/src/shared/storage/index.ts +4 -0
  108. package/src/shared/storage/storage.module.ts +150 -0
  109. package/src/shared/storage/storage.service.ts +293 -0
  110. package/src/shared/storage/types.ts +51 -0
  111. package/src/shared/verbose/index.ts +73 -0
  112. package/test/app.e2e-spec.ts +22 -0
  113. package/tsconfig.build.json +4 -0
  114. package/tsconfig.json +25 -0
  115. package/tsconfig.skill.json +18 -0
  116. package/vitest.config.ts +58 -0
@@ -0,0 +1,3 @@
1
+ export * from "./gitea.adapter";
2
+ export * from "./github.adapter";
3
+ export * from "./gitlab.adapter";
@@ -0,0 +1,195 @@
1
+ import { detectProvider } from "./detect-provider";
2
+
3
+ describe("detectProvider", () => {
4
+ // ============ 显式指定 ============
5
+
6
+ describe("GIT_PROVIDER_TYPE 显式指定", () => {
7
+ it("指定 github 时应返回 github", () => {
8
+ const result = detectProvider({ GIT_PROVIDER_TYPE: "github", GITHUB_TOKEN: "ghp-xxx" });
9
+ expect(result.provider).toBe("github");
10
+ expect(result.source).toContain("GIT_PROVIDER_TYPE");
11
+ });
12
+
13
+ it("指定 gitea 时应返回 gitea", () => {
14
+ const result = detectProvider({ GIT_PROVIDER_TYPE: "gitea", GITEA_TOKEN: "tok" });
15
+ expect(result.provider).toBe("gitea");
16
+ expect(result.source).toContain("GIT_PROVIDER_TYPE");
17
+ });
18
+
19
+ it("指定 gitlab 时应返回 gitlab", () => {
20
+ const result = detectProvider({ GIT_PROVIDER_TYPE: "gitlab", GITLAB_TOKEN: "tok" });
21
+ expect(result.provider).toBe("gitlab");
22
+ expect(result.source).toContain("GIT_PROVIDER_TYPE");
23
+ });
24
+
25
+ it("指定无效值时应走自动检测", () => {
26
+ const result = detectProvider({ GIT_PROVIDER_TYPE: "bitbucket" });
27
+ expect(result.provider).toBe("github");
28
+ expect(result.source).toBe("默认");
29
+ });
30
+ });
31
+
32
+ // ============ GITEA_TOKEN 检测 ============
33
+
34
+ describe("GITEA_TOKEN 检测", () => {
35
+ it("有 GITEA_TOKEN 时应识别为 gitea", () => {
36
+ const result = detectProvider({
37
+ GITEA_TOKEN: "tok",
38
+ GITEA_SERVER_URL: "https://gitea.example.com",
39
+ });
40
+ expect(result.provider).toBe("gitea");
41
+ expect(result.serverUrl).toBe("https://gitea.example.com");
42
+ expect(result.token).toBe("tok");
43
+ expect(result.source).toContain("GITEA_TOKEN");
44
+ });
45
+
46
+ it("GITEA_TOKEN 优先于 GITHUB_TOKEN", () => {
47
+ const result = detectProvider({
48
+ GITEA_TOKEN: "gitea-tok",
49
+ GITHUB_TOKEN: "gh-tok",
50
+ GITHUB_SERVER_URL: "https://github.com",
51
+ });
52
+ expect(result.provider).toBe("gitea");
53
+ expect(result.token).toBe("gitea-tok");
54
+ });
55
+ });
56
+
57
+ // ============ GITLAB_TOKEN / CI_JOB_TOKEN 检测 ============
58
+
59
+ describe("GitLab 检测", () => {
60
+ it("有 GITLAB_TOKEN 时应识别为 gitlab", () => {
61
+ const result = detectProvider({
62
+ GITLAB_TOKEN: "glpat-xxx",
63
+ CI_SERVER_URL: "https://gitlab.example.com",
64
+ });
65
+ expect(result.provider).toBe("gitlab");
66
+ expect(result.serverUrl).toBe("https://gitlab.example.com");
67
+ expect(result.token).toBe("glpat-xxx");
68
+ expect(result.source).toContain("GITLAB_TOKEN");
69
+ });
70
+
71
+ it("有 CI_JOB_TOKEN 时应识别为 gitlab", () => {
72
+ const result = detectProvider({
73
+ CI_JOB_TOKEN: "ci-tok",
74
+ CI_SERVER_URL: "https://gitlab.company.com",
75
+ });
76
+ expect(result.provider).toBe("gitlab");
77
+ expect(result.serverUrl).toBe("https://gitlab.company.com");
78
+ expect(result.token).toBe("ci-tok");
79
+ expect(result.source).toContain("CI_JOB_TOKEN");
80
+ });
81
+
82
+ it("未指定 CI_SERVER_URL 时应使用默认 gitlab.com", () => {
83
+ const result = detectProvider({ GITLAB_TOKEN: "glpat-xxx" });
84
+ expect(result.provider).toBe("gitlab");
85
+ expect(result.serverUrl).toBe("https://gitlab.com");
86
+ });
87
+
88
+ it("GITEA_TOKEN 优先于 GITLAB_TOKEN", () => {
89
+ const result = detectProvider({
90
+ GITEA_TOKEN: "gitea-tok",
91
+ GITLAB_TOKEN: "gl-tok",
92
+ });
93
+ expect(result.provider).toBe("gitea");
94
+ });
95
+ });
96
+
97
+ // ============ GITHUB_TOKEN 检测 ============
98
+
99
+ describe("GITHUB_TOKEN 检测", () => {
100
+ it("GITHUB_TOKEN + github.com 应识别为 github", () => {
101
+ const result = detectProvider({
102
+ GITHUB_TOKEN: "ghp-xxx",
103
+ GITHUB_SERVER_URL: "https://github.com",
104
+ GITHUB_API_URL: "https://api.github.com",
105
+ });
106
+ expect(result.provider).toBe("github");
107
+ expect(result.serverUrl).toBe("https://api.github.com");
108
+ expect(result.token).toBe("ghp-xxx");
109
+ expect(result.source).toContain("GITHUB_TOKEN");
110
+ });
111
+
112
+ it("GITHUB_TOKEN + 子域名也应识别为 github", () => {
113
+ const result = detectProvider({
114
+ GITHUB_TOKEN: "ghp-xxx",
115
+ GITHUB_SERVER_URL: "https://enterprise.github.com",
116
+ });
117
+ expect(result.provider).toBe("github");
118
+ });
119
+
120
+ it("GITHUB_TOKEN + 自定义域名也应识别为 github", () => {
121
+ const result = detectProvider({
122
+ GITHUB_TOKEN: "tok",
123
+ GITHUB_SERVER_URL: "https://git.example.com",
124
+ });
125
+ expect(result.provider).toBe("github");
126
+ expect(result.token).toBe("tok");
127
+ expect(result.source).toContain("GITHUB_TOKEN");
128
+ });
129
+
130
+ it("GITHUB_TOKEN 无 SERVER_URL 应识别为 github", () => {
131
+ const result = detectProvider({ GITHUB_TOKEN: "tok" });
132
+ expect(result.provider).toBe("github");
133
+ expect(result.source).toContain("GITHUB_TOKEN");
134
+ });
135
+ });
136
+
137
+ // ============ 默认 ============
138
+
139
+ describe("无任何环境变量", () => {
140
+ it("应默认为 github", () => {
141
+ const result = detectProvider({});
142
+ expect(result.provider).toBe("github");
143
+ expect(result.serverUrl).toBe("https://api.github.com");
144
+ expect(result.token).toBe("");
145
+ expect(result.source).toBe("默认");
146
+ });
147
+ });
148
+
149
+ // ============ GIT_PROVIDER_URL / GIT_PROVIDER_TOKEN 优先级 ============
150
+
151
+ describe("GIT_PROVIDER_URL / GIT_PROVIDER_TOKEN 优先级", () => {
152
+ it("GIT_PROVIDER_URL 应覆盖自动检测的 URL", () => {
153
+ const result = detectProvider({
154
+ GITEA_TOKEN: "tok",
155
+ GITEA_SERVER_URL: "https://gitea.example.com",
156
+ GIT_PROVIDER_URL: "https://custom.example.com",
157
+ });
158
+ expect(result.serverUrl).toBe("https://custom.example.com");
159
+ });
160
+
161
+ it("GIT_PROVIDER_TOKEN 应覆盖自动检测的 token", () => {
162
+ const result = detectProvider({
163
+ GITEA_TOKEN: "gitea-tok",
164
+ GIT_PROVIDER_TOKEN: "custom-tok",
165
+ });
166
+ expect(result.token).toBe("custom-tok");
167
+ });
168
+ });
169
+
170
+ // ============ GitHub 默认 API URL ============
171
+
172
+ describe("GitHub 默认 API URL", () => {
173
+ it("未指定 GITHUB_API_URL 时应使用默认值", () => {
174
+ const result = detectProvider({
175
+ GIT_PROVIDER_TYPE: "github",
176
+ GITHUB_TOKEN: "ghp-xxx",
177
+ });
178
+ expect(result.serverUrl).toBe("https://api.github.com");
179
+ });
180
+ });
181
+
182
+ // ============ Gitea Actions 场景(显式指定 GIT_PROVIDER_TYPE) ============
183
+
184
+ describe("Gitea Actions 场景", () => {
185
+ it("显式指定 gitea 时应回退到 GITHUB_SERVER_URL", () => {
186
+ const result = detectProvider({
187
+ GIT_PROVIDER_TYPE: "gitea",
188
+ GITHUB_TOKEN: "tok",
189
+ GITHUB_SERVER_URL: "https://git.bjxgj.com",
190
+ });
191
+ expect(result.provider).toBe("gitea");
192
+ expect(result.serverUrl).toBe("https://git.bjxgj.com");
193
+ });
194
+ });
195
+ });
@@ -0,0 +1,112 @@
1
+ import type { GitProviderType } from "./types";
2
+
3
+ /** 环境检测结果 */
4
+ export interface DetectedProviderInfo {
5
+ /** 检测到的 provider 类型 */
6
+ provider: GitProviderType;
7
+ /** 检测到的服务器 URL */
8
+ serverUrl: string;
9
+ /** 检测到的 API Token */
10
+ token: string;
11
+ /** 检测来源说明 */
12
+ source: string;
13
+ }
14
+
15
+ /**
16
+ * 从环境变量自动检测 Git Provider 类型和配置
17
+ *
18
+ * 检测优先级:
19
+ * 1. 显式指定 `GIT_PROVIDER_TYPE` 环境变量(最高优先级)
20
+ * 2. 存在 `GITEA_TOKEN` → Gitea
21
+ * 3. 存在 `GITLAB_TOKEN` 或 `CI_JOB_TOKEN`(GitLab CI)→ GitLab
22
+ * 4. 存在 `GITHUB_TOKEN` → GitHub
23
+ * 5. 默认 → GitHub
24
+ */
25
+ export function detectProvider(
26
+ env: Record<string, string | undefined> = process.env,
27
+ ): DetectedProviderInfo {
28
+ const explicit = env.GIT_PROVIDER_TYPE as GitProviderType | undefined;
29
+ if (explicit && isValidProvider(explicit)) {
30
+ return buildResult(explicit, env, "GIT_PROVIDER_TYPE 环境变量");
31
+ }
32
+ if (env.GITEA_TOKEN) {
33
+ return buildResult("gitea", env, "检测到 GITEA_TOKEN");
34
+ }
35
+ if (env.GITLAB_TOKEN || env.CI_JOB_TOKEN) {
36
+ return buildResult(
37
+ "gitlab",
38
+ env,
39
+ env.GITLAB_TOKEN ? "检测到 GITLAB_TOKEN" : "检测到 CI_JOB_TOKEN(GitLab CI)",
40
+ );
41
+ }
42
+ if (env.GITHUB_TOKEN) {
43
+ return buildResult("github", env, "检测到 GITHUB_TOKEN");
44
+ }
45
+ return buildResult("github", env, "默认");
46
+ }
47
+
48
+ /** 检查是否为有效的 provider 类型 */
49
+ function isValidProvider(value: string): value is GitProviderType {
50
+ return value === "gitea" || value === "github" || value === "gitlab";
51
+ }
52
+
53
+ /** 根据 provider 类型从环境变量中提取 serverUrl 和 token */
54
+ function buildResult(
55
+ provider: GitProviderType,
56
+ env: Record<string, string | undefined>,
57
+ source: string,
58
+ ): DetectedProviderInfo {
59
+ const serverUrl = resolveServerUrl(provider, env);
60
+ const token = resolveToken(provider, env);
61
+ return { provider, serverUrl, token, source };
62
+ }
63
+
64
+ /**
65
+ * 解析服务器 URL
66
+ * - 优先使用 GIT_PROVIDER_URL
67
+ * - Gitea: GITEA_SERVER_URL > GITHUB_SERVER_URL
68
+ * - GitHub: GITHUB_API_URL > 默认 https://api.github.com
69
+ * - GitLab: CI_SERVER_URL > GITLAB_URL
70
+ */
71
+ function resolveServerUrl(
72
+ provider: GitProviderType,
73
+ env: Record<string, string | undefined>,
74
+ ): string {
75
+ if (env.GIT_PROVIDER_URL) {
76
+ return env.GIT_PROVIDER_URL;
77
+ }
78
+ if (provider === "github") {
79
+ return env.GITHUB_API_URL || "https://api.github.com";
80
+ }
81
+ if (provider === "gitlab") {
82
+ return env.CI_SERVER_URL || env.GITLAB_URL || "https://gitlab.com";
83
+ }
84
+ // Gitea: 优先 GITEA_SERVER_URL,其次从 GITHUB_SERVER_URL 推导
85
+ if (env.GITEA_SERVER_URL) {
86
+ return env.GITEA_SERVER_URL;
87
+ }
88
+ if (env.GITHUB_SERVER_URL) {
89
+ return env.GITHUB_SERVER_URL;
90
+ }
91
+ return "";
92
+ }
93
+
94
+ /**
95
+ * 解析 API Token
96
+ * - 优先使用 GIT_PROVIDER_TOKEN
97
+ * - Gitea: GITEA_TOKEN > GITHUB_TOKEN
98
+ * - GitHub: GITHUB_TOKEN
99
+ * - GitLab: GITLAB_TOKEN > CI_JOB_TOKEN
100
+ */
101
+ function resolveToken(provider: GitProviderType, env: Record<string, string | undefined>): string {
102
+ if (env.GIT_PROVIDER_TOKEN) {
103
+ return env.GIT_PROVIDER_TOKEN;
104
+ }
105
+ if (provider === "github") {
106
+ return env.GITHUB_TOKEN || "";
107
+ }
108
+ if (provider === "gitlab") {
109
+ return env.GITLAB_TOKEN || env.CI_JOB_TOKEN || "";
110
+ }
111
+ return env.GITEA_TOKEN || env.GITHUB_TOKEN || "";
112
+ }
@@ -0,0 +1,188 @@
1
+ import type {
2
+ BranchProtection,
3
+ CreateBranchProtectionOption,
4
+ EditBranchProtectionOption,
5
+ Branch,
6
+ Repository,
7
+ PullRequest,
8
+ PullRequestCommit,
9
+ ChangedFile,
10
+ CommitInfo,
11
+ IssueComment,
12
+ CreateIssueCommentOption,
13
+ CreateIssueOption,
14
+ Issue,
15
+ CreatePullReviewOption,
16
+ PullReview,
17
+ PullReviewComment,
18
+ Reaction,
19
+ EditPullRequestOption,
20
+ User,
21
+ RepositoryContent,
22
+ } from "./types";
23
+
24
+ /** PR 列表查询选项 */
25
+ export interface ListPullRequestsOptions {
26
+ state?: "open" | "closed" | "all";
27
+ sort?: "oldest" | "recentupdate" | "leastupdate" | "mostcomment" | "leastcomment" | "priority";
28
+ milestone?: number;
29
+ labels?: string[];
30
+ }
31
+
32
+ /** 锁定分支选项 */
33
+ export interface LockBranchOptions {
34
+ /** 允许推送的用户名白名单(如 CI 机器人) */
35
+ pushWhitelistUsernames?: string[];
36
+ }
37
+
38
+ /**
39
+ * Git Provider 抽象接口
40
+ * 定义所有 Git 托管平台需要实现的通用操作
41
+ */
42
+ export interface GitProvider {
43
+ // ============ 配置验证 ============
44
+ /** 验证配置是否完整 */
45
+ validateConfig(): void;
46
+
47
+ // ============ 仓库操作 ============
48
+ /** 获取仓库信息 */
49
+ getRepository(owner: string, repo: string): Promise<Repository>;
50
+
51
+ // ============ 分支操作 ============
52
+ /** 获取分支信息 */
53
+ getBranch(owner: string, repo: string, branch: string): Promise<Branch>;
54
+
55
+ // ============ 分支保护 ============
56
+ /** 列出仓库的所有分支保护规则 */
57
+ listBranchProtections(owner: string, repo: string): Promise<BranchProtection[]>;
58
+ /** 获取特定分支保护规则 */
59
+ getBranchProtection(owner: string, repo: string, name: string): Promise<BranchProtection>;
60
+ /** 创建分支保护规则 */
61
+ createBranchProtection(
62
+ owner: string,
63
+ repo: string,
64
+ options: CreateBranchProtectionOption,
65
+ ): Promise<BranchProtection>;
66
+ /** 编辑分支保护规则 */
67
+ editBranchProtection(
68
+ owner: string,
69
+ repo: string,
70
+ name: string,
71
+ options: EditBranchProtectionOption,
72
+ ): Promise<BranchProtection>;
73
+ /** 删除分支保护规则 */
74
+ deleteBranchProtection(owner: string, repo: string, name: string): Promise<void>;
75
+ /** 锁定分支 - 禁止推送(可配置白名单用户) */
76
+ lockBranch(
77
+ owner: string,
78
+ repo: string,
79
+ branch: string,
80
+ options?: LockBranchOptions,
81
+ ): Promise<BranchProtection>;
82
+ /** 解锁分支 - 允许推送 */
83
+ unlockBranch(owner: string, repo: string, branch: string): Promise<BranchProtection | null>;
84
+ /** 同步解锁分支(用于进程退出时的清理) */
85
+ unlockBranchSync(owner: string, repo: string, branch: string): void;
86
+
87
+ // ============ Pull Request 操作 ============
88
+ /** 获取 Pull Request 信息 */
89
+ getPullRequest(owner: string, repo: string, index: number): Promise<PullRequest>;
90
+ /** 编辑 Pull Request */
91
+ editPullRequest(
92
+ owner: string,
93
+ repo: string,
94
+ index: number,
95
+ options: EditPullRequestOption,
96
+ ): Promise<PullRequest>;
97
+ /** 列出仓库的 Pull Request */
98
+ listPullRequests(
99
+ owner: string,
100
+ repo: string,
101
+ state?: "open" | "closed" | "all",
102
+ ): Promise<PullRequest[]>;
103
+ /** 列出仓库的所有 Pull Request(支持分页获取全部) */
104
+ listAllPullRequests(
105
+ owner: string,
106
+ repo: string,
107
+ options?: ListPullRequestsOptions,
108
+ ): Promise<PullRequest[]>;
109
+ /** 获取 PR 的 commits */
110
+ getPullRequestCommits(owner: string, repo: string, index: number): Promise<PullRequestCommit[]>;
111
+ /** 获取 PR 的文件变更 */
112
+ getPullRequestFiles(owner: string, repo: string, index: number): Promise<ChangedFile[]>;
113
+ /** 获取 PR 的 diff */
114
+ getPullRequestDiff(owner: string, repo: string, index: number): Promise<string>;
115
+
116
+ // ============ Commit 操作 ============
117
+ /** 获取单个 commit 信息 */
118
+ getCommit(owner: string, repo: string, sha: string): Promise<CommitInfo>;
119
+ /** 获取两个 ref 之间的 diff */
120
+ getCompareDiff(owner: string, repo: string, baseSha: string, headSha: string): Promise<string>;
121
+ /** 获取单个 commit 的 diff */
122
+ getCommitDiff(owner: string, repo: string, sha: string): Promise<string>;
123
+
124
+ // ============ 文件操作 ============
125
+ /** 获取文件内容 */
126
+ getFileContent(owner: string, repo: string, filepath: string, ref?: string): Promise<string>;
127
+ /** 列出仓库目录下的文件和子目录 */
128
+ listRepositoryContents(
129
+ owner: string,
130
+ repo: string,
131
+ path?: string,
132
+ ref?: string,
133
+ ): Promise<RepositoryContent[]>;
134
+
135
+ // ============ Issue 操作 ============
136
+ /** 创建 Issue */
137
+ createIssue(owner: string, repo: string, options: CreateIssueOption): Promise<Issue>;
138
+ /** 列出 Issue/PR 的评论 */
139
+ listIssueComments(owner: string, repo: string, index: number): Promise<IssueComment[]>;
140
+ /** 创建 Issue/PR 评论 */
141
+ createIssueComment(
142
+ owner: string,
143
+ repo: string,
144
+ index: number,
145
+ options: CreateIssueCommentOption,
146
+ ): Promise<IssueComment>;
147
+ /** 更新 Issue/PR 评论 */
148
+ updateIssueComment(
149
+ owner: string,
150
+ repo: string,
151
+ commentId: number,
152
+ body: string,
153
+ ): Promise<IssueComment>;
154
+ /** 删除 Issue/PR 评论 */
155
+ deleteIssueComment(owner: string, repo: string, commentId: number): Promise<void>;
156
+
157
+ // ============ PR Review 操作 ============
158
+ /** 创建 PR Review */
159
+ createPullReview(
160
+ owner: string,
161
+ repo: string,
162
+ index: number,
163
+ options: CreatePullReviewOption,
164
+ ): Promise<PullReview>;
165
+ /** 列出 PR 的所有 Reviews */
166
+ listPullReviews(owner: string, repo: string, index: number): Promise<PullReview[]>;
167
+ /** 删除 PR Review */
168
+ deletePullReview(owner: string, repo: string, index: number, reviewId: number): Promise<void>;
169
+ /** 获取 PR Review 的行级评论列表 */
170
+ listPullReviewComments(
171
+ owner: string,
172
+ repo: string,
173
+ index: number,
174
+ reviewId: number,
175
+ ): Promise<PullReviewComment[]>;
176
+
177
+ // ============ Reaction 操作 ============
178
+ /** 获取 Issue/PR 评论的 reactions */
179
+ getIssueCommentReactions(owner: string, repo: string, commentId: number): Promise<Reaction[]>;
180
+ /** 获取 Issue/PR 的 reactions */
181
+ getIssueReactions(owner: string, repo: string, index: number): Promise<Reaction[]>;
182
+
183
+ // ============ 用户操作 ============
184
+ /** 搜索用户 */
185
+ searchUsers(query: string, limit?: number): Promise<User[]>;
186
+ /** 获取团队成员列表 */
187
+ getTeamMembers(teamId: number): Promise<User[]>;
188
+ }
@@ -0,0 +1,73 @@
1
+ import { DynamicModule, Module } from "@nestjs/common";
2
+ import { ConfigModule, ConfigService } from "@nestjs/config";
3
+ import { GitProviderService } from "./git-provider.service";
4
+ import {
5
+ type GitProviderModuleOptions,
6
+ type GitProviderModuleAsyncOptions,
7
+ GIT_PROVIDER_MODULE_OPTIONS,
8
+ } from "./types";
9
+ import { gitProviderConfig, type GitProviderConfig } from "../../config/git-provider.config";
10
+
11
+ @Module({})
12
+ export class GitProviderModule {
13
+ /**
14
+ * 同步注册模块
15
+ */
16
+ static forRoot(options: GitProviderModuleOptions): DynamicModule {
17
+ return {
18
+ module: GitProviderModule,
19
+ providers: [
20
+ {
21
+ provide: GIT_PROVIDER_MODULE_OPTIONS,
22
+ useValue: options,
23
+ },
24
+ GitProviderService,
25
+ ],
26
+ exports: [GitProviderService],
27
+ };
28
+ }
29
+
30
+ /**
31
+ * 异步注册模块 - 支持从环境变量等动态获取配置
32
+ */
33
+ static forRootAsync(options: GitProviderModuleAsyncOptions): DynamicModule {
34
+ return {
35
+ module: GitProviderModule,
36
+ providers: [
37
+ {
38
+ provide: GIT_PROVIDER_MODULE_OPTIONS,
39
+ useFactory: options.useFactory,
40
+ inject: options.inject || [],
41
+ },
42
+ GitProviderService,
43
+ ],
44
+ exports: [GitProviderService],
45
+ };
46
+ }
47
+
48
+ /**
49
+ * 使用 ConfigService 注册模块
50
+ */
51
+ static forFeature(): DynamicModule {
52
+ return {
53
+ module: GitProviderModule,
54
+ imports: [ConfigModule.forFeature(gitProviderConfig)],
55
+ providers: [
56
+ {
57
+ provide: GIT_PROVIDER_MODULE_OPTIONS,
58
+ useFactory: (configService: ConfigService): GitProviderModuleOptions => {
59
+ const config = configService.get<GitProviderConfig>("gitProvider");
60
+ return {
61
+ provider: config?.provider || "gitea",
62
+ baseUrl: config?.serverUrl || "",
63
+ token: config?.token || "",
64
+ };
65
+ },
66
+ inject: [ConfigService],
67
+ },
68
+ GitProviderService,
69
+ ],
70
+ exports: [GitProviderService],
71
+ };
72
+ }
73
+ }