mcp-openapi-schema-explorer 1.0.1 → 1.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.
- package/.github/workflows/ci.yml +3 -2
- package/CHANGELOG.md +12 -0
- package/README.md +41 -17
- package/dist/src/index.js +17 -8
- package/dist/src/index.js.map +1 -1
- package/dist/src/rendering/components.js +26 -4
- package/dist/src/rendering/components.js.map +1 -1
- package/dist/src/rendering/path-item.js +7 -2
- package/dist/src/rendering/path-item.js.map +1 -1
- package/dist/src/rendering/utils.d.ts +1 -0
- package/dist/src/rendering/utils.js +19 -1
- package/dist/src/rendering/utils.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
- package/src/index.ts +20 -9
- package/src/rendering/components.ts +27 -4
- package/src/rendering/path-item.ts +8 -2
- package/src/rendering/utils.ts +27 -1
- package/src/version.ts +1 -1
- package/test/__tests__/unit/rendering/components.test.ts +19 -8
- package/test/__tests__/unit/rendering/path-item.test.ts +2 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -94,7 +94,8 @@ jobs:
|
|
|
94
94
|
steps:
|
|
95
95
|
- name: Checkout
|
|
96
96
|
uses: actions/checkout@v4
|
|
97
|
-
|
|
97
|
+
with:
|
|
98
|
+
persist-credentials: false
|
|
98
99
|
- name: Setup Node.js
|
|
99
100
|
uses: actions/setup-node@v4
|
|
100
101
|
with:
|
|
@@ -107,5 +108,5 @@ jobs:
|
|
|
107
108
|
- name: Semantic Release
|
|
108
109
|
uses: cycjimmy/semantic-release-action@v4
|
|
109
110
|
env:
|
|
110
|
-
GITHUB_TOKEN: ${{ secrets.
|
|
111
|
+
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
111
112
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [1.1.0](https://github.com/kadykov/mcp-openapi-schema-explorer/compare/v1.0.2...v1.1.0) (2025-04-13)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- enhance component and path item rendering with descriptions and examples in hints ([6989159](https://github.com/kadykov/mcp-openapi-schema-explorer/commit/698915972338b4a16419c9cea3e2377b7701f50b))
|
|
6
|
+
|
|
7
|
+
## [1.0.2](https://github.com/kadykov/mcp-openapi-schema-explorer/compare/v1.0.1...v1.0.2) (2025-04-13)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- update CI workflow to use RELEASE_TOKEN and disable credential persistence ([e7b18f9](https://github.com/kadykov/mcp-openapi-schema-explorer/commit/e7b18f9055b95f0e2c6e2a356cb87482db6205da))
|
|
12
|
+
|
|
1
13
|
## [1.0.1](https://github.com/kadykov/mcp-openapi-schema-explorer/compare/v1.0.0...v1.0.1) (2025-04-12)
|
|
2
14
|
|
|
3
15
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -33,26 +33,34 @@ This server is designed to be run by MCP clients. The recommended way to configu
|
|
|
33
33
|
{
|
|
34
34
|
"mcpServers": {
|
|
35
35
|
"My API Spec": {
|
|
36
|
-
// Choose a descriptive name for this server instance
|
|
37
36
|
"command": "npx",
|
|
38
37
|
"args": [
|
|
39
|
-
"-y",
|
|
38
|
+
"-y",
|
|
40
39
|
"mcp-openapi-schema-explorer",
|
|
41
|
-
"/path/to/your/local/openapi.json"
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
"/path/to/your/local/openapi.json",
|
|
41
|
+
"--output-format",
|
|
42
|
+
"yaml"
|
|
44
43
|
],
|
|
45
|
-
"env": {}
|
|
44
|
+
"env": {}
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
```
|
|
50
49
|
|
|
50
|
+
**Configuration Details:**
|
|
51
|
+
|
|
52
|
+
- **`"My API Spec"`:** Choose a descriptive name for this server instance. This is how you'll identify it within your MCP client.
|
|
53
|
+
- **`command`:** Use `"npx"` to run the package directly.
|
|
54
|
+
- **`args`:**
|
|
55
|
+
- `"-y"`: Auto-confirms the `npx` installation prompt if needed the first time.
|
|
56
|
+
- `"mcp-openapi-schema-explorer"`: The name of the package to execute.
|
|
57
|
+
- `"/path/to/your/local/openapi.json"`: **Required.** The absolute path to your local spec file or the full URL to a remote spec (e.g., `"https://remote/url/spec.json"`).
|
|
58
|
+
- `"--output-format", "yaml"`: **Optional.** Specifies the output format for detailed resource views. Defaults to `"json"`. Other options are `"yaml"` and `"json-minified"`.
|
|
59
|
+
- **`env`:** Currently, no environment variables are needed for this server.
|
|
60
|
+
|
|
51
61
|
**Notes:**
|
|
52
62
|
|
|
53
|
-
-
|
|
54
|
-
- The server name (`"My API Spec"` in the example) is how you'll identify this specific server instance within your MCP client.
|
|
55
|
-
- This server handles one specification per instance. To explore multiple specifications simultaneously, configure multiple entries under `mcpServers` in your client's configuration file, each pointing to a different spec file or URL.
|
|
63
|
+
- This server handles one specification per instance. To explore multiple specifications simultaneously, configure multiple entries under `mcpServers` in your client's configuration file, each pointing to a different spec file or URL and using a unique server name.
|
|
56
64
|
|
|
57
65
|
## Alternative: Global Installation
|
|
58
66
|
|
|
@@ -79,40 +87,56 @@ If installed globally, your MCP client configuration would change:
|
|
|
79
87
|
|
|
80
88
|
## Available MCP Resources
|
|
81
89
|
|
|
82
|
-
This server exposes the following MCP resource templates for exploring the OpenAPI specification
|
|
90
|
+
This server exposes the following MCP resource templates for exploring the OpenAPI specification.
|
|
91
|
+
|
|
92
|
+
**Understanding Multi-Value Parameters (`*`)**
|
|
93
|
+
|
|
94
|
+
Some resource templates include parameters ending with an asterisk (`*`), like `{method*}` or `{name*}`. This indicates that the parameter accepts **multiple comma-separated values**. For example, to request details for both the `GET` and `POST` methods of a path, you would use a URI like `openapi://paths/users/get,post`. This allows fetching details for multiple items in a single request.
|
|
95
|
+
|
|
96
|
+
**Resource Templates:**
|
|
83
97
|
|
|
84
98
|
- **`openapi://{field}`**
|
|
85
99
|
|
|
86
|
-
- **Description:** Accesses top-level fields of the OpenAPI document (`info`, `servers`, `tags
|
|
87
|
-
- **
|
|
100
|
+
- **Description:** Accesses top-level fields of the OpenAPI document (e.g., `info`, `servers`, `tags`) or lists the contents of `paths` or `components`. The specific available fields depend on the loaded specification.
|
|
101
|
+
- **Example:** `openapi://info`
|
|
88
102
|
- **Output:** `text/plain` list for `paths` and `components`; configured format (JSON/YAML/minified JSON) for other fields.
|
|
103
|
+
- **Completions:** Provides dynamic suggestions for `{field}` based on the actual top-level keys found in the loaded spec.
|
|
89
104
|
|
|
90
105
|
- **`openapi://paths/{path}`**
|
|
91
106
|
|
|
92
107
|
- **Description:** Lists the available HTTP methods (operations) for a specific API path.
|
|
93
108
|
- **Parameter:** `{path}` - The API path string. **Must be URL-encoded** (e.g., `/users/{id}` becomes `users%2F%7Bid%7D`).
|
|
109
|
+
- **Example:** `openapi://paths/users%2F%7Bid%7D`
|
|
94
110
|
- **Output:** `text/plain` list of methods.
|
|
111
|
+
- **Completions:** Provides dynamic suggestions for `{path}` based on the paths found in the loaded spec (URL-encoded).
|
|
95
112
|
|
|
96
113
|
- **`openapi://paths/{path}/{method*}`**
|
|
97
114
|
|
|
98
115
|
- **Description:** Gets the detailed specification for one or more operations (HTTP methods) on a specific API path.
|
|
99
116
|
- **Parameters:**
|
|
100
117
|
- `{path}` - The API path string. **Must be URL-encoded**.
|
|
101
|
-
- `{method*}` - One or more HTTP methods (e.g., `
|
|
118
|
+
- `{method*}` - One or more HTTP methods (e.g., `get`, `post`, `get,post`). Case-insensitive.
|
|
119
|
+
- **Example (Single):** `openapi://paths/users%2F%7Bid%7D/get`
|
|
120
|
+
- **Example (Multiple):** `openapi://paths/users%2F%7Bid%7D/get,post`
|
|
102
121
|
- **Output:** Configured format (JSON/YAML/minified JSON).
|
|
122
|
+
- **Completions:** Provides dynamic suggestions for `{path}`. Provides static suggestions for `{method*}` (common HTTP verbs like GET, POST, PUT, DELETE, etc.).
|
|
103
123
|
|
|
104
124
|
- **`openapi://components/{type}`**
|
|
105
125
|
|
|
106
|
-
- **Description:** Lists the names of all defined components of a specific type.
|
|
107
|
-
- **
|
|
108
|
-
- **Output:** `text/plain` list of component names.
|
|
126
|
+
- **Description:** Lists the names of all defined components of a specific type (e.g., `schemas`, `responses`, `parameters`). The specific available types depend on the loaded specification. Also provides a short description for each listed type.
|
|
127
|
+
- **Example:** `openapi://components/schemas`
|
|
128
|
+
- **Output:** `text/plain` list of component names with descriptions.
|
|
129
|
+
- **Completions:** Provides dynamic suggestions for `{type}` based on the component types found in the loaded spec.
|
|
109
130
|
|
|
110
131
|
- **`openapi://components/{type}/{name*}`**
|
|
111
132
|
- **Description:** Gets the detailed specification for one or more named components of a specific type.
|
|
112
133
|
- **Parameters:**
|
|
113
134
|
- `{type}` - The component type.
|
|
114
|
-
- `{name*}` - One or more component names
|
|
135
|
+
- `{name*}` - One or more component names (e.g., `User`, `Order`, `User,Order`). Case-sensitive.
|
|
136
|
+
- **Example (Single):** `openapi://components/schemas/User`
|
|
137
|
+
- **Example (Multiple):** `openapi://components/schemas/User,Order`
|
|
115
138
|
- **Output:** Configured format (JSON/YAML/minified JSON).
|
|
139
|
+
- **Completions:** Provides dynamic suggestions for `{type}`. Provides dynamic suggestions for `{name*}` _only if_ the loaded spec contains exactly one component type overall (e.g., only `schemas`). This limitation exists because the MCP SDK currently doesn't support providing completions scoped to the selected `{type}`; providing all names across all types could be misleading.
|
|
116
140
|
|
|
117
141
|
## Contributing
|
|
118
142
|
|
package/dist/src/index.js
CHANGED
|
@@ -54,7 +54,16 @@ async function main() {
|
|
|
54
54
|
const operationHandler = new OperationHandler(specLoader, formatter);
|
|
55
55
|
const componentMapHandler = new ComponentMapHandler(specLoader, formatter);
|
|
56
56
|
const componentDetailHandler = new ComponentDetailHandler(specLoader, formatter);
|
|
57
|
-
// Register
|
|
57
|
+
// --- Define Resource Templates and Register Handlers ---
|
|
58
|
+
// Helper to get dynamic field list for descriptions
|
|
59
|
+
const getFieldList = () => Object.keys(transformedSpec).join(', ');
|
|
60
|
+
// Helper to get dynamic component type list for descriptions
|
|
61
|
+
const getComponentTypeList = () => {
|
|
62
|
+
if (isOpenAPIV3(transformedSpec) && transformedSpec.components) {
|
|
63
|
+
return Object.keys(transformedSpec.components).join(', ');
|
|
64
|
+
}
|
|
65
|
+
return ''; // Return empty if no components or not V3
|
|
66
|
+
};
|
|
58
67
|
// 1. openapi://{field}
|
|
59
68
|
const fieldTemplate = new ResourceTemplate('openapi://{field}', {
|
|
60
69
|
list: undefined, // List is handled by the handler logic based on field value
|
|
@@ -64,8 +73,8 @@ async function main() {
|
|
|
64
73
|
});
|
|
65
74
|
server.resource('openapi-field', // Unique ID for the resource registration
|
|
66
75
|
fieldTemplate, {
|
|
67
|
-
// MimeType varies (text/plain for lists, JSON/YAML for details)
|
|
68
|
-
description:
|
|
76
|
+
// MimeType varies (text/plain for lists, JSON/YAML for details)
|
|
77
|
+
description: `Access top-level fields like ${getFieldList()}. (e.g., openapi://info)`,
|
|
69
78
|
name: 'OpenAPI Field/List', // Generic name
|
|
70
79
|
}, topLevelFieldHandler.handleRequest);
|
|
71
80
|
// 2. openapi://paths/{path}
|
|
@@ -77,7 +86,7 @@ async function main() {
|
|
|
77
86
|
});
|
|
78
87
|
server.resource('openapi-path-methods', pathTemplate, {
|
|
79
88
|
mimeType: 'text/plain', // This always returns a list
|
|
80
|
-
description: 'List
|
|
89
|
+
description: 'List methods for a specific path (URL encode paths with slashes). (e.g., openapi://paths/users%2F%7Bid%7D)',
|
|
81
90
|
name: 'Path Methods List',
|
|
82
91
|
}, pathItemHandler.handleRequest);
|
|
83
92
|
// 3. openapi://paths/{path}/{method*}
|
|
@@ -100,7 +109,7 @@ async function main() {
|
|
|
100
109
|
});
|
|
101
110
|
server.resource('openapi-operation-detail', operationTemplate, {
|
|
102
111
|
mimeType: formatter.getMimeType(), // Detail view uses formatter
|
|
103
|
-
description: 'Get details for one or more
|
|
112
|
+
description: 'Get details for one or more operations (comma-separated). (e.g., openapi://paths/users%2F%7Bid%7D/get,post)',
|
|
104
113
|
name: 'Operation Detail',
|
|
105
114
|
}, operationHandler.handleRequest);
|
|
106
115
|
// 4. openapi://components/{type}
|
|
@@ -118,7 +127,7 @@ async function main() {
|
|
|
118
127
|
});
|
|
119
128
|
server.resource('openapi-component-list', componentMapTemplate, {
|
|
120
129
|
mimeType: 'text/plain', // This always returns a list
|
|
121
|
-
description:
|
|
130
|
+
description: `List components of a specific type like ${getComponentTypeList()}. (e.g., openapi://components/schemas)`,
|
|
122
131
|
name: 'Component List',
|
|
123
132
|
}, componentMapHandler.handleRequest);
|
|
124
133
|
// 5. openapi://components/{type}/{name*}
|
|
@@ -131,7 +140,7 @@ async function main() {
|
|
|
131
140
|
return Object.keys(transformedSpec.components ?? {});
|
|
132
141
|
}
|
|
133
142
|
return []; // Return empty array if not V3
|
|
134
|
-
},
|
|
143
|
+
},
|
|
135
144
|
name: () => {
|
|
136
145
|
// Provide names only if there's exactly one component type defined
|
|
137
146
|
if (isOpenAPIV3(transformedSpec) &&
|
|
@@ -157,7 +166,7 @@ async function main() {
|
|
|
157
166
|
});
|
|
158
167
|
server.resource('openapi-component-detail', componentDetailTemplate, {
|
|
159
168
|
mimeType: formatter.getMimeType(), // Detail view uses formatter
|
|
160
|
-
description: 'Get details for one or more
|
|
169
|
+
description: 'Get details for one or more components (comma-separated). (e.g., openapi://components/schemas/User,Task)',
|
|
161
170
|
name: 'Component Detail',
|
|
162
171
|
}, componentDetailHandler.handleRequest);
|
|
163
172
|
// Start server
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,21 @@ export const VALID_COMPONENT_TYPES = [
|
|
|
11
11
|
'callbacks',
|
|
12
12
|
// 'pathItems' is technically allowed but we handle paths separately
|
|
13
13
|
];
|
|
14
|
+
// Simple descriptions for component types
|
|
15
|
+
const componentTypeDescriptions = {
|
|
16
|
+
schemas: 'Reusable data structures (models)',
|
|
17
|
+
responses: 'Reusable API responses',
|
|
18
|
+
parameters: 'Reusable request parameters (query, path, header, cookie)',
|
|
19
|
+
examples: 'Reusable examples of media type payloads',
|
|
20
|
+
requestBodies: 'Reusable request body definitions',
|
|
21
|
+
headers: 'Reusable header definitions for responses',
|
|
22
|
+
securitySchemes: 'Reusable security scheme definitions (e.g., API keys, OAuth2)',
|
|
23
|
+
links: 'Reusable descriptions of links between responses and operations',
|
|
24
|
+
callbacks: 'Reusable descriptions of callback operations',
|
|
25
|
+
// pathItems: 'Reusable path item definitions (rarely used directly here)' // Excluded as per comment above
|
|
26
|
+
};
|
|
27
|
+
// Use a Map for safer lookups against prototype pollution
|
|
28
|
+
const componentDescriptionsMap = new Map(Object.entries(componentTypeDescriptions));
|
|
14
29
|
/**
|
|
15
30
|
* Wraps an OpenAPIV3.ComponentsObject to make it renderable.
|
|
16
31
|
* Handles listing the available component types.
|
|
@@ -33,10 +48,15 @@ export class RenderableComponents {
|
|
|
33
48
|
}
|
|
34
49
|
let listText = 'Available Component Types:\n\n';
|
|
35
50
|
availableTypes.sort().forEach(type => {
|
|
36
|
-
|
|
51
|
+
const description = componentDescriptionsMap.get(type) ?? 'Unknown component type'; // Removed unnecessary 'as ComponentType'
|
|
52
|
+
listText += `- ${type}: ${description}\n`;
|
|
53
|
+
});
|
|
54
|
+
// Use the new hint generator structure, providing the first type as an example
|
|
55
|
+
const firstTypeExample = availableTypes.length > 0 ? availableTypes[0] : undefined;
|
|
56
|
+
listText += generateListHint(context, {
|
|
57
|
+
itemType: 'componentType',
|
|
58
|
+
firstItemExample: firstTypeExample,
|
|
37
59
|
});
|
|
38
|
-
// Use the new hint generator structure
|
|
39
|
-
listText += generateListHint(context, { itemType: 'componentType' });
|
|
40
60
|
return [
|
|
41
61
|
{
|
|
42
62
|
uriSuffix: 'components',
|
|
@@ -92,10 +112,12 @@ export class RenderableComponentMap {
|
|
|
92
112
|
names.forEach(name => {
|
|
93
113
|
listText += `- ${name}\n`;
|
|
94
114
|
});
|
|
95
|
-
// Use the new hint generator structure, providing parent type
|
|
115
|
+
// Use the new hint generator structure, providing parent type and first name as example
|
|
116
|
+
const firstNameExample = names.length > 0 ? names[0] : undefined;
|
|
96
117
|
listText += generateListHint(context, {
|
|
97
118
|
itemType: 'componentName',
|
|
98
119
|
parentComponentType: this.componentType,
|
|
120
|
+
firstItemExample: firstNameExample,
|
|
99
121
|
});
|
|
100
122
|
return [
|
|
101
123
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/rendering/components.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC,CAAC,UAAU;AAI5E,MAAM,CAAC,MAAM,qBAAqB,GAAoB;IACpD,SAAS;IACT,WAAW;IACX,YAAY;IACZ,UAAU;IACV,eAAe;IACf,SAAS;IACT,iBAAiB;IACjB,OAAO;IACP,WAAW;IACX,oEAAoE;CACrE,CAAC;AAEF;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAC/B,YAAoB,UAAkD;QAAlD,eAAU,GAAV,UAAU,CAAwC;IAAG,CAAC;IAE1E;;;OAGG;IACH,UAAU,CAAC,OAAsB;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClE,OAAO,iBAAiB,CAAC,YAAY,EAAE,2CAA2C,CAAC,CAAC;QACtF,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAwB,EAAE,CACvF,qBAAqB,CAAC,QAAQ,CAAC,GAAoB,CAAC,CACrD,CAAC;QAEF,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,iBAAiB,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,QAAQ,GAAG,gCAAgC,CAAC;QAChD,cAAc,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YACnC,QAAQ,IAAI,KAAK,IAAI,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/rendering/components.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,14 +36,19 @@ export class RenderablePathItem {
|
|
|
36
36
|
},
|
|
37
37
|
];
|
|
38
38
|
}
|
|
39
|
-
//
|
|
39
|
+
// Sort methods first to get the correct example
|
|
40
|
+
methods.sort();
|
|
41
|
+
const firstMethodExample = methods.length > 0 ? methods[0] : undefined;
|
|
42
|
+
// Generate hint using the new structure, providing the first *sorted* method as an example
|
|
40
43
|
const hint = generateListHint(context, {
|
|
41
44
|
itemType: 'pathMethod',
|
|
42
45
|
parentPath: this.path, // Use the stored raw path
|
|
46
|
+
firstItemExample: firstMethodExample,
|
|
43
47
|
});
|
|
44
48
|
// Hint includes leading newline, so start output with it directly
|
|
45
49
|
let outputLines = [hint.trim(), '']; // Trim leading newline from hint for first line
|
|
46
|
-
|
|
50
|
+
// Iterate over the already sorted methods
|
|
51
|
+
methods.forEach(method => {
|
|
47
52
|
const operation = this.getOperation(method);
|
|
48
53
|
// Use summary or operationId (via getOperationSummary)
|
|
49
54
|
const summaryText = getOperationSummary(operation);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"path-item.js","sourceRoot":"","sources":["../../../src/rendering/path-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC,CAAC,UAAU;AAEjG;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAC7B,YACU,QAA8C,EAC9C,IAAY,EAAE,uDAAuD;IACrE,aAAqB,CAAC,2EAA2E;;QAFjG,aAAQ,GAAR,QAAQ,CAAsC;QAC9C,SAAI,GAAJ,IAAI,CAAQ;QACZ,kBAAa,GAAb,aAAa,CAAQ;IAC5B,CAAC;IAEJ;;;OAGG;IACH,UAAU,CAAC,OAAsB;QAC/B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,iBAAiB,CAAC,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,CAAC;QACvE,CAAC;QAED,iEAAiE;QACjE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACtD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAA2B,CAAC,CAC/D,CAAC;QAE7B,oDAAoD;QACpD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,uEAAuE;YACvE,OAAO;gBACL;oBACE,SAAS,EAAE,IAAI,CAAC,aAAa;oBAC7B,IAAI,EAAE,4CAA4C,kBAAkB,CAClE,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,gCAAgC;qBAC/E,EAAE;oBACH,YAAY,EAAE,IAAI;oBAClB,mCAAmC;iBACpC;aACF,CAAC;QACJ,CAAC;QAED,
|
|
1
|
+
{"version":3,"file":"path-item.js","sourceRoot":"","sources":["../../../src/rendering/path-item.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { RenderContext, RenderResultItem } from './types.js';
|
|
|
3
3
|
type ListItemType = 'componentType' | 'componentName' | 'pathMethod';
|
|
4
4
|
interface HintContext {
|
|
5
5
|
itemType: ListItemType;
|
|
6
|
+
firstItemExample?: string;
|
|
6
7
|
parentComponentType?: string;
|
|
7
8
|
parentPath?: string;
|
|
8
9
|
}
|
|
@@ -21,12 +21,16 @@ export function getOperationSummary(operation) {
|
|
|
21
21
|
export function generateListHint(renderContext, hintContext) {
|
|
22
22
|
let detailUriSuffixPattern;
|
|
23
23
|
let itemTypeName; // User-friendly name for the item type in the hint text
|
|
24
|
+
let exampleUriSuffix; // To hold the generated example URI
|
|
24
25
|
switch (hintContext.itemType) {
|
|
25
26
|
case 'componentType':
|
|
26
27
|
// Listing component types (e.g., schemas, responses) at openapi://components
|
|
27
28
|
// Hint should point to openapi://components/{type}
|
|
28
29
|
detailUriSuffixPattern = buildComponentMapUriSuffix('{type}'); // Use placeholder
|
|
29
30
|
itemTypeName = 'component type';
|
|
31
|
+
if (hintContext.firstItemExample) {
|
|
32
|
+
exampleUriSuffix = buildComponentMapUriSuffix(hintContext.firstItemExample);
|
|
33
|
+
}
|
|
30
34
|
break;
|
|
31
35
|
case 'componentName':
|
|
32
36
|
// Listing component names (e.g., MySchema, User) at openapi://components/{type}
|
|
@@ -38,6 +42,9 @@ export function generateListHint(renderContext, hintContext) {
|
|
|
38
42
|
// Use the actual parent type and a placeholder for the name
|
|
39
43
|
detailUriSuffixPattern = buildComponentDetailUriSuffix(hintContext.parentComponentType, '{name}');
|
|
40
44
|
itemTypeName = hintContext.parentComponentType.slice(0, -1); // e.g., 'schema' from 'schemas'
|
|
45
|
+
if (hintContext.firstItemExample) {
|
|
46
|
+
exampleUriSuffix = buildComponentDetailUriSuffix(hintContext.parentComponentType, hintContext.firstItemExample);
|
|
47
|
+
}
|
|
41
48
|
break;
|
|
42
49
|
case 'pathMethod':
|
|
43
50
|
// Listing methods (e.g., get, post) at openapi://paths/{path}
|
|
@@ -49,6 +56,10 @@ export function generateListHint(renderContext, hintContext) {
|
|
|
49
56
|
// Use the actual parent path and a placeholder for the method
|
|
50
57
|
detailUriSuffixPattern = buildOperationUriSuffix(hintContext.parentPath, '{method}');
|
|
51
58
|
itemTypeName = 'operation'; // Or 'method'? 'operation' seems clearer
|
|
59
|
+
if (hintContext.firstItemExample) {
|
|
60
|
+
// Ensure the example method is valid if needed, though usually it's just 'get', 'post' etc.
|
|
61
|
+
exampleUriSuffix = buildOperationUriSuffix(hintContext.parentPath, hintContext.firstItemExample);
|
|
62
|
+
}
|
|
52
63
|
break;
|
|
53
64
|
default:
|
|
54
65
|
// Explicitly cast to string to avoid potential 'never' type issue in template literal
|
|
@@ -57,7 +68,14 @@ export function generateListHint(renderContext, hintContext) {
|
|
|
57
68
|
}
|
|
58
69
|
// Construct the full hint URI pattern using the base URI
|
|
59
70
|
const fullHintPattern = `${renderContext.baseUri}${detailUriSuffixPattern}`;
|
|
60
|
-
|
|
71
|
+
const fullExampleUri = exampleUriSuffix
|
|
72
|
+
? `${renderContext.baseUri}${exampleUriSuffix}`
|
|
73
|
+
: undefined;
|
|
74
|
+
let hintText = `\nHint: Use '${fullHintPattern}' to view details for a specific ${itemTypeName}.`;
|
|
75
|
+
if (fullExampleUri) {
|
|
76
|
+
hintText += ` (e.g., ${fullExampleUri})`;
|
|
77
|
+
}
|
|
78
|
+
return hintText;
|
|
61
79
|
}
|
|
62
80
|
/**
|
|
63
81
|
* Helper to generate a standard error item for RenderResultItem arrays.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/rendering/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB;AACvB,oEAAoE;EACrE,MAAM,yBAAyB,CAAC,CAAC,sBAAsB;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/rendering/utils.ts"],"names":[],"mappings":"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"}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.0
|
|
1
|
+
export declare const VERSION = "1.1.0";
|
package/dist/src/version.js
CHANGED
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -64,7 +64,18 @@ async function main(): Promise<void> {
|
|
|
64
64
|
const componentMapHandler = new ComponentMapHandler(specLoader, formatter);
|
|
65
65
|
const componentDetailHandler = new ComponentDetailHandler(specLoader, formatter);
|
|
66
66
|
|
|
67
|
-
// Register
|
|
67
|
+
// --- Define Resource Templates and Register Handlers ---
|
|
68
|
+
|
|
69
|
+
// Helper to get dynamic field list for descriptions
|
|
70
|
+
const getFieldList = (): string => Object.keys(transformedSpec).join(', ');
|
|
71
|
+
// Helper to get dynamic component type list for descriptions
|
|
72
|
+
const getComponentTypeList = (): string => {
|
|
73
|
+
if (isOpenAPIV3(transformedSpec) && transformedSpec.components) {
|
|
74
|
+
return Object.keys(transformedSpec.components).join(', ');
|
|
75
|
+
}
|
|
76
|
+
return ''; // Return empty if no components or not V3
|
|
77
|
+
};
|
|
78
|
+
|
|
68
79
|
// 1. openapi://{field}
|
|
69
80
|
const fieldTemplate = new ResourceTemplate('openapi://{field}', {
|
|
70
81
|
list: undefined, // List is handled by the handler logic based on field value
|
|
@@ -76,9 +87,8 @@ async function main(): Promise<void> {
|
|
|
76
87
|
'openapi-field', // Unique ID for the resource registration
|
|
77
88
|
fieldTemplate,
|
|
78
89
|
{
|
|
79
|
-
// MimeType varies (text/plain for lists, JSON/YAML for details)
|
|
80
|
-
description:
|
|
81
|
-
'Access top-level fields (info, servers, tags), list paths, or list component types.',
|
|
90
|
+
// MimeType varies (text/plain for lists, JSON/YAML for details)
|
|
91
|
+
description: `Access top-level fields like ${getFieldList()}. (e.g., openapi://info)`,
|
|
82
92
|
name: 'OpenAPI Field/List', // Generic name
|
|
83
93
|
},
|
|
84
94
|
topLevelFieldHandler.handleRequest
|
|
@@ -97,7 +107,7 @@ async function main(): Promise<void> {
|
|
|
97
107
|
{
|
|
98
108
|
mimeType: 'text/plain', // This always returns a list
|
|
99
109
|
description:
|
|
100
|
-
'List
|
|
110
|
+
'List methods for a specific path (URL encode paths with slashes). (e.g., openapi://paths/users%2F%7Bid%7D)',
|
|
101
111
|
name: 'Path Methods List',
|
|
102
112
|
},
|
|
103
113
|
pathItemHandler.handleRequest
|
|
@@ -127,7 +137,7 @@ async function main(): Promise<void> {
|
|
|
127
137
|
{
|
|
128
138
|
mimeType: formatter.getMimeType(), // Detail view uses formatter
|
|
129
139
|
description:
|
|
130
|
-
'Get details for one or more
|
|
140
|
+
'Get details for one or more operations (comma-separated). (e.g., openapi://paths/users%2F%7Bid%7D/get,post)',
|
|
131
141
|
name: 'Operation Detail',
|
|
132
142
|
},
|
|
133
143
|
operationHandler.handleRequest
|
|
@@ -151,7 +161,7 @@ async function main(): Promise<void> {
|
|
|
151
161
|
componentMapTemplate,
|
|
152
162
|
{
|
|
153
163
|
mimeType: 'text/plain', // This always returns a list
|
|
154
|
-
description:
|
|
164
|
+
description: `List components of a specific type like ${getComponentTypeList()}. (e.g., openapi://components/schemas)`,
|
|
155
165
|
name: 'Component List',
|
|
156
166
|
},
|
|
157
167
|
componentMapHandler.handleRequest
|
|
@@ -167,7 +177,7 @@ async function main(): Promise<void> {
|
|
|
167
177
|
return Object.keys(transformedSpec.components ?? {});
|
|
168
178
|
}
|
|
169
179
|
return []; // Return empty array if not V3
|
|
170
|
-
},
|
|
180
|
+
},
|
|
171
181
|
name: (): string[] => {
|
|
172
182
|
// Provide names only if there's exactly one component type defined
|
|
173
183
|
if (
|
|
@@ -197,7 +207,8 @@ async function main(): Promise<void> {
|
|
|
197
207
|
componentDetailTemplate,
|
|
198
208
|
{
|
|
199
209
|
mimeType: formatter.getMimeType(), // Detail view uses formatter
|
|
200
|
-
description:
|
|
210
|
+
description:
|
|
211
|
+
'Get details for one or more components (comma-separated). (e.g., openapi://components/schemas/User,Task)',
|
|
201
212
|
name: 'Component Detail',
|
|
202
213
|
},
|
|
203
214
|
componentDetailHandler.handleRequest
|
|
@@ -17,6 +17,22 @@ export const VALID_COMPONENT_TYPES: ComponentType[] = [
|
|
|
17
17
|
// 'pathItems' is technically allowed but we handle paths separately
|
|
18
18
|
];
|
|
19
19
|
|
|
20
|
+
// Simple descriptions for component types
|
|
21
|
+
const componentTypeDescriptions: Record<ComponentType, string> = {
|
|
22
|
+
schemas: 'Reusable data structures (models)',
|
|
23
|
+
responses: 'Reusable API responses',
|
|
24
|
+
parameters: 'Reusable request parameters (query, path, header, cookie)',
|
|
25
|
+
examples: 'Reusable examples of media type payloads',
|
|
26
|
+
requestBodies: 'Reusable request body definitions',
|
|
27
|
+
headers: 'Reusable header definitions for responses',
|
|
28
|
+
securitySchemes: 'Reusable security scheme definitions (e.g., API keys, OAuth2)',
|
|
29
|
+
links: 'Reusable descriptions of links between responses and operations',
|
|
30
|
+
callbacks: 'Reusable descriptions of callback operations',
|
|
31
|
+
// pathItems: 'Reusable path item definitions (rarely used directly here)' // Excluded as per comment above
|
|
32
|
+
};
|
|
33
|
+
// Use a Map for safer lookups against prototype pollution
|
|
34
|
+
const componentDescriptionsMap = new Map(Object.entries(componentTypeDescriptions));
|
|
35
|
+
|
|
20
36
|
/**
|
|
21
37
|
* Wraps an OpenAPIV3.ComponentsObject to make it renderable.
|
|
22
38
|
* Handles listing the available component types.
|
|
@@ -43,11 +59,16 @@ export class RenderableComponents implements RenderableSpecObject {
|
|
|
43
59
|
|
|
44
60
|
let listText = 'Available Component Types:\n\n';
|
|
45
61
|
availableTypes.sort().forEach(type => {
|
|
46
|
-
|
|
62
|
+
const description = componentDescriptionsMap.get(type) ?? 'Unknown component type'; // Removed unnecessary 'as ComponentType'
|
|
63
|
+
listText += `- ${type}: ${description}\n`;
|
|
47
64
|
});
|
|
48
65
|
|
|
49
|
-
// Use the new hint generator structure
|
|
50
|
-
|
|
66
|
+
// Use the new hint generator structure, providing the first type as an example
|
|
67
|
+
const firstTypeExample = availableTypes.length > 0 ? availableTypes[0] : undefined;
|
|
68
|
+
listText += generateListHint(context, {
|
|
69
|
+
itemType: 'componentType',
|
|
70
|
+
firstItemExample: firstTypeExample,
|
|
71
|
+
});
|
|
51
72
|
|
|
52
73
|
return [
|
|
53
74
|
{
|
|
@@ -126,10 +147,12 @@ export class RenderableComponentMap implements RenderableSpecObject {
|
|
|
126
147
|
listText += `- ${name}\n`;
|
|
127
148
|
});
|
|
128
149
|
|
|
129
|
-
// Use the new hint generator structure, providing parent type
|
|
150
|
+
// Use the new hint generator structure, providing parent type and first name as example
|
|
151
|
+
const firstNameExample = names.length > 0 ? names[0] : undefined;
|
|
130
152
|
listText += generateListHint(context, {
|
|
131
153
|
itemType: 'componentName',
|
|
132
154
|
parentComponentType: this.componentType,
|
|
155
|
+
firstItemExample: firstNameExample,
|
|
133
156
|
});
|
|
134
157
|
|
|
135
158
|
return [
|
|
@@ -43,15 +43,21 @@ export class RenderablePathItem implements RenderableSpecObject {
|
|
|
43
43
|
];
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
//
|
|
46
|
+
// Sort methods first to get the correct example
|
|
47
|
+
methods.sort();
|
|
48
|
+
const firstMethodExample = methods.length > 0 ? methods[0] : undefined;
|
|
49
|
+
|
|
50
|
+
// Generate hint using the new structure, providing the first *sorted* method as an example
|
|
47
51
|
const hint = generateListHint(context, {
|
|
48
52
|
itemType: 'pathMethod',
|
|
49
53
|
parentPath: this.path, // Use the stored raw path
|
|
54
|
+
firstItemExample: firstMethodExample,
|
|
50
55
|
});
|
|
51
56
|
// Hint includes leading newline, so start output with it directly
|
|
52
57
|
let outputLines: string[] = [hint.trim(), '']; // Trim leading newline from hint for first line
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
// Iterate over the already sorted methods
|
|
60
|
+
methods.forEach(method => {
|
|
55
61
|
const operation = this.getOperation(method);
|
|
56
62
|
// Use summary or operationId (via getOperationSummary)
|
|
57
63
|
const summaryText = getOperationSummary(operation);
|
package/src/rendering/utils.ts
CHANGED
|
@@ -14,6 +14,7 @@ type ListItemType = 'componentType' | 'componentName' | 'pathMethod';
|
|
|
14
14
|
// Define context needed for generating the correct detail URI suffix
|
|
15
15
|
interface HintContext {
|
|
16
16
|
itemType: ListItemType;
|
|
17
|
+
firstItemExample?: string; // Example value from the first item in the list
|
|
17
18
|
// For componentName hints, the parent component type is needed
|
|
18
19
|
parentComponentType?: string;
|
|
19
20
|
// For pathMethod hints, the parent path is needed
|
|
@@ -43,6 +44,7 @@ export function getOperationSummary(
|
|
|
43
44
|
export function generateListHint(renderContext: RenderContext, hintContext: HintContext): string {
|
|
44
45
|
let detailUriSuffixPattern: string;
|
|
45
46
|
let itemTypeName: string; // User-friendly name for the item type in the hint text
|
|
47
|
+
let exampleUriSuffix: string | undefined; // To hold the generated example URI
|
|
46
48
|
|
|
47
49
|
switch (hintContext.itemType) {
|
|
48
50
|
case 'componentType':
|
|
@@ -50,6 +52,9 @@ export function generateListHint(renderContext: RenderContext, hintContext: Hint
|
|
|
50
52
|
// Hint should point to openapi://components/{type}
|
|
51
53
|
detailUriSuffixPattern = buildComponentMapUriSuffix('{type}'); // Use placeholder
|
|
52
54
|
itemTypeName = 'component type';
|
|
55
|
+
if (hintContext.firstItemExample) {
|
|
56
|
+
exampleUriSuffix = buildComponentMapUriSuffix(hintContext.firstItemExample);
|
|
57
|
+
}
|
|
53
58
|
break;
|
|
54
59
|
case 'componentName':
|
|
55
60
|
// Listing component names (e.g., MySchema, User) at openapi://components/{type}
|
|
@@ -64,6 +69,12 @@ export function generateListHint(renderContext: RenderContext, hintContext: Hint
|
|
|
64
69
|
'{name}'
|
|
65
70
|
);
|
|
66
71
|
itemTypeName = hintContext.parentComponentType.slice(0, -1); // e.g., 'schema' from 'schemas'
|
|
72
|
+
if (hintContext.firstItemExample) {
|
|
73
|
+
exampleUriSuffix = buildComponentDetailUriSuffix(
|
|
74
|
+
hintContext.parentComponentType,
|
|
75
|
+
hintContext.firstItemExample
|
|
76
|
+
);
|
|
77
|
+
}
|
|
67
78
|
break;
|
|
68
79
|
case 'pathMethod':
|
|
69
80
|
// Listing methods (e.g., get, post) at openapi://paths/{path}
|
|
@@ -75,6 +86,13 @@ export function generateListHint(renderContext: RenderContext, hintContext: Hint
|
|
|
75
86
|
// Use the actual parent path and a placeholder for the method
|
|
76
87
|
detailUriSuffixPattern = buildOperationUriSuffix(hintContext.parentPath, '{method}');
|
|
77
88
|
itemTypeName = 'operation'; // Or 'method'? 'operation' seems clearer
|
|
89
|
+
if (hintContext.firstItemExample) {
|
|
90
|
+
// Ensure the example method is valid if needed, though usually it's just 'get', 'post' etc.
|
|
91
|
+
exampleUriSuffix = buildOperationUriSuffix(
|
|
92
|
+
hintContext.parentPath,
|
|
93
|
+
hintContext.firstItemExample
|
|
94
|
+
);
|
|
95
|
+
}
|
|
78
96
|
break;
|
|
79
97
|
default:
|
|
80
98
|
// Explicitly cast to string to avoid potential 'never' type issue in template literal
|
|
@@ -84,8 +102,16 @@ export function generateListHint(renderContext: RenderContext, hintContext: Hint
|
|
|
84
102
|
|
|
85
103
|
// Construct the full hint URI pattern using the base URI
|
|
86
104
|
const fullHintPattern = `${renderContext.baseUri}${detailUriSuffixPattern}`;
|
|
105
|
+
const fullExampleUri = exampleUriSuffix
|
|
106
|
+
? `${renderContext.baseUri}${exampleUriSuffix}`
|
|
107
|
+
: undefined;
|
|
108
|
+
|
|
109
|
+
let hintText = `\nHint: Use '${fullHintPattern}' to view details for a specific ${itemTypeName}.`;
|
|
110
|
+
if (fullExampleUri) {
|
|
111
|
+
hintText += ` (e.g., ${fullExampleUri})`;
|
|
112
|
+
}
|
|
87
113
|
|
|
88
|
-
return
|
|
114
|
+
return hintText;
|
|
89
115
|
}
|
|
90
116
|
|
|
91
117
|
/**
|
package/src/version.ts
CHANGED
|
@@ -40,13 +40,18 @@ describe('RenderableComponents (List Types)', () => {
|
|
|
40
40
|
expect(result[0].renderAsList).toBe(true);
|
|
41
41
|
expect(result[0].isError).toBeUndefined();
|
|
42
42
|
expect(result[0].data).toContain('Available Component Types:');
|
|
43
|
-
// Check sorted types
|
|
44
|
-
expect(result[0].data).toMatch(/-\s+examples\n/);
|
|
45
|
-
expect(result[0].data).toMatch(
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
// Check sorted types with descriptions
|
|
44
|
+
expect(result[0].data).toMatch(/-\s+examples: Reusable examples of media type payloads\n/);
|
|
45
|
+
expect(result[0].data).toMatch(
|
|
46
|
+
/-\s+parameters: Reusable request parameters \(query, path, header, cookie\)\n/
|
|
47
|
+
);
|
|
48
|
+
expect(result[0].data).toMatch(/-\s+responses: Reusable API responses\n/);
|
|
49
|
+
expect(result[0].data).toMatch(/-\s+schemas: Reusable data structures \(models\)\n/);
|
|
48
50
|
expect(result[0].data).not.toContain('- securitySchemes'); // Missing type
|
|
49
|
-
|
|
51
|
+
// Check hint with example
|
|
52
|
+
expect(result[0].data).toContain(
|
|
53
|
+
"Hint: Use 'openapi://components/{type}' to view details for a specific component type. (e.g., openapi://components/examples)"
|
|
54
|
+
);
|
|
50
55
|
});
|
|
51
56
|
|
|
52
57
|
it('should handle empty components object', () => {
|
|
@@ -121,7 +126,10 @@ describe('RenderableComponentMap (List/Detail Names)', () => {
|
|
|
121
126
|
expect(result[0].data).toContain('Available schemas:');
|
|
122
127
|
expect(result[0].data).toMatch(/-\s+Error\n/); // Sorted
|
|
123
128
|
expect(result[0].data).toMatch(/-\s+User\n/);
|
|
124
|
-
|
|
129
|
+
// Check hint with example
|
|
130
|
+
expect(result[0].data).toContain(
|
|
131
|
+
"Hint: Use 'openapi://components/schemas/{name}' to view details for a specific schema. (e.g., openapi://components/schemas/Error)"
|
|
132
|
+
);
|
|
125
133
|
});
|
|
126
134
|
|
|
127
135
|
it('should list component names correctly (parameters)', () => {
|
|
@@ -131,7 +139,10 @@ describe('RenderableComponentMap (List/Detail Names)', () => {
|
|
|
131
139
|
expect(result[0].uriSuffix).toBe(paramsUriSuffix);
|
|
132
140
|
expect(result[0].data).toContain('Available parameters:');
|
|
133
141
|
expect(result[0].data).toMatch(/-\s+userIdParam\n/);
|
|
134
|
-
|
|
142
|
+
// Check hint with example
|
|
143
|
+
expect(result[0].data).toContain(
|
|
144
|
+
"Hint: Use 'openapi://components/parameters/{name}' to view details for a specific parameter. (e.g., openapi://components/parameters/userIdParam)"
|
|
145
|
+
);
|
|
135
146
|
});
|
|
136
147
|
|
|
137
148
|
it('should handle empty component map', () => {
|
|
@@ -49,8 +49,9 @@ describe('RenderablePathItem', () => {
|
|
|
49
49
|
// Define expected output lines based on the new format and builder logic
|
|
50
50
|
// generateListHint uses buildOperationUriSuffix which encodes the path
|
|
51
51
|
// Since rawPath is '/items', encoded is 'items'.
|
|
52
|
+
// The first sorted method is 'delete'.
|
|
52
53
|
const expectedHint =
|
|
53
|
-
"Hint: Use 'openapi://paths/items/{method}' to view details for a specific operation.";
|
|
54
|
+
"Hint: Use 'openapi://paths/items/{method}' to view details for a specific operation. (e.g., openapi://paths/items/delete)";
|
|
54
55
|
const expectedLineDelete = 'DELETE'; // No summary/opId
|
|
55
56
|
const expectedLineGet = 'GET: Get Item'; // Summary exists
|
|
56
57
|
const expectedLinePost = 'POST: Create Item'; // Summary exists
|