mcp4openapi 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 (209) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +489 -0
  3. package/dist/composite-executor.d.ts +65 -0
  4. package/dist/composite-executor.d.ts.map +1 -0
  5. package/dist/composite-executor.js +147 -0
  6. package/dist/composite-executor.js.map +1 -0
  7. package/dist/constants.d.ts +36 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +36 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/http-transport.d.ts +195 -0
  12. package/dist/http-transport.d.ts.map +1 -0
  13. package/dist/http-transport.js +760 -0
  14. package/dist/http-transport.js.map +1 -0
  15. package/dist/interceptors.d.ts +74 -0
  16. package/dist/interceptors.d.ts.map +1 -0
  17. package/dist/interceptors.js +220 -0
  18. package/dist/interceptors.js.map +1 -0
  19. package/dist/logger.d.ts +81 -0
  20. package/dist/logger.d.ts.map +1 -0
  21. package/dist/logger.js +264 -0
  22. package/dist/logger.js.map +1 -0
  23. package/dist/mcp-server.d.ts +110 -0
  24. package/dist/mcp-server.d.ts.map +1 -0
  25. package/dist/mcp-server.js +568 -0
  26. package/dist/mcp-server.js.map +1 -0
  27. package/dist/metrics.d.ts +86 -0
  28. package/dist/metrics.d.ts.map +1 -0
  29. package/dist/metrics.js +229 -0
  30. package/dist/metrics.js.map +1 -0
  31. package/dist/openapi-parser.d.ts +35 -0
  32. package/dist/openapi-parser.d.ts.map +1 -0
  33. package/dist/openapi-parser.js +160 -0
  34. package/dist/openapi-parser.js.map +1 -0
  35. package/dist/profile-loader.d.ts +25 -0
  36. package/dist/profile-loader.d.ts.map +1 -0
  37. package/dist/profile-loader.js +134 -0
  38. package/dist/profile-loader.js.map +1 -0
  39. package/dist/schema-validator.d.ts +32 -0
  40. package/dist/schema-validator.d.ts.map +1 -0
  41. package/dist/schema-validator.js +126 -0
  42. package/dist/schema-validator.js.map +1 -0
  43. package/dist/scripts/validate-profile.d.ts +9 -0
  44. package/dist/scripts/validate-profile.d.ts.map +1 -0
  45. package/dist/scripts/validate-profile.js +289 -0
  46. package/dist/scripts/validate-profile.js.map +1 -0
  47. package/dist/scripts/validate-schema.d.ts +9 -0
  48. package/dist/scripts/validate-schema.d.ts.map +1 -0
  49. package/dist/scripts/validate-schema.js +84 -0
  50. package/dist/scripts/validate-schema.js.map +1 -0
  51. package/dist/src/composite-executor.d.ts +75 -0
  52. package/dist/src/composite-executor.d.ts.map +1 -0
  53. package/dist/src/composite-executor.js +175 -0
  54. package/dist/src/composite-executor.js.map +1 -0
  55. package/dist/src/constants.d.ts +36 -0
  56. package/dist/src/constants.d.ts.map +1 -0
  57. package/dist/src/constants.js +36 -0
  58. package/dist/src/constants.js.map +1 -0
  59. package/dist/src/dag-executor.d.ts +49 -0
  60. package/dist/src/dag-executor.d.ts.map +1 -0
  61. package/dist/src/dag-executor.js +138 -0
  62. package/dist/src/dag-executor.js.map +1 -0
  63. package/dist/src/errors.d.ts +47 -0
  64. package/dist/src/errors.d.ts.map +1 -0
  65. package/dist/src/errors.js +99 -0
  66. package/dist/src/errors.js.map +1 -0
  67. package/dist/src/generated-schemas.d.ts +661 -0
  68. package/dist/src/generated-schemas.d.ts.map +1 -0
  69. package/dist/src/generated-schemas.js +66 -0
  70. package/dist/src/generated-schemas.js.map +1 -0
  71. package/dist/src/http-client-factory.d.ts +62 -0
  72. package/dist/src/http-client-factory.d.ts.map +1 -0
  73. package/dist/src/http-client-factory.js +121 -0
  74. package/dist/src/http-client-factory.js.map +1 -0
  75. package/dist/src/http-transport.d.ts +194 -0
  76. package/dist/src/http-transport.d.ts.map +1 -0
  77. package/dist/src/http-transport.js +851 -0
  78. package/dist/src/http-transport.js.map +1 -0
  79. package/dist/src/index.d.ts +8 -0
  80. package/dist/src/index.d.ts.map +1 -0
  81. package/dist/src/index.js +59 -0
  82. package/dist/src/index.js.map +1 -0
  83. package/dist/src/interceptors.d.ts +78 -0
  84. package/dist/src/interceptors.d.ts.map +1 -0
  85. package/dist/src/interceptors.js +252 -0
  86. package/dist/src/interceptors.js.map +1 -0
  87. package/dist/src/jsonrpc-validator.d.ts +27 -0
  88. package/dist/src/jsonrpc-validator.d.ts.map +1 -0
  89. package/dist/src/jsonrpc-validator.js +58 -0
  90. package/dist/src/jsonrpc-validator.js.map +1 -0
  91. package/dist/src/lib.d.ts +8 -0
  92. package/dist/src/lib.d.ts.map +1 -0
  93. package/dist/src/lib.js +7 -0
  94. package/dist/src/lib.js.map +1 -0
  95. package/dist/src/logger.d.ts +81 -0
  96. package/dist/src/logger.d.ts.map +1 -0
  97. package/dist/src/logger.js +264 -0
  98. package/dist/src/logger.js.map +1 -0
  99. package/dist/src/mcp-server.d.ts +117 -0
  100. package/dist/src/mcp-server.d.ts.map +1 -0
  101. package/dist/src/mcp-server.js +621 -0
  102. package/dist/src/mcp-server.js.map +1 -0
  103. package/dist/src/metrics.d.ts +86 -0
  104. package/dist/src/metrics.d.ts.map +1 -0
  105. package/dist/src/metrics.js +229 -0
  106. package/dist/src/metrics.js.map +1 -0
  107. package/dist/src/naming-warnings.d.ts +23 -0
  108. package/dist/src/naming-warnings.d.ts.map +1 -0
  109. package/dist/src/naming-warnings.js +83 -0
  110. package/dist/src/naming-warnings.js.map +1 -0
  111. package/dist/src/naming.d.ts +58 -0
  112. package/dist/src/naming.d.ts.map +1 -0
  113. package/dist/src/naming.js +510 -0
  114. package/dist/src/naming.js.map +1 -0
  115. package/dist/src/openapi-parser.d.ts +49 -0
  116. package/dist/src/openapi-parser.d.ts.map +1 -0
  117. package/dist/src/openapi-parser.js +216 -0
  118. package/dist/src/openapi-parser.js.map +1 -0
  119. package/dist/src/profile-loader.d.ts +77 -0
  120. package/dist/src/profile-loader.d.ts.map +1 -0
  121. package/dist/src/profile-loader.js +443 -0
  122. package/dist/src/profile-loader.js.map +1 -0
  123. package/dist/src/schema-validator.d.ts +30 -0
  124. package/dist/src/schema-validator.d.ts.map +1 -0
  125. package/dist/src/schema-validator.js +115 -0
  126. package/dist/src/schema-validator.js.map +1 -0
  127. package/dist/src/testing/fixtures.d.ts +268 -0
  128. package/dist/src/testing/fixtures.d.ts.map +1 -0
  129. package/dist/src/testing/fixtures.js +210 -0
  130. package/dist/src/testing/fixtures.js.map +1 -0
  131. package/dist/src/testing/mock-gitlab-server.d.ts +34 -0
  132. package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -0
  133. package/dist/src/testing/mock-gitlab-server.js +351 -0
  134. package/dist/src/testing/mock-gitlab-server.js.map +1 -0
  135. package/dist/src/testing/mock-utils.d.ts +41 -0
  136. package/dist/src/testing/mock-utils.d.ts.map +1 -0
  137. package/dist/src/testing/mock-utils.js +59 -0
  138. package/dist/src/testing/mock-utils.js.map +1 -0
  139. package/dist/src/testing/test-http-utils.d.ts +52 -0
  140. package/dist/src/testing/test-http-utils.d.ts.map +1 -0
  141. package/dist/src/testing/test-http-utils.js +109 -0
  142. package/dist/src/testing/test-http-utils.js.map +1 -0
  143. package/dist/src/testing/test-types.d.ts +76 -0
  144. package/dist/src/testing/test-types.d.ts.map +1 -0
  145. package/dist/src/testing/test-types.js +7 -0
  146. package/dist/src/testing/test-types.js.map +1 -0
  147. package/dist/src/tool-generator.d.ts +43 -0
  148. package/dist/src/tool-generator.d.ts.map +1 -0
  149. package/dist/src/tool-generator.js +123 -0
  150. package/dist/src/tool-generator.js.map +1 -0
  151. package/dist/src/types/http-transport.d.ts +45 -0
  152. package/dist/src/types/http-transport.d.ts.map +1 -0
  153. package/dist/src/types/http-transport.js +8 -0
  154. package/dist/src/types/http-transport.js.map +1 -0
  155. package/dist/src/types/openapi.d.ts +50 -0
  156. package/dist/src/types/openapi.d.ts.map +1 -0
  157. package/dist/src/types/openapi.js +9 -0
  158. package/dist/src/types/openapi.js.map +1 -0
  159. package/dist/src/types/profile.d.ts +80 -0
  160. package/dist/src/types/profile.d.ts.map +1 -0
  161. package/dist/src/types/profile.js +9 -0
  162. package/dist/src/types/profile.js.map +1 -0
  163. package/dist/src/validation-utils.d.ts +15 -0
  164. package/dist/src/validation-utils.d.ts.map +1 -0
  165. package/dist/src/validation-utils.js +25 -0
  166. package/dist/src/validation-utils.js.map +1 -0
  167. package/dist/testing/fixtures.d.ts +186 -0
  168. package/dist/testing/fixtures.d.ts.map +1 -0
  169. package/dist/testing/fixtures.js +135 -0
  170. package/dist/testing/fixtures.js.map +1 -0
  171. package/dist/testing/http-integration.test.d.ts +7 -0
  172. package/dist/testing/http-integration.test.d.ts.map +1 -0
  173. package/dist/testing/http-integration.test.js +383 -0
  174. package/dist/testing/http-integration.test.js.map +1 -0
  175. package/dist/testing/http-multiuser.test.d.ts +10 -0
  176. package/dist/testing/http-multiuser.test.d.ts.map +1 -0
  177. package/dist/testing/http-multiuser.test.js +255 -0
  178. package/dist/testing/http-multiuser.test.js.map +1 -0
  179. package/dist/testing/integration.test.d.ts +8 -0
  180. package/dist/testing/integration.test.d.ts.map +1 -0
  181. package/dist/testing/integration.test.js +247 -0
  182. package/dist/testing/integration.test.js.map +1 -0
  183. package/dist/testing/mock-gitlab-server.d.ts +34 -0
  184. package/dist/testing/mock-gitlab-server.d.ts.map +1 -0
  185. package/dist/testing/mock-gitlab-server.js +224 -0
  186. package/dist/testing/mock-gitlab-server.js.map +1 -0
  187. package/dist/testing/test-types.d.ts +59 -0
  188. package/dist/testing/test-types.d.ts.map +1 -0
  189. package/dist/testing/test-types.js +7 -0
  190. package/dist/testing/test-types.js.map +1 -0
  191. package/dist/tool-generator.d.ts +43 -0
  192. package/dist/tool-generator.d.ts.map +1 -0
  193. package/dist/tool-generator.js +123 -0
  194. package/dist/tool-generator.js.map +1 -0
  195. package/dist/tsconfig.tsbuildinfo +1 -0
  196. package/dist/types/http-transport.d.ts +39 -0
  197. package/dist/types/http-transport.d.ts.map +1 -0
  198. package/dist/types/http-transport.js +8 -0
  199. package/dist/types/http-transport.js.map +1 -0
  200. package/dist/types/openapi.d.ts +50 -0
  201. package/dist/types/openapi.d.ts.map +1 -0
  202. package/dist/types/openapi.js +9 -0
  203. package/dist/types/openapi.js.map +1 -0
  204. package/dist/types/profile.d.ts +76 -0
  205. package/dist/types/profile.d.ts.map +1 -0
  206. package/dist/types/profile.js +9 -0
  207. package/dist/types/profile.js.map +1 -0
  208. package/package.json +84 -0
  209. package/profile-schema.json +369 -0
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Mock GitLab API server for integration testing
3
+ *
4
+ * Why: Enables end-to-end testing without real GitLab instance.
5
+ * Tests actual HTTP flow, parameter handling, error scenarios.
6
+ */
7
+ import { http, HttpResponse } from 'msw';
8
+ import { setupServer } from 'msw/node';
9
+ import * as fixtures from './fixtures.js';
10
+ import { parsePaginationParams, parseSearchParam, parseBranchParams, parseScopeParam } from './mock-utils.js';
11
+ const BASE_URL = 'https://gitlab.com/api/v4';
12
+ /**
13
+ * Helper: Extract and validate IID from URL
14
+ *
15
+ * Why: Prevents path traversal and invalid integer attacks
16
+ * Returns null if invalid (caller should return 400 Bad Request)
17
+ */
18
+ function extractIidFromUrl(url) {
19
+ const parts = url.split('/');
20
+ const iidStr = parts[parts.length - 1];
21
+ // Validate it's a positive integer
22
+ if (!iidStr || !/^\d+$/.test(iidStr)) {
23
+ return null;
24
+ }
25
+ const iid = parseInt(iidStr, 10);
26
+ if (isNaN(iid) || iid < 1 || iid > 2147483647) {
27
+ return null;
28
+ }
29
+ return iid;
30
+ }
31
+ /**
32
+ * Mock GitLab API endpoints
33
+ *
34
+ * Why ordered by resource: Mirrors actual GitLab API structure for maintainability
35
+ * Why wildcard patterns: GitLab accepts URL-encoded paths like my-org/my-project
36
+ */
37
+ export const handlers = [
38
+ // Project Badges
39
+ http.get(`${BASE_URL}/projects/*/badges`, ({ request, params }) => {
40
+ const { page } = parsePaginationParams(request);
41
+ // Simple pagination
42
+ if (page === 1) {
43
+ return HttpResponse.json(fixtures.mockBadgesList);
44
+ }
45
+ return HttpResponse.json([]);
46
+ }),
47
+ http.get(`${BASE_URL}/projects/*/badges/*`, ({ request }) => {
48
+ const badgeId = extractIidFromUrl(request.url);
49
+ if (badgeId === null) {
50
+ return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
51
+ }
52
+ if (badgeId === 1) {
53
+ return HttpResponse.json(fixtures.mockBadge);
54
+ }
55
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
56
+ }),
57
+ http.post(`${BASE_URL}/projects/*/badges`, async ({ request }) => {
58
+ const body = await request.json();
59
+ if (!body.link_url || !body.image_url) {
60
+ return HttpResponse.json({ error: 'link_url and image_url are required' }, { status: 400 });
61
+ }
62
+ return HttpResponse.json({
63
+ ...fixtures.mockBadge,
64
+ id: 3,
65
+ name: body.name || 'New Badge',
66
+ link_url: body.link_url,
67
+ image_url: body.image_url,
68
+ }, { status: 201 });
69
+ }),
70
+ http.put(`${BASE_URL}/projects/*/badges/*`, async ({ request }) => {
71
+ const badgeId = extractIidFromUrl(request.url);
72
+ if (badgeId === null) {
73
+ return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
74
+ }
75
+ const body = await request.json();
76
+ if (badgeId === 1) {
77
+ return HttpResponse.json({
78
+ ...fixtures.mockBadge,
79
+ name: body.name || fixtures.mockBadge.name,
80
+ link_url: body.link_url || fixtures.mockBadge.link_url,
81
+ image_url: body.image_url || fixtures.mockBadge.image_url,
82
+ });
83
+ }
84
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
85
+ }),
86
+ http.delete(`${BASE_URL}/projects/*/badges/*`, ({ request }) => {
87
+ const badgeId = extractIidFromUrl(request.url);
88
+ if (badgeId === null) {
89
+ return HttpResponse.json({ error: 'Invalid badge ID' }, { status: 400 });
90
+ }
91
+ if (badgeId === 1) {
92
+ return new HttpResponse(null, { status: 204 });
93
+ }
94
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
95
+ }),
96
+ // Group Badges (similar structure)
97
+ http.get(`${BASE_URL}/groups/*/badges`, () => {
98
+ return HttpResponse.json(fixtures.mockBadgesList);
99
+ }),
100
+ http.post(`${BASE_URL}/groups/*/badges`, async ({ request }) => {
101
+ const body = await request.json();
102
+ return HttpResponse.json({
103
+ ...fixtures.mockBadge,
104
+ id: 4,
105
+ kind: 'group',
106
+ name: body.name || 'Group Badge',
107
+ }, { status: 201 });
108
+ }),
109
+ // Branches
110
+ http.get(`${BASE_URL}/projects/*/repository/branches`, ({ request }) => {
111
+ const search = parseSearchParam(request);
112
+ if (search) {
113
+ return HttpResponse.json(fixtures.mockBranchesList.filter(b => b.name.includes(search)));
114
+ }
115
+ return HttpResponse.json(fixtures.mockBranchesList);
116
+ }),
117
+ http.get(`${BASE_URL}/projects/*/repository/branches/*`, ({ request }) => {
118
+ const branch = decodeURIComponent(request.url.split('/').pop() || '');
119
+ const found = fixtures.mockBranchesList.find(b => b.name === branch);
120
+ if (found) {
121
+ return HttpResponse.json(found);
122
+ }
123
+ return HttpResponse.json({ message: 'Branch Not Found' }, { status: 404 });
124
+ }),
125
+ http.post(`${BASE_URL}/projects/*/repository/branches`, async ({ request }) => {
126
+ const { branch, ref } = parseBranchParams(request);
127
+ if (!branch || !ref) {
128
+ return HttpResponse.json({ error: 'branch and ref parameters are required' }, { status: 400 });
129
+ }
130
+ return HttpResponse.json({
131
+ name: branch,
132
+ commit: fixtures.mockBranch.commit,
133
+ merged: false,
134
+ protected: false,
135
+ default: false,
136
+ }, { status: 201 });
137
+ }),
138
+ http.delete(`${BASE_URL}/projects/*/repository/branches/*`, ({ request }) => {
139
+ const branch = decodeURIComponent(request.url.split('/').pop() || '');
140
+ if (branch !== 'main') {
141
+ return new HttpResponse(null, { status: 204 });
142
+ }
143
+ return HttpResponse.json({ message: 'Cannot delete default branch' }, { status: 403 });
144
+ }),
145
+ http.put(`${BASE_URL}/projects/*/repository/branches/*/protect`, ({ request }) => {
146
+ const parts = request.url.split('/');
147
+ const branch = decodeURIComponent(parts[parts.length - 2]); // second-to-last part
148
+ return HttpResponse.json({
149
+ ...fixtures.mockBranch,
150
+ name: branch,
151
+ protected: true,
152
+ });
153
+ }),
154
+ http.put(`${BASE_URL}/projects/*/repository/branches/*/unprotect`, ({ request }) => {
155
+ const parts = request.url.split('/');
156
+ const branch = decodeURIComponent(parts[parts.length - 2]); // second-to-last part
157
+ return HttpResponse.json({
158
+ ...fixtures.mockBranch,
159
+ name: branch,
160
+ protected: false,
161
+ });
162
+ }),
163
+ // Access Requests
164
+ http.get(`${BASE_URL}/projects/*/access_requests`, () => {
165
+ return HttpResponse.json(fixtures.mockAccessRequestsList);
166
+ }),
167
+ http.get(`${BASE_URL}/groups/*/access_requests`, () => {
168
+ return HttpResponse.json(fixtures.mockAccessRequestsList);
169
+ }),
170
+ http.post(`${BASE_URL}/projects/*/access_requests`, () => {
171
+ return HttpResponse.json(fixtures.mockAccessRequest, { status: 201 });
172
+ }),
173
+ http.put(`${BASE_URL}/projects/*/access_requests/*/approve`, async ({ request }) => {
174
+ const body = await request.json();
175
+ const parts = request.url.split('/');
176
+ const userId = parseInt(parts[parts.length - 2], 10); // second-to-last part
177
+ return HttpResponse.json({
178
+ ...fixtures.mockAccessRequest,
179
+ id: userId,
180
+ access_level: body.access_level || 30,
181
+ });
182
+ }),
183
+ http.delete(`${BASE_URL}/projects/*/access_requests/*`, () => {
184
+ return new HttpResponse(null, { status: 204 });
185
+ }),
186
+ // Jobs
187
+ http.get(`${BASE_URL}/projects/*/jobs`, ({ request }) => {
188
+ const scope = parseScopeParam(request);
189
+ if (scope.length > 0 && scope.includes('failed')) {
190
+ return HttpResponse.json(fixtures.mockJobsList.filter(j => j.status === 'failed'));
191
+ }
192
+ return HttpResponse.json(fixtures.mockJobsList);
193
+ }),
194
+ http.get(`${BASE_URL}/projects/*/jobs/*`, ({ request }) => {
195
+ const jobId = extractIidFromUrl(request.url);
196
+ if (jobId === null) {
197
+ return HttpResponse.json({ error: 'Invalid job ID' }, { status: 400 });
198
+ }
199
+ if (jobId === 1234) {
200
+ return HttpResponse.json(fixtures.mockJob);
201
+ }
202
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
203
+ }),
204
+ http.post(`${BASE_URL}/projects/*/jobs/*/play`, ({ request }) => {
205
+ const parts = request.url.split('/');
206
+ const jobId = parseInt(parts[parts.length - 2], 10); // second-to-last part
207
+ return HttpResponse.json({
208
+ ...fixtures.mockJob,
209
+ id: jobId,
210
+ status: 'pending',
211
+ });
212
+ }),
213
+ // Rate limiting simulation
214
+ http.get(`${BASE_URL}/rate-limit-test`, () => {
215
+ return HttpResponse.json({ message: 'Rate limit exceeded' }, { status: 429, headers: { 'Retry-After': '60' } });
216
+ }),
217
+ // Merge Requests
218
+ http.get(`${BASE_URL}/projects/*/merge_requests`, ({ request, params }) => {
219
+ const { page } = parsePaginationParams(request);
220
+ // Simple pagination
221
+ if (page === 1) {
222
+ return HttpResponse.json(fixtures.mockMergeRequestsList);
223
+ }
224
+ return HttpResponse.json([]);
225
+ }),
226
+ http.get(`${BASE_URL}/projects/*/merge_requests/*`, ({ request }) => {
227
+ const mergeRequestIid = extractIidFromUrl(request.url);
228
+ if (mergeRequestIid === null) {
229
+ return HttpResponse.json({ error: 'Invalid merge request IID' }, { status: 400 });
230
+ }
231
+ if (mergeRequestIid === 1) {
232
+ return HttpResponse.json(fixtures.mockMergeRequest);
233
+ }
234
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
235
+ }),
236
+ http.post(`${BASE_URL}/projects/*/merge_requests`, async ({ request }) => {
237
+ const body = await request.json();
238
+ if (!body.source_branch || !body.target_branch || !body.title) {
239
+ return HttpResponse.json({ error: 'source_branch, target_branch, and title are required' }, { status: 400 });
240
+ }
241
+ // Return created merge request
242
+ const createdMR = {
243
+ ...fixtures.mockMergeRequest,
244
+ iid: 3,
245
+ id: 3,
246
+ title: body.title,
247
+ source_branch: body.source_branch,
248
+ target_branch: body.target_branch,
249
+ description: body.description,
250
+ web_url: 'https://gitlab.com/my-org/my-project/-/merge_requests/3',
251
+ };
252
+ return HttpResponse.json(createdMR, { status: 201 });
253
+ }),
254
+ http.delete(`${BASE_URL}/projects/*/merge_requests/*`, ({ request }) => {
255
+ // Check for forbidden project
256
+ if (request.url.includes('/forbidden-project/')) {
257
+ return HttpResponse.json({ message: 'Forbidden', error: 'You do not have permission to delete this merge request' }, { status: 403 });
258
+ }
259
+ const mergeRequestIid = extractIidFromUrl(request.url);
260
+ if (mergeRequestIid === null) {
261
+ return HttpResponse.json({ error: 'Invalid merge request IID' }, { status: 400 });
262
+ }
263
+ if (mergeRequestIid === 1) {
264
+ return new HttpResponse(null, { status: 204 });
265
+ }
266
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
267
+ }),
268
+ // Issues
269
+ http.get(`${BASE_URL}/projects/*/issues`, ({ request }) => {
270
+ const { page } = parsePaginationParams(request);
271
+ // Simple pagination
272
+ if (page === 1) {
273
+ return HttpResponse.json(fixtures.mockIssuesList);
274
+ }
275
+ return HttpResponse.json([]);
276
+ }),
277
+ http.get(`${BASE_URL}/projects/*/issues/*`, ({ request }) => {
278
+ const issueIid = extractIidFromUrl(request.url);
279
+ if (issueIid === null) {
280
+ return HttpResponse.json({ error: 'Invalid issue IID' }, { status: 400 });
281
+ }
282
+ if (issueIid === 1) {
283
+ return HttpResponse.json(fixtures.mockIssue);
284
+ }
285
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
286
+ }),
287
+ http.post(`${BASE_URL}/projects/*/issues`, async ({ request }) => {
288
+ const body = await request.json();
289
+ // Validate required fields
290
+ if (!body.title) {
291
+ return HttpResponse.json({ error: 'title is required' }, { status: 400 });
292
+ }
293
+ // Return created issue
294
+ const createdIssue = {
295
+ ...fixtures.mockIssue,
296
+ iid: 3,
297
+ id: 3,
298
+ title: body.title,
299
+ description: body.description || '',
300
+ state: 'opened',
301
+ web_url: 'https://gitlab.com/my-org/my-project/-/issues/3',
302
+ created_at: new Date().toISOString(),
303
+ };
304
+ return HttpResponse.json(createdIssue, { status: 201 });
305
+ }),
306
+ http.delete(`${BASE_URL}/projects/*/issues/*`, ({ request }) => {
307
+ // Check for forbidden project
308
+ if (request.url.includes('/forbidden-project/')) {
309
+ return HttpResponse.json({ message: 'Forbidden', error: 'You do not have permission to delete this issue' }, { status: 403 });
310
+ }
311
+ const issueIid = extractIidFromUrl(request.url);
312
+ if (issueIid === null) {
313
+ return HttpResponse.json({ error: 'Invalid issue IID' }, { status: 400 });
314
+ }
315
+ if (issueIid === 1) {
316
+ return new HttpResponse(null, { status: 204 });
317
+ }
318
+ return HttpResponse.json({ message: 'Not Found' }, { status: 404 });
319
+ }),
320
+ // Server error simulation
321
+ http.get(`${BASE_URL}/server-error-test`, () => {
322
+ return HttpResponse.json({ message: 'Internal Server Error' }, { status: 503 });
323
+ }),
324
+ ];
325
+ /**
326
+ * Create and configure mock server
327
+ *
328
+ * Why setupServer: MSW's node integration for testing environments
329
+ */
330
+ export const mockServer = setupServer(...handlers);
331
+ /**
332
+ * Helper: start server before tests
333
+ */
334
+ export function startMockServer() {
335
+ mockServer.listen({ onUnhandledRequest: 'error' });
336
+ }
337
+ /**
338
+ * Helper: reset handlers between tests
339
+ *
340
+ * Why: Prevents test pollution from runtime handler modifications
341
+ */
342
+ export function resetMockServer() {
343
+ mockServer.resetHandlers();
344
+ }
345
+ /**
346
+ * Helper: stop server after tests
347
+ */
348
+ export function stopMockServer() {
349
+ mockServer.close();
350
+ }
351
+ //# sourceMappingURL=mock-gitlab-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-gitlab-server.js","sourceRoot":"","sources":["../../../src/testing/mock-gitlab-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Mock server utilities for parsing HTTP requests
3
+ *
4
+ * Why: Eliminates code duplication in mock server handlers
5
+ * Provides consistent parameter parsing and validation
6
+ */
7
+ /**
8
+ * Parse URL from MSW request
9
+ */
10
+ export declare function parseUrl(request: Request): URL;
11
+ /**
12
+ * Parse pagination parameters (page, per_page)
13
+ */
14
+ export declare function parsePaginationParams(request: Request): {
15
+ page: number;
16
+ perPage: number;
17
+ };
18
+ /**
19
+ * Parse search parameter
20
+ */
21
+ export declare function parseSearchParam(request: Request): string | null;
22
+ /**
23
+ * Parse branch and ref parameters for repository operations
24
+ */
25
+ export declare function parseBranchParams(request: Request): {
26
+ branch?: string;
27
+ ref?: string;
28
+ };
29
+ /**
30
+ * Parse scope array parameter (GitLab style: scope[]=value1&scope[]=value2)
31
+ */
32
+ export declare function parseScopeParam(request: Request): string[];
33
+ /**
34
+ * Calculate pagination offset
35
+ */
36
+ export declare function calculateOffset(page: number, perPage: number): number;
37
+ /**
38
+ * Apply pagination to array data
39
+ */
40
+ export declare function applyPagination<T>(data: T[], page: number, perPage: number): T[];
41
+ //# sourceMappingURL=mock-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-utils.d.ts","sourceRoot":"","sources":["../../../src/testing/mock-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAE9C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAKzF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAMrF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAG1D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,CAAC,EAAE,EACT,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,CAAC,EAAE,CAGL"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Mock server utilities for parsing HTTP requests
3
+ *
4
+ * Why: Eliminates code duplication in mock server handlers
5
+ * Provides consistent parameter parsing and validation
6
+ */
7
+ /**
8
+ * Parse URL from MSW request
9
+ */
10
+ export function parseUrl(request) {
11
+ return new URL(request.url);
12
+ }
13
+ /**
14
+ * Parse pagination parameters (page, per_page)
15
+ */
16
+ export function parsePaginationParams(request) {
17
+ const url = parseUrl(request);
18
+ const page = parseInt(url.searchParams.get('page') || '1', 10);
19
+ const perPage = parseInt(url.searchParams.get('per_page') || '20', 10);
20
+ return { page, perPage };
21
+ }
22
+ /**
23
+ * Parse search parameter
24
+ */
25
+ export function parseSearchParam(request) {
26
+ const url = parseUrl(request);
27
+ return url.searchParams.get('search');
28
+ }
29
+ /**
30
+ * Parse branch and ref parameters for repository operations
31
+ */
32
+ export function parseBranchParams(request) {
33
+ const url = parseUrl(request);
34
+ return {
35
+ branch: url.searchParams.get('branch') || undefined,
36
+ ref: url.searchParams.get('ref') || undefined,
37
+ };
38
+ }
39
+ /**
40
+ * Parse scope array parameter (GitLab style: scope[]=value1&scope[]=value2)
41
+ */
42
+ export function parseScopeParam(request) {
43
+ const url = parseUrl(request);
44
+ return url.searchParams.getAll('scope[]');
45
+ }
46
+ /**
47
+ * Calculate pagination offset
48
+ */
49
+ export function calculateOffset(page, perPage) {
50
+ return (page - 1) * perPage;
51
+ }
52
+ /**
53
+ * Apply pagination to array data
54
+ */
55
+ export function applyPagination(data, page, perPage) {
56
+ const offset = calculateOffset(page, perPage);
57
+ return data.slice(offset, offset + perPage);
58
+ }
59
+ //# sourceMappingURL=mock-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-utils.js","sourceRoot":"","sources":["../../../src/testing/mock-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,SAAS;QACnD,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS;KAC9C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAS,EACT,IAAY,EACZ,OAAe;IAEf,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Test utilities for HTTP client setup and mocking
3
+ *
4
+ * Why: Eliminates code duplication in HTTP client test setup
5
+ * Provides consistent mocking and client creation patterns
6
+ */
7
+ import { HttpClient } from '../interceptors.js';
8
+ import type { InterceptorConfig } from '../types/profile.js';
9
+ type RequestInput = any;
10
+ /**
11
+ * Create HTTP client with interceptors for testing
12
+ */
13
+ export declare function createTestHttpClient(baseUrl?: RequestInput, interceptors?: InterceptorConfig): HttpClient;
14
+ /**
15
+ * Setup fetch mock that captures request headers
16
+ */
17
+ export declare function setupFetchMock(responseBody?: any, responseOptions?: ResponseInit): {
18
+ capturedHeaders: Record<RequestInput, RequestInput>;
19
+ };
20
+ /**
21
+ * Setup fetch mock that returns error response
22
+ */
23
+ export declare function setupErrorFetchMock(status?: number, message?: RequestInput): void;
24
+ /**
25
+ * Setup fetch mock for network errors
26
+ */
27
+ export declare function setupNetworkErrorFetchMock(): void;
28
+ /**
29
+ * Setup fetch mock for rate limiting
30
+ */
31
+ export declare function setupRateLimitFetchMock(): void;
32
+ /**
33
+ * Restore original fetch
34
+ */
35
+ export declare function restoreFetch(): void;
36
+ /**
37
+ * Test helper for HTTP client tests
38
+ */
39
+ export declare class HttpTestHelper {
40
+ private baseUrl;
41
+ private interceptors;
42
+ private capturedHeaders;
43
+ constructor(baseUrl?: RequestInput, interceptors?: InterceptorConfig);
44
+ private setupMock;
45
+ getClient(): HttpClient;
46
+ getCapturedHeaders(): Record<RequestInput, RequestInput>;
47
+ setResponse(responseBody: any, options?: ResponseInit): void;
48
+ setErrorResponse(status: number, message: RequestInput): void;
49
+ cleanup(): void;
50
+ }
51
+ export {};
52
+ //# sourceMappingURL=test-http-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-http-utils.d.ts","sourceRoot":"","sources":["../../../src/testing/test-http-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAoB,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,YAAwC,EACjD,YAAY,GAAE,iBAAsB,GACnC,UAAU,CAGZ;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,YAAY,GAAE,GAAkB,EAChC,eAAe,GAAE,YAA+E,GAC/F;IAAE,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;CAAE,CAUzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,MAAY,EAAE,OAAO,GAAE,YAAsC,GAAG,IAAI,CAK/G;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED;;GAEG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,YAAY;IAJtB,OAAO,CAAC,eAAe,CAA0C;gBAGvD,OAAO,GAAE,YAAwC,EACjD,YAAY,GAAE,iBAAsB;IAK9C,OAAO,CAAC,SAAS;IAUjB,SAAS,IAAI,UAAU;IAIvB,kBAAkB,IAAI,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC;IAIxD,WAAW,CAAC,YAAY,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAW5D,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAU7D,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Test utilities for HTTP client setup and mocking
3
+ *
4
+ * Why: Eliminates code duplication in HTTP client test setup
5
+ * Provides consistent mocking and client creation patterns
6
+ */
7
+ import { HttpClient, InterceptorChain } from '../interceptors.js';
8
+ /**
9
+ * Create HTTP client with interceptors for testing
10
+ */
11
+ export function createTestHttpClient(baseUrl = 'https://api.example.com', interceptors = {}) {
12
+ const interceptorChain = new InterceptorChain(interceptors);
13
+ return new HttpClient(baseUrl, interceptorChain);
14
+ }
15
+ /**
16
+ * Setup fetch mock that captures request headers
17
+ */
18
+ export function setupFetchMock(responseBody = { ok: true }, responseOptions = { status: 200, headers: { 'Content-Type': 'application/json' } }) {
19
+ const capturedHeaders = {};
20
+ global.fetch = async (url, init) => {
21
+ // Copy headers to the shared object
22
+ Object.assign(capturedHeaders, init?.headers || {});
23
+ return new Response(JSON.stringify(responseBody), responseOptions);
24
+ };
25
+ return { capturedHeaders };
26
+ }
27
+ /**
28
+ * Setup fetch mock that returns error response
29
+ */
30
+ export function setupErrorFetchMock(status = 500, message = 'Internal Server Error') {
31
+ global.fetch = async () => new Response(JSON.stringify({ message }), {
32
+ status,
33
+ headers: { 'Content-Type': 'application/json' }
34
+ });
35
+ }
36
+ /**
37
+ * Setup fetch mock for network errors
38
+ */
39
+ export function setupNetworkErrorFetchMock() {
40
+ global.fetch = async () => {
41
+ throw new Error('Network error');
42
+ };
43
+ }
44
+ /**
45
+ * Setup fetch mock for rate limiting
46
+ */
47
+ export function setupRateLimitFetchMock() {
48
+ global.fetch = async () => new Response(null, {
49
+ status: 429,
50
+ headers: { 'Retry-After': '60' }
51
+ });
52
+ }
53
+ /**
54
+ * Restore original fetch
55
+ */
56
+ export function restoreFetch() {
57
+ delete global.fetch;
58
+ }
59
+ /**
60
+ * Test helper for HTTP client tests
61
+ */
62
+ export class HttpTestHelper {
63
+ baseUrl;
64
+ interceptors;
65
+ capturedHeaders = {};
66
+ constructor(baseUrl = 'https://api.example.com', interceptors = {}) {
67
+ this.baseUrl = baseUrl;
68
+ this.interceptors = interceptors;
69
+ this.setupMock();
70
+ }
71
+ setupMock() {
72
+ global.fetch = async (url, init) => {
73
+ this.capturedHeaders = init?.headers;
74
+ return new Response(JSON.stringify({ ok: true }), {
75
+ status: 200,
76
+ headers: { 'Content-Type': 'application/json' }
77
+ });
78
+ };
79
+ }
80
+ getClient() {
81
+ return createTestHttpClient(this.baseUrl, this.interceptors);
82
+ }
83
+ getCapturedHeaders() {
84
+ return { ...this.capturedHeaders };
85
+ }
86
+ setResponse(responseBody, options) {
87
+ global.fetch = async (url, init) => {
88
+ Object.assign(this.capturedHeaders, init?.headers || {});
89
+ return new Response(JSON.stringify(responseBody), {
90
+ status: 200,
91
+ headers: { 'Content-Type': 'application/json' },
92
+ ...options
93
+ });
94
+ };
95
+ }
96
+ setErrorResponse(status, message) {
97
+ global.fetch = async (url, init) => {
98
+ Object.assign(this.capturedHeaders, init?.headers || {});
99
+ return new Response(JSON.stringify({ message }), {
100
+ status,
101
+ headers: { 'Content-Type': 'application/json' }
102
+ });
103
+ };
104
+ }
105
+ cleanup() {
106
+ restoreFetch();
107
+ }
108
+ }
109
+ //# sourceMappingURL=test-http-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-http-utils.js","sourceRoot":"","sources":["../../../src/testing/test-http-utils.ts"],"names":[],"mappings":"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"}