@tzurp/openapi-skills 1.2.9 → 1.3.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/README.md +67 -19
- package/dist/cli.min.js +71 -0
- package/package.json +60 -64
- package/skill-templates/SKILL.md +30 -16
- package/bin/openapi-skills +0 -4
- package/dist/cli.d.ts +0 -37
- package/dist/cli.js +0 -1646
- package/dist/cli.js.map +0 -1
- package/dist/client-schema-builder.d.ts +0 -35
- package/dist/client-schema-builder.js +0 -268
- package/dist/client-schema-builder.js.map +0 -1
- package/dist/helper/base64url-json.d.ts +0 -3
- package/dist/helper/base64url-json.js +0 -28
- package/dist/helper/base64url-json.js.map +0 -1
- package/dist/helper/dotNotation.d.ts +0 -3
- package/dist/helper/dotNotation.js +0 -34
- package/dist/helper/dotNotation.js.map +0 -1
- package/dist/helper/endpoint-filter.d.ts +0 -16
- package/dist/helper/endpoint-filter.js +0 -165
- package/dist/helper/endpoint-filter.js.map +0 -1
- package/dist/helper/endpoint-utils.d.ts +0 -2
- package/dist/helper/endpoint-utils.js +0 -10
- package/dist/helper/endpoint-utils.js.map +0 -1
- package/dist/helper/error-codes.d.ts +0 -27
- package/dist/helper/error-codes.js +0 -116
- package/dist/helper/error-codes.js.map +0 -1
- package/dist/helper/error-formatter.d.ts +0 -46
- package/dist/helper/error-formatter.js +0 -72
- package/dist/helper/error-formatter.js.map +0 -1
- package/dist/helper/get-operation-filter.d.ts +0 -17
- package/dist/helper/get-operation-filter.js +0 -26
- package/dist/helper/get-operation-filter.js.map +0 -1
- package/dist/helper/graphql.d.ts +0 -40
- package/dist/helper/graphql.js +0 -967
- package/dist/helper/graphql.js.map +0 -1
- package/dist/helper/http-client.d.ts +0 -28
- package/dist/helper/http-client.js +0 -90
- package/dist/helper/http-client.js.map +0 -1
- package/dist/helper/json-updater.d.ts +0 -17
- package/dist/helper/json-updater.js +0 -195
- package/dist/helper/json-updater.js.map +0 -1
- package/dist/helper/logger.d.ts +0 -13
- package/dist/helper/logger.js +0 -56
- package/dist/helper/logger.js.map +0 -1
- package/dist/helper/output-size.d.ts +0 -5
- package/dist/helper/output-size.js +0 -7
- package/dist/helper/output-size.js.map +0 -1
- package/dist/helper/parameter-schema.d.ts +0 -14
- package/dist/helper/parameter-schema.js +0 -36
- package/dist/helper/parameter-schema.js.map +0 -1
- package/dist/helper/paths.d.ts +0 -11
- package/dist/helper/paths.js +0 -47
- package/dist/helper/paths.js.map +0 -1
- package/dist/helper/prompt-delete.d.ts +0 -1
- package/dist/helper/prompt-delete.js +0 -13
- package/dist/helper/prompt-delete.js.map +0 -1
- package/dist/helper/request-artifacts.d.ts +0 -14
- package/dist/helper/request-artifacts.js +0 -60
- package/dist/helper/request-artifacts.js.map +0 -1
- package/dist/helper/request-preparation.d.ts +0 -23
- package/dist/helper/request-preparation.js +0 -85
- package/dist/helper/request-preparation.js.map +0 -1
- package/dist/helper/sanitizer.d.ts +0 -1
- package/dist/helper/sanitizer.js +0 -17
- package/dist/helper/sanitizer.js.map +0 -1
- package/dist/helper/update-check.d.ts +0 -1
- package/dist/helper/update-check.js +0 -36
- package/dist/helper/update-check.js.map +0 -1
- package/dist/index.d.ts +0 -50
- package/dist/index.js +0 -163
- package/dist/index.js.map +0 -1
- package/dist/install-skill.d.ts +0 -5
- package/dist/install-skill.js +0 -139
- package/dist/install-skill.js.map +0 -1
- package/dist/parser.d.ts +0 -12
- package/dist/parser.js +0 -393
- package/dist/parser.js.map +0 -1
- package/dist/validate-response.d.ts +0 -47
- package/dist/validate-response.js +0 -1017
- package/dist/validate-response.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
|
|
2
|
-
# openapi-skills
|
|
3
|
-
API CLI with SKILLS
|
|
2
|
+
# openapi-skills: OpenAPI & GraphQL CLI
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
Looking for the Pro version? → https://github.com/tzurp/openapi-skills-pro
|
|
5
|
+
[](https://github.com/tzurp/openapi-skills-pro)
|
|
6
|
+
|
|
7
|
+
`openapi-skills` is an OpenAPI CLI and GraphQL CLI for exploring APIs, generating artifacts, validating schemas, and preparing live API requests. Its optional AI agent skills enable Copilot, Claude, Cursor, and other agents to use the CLI through natural language.
|
|
8
|
+
|
|
9
|
+

|
|
6
10
|

|
|
7
11
|
<p align="center">
|
|
8
12
|
<img src="https://raw.githubusercontent.com/tzurp/images/refs/heads/main/openapi-skills.png">
|
|
@@ -13,7 +17,16 @@ Use it manually like a fast, lightweight API explorer, or unlock its full potent
|
|
|
13
17
|
|
|
14
18
|
With Skills enabled, openapi‑skills becomes an AI‑ready API engine: agents can explore your API, prepare and execute live requests, validate schemas, and even generate client code, tests, and workflows - all from simple, conversational instructions.
|
|
15
19
|
|
|
16
|
-
##
|
|
20
|
+
## Quick links
|
|
21
|
+
|
|
22
|
+
- [Install the CLI](#install-the-cli)
|
|
23
|
+
- [Install the AI skill bundle](#install-the-skill)
|
|
24
|
+
- [Quick start](#quick-start)
|
|
25
|
+
- [AI agent examples](#ai-agent-integration)
|
|
26
|
+
- [Video demo](#-video-demo)
|
|
27
|
+
- [Support and issues](#support)
|
|
28
|
+
|
|
29
|
+
## Overview: OpenAPI & GraphQL CLI
|
|
17
30
|
|
|
18
31
|
`openapi-skills` helps developers work with API schemas efficiently. It parses OpenAPI and GraphQL definitions, generates structured artifacts, provides exploration tools, validates schemas, prepares request templates, and supports test generation. When the AI skills are installed, agents can understand your API and execute CLI commands automatically.
|
|
19
32
|
|
|
@@ -27,6 +40,27 @@ Working with API schemas can be slow and error‑prone. `openapi-skills` provide
|
|
|
27
40
|
- Built‑in validation tools
|
|
28
41
|
- Optional AI integration for natural-language workflows
|
|
29
42
|
|
|
43
|
+
## Free vs. Pro: Choosing the right tool for your workflow
|
|
44
|
+
|
|
45
|
+
The free CLI is perfect for solo developers, quick exploration, and everyday API work.
|
|
46
|
+
The Pro CLI is built for teams, automation, and production‑grade workflows, where speed, orchestration, and tooling depth matter.
|
|
47
|
+
Here’s a concise comparison to help you understand where each version shines:
|
|
48
|
+
|
|
49
|
+
### Comparison Table
|
|
50
|
+
| **Scenario / Workflow** | **Free CLI** | **Pro CLI** |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| **Explore OpenAPI & GraphQL schemas** | ✔ Explore OpenAPI 2.0 / 3.0.x & GraphQL schemas | ✔ Same, with OpenAPI 3.1 support |
|
|
53
|
+
| **Generate artifacts** | ✔ endpoints.json, schemas/ | ✔ Extended artifacts for docs, diffing & analysis |
|
|
54
|
+
| **Validate schemas** | ✔ Built‑in validation | ✔ Deep validation + version comparison |
|
|
55
|
+
| **Prepare & execute live API requests** | ✔ Postman‑like request builder | ✔ Same, plus mock‑server integration |
|
|
56
|
+
| **AI agent workflows** | ✔ Optional skill bundle for LLM agents | ✔ Enhanced Skills (OpenAPI annotation generation) |
|
|
57
|
+
| **Mock server** | — | ✔ Local mock server from schema artifacts |
|
|
58
|
+
| **HTML API documentation** | — | ✔ Generate interactive HTML docs |
|
|
59
|
+
| **Compare API responses with response schemas** | — | ✔ Validate API responses against their OpenAPI response schemas |
|
|
60
|
+
| **Schema diffing / version comparison** | — | ✔ Operation‑level diffing & breaking‑change detection |
|
|
61
|
+
| **Code‑first OpenAPI generation** | — | ✔ Bootstrap OpenAPI from annotated source code |
|
|
62
|
+
| **Distribution** | ``npm install -g`` | Native installers (Windows/macOS/Linux) |
|
|
63
|
+
|
|
30
64
|
## Manual CLI + AI Skills
|
|
31
65
|
|
|
32
66
|
openapi-skills works perfectly as a traditional CLI. You can explore endpoints, inspect schemas, prepare requests, and execute live API calls directly from the terminal.
|
|
@@ -38,10 +72,10 @@ Enable the optional Skill bundle, and AI agents (Copilot, Claude, Cursor, etc.)
|
|
|
38
72
|
- Explore operations by method, path, tag, or keyword
|
|
39
73
|
- Describe endpoints with full request/response details
|
|
40
74
|
- Prepare and execute live API requests (Postman‑like, no code needed)
|
|
41
|
-
- Parse OpenAPI 2.0/3.x and GraphQL schemas
|
|
75
|
+
- Parse OpenAPI 2.0/3.0.x and GraphQL schemas
|
|
42
76
|
- Generate artifacts (`endpoints.json`, `schemas/`)
|
|
43
77
|
- Work with multiple API schemas simultaneously (stored under: .openapi-skills/<apiName>/ directory)
|
|
44
|
-
- Validate schemas
|
|
78
|
+
- Validate schemas; validates API responses against response schemas
|
|
45
79
|
- Build multi-step scenarios
|
|
46
80
|
- AI Skills bundle for agent-driven workflows (code, tests, clients, docs)
|
|
47
81
|
|
|
@@ -90,9 +124,13 @@ openapi-skills describe addPet --api petstore
|
|
|
90
124
|
### Prepare and execute a request manually
|
|
91
125
|
|
|
92
126
|
```bash
|
|
93
|
-
openapi-skills request addPet --api petstore --force --update-request '{"body.id":1,"body.name":"
|
|
127
|
+
openapi-skills request addPet --api petstore --force --update-request '{"body.id":1,"body.name":""}' --omit-empty
|
|
94
128
|
```
|
|
95
129
|
|
|
130
|
+
Use `--force-request` to reset only the request artifact from the cached operation schema. `--force` refreshes both the operation schema and the request artifact.
|
|
131
|
+
|
|
132
|
+
`--omit-empty` removes empty-string values from optional fields using the operation schema; required fields and other values are preserved.
|
|
133
|
+
|
|
96
134
|
---
|
|
97
135
|
|
|
98
136
|
## ⚡ One‑line agent command
|
|
@@ -155,7 +193,7 @@ Select your preferred path and confirm — that’s it.
|
|
|
155
193
|
> **💡 Note:**
|
|
156
194
|
>
|
|
157
195
|
> Installing the skill bundle allows AI agents to understand your API structure and execute CLI commands automatically.
|
|
158
|
-
> See the section on [AI agent capabilities](#ai-agent-
|
|
196
|
+
> See the section on [AI agent capabilities](#ai-agent-integration).
|
|
159
197
|
|
|
160
198
|
|
|
161
199
|
### 2. Parse a public API and set its base URL
|
|
@@ -183,18 +221,28 @@ openapi-skills request addPet --api petstore --force --update-request '{"body.id
|
|
|
183
221
|
openapi-skills generate https://petstore.swagger.io/v2/swagger.json --validate
|
|
184
222
|
```
|
|
185
223
|
|
|
186
|
-
##
|
|
224
|
+
## AI agent integration
|
|
225
|
+
|
|
226
|
+
The optional skill bundle teaches AI agents how to operate this API CLI using natural-language instructions. With the skill enabled, agents can:
|
|
227
|
+
|
|
228
|
+
- Explore OpenAPI and GraphQL schemas and API operations
|
|
229
|
+
- Generate client code, tests, documentation, and other artifacts
|
|
230
|
+
- Prepare and execute live API requests
|
|
231
|
+
- Validate schemas and API responses
|
|
232
|
+
- Build multi-step API workflows
|
|
233
|
+
|
|
234
|
+
### AI agent examples
|
|
187
235
|
|
|
188
236
|
| Natural language request | CLI/Skill executed |
|
|
189
237
|
|--------------------------|--------------------|
|
|
190
|
-
|
|
|
191
|
-
|
|
|
192
|
-
|
|
|
193
|
-
|
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
|
|
|
197
|
-
|
|
|
238
|
+
| "/openapi-skills Make a live request to addPet with name Fluffy." | Postman‑like API call via `request --update-request` |
|
|
239
|
+
| "/openapi-skills Show me the first POST operation." | Explore endpoints via `list` |
|
|
240
|
+
| "/openapi-skills Describe the addPet operation." | Operation breakdown via `describe` |
|
|
241
|
+
| "/openapi-skills Validate this API schema." | Schema validation via `generate --validate` |
|
|
242
|
+
| "/openapi-skills Generate a Jest test for addPet." | Agent writes full Jest test using CLI metadata |
|
|
243
|
+
| "/openapi-skills Create a Playwright API test for addPet." | Agent generates Playwright test using endpoint + schema |
|
|
244
|
+
| "/openapi-skills Build a TypeScript API client for this API." | Agent generates typed client functions + models |
|
|
245
|
+
| "/openapi-skills Create a 3-step scenario: add, fetch, delete pet." | Multi-step workflow via `request` |
|
|
198
246
|
|
|
199
247
|
Agents combine CLI output with code generation to produce:
|
|
200
248
|
- typed API clients
|
|
@@ -208,7 +256,7 @@ Agents combine CLI output with code generation to produce:
|
|
|
208
256
|
|
|
209
257
|
A short video clip demonstrating the CLI in action is available here:
|
|
210
258
|
|
|
211
|
-
[https://github.com/tzurp/openapi-skills-cli/releases
|
|
259
|
+
[https://github.com/tzurp/openapi-skills-cli/releases/tag/video](https://github.com/tzurp/openapi-skills-cli/releases/tag/video)
|
|
212
260
|
|
|
213
261
|
## Support
|
|
214
262
|
|
|
@@ -230,4 +278,4 @@ If you run into issues or have questions:
|
|
|
230
278
|
|
|
231
279
|
- npm package: [https://www.npmjs.com/package/@tzurp/openapi-skills](https://www.npmjs.com/package/@tzurp/openapi-skills)
|
|
232
280
|
- GitHub repository: [https://github.com/tzurp/openapi-skills-cli](https://github.com/tzurp/openapi-skills-cli)
|
|
233
|
-
|
|
281
|
+
- Bedekbyte: [https://www.bedekbyte.com](https://www.bedekbyte.com)
|
package/dist/cli.min.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var fn=Object.defineProperty;var S=(e,t,r)=>()=>{if(r)throw r[0];try{return e&&(t=e(e=0)),t}catch(n){throw r=[n],n}};var mn=(e,t)=>{for(var r in t)fn(e,r,{get:t[r],enumerable:!0})};function se(e){return e.normalize("NFKD").replace(/[\\/]/g,"_").split("_").map(s=>s===""?"_":(s=s.replace(/\./g,"_"),s=s.replace(/[^a-zA-Z0-9_-]/g,"_"),s=s.replace(/^_+|_+$/g,""),s||"_")).join("_")}var mt=S(()=>{"use strict"});import Pe from"fs-extra";import gn from"os";import Ie from"path";import{createRequire as zt}from"module";import{pathToFileURL as hn}from"url";import{buildSchema as yn,isEnumType as Kt,isInputObjectType as wn,isListType as Yt,isNonNullType as Xt,isObjectType as bn,isScalarType as Zt,valueFromAST as An}from"graphql";function er(e){if(!(e instanceof Error))return[String(e)];let t=[e.message],r=e.cause;return r instanceof Error?t.push(...er(r)):r!=null&&t.push(String(r)),t}function xn(e){return!/typescript/i.test(e)||!/(?:Cannot find (?:package|module)|ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND)/i.test(e)?!1:/['"]typescript(?:\/(?:unstable\/)?(?:ast|sync))?['"]/i.test(e)||/Cannot find typescript(?:\/(?:unstable\/)?(?:ast|sync))?/i.test(e)}function tr(e){return er(e).some(t=>/TypeScript is required to analyze builder GraphQL schemas/i.test(t)||xn(t))}function rr(e){let t=[zt(import.meta.url),zt(Ie.join(process.cwd(),"package.json"))];for(let r of t)try{return hn(r.resolve(e)).href}catch{}throw new Error(`Cannot find ${e}`)}async function En(){let e;for(let t of Tn)try{let r=await Sn(t);if(typeof r.isCallExpression=="function")return r;e=new Error(`TypeScript module '${t}' does not export the AST API.`)}catch(r){e=r;try{let n=await import(rr(t));if(typeof n.isCallExpression=="function")return n;e=new Error(`TypeScript module '${t}' does not export the AST API.`)}catch(n){e=n}}throw e??new Error("TypeScript is required to analyze builder GraphQL schemas.")}async function Sn(e){return await import(e)}async function Pn(){let e;for(let t of kn)try{let r=await In(t);if(typeof r.API=="function")return r.API;let n=Ht(r);if(n)return n;e=new Error(`TypeScript module '${t}' does not export API.`)}catch(r){e=r;try{let n=await import(rr(t));if(typeof n.API=="function")return n.API;let s=Ht(n);if(s)return s;e=new Error(`TypeScript module '${t}' does not export API.`)}catch(n){e=n}}throw e??new Error("TypeScript is required to analyze builder GraphQL schemas.")}function Ht(e){return typeof e.createSourceFile!="function"||!e.ScriptTarget||!e.ScriptKind?null:class{updateSnapshot(r){let n=r.openFiles[0],s=Pe.readFileSync(n,"utf8"),i=e.createSourceFile(n,s,e.ScriptTarget.Latest,!0,e.ScriptKind.TS);return{getDefaultProjectForFile:()=>({program:{getSourceFile:()=>i}}),dispose:()=>{}}}close(){}}}async function In(e){return await import(e)}async function nr(){if(ge&&Me)return ge;try{ge=await En(),Me=await Pn()}catch(e){throw new Error("TypeScript is required to analyze builder GraphQL schemas.",{cause:e})}return ge}function J(){if(!ge)throw new Error("TypeScript has not been loaded.");return ge}async function Rn(e,t){await nr();let r=Ie.extname(t??"").toLowerCase(),n=`graphql-source${r===".tsx"||r===".jsx"?r:".ts"}`,s=await Pe.mkdtemp(Ie.join(gn.tmpdir(),"openapi-skills-graphql-")),i=Ie.join(s,n);if(await Pe.writeFile(i,e,"utf8"),!Me)throw new Error("TypeScript API has not been loaded.");let o=new Me,a=o.updateSnapshot({openFiles:[i]});try{let c=a.getDefaultProjectForFile(i)?.program.getSourceFile(i);if(!c)throw new Error("TypeScript could not parse the GraphQL builder source.");return c}finally{a.dispose(),o.close(),await Pe.remove(s)}}function On(e,t){return t&&[".ts",".tsx",".mts",".cts"].includes(Ie.extname(t).toLowerCase())?!0:[/\bbuilder\.queryType\s*\(/,/\bbuilder\.mutationType\s*\(/,/\bbuilder\.subscriptionType\s*\(/,/\bobjectType\s*\(/,/\bnew\s+SchemaBuilder\s*\(/].some(r=>r.test(e))}async function He(e){if(/^https?:\/\//i.test(e)){let t=await fetch(e);if(!t.ok)throw new Error(`Failed to load GraphQL source from ${e}: HTTP ${t.status}`);return await t.text()}return await Pe.readFile(e,"utf8")}function We(e){return[/\btype\s+Query\b/i,/\btype\s+Mutation\b/i,/\btype\s+Subscription\b/i,/\bschema\s*\{/i,/\bextend\s+type\s+Query\b/i,/\bbuilder\.(queryType|mutationType|subscriptionType)\s*\(/i,/\btoSchema\s*\(/i].some(t=>t.test(e))}function gt(e){let t=J();if(e&&(t.isStringLiteral(e)||t.isNoSubstitutionTemplateLiteral(e)))return e.text}function qn(e,t){let r=J();if(e)return e.properties.find(n=>r.isPropertyAssignment(n)||r.isShorthandPropertyAssignment(n)?(r.isIdentifier(n.name)||r.isStringLiteral(n.name)||r.isNumericLiteral(n.name)?n.name.text:n.name.getText())===t:!1)}function C(e,t){let r=J(),n=qn(e,t);if(!(!n||!r.isPropertyAssignment(n)))return n.initializer}function he(e){let t=J(),r=e;for(;r&&t.isParenthesizedExpression(r);)r=r.expression;return r}function G(e){let t=J(),r=he(e);if(r){if(t.isObjectLiteralExpression(r))return r;if(t.isArrowFunction(r)||t.isFunctionExpression(r)){if(t.isBlock(r.body)){for(let n of r.body.statements)if(t.isReturnStatement(n)&&n.expression){let s=G(n.expression);if(s)return s}return}return G(r.body)}}}function vn(e){let t=J(),r=e.expression;if(!t.isPropertyAccessExpression(r))return;let n=r.name.text;if(n==="queryType")return"query";if(n==="mutationType")return"mutation";if(n==="subscriptionType")return"subscription"}function Wt(e,t){let r=J(),n=he(e);if(n)return r.isStringLiteral(n)||r.isNoSubstitutionTemplateLiteral(n)?n.text:r.isIdentifier(n)?t.objectTypeNames[n.text]??n.text:n.getText()}function Nn(e,t){let r=J(),n=he(e);if(n){if(r.isCallExpression(n)){let s=n.expression.getText();if(/\.exposeID$/i.test(s))return"ID";if(/\.exposeString$/i.test(s))return"String";if(/\.exposeInt$/i.test(s))return"Int";if(/\.exposeFloat$/i.test(s))return"Float";if(/\.exposeBoolean$/i.test(s))return"Boolean";if(/\.string$/i.test(s))return"String";if(/\.int$/i.test(s))return"Int";if(/\.float$/i.test(s))return"Float";if(/\.boolean$/i.test(s))return"Boolean";if(/\.id$/i.test(s))return"ID";if(/\.stringList$/i.test(s))return"[String]";if(/\.intList$/i.test(s))return"[Int]";if(/\.floatList$/i.test(s))return"[Float]";if(/\.booleanList$/i.test(s))return"[Boolean]";if(/\.idList$/i.test(s))return"[ID]";let i=n.arguments[0];if(i&&r.isObjectLiteralExpression(i)){let o=C(i,"type");if(o){let a=Wt(o,t);if(a)return a}}}return Wt(n,t)}}function jn(e){let t=J(),r={},n={};function s(i){if(t.isVariableDeclaration(i)&&i.initializer&&t.isCallExpression(i.initializer)&&t.isPropertyAccessExpression(i.initializer.expression)&&i.initializer.expression.name.text==="objectRef"){let o=i.initializer.arguments[0],a=i.name.getText(e);o&&t.isStringLiteral(o)&&(r[a]=o.text)}if(t.isCallExpression(i)&&t.isPropertyAccessExpression(i.expression)&&i.expression.name.text==="objectType"&&i.arguments.length>1){let o=i.arguments[0],a=G(i.arguments[1]),p=C(a,"name")?gt(C(a,"name")):o&&t.isIdentifier(o)?r[o.text]??o.text:o&&t.isStringLiteral(o)?o.text:void 0;if(p&&a){let c=C(a,"fields"),u=G(c);if(u){let m={};for(let f of u.properties){if(!t.isPropertyAssignment(f))continue;let l=t.isIdentifier(f.name)||t.isStringLiteral(f.name)||t.isNumericLiteral(f.name)?f.name.text:f.name.getText(e),g=Nn(f.initializer,{objectTypeNames:r,objectFields:n});g&&(m[l]=g)}n[p]=m}}}i.forEachChild(s)}return s(e),{objectTypeNames:r,objectFields:n}}function Ue(e,t,r=new Set){let n=e.trim();if(!n)return{kind:"unknown",typeName:"Unknown"};if(n.endsWith("!"))return{kind:"non-null",typeName:n,required:!0,ofType:Ue(n.slice(0,-1),t,r)};if(n.startsWith("[")&&n.endsWith("]"))return{kind:"list",typeName:n,ofType:Ue(n.slice(1,-1).trim(),t,r)};if(wt.has(n))return{kind:"scalar",typeName:n};let s=t.objectTypeNames[n]??n;if(r.has(s))return{kind:"object",typeName:s,circular:s,fields:{}};let i=t.objectFields[s];if(!i)return{kind:"object",typeName:s};let o=new Set(r);o.add(s);let a={};for(let[p,c]of Object.entries(i))a[p]=Ue(c,t,o);return{kind:"object",typeName:s,fields:a}}function Ke(e){let t=e.trim();for(;t.endsWith("!");)t=t.slice(0,-1).trim();return t.startsWith("[")&&t.endsWith("]")&&(t=t.slice(1,-1).trim()),t}function _n(e,t){let r=Ke(e);return wt.has(r)?"scalar":t&&/input|filter|where|args?/i.test(r)||t?"input-object":"object"}function Ve(e,t){let r=e.trim();if(!r)return{kind:"unknown",typeName:"Unknown"};if(r.endsWith("!"))return{kind:"non-null",typeName:r,required:!0,ofType:Ve(r.slice(0,-1),t)};if(r.startsWith("[")&&r.endsWith("]")){let s=r.slice(1,-1).trim();return{kind:"list",typeName:r,ofType:Ve(s,t)}}return{kind:_n(r,t),typeName:r}}function ze(e){let t=J(),r=he(e);if(r){if(t.isStringLiteral(r)||t.isNoSubstitutionTemplateLiteral(r))return r.text;if(t.isNumericLiteral(r))return Number(r.text);if(r.kind===t.SyntaxKind.TrueKeyword)return!0;if(r.kind===t.SyntaxKind.FalseKeyword)return!1;if(r.kind===t.SyntaxKind.NullKeyword)return null;if(t.isArrayLiteralExpression(r))return r.elements.map(n=>ze(n));if(t.isObjectLiteralExpression(r)){let n={};for(let s of r.properties)if(t.isPropertyAssignment(s)){let i=t.isIdentifier(s.name)||t.isStringLiteral(s.name)||t.isNumericLiteral(s.name)?s.name.text:s.name.getText();n[i]=ze(s.initializer)}return n}t.isIdentifier(r)&&r.text}}function Ln(e){let t=J(),r=he(e);if(!r)return{kind:"unknown",typeName:"Unknown"};if(t.isCallExpression(r)){let n=r.expression.getText(),s=r.arguments[0];if(s&&t.isObjectLiteralExpression(s)){let i=C(s,"type"),o=C(s,"required"),a=C(s,"defaultValue"),p;if(i?p=Ve(i.getText(),!0):/\.string$/i.test(n)?p={kind:"scalar",typeName:"String"}:/\.int$/i.test(n)?p={kind:"scalar",typeName:"Int"}:/\.float$/i.test(n)?p={kind:"scalar",typeName:"Float"}:/\.boolean$/i.test(n)?p={kind:"scalar",typeName:"Boolean"}:/\.id$/i.test(n)&&(p={kind:"scalar",typeName:"ID"}),p)return p.defaultValue=ze(a),o&&ze(o)===!0?{kind:"non-null",typeName:`${p.typeName}!`,required:!0,ofType:p}:p}if(/\.string$/i.test(n))return{kind:"scalar",typeName:"String"};if(/\.int$/i.test(n))return{kind:"scalar",typeName:"Int"};if(/\.float$/i.test(n))return{kind:"scalar",typeName:"Float"};if(/\.boolean$/i.test(n))return{kind:"scalar",typeName:"Boolean"};if(/\.id$/i.test(n))return{kind:"scalar",typeName:"ID"}}return Ve(r.getText(),!0)}function Cn(e){let t=Ke(e);return t==="Boolean"?!1:t==="Int"||t==="Float"?0:t==="ID"||t==="String"?"":null}function ht(e){if(e.kind==="non-null"&&e.ofType)return ht(e.ofType);if(e.kind==="list")return[];if(e.kind==="scalar")return Cn(e.typeName);if(e.kind==="enum")return e.enumValues?.[0]??null;if(e.kind==="input-object"){let t={};for(let[r,n]of Object.entries(e.fields??{}))t[r]=ht(n);return t}return null}function yt(e){return e.kind==="non-null"&&e.ofType?`${yt(e.ofType)}!`:e.kind==="list"&&e.ofType?`[${yt(e.ofType)}]`:e.typeName}function $n(e){let t=Ke(e.typeName);return e.kind==="scalar"||e.kind==="enum"||wt.has(t)}function Ge(e,t=new Set){if(e.kind==="non-null"&&e.ofType||e.kind==="list"&&e.ofType)return Ge(e.ofType,t);if($n(e))return"";let r=Ke(e.typeName);if(t.has(r))return"__typename";if(e.kind==="object"||e.kind==="input-object"){let n=new Set(t);n.add(r);let s=Object.entries(e.fields??{});return s.length===0?"{ __typename }":`{ ${s.map(([o,a])=>{let p=Ge(a,n);if(!p)return o;if(a.kind==="object"||a.kind==="input-object"||a.kind==="list"||a.kind==="non-null"){let c=p.startsWith("{")?p:`{ ${p} }`;return`${o} ${c}`}return`${o} ${p}`}).join(" ")} }`}return"__typename"}function Dn(e){let t=Object.keys(e.args),r=t.map(u=>{let m=e.args[u];return`$${u}: ${m?yt(m):"String"}`}),n={};for(let[u,m]of Object.entries(e.args))n[u]=ht(m);let s=t.map(u=>`${u}: $${u}`).join(", "),i=Ge(e.returns),o=i?` ${i}`:"",a=se(e.operationId)||e.operationId,p=r.length>0?`(${r.join(", ")})`:"",c=s.length>0?`(${s})`:"";return{query:`${e.rootType} ${a}${p} { ${e.name}${c}${o} }`,variables:n}}function Fn(e){let t=yn(e),r=[["query",t.getQueryType()],["mutation",t.getMutationType()],["subscription",t.getSubscriptionType()]],n=[];for(let[s,i]of r)if(i)for(let o of Object.values(i.getFields())){let a={};for(let u of o.args){let m=Be(u.type),f=sr(u);f!==void 0&&(m.defaultValue=f),a[u.name]=m}let p={name:o.name,operationId:o.name,sanitizedOperationId:se(o.name),rootType:s,args:a,returns:Qe(o.type)},c=o.description?.split(`
|
|
3
|
+
`).map(u=>u.trim()).filter(Boolean)[0];c&&(p.summary=c),o.description&&(p.description=o.description),n.push(p)}return n}function sr(e){if(e.defaultValue!==void 0)return e.defaultValue;let t=e.astNode?.defaultValue;return t?An(t,e.type):void 0}function Be(e,t=new Set){if(Xt(e))return{kind:"non-null",typeName:e.toString(),required:!0,ofType:Be(e.ofType,t)};if(Yt(e))return{kind:"list",typeName:e.toString(),ofType:Be(e.ofType,t)};if(Zt(e))return{kind:"scalar",typeName:e.name};if(Kt(e))return{kind:"enum",typeName:e.name,enumValues:e.getValues().map(r=>r.name)};if(wn(e)){if(t.has(e.name))return{kind:"input-object",typeName:e.name,circular:e.name,fields:{}};let r=new Set(t);r.add(e.name);let n={};for(let[s,i]of Object.entries(e.getFields())){let o=Be(i.type,r),a=sr(i);a!==void 0&&(o.defaultValue=a),n[s]=o}return{kind:"input-object",typeName:e.name,fields:n}}return{kind:"unknown",typeName:String(e)}}function Qe(e,t=new Set){if(Xt(e))return{kind:"non-null",typeName:e.toString(),required:!0,ofType:Qe(e.ofType,t)};if(Yt(e))return{kind:"list",typeName:e.toString(),ofType:Qe(e.ofType,t)};if(Zt(e))return{kind:"scalar",typeName:e.name};if(Kt(e))return{kind:"enum",typeName:e.name,enumValues:e.getValues().map(r=>r.name)};if(bn(e)){if(t.has(e.name))return{kind:"object",typeName:e.name,circular:e.name,fields:{}};let r=new Set(t);r.add(e.name);let n={};for(let[s,i]of Object.entries(e.getFields()))n[s]=Qe(i.type,r);return{kind:"object",typeName:e.name,fields:n}}return{kind:"unknown",typeName:e.toString()}}async function Jn(e,t){let r=await nr(),n=await Rn(e,t),s=jn(n),i=[];function o(a){if(r.isCallExpression(a)&&r.isPropertyAccessExpression(a.expression)){let p=vn(a);if(p&&a.arguments.length>0){let c=G(a.arguments[0]),u=C(c,"fields"),m=G(u);if(m)for(let f of m.properties){if(!r.isPropertyAssignment(f))continue;let l=r.isIdentifier(f.name)||r.isStringLiteral(f.name)||r.isNumericLiteral(f.name)?f.name.text:f.name.getText(n),g=G(f.initializer)??G(f.initializer),b=he(f.initializer),T=b&&r.isCallExpression(b)?b:void 0,h=T?G(T.arguments[0]):g,y=C(h,"type"),A=gt(C(h,"summary")),P=gt(C(h,"description")),O=C(h,"args"),E=G(O),V={};if(E)for(let D of E.properties){if(!r.isPropertyAssignment(D))continue;let ne=r.isIdentifier(D.name)||r.isStringLiteral(D.name)||r.isNumericLiteral(D.name)?D.name.text:D.name.getText(n);V[ne]=Ln(D.initializer)}let x={name:l,operationId:l,sanitizedOperationId:se(l),rootType:p,args:V,returns:y?Ue(y.getText(n),s):{kind:"unknown",typeName:"Unknown"}};A&&(x.summary=A),P&&(x.description=P),i.push(x)}}}a.forEachChild(o)}return o(n),i}async function Ye(e,t){return On(e,t)?await Jn(e,t):Fn(e)}async function ye(e,t,r,n){let i=(await Ye(e,n)).find(o=>o.rootType===t&&o.name===r);if(!i)throw new Error(`GraphQL field '${r}' not found on root type '${t}'.`);return i}function Re(e){return Dn(e)}var wt,bt,Tn,kn,ge,Me,Oe=S(()=>{"use strict";mt();wt=new Set(["String","Int","Float","Boolean","ID"]),bt="npm install typescript",Tn=["typescript/ast","typescript","typescript/unstable/ast"],kn=["typescript/sync","typescript","typescript/unstable/sync"],ge=null,Me=null});function we(e,t){process.stderr.write(t?`${e}
|
|
4
|
+
`:e)}function W(e){return e instanceof Error?e.message:String(e)}var H,d,be=S(()=>{"use strict";H=process.stderr.isTTY&&process.stdout.isTTY;d={info(e){we(e,!0)},warn(e){let t="\u26A0\uFE0F ";if(H){let r=`\x1B[33m${t}${e}\x1B[0m`;we(r,!0)}else we(t+e,!0)},banner(e){we(H?`\x1B[35m${e}\x1B[0m`:e,!0)},error(e){process.stderr.write(`\u274C ${e}
|
|
5
|
+
`)},progress(e){H&&we(e,!1)},progressLine(e){H&&we(e,!0)},result(e){process.stdout.write(`${JSON.stringify(e)}
|
|
6
|
+
`)}}});import{promises as Xe}from"fs";import ir from"path";import Ze from"fs-extra";async function ar(e){try{return await Ze.readJSON(e,"utf8")}catch(t){if(t.code==="ENOENT")return{};throw t}}function Un(e,t,r){let n=t.split("."),s=e;for(let i=0;i<n.length;i++){let o=n[i]??"",a=i===n.length-1,p=typeof o=="string"&&/^[0-9]+$/.test(o),c=p?Number(o):void 0;if(a)p&&Array.isArray(s)&&c!==void 0?s[c]=r:s[o]=r;else if(p&&c!==void 0){if(!Array.isArray(s)&&i>0){let u=n[i-1]??"";s[u]=[],s=s[u]}s[c]||(s[c]={}),s=s[c]}else(!(o in s)||typeof s[o]!="object"||s[o]===null)&&(s[o]={}),s=s[o]}}function Gn(e,t){let r=t.split(".");if(r.length===0)return!1;let n=e;for(let o=0;o<r.length-1;o++){let a=r[o]??"",c=/^[0-9]+$/.test(a)&&Array.isArray(n)?n[Number(a)]:n&&typeof n=="object"?n[a]:void 0;if(c==null)return!1;n=c}let s=r[r.length-1]??"",i=/^[0-9]+$/.test(s);if(Array.isArray(n)&&i){let o=Number(s);return o<0||o>=n.length?!1:(n.splice(o,1),!0)}return n&&typeof n=="object"&&Object.prototype.hasOwnProperty.call(n,s)?(delete n[s],!0):!1}function Bn(e,t){return e===t||e.startsWith(`${t}.`)}function Qn(e,t){let r=e.split("."),n=t.split(".");if(r.length!==n.length)return n.length-r.length;let s=r[r.length-1]??"",i=n[n.length-1]??"",o=r.slice(0,-1).join("."),a=n.slice(0,-1).join(".");return o===a&&/^[0-9]+$/.test(s)&&/^[0-9]+$/.test(i)?Number(i)-Number(s):t.localeCompare(e)}async function qe(e,t,r=2,n={}){let s={};try{let h=await Xe.readFile(e,"utf8");s=JSON.parse(h)}catch(h){if(h.code!=="ENOENT")throw h}let i=JSON.parse(JSON.stringify(s)),o=n.deleteSentinel,a=o===void 0?[]:Object.entries(t).filter(([,h])=>h===o).map(([h])=>h).sort(Qn);for(let h of a)Gn(i,h);for(let[h,y]of Object.entries(t))o!==void 0&&y===o||a.some(A=>Bn(h,A))||Un(i,h,y);if(n.transform?.(i),!(JSON.stringify(s)!==JSON.stringify(i)))return{changed:!1,before:s,after:i};let c=ir.resolve(e),u=ir.dirname(c),m=Math.random().toString(36).slice(2,10),f=`${c}.tmp.${process.pid}.${m}`,l,g=new Set(["EPERM","EACCES","EBUSY"]);async function b(h){await new Promise(y=>setTimeout(y,h))}async function T(h,y){for(let P=1;P<=5;P++)try{await Xe.rename(h,y);return}catch(O){if(!g.has(O?.code)||P===5)throw O;await b(25*P)}}try{await Xe.mkdir(u,{recursive:!0}),l=await Xe.open(f,"w"),await l.writeFile(JSON.stringify(i,null,r),"utf8"),await l.sync(),await l.close(),await T(f,c);try{let h=Ze.openSync(u,"r");Ze.fsyncSync(h),Ze.closeSync(h)}catch{}return{changed:!0,before:s,after:i}}catch(h){if(l)try{await l.close()}catch{}throw(h.code==="EPERM"||h.code==="EACCES"||h.code==="EBUSY")&&d.error(`Failed to atomically update JSON file due to a file lock or permission error.
|
|
7
|
+
Please close any programs that may have the file open and try again.
|
|
8
|
+
The temporary file with your changes is: ${f}`),h}}var et,At=S(()=>{"use strict";be();et="__delete__"});import B from"path";import Mn from"find-root";function ae(e,t){let r=v(e);return B.join(r,`${t}.json`)}function oe(e){return B.resolve(ie,".openapi-skills",e,"bundled.json")}function Tt(e){return B.resolve(ie,".openapi-skills",e,"components.json")}function pe(e,t){let r=v(e);return B.resolve(r,t)}function v(e){return B.resolve(ie,".openapi-skills",e,"schemas")}function ve(e){return B.resolve(ie,".openapi-skills",e)}function or(){return B.resolve(ie,".openapi-skills","config.json")}function L(e){return B.resolve(ie,".openapi-skills",e,"endpoints.json")}function tt(e,t,r){let n=pe(e,t),s=r==="response-schema"?"response-schema.json":`${r}.json`;return B.join(n,s)}function rt(){return B.resolve(ie,".openapi-skills")}function nt(){let e=process.cwd();try{return Mn(e)}catch{return e}}var ie,K=S(()=>{"use strict";ie=nt()});import{readFile as Vn}from"fs/promises";import zn from"path";import ce from"fs-extra";async function U(){return await ce.readJSON(Ae)}async function kt(){if(await ce.ensureDir(Hn),!await ce.pathExists(Ae)){let e={apis:{}};await ce.writeJson(Ae,e,{spaces:2})}}function pr(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}async function Te(e,t={}){if(typeof e!="string"||e.trim().length===0)throw new Error("API name is required.");let{baseUrl:r,auth:n,vars:s,version:i,openapiSource:o,schemaType:a,removeApi:p}=t,c={};if(p){if(!await ce.pathExists(Ae))throw new Error("Config file not found.");let u=await U();if(!pr(u)||!pr(u.apis))throw new Error("Invalid config file.");if(!(e in u.apis))throw new Error(`API '${e}' not found`);delete u.apis[e],await ce.writeJson(Ae,u,{spaces:2});return}if(await kt(),n!==void 0&&(c[`apis.${e}.auth.headers`]=n),s!==void 0)for(let[u,m]of Object.entries(s))c[`apis.${e}.vars.${u}`]=m;if(i!==void 0&&(c[`apis.${e}.version`]=i),o!==void 0){let u=o;try{new URL(o)}catch{u=zn.normalize(o)}c[`apis.${e}.openapiSource`]=u}r!==void 0&&(c[`apis.${e}.baseUrl`]=r),a!==void 0&&(c[`apis.${e}.schemaType`]=a),Object.keys(c).length!==0&&await qe(Ae,c,2)}function Wn(e){let t=e instanceof Error?e.message:String(e);return/config/i.test(t)?{type:"ConfigError",message:t}:/permission|EACCES|EPERM/i.test(t)?{type:"DirectoryDeletionError",message:t}:{type:"DeleteApiError",message:t}}async function cr(e){if(typeof e!="string"||e.trim().length===0)return{ok:!1,error:{type:"InvalidApiName",message:"API name is required."}};try{if(!(await ue()).includes(e))return{ok:!1,error:{type:"ApiNotFound",message:`API '${e}' is not installed.`}};await Te(e,{removeApi:!0});let r=ve(e);return await ce.remove(r),{ok:!0,message:`API ${e} removed successfully`,data:{removedApi:e}}}catch(t){return{ok:!1,error:Wn(t)}}}async function st(e,t){let n=(await U()).apis[e];if(!n)throw new Error(`API '${e}' not found`);switch(t){case"version":return n.version??"unknown";case"baseUrl":return n.baseUrl;case"authHeaders":return n.auth?.headers??{};case"vars":return Object.entries(n.vars??{})}}async function ur(e){try{let t=await Vn(L(e),"utf-8");return JSON.parse(t)}catch(t){throw t instanceof SyntaxError?new Error(`Failed to parse endpoints.json: Invalid JSON format. ${t.message}`):new Error(`Failed to read endpoints.json: ${t instanceof Error?t.message:String(t)}`)}}async function ue(){let e=await U();return Object.keys(e.apis)||[]}var Hn,Ae,de=S(()=>{"use strict";At();K();Hn=rt(),Ae=or()});import xt from"@apidevtools/swagger-parser";import Kn from"@apidevtools/json-schema-ref-parser";import I from"fs-extra";import Y from"path";function dr(e){let t;try{let r=new URL(e);t=Y.basename(r.pathname,Y.extname(r.pathname))}catch{t=Y.basename(e,Y.extname(e))}return se(t||"api")}function Yn(e){if(e instanceof Error)return/circular/i.test(e.message)||/circular/i.test(e.name);if(typeof e=="object"&&e!==null){let t=String(e.message??""),r=String(e.name??"");return/circular/i.test(t)||/circular/i.test(r)}return!1}function Et(e,t=new WeakSet){if(e&&typeof e=="object"){if(t.has(e))return;if(t.add(e),Array.isArray(e)){let n=e.map(s=>Et(s,t));return t.delete(e),n}let r={};for(let[n,s]of Object.entries(e)){let i=Et(s,t);i!==void 0&&(r[n]=i)}return t.delete(e),r}return e}async function Xn(e){let t=oe(e),r=await I.readJson(t),n=typeof r?.source=="string"?r.source:typeof r?.sourceText=="string"?r.sourceText:void 0;if(!n)throw new Error(`GraphQL source not found for API '${e}'. Run generate first.`);return n}async function Zn(e,t,r,n=!1){let s=ae(e,r);if(!n&&await I.pathExists(s))return I.readJson(s);let i=await I.readJson(L(e)),o=Array.isArray(i)?i.find(u=>u.operationId===t||u.name===t||u.sanitizedOperationId===r):void 0;if(!o)throw new Error(`Endpoint '${t}' not found in GraphQL endpoint list.`);let a=typeof o.rootType=="string"?o.rootType:typeof o.method=="string"?o.method:void 0;if(!a||a!=="query"&&a!=="mutation"&&a!=="subscription")throw new Error(`Invalid GraphQL endpoint metadata for '${t}'.`);let p=await Xn(e),c=await ye(p,a,t);return await I.ensureDir(Y.dirname(s)),await I.writeJson(s,c,{spaces:2}),c}function es(e,t){for(let[r,n]of Object.entries(e))for(let[s,i]of Object.entries(n))if(i&&typeof i=="object"&&"operationId"in i){let o=i;if(o.operationId===t)return{pathKey:r,method:s,operation:o}}}async function ts(e,t){let r=typeof e.operationId=="string"?e.operationId:"unknown-operation",n=typeof e.method=="string"?e.method.toUpperCase():"GET",s=typeof e.path=="string"?e.path:"unknown-path",i=H;i&&d.progressLine(`Dereferencing endpoint ${r} (${n} ${s})...`);let o={openapi:"3.0.0",paths:{"/temp":{get:e}},definitions:t,components:t},a=await Kn.dereference(o,{mutateInputSchema:!1,dereference:{circular:"ignore"}}),p=Et(a),c=p.paths,u=c&&typeof c=="object"?c["/temp"]:void 0,m=u&&typeof u=="object"?u.get:void 0;return m&&typeof m=="object"?(i&&d.progressLine(`Endpoint ${r} (${n} ${s}) dereference complete.`),m):(i&&d.progressLine(`Endpoint ${r} (${n} ${s}) dereference complete.`),p)}async function Q(e,t,r,n=!1){let s=ae(e,r);if(!n&&await I.pathExists(s))return I.readJson(s);let i=oe(e),o=Tt(e),a=await I.readJson(i);if(a&&typeof a=="object"&&a.schemaType==="graphql")return await Zn(e,t,r,n);if(!a||typeof a!="object"||!("paths"in a))throw new Error(`Bundled OpenAPI document not found for API '${e}'. Run generate first.`);let p={},c=a.components,u=a.definitions;c&&typeof c=="object"&&!Array.isArray(c)?p=c:u&&typeof u=="object"&&!Array.isArray(u)?p=u:await I.pathExists(o)&&(p=await I.readJson(o));let m=es(a.paths,t);if(!m)throw new Error(`Endpoint '${t}' not found in bundled OpenAPI document.`);let f={operationId:t,method:m.method,path:m.pathKey,...m.operation},l=await ts(f,p);return await I.ensureDir(Y.dirname(s)),await I.writeJson(s,l,{spaces:2}),l}async function rs(e,t){if(!t)return xt.bundle(e);try{return await xt.dereference(e,{dereference:{circular:!1}})}catch(r){throw Yn(r)?new Error("The --dereference flag cannot be used because this OpenAPI spec contains circular references. Try running without --dereference."):r}}function ns(e){if(typeof e!="object"||e===null||Array.isArray(e))throw new Error("Invalid OpenAPI schema: expected a document object.");let t=e;if(t.swagger!==void 0&&t.openapi!==void 0)throw new Error("Invalid OpenAPI schema: both 'swagger' and 'openapi' version fields are present.");if(t.swagger!==void 0){if(t.swagger==="2.0")return"2";throw new Error(`Unsupported Swagger version '${String(t.swagger)}'. This CLI supports Swagger 2.0 and OpenAPI 3.0.x.`)}if(t.openapi!==void 0){if(typeof t.openapi!="string")throw new Error("Invalid OpenAPI schema: 'openapi' version must be a string.");if(/^3\.0\.\d+$/.test(t.openapi))return"3";throw new Error(`Unsupported OpenAPI version '${t.openapi}'. This CLI supports OpenAPI 2.0 and 3.0.x; For OpenAPI 3.1.0 and later, please use openapi-skills Pro.`)}throw new Error("Invalid OpenAPI schema: missing version declaration ('swagger' or 'openapi'); cannot determine a supported version.")}async function ss(e,t,r={}){let n="",s="unknown",i,o=r.progress!==!1&&H;try{o&&d.progressLine(`Loading OpenAPI document from ${e}...`),i=await rs(e,r.dereference===!0),o&&d.progressLine("OpenAPI document load complete.")}catch(a){throw d.error(`Error during parsing OpenAPI schema: ${a instanceof Error?a.message:String(a)}`),a}if(typeof i!="object"||!i.paths)throw new Error("Invalid OpenAPI schema: Missing 'paths'");try{s=ns(i),n=r.rename||dr(e);let a=ve(n);await I.remove(a);let p=v(n);await I.ensureDir(p);let c=oe(n);if(await I.writeJson(c,i,{spaces:2}),!r.dereference){let g=Tt(n);await I.writeJson(g,i?.components??{},{spaces:2})}let u=[],m=0,f=0,l=r.progress!==!1&&H;for(let[g,b]of Object.entries(i.paths))for(let[T,h]of Object.entries(b))h&&typeof h=="object"&&"operationId"in h&&h.operationId&&(m+=1);for(let[g,b]of Object.entries(i.paths))for(let[T,h]of Object.entries(b))if(h&&typeof h=="object"&&"operationId"in h){let y=h;if(y.operationId){let A={operationId:y.operationId,sanitizedOperationId:se(y.operationId),method:T,path:g};if(Array.isArray(y.tags)){let P=y.tags.map(O=>typeof O=="string"?O.trim():"").filter(O=>O.length>0);P.length>0&&(A.tags=P)}y.summary!==void 0&&(A.summary=y.summary),y.description!==void 0&&(A.description=y.description),u.push(A),f+=1,l&&d.progress(`\rProcessed ${f}/${m}`)}}l&&m>0&&d.progressLine("");try{let g=Y.join(a,"endpoints.json");await I.writeJson(g,u,{spaces:2})}catch(g){throw d.error(`Error writing endpoints.json: ${g instanceof Error?g.message:String(g)}`),g}try{await Te(n,{baseUrl:t,openapiSource:e,schemaType:"openapi",version:s});let g=t?"with baseUrl":"without baseUrl";d.info(`Schema '${n}' added to config.json ${g} and openapiSource recorded.`)}catch(g){throw d.error(`Error updating config.json: ${g instanceof Error?g.message:String(g)}`),g}}catch(a){throw d.error(`Error during OpenAPI schema processing: ${a instanceof Error?a.message:String(a)}`),a}return n}async function is(e,t,r={},n){let s="",i=r.progress!==!1&&H,o=n??await He(e);if(!We(o))throw new Error("Invalid GraphQL schema: missing GraphQL schema markers or builder pattern.");i&&d.progressLine(`Loading GraphQL schema from ${e}...`),s=r.rename||dr(e);let a=ve(s);await I.remove(a);let p=v(s);await I.ensureDir(p);let c=await Ye(o,e);if(c.length===0)throw new Error("Invalid GraphQL schema: no query, mutation, or subscription fields were found.");let u=oe(s);await I.writeJson(u,{schemaType:"graphql",source:o},{spaces:2});let m=c.map(f=>({name:f.name,sanitizedOperationId:f.sanitizedOperationId,rootType:f.rootType,summary:f.summary,description:f.description}));for(let f of c){let l=ae(s,f.sanitizedOperationId);await I.ensureDir(Y.dirname(l)),await I.writeJson(l,f,{spaces:2})}await I.writeJson(Y.join(a,"endpoints.json"),m,{spaces:2});try{await Te(s,{baseUrl:t,openapiSource:e,schemaType:"graphql",version:"graphql"});let f=t?"with baseUrl":"without baseUrl";d.info(`Schema '${s}' added to config.json ${f} and GraphQL source recorded.`)}catch(f){throw d.error(`Error updating config.json: ${f instanceof Error?f.message:String(f)}`),f}return i&&d.progressLine("GraphQL schema load complete."),s}async function lr(e,t,r={}){let n=await He(e).catch(()=>{});return n&&We(n)?await is(e,t,r,n):await ss(e,t,r)}async function fr(e){try{let t=await He(e).catch(()=>{});if(t&&We(t)){await Ye(t,e);return}await xt.validate(e);return}catch(t){throw new Error(t instanceof Error?t.message:String(t))}}var ke=S(()=>{"use strict";Oe();de();K();be();mt()});function as(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function St(e){if(!(!e||typeof e!="object"))return as(e.schema)?e.schema:e}function mr(e){let t=St(e);switch(typeof t?.type=="string"?t.type:typeof e?.type=="string"?e.type:void 0){case"string":return"";case"number":case"integer":return 0;case"boolean":return!1;case"array":return[];case"object":return{};default:return null}}var Pt=S(()=>{"use strict"});import xe from"fs-extra";function it(e){return e.replace(/[^a-zA-Z0-9]+(.)/g,(t,r)=>r.toUpperCase()).replace(/^[a-z]/,t=>t.toUpperCase())}function Z(e,t,r){if(!(!e||typeof e!="object")){if(Array.isArray(e.enum)){let n=it(r);t[n]=e.enum}if(e.properties&&typeof e.properties=="object")for(let[n,s]of Object.entries(e.properties))Z(s,t,`${r}_${n}`);e.items&&Z(e.items,t,`${r}_item`),e.oneOf&&e.oneOf.forEach((n,s)=>Z(n,t,`${r}_oneOf_${s}`)),e.anyOf&&e.anyOf.forEach((n,s)=>Z(n,t,`${r}_anyOf_${s}`)),e.allOf&&e.allOf.forEach((n,s)=>Z(n,t,`${r}_allOf_${s}`))}}function ee(e){if(!(!e||typeof e!="object")){if(delete e.xml,e.properties&&typeof e.properties=="object")for(let t of Object.values(e.properties))ee(t);e.items&&ee(e.items),e.oneOf&&e.oneOf.forEach(ee),e.anyOf&&e.anyOf.forEach(ee),e.allOf&&e.allOf.forEach(ee)}}function gr(e){if(!e||typeof e!="object")return null;let r=Object.keys(e).filter(n=>/^\d{3}$/.test(n)).find(n=>n.startsWith("2"));return r?e[r]:null}function It(e){if(!e||typeof e!="object")return null;let t=Object.entries(e).find(([r])=>r.toLowerCase().includes("json"));return t?t[1]:null}function os(e){let t=gr(e);if(!t)return null;if(t.content){let r=It(t.content);return!r||!r.schema?null:r.schema}return t.schema??null}function ps(e){let t=gr(e);return t?t.schema??null:null}function cs(e){let t=Array.isArray(e?.parameters)?e.parameters:[],r=t.find(i=>i.in==="body");if(r?.schema)return r.schema;let n=t.filter(i=>i.in==="formData");if(n.length===0)return null;let s={type:"object",properties:{}};for(let i of n){let o={};i.schema&&typeof i.schema=="object"?Object.assign(o,i.schema):(typeof i.type=="string"&&(o.type=i.type),i.items&&(o.items=i.items),typeof i.format=="string"&&(o.format=i.format),Array.isArray(i.enum)&&(o.enum=i.enum),i.type==="file"&&(o.type="string",o.format="binary")),s.properties[i.name]=o}return s}function ds(e){let t={};if(!e||typeof e!="object")return t;for(let[r,n]of Object.entries(e)){if(!/^\d{3}$/.test(r)||r.startsWith("2"))continue;let s=n.content,i=s?It(s):null,o=i&&i.schema?i.schema:n.schema??us;t[r]=o}return t}function ls(e,t){let r={};for(let n of["path","query","header"])for(let[s,i]of Object.entries(e[n]||{}))r[s]={...i.schema,required:i.required??!1,description:i.description,in:n};return{typeName:`${it(t)}Params`,schema:r}}async function Ne(e,t,r,n=!1){let s=await U(),i=await xe.readJson(L(e)),o=Array.isArray(i)&&i.some(y=>typeof y?.rootType=="string");if(s.apis?.[e]?.schemaType==="graphql"||s.apis?.[e]?.schemaType!=="openapi"&&o){let y=i.find(E=>E.operationId===t||E.name===t);if(!y)throw new Error(`Endpoint with operationId '${t}' not found.`);let A=typeof y.rootType=="string"?y.rootType:typeof y.method=="string"?y.method:void 0;if(!A||A!=="query"&&A!=="mutation"&&A!=="subscription")throw new Error(`Invalid GraphQL endpoint metadata for '${t}'.`);let P=v(e)+`/${r}.json`,O;if(!n&&await xe.pathExists(P))O=await xe.readJson(P);else{let E=await xe.readJson(oe(e)),V=typeof E?.source=="string"?E.source:typeof E?.sourceText=="string"?E.sourceText:void 0;if(!V)throw new Error(`GraphQL source not found for API '${e}'. Run generate first.`);O=await ye(V,A,t),await xe.ensureDir(v(e)),await xe.writeJson(P,O,{spaces:2})}return{schemaType:"graphql",fieldName:y.name??t,rootType:A,args:Object.fromEntries(Object.entries(O.args??{}).map(([E,V])=>{let x=V;return[E,{type:x.typeName??"unknown",required:x.required===!0}]})),returnType:O.returns?.typeName??"unknown",query:Re(O).query}}let p=i.find(y=>y.operationId===t);if(!p)throw new Error(`Endpoint with operationId '${t}' not found.`);let c=await Q(e,t,r,n),u={path:{},query:{},header:{}};for(let y of c.parameters||[])(y.in==="path"||y.in==="query"||y.in==="header")&&(u[y.in][y.name]={description:y.description,required:y.required,schema:St(y)});let m=os(c.responses)??ps(c.responses),f={};m&&(ee(m),Z(m,f,`${t}_response`));let l=ls(u,t),g=ds(c.responses),b=null,T=c.requestBody;if(T&&T.content){let y=It(T.content);y&&y.schema&&(b=y.schema,ee(b),Z(b,f,`${t}_request`))}else b=cs(c),b&&(ee(b),Z(b,f,`${t}_request`));let h=it(t.replace(/^(get|post|put|delete|patch|head|options)/i,"")||t);return{schemaType:"rest",operationId:t,method:p.method,path:p.path,deprecated:p.deprecated??c.deprecated??!1,params:l,response:m?{typeName:h,schema:m}:null,requestBody:b?{typeName:`${it(t)}Request`,schema:b}:null,errors:g,enums:f}}var us,Rt=S(()=>{"use strict";K();ke();Pt();Oe();de();us={type:"object",properties:{message:{type:"string"},status:{type:"number"}}}});var je,hr=S(()=>{"use strict";je=class{constructor(t){this.baseUrl=t}baseUrl;async request(t,r,n={}){if(!/^https?:\/\//i.test(this.baseUrl))throw new Error(`Invalid baseUrl: "${this.baseUrl}". Must include http:// or https://`);let s=this.baseUrl.endsWith("/")?this.baseUrl:this.baseUrl+"/",i=new URL(r.replace(/^\//,""),s).toString(),o="body"in n&&n.body!==void 0&&t!=="GET"&&t!=="HEAD",a=new Headers(n.headers??{}),p=null;if(o){let f=n.body,l=typeof FormData<"u"&&f instanceof FormData,g=typeof Blob<"u"&&f instanceof Blob,b=f instanceof ArrayBuffer||ArrayBuffer.isView(f),T=typeof Buffer<"u"&&Buffer.isBuffer(f);l?(a.delete("Content-Type"),p=f):g||b||T||typeof f=="string"?p=f:(a.has("Content-Type")||a.set("Content-Type","application/json"),p=JSON.stringify(f))}let c=await fetch(i,{method:t,headers:a,body:p}),u=await c.text(),m={};if(u.trim().length>0)try{m=JSON.parse(u)}catch{m=u}return m!==null&&typeof m=="object"&&!Array.isArray(m)?{...m,status:c.status,statusText:c.statusText}:{body:m,status:c.status,statusText:c.statusText}}get(t,r){return this.request("GET",t,r)}head(t,r){return this.request("HEAD",t,r)}options(t,r){return this.request("OPTIONS",t,r)}post(t,r){return this.request("POST",t,r)}put(t,r){return this.request("PUT",t,r)}patch(t,r){return this.request("PATCH",t,r)}delete(t,r){return this.request("DELETE",t,r)}}});import fs from"fs-extra";function yr(e){return{orGroups:e.trim().toLowerCase().split("|").map(r=>r.trim()).filter(Boolean).map(r=>r.split(/\s+/).filter(Boolean))}}function ms(e,t){return t.orGroups.length===0?!0:t.orGroups.some(r=>r.every(n=>e.includes(n)))}function gs(e){return e.split("/").map(t=>t.trim().toLowerCase()).filter(Boolean).flatMap(t=>{if(t.startsWith("{")&&t.endsWith("}")){let r=t.slice(1,-1).trim();return r?[t,r]:[t]}return[t]})}function hs(e,t){return t?t===":param"?/\{[^/{}]+\}/.test(e):t.startsWith("/")?e.startsWith(t):gs(e).includes(t):!0}function ys(e,t){return yr(t).orGroups.some(n=>n.every(s=>hs(e,s)))}function ws(e){return e?(Array.isArray(e)?e:[e]).map(t=>t.trim()).filter(Boolean):[]}function bs(e,t){if(typeof t!="string"||t.trim().length===0||t.trim()===":")return e;let r=t.trim(),n=r.match(/^-?\d+$/),s=r.match(/^(-?\d*)?:(-?\d*)?$/),i,o;if(n)i=Number(r),o=i;else if(s){let f=s[1],l=s[2];i=f===void 0||f===""?0:Number(f),o=l===void 0||l===""?e.length-1:Number(l)}else throw new Error(`Invalid --index value: ${t}`);if(Number.isNaN(i)||Number.isNaN(o))throw new Error(`Invalid --index value: ${t}`);let a=f=>f<0?e.length+f:f,p=a(i),c=a(o);if(e.length===0)return[];let u=Math.max(0,p),m=Math.min(e.length-1,c);return u>m?[]:e.slice(u,m+1)}function wr(e,t){return bs(e,t)}function at(e,t){let r=e;if(t.operationId){let s=t.operationId.toLowerCase();r=r.filter(i=>(i.operationId||"").toLowerCase()===s)}if(t.method){let s=t.method.toLowerCase();r=r.filter(i=>(i.method||"").toLowerCase()===s)}if(t.rootType){let s=t.rootType.toLowerCase();r=r.filter(i=>(i.rootType||"").toLowerCase()===s)}if(t.tag){let s=t.tag.toLowerCase();r=r.filter(i=>(Array.isArray(i.tags)?i.tags:[]).some(a=>typeof a=="string"&&a.toLowerCase()===s))}let n=ws(t.path);if(n.length>0&&(r=r.filter(s=>{let i=(s.path||"").toString().toLowerCase();return n.every(o=>ys(i,o))})),t.filter){let s=yr(t.filter);r=r.filter(i=>{let o=[i.operationId,i.name,i.method,i.rootType,i.path,i.summary,i.description].map(a=>(a||"").toString().toLowerCase()).join(" ");return ms(o,s)})}return r}async function As(e){let t=v(e);try{let r=await fs.readdir(t,{withFileTypes:!0});return new Set(r.filter(n=>n.isFile()&&n.name.toLowerCase().endsWith(".json")).map(n=>n.name.slice(0,-5)))}catch(r){if(r?.code==="ENOENT")return new Set;throw r}}async function br(e,t){let r=await As(e);return r.size===0?[]:t.filter(n=>{let s=typeof n.sanitizedOperationId=="string"?n.sanitizedOperationId:"";return r.has(s)})}var Ot=S(()=>{"use strict";K()});async function X(e,t){let r={operationId:t},n=await ur(e),s=at(n,r)[0]??n.find(i=>i.name===t);return s?.sanitizedOperationId??s?.operationId??s?.name??""}var le,ot=S(()=>{"use strict";de();Ot();le=X});function Ts(e){return e.replace(/\[(\d+)\]/g,".$1").split(".").filter(r=>r.length>0).map(r=>/^\d+$/.test(r)?Number(r):r)}function _e(e,t){let r=e;for(let n of Ts(t)){if(r==null)return;if(typeof n=="number"){if(!Array.isArray(r)&&typeof r!="object")return;r=r[n];continue}if(typeof r!="object")return;r=r[n]}return r}function Ar(e,t,r){return Array.isArray(e)?e.filter(n=>String(_e(n,t))===String(r)):e}var qt=S(()=>{"use strict"});function N(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ks(e){let t=e.requestBody;if(N(t)&&N(t.content)){for(let a of Object.values(t.content))if(N(a)&&a.schema)return a.schema}let r=Array.isArray(e.parameters)?e.parameters:[],n=r.find(a=>N(a)&&a.in==="body");if(N(n)&&n.schema)return n.schema;let s=r.filter(a=>N(a)&&a.in==="formData");if(s.length===0)return;let i={},o=[];for(let a of s)!N(a)||typeof a.name!="string"||(i[a.name]=N(a.schema)?a.schema:Object.fromEntries(["type","items","format","enum"].filter(p=>a[p]!==void 0).map(p=>[p,a[p]])),a.required===!0&&o.push(a.name));return{type:"object",properties:i,...o.length>0?{required:o}:{}}}function xs(e){let t=[],r=new Set,n=!1,s=i=>{if(!N(i)){n=!0;return}if(r.has(i)){n=!0;return}if("$ref"in i||"oneOf"in i||"anyOf"in i||"not"in i){n=!0;return}if(r.add(i),t.push(i),Array.isArray(i.allOf))for(let o of i.allOf)s(o);r.delete(i)};for(let i of e)s(i);return{schemas:t,ambiguous:n}}function vt(e,t){let r=xs(t);if(r.ambiguous)return!1;let n=r.schemas;if(Array.isArray(e)){let a=n.map(p=>p.items).filter(p=>N(p));return a.length===0?!1:e.reduce((p,c)=>vt(c,a)||p,!1)}if(!N(e))return!1;let s=new Set(n.flatMap(a=>Array.isArray(a.required)?a.required.filter(p=>typeof p=="string"):[])),i=new Map;for(let a of n)if(N(a.properties))for(let[p,c]of Object.entries(a.properties)){let u=i.get(p)??[];u.push(c),i.set(p,u)}let o=!1;for(let[a,p]of Object.entries(e)){let c=i.get(a);if(c){if(p===""&&!s.has(a)){delete e[a],o=!0;continue}o=vt(p,c)||o}}return o}function kr(e,t){if(!N(e)||!N(t))return!1;let r=!1;if(Array.isArray(e.parameters)&&Array.isArray(t.parameters)){let s=t.parameters.filter(N),i=e.parameters.filter(o=>{if(!N(o)||o.value!==""||!["path","query","header"].includes(String(o.in)))return!0;let a=s.find(p=>p.name===o.name&&p.in===o.in);return!a||o.in==="path"||a.required===!0?!0:(r=!0,!1)});r&&(e.parameters=i)}let n=ks(t);return n&&"requestBody"in e&&(r=vt(e.requestBody,[n])||r),r}function Tr(e){let t=e;for(;t&&t.kind==="non-null"&&t.ofType;)t=t.ofType;return t}function Es(e){if(!e)return!1;let t=e;for(;t;){if(t.defaultValue!==void 0)return!1;t=t.ofType}return e.required===!0||e.kind==="non-null"||e.typeName.trim().endsWith("!")}function xr(e,t){if(Array.isArray(e)){let n=Tr(t);return n?.kind!=="list"||!n.ofType?!1:e.reduce((s,i)=>xr(i,n.ofType)||s,!1)}if(!N(e))return!1;let r=Tr(t);return r?.kind!=="input-object"||!r.fields?!1:Er(e,r.fields)}function Er(e,t){let r=!1;for(let[n,s]of Object.entries(e)){let i=t[n];if(i){if(s===""&&!Es(i)){delete e[n],r=!0;continue}r=xr(s,i)||r}}return r}function Sr(e,t){return!N(e)||!N(e.variables)?!1:Er(e.variables,t.args)}var Pr=S(()=>{"use strict"});import k from"fs-extra";import R from"path";import Ss from"ajv";import{fileURLToPath as Ps}from"url";function Le(e,t="",r={}){if(!e||typeof e!="object"||Array.isArray(e))return r;for(let[n,s]of Object.entries(e)){let i=t?`${t}.${n}`:n;s&&typeof s=="object"&&!Array.isArray(s)?Le(s,i,r):r[i]=s}return r}function vr(e,t=""){if(!e||typeof e!="object"||Array.isArray(e))return[];let r=[];for(let[n,s]of Object.entries(e)){let i=t?`${t}.${n}`:n;s&&typeof s=="object"&&!Array.isArray(s)&&(r.push(i),r.push(...vr(s,i)))}return Array.from(new Set(r))}function Is(e){let t=vr(e);if(t.length===0)return;let r=Le(e);return["Use only flattened object dot-notation keys with --force.",`Example: --force --update-request '${JSON.stringify(r)}'.`,`Detected nested keys: ${t.join(", ")}.`].join(" ")}function Ir(e){return e===null?"null":Nr(e)?"file":Array.isArray(e)?"array":typeof e}function Nr(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&e.kind==="file"}function Ct(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&typeof e.path=="string"&&(e.kind===void 0||e.kind==="file")}function Rs(e,t){return Nr(e)?typeof t=="string"||Ct(t):e===null?t===null:Array.isArray(e)?Array.isArray(t):typeof e=="object"?!!t&&typeof t=="object"&&!Array.isArray(t):typeof t==typeof e}function jr(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&typeof e.query=="string"&&typeof e.variables=="object"&&!Array.isArray(e.variables)}function _r(e){if(e)return e.split(",")[0]?.trim()||void 0}function Os(e){switch(R.extname(e).toLowerCase()){case".pdf":return"application/pdf";case".jpg":case".jpeg":return"image/jpeg";case".png":return"image/png";case".webp":return"image/webp";case".gif":return"image/gif";case".txt":return"text/plain";case".csv":return"text/csv";case".json":return"application/json";case".xml":return"application/xml";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";case".xls":return"application/vnd.ms-excel";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".zip":return"application/zip";default:return"application/octet-stream"}}function Rr(e){let t=e.trim();return t.startsWith("@")?R.resolve(t.slice(1)):t.startsWith("file://")?R.resolve(Ps(new URL(t))):R.resolve(t)}async function Nt(e,t){let r,n,s;if(typeof e=="string"){if(e.trim().length===0)throw new Error("File upload path cannot be empty.");r=Rr(e)}else if(Ct(e)){if(e.path.trim().length===0)throw new Error("File upload path cannot be empty.");r=Rr(e.path),n=e.fileName?.trim()||void 0,s=e.mimeType?.trim()||void 0}if(!r)throw new Error("File upload values must be a file path string or { kind: 'file', path, fileName?, mimeType? } object.");if(!await k.pathExists(r))throw new Error(`Upload file not found: ${r}`);let i=await k.readFile(r),o=n||R.basename(r),a=s||_r(t)||Os(r);return{buffer:i,path:r,fileName:o,mimeType:a}}function Or(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}function qs(e){let t=Object.entries(e),r=t.find(([o])=>o.toLowerCase().includes("multipart/form-data"));if(r)return{contentType:r[0],contentObject:r[1]};let n=t.find(([o,a])=>{let p=a?.schema;return o.toLowerCase().includes("octet-stream")||p?.type==="string"&&p?.format==="binary"});if(n)return{contentType:n[0],contentObject:n[1]};let s=t.find(([o])=>o.toLowerCase().includes("json"));if(s)return{contentType:s[0],contentObject:s[1]};let i=t[0];return i?{contentType:i[0],contentObject:i[1]}:void 0}function vs(e){let t=e?.requestBody,n=(Array.isArray(e?.parameters)?e.parameters:[]).filter(a=>a&&a.in==="formData"),i=(Array.isArray(e?.consumes)?e.consumes:[]).some(a=>typeof a=="string"&&a.toLowerCase().includes("multipart/form-data"));if(n.length>0&&i)return{kind:"multipart",schema:_t(e)??{type:"object",properties:{}},encoding:{}};if(!t||typeof t!="object")return n.length>0?{kind:"multipart",schema:_t(e)??{type:"object",properties:{}},encoding:{}}:{kind:"json"};let o=t.content;if(o&&typeof o=="object"&&!Array.isArray(o)){let a=qs(o);if(!a)return{kind:"json"};let p=a.contentObject,c=p?.schema;if(a.contentType.toLowerCase().includes("multipart/form-data"))return{kind:"multipart",schema:c&&typeof c=="object"?c:{type:"object",properties:{}},encoding:p?.encoding??{}};if(a.contentType.toLowerCase().includes("octet-stream")||c?.type==="string"&&c?.format==="binary")return{kind:"binary",contentType:a.contentType}}return{kind:"json"}}async function jt(e,t){let r=vs(e);if(r.kind==="multipart"){let o=t,a=!!o&&typeof o=="object"&&!Array.isArray(o)&&("requestBody"in o||"parameters"in o),p=a?o.requestBody:t,c=a&&Array.isArray(o?.parameters)?Object.fromEntries(o.parameters.filter(l=>!!l&&l.in==="formData"&&typeof l.name=="string").map(l=>[l.name,l.value])):{},u=p&&typeof p=="object"&&!Array.isArray(p)?p:c;if(!u||typeof u!="object"||Array.isArray(u))throw new Error("multipart/form-data request bodies must be JSON objects.");let m=new FormData,f=r.schema?.properties&&typeof r.schema.properties=="object"?r.schema.properties:{};for(let[l,g]of Object.entries(u)){let b=f[l],T=r.encoding[l],h=_r(T?.contentType);if(b?.type==="string"&&b?.format==="binary"){let y=await Nt(g,h);m.append(l,new Blob([Or(y.buffer)],{type:y.mimeType}),y.fileName);continue}if(Ct(g)){let y=await Nt(g,h);m.append(l,new Blob([Or(y.buffer)],{type:y.mimeType}),y.fileName);continue}g==null?m.append(l,""):typeof g=="object"?m.append(l,JSON.stringify(g)):m.append(l,String(g))}return{kind:"multipart",body:m,headers:{}}}if(r.kind==="binary"){let o=t,p=!!o&&typeof o=="object"&&!Array.isArray(o)&&"requestBody"in o?o.requestBody:t,c=await Nt(p,r.contentType);return{kind:"binary",body:c.buffer,headers:{"Content-Type":c.mimeType}}}let n=t;return{kind:"json",body:!!n&&typeof n=="object"&&!Array.isArray(n)&&"requestBody"in n?n.requestBody:t,headers:{}}}function Ns(e){let t={};for(let[r,n]of Object.entries(e)){let s=n.type.trim(),i=s.endsWith("!")?s.slice(0,-1).trim():s;i.startsWith("[")&&i.endsWith("]")?t[r]=[]:i==="Boolean"?t[r]=!1:i==="Int"||i==="Float"?t[r]=0:t[r]=""}return t}async function $t(e){let r=(await U()).apis?.[e]?.schemaType;if(r==="graphql")return"graphql";if(r==="openapi")return"openapi";try{let n=await k.readJson(L(e));if(Array.isArray(n)&&n.some(s=>typeof s?.rootType=="string"))return"graphql"}catch{}return"openapi"}async function js(e){let t=R.join(R.dirname(v(e)),"bundled.json"),r=await k.readJson(t),n=typeof r?.source=="string"?r.source:typeof r?.sourceText=="string"?r.sourceText:void 0;if(!n)throw new Error(`GraphQL source not found for API '${e}'. Run generate first.`);return n}async function Dt(e,t,r=!1){let n=await le(e,t),s=ae(e,n);if(!r&&await k.pathExists(s))return await k.readJson(s);let o=(await k.readJson(L(e))).find(u=>u.operationId===t||u.name===t);if(!o)throw new Error(`Endpoint '${t}' not found in GraphQL endpoint list.`);let a=await js(e),p=typeof o.rootType=="string"?o.rootType:typeof o.method=="string"?o.method:void 0;if(!p||p!=="query"&&p!=="mutation"&&p!=="subscription")throw new Error(`Invalid GraphQL endpoint metadata for '${t}'.`);let c=await ye(a,p,t);return await k.ensureDir(R.dirname(s)),await k.writeJson(s,c,{spaces:2}),c}async function Ft(e){return await $t(e)}function Jt(e,t){let r=Le(t),n=[];for(let[s,i]of Object.entries(r)){if(i===et)continue;let o=_e(e,s);o!==void 0&&(Rs(o,i)||n.push(`--update-request type mismatch at ${s}: expected ${Ir(o)}, received ${Ir(i)}.`))}return n}async function Ut(e,t){if(await Ft(e)==="graphql"){let p=await le(e,t),c=R.join(pe(e,p),"response-schema.json");if(await k.pathExists(c))return await k.readJson(c);let u=await Dt(e,t,!1);return await k.ensureDir(R.dirname(c)),await k.writeJson(c,u,{spaces:2}),u}let r=await le(e,t),n=v(e),s=await ar(R.resolve(n,`${r}.json`)),i=pe(e,r),o=R.join(i,"response-schema.json");if(await k.pathExists(o))return await k.readJson(o);let a=Qs(s);return a!==void 0&&(await k.ensureDir(i),await k.writeJson(o,a,{spaces:2})),a}async function Gt(e,t,r=!1,n,s,i,o=!1,a=!1){let p=await Ne(e,t,await le(e,t),r),c=await U(),u=c.apis?.[e]?.baseUrl;if(!u)throw new Error("Base URL not found in config");if(p.schemaType==="graphql"){let x=await le(e,t),D=await Dt(e,t,r),{requestJson:ne,responseJsonPath:me}=await _s(e,x,r||a,D),Fe=R.join(v(e),x,"request.json"),dt=ne,Vt=[];if(i&&i.length>0&&Vt.push(...i),s&&typeof s=="object"&&Object.keys(s).length>0||o){let ft={...s?Le(s):{}};for(let[Je,ln]of Object.entries(s??{}))Je in ft||(ft[Je]=ln);await qe(Fe,ft,2,{deleteSentinel:et,transform:o?Je=>Sr(Je,D):void 0}),dt=await k.readJson(Fe)}let cn={...Ns(p.args),...jr(dt)?dt.variables:{}},lt={query:p.query,variables:cn},F={headers:{"Content-Type":"application/json"},url:"",warnings:Vt,responseJsonPath:me},un=new je(u),_;try{if(_=await un.post(u,{headers:F.headers,body:lt}),_&&typeof _=="object"&&"status"in _){let z=_.status;typeof z=="number"&&(z<200||z>=300)&&F.warnings.push(`\u26A0\uFE0F The live HTTP request failed for ${u}: HTTP ${z}${"statusText"in _&&typeof _.statusText=="string"&&_.statusText?` ${_.statusText}`:""}`)}_&&typeof _=="object"&&Array.isArray(_.errors)&&_.errors?.length&&F.warnings.push("\u26A0\uFE0F GraphQL response contains errors."),await k.writeJson(F.responseJsonPath,_,{spaces:2})}catch(z){if(F.warnings.push(`\u26A0\uFE0F The live HTTP request failed for ${u}: ${z instanceof Error?z.message:String(z)}`),!await k.pathExists(F.responseJsonPath))return F.warnings.push(`response.json not found at ${F.responseJsonPath}`),{request:lt,response:void 0,warnings:F.warnings}}let dn=await k.readJson(F.responseJsonPath);return{request:lt,response:dn?.data?.[p.fieldName],warnings:F.warnings}}let m=await le(e,t),f=await Ne(e,t,m);if(f.schemaType!=="rest")throw new Error(`Invalid REST endpoint metadata for '${t}'.`);let l=await Q(e,t,m,r),{requestJson:g,responseJsonPath:b}=await Cr(e,m,r||a),T=R.join(v(e),m,"request.json"),h=g,y=[];if(i&&i.length>0&&y.push(...i),s&&typeof s=="object"&&Object.keys(s).length>0||o){let x=s?Is(s):void 0;x&&y.push(x);let ne={...s?Le(s):{}};for(let[me,Fe]of Object.entries(s??{}))me in ne||(ne[me]=Fe);await qe(T,ne,2,{deleteSentinel:et,transform:o?me=>kr(me,l):void 0}),h=await k.readJson(T)}let A=Cs(e,f,h,c,b,n,y),P=new je(u);if(!f.method||!f.path)throw new Error(`Invalid OpenAPI endpoint metadata for '${t}'.`);let O=f.method.toLowerCase(),E;try{switch(O){case"get":E=await P.get(A.url,{headers:A.headers});break;case"post":{let x=await jt(l,h);E=await P.post(A.url,{headers:{...A.headers,...x.headers},body:x.body})}break;case"put":{let x=await jt(l,h);E=await P.put(A.url,{headers:{...A.headers,...x.headers},body:x.body})}break;case"delete":E=await P.delete(A.url,{headers:A.headers});break;case"patch":{let x=await jt(l,h);E=await P.patch(A.url,{headers:{...A.headers,...x.headers},body:x.body})}break;case"head":E=await P.head(A.url,{headers:A.headers});break;case"options":E=await P.options(A.url,{headers:A.headers});break;default:throw new Error(`Unsupported HTTP method: ${f.method}`)}if(E&&typeof E=="object"&&"status"in E){let x=E.status;typeof x=="number"&&(x<200||x>=300)&&A.warnings.push(`\u26A0\uFE0F The live HTTP request failed for ${u}${A.url}: HTTP ${x}${"statusText"in E&&typeof E.statusText=="string"&&E.statusText?` ${E.statusText}`:""}`)}await k.writeJson(A.responseJsonPath,E,{spaces:2})}catch(x){if(A.warnings.push(`\u26A0\uFE0F The live HTTP request failed for ${u}${A.url}: ${x instanceof Error?x.message:String(x)}`),!await k.pathExists(A.responseJsonPath))return A.warnings.push(`response.json not found at ${A.responseJsonPath}`),{request:h,response:void 0,warnings:A.warnings}}let V=await k.readJson(A.responseJsonPath);return{request:h,response:V,warnings:A.warnings}}async function Lr(e,t,r=!1,n,s,i,o=!1,a=!1){let{request:p,response:c,warnings:u}=await Gt(e,t,r,n,s,i,o,a),m=u??[];if(await Ft(e)==="graphql"){if(!c||typeof c!="object")return{valid:!1,warnings:m,errors:["response.body missing or invalid"]};let T=c;return Array.isArray(T.errors)&&T.errors.length>0?{valid:!1,warnings:m,errors:["GraphQL response contains errors"]}:{valid:!0,warnings:m}}let f=await Ut(e,t);if(f===void 0||Object.keys(f).length===0)return u.push("No response schema found for this operation. Skipping validation."),{valid:!0,warnings:m};if(!c)return{valid:!1,warnings:m};let g=new Ss({allErrors:!0,strict:!1,strictSchema:!1,allowUnknownKeywords:!0,removeAdditional:!1}).compile(f);return g(c)?{valid:!0,warnings:m}:{valid:!1,errors:(g.errors||[]).map(h=>`${h.instancePath?h.instancePath.replace(/^\//,"response.body.").replace(/\//g,"."):"response.body"} ${h.message}`),warnings:m}}async function Ce(e,t,r=!1,n=!1){if(await Ft(e)==="graphql"){let a=await Dt(e,t,r),p=R.join(v(e),t,"request.json"),c=R.join(pe(e,t),"response.json"),u=Re(a);return await k.ensureDir(R.dirname(p)),await k.writeJson(p,u,{spaces:2}),{requestJsonPath:p,responseJsonPath:c,requestJson:u}}let{requestJson:s,responseJsonPath:i}=await Cr(e,t,r||n);return{requestJsonPath:R.join(v(e),t,"request.json"),responseJsonPath:i,requestJson:s}}async function Cr(e,t,r){let n=ae(e,t),s=await k.readJson(n),i=R.join(v(e),t);await k.ensureDir(i);let o=R.join(i,"request.json"),a=R.join(i,"response.json");if(await(async()=>{if(r||!await k.pathExists(o))return!0;let c=await k.readJson(o);return!Ls(c)})()){let c=Ds(s);return await k.writeJson(o,c,{spaces:2}),{requestJson:c,responseJsonPath:a}}return{requestJson:await k.readJson(o),responseJsonPath:a}}async function _s(e,t,r,n){let s=R.join(v(e),t);await k.ensureDir(s);let i=R.join(s,"request.json"),o=R.join(s,"response.json");if(await(async()=>{if(r||!await k.pathExists(i))return!0;let p=await k.readJson(i);return!jr(p)})()){let p=Re(n);return await k.writeJson(i,p,{spaces:2}),{requestJson:p,responseJsonPath:o}}return{requestJson:await k.readJson(i),responseJsonPath:o}}function Ls(e){if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e;return Object.prototype.hasOwnProperty.call(t,"parameters")&&Array.isArray(t.parameters)}function Cs(e,t,r,n,s,i,o=[]){let a={},p=n.apis?.[e]?.auth?.headers;p&&typeof p=="object"&&Object.assign(a,p),i&&typeof i=="object"&&Object.assign(a,i);let c={},u={};for(let l of r.parameters||[])l.in==="path"?c[l.name]=l.value:l.in==="query"?u[l.name]=l.value:l.in==="header"&&(a[l.name]=String(l.value));if(!t.path)throw new Error(`Invalid OpenAPI endpoint metadata for '${t.operationId}'.`);let m=Fs(t.path,c),f=$s(u);return{headers:a,url:m+f,warnings:o,responseJsonPath:s}}function $s(e){return Object.keys(e).length?"?"+Object.entries(e).map(([t,r])=>`${encodeURIComponent(t)}=${encodeURIComponent(String(r))}`).join("&"):""}function Ds(e){let t=[];if(Array.isArray(e.parameters))for(let s of e.parameters){let i=mr(s);t.push({name:s.name,in:s.in,value:i})}let r=null;(e?.requestBody||e?.parameters)&&(r=Js(e));let n={parameters:t};return r!==null&&(n.requestBody=r),n}function Fs(e,t){return e.replace(/\{([^}]+)\}/g,(r,n)=>{if(!(n in t))throw new Error(`Missing path parameter: ${n}`);return encodeURIComponent(t[n])})}function Js(e){let t=Us(e);if(t)return Ee(t);let r=_t(e);return r?Ee(r):null}function Us(e){let t=e?.requestBody?.content;if(!t||typeof t!="object")return null;for(let r of Object.values(t)){let n=r;if(n?.schema)return n.schema}return null}function _t(e){let t=Array.isArray(e?.parameters)?e.parameters:[],r=t.find(o=>o.in==="body");if(r?.schema){let o=r.schema;return!o.type&&o.properties&&(o.type="object"),o}let n=e?.consumes||[],s=n.includes("application/x-www-form-urlencoded")||n.includes("multipart/form-data"),i=t.filter(o=>o.in==="formData");if(s&&i.length){let o={type:"object",properties:{},required:[]};for(let a of i){let p={};a.schema?Object.assign(p,a.schema):(a.type&&(p.type=a.type),a.items&&(p.items=a.items),a.format&&(p.format=a.format),a.enum&&(p.enum=a.enum),a.type==="file"&&(p.type="string",p.format="binary")),o.properties[a.name]=p,a.required&&o.required.push(a.name)}return o.required.length===0&&delete o.required,o}return null}function Ee(e){if(!e)return null;if(e.const!==void 0)return e.const;if(e.default!==void 0)return e.default;if(Array.isArray(e.allOf)&&e.allOf.length>0){let t=e.allOf.map(r=>Ee(r)).filter(r=>r!=null).reduce((r,n)=>$r(r,n),{});if(t!=null)return t}if(Array.isArray(e.oneOf)&&e.oneOf.length>0)return qr(e.oneOf.map(t=>Ee(t)));if(Array.isArray(e.anyOf)&&e.anyOf.length>0)return qr(e.anyOf.map(t=>Ee(t)));if(!e.type&&e.properties&&(e.type="object"),e.$ref)throw new Error("Schema contains $ref. Resolve references before building template.");switch(e.type){case"string":return e.format==="binary"?{kind:"file",path:"",fileName:"",mimeType:""}:e.example??"";case"integer":case"number":return e.example??0;case"boolean":return e.example??!1;case"array":return[];case"object":let t={};if(e.properties)for(let[r,n]of Object.entries(e.properties))t[r]=Ee(n);return t;default:return null}}function Lt(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function $r(e,t){if(e==null)return t;if(t==null)return e;if(Lt(e)&&Lt(t)){let r={...e};for(let[n,s]of Object.entries(t))r[n]=n in r?$r(r[n],s):s;return r}return t}function qr(e){let t=e.filter(n=>n!=null);if(t.length===0)return null;let r=t.filter(Lt);return r.length>0?r.reduce((n,s)=>{let i=Object.keys(n).length;return Object.keys(s).length>i?s:n}):t[0]}function Gs(e){let t=e?.responses;if(!t)return null;let r=t[200]||t[201]||t.default||Object.values(t)[0];if(!r?.content)return null;let n=r.content["application/json"];if(n?.schema)return n.schema;for(let s of Object.values(r.content)){let i=s;if(i.schema)return i.schema}return null}function Bs(e){let t=e?.responses;return t?(t[200]||t[201]||t.default||Object.values(t)[0])?.schema||{}:{}}function Qs(e){let t=Gs(e);if(t)return t;let r=Bs(e);if(r)return r}var Bt=S(()=>{"use strict";hr();K();Rt();At();de();ot();Pt();qt();Oe();K();ke();Pr()});import*as te from"node:fs/promises";import $ from"path";import Ms from"readline";import{fileURLToPath as Vs}from"url";function Se(e){return e?"Yes":"No"}function Hs(e){return Array.isArray(e)?e.join(`
|
|
9
|
+
`):e}function Ws(e){let t=e.arguments.length>0?e.arguments.map(s=>{let i=[s.type,s.required?"required":"optional"];s.positional&&i.push("positional"),s.flag&&i.push("flag");let o=s.description?`: ${s.description}`:"",a=s.flag?"--":"";return`- \`${s.positional?s.name:`${a}${s.name}`}\` (${i.join(", ")})${o}`}).join(`
|
|
10
|
+
`):"- None",r=e.examples.length>0?e.examples.map(s=>`- \`\`\`bash
|
|
11
|
+
${s}
|
|
12
|
+
\`\`\``).join(`
|
|
13
|
+
`):"- None",n=e.filesWritten.length>0?e.filesWritten.map(s=>`\`${s}\``).join(", "):"None";return[`### ${e.name}`,"",`**Category:** ${e.category}`,"","**Usage:**","```bash",e.usage,"```","",`**Description:** ${Hs(e.description)}`,"","**Arguments:**",t,"","**Examples:**",r,"",`**Returns:** ${e.returns.type} - ${e.returns.description}`,"",`**Side Effects:** Writes Files: ${Se(e.sideEffects.writesFiles)}, Reads Files: ${Se(e.sideEffects.readsFiles)}, Network: ${Se(e.sideEffects.network)}`,"",`**Constraints:** Destructive: ${Se(e.constraints.destructive)}, Idempotent: ${Se(e.constraints.idempotent)}, Requires Parsed API: ${Se(e.constraints.requiresParsedApi)}`,"",`**Files Written:** ${n}`].join(`
|
|
14
|
+
`)}async function Ks(){let{program:e}=await Br().then(()=>Gr);return e.commands.filter(n=>!!n.agentMeta).filter(n=>n.agentMeta.name!=="help"&&n.agentMeta.name!=="install").map(n=>Ws(n.agentMeta)).join(`
|
|
15
|
+
|
|
16
|
+
`)}async function Fr(e,t){let r=[{label:"~/.claude/skills/openapi-skills",value:$.join(e,".claude","skills","openapi-skills")},{label:"~/.cursor/skills/openapi-skills",value:$.join(e,".cursor","skills","openapi-skills")},{label:"~/.agents/skills/openapi-skills",value:$.join(e,".agents","skills","openapi-skills")},{label:"~/.github/skills/openapi-skills",value:$.join(e,".github","skills","openapi-skills")},{label:"Other (enter a custom path)",value:"__custom__"}];function n(i){let o=Ms.createInterface({input:process.stdin,output:process.stderr});return new Promise(a=>o.question(i,p=>{o.close(),a(p)}))}d.info("Select install location:"),r.forEach((i,o)=>{d.info(` ${o+1}) ${i.label}`)});let s;for(;;){s=await n(`Enter number (1-${r.length}): `);let i=parseInt(s,10)-1;if(!isNaN(i)&&i>=0&&i<r.length&&r[i])return r[i].value==="__custom__"?(await n(`Enter custom install path [${t}]: `)).trim()||t:r[i].value;d.warn(`Invalid selection. Please enter a number between 1 and ${r.length}.`)}}async function Dr(e,t,r){let n=$.join(zs,"../skill-templates",e);try{let s=await te.readFile(n,"utf8"),i=r?await r(s):s;await te.mkdir($.dirname(t),{recursive:!0}),await te.writeFile(t,i,"utf8")}catch(s){let i=s instanceof Error?s.message:String(s);throw new Error(`Failed to copy skill template "${e}" from "${n}" to "${t}": ${i}`,{cause:s instanceof Error?s:void 0})}}async function Jr(e,t){await te.mkdir(t,{recursive:!0});let r=$.join(t,"references");await te.mkdir(r,{recursive:!0});let n=[{templateName:"SKILL.md",outputPath:$.join(t,"SKILL.md")},{templateName:"write-client-code.md",outputPath:$.join(r,"write-client-code.md")},{templateName:"create-endpoint-test.md",outputPath:$.join(r,"create-endpoint-test.md")},{templateName:"http-client.md",outputPath:$.join(r,"http-client.md")}];for(let s of n){if(s.templateName==="SKILL.md"){await Dr(s.templateName,s.outputPath,async i=>{let o=await Ks();if(!i.includes("<command-list-here>"))throw new Error("SKILL.md template is missing <command-list-here>.");return i.replace("<command-list-here>",o)});continue}await Dr(s.templateName,s.outputPath)}return{destDir:t,files:n.map(s=>s.outputPath)}}var zs,Ur=S(()=>{"use strict";be();zs=$.dirname(Vs(import.meta.url))});import Qr from"fs-extra";import Ys from"https";import Xs from"os";import Zs from"path";async function Mr(e){try{let t=new Date().toISOString().slice(0,10),r=Zs.join(Xs.tmpdir(),`openapi-skills-session-${t}`);if(Qr.existsSync(r))return;Qr.writeFileSync(r,String(Date.now()));let n=await new Promise((s,i)=>{Ys.get("https://registry.npmjs.org/@tzurp/openapi-skills/latest",o=>{let a="";o.on("data",p=>a+=p),o.on("end",()=>{try{let p=JSON.parse(a);s(p.version)}catch(p){i(p)}})}).on("error",i)});n&&n!==e&&(d.warn(`UPDATE_AVAILABLE: A newer version of openapi-skills is available \u2192 ${n} (current: ${e})`),d.warn("Update with: npm install -g @tzurp/openapi-skills")),d.banner(`\u{1F48E} openapi-skills v2 is available \u2014 including mock APIs, HTML docs, schema diffing, code\u2011first tools, full OpenAPI 3.1 support, premium support, and additional Pro tools.
|
|
17
|
+
https://openapi-skills.lemonsqueezy.com/`)}catch{}}var Vr=S(()=>{"use strict";be()});function $e(e){let t=JSON.stringify(e)??"",r=Buffer.byteLength(t,"utf8");return{text:t,sizeBytes:r}}var zr=S(()=>{"use strict"});import ei from"readline";async function Hr(e){let t=`Are you sure you want to delete ${e}? Y/n `;return await new Promise(r=>{let n=ei.createInterface({input:process.stdin,output:process.stderr});n.question(t,s=>{n.close();let i=s.trim().toLowerCase();r(i==="y"||i==="yes")})})}var Wr=S(()=>{"use strict"});function De(e,t="",r=new Set){if(t&&r.add(t),!e||typeof e!="object")return r;if(Array.isArray(e)){for(let n=0;n<e.length;n++){let s=t?`${t}.${n}`:`${n}`;De(e[n],s,r)}return r}for(let[n,s]of Object.entries(e)){let i=t?`${t}.${n}`:n;De(s,i,r)}return r}function pt(e,t="",r=new Set){if(!e||typeof e!="object")return r;if(Array.isArray(e))return t&&r.add(t),r;for(let[n,s]of Object.entries(e)){let i=t?`${t}.${n}`:n;s&&typeof s=="object"&&!Array.isArray(s)?pt(s,i,r):r.add(i)}return r}function Kr(e){let t=[];return e.request&&t.push("request"),e.response&&t.push("response"),e.responseSchema&&t.push("response-schema"),t.length!==1?{artifactName:void 0,error:t.length===0?"Exactly one of --request, --response, or --response-schema is required.":"Only one of --request, --response, or --response-schema can be used at a time."}:{artifactName:t[0],error:void 0}}var Yr=S(()=>{"use strict"});import Xr from"fs-extra";function ct(e,t){let r=pe(e,t);return{fileCount:Xr.existsSync(r)?Xr.readdirSync(r).length:0}}async function ti(e,t){let r=new Set,n=new Set;for(let o of t)r.has(o)&&n.add(o),r.add(o);if(n.size>0)throw new Error(`Duplicate operationId(s) are not allowed in prepare-only mode: ${Array.from(n).join(", ")}`);let s=await ue();if(!Array.isArray(s)||!s.includes(e))throw new Error(`API '${e}' is not installed. Run generate first.`);let i=[];for(let o of t){let a=await X(e,o);if(!a)throw new Error(`OperationId '${o}' was not found for API '${e}'.`);i.push({operationId:o,sanitizedOperationId:a})}return i}async function Zr(e,t,r=!1,n=!1){let s=await ti(e,t),i=[];for(let{operationId:p,sanitizedOperationId:c}of s){await Q(e,p,c),await Ce(e,c,r,n);let u=ct(e,c);i.push({kind:"request-result",apiName:e,operationId:p,sanitizedOperationId:c,preparedOnly:!0,request:null,response:null,warnings:[],...u})}let o=[`Prepared request templates for ${i.length} operations:`,"",...i.map(p=>` \u2713 ${p.operationId}`),"","No live requests were executed.","Use `openapi-skills request <operationId> --force-request --update-request ...` with only flattened object dot-notation keys to reset the request template from the cached schema and run each step."],a={kind:"request-result",apiName:e,preparedOnly:!0,operationIds:t,summary:o,message:"No live requests were executed.",hint:"Use `openapi-skills request <operationId> --force-request --update-request ...` with only flattened object dot-notation keys to reset the request template from the cached schema and run each step.",operations:i};return{operations:i,summaryText:o.join(`
|
|
18
|
+
`),payload:a}}var en=S(()=>{"use strict";ke();de();ot();K();Bt()});function tn(e){let t=e.trim();if(t==="count")return{kind:"count"};if(/^-?\d+$/.test(t))return{kind:"index",index:Number(t)};let r=t.match(/^(-?\d*):(-?\d*)$/);if(r)return{kind:"range",start:r[1]===""?0:Number(r[1]),end:r[2]===""?Number.POSITIVE_INFINITY:Number(r[2])};let n=t.indexOf("=");if(n>0){let s=t.slice(0,n).trim();if(s)return{kind:"path",path:s,value:t.slice(n+1)}}return{kind:"invalid"}}var rn=S(()=>{"use strict"});function ri(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ut(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`${t} must be a non-empty base64url string.`);let r;try{r=Buffer.from(e,"base64url").toString("utf8")}catch{throw new Error(`${t} must be valid base64url-encoded JSON.`)}let n;try{n=JSON.parse(r)}catch(s){let i=s instanceof Error?s.message:String(s);throw new Error(`${t} decoded value must be valid JSON: ${i}`)}if(!ri(n))throw new Error(`${t} decoded value must be a JSON object.`);return n}var nn=S(()=>{"use strict"});var sn,an,Qt=S(()=>{"use strict";sn={UNKNOWN_API:{reason:"The API name is not registered in .openapi-skills/config.json.",nextCommandHint:"Run 'openapi-skills get-api-names' to list available APIs, then use the correct name."},MISSING_PARSED_API:{reason:"No APIs have been parsed yet. The workspace is empty.",nextCommandHint:"Run 'openapi-skills generate' with an OpenAPI or GraphQL source."},NO_ENDPOINTS_FOUND:{reason:"The API endpoint file does not exist. Run generate first.",nextCommandHint:"Run 'openapi-skills generate' to create endpoints.json."},NO_RESPONSE_SCHEMA:{reason:"The response schema artifact has not been created yet.",nextCommandHint:"Run 'openapi-skills request <operationId> --api <apiName>' to create the response-schema artifact."},REQUEST_TEMPLATE_STALE:{reason:"The request template does not exist for this operation.",nextCommandHint:"Run the command again with --force to regenerate the request template."},SCHEMA_VALIDATION_FAILED:{reason:"The provided OpenAPI or GraphQL schema is malformed.",nextCommandHint:"Fix the schema at its source and retry."},INVALID_FILTER_SYNTAX:{reason:"--filter requires the target to be an array.",nextCommandHint:"Use --response-schema first to inspect the response shape, then use --get to narrow the value before filtering."},MISSING_FILTER_ARGUMENT:{reason:"The list command requires at least one filter to avoid returning large, unbounded result sets.",nextCommandHint:"Add --path, --filter, --method, --root-type, or --index to narrow results."},SCHEMA_TYPE_MISMATCH:{reason:"The flag used is incompatible with this schema type.",nextCommandHint:"Use --path and --method for OpenAPI; use --root-type for GraphQL."},INVALID_JSON_ARGUMENT:{reason:"The provided JSON argument is malformed.",nextCommandHint:"Fix the JSON syntax and retry."},INVALID_VARIABLE_SYNTAX:{reason:"Variable syntax is invalid. Expected key=value format.",nextCommandHint:"Use --var key=value format."},INVALID_UPDATE_REQUEST_JSON:{reason:"The --update-request JSON could not be parsed.",nextCommandHint:"Fix the JSON syntax and retry."},INVALID_REQUEST_UPDATE:{reason:"The request keys specified do not exist in request.json.",nextCommandHint:"Use valid request.json keys. Inspect with 'openapi-skills get-operation <operationId> --api <apiName> --request' first."},OVERSIZED_OUTPUT:{reason:"The output is too large to display.",nextCommandHint:"Use --get or --filter to reduce output size."},API_PARSE_ERROR:{reason:"An error occurred while parsing the API schema.",nextCommandHint:"Review the error details and fix the schema at its source."},REQUEST_FAILED:{reason:"The HTTP request failed.",nextCommandHint:"Check the base URL, authentication headers, and network connectivity."},VALIDATION_FAILED:{reason:"The response does not match the expected schema.",nextCommandHint:"Verify that the API response matches the declared schema."},CONFIG_ERROR:{reason:"Failed to read or write configuration file.",nextCommandHint:"Check file permissions on .openapi-skills/config.json."}},an={UNKNOWN_API:"usage",MISSING_FILTER_ARGUMENT:"usage",INVALID_FILTER_SYNTAX:"usage",SCHEMA_TYPE_MISMATCH:"usage",INVALID_VARIABLE_SYNTAX:"usage",INVALID_JSON_ARGUMENT:"usage",SCHEMA_VALIDATION_FAILED:"validation",INVALID_REQUEST_UPDATE:"validation",INVALID_UPDATE_REQUEST_JSON:"validation",MISSING_PARSED_API:"state",NO_ENDPOINTS_FOUND:"state",NO_RESPONSE_SCHEMA:"state",REQUEST_TEMPLATE_STALE:"state",OVERSIZED_OUTPUT:"state",API_PARSE_ERROR:"runtime",REQUEST_FAILED:"runtime",VALIDATION_FAILED:"runtime",CONFIG_ERROR:"runtime"}});function w(e,t){let r=an[e],n=sn[e],s=t.nextCommand??"None",i=t.reason??n?.reason??"Unable to remediate automatically.",o=t.severity??"error";return{ok:!1,error:{code:e,category:r,severity:o,summary:t.summary,message:t.message,remediation:{required:!0,next_command:s,reason:i},context:t.context??{}}}}function q(e,t){let r={ok:!0,data:e};return t?.kind!==void 0&&(r.kind=t.kind),r}var on=S(()=>{"use strict";Qt()});var Gr={};mn(Gr,{program:()=>j});import{Command as ni}from"commander";import M from"fs-extra";import si from"path";import ii from"os";import{createRequire as ai}from"module";async function fe(e){return(await ue().catch(()=>[])).includes(e)?!0:(d.result(w("UNKNOWN_API",{summary:`API '${e}' is not installed.`,message:`No API named '${e}' was found. Run 'openapi-skills get-api-names' to list installed APIs, or run 'openapi-skills generate <openapi-source>' first.`,context:{api_name:e},nextCommand:"openapi-skills get-api-names"})),process.exitCode=1,!1)}var oi,Mt,pi,Uo,j,pn,ci,ui,di,li,fi,mi,gi,hi,yi,wi,bi,Ai,Ti,ki,Br=S(async()=>{ke();K();de();Rt();Bt();Ur();ke();be();Ot();ot();Vr();zr();Wr();Yr();en();qt();rn();nn();on();Qt();Oe();oi=ai(import.meta.url),Mt=oi("../package.json"),pi=Mt.repository.url;await Mr(Mt.version);Uo=rt(),j=new ni,pn=process.argv.includes("--silent");j.name("openapi-skills").description("A command\u2011line tool for working with OpenAPI/Swagger and GraphQL specs. Use it to parse specs into artifacts, explore API endpoints and root fields, validate requests, generate typed client metadata, and teach AI agents how to operate the CLI and write API tests and client code.").version(Mt.version);ci=`
|
|
19
|
+
\x1B[32m
|
|
20
|
+
\u2584\u2584\u2584 \u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584 \u2584\u2584 \u2584\u2584 \u2584\u2584\u2584 \u2584\u2584\u2584\u2584 \u2584\u2584 \u2584\u2584\u2584\u2584 \u2584\u2584 \u2584\u2584 \u2584\u2584 \u2584\u2584 \u2584\u2584 \u2584\u2584\u2584\u2584
|
|
21
|
+
\u2588\u2588\u2580\u2588\u2588 \u2588\u2588\u2584\u2588\u2580 \u2588\u2588\u2584\u2584 \u2588\u2588\u2588\u2584\u2588\u2588 \u2588\u2588\u2580\u2588\u2588 \u2588\u2588\u2584\u2588\u2580 \u2588\u2588 \u2584\u2584\u2584 \u2588\u2588\u2588\u2584\u2584 \u2588\u2588\u2584\u2588\u2580 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2584\u2584
|
|
22
|
+
\u2580\u2588\u2588\u2588\u2580 \u2588\u2588 \u2588\u2588\u2584\u2584\u2584 \u2588\u2588 \u2580\u2588\u2588 \u2588\u2588\u2580\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2584\u2584\u2588\u2588\u2580 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2584\u2584\u2584 \u2588\u2588\u2584\u2584\u2584 \u2584\u2584\u2588\u2588\u2580
|
|
23
|
+
\x1B[0m
|
|
24
|
+
`;j.option("--silent","Hide the banner and Pro feature summary in help output for agent-friendly usage.");pn||j.addHelpText("before",ci);j.addHelpText("before",`
|
|
25
|
+
===================
|
|
26
|
+
openapi-skills CLI
|
|
27
|
+
===================
|
|
28
|
+
`);ui=2026,di=new Date().getFullYear(),li=`${ui}-${di}`;pn||j.addHelpText("after",`
|
|
29
|
+
\x1B[35m
|
|
30
|
+
-------------------------------------------------------------------------------
|
|
31
|
+
openapi-skills Pro-only commands:
|
|
32
|
+
generate-openapi Generate an OpenAPI document from source annotations.
|
|
33
|
+
docs Generate and serve an HTML viewer for an OpenAPI schema.
|
|
34
|
+
compare Compare APIs/operations or responses with response schemas.
|
|
35
|
+
mock-server Start a local mock HTTP server.
|
|
36
|
+
|
|
37
|
+
Pro-only options on shared commands:
|
|
38
|
+
install --skills-annotator
|
|
39
|
+
request --mock, --update-request-file <path>
|
|
40
|
+
request --patch-set <path=value>, --patch-set-num <path=value>,
|
|
41
|
+
--patch-set-bool <path=value>, --patch-append <path=value>,
|
|
42
|
+
--patch-append-num <path=value>, --patch-append-bool <path=value>,
|
|
43
|
+
--patch-delete <path>
|
|
44
|
+
|
|
45
|
+
Learn more: https://github.com/tzurp/openapi-skills-pro
|
|
46
|
+
-------------------------------------------------------------------------------
|
|
47
|
+
\x1B[0m
|
|
48
|
+
`);j.addHelpText("after",`
|
|
49
|
+
-------------------------------------------------------------------------------
|
|
50
|
+
Copyright \xA9 ${li} Tzur Paldi \u2014 Powered by Bedekbyte\xAE All rights reserved
|
|
51
|
+
Support: tzur.paldi@outlook.com
|
|
52
|
+
Project: ${pi}
|
|
53
|
+
-------------------------------------------------------------------------------
|
|
54
|
+
`);j.command("install").description("Install SKILL.md and scenario markdowns for agent frameworks like Claude and GitHub Copilot. Supports: --skills [--global].").option("--skills","Install SKILL.md files for agent frameworks.").option("--global","Install the skill bundle under the user's home directory instead of the current project.").action(async e=>{if(e.global&&!e.skills){d.result(w("CONFIG_ERROR",{summary:"--global requires --skills.",message:"Use `openapi-skills install --skills --global` to install the skill bundle under your home directory.",context:{},nextCommand:"openapi-skills install --skills --global"})),process.exitCode=1;return}if(!e.skills){await kt(),d.info(".openapi-skills directory and configuration installed. Use --skills to install SKILL.md files for agent frameworks.");return}let t=e.global?ii.homedir():nt(),r=nt(),n=si.join(t,"installed-skills");d.info(`Source directory (copied): ${r}`);let s=await Fr(t,n);d.info(`Target install directory: ${s}`);try{let i=await Jr(r,s);d.info("openapi-skills skill bundle installed")}catch(i){d.result(w("CONFIG_ERROR",{summary:"Failed to install skill bundle.",message:i instanceof Error?i.message:String(i),context:{install_path:s},nextCommand:"openapi-skills install --skills"})),process.exitCode=1}});fi=j.command("generate [openapi-source]").description("Parse an OpenAPI 2.0, OpenAPI 3.0.x, or GraphQL source (file path or URL) and generate endpoints.json, schemas/, and config.json. OpenAPI 3.1.0 and later are not supported. Run this command first for a new spec. Supports: --validate, --base-url, --dereference, --no-progress.").option("--validate <schema>","Validate an OpenAPI or GraphQL schema (file path or URL) and exit").option("--base-url <url>","Base URL for the API").option("--dereference","Fully dereference the entire OpenAPI document before processing endpoints").option("--no-progress","Disable the progress indicator").option("--rename <newName>","Optional new name for the generated schema.").action(async(e,t)=>{try{if(typeof t.validate=="string"&&t.validate.length>0){try{await fr(t.validate),d.result(q({valid:!0,schemaSource:t.validate,message:"Schema is valid"},{kind:"schema-validation"})),process.exitCode=0}catch(o){d.result(w("SCHEMA_VALIDATION_FAILED",{summary:"OpenAPI or GraphQL schema is invalid.",message:`Schema validation failed: ${W(o)}`,context:{schema_source:t.validate},nextCommand:`openapi-skills generate ${t.validate}`})),process.exitCode=1}return}if(!e)throw new Error("An OpenAPI source is required unless --validate is used.");let r=typeof t.baseUrl=="string"?t.baseUrl.trim():"",n=r.length>0,i=await lr(e,n?r:"",{dereference:t.dereference===!0,progress:t.progress!==!1,rename:t.rename});if(!n){let o=[`You haven't included --base-url for API "${i}".`,`If you need to make requests and validations, add baseUrl directly to .openapi-skills/config.json under apis.${i}.baseUrl.`,"Example:",`{
|
|
55
|
+
"apis": {
|
|
56
|
+
"${i}": {
|
|
57
|
+
"baseUrl": "https://petstore3.swagger.io/api/v3",
|
|
58
|
+
"openapi-sorce": "https://petstore3.swagger.io/api/v3/openapi.json"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}`].join(`
|
|
62
|
+
`);d.warn(o),d.result(q({apiName:i,openapiSource:e,warning:o},{kind:"generate-warning"}))}d.result(q({apiName:i,openapiSource:e,fileCount:3},{kind:"generate-result"})),process.exitCode=0}catch(r){if(tr(r)){d.result(w("API_PARSE_ERROR",{summary:"TypeScript is required to analyze builder GraphQL schemas.",message:`TypeScript is not available in this environment. Install it with \`${bt}\` and rerun the command.`,context:{openapi_source:e},nextCommand:bt,reason:"GraphQL builder parsing requires TypeScript to be installed in the current workspace."})),process.exitCode=1;return}d.result(w(t.validate?"SCHEMA_VALIDATION_FAILED":"API_PARSE_ERROR",{summary:t.validate?"OpenAPI or GraphQL schema is invalid.":"Failed to parse the provided schema.",message:W(r),context:{openapi_source:e},nextCommand:t.validate?`openapi-skills generate ${t.validate}`:`openapi-skills generate ${e??"<openapi-source>"}`})),process.exitCode=1}});fi.agentMeta={name:"generate",category:"Generation",usage:"openapi-skills generate [openapi-source] [--validate <schema>] [--base-url <url>] [--dereference] [--no-progress] [--rename <newName>]",description:"Parse an OpenAPI 2.0, OpenAPI 3.0.x, or GraphQL source file or URL and generate the API artifacts used by the rest of the CLI. OpenAPI 3.1.0 and later are not supported. Use --validate to check a schema and exit, --base-url to set the API base URL, --dereference when full dereferencing is appropriate, --rename to override the generated API name, and --no-progress to suppress progress output.",arguments:[{name:"openapi-source",type:"path|url",required:!1,positional:!0,description:"OpenAPI source file path or URL."},{name:"validate",type:"path|url",required:!1,flag:!0,description:"Validate an OpenAPI schema and exit."},{name:"base-url",type:"string",required:!1,flag:!0,description:"Base URL for the generated API."},{name:"dereference",type:"boolean",required:!1,flag:!0,description:"Fully dereference the OpenAPI document before processing endpoints."},{name:"no-progress",type:"boolean",required:!1,flag:!0,description:"Disable the progress indicator."},{name:"rename",type:"string",required:!1,flag:!0,description:"Optional new name for the generated schema."}],examples:["openapi-skills generate ./petstore.yaml --base-url https://api.example.com","openapi-skills generate https://example.com/openapi.yaml","openapi-skills generate ./petstore.yaml --validate ./petstore.yaml","openapi-skills generate ./petstore.yaml --dereference","openapi-skills generate ./petstore.yaml --rename petstore-v2","openapi-skills generate ./petstore.yaml --no-progress"],returns:{type:"json",description:"Prints output directory and config.json path."},sideEffects:{writesFiles:!0,readsFiles:!0,network:!0},constraints:{destructive:!1,idempotent:!1,requiresParsedApi:!1},filesWritten:["endpoints.json","schemas/","config.json"]};mi=j.command("list").description("List summarized operation objects for the specified API as JSON. Supports --filter, --tag, --resolved/--dereferenced, --index slicing, and --count for operation totals. Also supports OpenAPI\u2011only options (--path, --method) and the GraphQL\u2011only option (--root-type). At least one filter is required unless --index : is used intentionally. GraphQL APIs reject --method, --path, and --tag, and OpenAPI APIs reject --root-type.").requiredOption("--api <apiName>","API name to use").option("--count","Return the number of operations after applying any list filters and index slicing. With no filters, returns the total operation count.").option("--resolved, --dereferenced","Show only operations that already have generated schema details saved.").option("--path <path>",["Filter operations by path structure. Repeatable; multiple values are ANDed.","Supports:"," - Path prefix: /users (matches operations whose path begins with /users)"," - Parameter detection: :param (matches operations with any {param} in the path)"," - Segment matching: 'store order' (matches operations whose path contains BOTH 'store' AND 'order' as segments, in any order)"," - OR within a clause: 'store|shop' (matches operations whose path contains EITHER 'store' OR 'shop')"," - Combined AND+OR: 'store order|shop item' (matches endpoints with both 'store' and 'order', OR both 'shop' and 'item')"," - Multiple --path flags are ANDed: --path /store --path order (matches endpoints starting with /store AND containing 'order')","","Examples:"," --path /users"," --path :param"," --path 'store order'"," --path 'store|shop'"," --path /store --path order"].join(`
|
|
63
|
+
`),(e,t)=>[...Array.isArray(t)?t:t?[t]:[],e]).option("--filter <filterPattern>","Filter operations by any of their searchable properties. Supports AND/OR (use spaces for AND, | for OR), e.g. --filter 'create account|register user'.").option("--tag <tag>","Filter OpenAPI operations by an exact tag, case-insensitive.").option("--method <method>","Filter operations by HTTP method (GET, POST, etc). Use this for OpenAPI operations.").option("--root-type <rootType>","Filter GraphQL root fields by root type (query, mutation, or subscription).").option("--index <range>","Slice the filtered results with inclusive Python-like range syntax, e.g. 0:10, 5:, :10, -1, or :").action(async e=>{let t=e.api;if(await fe(t))try{let r=L(t),n=await $t(t),s=e.resolved===!0||e.dereferenced===!0,i=!!(e.path||e.filter||e.tag||e.method||e.rootType||e.index||s),o={};if((typeof e.path=="string"||Array.isArray(e.path))&&(o.path=e.path),typeof e.filter=="string"&&(o.filter=e.filter),typeof e.tag=="string"&&(o.tag=e.tag),typeof e.method=="string"&&(o.method=e.method),typeof e.rootType=="string"&&(o.rootType=e.rootType),n==="graphql"&&(typeof e.method=="string"||typeof e.path=="string"||typeof e.tag=="string")){d.result(w("SCHEMA_TYPE_MISMATCH",{summary:"--method, --path, and --tag are only valid for OpenAPI APIs.",message:"This API is GraphQL. Use --root-type with --filter instead.",context:{api_name:t,schema_type:n},nextCommand:`openapi-skills list --api ${t} --root-type query`})),process.exitCode=2;return}if(n==="openapi"&&typeof e.rootType=="string"){d.result(w("SCHEMA_TYPE_MISMATCH",{summary:"--root-type is only valid for GraphQL APIs.",message:"This API is OpenAPI. Use --method and --path or --filter instead.",context:{api_name:t,schema_type:n},nextCommand:`openapi-skills list --api ${t} --method GET`})),process.exitCode=2;return}if(!e.count&&!i){d.result(w("MISSING_FILTER_ARGUMENT",{summary:"No filter provided. Use --path, --filter, --tag, --method, --root-type, or --index.",message:"The list command requires at least one filter to avoid returning large, unbounded result sets.",context:{api_name:t},nextCommand:`openapi-skills list --api ${t} --index :`,severity:"warning"})),process.exitCode=0;return}if(M.existsSync(r)===!1){if(e.count){d.result(q({count:0,message:`No endpoints.json found for API "${t}".`},{kind:"endpoint-count"}));return}d.result(w("NO_ENDPOINTS_FOUND",{summary:`No endpoints.json found for API "${t}".`,message:"The API has not been parsed yet. Run 'openapi-skills generate' to create it.",context:{api_name:t},nextCommand:`openapi-skills generate <openapi-source> --rename ${t}`,reason:"The API artifacts have not been generated."})),d.warn(`No endpoints found for "${t}". This API name may be misspelled or not generated yet. (openapi-skills generate <openapi-source> [options])`);return}let a=await M.readJson(r),p=at(a,o);s&&(p=await br(t,p)),p=wr(p,e.index);let c=p.map(({tags:u,...m})=>m);if(e.count){d.result(q({count:p.length,apiName:t},{kind:"endpoint-count"}));return}if(p.length===0){if(d.result(q({apiName:t,items:[]},{kind:"endpoint-list"})),e.path||e.filter||e.tag||e.method||e.rootType||e.index||s){let u=Array.isArray(e.path)?e.path.join(", "):e.path,m=u?`path "${u}"`:"",f=e.filter?`filter "${e.filter}"`:"",l=e.tag?`tag "${e.tag}"`:"",g=e.method?`method "${e.method}"`:"",b=e.rootType?`rootType "${e.rootType}"`:"",T=s?"resolve":"",h=e.index?`index "${e.index}"`:"",y=[m,f,l,g,b,T,h].filter(Boolean).join(", ");d.warn(`No endpoints matched the ${y}.`)}return}d.result(q({apiName:t,items:c},{kind:"endpoint-list"}))}catch(r){d.result(w("API_PARSE_ERROR",{summary:"Error listing endpoints.",message:W(r),context:{api_name:t}})),process.exitCode=1}});mi.agentMeta={name:"list",category:"Navigation",usage:"openapi-skills list --api <apiName> [--count] [--resolved|--dereferenced] [--path <path>]... [--filter <pattern>] [--tag <tag>] [--method <method>] [--root-type <rootType>] [--index <range>]",description:["List operation summaries for a parsed API as JSON.","At least one filter is required. --index is treated as a filter input, so the command can run when only a slice is requested.","Use --count to return the number of operations after filtering and slicing, or --resolved to show only operations that already have generated schema details saved.","Filter usage differs by schema type: use --method, --path, and --tag for OpenAPI operations, use --root-type for GraphQL root fields, and use --filter and --index with either schema. Filtering is case-insensitive and supports:","- Path prefix: --path '/users' (matches operations whose path begins with the prefix)","- Parameter detection: --path :param (matches operations that contain at least one '{...}' path placeholder)","- Segment matching: --path 'store order' (matches endpoints whose path contains both segments)","- OR within a single path clause: --path 'store|shop' (matches either segment)","- Multiple path flags are ANDed: --path /store --path order","- Exact tag matching: --tag pet (matches OpenAPI operations whose tag is exactly 'pet', ignoring case)","- Simple substring filtering: --filter 'user account' (matches operations containing both 'user' and 'account' in any field, including GraphQL name/rootType fields)","- OR filtering: --filter 'create|register|signup' (matches any operation containing any of the words)","- Combined AND+OR: --filter 'create account|register user' (matches operations containing both 'create' and 'account', OR both 'register' and 'user')","- Path substring search: --filter '/users' (matches operations whose path contains the substring)","- OperationId: --filter 'getUser' (matches operationId field)","- Summary/description: --filter 'delete permanently'","- Method filtering: --method GET (OpenAPI only; can be combined with --path and/or --filter)","- GraphQL root type filtering: --root-type query (query, mutation, or subscription)","- Index slicing: --index 0:10, --index 5:, --index :10, --index -1, --index :"," Slices the filtered results using inclusive Python-like range syntax:"," N = only the Nth item (0-based, negative counts from end)"," start:end = all items from start to end, inclusive"," start: = from start to last"," :end = from first to end"," : = all items"," Negative indices count from the end (e.g., -1 is the last item, -2 is second-to-last)."," Examples:"," --index 0:2 (first three items)"," --index 5: (from 6th to last)"," --index :3 (first four items)"," --index -1 (last item)"," --index : (all items)"," --count (return the filtered/sliced endpoint count, or the total count when no filters are used)",`
|
|
64
|
+
`,"Use --path for path-aware matching. Use --filter for substring matching across path, operationId/name, rootType, summary, or description.","If no operations match, outputs [] and prints a message to stderr."].join(`
|
|
65
|
+
`),arguments:[{name:"api",type:"string",required:!0,flag:!0,description:"API name to use."},{name:"count",type:"flag",required:!1,flag:!0,description:"Return the number of operations after filtering and slicing."},{name:"resolved",type:"flag",required:!1,flag:!0,description:"Show only operations that already have generated schema details saved. Alias: --dereferenced."},{name:"path",type:"string[]",required:!1,flag:!0,description:"Filter operations by path structure."},{name:"filter",type:"string",required:!1,flag:!0,description:"Filter operations by keywords, operationId/name, rootType, path, summary, or description."},{name:"tag",type:"string",required:!1,flag:!0,description:"Filter OpenAPI operations by an exact tag, case-insensitive."},{name:"method",type:"string",required:!1,flag:!0,description:"Filter OpenAPI operations by HTTP method."},{name:"rootType",type:"string",required:!1,flag:!0,description:"Filter GraphQL operations by root type (query, mutation, or subscription)."},{name:"index",type:"string",required:!1,flag:!0,description:"Slice the filtered results with inclusive Python-like range syntax."}],examples:["openapi-skills list --api petstore","openapi-skills list --api petstore --count","openapi-skills list --api petstore --resolved","openapi-skills list --api petstore --tag pet","openapi-skills list --api petstore --path /users","openapi-skills list --api petstore --path /store --path order","openapi-skills list --api petstore --path 'store order'","openapi-skills list --api petstore --path :param","openapi-skills list --api petstore --filter addpet","openapi-skills list --api petstore --filter 'create|register' --method POST","openapi-skills list --api countries --root-type query","openapi-skills list --api petstore --resolved --count","openapi-skills list --api petstore --filter '/users'","openapi-skills list --api petstore --index 0:10"],returns:{type:"json",description:"Returns filtered operation summaries as JSON, or a count object when --count is used. When no filters are provided, returns a structured warning object."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!0},filesWritten:[]};gi=j.command("generate-client-schema <operationId>").requiredOption("--api <apiName>","API name to use").option("--force","Overwrite the cached <operationId> artifact file before generating metadata.").description("Return structured metadata for client code generation for a specific operation. Use --force to overwrite the cached <operationId> artifact file before reading it.").action(async(e,t)=>{let r=t.api;if(await fe(r))try{let n=await X(r,e),s=await Ne(r,e,n,t.force===!0);d.result(q(s,{kind:"client-schema"}))}catch(n){let s=n instanceof Error?n.message:String(n);d.result(w("API_PARSE_ERROR",{summary:"Error generating client code metadata.",message:s,context:{api_name:r,operation_id:e}})),process.exitCode=1}});gi.agentMeta={name:"generate-client-schema",category:"Code Generation",usage:"openapi-skills generate-client-schema <operationId> --api <apiName> [--force]",description:"Print structured metadata optimized for client code generation as pretty-printed JSON. Returns `response: null` for operations with no JSON response body, in which case the generated client should return `Promise<void>`. The cached artifact is reused unless --force is provided.",arguments:[{name:"operationId",type:"string",required:!0,positional:!0,description:"The operationId of the operation to inspect."},{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."},{name:"force",type:"flag",required:!1,flag:!0,description:"Overwrite the cached artifact file before generating metadata."}],examples:["openapi-skills generate-client-schema addPet --api petstore","openapi-skills generate-client-schema addPet --api petstore --force"],returns:{type:"json",description:"Returns metadata as pretty-printed JSON."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!0},filesWritten:[]};hi=j.command("describe <operationId>").requiredOption("--api <apiName>","API name to use").option("--force","Overwrite the cached <operationId> artifact file before printing the raw schema.").description("describe \u2192 fallback for generate-client-schema. Use generate-client-schema first. Prints the complete raw schema for a specific operation as JSON, including all parameters, request body, and all response codes. The cached <operationId> artifact file is reused unless --force is provided, which overwrites the cached schema from the bundled API document before output.").action(async(e,t)=>{let r=t.api;if(await fe(r))try{let n=await X(r,e),s=await Q(r,e,n,t.force===!0);d.result(q({operationId:e,warnings:["describe \u2192 fallback for generate-client-schema. Use openapi-skills generate-client-schema first for client code generation."],schema:s},{kind:"describe-result"}));return}catch(n){let s=n instanceof Error?n.message:String(n);d.result(w("API_PARSE_ERROR",{summary:"Error describing operation.",message:s,context:{api_name:r,operation_id:e}})),process.exitCode=1;return}});hi.agentMeta={name:"describe",category:"Navigation",usage:"openapi-skills describe <operationId> --api <apiName> [--force]",description:["Fallback for generate-client-schema. Prints the complete raw schema for a specific operation as JSON, including all parameters, request body, and response codes. The cached artifact is reused unless --force is provided.","","**Agents MUST use `generate-client-schema` for client code generation. Use `describe` only when you need full raw schema detail beyond what `generate-client-schema` provides.**"].join(`
|
|
66
|
+
`),arguments:[{name:"operationId",type:"string",required:!0,positional:!0,description:"The operationId of the endpoint to describe."},{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."},{name:"force",type:"flag",required:!1,flag:!0,description:"Overwrite the cached schema file before printing the raw schema."}],examples:["openapi-skills describe getPetById --api petstore","openapi-skills describe deletePet --api petstore","openapi-skills describe getPetById --api petstore --force"],returns:{type:"json",description:"Structured JSON with a fallback warning and the raw OpenAPI schema nested under `schema`."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!0},filesWritten:[]};yi=j.command("get-operation <operationId>").alias("get-operation-artifact").requiredOption("--api <apiName>","API name to use").option("--request","Return request artifact for the operation.").option("--response","Return response artifact for the operation.").option("--response-schema","Return response-schema artifact for the operation. Inspect this first when the response shape is unknown.").option("--get <path>","Select a nested value by dot-notation path first. Inspect --response-schema first so the path matches the actual response shape.").option("--filter <expr>","Filter the selected value using count, index, range, or <path>=<value> syntax (e.g. count, 0, 0:10, status=sold). Select path first with --get, then filter or slice the selected value.").description("Return one stored operation artifact as JSON. Run `request` first for the same operationId so the artifact exists. Exactly one of --request, --response, or --response-schema is required. Select path first with --get, then apply --filter to the selected value. Use --response-schema first when the response shape is unknown.").action(async(e,t)=>{let r=t.api;if(!await fe(r))return;let n=Kr(t),s=await X(r,e);if(n.error||!n.artifactName){d.result(w("INVALID_REQUEST_UPDATE",{summary:"Invalid operation artifact selection.",message:n.error??"Invalid operation artifact selection.",context:{api_name:r,operation_id:e},nextCommand:`openapi-skills get-operation ${e} --api ${r} --request`})),process.exitCode=1;return}let i=tt(r,s,n.artifactName);if(!await M.pathExists(i)){if(n.artifactName==="response-schema"){d.result(w("NO_RESPONSE_SCHEMA",{summary:"No response schema artifact exists for this operation.",message:"The response schema has not been created yet.",context:{api_name:r,operation_id:e,artifact_type:"response-schema"},nextCommand:`openapi-skills request ${e} --api ${r}`,reason:"Make a request first to generate the response-schema artifact."})),process.exitCode=1;return}d.result(w("REQUEST_TEMPLATE_STALE",{summary:`Artifact '${n.artifactName}' is missing for this operation.`,message:`The '${n.artifactName}' artifact does not exist yet.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName},nextCommand:`openapi-skills request ${e} --api ${r}`})),process.exitCode=1;return}try{let o=await M.readJson(i),a=typeof t.get=="string"?t.get:void 0,p=typeof t.filter=="string"?t.filter:void 0,c=typeof a=="string"&&a.length>0,u=typeof p=="string"&&p.length>0,m=c?_e(o,a):o;if(c&&!u){let{sizeBytes:l}=$e(m);l>=51200?d.result(w("OVERSIZED_OUTPUT",{summary:"Output is too large to display.",message:`The selected value is ${l} bytes, exceeding the limit of ${51200} bytes.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName,size_bytes:l},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --get ${a} --filter count`})):d.result(q({apiName:r,value:m},{kind:"artifact-value"}));return}if(u){let l=m,g=[];!Array.isArray(l)&&l!==null&&typeof l=="object"&&(g=Object.values(l).filter(y=>Array.isArray(y)),g.length===1&&(l=g[0]));let b=tn(p),T;if(b.kind==="count"||b.kind==="index"||b.kind==="range"){if(!Array.isArray(l))if(g.length===1)l=g[0];else{d.result(w("INVALID_FILTER_SYNTAX",{summary:"--filter requires the target to be an array.",message:"The selected value is not an array and contains no single array field to unwrap.",context:{api_name:r,operation_id:e,artifact_type:n.artifactName,filter:p,selected_path:c?a:void 0},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --response-schema`})),process.exitCode=1;return}if(!Array.isArray(l)){d.result(w("INVALID_FILTER_SYNTAX",{summary:"--filter requires the target to be an array.",message:"The selected value is not an array.",context:{api_name:r,operation_id:e,artifact_type:n.artifactName,filter:p,selected_path:c?a:void 0},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName}`})),process.exitCode=1;return}if(b.kind==="count")T=l.length;else if(b.kind==="index"){let y=b.index<0?l.length+b.index:b.index;T=l[y]}else T=l.slice(b.start,b.end)}else if(b.kind==="path"){let y=b.path,P=b.value;if(c&&!Array.isArray(l)){d.result(w("INVALID_FILTER_SYNTAX",{summary:"--filter requires the --get result to be an array.",message:`The value at path '${a}' is not an array.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName,filter:p,selected_path:a},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --response-schema`})),process.exitCode=1;return}if(!Array.isArray(l)){let{sizeBytes:O}=$e(l);O>=51200?d.result(w("OVERSIZED_OUTPUT",{summary:"Output is too large to display.",message:`The selected value is ${O} bytes, exceeding the limit of ${51200} bytes.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName,size_bytes:O},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --filter count`})):d.result(q({apiName:r,value:l},{kind:"artifact-value"}));return}T=Ar(l,y,P)}else{d.result(w("INVALID_FILTER_SYNTAX",{summary:"Invalid --filter syntax.",message:"--filter must use count, index, range, or <path>=<value> syntax.",context:{api_name:r,operation_id:e,artifact_type:n.artifactName,filter:p},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --filter 0`})),process.exitCode=1;return}let{sizeBytes:h}=$e(T);h>=51200?d.result(w("OVERSIZED_OUTPUT",{summary:"Output is too large to display.",message:`The filtered result is ${h} bytes, exceeding the limit of ${51200} bytes.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName,size_bytes:h},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --filter count`})):d.result(q({apiName:r,value:T},{kind:"artifact-value"}));return}let{sizeBytes:f}=$e(o);f>=51200?d.result(w("OVERSIZED_OUTPUT",{summary:"Output is too large to display.",message:`The artifact is ${f} bytes, exceeding the limit of ${51200} bytes.`,context:{api_name:r,operation_id:e,artifact_type:n.artifactName,size_bytes:f},nextCommand:`openapi-skills get-operation ${e} --api ${r} --${n.artifactName} --get <path> --filter count`})):d.result(q({apiName:r,operationId:e,artifact:o},{kind:"artifact"}))}catch(o){d.result(w("API_PARSE_ERROR",{summary:`Failed to read artifact '${n.artifactName}'.`,message:W(o),context:{api_name:r,operation_id:e,artifact_type:n.artifactName}})),process.exitCode=1}});yi.agentMeta={name:"get-operation",category:"Navigation",usage:"openapi-skills get-operation|get-operation-artifact <operationId> --api <apiName> [--request] [--response] [--response-schema] [--get <path>] [--filter count|<index>|<range>|<path>=<value>]",description:"Return a stored operation artifact created by `openapi-skills request` as raw JSON. Run `request` first so the artifact exists. Use --get to select a nested value, then --filter to count, slice, or match values. Use --response-schema first when the response shape is unknown. Exactly one of --request, --response, or --response-schema is required. Alias: `get-operation-artifact`.",arguments:[{name:"operationId",type:"string",required:!0,positional:!0,description:"The operationId whose stored artifact should be returned."},{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."},{name:"request",type:"flag",required:!1,flag:!0,description:"Return request artifact for the operation."},{name:"response",type:"flag",required:!1,flag:!0,description:"Return response artifact for the operation."},{name:"response-schema",type:"flag",required:!1,flag:!0,description:"Return response-schema artifact for the operation. Inspect this first when the response shape is unknown."},{name:"get",type:"string",required:!1,flag:!0,description:"Select a nested value by dot-notation path first. Inspect get-operation --response-schema first so the path matches the actual response shape."},{name:"filter",type:"string",required:!1,flag:!0,description:"Filter the selected value using count, index, range, or <path>=<value> syntax. Examples: --filter count, --filter 0, --filter 0:10, --filter status=sold. Select path first with --get, then filter or slice the selected value."}],examples:["openapi-skills request getPetById --api petstore --force","openapi-skills get-operation getPetById --api petstore --request","openapi-skills get-operation-artifact getPetById --api petstore --request","openapi-skills get-operation getPetById --api petstore --response-schema","openapi-skills get-operation-artifact getPetById --api petstore --response-schema","openapi-skills get-operation getPetById --api petstore --response","openapi-skills get-operation-artifact getPetById --api petstore --response","openapi-skills get-operation getPetById --api petstore --response --get name","openapi-skills get-operation getPetById --api petstore --response --get body --filter id=555","openapi-skills get-operation getPetById --api petstore --response --filter id=5555","openapi-skills get-operation getPetById --api petstore --response --filter count","openapi-skills get-operation getPetById --api petstore --response --filter 0","openapi-skills get-operation getPetById --api petstore --response --filter 0:10"],returns:{type:"json",description:"Returns the selected artifact as raw JSON, or a nested value / filtered array when --get or --filter is supplied. When both are used, --get runs first and --filter applies to the narrowed result. Inspect --response-schema first when the response shape is unknown so --get and --filter can be applied in the right order. --filter can also return an array count, single item, or slice when the selected target is an array."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!0},filesWritten:[]};wi=j.command("request <operationId...>").description("Make a live HTTP request for a specific operation, or prepare a multi-step request scenario without executing requests. Supports: --validate (validate only the response against the schema after the request is sent; it does not validate request bodies or guarantee a response exists), --force (refresh operation schema and regenerate request artifact), --force-request (regenerate only request artifact from the cached operation schema), --update-request (patch request artifact using flattened dot-notation keys; binary fields can be file paths or {kind:'file', path,...} descriptors), --update-request-encoded (patch request artifact using base64url-encoded JSON), --omit-empty (remove empty-string values from schema-optional request fields before sending), --header (add headers), --header-encoded (add headers using base64url-encoded JSON).").requiredOption("--api <apiName>","API name to use").option("--validate","Validate only the response against the schema after the request is sent. Does not validate the request body or guarantee a response exists.").option("--omit-empty","For single-operation requests, remove empty-string values from schema-optional fields before sending and persist the cleaned artifact.").option("--force","Refresh the operation schema and overwrite the request artifact with defaults.").option("--force-request","Force overwrite only the request artifact with defaults from the cached operation schema; does not refresh the operation schema.").option("--update-request <json>",["Update request artifact before making the request using a single-quoted JSON string that represents a flattened object with dot-notation keys.","Nested JSON objects are supported (they will be flattened and issue a warning), but the top-level value must be a JSON object. Invalid JSON will cause the command to fail.",'To delete a field, set its value to "__delete__".','Binary request fields may be patched with a file path string or an object like {"kind":"file","path":"c:/path/file.pdf","fileName":"file.pdf","mimeType":"application/pdf"}.',`Format (POSIX shells): --update-request '{"field.path":value,...}'`,'Format (PowerShell): --update-request "{"field.path":value,...}" (escape inner quotes as needed)'," - Only flattened object dot-notation keys are recommended (e.g. 'items.0.name').","Examples:",` --update-request '{"person.id":"2"}'`,` --update-request '{"items.0.name":"Alice","items.1.value":42}'`,` --update-request '{"parameters.0":"__delete__"}'`,` --update-request '{"address.street":"Main St","address.zip":12345}'`,"Note: The CLI runs JSON.parse on the provided value; if parsing fails the command exits with an error."].join(`
|
|
67
|
+
`)).option("--update-request-encoded <base64url>",["Patch request artifact before making the request using base64url-encoded JSON.","Use this when a shell or agent may strip quotes from literal JSON.","Example:"," --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9"].join(`
|
|
68
|
+
`)).option("--header <json>",["Additional headers as a JSON string (merged with config and defaults).",`Format: --header '{"Header-Name":"value"}'`,"Example:",` --header '{"X-Api-Key":"abc"}'`].join(`
|
|
69
|
+
`)).option("--header-encoded <base64url>",["Additional headers as base64url-encoded JSON (merged with config and defaults).","Use this when a shell or agent may strip quotes from literal JSON.","Example:"," --header-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9"].join(`
|
|
70
|
+
`)).action(async(e,t)=>{let r=t.api;if(!await fe(r))return;if(e.length>1){if(t.omitEmpty){d.result(w("INVALID_REQUEST_UPDATE",{summary:"--omit-empty requires a single operation request.",message:"Multiple operationIds prepare a request scenario without sending requests, so there are no request values to omit.",context:{api_name:r,operation_ids:e},nextCommand:`openapi-skills request <operationId> --api ${r} --omit-empty`})),process.exitCode=2;return}try{let{summaryText:a,payload:p}=await Zr(r,e,t.force===!0,t.forceRequest===!0);d.result(q({summary:a,operationIds:e,apiName:r},{kind:"request-prepare"})),process.exitCode=0}catch(a){let p=W(a);d.result(w("API_PARSE_ERROR",{summary:"Failed to prepare multi-operation request scenario.",message:p,context:{api_name:r,operation_ids:e}})),process.exitCode=1}return}let n=e[0];if(!n){d.result(w("INVALID_REQUEST_UPDATE",{summary:"An operationId is required.",message:"Provide at least one operationId to invoke.",context:{api_name:r},nextCommand:`openapi-skills request <operationId> --api ${r}`})),process.exitCode=1;return}let s,i;if(t.updateRequest&&t.updateRequestEncoded){d.result(w("INVALID_REQUEST_UPDATE",{summary:"Specify only one of --update-request or --update-request-encoded.",message:"Choose the raw JSON form or the base64url-encoded form, not both.",context:{api_name:r,operation_id:n},nextCommand:`openapi-skills request ${n} --api ${r} --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9`})),process.exitCode=2;return}if(t.updateRequest){let a;try{a=JSON.parse(t.updateRequest)}catch(g){let b=`Invalid JSON for --update-request: ${g instanceof Error?g.message:String(g)}`;d.result(w("INVALID_UPDATE_REQUEST_JSON",{summary:"--update-request JSON is malformed.",message:b,context:{api_name:r,operation_id:n,update_request:t.updateRequest},nextCommand:`openapi-skills request ${n} --api ${r} --update-request '{"field.path":"value"}'`})),process.exitCode=2;return}if(typeof a!="object"||Array.isArray(a)||!a||Object.keys(a).length===0){d.result(w("INVALID_REQUEST_UPDATE",{summary:"--update-request must be a non-empty JSON object.",message:"Use flattened dot-notation keys and provide at least one update.",context:{api_name:r,operation_id:n,update_request:t.updateRequest},nextCommand:`openapi-skills request ${n} --api ${r} --update-request '{"field.path":"value"}'`})),process.exitCode=2;return}let p=await X(r,n),c=tt(r,p,"request");if(t.force===!0||t.forceRequest===!0){let b=(await U()).apis?.[r]?.schemaType,T=b==="graphql";if(!T&&b!=="openapi")try{let h=await M.readJson(L(r));T=Array.isArray(h)&&h.some(y=>typeof y?.rootType=="string")}catch{T=!1}T||await Q(r,n,p),await Ce(r,p,t.force===!0,t.forceRequest===!0)}else if(!await M.pathExists(c)){d.result(w("REQUEST_TEMPLATE_STALE",{summary:"request.json does not exist for this operation.",message:"--update-request requires an existing request.json artifact. Use --force-request to regenerate it from the cached operation schema, or --force to refresh the schema too.",context:{api_name:r,operation_id:n,artifact_type:"request"},nextCommand:`openapi-skills request ${n} --api ${r} --force-request --update-request '{"field.path":"value"}'`})),process.exitCode=2;return}let u=await M.readJson(c),m=De(u),f=pt(a),l=Array.from(f).filter(g=>!m.has(g));if(l.length>0){d.result(w("INVALID_REQUEST_UPDATE",{summary:"--update-request contains keys not present in request.json.",message:`The following keys are missing from request.json: ${l.join(", ")}.`,context:{api_name:r,operation_id:n,update_request:t.updateRequest,missing_keys:l},nextCommand:`openapi-skills request ${n} --api ${r} ${t.force?"--force":"--force-request"}`})),process.exitCode=2;return}if(t.force===!0||t.forceRequest===!0){let g=Jt(u,a);g.length>0&&(i=g)}s=a}if(t.updateRequestEncoded){let a;try{a=ut(t.updateRequestEncoded,"--update-request-encoded")}catch(g){let b=`Invalid base64url for --update-request-encoded: ${g instanceof Error?g.message:String(g)}`;d.result(w("INVALID_UPDATE_REQUEST_JSON",{summary:"--update-request-encoded value is malformed.",message:b,context:{api_name:r,operation_id:n,update_request_encoded:t.updateRequestEncoded},nextCommand:`openapi-skills request ${n} --api ${r} --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9`})),process.exitCode=2;return}if(typeof a!="object"||Array.isArray(a)||!a||Object.keys(a).length===0){d.result(w("INVALID_REQUEST_UPDATE",{summary:"--update-request-encoded must decode to a non-empty JSON object.",message:"The decoded payload must contain at least one flattened dot-notation key.",context:{api_name:r,operation_id:n,update_request_encoded:t.updateRequestEncoded},nextCommand:`openapi-skills request ${n} --api ${r} --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9`})),process.exitCode=2;return}let p=await X(r,n),c=tt(r,p,"request");if(t.force===!0||t.forceRequest===!0){let b=(await U()).apis?.[r]?.schemaType,T=b==="graphql";if(!T&&b!=="openapi")try{let h=await M.readJson(L(r));T=Array.isArray(h)&&h.some(y=>typeof y?.rootType=="string")}catch{T=!1}T||await Q(r,n,p),await Ce(r,p,t.force===!0,t.forceRequest===!0)}else if(!await M.pathExists(c)){d.result(w("REQUEST_TEMPLATE_STALE",{summary:"request.json does not exist for this operation.",message:"--update-request-encoded requires an existing request.json artifact. Use --force-request to regenerate it from the cached operation schema, or --force to refresh the schema too.",context:{api_name:r,operation_id:n,artifact_type:"request"},nextCommand:`openapi-skills request ${n} --api ${r} --force-request --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9`})),process.exitCode=2;return}let u=await M.readJson(c),m=De(u),f=pt(a),l=Array.from(f).filter(g=>!m.has(g));if(l.length>0){d.result(w("INVALID_REQUEST_UPDATE",{summary:"--update-request-encoded contains keys not present in request.json.",message:`The following keys are missing from request.json: ${l.join(", ")}.`,context:{api_name:r,operation_id:n,update_request_encoded:t.updateRequestEncoded,missing_keys:l},nextCommand:`openapi-skills request ${n} --api ${r} ${t.force?"--force":"--force-request"}`})),process.exitCode=2;return}if(t.force===!0||t.forceRequest===!0){let g=Jt(u,a);g.length>0&&(i=g)}s=a}if(t.header&&t.headerEncoded){d.result(w("INVALID_JSON_ARGUMENT",{summary:"Provide only one of --header or --header-encoded.",message:"--header and --header-encoded are mutually exclusive.",context:{api_name:r,operation_id:n,header:t.header,header_encoded:t.headerEncoded},nextCommand:`openapi-skills request ${n} --api ${r} --header-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9`})),process.exitCode=2;return}let o;if(t.header)try{if(o=JSON.parse(t.header),typeof o!="object"||Array.isArray(o)||!o)throw new Error("--header must be a JSON object")}catch{d.result(w("INVALID_JSON_ARGUMENT",{summary:"--header JSON is malformed.",message:`Invalid --header JSON. Example: --header '{"X-Api-Key":"abc"}'`,context:{header:t.header},nextCommand:`openapi-skills request ${n} --api ${r} --header '{"Header-Name":"value"}'`})),process.exitCode=2;return}if(t.headerEncoded)try{o=ut(t.headerEncoded,"--header-encoded")}catch(a){let p=`Invalid base64url for --header-encoded: ${a instanceof Error?a.message:String(a)}`;d.result(w("INVALID_JSON_ARGUMENT",{summary:"--header-encoded value is malformed.",message:p,context:{header_encoded:t.headerEncoded},nextCommand:`openapi-skills request ${n} --api ${r} --header-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9`})),process.exitCode=2;return}if(t.validate)try{let a=await Lr(r,n,t.force,o,s,i,t.omitEmpty,t.forceRequest),p=ct(r,n);if(!a.valid){d.result(w("VALIDATION_FAILED",{summary:"Response validation failed.",message:(a.errors??[]).join("; ")||"The response did not match the expected schema.",context:{api_name:r,operation_id:n,validation_warnings:a.warnings??[],validation_errors:a.errors??[],operation_artifact_count:p.fileCount},nextCommand:`openapi-skills request ${n} --api ${r} --validate`})),process.exitCode=1;return}d.result(q({apiName:r,operationId:n,valid:a.valid,warnings:a.warnings??[],errors:a.errors??[],operationArtifactCount:p.fileCount,retrieveArtifacts:"Use `get-operation-artifact [--request|--response|--response-schema] <operationId>` to view this operation's artifacts."},{kind:"validation-result"})),process.exitCode=0}catch(a){d.result(w("VALIDATION_FAILED",{summary:"Validation failed.",message:W(a),context:{api_name:r,operation_id:n},nextCommand:`openapi-skills request ${n} --api ${r} --validate`})),process.exitCode=2;return}else try{let{request:a,response:p,warnings:c}=await Gt(r,n,t.force,o,s,i,t.omitEmpty,t.forceRequest);await Ut(r,n);let u=ct(r,n);d.result(q({apiName:r,operationId:n,warnings:c??[],fileCount:u.fileCount,retrieveArtifacts:"Use `get-operation-artifact [--request|--response|--response-schema] <operationId>` to view this operation's artifacts."},{kind:"request-result"})),process.exitCode=0}catch(a){d.result(w("REQUEST_FAILED",{summary:"Request failed.",message:W(a),context:{api_name:r,operation_id:n},nextCommand:`openapi-skills request ${n} --api ${r}`})),process.exitCode=2;return}});wi.agentMeta={name:"request",category:"Validation",usage:"openapi-skills request <operationId...> --api <apiName> [--validate] [--force] [--force-request] [--update-request <json>] [--update-request-encoded <base64url>] [--omit-empty] [--header <json>] [--header-encoded <base64url>]",description:["Make a live HTTP request for an operation, or prepare a multi-step request scenario without executing requests.","When multiple operationIds are supplied, the command enters prepare-only mode and refreshes request artifact templates for the scenario.","With --validate, validate only the response against the schema after the request is sent.","With --force, refresh the operation schema and regenerate the request artifact from defaults.","With --force-request, regenerate only the request artifact from the cached operation schema without refreshing the schema.",'With --update-request, patch the request artifact using flattened dot-notation keys. Nested JSON objects are accepted, but the provided value must be valid JSON. With --update-request-encoded, pass base64url-encoded JSON instead. With --omit-empty on a single-operation request, remove empty-string values from schema-optional fields after updates and persist the cleaned artifact; this option is not available in multi-operation prepare-only mode. With --header, merge JSON headers into the request. With --header-encoded, pass base64url-encoded JSON headers instead. Binary fields can be set to a file path string or a file descriptor object. Set a field to "__delete__" to remove it.'].join(" "),arguments:[{name:"operationId",type:"string[]",required:!0,positional:!0,description:"One or more operationIds to invoke. Multiple values switch the command into prepare-only mode for a multi-step scenario."},{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."},{name:"validate",type:"flag",required:!1,flag:!0,description:"Validate only the response against the schema after the request is sent. Does not validate the request body or guarantee a response exists."},{name:"force",type:"flag",required:!1,flag:!0,description:"Refresh the operation schema and overwrite the request artifact with defaults."},{name:"force-request",type:"flag",required:!1,flag:!0,description:"Force overwrite only the request artifact with defaults from the cached operation schema; does not refresh the operation schema. If used with --force, --force behavior applies."},{name:"omit-empty",type:"flag",required:!1,flag:!0,description:"For single-operation requests, remove empty-string values from schema-optional fields after updates and persist the cleaned request artifact."},{name:"update-request",type:"json",required:!1,flag:!0,description:'Patch request artifact before making the request. Only flattened object dot-notation keys are allowed. Binary fields can be set to a file path string or file descriptor object. Set a field to "__delete__" to remove it. Use with --force-request to rebuild defaults from the cached schema, or --force to refresh the schema too.'},{name:"update-request-encoded",type:"string",required:!1,flag:!0,description:"Patch request artifact before making the request using base64url-encoded JSON. Use this when quoting is unreliable."},{name:"header",type:"json",required:!1,flag:!0,description:"Additional headers as a JSON string."},{name:"header-encoded",type:"string",required:!1,flag:!0,description:"Additional headers as base64url-encoded JSON. Use this when quoting is unreliable."}],examples:["openapi-skills request getPetById --api petstore","openapi-skills request getPetById --api petstore --validate","openapi-skills request createPet --api petstore --omit-empty",`openapi-skills request getPetById --api petstore --force-request --update-request '{"user.profile.name":"Ada"}'`,"openapi-skills request getPetById --api petstore --force-request","openapi-skills request getPetById --api petstore --force --update-request-encoded eyJyZXF1ZXN0Qm9keS5pZCI6MTJ9",`openapi-skills request getPetById --api petstore --update-request '{"user.profile.name":"Ada"}'`,`openapi-skills request getPetById --api petstore --update-request '{"parameters.0.id":1}'`,"openapi-skills request getPetById --api petstore --header-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9",`openapi-skills request getPetById --api petstore --update-request '{"parameters.0":"__delete__"}'`,"openapi-skills request operationId1 operationId2 --api petstore"],returns:{type:"json",description:"Returns raw request and response for single-operation requests, or a structured batch preparation summary when multiple operationIds are supplied."},sideEffects:{writesFiles:!0,readsFiles:!0,network:!0},constraints:{destructive:!1,idempotent:!1,requiresParsedApi:!0},filesWritten:["request artifact","response artifact","response-schema artifact (when response has JSON body)"]};bi=j.command("set-env").requiredOption("--api <apiName>","API name to use").option("--base-url <url>","Base URL for the API environment.").option("--auth <json>","Authentication headers as a JSON string.").option("--auth-encoded <base64url>","Authentication headers as base64url-encoded JSON. Use this when a shell or agent may strip quotes from literal JSON.").option("--var <key=value>","Set a runtime variable for the API environment. Repeatable.",(e,t)=>[...Array.isArray(t)?t:t?[t]:[],e]).description("Set or update the runtime environment for a parsed API.").addHelpText("after",["Use this command to set baseUrl, auth headers, and runtime vars for a parsed API.","Pass auth headers with --auth as JSON or --auth-encoded as base64url-encoded JSON when quoting is unreliable.","","Examples:",` set-env --api petstore --base-url https://dev.example.com --auth '{"Authorization":"Bearer abc"}'`," set-env --api petstore --auth-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9",` set-env --api petstore --auth '{"Authorization":"Bearer abc"}'`," set-env --api petstore --var userId=123"].join(`
|
|
71
|
+
`)).action(async e=>{let t=e.api;if(!await fe(t))return;let r=typeof e.baseUrl=="string"?e.baseUrl.trim():"",n=r.length>0?r:void 0,s;if(typeof e.auth=="string"&&typeof e.authEncoded=="string"){d.result(w("INVALID_JSON_ARGUMENT",{summary:"Provide only one of --auth or --auth-encoded.",message:"--auth and --auth-encoded are mutually exclusive.",context:{api_name:t,auth:e.auth,auth_encoded:e.authEncoded},nextCommand:`openapi-skills set-env --api ${t} --auth-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9`})),process.exitCode=1;return}if(typeof e.auth=="string")try{let a=JSON.parse(e.auth);if(typeof a!="object"||Array.isArray(a)||!a)throw new Error("Auth must be a JSON object");s=a}catch{d.result(w("INVALID_JSON_ARGUMENT",{summary:"--auth JSON is malformed.",message:`Invalid --auth JSON. Example: '{"Authorization":"Bearer abc"}'`,context:{api_name:t,auth:e.auth??null},nextCommand:`openapi-skills set-env --api ${t} --auth '{"Authorization":"Bearer abc"}'`})),process.exitCode=1;return}if(typeof e.authEncoded=="string")try{let a=ut(e.authEncoded,"--auth-encoded"),p={};for(let[c,u]of Object.entries(a)){if(typeof u!="string")throw new Error(`Auth header "${c}" must be a string`);p[c]=u}s=p}catch(a){d.result(w("INVALID_JSON_ARGUMENT",{summary:"--auth-encoded value is malformed.",message:`Invalid base64url for --auth-encoded: ${a instanceof Error?a.message:String(a)}`,context:{api_name:t,auth_encoded:e.authEncoded},nextCommand:`openapi-skills set-env --api ${t} --auth-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9`})),process.exitCode=1;return}let i=e.var?Array.isArray(e.var)?e.var:[e.var]:[],o={};for(let a of i){let p=a.indexOf("=");if(p<=0){d.result(w("INVALID_VARIABLE_SYNTAX",{summary:"Invalid --var syntax.",message:`Invalid --var value "${a}". Use key=value.`,context:{api_name:t,variable:a},nextCommand:`openapi-skills set-env --api ${t} --var userId=123`})),process.exitCode=1;return}let c=a.slice(0,p).trim(),u=a.slice(p+1);if(!c){d.result(w("INVALID_VARIABLE_SYNTAX",{summary:"Invalid --var syntax.",message:`Invalid --var value "${a}". Use key=value.`,context:{api_name:t,variable:a},nextCommand:`openapi-skills set-env --api ${t} --var userId=123`})),process.exitCode=1;return}o[c]=u}try{let a={};n!==void 0&&(a.baseUrl=n),s!==void 0&&(a.auth=s),Object.keys(o).length>0&&(a.vars=o),await Te(t,a),d.result(q({apiName:t,baseUrl:n,hasAuth:s!==void 0,varCount:Object.keys(o).length},{kind:"set-env-result"}))}catch(a){d.result(w("CONFIG_ERROR",{summary:"Failed to update API environment.",message:W(a),context:{api_name:t,base_url:n??null,var_count:Object.keys(o).length},nextCommand:`openapi-skills set-env --api ${t}`})),process.exitCode=1}});bi.agentMeta={name:"set-env",category:"Configuration",usage:"openapi-skills set-env --api <apiName> [--base-url <url>] [--auth <json>] [--auth-encoded <base64url>] [--var key=value]",description:"Set or update the runtime environment for a parsed API. Persists baseUrl, auth headers, and named vars in config.json.",arguments:[{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."},{name:"base-url",type:"string",required:!1,flag:!0,description:"Base URL for the API environment."},{name:"auth",type:"json",required:!1,flag:!0,description:"Authentication headers as a JSON object."},{name:"auth-encoded",type:"string",required:!1,flag:!0,description:"Authentication headers as base64url-encoded JSON."},{name:"var",type:"string",required:!1,flag:!0,description:"Runtime variable in key=value form. Repeatable."}],examples:[`openapi-skills set-env --api petstore --base-url https://dev.example.com --auth '{"Authorization":"Bearer abc"}'`,"openapi-skills set-env --api petstore --auth-encoded eyJBdXRob3JpemF0aW9uIjoiQmVhcmVyIGFiYyJ9",`openapi-skills set-env --api petstore --auth '{"Authorization":"Bearer abc"}'`,"openapi-skills set-env --api petstore --var userId=123 --var env=staging"],returns:{type:"json",description:"Returns success or error message."},sideEffects:{writesFiles:!0,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!1,requiresParsedApi:!1},filesWritten:["config.json"]};Ai=j.command("get-env").requiredOption("--api <apiName>","API name to use").option("--base-url","Include baseUrl in output").option("--auth","Include auth headers in output").option("--var <key=value>","Request one or more runtime vars. Repeatable; only the key part is used to filter output.",(e,t)=>[...Array.isArray(t)?t:t?[t]:[],e]).description("Read API environment configuration from `.openapi-skills/config.json`. Returns all values unless a specific field is requested via flags.").action(async e=>{let t=e.api;if(await fe(t))try{let r=e.baseUrl===!0,n=e.auth===!0,s=e.var?Array.isArray(e.var)?e.var:[e.var]:[],i=r||n||s.length>0,o=await st(t,"baseUrl"),a=await st(t,"authHeaders"),p=await st(t,"vars"),c=Array.isArray(p)?p:[],u=Object.fromEntries(c),m={apiName:t};if((!i||r)&&(m.baseUrl=o),(!i||n)&&(m.authHeaders=a),!i)m.vars=c;else if(s.length>0){let f=s.map(l=>{let g=l.indexOf("=");return g>=0?l.slice(0,g).trim():l.trim()}).filter(Boolean);m.vars=f.map(l=>[l,u[l]]).filter(([l,g])=>g!==void 0)}d.result(q(m,{kind:"get-env-result"})),process.exitCode=0}catch(r){d.result(w("CONFIG_ERROR",{summary:"Failed to read API environment.",message:r instanceof Error?r.message:String(r),context:{api_name:t},nextCommand:`openapi-skills get-env --api ${t}`})),process.exitCode=1}});Ai.agentMeta={name:"get-env",category:"Configuration",usage:"openapi-skills get-env --api <apiName>",description:"Read environment configuration for an API. Returns all values by default, or only a specific field when a flag is provided.",arguments:[{name:"api",type:"string",required:!0,flag:!0,description:"The API name as defined in .openapi-skills/config.json."}],examples:["openapi-skills get-env --api petstore","openapi-skills get-env --api petstore --base-url","openapi-skills get-env --api petstore --var userId"],returns:{type:"json",description:"Prints { apiName, baseUrl, authHeaders, vars } where vars is an entries array."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!1},filesWritten:[]};Ti=j.command("get-api-names").description("List all available API names (parsed OpenAPI bundles) in the project.").action(async()=>{try{let e=await ue();d.result(q({apiNames:e},{kind:"api-list"})),(!e||e.length===0)&&d.warn("No APIs were generated yet. Run first: openapi-skills generate <openapi-source> [options]")}catch{d.result(w("CONFIG_ERROR",{summary:"Failed to list APIs.",message:"Run `openapi-skills generate [options] [openapi-source]` to parse APIs first.",context:{},nextCommand:"openapi-skills generate <openapi-source>"})),process.exitCode=1}});Ti.agentMeta={name:"get-api-names",category:"Navigation",usage:"openapi-skills get-api-names",description:"List all available parsed API names in the project. Output is always JSON: { kind: 'api-list', apiNames: [<apiName>, ...] }.",arguments:[],examples:["openapi-skills get-api-names"],returns:{type:"json",description:"Returns { kind: 'api-list', apiNames: [<apiName>, ...] } as JSON."},sideEffects:{writesFiles:!1,readsFiles:!0,network:!1},constraints:{destructive:!1,idempotent:!0,requiresParsedApi:!1},filesWritten:[]};ki=j.command("remove-api <apiName>").description("Remove an API from config.json and delete its .openapi-skills directory after confirmation.").option("-y, --yes","Confirm removal automatically without prompting.").action(async(e,t)=>{let r=e;try{if(!(await ue()).includes(r)){d.result(w("UNKNOWN_API",{summary:`API '${r}' is not installed.`,message:`API '${r}' is not installed.`,context:{api_name:r},nextCommand:"openapi-skills get-api-names"})),process.exitCode=1;return}if(!(t?.yes===!0?!0:await Hr(r))){d.result(q({cancelled:!0,apiName:r},{kind:"remove-api-result"})),process.exitCode=0;return}let i=await cr(r);if(i.ok){d.result(q({removedApi:i.data.removedApi,message:i.message},{kind:"remove-api-result"})),process.exitCode=0;return}let o=/config/i.test(i.error.message)?"CONFIG_ERROR":i.error.type==="ApiNotFound"?"UNKNOWN_API":"REQUEST_FAILED";d.result(w(o,{summary:`Remove API error for ${r}.`,message:i.error.message,context:{api_name:r},nextCommand:o==="UNKNOWN_API"?"openapi-skills get-api-names":"None"})),process.exitCode=1;return}catch(n){let s=n instanceof Error?n.message:String(n);d.result(w(/config/i.test(s)?"CONFIG_ERROR":"REQUEST_FAILED",{summary:`Remove API error for ${r}.`,message:s,context:{api_name:r},nextCommand:/config/i.test(s)?"None":`openapi-skills remove-api ${r} --yes`})),process.exitCode=1}});ki.agentMeta={name:"remove-api",category:"Configuration",usage:"openapi-skills remove-api <apiName> [--yes|-y]",description:"Remove a parsed API after confirmation. The command deletes the API entry from config.json and removes the API directory under .openapi-skills.",arguments:[{name:"apiName",type:"string",required:!0,positional:!0,description:"The API name to remove."},{name:"yes",type:"flag",required:!1,flag:!0,description:"Confirm removal automatically without prompting."}],examples:["openapi-skills remove-api petstore --yes"],returns:{type:"json",description:"Returns a structured success or error result for the deletion operation."},sideEffects:{writesFiles:!0,readsFiles:!0,network:!1},constraints:{destructive:!0,idempotent:!1,requiresParsedApi:!0},filesWritten:["config.json"]};j.parse(process.argv)});await Br();export{j as program};
|