mcp4openapi 0.1.0 → 0.2.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 (152) hide show
  1. package/README.md +137 -95
  2. package/dist/scripts/validate-profile.js +3 -3
  3. package/dist/scripts/validate-profile.js.map +1 -1
  4. package/dist/src/composite-executor.d.ts +3 -1
  5. package/dist/src/composite-executor.d.ts.map +1 -1
  6. package/dist/src/composite-executor.js +16 -5
  7. package/dist/src/composite-executor.js.map +1 -1
  8. package/dist/src/constants.d.ts +49 -0
  9. package/dist/src/constants.d.ts.map +1 -1
  10. package/dist/src/constants.js +49 -0
  11. package/dist/src/constants.js.map +1 -1
  12. package/dist/src/errors.d.ts +6 -0
  13. package/dist/src/errors.d.ts.map +1 -1
  14. package/dist/src/errors.js +13 -0
  15. package/dist/src/errors.js.map +1 -1
  16. package/dist/src/generated-schemas.d.ts +832 -52
  17. package/dist/src/generated-schemas.d.ts.map +1 -1
  18. package/dist/src/generated-schemas.js +31 -8
  19. package/dist/src/generated-schemas.js.map +1 -1
  20. package/dist/src/http-client-factory.d.ts.map +1 -1
  21. package/dist/src/http-client-factory.js +14 -3
  22. package/dist/src/http-client-factory.js.map +1 -1
  23. package/dist/src/http-transport.d.ts +65 -0
  24. package/dist/src/http-transport.d.ts.map +1 -1
  25. package/dist/src/http-transport.js +921 -77
  26. package/dist/src/http-transport.js.map +1 -1
  27. package/dist/src/index.js +108 -8
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/interceptors.d.ts +3 -0
  30. package/dist/src/interceptors.d.ts.map +1 -1
  31. package/dist/src/interceptors.js +76 -8
  32. package/dist/src/interceptors.js.map +1 -1
  33. package/dist/src/logger.d.ts +1 -1
  34. package/dist/src/logger.js +3 -3
  35. package/dist/src/logger.js.map +1 -1
  36. package/dist/src/mcp-server.d.ts +33 -0
  37. package/dist/src/mcp-server.d.ts.map +1 -1
  38. package/dist/src/mcp-server.js +263 -54
  39. package/dist/src/mcp-server.js.map +1 -1
  40. package/dist/src/oauth-provider.d.ts +92 -0
  41. package/dist/src/oauth-provider.d.ts.map +1 -0
  42. package/dist/src/oauth-provider.js +588 -0
  43. package/dist/src/oauth-provider.js.map +1 -0
  44. package/dist/src/openapi-parser.d.ts +16 -0
  45. package/dist/src/openapi-parser.d.ts.map +1 -1
  46. package/dist/src/openapi-parser.js +141 -6
  47. package/dist/src/openapi-parser.js.map +1 -1
  48. package/dist/src/profile-loader.d.ts +2 -2
  49. package/dist/src/profile-loader.d.ts.map +1 -1
  50. package/dist/src/profile-loader.js +45 -24
  51. package/dist/src/profile-loader.js.map +1 -1
  52. package/dist/src/testing/fixtures.d.ts +189 -0
  53. package/dist/src/testing/fixtures.d.ts.map +1 -1
  54. package/dist/src/testing/fixtures.js +144 -0
  55. package/dist/src/testing/fixtures.js.map +1 -1
  56. package/dist/src/testing/mock-gitlab-server.d.ts +26 -17
  57. package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -1
  58. package/dist/src/testing/mock-gitlab-server.js +567 -304
  59. package/dist/src/testing/mock-gitlab-server.js.map +1 -1
  60. package/dist/src/types/http-transport.d.ts +16 -0
  61. package/dist/src/types/http-transport.d.ts.map +1 -1
  62. package/dist/src/types/openapi.d.ts +5 -0
  63. package/dist/src/types/openapi.d.ts.map +1 -1
  64. package/dist/src/types/profile.d.ts +112 -3
  65. package/dist/src/types/profile.d.ts.map +1 -1
  66. package/dist/src/validation-utils.d.ts +12 -0
  67. package/dist/src/validation-utils.d.ts.map +1 -1
  68. package/dist/src/validation-utils.js +17 -0
  69. package/dist/src/validation-utils.js.map +1 -1
  70. package/package.json +12 -3
  71. package/profile-schema.json +169 -7
  72. package/dist/composite-executor.d.ts +0 -65
  73. package/dist/composite-executor.d.ts.map +0 -1
  74. package/dist/composite-executor.js +0 -147
  75. package/dist/composite-executor.js.map +0 -1
  76. package/dist/constants.d.ts +0 -36
  77. package/dist/constants.d.ts.map +0 -1
  78. package/dist/constants.js +0 -36
  79. package/dist/constants.js.map +0 -1
  80. package/dist/http-transport.d.ts +0 -195
  81. package/dist/http-transport.d.ts.map +0 -1
  82. package/dist/http-transport.js +0 -760
  83. package/dist/http-transport.js.map +0 -1
  84. package/dist/interceptors.d.ts +0 -74
  85. package/dist/interceptors.d.ts.map +0 -1
  86. package/dist/interceptors.js +0 -220
  87. package/dist/interceptors.js.map +0 -1
  88. package/dist/logger.d.ts +0 -81
  89. package/dist/logger.d.ts.map +0 -1
  90. package/dist/logger.js +0 -264
  91. package/dist/logger.js.map +0 -1
  92. package/dist/mcp-server.d.ts +0 -110
  93. package/dist/mcp-server.d.ts.map +0 -1
  94. package/dist/mcp-server.js +0 -568
  95. package/dist/mcp-server.js.map +0 -1
  96. package/dist/metrics.d.ts +0 -86
  97. package/dist/metrics.d.ts.map +0 -1
  98. package/dist/metrics.js +0 -229
  99. package/dist/metrics.js.map +0 -1
  100. package/dist/openapi-parser.d.ts +0 -35
  101. package/dist/openapi-parser.d.ts.map +0 -1
  102. package/dist/openapi-parser.js +0 -160
  103. package/dist/openapi-parser.js.map +0 -1
  104. package/dist/profile-loader.d.ts +0 -25
  105. package/dist/profile-loader.d.ts.map +0 -1
  106. package/dist/profile-loader.js +0 -134
  107. package/dist/profile-loader.js.map +0 -1
  108. package/dist/schema-validator.d.ts +0 -32
  109. package/dist/schema-validator.d.ts.map +0 -1
  110. package/dist/schema-validator.js +0 -126
  111. package/dist/schema-validator.js.map +0 -1
  112. package/dist/testing/fixtures.d.ts +0 -186
  113. package/dist/testing/fixtures.d.ts.map +0 -1
  114. package/dist/testing/fixtures.js +0 -135
  115. package/dist/testing/fixtures.js.map +0 -1
  116. package/dist/testing/http-integration.test.d.ts +0 -7
  117. package/dist/testing/http-integration.test.d.ts.map +0 -1
  118. package/dist/testing/http-integration.test.js +0 -383
  119. package/dist/testing/http-integration.test.js.map +0 -1
  120. package/dist/testing/http-multiuser.test.d.ts +0 -10
  121. package/dist/testing/http-multiuser.test.d.ts.map +0 -1
  122. package/dist/testing/http-multiuser.test.js +0 -255
  123. package/dist/testing/http-multiuser.test.js.map +0 -1
  124. package/dist/testing/integration.test.d.ts +0 -8
  125. package/dist/testing/integration.test.d.ts.map +0 -1
  126. package/dist/testing/integration.test.js +0 -247
  127. package/dist/testing/integration.test.js.map +0 -1
  128. package/dist/testing/mock-gitlab-server.d.ts +0 -34
  129. package/dist/testing/mock-gitlab-server.d.ts.map +0 -1
  130. package/dist/testing/mock-gitlab-server.js +0 -224
  131. package/dist/testing/mock-gitlab-server.js.map +0 -1
  132. package/dist/testing/test-types.d.ts +0 -59
  133. package/dist/testing/test-types.d.ts.map +0 -1
  134. package/dist/testing/test-types.js +0 -7
  135. package/dist/testing/test-types.js.map +0 -1
  136. package/dist/tool-generator.d.ts +0 -43
  137. package/dist/tool-generator.d.ts.map +0 -1
  138. package/dist/tool-generator.js +0 -123
  139. package/dist/tool-generator.js.map +0 -1
  140. package/dist/tsconfig.tsbuildinfo +0 -1
  141. package/dist/types/http-transport.d.ts +0 -39
  142. package/dist/types/http-transport.d.ts.map +0 -1
  143. package/dist/types/http-transport.js +0 -8
  144. package/dist/types/http-transport.js.map +0 -1
  145. package/dist/types/openapi.d.ts +0 -50
  146. package/dist/types/openapi.d.ts.map +0 -1
  147. package/dist/types/openapi.js +0 -9
  148. package/dist/types/openapi.js.map +0 -1
  149. package/dist/types/profile.d.ts +0 -76
  150. package/dist/types/profile.d.ts.map +0 -1
  151. package/dist/types/profile.js +0 -9
  152. package/dist/types/profile.js.map +0 -1
