mcp-openapi-schema-explorer 1.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 (133) hide show
  1. package/.devcontainer/devcontainer.json +24 -0
  2. package/.github/dependabot.yml +13 -0
  3. package/.github/workflows/ci.yml +111 -0
  4. package/.husky/pre-commit +6 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc.json +12 -0
  7. package/.releaserc.json +23 -0
  8. package/CHANGELOG.md +32 -0
  9. package/CONTRIBUTING.md +67 -0
  10. package/Dockerfile +3 -0
  11. package/LICENSE +21 -0
  12. package/README.md +127 -0
  13. package/dist/src/config.d.ts +15 -0
  14. package/dist/src/config.js +19 -0
  15. package/dist/src/config.js.map +1 -0
  16. package/dist/src/handlers/component-detail-handler.d.ts +14 -0
  17. package/dist/src/handlers/component-detail-handler.js +87 -0
  18. package/dist/src/handlers/component-detail-handler.js.map +1 -0
  19. package/dist/src/handlers/component-map-handler.d.ts +14 -0
  20. package/dist/src/handlers/component-map-handler.js +63 -0
  21. package/dist/src/handlers/component-map-handler.js.map +1 -0
  22. package/dist/src/handlers/handler-utils.d.ts +69 -0
  23. package/dist/src/handlers/handler-utils.js +180 -0
  24. package/dist/src/handlers/handler-utils.js.map +1 -0
  25. package/dist/src/handlers/operation-handler.d.ts +14 -0
  26. package/dist/src/handlers/operation-handler.js +86 -0
  27. package/dist/src/handlers/operation-handler.js.map +1 -0
  28. package/dist/src/handlers/path-item-handler.d.ts +14 -0
  29. package/dist/src/handlers/path-item-handler.js +66 -0
  30. package/dist/src/handlers/path-item-handler.js.map +1 -0
  31. package/dist/src/handlers/top-level-field-handler.d.ts +14 -0
  32. package/dist/src/handlers/top-level-field-handler.js +72 -0
  33. package/dist/src/handlers/top-level-field-handler.js.map +1 -0
  34. package/dist/src/index.d.ts +2 -0
  35. package/dist/src/index.js +177 -0
  36. package/dist/src/index.js.map +1 -0
  37. package/dist/src/rendering/components.d.ts +67 -0
  38. package/dist/src/rendering/components.js +177 -0
  39. package/dist/src/rendering/components.js.map +1 -0
  40. package/dist/src/rendering/document.d.ts +36 -0
  41. package/dist/src/rendering/document.js +147 -0
  42. package/dist/src/rendering/document.js.map +1 -0
  43. package/dist/src/rendering/path-item.d.ts +45 -0
  44. package/dist/src/rendering/path-item.js +141 -0
  45. package/dist/src/rendering/path-item.js.map +1 -0
  46. package/dist/src/rendering/paths.d.ts +26 -0
  47. package/dist/src/rendering/paths.js +78 -0
  48. package/dist/src/rendering/paths.js.map +1 -0
  49. package/dist/src/rendering/types.d.ts +50 -0
  50. package/dist/src/rendering/types.js +12 -0
  51. package/dist/src/rendering/types.js.map +1 -0
  52. package/dist/src/rendering/utils.d.ts +31 -0
  53. package/dist/src/rendering/utils.js +79 -0
  54. package/dist/src/rendering/utils.js.map +1 -0
  55. package/dist/src/services/formatters.d.ts +36 -0
  56. package/dist/src/services/formatters.js +52 -0
  57. package/dist/src/services/formatters.js.map +1 -0
  58. package/dist/src/services/reference-transform.d.ts +27 -0
  59. package/dist/src/services/reference-transform.js +75 -0
  60. package/dist/src/services/reference-transform.js.map +1 -0
  61. package/dist/src/services/spec-loader.d.ts +27 -0
  62. package/dist/src/services/spec-loader.js +77 -0
  63. package/dist/src/services/spec-loader.js.map +1 -0
  64. package/dist/src/types.d.ts +11 -0
  65. package/dist/src/types.js +2 -0
  66. package/dist/src/types.js.map +1 -0
  67. package/dist/src/utils/uri-builder.d.ts +81 -0
  68. package/dist/src/utils/uri-builder.js +121 -0
  69. package/dist/src/utils/uri-builder.js.map +1 -0
  70. package/dist/src/version.d.ts +1 -0
  71. package/dist/src/version.js +4 -0
  72. package/dist/src/version.js.map +1 -0
  73. package/eslint.config.js +88 -0
  74. package/jest.config.js +32 -0
  75. package/justfile +66 -0
  76. package/memory-bank/activeContext.md +139 -0
  77. package/memory-bank/productContext.md +39 -0
  78. package/memory-bank/progress.md +141 -0
  79. package/memory-bank/projectbrief.md +50 -0
  80. package/memory-bank/systemPatterns.md +224 -0
  81. package/memory-bank/techContext.md +131 -0
  82. package/package.json +76 -0
  83. package/scripts/generate-version.js +49 -0
  84. package/src/config.ts +33 -0
  85. package/src/handlers/component-detail-handler.ts +121 -0
  86. package/src/handlers/component-map-handler.ts +92 -0
  87. package/src/handlers/handler-utils.ts +230 -0
  88. package/src/handlers/operation-handler.ts +114 -0
  89. package/src/handlers/path-item-handler.ts +88 -0
  90. package/src/handlers/top-level-field-handler.ts +92 -0
  91. package/src/index.ts +222 -0
  92. package/src/rendering/components.ts +228 -0
  93. package/src/rendering/document.ts +167 -0
  94. package/src/rendering/path-item.ts +157 -0
  95. package/src/rendering/paths.ts +87 -0
  96. package/src/rendering/types.ts +63 -0
  97. package/src/rendering/utils.ts +107 -0
  98. package/src/services/formatters.ts +71 -0
  99. package/src/services/reference-transform.ts +105 -0
  100. package/src/services/spec-loader.ts +88 -0
  101. package/src/types.ts +17 -0
  102. package/src/utils/uri-builder.ts +134 -0
  103. package/src/version.ts +4 -0
  104. package/test/__tests__/e2e/format.test.ts +224 -0
  105. package/test/__tests__/e2e/resources.test.ts +369 -0
  106. package/test/__tests__/e2e/spec-loading.test.ts +172 -0
  107. package/test/__tests__/unit/config.test.ts +39 -0
  108. package/test/__tests__/unit/handlers/component-detail-handler.test.ts +241 -0
  109. package/test/__tests__/unit/handlers/component-map-handler.test.ts +187 -0
  110. package/test/__tests__/unit/handlers/handler-utils.test.ts +255 -0
  111. package/test/__tests__/unit/handlers/operation-handler.test.ts +202 -0
  112. package/test/__tests__/unit/handlers/path-item-handler.test.ts +153 -0
  113. package/test/__tests__/unit/handlers/top-level-field-handler.test.ts +182 -0
  114. package/test/__tests__/unit/rendering/components.test.ts +269 -0
  115. package/test/__tests__/unit/rendering/document.test.ts +172 -0
  116. package/test/__tests__/unit/rendering/path-item.test.ts +197 -0
  117. package/test/__tests__/unit/rendering/paths.test.ts +115 -0
  118. package/test/__tests__/unit/services/formatters.test.ts +109 -0
  119. package/test/__tests__/unit/services/reference-transform.test.ts +320 -0
  120. package/test/__tests__/unit/services/spec-loader.test.ts +214 -0
  121. package/test/__tests__/unit/utils/uri-builder.test.ts +103 -0
  122. package/test/fixtures/complex-endpoint.json +146 -0
  123. package/test/fixtures/empty-api.json +8 -0
  124. package/test/fixtures/multi-component-types.json +55 -0
  125. package/test/fixtures/paths-test.json +61 -0
  126. package/test/fixtures/sample-api.json +68 -0
  127. package/test/fixtures/sample-v2-api.json +39 -0
  128. package/test/setup.ts +32 -0
  129. package/test/utils/console-helpers.ts +48 -0
  130. package/test/utils/mcp-test-helpers.ts +66 -0
  131. package/test/utils/test-types.ts +54 -0
  132. package/tsconfig.json +25 -0
  133. package/tsconfig.test.json +5 -0
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'; // Import ResourceTemplate
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { loadConfig } from './config.js';
5
+ // Import new handlers
6
+ import { TopLevelFieldHandler } from './handlers/top-level-field-handler.js';
7
+ import { PathItemHandler } from './handlers/path-item-handler.js';
8
+ import { OperationHandler } from './handlers/operation-handler.js';
9
+ import { ComponentMapHandler } from './handlers/component-map-handler.js';
10
+ import { ComponentDetailHandler } from './handlers/component-detail-handler.js';
11
+ import { OpenAPITransformer, ReferenceTransformService } from './services/reference-transform.js';
12
+ import { SpecLoaderService } from './services/spec-loader.js';
13
+ import { createFormatter } from './services/formatters.js';
14
+ import { encodeUriPathComponent } from './utils/uri-builder.js'; // Import specific function
15
+ import { isOpenAPIV3, getValidatedComponentMap } from './handlers/handler-utils.js'; // Import type guard and helper
16
+ import { VERSION } from './version.js'; // Import the generated version
17
+ async function main() {
18
+ try {
19
+ // Get spec path and options from command line arguments
20
+ const [, , specPath, ...args] = process.argv;
21
+ const options = {
22
+ outputFormat: args.includes('--output-format')
23
+ ? args[args.indexOf('--output-format') + 1]
24
+ : undefined,
25
+ };
26
+ // Load configuration
27
+ const config = loadConfig(specPath, options);
28
+ // Initialize services
29
+ const referenceTransform = new ReferenceTransformService();
30
+ referenceTransform.registerTransformer('openapi', new OpenAPITransformer());
31
+ const specLoader = new SpecLoaderService(config.specPath, referenceTransform);
32
+ await specLoader.loadSpec();
33
+ // Get the loaded spec to extract the title
34
+ const spec = await specLoader.getSpec(); // Rename back to spec
35
+ // Get the transformed spec for use in completions
36
+ const transformedSpec = await specLoader.getTransformedSpec({
37
+ resourceType: 'schema', // Use a default context
38
+ format: 'openapi',
39
+ });
40
+ const defaultServerName = 'OpenAPI Schema Explorer';
41
+ // Use original spec for title
42
+ const serverName = spec.info?.title
43
+ ? `Schema Explorer for ${spec.info.title}`
44
+ : defaultServerName;
45
+ // Create MCP server with dynamic name
46
+ const server = new McpServer({
47
+ name: serverName,
48
+ version: VERSION, // Use the imported version
49
+ });
50
+ // Set up formatter and new handlers
51
+ const formatter = createFormatter(config.outputFormat);
52
+ const topLevelFieldHandler = new TopLevelFieldHandler(specLoader, formatter);
53
+ const pathItemHandler = new PathItemHandler(specLoader, formatter);
54
+ const operationHandler = new OperationHandler(specLoader, formatter);
55
+ const componentMapHandler = new ComponentMapHandler(specLoader, formatter);
56
+ const componentDetailHandler = new ComponentDetailHandler(specLoader, formatter);
57
+ // Register new resources
58
+ // 1. openapi://{field}
59
+ const fieldTemplate = new ResourceTemplate('openapi://{field}', {
60
+ list: undefined, // List is handled by the handler logic based on field value
61
+ complete: {
62
+ field: () => Object.keys(transformedSpec), // Use transformedSpec
63
+ },
64
+ });
65
+ server.resource('openapi-field', // Unique ID for the resource registration
66
+ fieldTemplate, {
67
+ // MimeType varies (text/plain for lists, JSON/YAML for details) - SDK might handle this? Or maybe set a default? Let's omit for now.
68
+ description: 'Access top-level fields (info, servers, tags), list paths, or list component types.',
69
+ name: 'OpenAPI Field/List', // Generic name
70
+ }, topLevelFieldHandler.handleRequest);
71
+ // 2. openapi://paths/{path}
72
+ const pathTemplate = new ResourceTemplate('openapi://paths/{path}', {
73
+ list: undefined, // List is handled by the handler
74
+ complete: {
75
+ path: () => Object.keys(transformedSpec.paths ?? {}).map(encodeUriPathComponent), // Use imported function directly
76
+ },
77
+ });
78
+ server.resource('openapi-path-methods', pathTemplate, {
79
+ mimeType: 'text/plain', // This always returns a list
80
+ description: 'List available HTTP methods for a specific path. (Note: {path} must be URL-encoded, e.g., /users/{id} becomes users%2F%7Bid%7D)',
81
+ name: 'Path Methods List',
82
+ }, pathItemHandler.handleRequest);
83
+ // 3. openapi://paths/{path}/{method*}
84
+ const operationTemplate = new ResourceTemplate('openapi://paths/{path}/{method*}', {
85
+ list: undefined, // Detail view handled by handler
86
+ complete: {
87
+ path: () => Object.keys(transformedSpec.paths ?? {}).map(encodeUriPathComponent), // Use imported function directly
88
+ method: () => [
89
+ // Provide static list of common methods
90
+ 'GET',
91
+ 'POST',
92
+ 'PUT',
93
+ 'DELETE',
94
+ 'PATCH',
95
+ 'OPTIONS',
96
+ 'HEAD',
97
+ 'TRACE',
98
+ ],
99
+ },
100
+ });
101
+ server.resource('openapi-operation-detail', operationTemplate, {
102
+ mimeType: formatter.getMimeType(), // Detail view uses formatter
103
+ description: 'Get details for one or more specific API operations (methods). (Note: {path} must be URL-encoded, e.g., /users/{id} becomes users%2F%7Bid%7D)',
104
+ name: 'Operation Detail',
105
+ }, operationHandler.handleRequest);
106
+ // 4. openapi://components/{type}
107
+ const componentMapTemplate = new ResourceTemplate('openapi://components/{type}', {
108
+ list: undefined, // List is handled by the handler
109
+ complete: {
110
+ type: () => {
111
+ // Use type guard to ensure spec is V3 before accessing components
112
+ if (isOpenAPIV3(transformedSpec)) {
113
+ return Object.keys(transformedSpec.components ?? {});
114
+ }
115
+ return []; // Return empty array if not V3 (shouldn't happen ideally)
116
+ },
117
+ },
118
+ });
119
+ server.resource('openapi-component-list', componentMapTemplate, {
120
+ mimeType: 'text/plain', // This always returns a list
121
+ description: 'List available components of a specific type (e.g., schemas, parameters).',
122
+ name: 'Component List',
123
+ }, componentMapHandler.handleRequest);
124
+ // 5. openapi://components/{type}/{name*}
125
+ const componentDetailTemplate = new ResourceTemplate('openapi://components/{type}/{name*}', {
126
+ list: undefined, // Detail view handled by handler
127
+ complete: {
128
+ type: () => {
129
+ // Use type guard to ensure spec is V3 before accessing components
130
+ if (isOpenAPIV3(transformedSpec)) {
131
+ return Object.keys(transformedSpec.components ?? {});
132
+ }
133
+ return []; // Return empty array if not V3
134
+ }, // <<< Added missing closing brace
135
+ name: () => {
136
+ // Provide names only if there's exactly one component type defined
137
+ if (isOpenAPIV3(transformedSpec) &&
138
+ transformedSpec.components &&
139
+ Object.keys(transformedSpec.components).length === 1) {
140
+ // Get the single component type key (e.g., 'schemas')
141
+ const componentTypeKey = Object.keys(transformedSpec.components)[0];
142
+ // Use the helper to safely get the map
143
+ try {
144
+ const componentTypeMap = getValidatedComponentMap(transformedSpec, componentTypeKey);
145
+ return Object.keys(componentTypeMap);
146
+ }
147
+ catch (error) {
148
+ // Should not happen if key came from Object.keys, but handle defensively
149
+ console.error(`Error getting component map for key ${componentTypeKey}:`, error);
150
+ return [];
151
+ }
152
+ }
153
+ // Otherwise, return no completions for name
154
+ return [];
155
+ },
156
+ },
157
+ });
158
+ server.resource('openapi-component-detail', componentDetailTemplate, {
159
+ mimeType: formatter.getMimeType(), // Detail view uses formatter
160
+ description: 'Get details for one or more specific components (e.g., schemas, parameters).',
161
+ name: 'Component Detail',
162
+ }, componentDetailHandler.handleRequest);
163
+ // Start server
164
+ const transport = new StdioServerTransport();
165
+ await server.connect(transport);
166
+ }
167
+ catch (error) {
168
+ console.error('Failed to start server:', error instanceof Error ? error.message : String(error));
169
+ process.exit(1);
170
+ }
171
+ }
172
+ // Run the server
173
+ main().catch(error => {
174
+ console.error('Unhandled error:', error instanceof Error ? error.message : String(error));
175
+ process.exit(1);
176
+ });
177
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC,CAAC,0BAA0B;AACjH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,sBAAsB;AACtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC,CAAC,2BAA2B;AAC5F,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC,CAAC,+BAA+B;AACpH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC,CAAC,+BAA+B;AAEvE,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,wDAAwD;QACxD,MAAM,CAAC,EAAE,AAAD,EAAG,QAAQ,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;QAC7C,MAAM,OAAO,GAAG;YACd,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC;gBAC5C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAC3C,CAAC,CAAC,SAAS;SACd,CAAC;QAEF,qBAAqB;QACrB,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAE7C,sBAAsB;QACtB,MAAM,kBAAkB,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC3D,kBAAkB,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,kBAAkB,EAAE,CAAC,CAAC;QAE5E,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAC9E,MAAM,UAAU,CAAC,QAAQ,EAAE,CAAC;QAE5B,2CAA2C;QAC3C,MAAM,IAAI,GAAqB,MAAM,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,sBAAsB;QACjF,kDAAkD;QAClD,MAAM,eAAe,GAAqB,MAAM,UAAU,CAAC,kBAAkB,CAAC;YAC5E,YAAY,EAAE,QAAQ,EAAE,wBAAwB;YAChD,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QACH,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;QACpD,8BAA8B;QAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK;YACjC,CAAC,CAAC,uBAAuB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YAC1C,CAAC,CAAC,iBAAiB,CAAC;QAEtB,sCAAsC;QACtC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,OAAO,EAAE,2BAA2B;SAC9C,CAAC,CAAC;QAEH,oCAAoC;QACpC,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACvD,MAAM,oBAAoB,GAAG,IAAI,oBAAoB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC7E,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACnE,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACrE,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC3E,MAAM,sBAAsB,GAAG,IAAI,sBAAsB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAEjF,yBAAyB;QACzB,uBAAuB;QACvB,MAAM,aAAa,GAAG,IAAI,gBAAgB,CAAC,mBAAmB,EAAE;YAC9D,IAAI,EAAE,SAAS,EAAE,4DAA4D;YAC7E,QAAQ,EAAE;gBACR,KAAK,EAAE,GAAa,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,sBAAsB;aAC5E;SACF,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CACb,eAAe,EAAE,0CAA0C;QAC3D,aAAa,EACb;YACE,qIAAqI;YACrI,WAAW,EACT,qFAAqF;YACvF,IAAI,EAAE,oBAAoB,EAAE,eAAe;SAC5C,EACD,oBAAoB,CAAC,aAAa,CACnC,CAAC;QAEF,4BAA4B;QAC5B,MAAM,YAAY,GAAG,IAAI,gBAAgB,CAAC,wBAAwB,EAAE;YAClE,IAAI,EAAE,SAAS,EAAE,iCAAiC;YAClD,QAAQ,EAAE;gBACR,IAAI,EAAE,GAAa,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,iCAAiC;aAC9H;SACF,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CACb,sBAAsB,EACtB,YAAY,EACZ;YACE,QAAQ,EAAE,YAAY,EAAE,6BAA6B;YACrD,WAAW,EACT,iIAAiI;YACnI,IAAI,EAAE,mBAAmB;SAC1B,EACD,eAAe,CAAC,aAAa,CAC9B,CAAC;QAEF,sCAAsC;QACtC,MAAM,iBAAiB,GAAG,IAAI,gBAAgB,CAAC,kCAAkC,EAAE;YACjF,IAAI,EAAE,SAAS,EAAE,iCAAiC;YAClD,QAAQ,EAAE;gBACR,IAAI,EAAE,GAAa,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,iCAAiC;gBAC7H,MAAM,EAAE,GAAa,EAAE,CAAC;oBACtB,wCAAwC;oBACxC,KAAK;oBACL,MAAM;oBACN,KAAK;oBACL,QAAQ;oBACR,OAAO;oBACP,SAAS;oBACT,MAAM;oBACN,OAAO;iBACR;aACF;SACF,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CACb,0BAA0B,EAC1B,iBAAiB,EACjB;YACE,QAAQ,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,6BAA6B;YAChE,WAAW,EACT,+IAA+I;YACjJ,IAAI,EAAE,kBAAkB;SACzB,EACD,gBAAgB,CAAC,aAAa,CAC/B,CAAC;QAEF,iCAAiC;QACjC,MAAM,oBAAoB,GAAG,IAAI,gBAAgB,CAAC,6BAA6B,EAAE;YAC/E,IAAI,EAAE,SAAS,EAAE,iCAAiC;YAClD,QAAQ,EAAE;gBACR,IAAI,EAAE,GAAa,EAAE;oBACnB,kEAAkE;oBAClE,IAAI,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;wBACjC,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;oBACvD,CAAC;oBACD,OAAO,EAAE,CAAC,CAAC,0DAA0D;gBACvE,CAAC;aACF;SACF,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CACb,wBAAwB,EACxB,oBAAoB,EACpB;YACE,QAAQ,EAAE,YAAY,EAAE,6BAA6B;YACrD,WAAW,EAAE,2EAA2E;YACxF,IAAI,EAAE,gBAAgB;SACvB,EACD,mBAAmB,CAAC,aAAa,CAClC,CAAC;QAEF,yCAAyC;QACzC,MAAM,uBAAuB,GAAG,IAAI,gBAAgB,CAAC,qCAAqC,EAAE;YAC1F,IAAI,EAAE,SAAS,EAAE,iCAAiC;YAClD,QAAQ,EAAE;gBACR,IAAI,EAAE,GAAa,EAAE;oBACnB,kEAAkE;oBAClE,IAAI,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;wBACjC,OAAO,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;oBACvD,CAAC;oBACD,OAAO,EAAE,CAAC,CAAC,+BAA+B;gBAC5C,CAAC,EAAE,kCAAkC;gBACrC,IAAI,EAAE,GAAa,EAAE;oBACnB,mEAAmE;oBACnE,IACE,WAAW,CAAC,eAAe,CAAC;wBAC5B,eAAe,CAAC,UAAU;wBAC1B,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EACpD,CAAC;wBACD,sDAAsD;wBACtD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;wBACpE,uCAAuC;wBACvC,IAAI,CAAC;4BACH,MAAM,gBAAgB,GAAG,wBAAwB,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;4BACrF,OAAO,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;wBACvC,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,yEAAyE;4BACzE,OAAO,CAAC,KAAK,CAAC,uCAAuC,gBAAgB,GAAG,EAAE,KAAK,CAAC,CAAC;4BACjF,OAAO,EAAE,CAAC;wBACZ,CAAC;oBACH,CAAC;oBACD,4CAA4C;oBAC5C,OAAO,EAAE,CAAC;gBACZ,CAAC;aACF;SACF,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CACb,0BAA0B,EAC1B,uBAAuB,EACvB;YACE,QAAQ,EAAE,SAAS,CAAC,WAAW,EAAE,EAAE,6BAA6B;YAChE,WAAW,EAAE,8EAA8E;YAC3F,IAAI,EAAE,kBAAkB;SACzB,EACD,sBAAsB,CAAC,aAAa,CACrC,CAAC;QAEF,eAAe;QACf,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,yBAAyB,EACzB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,iBAAiB;AACjB,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { OpenAPIV3 } from 'openapi-types';
2
+ import { RenderableSpecObject, RenderContext, RenderResultItem } from './types.js';
3
+ export type ComponentType = keyof OpenAPIV3.ComponentsObject;
4
+ export declare const VALID_COMPONENT_TYPES: ComponentType[];
5
+ /**
6
+ * Wraps an OpenAPIV3.ComponentsObject to make it renderable.
7
+ * Handles listing the available component types.
8
+ */
9
+ export declare class RenderableComponents implements RenderableSpecObject {
10
+ private components;
11
+ constructor(components: OpenAPIV3.ComponentsObject | undefined);
12
+ /**
13
+ * Renders a list of available component types found in the spec.
14
+ * Corresponds to the `openapi://components` URI.
15
+ */
16
+ renderList(context: RenderContext): RenderResultItem[];
17
+ /**
18
+ * Detail view for the main 'components' object isn't meaningful.
19
+ */
20
+ renderDetail(context: RenderContext): RenderResultItem[];
21
+ /**
22
+ * Gets the map object for a specific component type.
23
+ * @param type - The component type (e.g., 'schemas').
24
+ * @returns The map (e.g., ComponentsObject['schemas']) or undefined.
25
+ */
26
+ getComponentMap(type: ComponentType): Record<string, OpenAPIV3.SchemaObject | OpenAPIV3.ResponseObject | OpenAPIV3.ParameterObject | OpenAPIV3.ExampleObject | OpenAPIV3.RequestBodyObject | OpenAPIV3.HeaderObject | OpenAPIV3.SecuritySchemeObject | OpenAPIV3.LinkObject | OpenAPIV3.CallbackObject | OpenAPIV3.ReferenceObject> | undefined;
27
+ }
28
+ /**
29
+ * Wraps a map of components of a specific type (e.g., all schemas).
30
+ * Handles listing component names and rendering component details.
31
+ */
32
+ export declare class RenderableComponentMap implements RenderableSpecObject {
33
+ private componentMap;
34
+ private componentType;
35
+ private mapUriSuffix;
36
+ constructor(componentMap: ReturnType<RenderableComponents['getComponentMap']>, componentType: ComponentType, // e.g., 'schemas'
37
+ mapUriSuffix: string);
38
+ /**
39
+ * Renders a list of component names for the specific type.
40
+ * Corresponds to the `openapi://components/{type}` URI.
41
+ */
42
+ renderList(context: RenderContext): RenderResultItem[];
43
+ /**
44
+ * Renders the detail view for one or more specific named components
45
+ * Renders the detail view. For a component map, this usually means listing
46
+ * the component names, similar to renderList. The handler should call
47
+ * `renderComponentDetail` for specific component details.
48
+ */
49
+ renderDetail(context: RenderContext): RenderResultItem[];
50
+ /**
51
+ * Renders the detail view for one or more specific named components
52
+ * within this map.
53
+ * Corresponds to the `openapi://components/{type}/{name*}` URI.
54
+ * This is called by the handler after identifying the name(s).
55
+ *
56
+ * @param _context - The rendering context (might be needed later).
57
+ * @param names - Array of component names.
58
+ * @returns An array of RenderResultItem representing the component details.
59
+ */
60
+ renderComponentDetail(_context: RenderContext, names: string[]): RenderResultItem[];
61
+ /**
62
+ * Gets a specific component object by name.
63
+ * @param name - The name of the component.
64
+ * @returns The component object (or ReferenceObject) or undefined.
65
+ */
66
+ getComponent(name: string): OpenAPIV3.SchemaObject | OpenAPIV3.ResponseObject | OpenAPIV3.ParameterObject | OpenAPIV3.ExampleObject | OpenAPIV3.RequestBodyObject | OpenAPIV3.HeaderObject | OpenAPIV3.SecuritySchemeObject | OpenAPIV3.LinkObject | OpenAPIV3.CallbackObject | OpenAPIV3.ReferenceObject | undefined;
67
+ }
@@ -0,0 +1,177 @@
1
+ import { createErrorResult, generateListHint } from './utils.js'; // Add .js
2
+ export const VALID_COMPONENT_TYPES = [
3
+ 'schemas',
4
+ 'responses',
5
+ 'parameters',
6
+ 'examples',
7
+ 'requestBodies',
8
+ 'headers',
9
+ 'securitySchemes',
10
+ 'links',
11
+ 'callbacks',
12
+ // 'pathItems' is technically allowed but we handle paths separately
13
+ ];
14
+ /**
15
+ * Wraps an OpenAPIV3.ComponentsObject to make it renderable.
16
+ * Handles listing the available component types.
17
+ */
18
+ export class RenderableComponents {
19
+ constructor(components) {
20
+ this.components = components;
21
+ }
22
+ /**
23
+ * Renders a list of available component types found in the spec.
24
+ * Corresponds to the `openapi://components` URI.
25
+ */
26
+ renderList(context) {
27
+ if (!this.components || Object.keys(this.components).length === 0) {
28
+ return createErrorResult('components', 'No components found in the specification.');
29
+ }
30
+ const availableTypes = Object.keys(this.components).filter((key) => VALID_COMPONENT_TYPES.includes(key));
31
+ if (availableTypes.length === 0) {
32
+ return createErrorResult('components', 'No valid component types found.');
33
+ }
34
+ let listText = 'Available Component Types:\n\n';
35
+ availableTypes.sort().forEach(type => {
36
+ listText += `- ${type}\n`;
37
+ });
38
+ // Use the new hint generator structure
39
+ listText += generateListHint(context, { itemType: 'componentType' });
40
+ return [
41
+ {
42
+ uriSuffix: 'components',
43
+ data: listText,
44
+ renderAsList: true,
45
+ },
46
+ ];
47
+ }
48
+ /**
49
+ * Detail view for the main 'components' object isn't meaningful.
50
+ */
51
+ renderDetail(context) {
52
+ return this.renderList(context);
53
+ }
54
+ /**
55
+ * Gets the map object for a specific component type.
56
+ * @param type - The component type (e.g., 'schemas').
57
+ * @returns The map (e.g., ComponentsObject['schemas']) or undefined.
58
+ */
59
+ getComponentMap(type) {
60
+ // Use Map for safe access
61
+ if (!this.components) {
62
+ return undefined;
63
+ }
64
+ const componentsMap = new Map(Object.entries(this.components));
65
+ // Cast needed as Map.get returns the value type or undefined
66
+ return componentsMap.get(type);
67
+ }
68
+ }
69
+ // =====================================================================
70
+ /**
71
+ * Wraps a map of components of a specific type (e.g., all schemas).
72
+ * Handles listing component names and rendering component details.
73
+ */
74
+ export class RenderableComponentMap {
75
+ constructor(componentMap, componentType, // e.g., 'schemas'
76
+ mapUriSuffix // e.g., 'components/schemas'
77
+ ) {
78
+ this.componentMap = componentMap;
79
+ this.componentType = componentType;
80
+ this.mapUriSuffix = mapUriSuffix;
81
+ }
82
+ /**
83
+ * Renders a list of component names for the specific type.
84
+ * Corresponds to the `openapi://components/{type}` URI.
85
+ */
86
+ renderList(context) {
87
+ if (!this.componentMap || Object.keys(this.componentMap).length === 0) {
88
+ return createErrorResult(this.mapUriSuffix, `No components of type "${this.componentType}" found.`);
89
+ }
90
+ const names = Object.keys(this.componentMap).sort();
91
+ let listText = `Available ${this.componentType}:\n\n`;
92
+ names.forEach(name => {
93
+ listText += `- ${name}\n`;
94
+ });
95
+ // Use the new hint generator structure, providing parent type
96
+ listText += generateListHint(context, {
97
+ itemType: 'componentName',
98
+ parentComponentType: this.componentType,
99
+ });
100
+ return [
101
+ {
102
+ uriSuffix: this.mapUriSuffix,
103
+ data: listText,
104
+ renderAsList: true,
105
+ },
106
+ ];
107
+ }
108
+ /**
109
+ * Renders the detail view for one or more specific named components
110
+ * Renders the detail view. For a component map, this usually means listing
111
+ * the component names, similar to renderList. The handler should call
112
+ * `renderComponentDetail` for specific component details.
113
+ */
114
+ renderDetail(context) {
115
+ // Delegate to renderList as the primary view for a component map itself.
116
+ return this.renderList(context);
117
+ }
118
+ /**
119
+ * Renders the detail view for one or more specific named components
120
+ * within this map.
121
+ * Corresponds to the `openapi://components/{type}/{name*}` URI.
122
+ * This is called by the handler after identifying the name(s).
123
+ *
124
+ * @param _context - The rendering context (might be needed later).
125
+ * @param names - Array of component names.
126
+ * @returns An array of RenderResultItem representing the component details.
127
+ */
128
+ renderComponentDetail(_context, names) {
129
+ if (!this.componentMap) {
130
+ // Create error results for all requested names if map is missing
131
+ return names.map(name => ({
132
+ uriSuffix: `${this.mapUriSuffix}/${name}`,
133
+ data: null,
134
+ isError: true,
135
+ errorText: `Component map for type "${this.componentType}" not found.`,
136
+ renderAsList: true,
137
+ }));
138
+ }
139
+ const results = [];
140
+ for (const name of names) {
141
+ const component = this.getComponent(name);
142
+ const componentUriSuffix = `${this.mapUriSuffix}/${name}`;
143
+ if (!component) {
144
+ results.push({
145
+ uriSuffix: componentUriSuffix,
146
+ data: null,
147
+ isError: true,
148
+ errorText: `Component "${name}" of type "${this.componentType}" not found.`,
149
+ renderAsList: true,
150
+ });
151
+ }
152
+ else {
153
+ // Return the raw component object; handler will format it
154
+ results.push({
155
+ uriSuffix: componentUriSuffix,
156
+ data: component,
157
+ });
158
+ }
159
+ }
160
+ return results;
161
+ }
162
+ /**
163
+ * Gets a specific component object by name.
164
+ * @param name - The name of the component.
165
+ * @returns The component object (or ReferenceObject) or undefined.
166
+ */
167
+ getComponent(name) {
168
+ // Use Map for safe access
169
+ if (!this.componentMap) {
170
+ return undefined;
171
+ }
172
+ const detailsMap = new Map(Object.entries(this.componentMap));
173
+ // No cast needed, Map.get returns the correct type (ValueType | undefined)
174
+ return detailsMap.get(name);
175
+ }
176
+ }
177
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/rendering/components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { OpenAPIV3 } from 'openapi-types';
2
+ import { RenderableSpecObject, RenderContext, RenderResultItem } from './types.js';
3
+ /**
4
+ * Wraps an OpenAPIV3.Document to make it renderable.
5
+ * Handles rendering for top-level fields like 'info', 'servers', etc.
6
+ * Delegates list rendering for 'paths' and 'components' to respective objects.
7
+ */
8
+ export declare class RenderableDocument implements RenderableSpecObject {
9
+ private document;
10
+ constructor(document: OpenAPIV3.Document);
11
+ /**
12
+ * Renders a list view. For the document level, this is intended
13
+ * to be called only when the requested field is 'paths' or 'components'.
14
+ * The actual routing/delegation will happen in the handler based on the field.
15
+ */
16
+ renderList(_context: RenderContext): RenderResultItem[];
17
+ /**
18
+ * Renders the detail view. For the document level, this should not be called
19
+ * directly without specifying a field. The handler should call
20
+ * `renderTopLevelFieldDetail` instead.
21
+ */
22
+ renderDetail(_context: RenderContext): RenderResultItem[];
23
+ /**
24
+ * Renders the detail view for a *specific* top-level field (e.g., 'info', 'servers').
25
+ * This is called by the handler after identifying the field.
26
+ *
27
+ * @param context - The rendering context.
28
+ * @param fieldObject - The actual top-level field object to render (e.g., document.info).
29
+ * @param fieldName - The name of the field being rendered (e.g., 'info').
30
+ * @returns An array of RenderResultItem representing the detail view.
31
+ */
32
+ renderTopLevelFieldDetail(context: RenderContext, fieldObject: unknown, fieldName: string): RenderResultItem[];
33
+ getPathsObject(): OpenAPIV3.PathsObject | undefined;
34
+ getComponentsObject(): OpenAPIV3.ComponentsObject | undefined;
35
+ getTopLevelField(fieldName: string): unknown;
36
+ }
@@ -0,0 +1,147 @@
1
+ // No longer need ResourceContents here
2
+ // Placeholder for other renderable objects we'll create
3
+ // import { RenderablePaths } from './paths.js'; // Add .js
4
+ // import { RenderableComponents } from './components.js'; // Add .js
5
+ /**
6
+ * Wraps an OpenAPIV3.Document to make it renderable.
7
+ * Handles rendering for top-level fields like 'info', 'servers', etc.
8
+ * Delegates list rendering for 'paths' and 'components' to respective objects.
9
+ */
10
+ export class RenderableDocument {
11
+ // TODO: Add RenderablePaths and RenderableComponents instances
12
+ // private renderablePaths: RenderablePaths;
13
+ // private renderableComponents: RenderableComponents;
14
+ constructor(document) {
15
+ this.document = document;
16
+ // Initialize renderable wrappers for paths and components here
17
+ // this.renderablePaths = new RenderablePaths(document.paths);
18
+ // this.renderableComponents = new RenderableComponents(document.components);
19
+ }
20
+ /**
21
+ * Renders a list view. For the document level, this is intended
22
+ * to be called only when the requested field is 'paths' or 'components'.
23
+ * The actual routing/delegation will happen in the handler based on the field.
24
+ */
25
+ renderList(_context) {
26
+ // Prefix context with _
27
+ // This method should ideally not be called directly on the document
28
+ // without specifying 'paths' or 'components' as the field.
29
+ // The handler for openapi://{field} will delegate to the appropriate
30
+ // sub-object's renderList.
31
+ // Returning an error result item.
32
+ return [
33
+ {
34
+ uriSuffix: 'error',
35
+ data: null, // No specific data for this error
36
+ isError: true,
37
+ errorText: 'Error: List rendering is only supported for specific fields like "paths" or "components" at the top level.',
38
+ renderAsList: true, // Errors often shown as plain text
39
+ },
40
+ ];
41
+ }
42
+ /**
43
+ * Renders the detail view. For the document level, this should not be called
44
+ * directly without specifying a field. The handler should call
45
+ * `renderTopLevelFieldDetail` instead.
46
+ */
47
+ renderDetail(_context) {
48
+ // Prefix context with _
49
+ // This method implementation fulfills the interface requirement,
50
+ // but direct detail rendering of the whole document isn't meaningful here.
51
+ return [
52
+ {
53
+ uriSuffix: 'error',
54
+ data: null,
55
+ isError: true,
56
+ errorText: 'Error: Detail rendering requires specifying a top-level field (e.g., "info", "servers").',
57
+ renderAsList: true, // Errors often shown as plain text
58
+ },
59
+ ];
60
+ }
61
+ /**
62
+ * Renders the detail view for a *specific* top-level field (e.g., 'info', 'servers').
63
+ * This is called by the handler after identifying the field.
64
+ *
65
+ * @param context - The rendering context.
66
+ * @param fieldObject - The actual top-level field object to render (e.g., document.info).
67
+ * @param fieldName - The name of the field being rendered (e.g., 'info').
68
+ * @returns An array of RenderResultItem representing the detail view.
69
+ */
70
+ renderTopLevelFieldDetail(context, fieldObject, fieldName) {
71
+ // Ensure fieldObject is provided (handler should validate fieldName exists)
72
+ if (fieldObject === undefined || fieldObject === null) {
73
+ return [
74
+ {
75
+ uriSuffix: fieldName,
76
+ data: null,
77
+ isError: true,
78
+ errorText: `Error: Field "${fieldName}" not found in the OpenAPI document.`,
79
+ renderAsList: true,
80
+ },
81
+ ];
82
+ }
83
+ // Avoid rendering structural fields that have dedicated list views
84
+ if (fieldName === 'paths' || fieldName === 'components') {
85
+ return [
86
+ {
87
+ uriSuffix: fieldName,
88
+ data: null,
89
+ isError: true,
90
+ errorText: `Error: Field "${fieldName}" should be accessed via its list view (${context.baseUri}${fieldName}). Use the list view first.`,
91
+ renderAsList: true,
92
+ },
93
+ ];
94
+ }
95
+ try {
96
+ // For successful detail rendering, return the data object itself.
97
+ // The handler will format it using the context.formatter.
98
+ return [
99
+ {
100
+ uriSuffix: fieldName,
101
+ data: fieldObject, // Pass the raw data
102
+ // isError defaults to false
103
+ // renderAsList defaults to false (meaning use detail formatter)
104
+ },
105
+ ];
106
+ }
107
+ catch (error) {
108
+ // Handle potential errors during data access or initial checks
109
+ // Formatting errors will be caught by the handler later
110
+ return [
111
+ {
112
+ uriSuffix: fieldName,
113
+ data: null,
114
+ isError: true,
115
+ errorText: `Error preparing field "${fieldName}" for rendering: ${error instanceof Error ? error.message : String(error)}`,
116
+ renderAsList: true,
117
+ },
118
+ ];
119
+ }
120
+ } // End of renderTopLevelFieldDetail
121
+ // --- Helper methods to access specific parts ---
122
+ getPathsObject() {
123
+ return this.document.paths;
124
+ }
125
+ getComponentsObject() {
126
+ return this.document.components;
127
+ }
128
+ getTopLevelField(fieldName) {
129
+ // Define allowed top-level OpenAPI document properties
130
+ const allowedFields = [
131
+ 'openapi',
132
+ 'info',
133
+ 'servers',
134
+ 'paths',
135
+ 'components',
136
+ 'security',
137
+ 'tags',
138
+ 'externalDocs',
139
+ ];
140
+ // Only allow access to documented OpenAPI properties
141
+ if (allowedFields.includes(fieldName)) {
142
+ return this.document[fieldName];
143
+ }
144
+ return undefined;
145
+ }
146
+ } // End of RenderableDocument class
147
+ //# sourceMappingURL=document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.js","sourceRoot":"","sources":["../../../src/rendering/document.ts"],"names":[],"mappings":"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"}