gitlab-auto-reviewers 2.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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1878 -0
  3. package/dist/api/gitlab-api.d.ts +136 -0
  4. package/dist/api/gitlab-api.d.ts.map +1 -0
  5. package/dist/api/gitlab-api.js +334 -0
  6. package/dist/api/gitlab-api.js.map +1 -0
  7. package/dist/bin/cli.d.ts +10 -0
  8. package/dist/bin/cli.d.ts.map +1 -0
  9. package/dist/bin/cli.js +186 -0
  10. package/dist/bin/cli.js.map +1 -0
  11. package/dist/bin/deprecated-mcp.d.ts +12 -0
  12. package/dist/bin/deprecated-mcp.d.ts.map +1 -0
  13. package/dist/bin/deprecated-mcp.js +73 -0
  14. package/dist/bin/deprecated-mcp.js.map +1 -0
  15. package/dist/bin/index.d.ts +18 -0
  16. package/dist/bin/index.d.ts.map +1 -0
  17. package/dist/bin/index.js +78 -0
  18. package/dist/bin/index.js.map +1 -0
  19. package/dist/bin/mcp.d.ts +11 -0
  20. package/dist/bin/mcp.d.ts.map +1 -0
  21. package/dist/bin/mcp.js +43 -0
  22. package/dist/bin/mcp.js.map +1 -0
  23. package/dist/cache/cache.service.d.ts +113 -0
  24. package/dist/cache/cache.service.d.ts.map +1 -0
  25. package/dist/cache/cache.service.js +213 -0
  26. package/dist/cache/cache.service.js.map +1 -0
  27. package/dist/cli/commands.d.ts +40 -0
  28. package/dist/cli/commands.d.ts.map +1 -0
  29. package/dist/cli/commands.js +142 -0
  30. package/dist/cli/commands.js.map +1 -0
  31. package/dist/cli/output.d.ts +24 -0
  32. package/dist/cli/output.d.ts.map +1 -0
  33. package/dist/cli/output.js +143 -0
  34. package/dist/cli/output.js.map +1 -0
  35. package/dist/config/config.service.d.ts +89 -0
  36. package/dist/config/config.service.d.ts.map +1 -0
  37. package/dist/config/config.service.js +169 -0
  38. package/dist/config/config.service.js.map +1 -0
  39. package/dist/datasources/git-data-source.interface.d.ts +140 -0
  40. package/dist/datasources/git-data-source.interface.d.ts.map +1 -0
  41. package/dist/datasources/git-data-source.interface.js +2 -0
  42. package/dist/datasources/git-data-source.interface.js.map +1 -0
  43. package/dist/datasources/gitlab-api-data-source.d.ts +127 -0
  44. package/dist/datasources/gitlab-api-data-source.d.ts.map +1 -0
  45. package/dist/datasources/gitlab-api-data-source.js +248 -0
  46. package/dist/datasources/gitlab-api-data-source.js.map +1 -0
  47. package/dist/datasources/local-git-data-source.d.ts +124 -0
  48. package/dist/datasources/local-git-data-source.d.ts.map +1 -0
  49. package/dist/datasources/local-git-data-source.js +580 -0
  50. package/dist/datasources/local-git-data-source.js.map +1 -0
  51. package/dist/errors/error-handler.d.ts +113 -0
  52. package/dist/errors/error-handler.d.ts.map +1 -0
  53. package/dist/errors/error-handler.js +230 -0
  54. package/dist/errors/error-handler.js.map +1 -0
  55. package/dist/index.d.ts +139 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +139 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/logging/example.d.ts +15 -0
  60. package/dist/logging/example.d.ts.map +1 -0
  61. package/dist/logging/example.js +79 -0
  62. package/dist/logging/example.js.map +1 -0
  63. package/dist/logging/index.d.ts +7 -0
  64. package/dist/logging/index.d.ts.map +1 -0
  65. package/dist/logging/index.js +7 -0
  66. package/dist/logging/index.js.map +1 -0
  67. package/dist/logging/logger.service.d.ts +98 -0
  68. package/dist/logging/logger.service.d.ts.map +1 -0
  69. package/dist/logging/logger.service.js +160 -0
  70. package/dist/logging/logger.service.js.map +1 -0
  71. package/dist/mcp/server.d.ts +67 -0
  72. package/dist/mcp/server.d.ts.map +1 -0
  73. package/dist/mcp/server.js +213 -0
  74. package/dist/mcp/server.js.map +1 -0
  75. package/dist/mcp/tools.d.ts +22 -0
  76. package/dist/mcp/tools.d.ts.map +1 -0
  77. package/dist/mcp/tools.js +176 -0
  78. package/dist/mcp/tools.js.map +1 -0
  79. package/dist/services/blacklist.service.d.ts +32 -0
  80. package/dist/services/blacklist.service.d.ts.map +1 -0
  81. package/dist/services/blacklist.service.js +59 -0
  82. package/dist/services/blacklist.service.js.map +1 -0
  83. package/dist/services/codeowners.service.d.ts +45 -0
  84. package/dist/services/codeowners.service.d.ts.map +1 -0
  85. package/dist/services/codeowners.service.js +200 -0
  86. package/dist/services/codeowners.service.js.map +1 -0
  87. package/dist/services/comment-builder.service.d.ts +48 -0
  88. package/dist/services/comment-builder.service.d.ts.map +1 -0
  89. package/dist/services/comment-builder.service.js +61 -0
  90. package/dist/services/comment-builder.service.js.map +1 -0
  91. package/dist/services/contributors.service.d.ts +52 -0
  92. package/dist/services/contributors.service.d.ts.map +1 -0
  93. package/dist/services/contributors.service.js +144 -0
  94. package/dist/services/contributors.service.js.map +1 -0
  95. package/dist/services/reviewer-service.d.ts +125 -0
  96. package/dist/services/reviewer-service.d.ts.map +1 -0
  97. package/dist/services/reviewer-service.js +554 -0
  98. package/dist/services/reviewer-service.js.map +1 -0
  99. package/dist/services/team-members.service.d.ts +29 -0
  100. package/dist/services/team-members.service.d.ts.map +1 -0
  101. package/dist/services/team-members.service.js +45 -0
  102. package/dist/services/team-members.service.js.map +1 -0
  103. package/dist/services/whitelist.service.d.ts +31 -0
  104. package/dist/services/whitelist.service.d.ts.map +1 -0
  105. package/dist/services/whitelist.service.js +51 -0
  106. package/dist/services/whitelist.service.js.map +1 -0
  107. package/dist/tools.d.ts +22 -0
  108. package/dist/tools.d.ts.map +1 -0
  109. package/dist/tools.js +176 -0
  110. package/dist/tools.js.map +1 -0
  111. package/dist/types/index.d.ts +502 -0
  112. package/dist/types/index.d.ts.map +1 -0
  113. package/dist/types/index.js +91 -0
  114. package/dist/types/index.js.map +1 -0
  115. package/dist/types.d.ts +219 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +7 -0
  118. package/dist/types.js.map +1 -0
  119. package/package.json +71 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Configuration Service