@@ -30,6 +30,17 @@
30
30
  }
31
31
  ]
32
32
  },
33
+ "resource_name": {
34
+ "type": "string",
35
+ "description": "OAuth 2.0 Protected Resource name (overrides OpenAPI info.title). Defaults to 'MCP Server' if not specified.",
36
+ "examples": ["GitLab Production API", "GitHub Enterprise API"]
37
+ },
38
+ "resource_documentation": {
39
+ "type": "string",
40
+ "format": "uri",
41
+ "description": "OAuth 2.0 Protected Resource documentation URL (overrides OpenAPI externalDocs.url). Omitted if not specified.",
42
+ "examples": ["https://docs.gitlab.com/ee/api/", "https://docs.github.com/rest"]
43
+ },
33
44
  "tools": {
34
45
  "type": "array",
35
46
  "description": "List of MCP tools defined in this profile",
@@ -217,7 +228,19 @@
217
228
  "description": "HTTP interceptor configuration (auth, rate limiting, retry)",
218
229
  "properties": {
219
230
  "auth": {
220
- "$ref": "#/definitions/Auth"
231
+ "oneOf": [
232
+ {
233
+ "$ref": "#/definitions/Auth"
234
+ },
235
+ {
236
+ "type": "array",
237
+ "items": {
238
+ "$ref": "#/definitions/Auth"
239
+ },
240
+ "minItems": 1,
241
+ "description": "Multiple authentication methods (tried in order of priority)"
242
+ }
243
+ ]
221
244
  },
222
245
  "base_url": {
223
246
  "$ref": "#/definitions/BaseUrl"
@@ -239,18 +262,25 @@
239
262
  },
240
263
  "Auth": {
241
264
  "type": "object",
242
- "required": ["type", "value_from_env"],
265
+ "required": ["type"],
243
266
  "properties": {
244
267
  "type": {
245
268
  "type": "string",
246
- "enum": ["bearer", "query", "custom-header"],
269
+ "enum": ["bearer", "query", "custom-header", "oauth"],
247
270
  "description": "Authentication type"
248
271
  },
272
+ "priority": {
273
+ "type": "integer",
274
+ "description": "Priority for multi-auth (lower = higher priority). Default: 0. Used when multiple auth methods are configured.",
275
+ "default": 0,
276
+ "minimum": 0,
277
+ "examples": [0, 1, 2]
278
+ },
249
279
  "value_from_env": {
250
280
  "type": "string",
251
- "description": "Environment variable name containing the auth token",
281
+ "description": "Environment variable name containing the auth token (required for bearer, query, custom-header)",
252
282
  "pattern": "^[A-Z][A-Z0-9_]*$",
253
- "examples": ["API_TOKEN", "GITLAB_TOKEN"]
283
+ "examples": ["MCP4_API_TOKEN", "GITLAB_TOKEN"]
254
284
  },
255
285
  "header_name": {
256
286
  "type": "string",
@@ -261,9 +291,48 @@
261
291
  "type": "string",
262
292
  "description": "Query parameter name (required for query type)",
263
293
  "examples": ["api_key", "token"]
294
+ },
295
+ "oauth_config": {
296
+ "$ref": "#/definitions/OAuthConfig"
297
+ },
298
+ "oauth_rate_limit": {
299
+ "type": "object",
300
+ "description": "OAuth rate limiting configuration. Overrides default OAuth rate limits (10 requests per 15 minutes).",
301
+ "properties": {
302
+ "max_requests": {
303
+ "type": "number",
304
+ "description": "Maximum number of OAuth requests allowed per window",
305
+ "minimum": 1,
306
+ "examples": [10, 20, 50]
307
+ },
308
+ "window_ms": {
309
+ "type": "number",
310
+ "description": "Rate limit window in milliseconds",
311
+ "minimum": 1000,
312
+ "examples": [900000, 1800000, 3600000]
313
+ }
314
+ },
315
+ "required": ["max_requests", "window_ms"]
264
316
  }
265
317
  },
266
318
  "allOf": [
319
+ {
320
+ "if": {
321
+ "properties": {
322
+ "type": {
323
+ "enum": ["bearer", "query", "custom-header"]
324
+ }
325
+ }
326
+ },
327
+ "then": {
328
+ "required": ["value_from_env"],
329
+ "properties": {
330
+ "value_from_env": {
331
+ "type": "string"
332
+ }
333
+ }
334
+ }
335
+ },
267
336
  {
268
337
  "if": {
269
338
  "properties": {
@@ -297,9 +366,102 @@
297
366
  }
298
367
  }
299
368
  }
369
+ },
370
+ {
371
+ "if": {
372
+ "properties": {
373
+ "type": {
374
+ "const": "oauth"
375
+ }
376
+ }
377
+ },
378
+ "then": {
379
+ "required": ["oauth_config"],
380
+ "properties": {
381
+ "oauth_config": {
382
+ "$ref": "#/definitions/OAuthConfig"
383
+ },
384
+ "oauth_rate_limit": {
385
+ "type": "object",
386
+ "description": "OAuth rate limiting configuration. Overrides default OAuth rate limits (10 requests per 15 minutes).",
387
+ "properties": {
388
+ "max_requests": {
389
+ "type": "number",
390
+ "description": "Maximum number of OAuth requests allowed per window",
391
+ "minimum": 1
392
+ },
393
+ "window_ms": {
394
+ "type": "number",
395
+ "description": "Rate limit window in milliseconds",
396
+ "minimum": 1000
397
+ }
398
+ },
399
+ "required": ["max_requests", "window_ms"]
400
+ }
401
+ }
402
+ }
300
403
  }
301
404
  ]
302
405
  },
406
+ "OAuthConfig": {
407
+ "type": "object",
408
+ "description": "OAuth 2.0 configuration. Must provide EITHER 'issuer' (endpoints auto-derived) OR both 'authorization_endpoint' and 'token_endpoint' (explicit).",
409
+ "properties": {
410
+ "issuer": {
411
+ "type": "string",
412
+ "description": "OAuth 2.0 issuer URL (RFC 8414). When provided, authorization_endpoint and token_endpoint are auto-derived via /.well-known/oauth-authorization-server or standard paths. Supports ${env:VAR} syntax.",
413
+ "examples": ["https://gitlab.example.com", "${env:MCP4_OAUTH_ISSUER}"]
414
+ },
415
+ "authorization_endpoint": {
416
+ "type": "string",
417
+ "description": "OAuth 2.0 authorization endpoint. Optional if issuer is provided. Supports ${env:VAR} syntax.",
418
+ "examples": ["https://gitlab.example.com/oauth/authorize", "${env:OAUTH_AUTHORIZATION_URL}"]
419
+ },
420
+ "token_endpoint": {
421
+ "type": "string",
422
+ "description": "OAuth 2.0 token endpoint. Optional if issuer is provided. Supports ${env:VAR} syntax.",
423
+ "examples": ["https://gitlab.example.com/oauth/token", "${env:OAUTH_TOKEN_URL}"]
424
+ },
425
+ "client_id": {
426
+ "type": "string",
427
+ "description": "Pre-registered OAuth client ID (supports ${env:VAR} syntax). Optional for dynamic registration.",
428
+ "examples": ["${env:MCP4_OAUTH_CLIENT_ID}"]
429
+ },
430
+ "client_secret": {
431
+ "type": "string",
432
+ "description": "Pre-registered OAuth client secret (supports ${env:VAR} syntax). Optional for public clients.",
433
+ "examples": ["${env:MCP4_OAUTH_CLIENT_SECRET}"]
434
+ },
435
+ "scopes": {
436
+ "type": "array",
437
+ "description": "OAuth 2.0 scopes to request. Optional - if not provided, no scopes will be requested (some APIs don't require scopes)",
438
+ "items": {
439
+ "type": "string"
440
+ },
441
+ "examples": [["api", "read_user"], ["read_repository", "write_repository"]]
442
+ },
443
+ "redirect_uri": {
444
+ "type": "string",
445
+ "description": "OAuth callback URI. Defaults to http://{MCP4_HOST}:{MCP4_PORT}/oauth/callback",
446
+ "examples": ["https://<your-mcp-server-host>/oauth/callback"]
447
+ },
448
+ "registration_endpoint": {
449
+ "type": "string",
450
+ "description": "Client registration endpoint for dynamic registration (RFC 7591)",
451
+ "examples": ["https://gitlab.example.com/oauth/register"]
452
+ },
453
+ "introspection_endpoint": {
454
+ "type": "string",
455
+ "description": "Token introspection endpoint (RFC 7662)",
456
+ "examples": ["https://gitlab.example.com/oauth/introspect"]
457
+ },
458
+ "revocation_endpoint": {
459
+ "type": "string",
460
+ "description": "Token revocation endpoint (RFC 7009)",
461
+ "examples": ["https://gitlab.example.com/oauth/revoke"]
462
+ }
463
+ }
464
+ },
303
465
  "BaseUrl": {
304
466
  "type": "object",
305
467
  "required": ["value_from_env"],
@@ -308,13 +470,13 @@
308
470
  "type": "string",
309
471
  "description": "Environment variable name containing the base URL",
310
472
  "pattern": "^[A-Z][A-Z0-9_]*$",
311
- "examples": ["API_BASE_URL"]
473
+ "examples": ["MCP4_API_BASE_URL"]
312
474
  },
313
475
  "default": {
314
476
  "type": "string",
315
477
  "format": "uri",
316
478
  "description": "Default base URL if environment variable is not set",
317
- "examples": ["https://gitlab.com/api/v4"]
479
+ "examples": ["https://www.gitlab.com/api/v4"]
318
480
  }
319
481
  }
320
482
  },
@@ -1,65 +0,0 @@
1
- /**
2
- * Composite action executor for chaining API calls
3
- *
4
- * Why: Reduces roundtrips by fetching related data in sequence (e.g., MR + comments).
5
- * Aggregates results into single JSON structure as defined by store_as paths.
6
- */
7
- import type { CompositeStep } from './types/profile.js';
8
- import type { HttpClient } from './interceptors.js';
9
- import { OpenAPIParser } from './openapi-parser.js';
10
- export interface CompositeResult {
11
- data: Record<string, unknown>;
12
- completed_steps: number;
13
- total_steps: number;
14
- errors?: StepError[];
15
- }
16
- export interface StepError {
17
- step_index: number;
18
- step_call: string;
19
- error: string;
20
- timestamp: string;
21
- }
22
- export declare class CompositeExecutor {
23
- private parser;
24
- private httpClient?;
25
- constructor(parser: OpenAPIParser, httpClient?: HttpClient);
26
- /**
27
- * Execute a series of API calls and merge results
28
- *
29
- * Why sequential: Steps may depend on previous results (e.g., get MR ID, then fetch comments).
30
- * Could parallelize independent steps in future optimization.
31
- *
32
- * Supports partial results: If allowPartial=true, continues after errors and returns
33
- * what was completed. Useful for composite actions where some data is better than none.
34
- */
35
- execute(steps: CompositeStep[], args: Record<string, unknown>, allowPartial?: boolean, httpClient?: HttpClient): Promise<CompositeResult>;
36
- /**
37
- * Parse composite step call syntax
38
- *
39
- * Format: "GET /projects/{id}/merge_requests/{iid}"
40
- */
41
- private parseCall;
42
- /**
43
- * Resolve path template with actual values
44
- *
45
- * Example: "/projects/{id}" + {id: "123"} => "/projects/123"
46
- */
47
- private resolvePath;
48
- /**
49
- * Extract query parameters from args based on operation definition
50
- */
51
- private extractQueryParams;
52
- /**
53
- * Store value at JSONPath-like location
54
- *
55
- * Why nested: Allows semantic structure (comments belong under merge_request object).
56
- *
57
- * Examples:
58
- * - "merge_request" => { merge_request: value }
59
- * - "merge_request.comments" => { merge_request: { comments: value } }
60
- *
61
- * Validates path navigation to prevent overwriting non-object values.
62
- */
63
- private storeResult;
64
- }
65
- //# sourceMappingURL=composite-executor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"composite-executor.d.ts","sourceRoot":"","sources":["../src/composite-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU,CAAC;gBADX,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,UAAU;IAGjC;;;;;;;;OAQG;IACG,OAAO,CACX,KAAK,EAAE,aAAa,EAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,YAAY,GAAE,OAAe,EAC7B,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,eAAe,CAAC;IAoE3B;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;CAwBpB"}
@@ -1,147 +0,0 @@
1
- /**
2
- * Composite action executor for chaining API calls
3
- *
4
- * Why: Reduces roundtrips by fetching related data in sequence (e.g., MR + comments).
5
- * Aggregates results into single JSON structure as defined by store_as paths.
6
- */
7
- export class CompositeExecutor {
8
- parser;
9
- httpClient;
10
- constructor(parser, httpClient) {
11
- this.parser = parser;
12
- this.httpClient = httpClient;
13
- }
14
- /**
15
- * Execute a series of API calls and merge results
16
- *
17
- * Why sequential: Steps may depend on previous results (e.g., get MR ID, then fetch comments).
18
- * Could parallelize independent steps in future optimization.
19
- *
20
- * Supports partial results: If allowPartial=true, continues after errors and returns
21
- * what was completed. Useful for composite actions where some data is better than none.
22
- */
23
- async execute(steps, args, allowPartial = false, httpClient) {
24
- const result = {};
25
- const errors = [];
26
- let completedSteps = 0;
27
- for (let i = 0; i < steps.length; i++) {
28
- const step = steps[i];
29
- try {
30
- const { method, path, operation } = this.parseCall(step.call);
31
- if (!operation) {
32
- throw new Error(`Operation not found for call: ${step.call}`);
33
- }
34
- // Substitute path parameters from args
35
- const resolvedPath = this.resolvePath(path, args);
36
- // Execute request
37
- const client = httpClient || this.httpClient;
38
- if (!client) {
39
- throw new Error('HTTP client not provided');
40
- }
41
- const response = await client.request(method, resolvedPath, {
42
- params: this.extractQueryParams(operation, args),
43
- });
44
- // Store result at specified path
45
- this.storeResult(result, step.store_as, response.body);
46
- completedSteps++;
47
- }
48
- catch (error) {
49
- const stepError = {
50
- step_index: i,
51
- step_call: step.call,
52
- error: error instanceof Error ? error.message : String(error),
53
- timestamp: new Date().toISOString(),
54
- };
55
- errors.push(stepError);
56
- // Store error in result for debugging
57
- this.storeResult(result, `${step.store_as}_error`, stepError);
58
- if (!allowPartial) {
59
- throw new Error(`Composite step ${i + 1}/${steps.length} failed: ${stepError.error}\n` +
60
- `Completed steps: ${completedSteps}\n` +
61
- `Failed step: ${step.call}`);
62
- }
63
- // Continue with next step if partial results allowed
64
- }
65
- }
66
- return {
67
- data: result,
68
- completed_steps: completedSteps,
69
- total_steps: steps.length,
70
- errors: errors.length > 0 ? errors : undefined,
71
- };
72
- }
73
- /**
74
- * Parse composite step call syntax
75
- *
76
- * Format: "GET /projects/{id}/merge_requests/{iid}"
77
- */
78
- parseCall(call) {
79
- const [method, path] = call.split(' ');
80
- const pathInfo = this.parser.getPath(path);
81
- const operation = pathInfo?.operations[method.toLowerCase()];
82
- return { method, path, operation };
83
- }
84
- /**
85
- * Resolve path template with actual values
86
- *
87
- * Example: "/projects/{id}" + {id: "123"} => "/projects/123"
88
- */
89
- resolvePath(template, args) {
90
- return template.replace(/\{(\w+)\}/g, (_, key) => {
91
- const value = args[key];
92
- if (value === undefined) {
93
- throw new Error(`Missing path parameter: ${key}`);
94
- }
95
- return String(value);
96
- });
97
- }
98
- /**
99
- * Extract query parameters from args based on operation definition
100
- */
101
- extractQueryParams(operation, args) {
102
- const params = {};
103
- for (const param of operation.parameters) {
104
- if (param.in === 'query' && args[param.name] !== undefined) {
105
- const value = args[param.name];
106
- // Pass arrays as-is for HttpClient serialization
107
- if (Array.isArray(value)) {
108
- params[param.name] = value.map(String);
109
- }
110
- else {
111
- params[param.name] = String(value);
112
- }
113
- }
114
- }
115
- return params;
116
- }
117
- /**
118
- * Store value at JSONPath-like location
119
- *
120
- * Why nested: Allows semantic structure (comments belong under merge_request object).
121
- *
122
- * Examples:
123
- * - "merge_request" => { merge_request: value }
124
- * - "merge_request.comments" => { merge_request: { comments: value } }
125
- *
126
- * Validates path navigation to prevent overwriting non-object values.
127
- */
128
- storeResult(target, path, value) {
129
- const parts = path.split('.');
130
- let current = target;
131
- for (let i = 0; i < parts.length - 1; i++) {
132
- const part = parts[i];
133
- const existing = current[part];
134
- // Validate we can navigate through this path
135
- if (existing !== undefined && (typeof existing !== 'object' || existing === null)) {
136
- throw new Error(`Cannot store at path '${path}': ` +
137
- `'${parts.slice(0, i + 1).join('.')}' is ${typeof existing}, not an object`);
138
- }
139
- if (!current[part]) {
140
- current[part] = {};
141
- }
142
- current = current[part];
143
- }
144
- current[parts[parts.length - 1]] = value;
145
- }
146
- }
147
- //# sourceMappingURL=composite-executor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"composite-executor.js","sourceRoot":"","sources":["../src/composite-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,MAAM,OAAO,iBAAiB;IAElB;IACA;IAFV,YACU,MAAqB,EACrB,UAAuB;QADvB,WAAM,GAAN,MAAM,CAAe;QACrB,eAAU,GAAV,UAAU,CAAa;IAC9B,CAAC;IAEJ;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CACX,KAAsB,EACtB,IAA6B,EAC7B,eAAwB,KAAK,EAC7B,UAAuB;QAEvB,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,IAAI,cAAc,GAAG,CAAC,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAE9D,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAChE,CAAC;gBAED,uCAAuC;gBACvC,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAElD,kBAAkB;gBAClB,MAAM,MAAM,GAAG,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC;gBAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;gBAC9C,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE;oBAC1D,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,IAAI,CAAC;iBACjD,CAAC,CAAC;gBAEH,iCAAiC;gBACjC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACvD,cAAc,EAAE,CAAC;YAEnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,SAAS,GAAc;oBAC3B,UAAU,EAAE,CAAC;oBACb,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC7D,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC;gBAEF,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAEvB,sCAAsC;gBACtC,IAAI,CAAC,WAAW,CACd,MAAM,EACN,GAAG,IAAI,CAAC,QAAQ,QAAQ,EACxB,SAAS,CACV,CAAC;gBAEF,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,IAAI,KAAK,CACb,kBAAkB,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,YAAY,SAAS,CAAC,KAAK,IAAI;wBACtE,oBAAoB,cAAc,IAAI;wBACtC,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAC5B,CAAC;gBACJ,CAAC;gBAED,qDAAqD;YACvD,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,eAAe,EAAE,cAAc;YAC/B,WAAW,EAAE,KAAK,CAAC,MAAM;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC/C,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,SAAS,CAAC,IAAY;QAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QAE7D,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACK,WAAW,CAAC,QAAgB,EAAE,IAA6B;QACjE,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,SAAwB,EAAE,IAA6B;QAChF,MAAM,MAAM,GAAsC,EAAE,CAAC;QAErD,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,UAAU,EAAE,CAAC;YACzC,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC/B,iDAAiD;gBACjD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACzC,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;OAUG;IACK,WAAW,CAAC,MAA+B,EAAE,IAAY,EAAE,KAAc;QAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,OAAO,GAAG,MAAiC,CAAC;QAEhD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAE/B,6CAA6C;YAC7C,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,CAAC,EAAE,CAAC;gBAClF,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,KAAK;oBAClC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,OAAO,QAAQ,iBAAiB,CAC5E,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACrB,CAAC;YACD,OAAO,GAAG,OAAO,CAAC,IAAI,CAA4B,CAAC;QACrD,CAAC;QAED,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IAC3C,CAAC;CACF"}
@@ -1,36 +0,0 @@
1
- /**
2
- * Application constants
3
- *
4
- * Why: Centralized constants improve readability and maintainability.
5
- * Magic numbers scattered through code are harder to understand and change.
6
- */
7
- /**
8
- * Time conversion constants
9
- */
10
- export declare const TIME: {
11
- readonly MS_PER_SECOND: 1000;
12
- readonly MS_PER_MINUTE: 60000;
13
- readonly MS_PER_HOUR: 3600000;
14
- readonly SECONDS_PER_MINUTE: 60;
15
- readonly MINUTES_PER_HOUR: 60;
16
- };
17
- /**
18
- * HTTP status codes
19
- *
20
- * Why: Named constants more readable than numeric literals.
21
- * Makes intent clear (STATUS_TOO_MANY_REQUESTS vs 429).
22
- */
23
- export declare const HTTP_STATUS: {
24
- readonly OK: 200;
25
- readonly MULTIPLE_CHOICES: 300;
26
- readonly BAD_REQUEST: 400;
27
- readonly UNAUTHORIZED: 401;
28
- readonly FORBIDDEN: 403;
29
- readonly NOT_FOUND: 404;
30
- readonly TOO_MANY_REQUESTS: 429;
31
- readonly INTERNAL_SERVER_ERROR: 500;
32
- readonly BAD_GATEWAY: 502;
33
- readonly SERVICE_UNAVAILABLE: 503;
34
- readonly GATEWAY_TIMEOUT: 504;
35
- };
36
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,IAAI;;;;;;CAMP,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;CAYd,CAAC"}
package/dist/constants.js DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * Application constants
3
- *
4
- * Why: Centralized constants improve readability and maintainability.
5
- * Magic numbers scattered through code are harder to understand and change.
6
- */
7
- /**
8
- * Time conversion constants
9
- */
10
- export const TIME = {
11
- MS_PER_SECOND: 1000,
12
- MS_PER_MINUTE: 60000,
13
- MS_PER_HOUR: 3600000,
14
- SECONDS_PER_MINUTE: 60,
15
- MINUTES_PER_HOUR: 60,
16
- };
17
- /**
18
- * HTTP status codes
19
- *
20
- * Why: Named constants more readable than numeric literals.
21
- * Makes intent clear (STATUS_TOO_MANY_REQUESTS vs 429).
22
- */
23
- export const HTTP_STATUS = {
24
- OK: 200,
25
- MULTIPLE_CHOICES: 300,
26
- BAD_REQUEST: 400,
27
- UNAUTHORIZED: 401,
28
- FORBIDDEN: 403,
29
- NOT_FOUND: 404,
30
- TOO_MANY_REQUESTS: 429,
31
- INTERNAL_SERVER_ERROR: 500,
32
- BAD_GATEWAY: 502,
33
- SERVICE_UNAVAILABLE: 503,
34
- GATEWAY_TIMEOUT: 504,
35
- };
36
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,OAAO;IACpB,kBAAkB,EAAE,EAAE;IACtB,gBAAgB,EAAE,EAAE;CACZ,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,EAAE,EAAE,GAAG;IACP,gBAAgB,EAAE,GAAG;IACrB,WAAW,EAAE,GAAG;IAChB,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,iBAAiB,EAAE,GAAG;IACtB,qBAAqB,EAAE,GAAG;IAC1B,WAAW,EAAE,GAAG;IAChB,mBAAmB,EAAE,GAAG;IACxB,eAAe,EAAE,GAAG;CACZ,CAAC"}