3
+ *
4
+ * Centralized configuration management with validation and type safety.
5
+ * Loads configuration from environment variables and provides type-safe access.
6
+ */
7
+ /**
8
+ * MCP Server configuration interface
9
+ *
10
+ * @property gitlabUrl - GitLab instance URL (e.g., https://gitlab.com)
11
+ * @property gitlabToken - GitLab API token for authentication (optional)
12
+ * @property repoPath - Path to local git repository for local operations (optional)
13
+ * @property cacheEnabled - Whether caching is enabled
14
+ * @property cacheTTL - Cache time-to-live in milliseconds
15
+ * @property maxParallelRequests - Maximum number of parallel API requests
16
+ * @property contributorDays - Number of days to analyze for contributor history
17
+ * @property maxRetries - Maximum number of retry attempts for failed operations
18
+ * @property retryDelayMs - Initial delay in milliseconds between retries
19
+ * @property logLevel - Minimum log level to output
20
+ * @property debug - Whether debug mode is enabled
21
+ */
22
+ export interface MCPServerConfig {
23
+ gitlabUrl: string;
24
+ gitlabToken?: string;
25
+ repoPath?: string;
26
+ cacheEnabled: boolean;
27
+ cacheTTL: number;
28
+ maxParallelRequests: number;
29
+ contributorDays: number;
30
+ maxRetries: number;
31
+ retryDelayMs: number;
32
+ logLevel: 'debug' | 'info' | 'warn' | 'error';
33
+ debug: boolean;
34
+ }
35
+ /**
36
+ * Configuration service for managing MCP server settings
37
+ *
38
+ * Loads configuration from environment variables, applies defaults,
39
+ * validates settings, and provides type-safe access to configuration.
40
+ */
41
+ export declare class ConfigService {
42
+ private config;
43
+ private appliedDefaults;
44
+ /**
45
+ * Create a new configuration service
46
+ *
47
+ * Automatically loads and validates configuration from environment variables.
48
+ * Logs any default values that were applied.
49
+ */
50
+ constructor();
51
+ /**
52
+ * Get the current configuration (read-only)
53
+ */
54
+ get(): Readonly<MCPServerConfig>;
55
+ /**
56
+ * Get which default values were applied during configuration loading
57
+ */
58
+ getAppliedDefaults(): ReadonlyMap<string, unknown>;
59
+ /**
60
+ * Load configuration from environment variables and validate
61
+ */
62
+ private loadAndValidate;
63
+ /**
64
+ * Validate the configuration
65
+ */
66
+ private validateConfig;
67
+ /**
68
+ * Get environment variable or default value
69
+ */
70
+ private getEnvOrDefault;
71
+ /**
72
+ * Get boolean environment variable
73
+ */
74
+ private getBooleanEnv;
75
+ /**
76
+ * Get number environment variable
77
+ */
78
+ private getNumberEnv;
79
+ /**
80
+ * Get log level from environment
81
+ */
82
+ private getLogLevel;
83
+ /**
84
+ * Log which default values were applied
85
+ * Uses console.error since MCP servers log to stderr
86
+ */
87
+ private logAppliedDefaults;
88
+ }
89
+ //# sourceMappingURL=config.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.service.d.ts","sourceRoot":"","sources":["../../src/config/config.service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,eAAe;IAE9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,MAAM,CAAC;IAG5B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IAGrB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC9C,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAAmC;IAE1D;;;;;OAKG;;IAKH;;OAEG;IACH,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC;IAIhC;;OAEG;IACH,kBAAkB,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAKlD;;OAEG;IACH,OAAO,CAAC,eAAe;IA6BvB;;OAEG;IACH,OAAO,CAAC,cAAc;IA2CtB;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAepB;;OAEG;IACH,OAAO,CAAC,WAAW;IAiBnB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAY3B"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Configuration Service
3
+ *
4
+ * Centralized configuration management with validation and type safety.
5
+ * Loads configuration from environment variables and provides type-safe access.
6
+ */
7
+ /**
8
+ * Configuration service for managing MCP server settings
9
+ *
10
+ * Loads configuration from environment variables, applies defaults,
11
+ * validates settings, and provides type-safe access to configuration.
12
+ */
13
+ export class ConfigService {
14
+ config;
15
+ appliedDefaults = new Map();
16
+ /**
17
+ * Create a new configuration service
18
+ *
19
+ * Automatically loads and validates configuration from environment variables.
20
+ * Logs any default values that were applied.
21
+ */
22
+ constructor() {
23
+ this.config = this.loadAndValidate();
24
+ }
25
+ /**
26
+ * Get the current configuration (read-only)
27
+ */
28
+ get() {
29
+ return Object.freeze({ ...this.config });
30
+ }
31
+ /**
32
+ * Get which default values were applied during configuration loading
33
+ */
34
+ getAppliedDefaults() {
35
+ // Return a copy of the map to prevent external modifications
36
+ return new Map(this.appliedDefaults);
37
+ }
38
+ /**
39
+ * Load configuration from environment variables and validate
40
+ */
41
+ loadAndValidate() {
42
+ const config = {
43
+ // GitLab Configuration
44
+ gitlabUrl: this.getEnvOrDefault('GITLAB_URL', 'https://gitlab.com'),
45
+ gitlabToken: process.env.GITLAB_TOKEN,
46
+ // Repository Configuration
47
+ repoPath: process.env.REPO_PATH,
48
+ // Performance Configuration
49
+ cacheEnabled: this.getBooleanEnv('CACHE_ENABLED', true),
50
+ cacheTTL: this.getNumberEnv('CACHE_TTL', 300000), // 5 minutes default
51
+ maxParallelRequests: this.getNumberEnv('MAX_PARALLEL_REQUESTS', 5),
52
+ // Git Configuration
53
+ contributorDays: this.getNumberEnv('CONTRIBUTOR_DAYS', 352),
54
+ maxRetries: this.getNumberEnv('MAX_RETRIES', 3),
55
+ retryDelayMs: this.getNumberEnv('RETRY_DELAY_MS', 1000),
56
+ // Logging Configuration
57
+ logLevel: this.getLogLevel(),
58
+ debug: this.getBooleanEnv('DEBUG', false),
59
+ };
60
+ this.validateConfig(config);
61
+ this.logAppliedDefaults();
62
+ return config;
63
+ }
64
+ /**
65
+ * Validate the configuration
66
+ */
67
+ validateConfig(config) {
68
+ const errors = [];
69
+ // Validate GitLab URL
70
+ if (!config.gitlabUrl) {
71
+ errors.push('GITLAB_URL is required');
72
+ }
73
+ else {
74
+ try {
75
+ new URL(config.gitlabUrl);
76
+ }
77
+ catch {
78
+ errors.push(`GITLAB_URL is not a valid URL: ${config.gitlabUrl}`);
79
+ }
80
+ }
81
+ // Validate numeric ranges
82
+ if (config.cacheTTL < 0) {
83
+ errors.push(`CACHE_TTL must be non-negative, got: ${config.cacheTTL}`);
84
+ }
85
+ if (config.maxParallelRequests < 1) {
86
+ errors.push(`MAX_PARALLEL_REQUESTS must be at least 1, got: ${config.maxParallelRequests}`);
87
+ }
88
+ if (config.contributorDays < 1) {
89
+ errors.push(`CONTRIBUTOR_DAYS must be at least 1, got: ${config.contributorDays}`);
90
+ }
91
+ if (config.maxRetries < 0) {
92
+ errors.push(`MAX_RETRIES must be non-negative, got: ${config.maxRetries}`);
93
+ }
94
+ if (config.retryDelayMs < 0) {
95
+ errors.push(`RETRY_DELAY_MS must be non-negative, got: ${config.retryDelayMs}`);
96
+ }
97
+ if (errors.length > 0) {
98
+ throw new Error(`Configuration validation failed:\n${errors.map(e => ` - ${e}`).join('\n')}\n\n` +
99
+ 'Please check your environment variables and try again.');
100
+ }
101
+ }
102
+ /**
103
+ * Get environment variable or default value
104
+ */
105
+ getEnvOrDefault(key, defaultValue) {
106
+ const value = process.env[key];
107
+ if (value === undefined) {
108
+ this.appliedDefaults.set(key, defaultValue);
109
+ return defaultValue;
110
+ }
111
+ return value;
112
+ }
113
+ /**
114
+ * Get boolean environment variable
115
+ */
116
+ getBooleanEnv(key, defaultValue) {
117
+ const value = process.env[key];
118
+ if (value === undefined) {
119
+ this.appliedDefaults.set(key, defaultValue);
120
+ return defaultValue;
121
+ }
122
+ return value.toLowerCase() === 'true' || value === '1';
123
+ }
124
+ /**
125
+ * Get number environment variable
126
+ */
127
+ getNumberEnv(key, defaultValue) {
128
+ const value = process.env[key];
129
+ if (value === undefined) {
130
+ this.appliedDefaults.set(key, defaultValue);
131
+ return defaultValue;
132
+ }
133
+ const parsed = parseInt(value, 10);
134
+ if (isNaN(parsed)) {
135
+ throw new Error(`Environment variable ${key} must be a number, got: ${value}`);
136
+ }
137
+ return parsed;
138
+ }
139
+ /**
140
+ * Get log level from environment
141
+ */
142
+ getLogLevel() {
143
+ const value = process.env.LOG_LEVEL?.toLowerCase();
144
+ if (value === undefined) {
145
+ this.appliedDefaults.set('LOG_LEVEL', 'info');
146
+ return 'info';
147
+ }
148
+ const validLevels = ['debug', 'info', 'warn', 'error'];
149
+ if (!validLevels.includes(value)) {
150
+ throw new Error(`LOG_LEVEL must be one of: ${validLevels.join(', ')}, got: ${value}`);
151
+ }
152
+ return value;
153
+ }
154
+ /**
155
+ * Log which default values were applied
156
+ * Uses console.error since MCP servers log to stderr
157
+ */
158
+ logAppliedDefaults() {
159
+ if (this.appliedDefaults.size === 0) {
160
+ return;
161
+ }
162
+ const timestamp = new Date().toISOString();
163
+ console.error(`[${timestamp}] [INFO] [ConfigService] Applied default configuration values:`);
164
+ for (const [key, value] of this.appliedDefaults.entries()) {
165
+ console.error(`[${timestamp}] [INFO] [ConfigService] ${key} = ${JSON.stringify(value)}`);
166
+ }
167
+ }
168
+ }
169
+ //# sourceMappingURL=config.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.service.js","sourceRoot":"","sources":["../../src/config/config.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { MergeRequest, MergeRequestDiff, BlameLine, GitLabNote } from '../types/index.js';
2
+ /**
3
+ * GitDataSource Interface
4
+ *
5
+ * Abstraction layer for accessing git data from different sources (GitLab API or local git repository).
6
+ * All implementations must provide consistent behavior and error handling.
7
+ *
8
+ * Error Handling Contract:
9
+ * - All methods should throw MCPError with appropriate error codes
10
+ * - All errors must include data source context (dataSource field in details)
11
+ * - Transient errors should be retryable via ErrorHandler.withRetry
12
+ * - Not found scenarios should throw ErrorCategory.NOT_FOUND errors
13
+ * - Invalid input should throw ErrorCategory.VALIDATION errors
14
+ *
15
+ * @interface GitDataSource
16
+ */
17
+ export interface GitDataSource {
18
+ /**
19
+ * Get the default branch name for a project
20
+ *
21
+ * @param project - Project identifier (e.g., "group/project")
22
+ * @returns Promise resolving to the default branch name (e.g., "main", "master")
23
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
24
+ */
25
+ getDefaultBranch(project: string): Promise<string>;
26
+ /**
27
+ * Get a specific merge request by its IID
28
+ *
29
+ * @param project - Project identifier
30
+ * @param mr - Merge request IID (internal ID)
31
+ * @returns Promise resolving to MergeRequest or null if not found
32
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
33
+ */
34
+ getMergeRequest(project: string, mr: number): Promise<MergeRequest | null>;
35
+ /**
36
+ * Find an open merge request by its source branch name
37
+ *
38
+ * @param project - Project identifier
39
+ * @param branch - Source branch name
40
+ * @returns Promise resolving to MergeRequest or null if not found
41
+ * @throws {MCPError} With code NOT_FOUND if no open MR exists for the branch
42
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
43
+ */
44
+ getMergeRequestByBranch(project: string, branch: string): Promise<MergeRequest | null>;
45
+ /**
46
+ * Get the current branch name (local git only)
47
+ *
48
+ * Optional method only available in local git data source.
49
+ *
50
+ * @returns Promise resolving to current branch name
51
+ * @throws {MCPError} With code GIT_OPERATION if repository is in detached HEAD state
52
+ */
53
+ getCurrentBranch?(): Promise<string>;
54
+ /**
55
+ * Get the diff for a merge request
56
+ *
57
+ * @param project - Project identifier
58
+ * @param mr - Merge request IID
59
+ * @returns Promise resolving to array of file diffs
60
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
61
+ * @throws {MCPError} With code VALIDATION if merge request data is invalid
62
+ */
63
+ getDiffs(project: string, mr: number): Promise<MergeRequestDiff[]>;
64
+ /**
65
+ * Get git blame information for a file at a specific commit
66
+ *
67
+ * Returns blame data showing which commits last modified each line.
68
+ * Should gracefully handle failures by falling back or returning empty array.
69
+ *
70
+ * @param project - Project identifier
71
+ * @param path - File path relative to repository root
72
+ * @param ref - Git commit SHA or ref
73
+ * @returns Promise resolving to array of blame lines, or null/empty array if unavailable
74
+ * @throws {MCPError} With code GIT_OPERATION if operation fails critically
75
+ */
76
+ getBlame(project: string, path: string, ref: string): Promise<BlameLine[] | null>;
77
+ /**
78
+ * Get raw file content from a specific commit
79
+ *
80
+ * @param project - Project identifier
81
+ * @param commitSha - Git commit SHA
82
+ * @param path - File path relative to repository root
83
+ * @returns Promise resolving to file content as string, or null if not found
84
+ * @throws {MCPError} With code NOT_FOUND if file doesn't exist
85
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
86
+ */
87
+ getRawFile(project: string, commitSha: string, path: string): Promise<string | null>;
88
+ /**
89
+ * Get and parse a JSON file from a specific commit
90
+ *
91
+ * @param project - Project identifier
92
+ * @param commitSha - Git commit SHA
93
+ * @param path - File path relative to repository root
94
+ * @returns Promise resolving to parsed JSON object, or null if not found
95
+ * @throws {MCPError} With code VALIDATION if JSON parsing fails
96
+ * @throws {MCPError} With code NOT_FOUND if file doesn't exist
97
+ */
98
+ getJsonFile<T = unknown>(project: string, commitSha: string, path: string): Promise<T | null>;
99
+ /**
100
+ * Get all merge requests for a project with optional state filter
101
+ *
102
+ * @param project - Project identifier
103
+ * @param state - Optional state filter (e.g., "opened", "closed", "merged")
104
+ * @returns Promise resolving to array of merge requests
105
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
106
+ */
107
+ getMergeRequests(project: string, state?: string): Promise<MergeRequest[]>;
108
+ /**
109
+ * Get all notes (comments) for a merge request
110
+ *
111
+ * @param project - Project identifier
112
+ * @param mr - Merge request IID
113
+ * @returns Promise resolving to array of notes
114
+ * @throws {MCPError} With code API_CALL or GIT_OPERATION if operation fails
115
+ */
116
+ getNotes(project: string, mr: number): Promise<GitLabNote[]>;
117
+ /**
118
+ * Get list of project contributors based on commit history
119
+ *
120
+ * Returns email addresses of contributors who have committed up to the specified commit
121
+ * within the configured time range (see ConfigService.contributorDays).
122
+ *
123
+ * @param project - Project identifier
124
+ * @param commitSha - Git commit SHA to analyze history from
125
+ * @returns Promise resolving to array of contributor email addresses
126
+ * @throws {MCPError} With code GIT_OPERATION if operation fails
127
+ */
128
+ getProjectContributors(project: string, commitSha: string): Promise<string[]>;
129
+ /**
130
+ * Create a new note (comment) on a merge request
131
+ *
132
+ * @param project - Project identifier
133
+ * @param mr - Merge request IID
134
+ * @param body - Comment body (markdown supported)
135
+ * @returns Promise resolving to the created note
136
+ * @throws {MCPError} With code API_CALL if operation fails
137
+ */
138
+ createNote(project: string, mr: number, body: string): Promise<GitLabNote>;
139
+ }
140
+ //# sourceMappingURL=git-data-source.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-data-source.interface.d.ts","sourceRoot":"","sources":["../../src/datasources/git-data-source.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,UAAU,EACX,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnD;;;;;;;OAOG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAE3E;;;;;;;;OAQG;IACH,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAEvF;;;;;;;OAOG;IACH,gBAAgB,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAErC;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAEnE;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;IAElF;;;;;;;;;OASG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAErF;;;;;;;;;OASG;IACH,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE9F;;;;;;;OAOG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAE3E;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAE7D;;;;;;;;;;OAUG;IACH,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE9E;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5E"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=git-data-source.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-data-source.interface.js","sourceRoot":"","sources":["../../src/datasources/git-data-source.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,127 @@
1
+ import { GitLabAPI } from "../api/gitlab-api.js";
2
+ import { GitDataSource } from "./git-data-source.interface.js";
3
+ import { MergeRequest, MergeRequestDiff, BlameLine, GitLabNote } from '../types/index.js';
4
+ import { Logger } from '../logging/logger.service.js';
5
+ /**
6
+ * GitLab API data source implementation
7
+ *
8
+ * Provides access to GitLab data through the GitLab REST API.
9
+ * Implements the GitDataSource interface with API-based operations.
10
+ */
11
+ export declare class GitLabAPIDataSource implements GitDataSource {
12
+ protected logger: Logger;
13
+ protected gitlabApi: GitLabAPI;
14
+ /**
15
+ * Create a new GitLab API data source
16
+ *
17
+ * @param gitlabApi - GitLab API client instance
18
+ * @param logger - Optional logger instance for logging operations
19
+ */
20
+ constructor(gitlabApi: GitLabAPI, logger?: Logger);
21
+ /**
22
+ * Find an open merge request by branch name
23
+ *
24
+ * @param project - The project ID or path
25
+ * @param branch - The source branch name to search for
26
+ * @returns Promise resolving to the merge request
27
+ * @throws {MCPError} If no open MR is found for the branch
28
+ */
29
+ protected findMergeRequestByBranch(project: string, branch: string): Promise<MergeRequest>;
30
+ /**
31
+ * Get the default branch for a project
32
+ *
33
+ * @param project - The project ID or path
34
+ * @returns Promise resolving to the default branch name
35
+ */
36
+ getDefaultBranch(project: string): Promise<string>;
37
+ /**
38
+ * Get a specific merge request by IID
39
+ *
40
+ * @param project - The project ID or path
41
+ * @param mr - The merge request internal ID
42
+ * @returns Promise resolving to the merge request or null if not found
43
+ */
44
+ getMergeRequest(project: string, mr: number): Promise<MergeRequest | null>;
45
+ /**
46
+ * Get a merge request by its source branch name
47
+ *
48
+ * @param project - The project ID or path
49
+ * @param branch - The source branch name
50
+ * @returns Promise resolving to the merge request or null if not found
51
+ */
52
+ getMergeRequestByBranch(project: string, branch: string): Promise<MergeRequest | null>;
53
+ /**
54
+ * Get all diffs for a merge request
55
+ *
56
+ * Note: For very large merge requests (100+ changed files), GitLab API may return
57
+ * limited or truncated data due to API constraints. Consider using LocalGitDataSource
58
+ * for complete analysis of large merge requests.
59
+ *
60
+ * @param project - The project ID or path
61
+ * @param mr - The merge request internal ID
62
+ * @returns Promise resolving to array of diffs (may be limited for large MRs)
63
+ */
64
+ getDiffs(project: string, mr: number): Promise<MergeRequestDiff[]>;
65
+ /**
66
+ * Get git blame information for a file
67
+ *
68
+ * @param project - The project ID or path
69
+ * @param path - The file path within the repository
70
+ * @param ref - The branch, tag, or commit SHA
71
+ * @returns Promise resolving to array of blame lines or null if file not found
72
+ */
73
+ getBlame(project: string, path: string, ref: string): Promise<BlameLine[] | null>;
74
+ /**
75
+ * Get raw file content from repository
76
+ *
77
+ * @param project - The project ID or path
78
+ * @param commitSha - The commit SHA
79
+ * @param path - The file path within the repository
80
+ * @returns Promise resolving to file content or null if not found
81
+ */
82
+ getRawFile(project: string, commitSha: string, path: string): Promise<string | null>;
83
+ /**
84
+ * Get and parse a JSON file from repository
85
+ *
86
+ * @param project - The project ID or path
87
+ * @param commitSha - The commit SHA
88
+ * @param path - The file path within the repository
89
+ * @returns Promise resolving to parsed JSON object or null if not found
90
+ * @throws {MCPError} If the file cannot be parsed as JSON
91
+ */
92
+ getJsonFile<T = unknown>(project: string, commitSha: string, path: string): Promise<T | null>;
93
+ /**
94
+ * Get all merge requests for a project
95
+ *
96
+ * @param project - The project ID or path
97
+ * @param state - The merge request state to filter by (default: "opened")
98
+ * @returns Promise resolving to array of merge requests
99
+ */
100
+ getMergeRequests(project: string, state?: string): Promise<MergeRequest[]>;
101
+ /**
102
+ * Get all notes (comments) for a merge request
103
+ *
104
+ * @param project - The project ID or path
105
+ * @param mr - The merge request internal ID
106
+ * @returns Promise resolving to array of notes
107
+ */
108
+ getNotes(project: string, mr: number): Promise<GitLabNote[]>;
109
+ /**
110
+ * Get project contributors by analyzing commit history
111
+ *
112
+ * @param project - The project ID or path
113
+ * @param commitSha - The commit SHA to analyze history from
114
+ * @returns Promise resolving to array of contributor email addresses
115
+ */
116
+ getProjectContributors(project: string, commitSha: string): Promise<string[]>;
117
+ /**
118
+ * Create a note (comment) on a merge request
119
+ *
120
+ * @param project - The project ID or path
121
+ * @param mr - The merge request internal ID
122
+ * @param body - The comment text (supports Markdown)
123
+ * @returns Promise resolving to the created note
124
+ */
125
+ createNote(project: string, mr: number, body: string): Promise<GitLabNote>;
126
+ }
127
+ //# sourceMappingURL=gitlab-api-data-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitlab-api-data-source.d.ts","sourceRoot":"","sources":["../../src/datasources/gitlab-api-data-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,UAAU,EACX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAGtD;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B;;;;;OAKG;gBACS,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM;IAKjD;;;;;;;OAOG;cACa,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,CAAC;IAgCxB;;;;;OAKG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAcxD;;;;;;OAMG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAchF;;;;;;OAMG;IACG,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAI5F;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA0BxE;;;;;;;OAOG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC;IAcvF;;;;;;;OAOG;IACG,UAAU,CACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAezB;;;;;;;;OAQG;IACG,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAkBpB;;;;;;OAMG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAclF;;;;;;OAMG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAclE;;;;;;OAMG;IACG,sBAAsB,CAC1B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC;IAepB;;;;;;;OAOG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;CAajF"}