@redocly/cli 2.41.2 → 2.43.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 +15 -0
- package/THIRD_PARTY_NOTICES +3 -2
- package/lib/chunks/32XCOMOR.js +7 -0
- package/lib/chunks/3BCHPW6T.js +22 -0
- package/lib/chunks/3VZLNQK3.js +47 -0
- package/lib/chunks/4VF6MPJJ.js +11 -0
- package/lib/chunks/55GMSQDD.js +7 -0
- package/lib/chunks/5E3VKU5T.js +7 -0
- package/lib/chunks/AE6JGTY4.js +7 -0
- package/lib/chunks/C35TOMVY.js +8 -0
- package/lib/chunks/D5T6ETPZ.js +8 -0
- package/lib/chunks/DNOXLF53.js +8 -0
- package/lib/chunks/E36IFTLX.js +59 -0
- package/lib/chunks/ECZUPR2N.js +7 -0
- package/lib/chunks/EU6GURJZ.js +7 -0
- package/lib/chunks/HXYO6QS2.js +3132 -0
- package/lib/chunks/IW4HG6VD.js +19 -0
- package/lib/chunks/KIVPQZDC.js +31 -0
- package/lib/chunks/KLY5RV3W.js +7 -0
- package/lib/chunks/KM7RL6C4.js +2317 -0
- package/lib/chunks/L3YH7RCT.js +8 -0
- package/lib/chunks/NEWT5A6S.js +159 -0
- package/lib/chunks/NGPG6D6W.js +7 -0
- package/lib/chunks/O6MCQRCP.js +59 -0
- package/lib/chunks/O6PRCLSV.js +13 -0
- package/lib/chunks/OFAMJNQ6.js +7 -0
- package/lib/chunks/P26PQ2RU.js +7 -0
- package/lib/chunks/PFD7KGH7.js +93 -0
- package/lib/chunks/QFG7TTKG.js +22 -0
- package/lib/chunks/RFWIIJFG.js +7 -0
- package/lib/chunks/RS5PUOTT.js +18 -0
- package/lib/chunks/TMQJQANP.js +7 -0
- package/lib/chunks/UPPWQBGX.js +7 -0
- package/lib/chunks/UXH3ZSSV.js +9 -0
- package/lib/chunks/UYZXI3NO.js +7 -0
- package/lib/chunks/WNTLDT6L.js +184 -0
- package/lib/chunks/WZXA5XPB.js +7 -0
- package/lib/chunks/X6IKW6K4.js +7 -0
- package/lib/index.js +226 -13885
- package/package.json +1 -1
- package/lib/chunks/3CX2Z7JI.js +0 -496
- package/lib/chunks/3UUTQVCJ.js +0 -3614
- package/lib/chunks/4FB5ZIPP.js +0 -1133
- package/lib/chunks/5ILQMFXK.js +0 -59
- package/lib/chunks/7F5O43EU.js +0 -1756
- package/lib/chunks/7IX44JLO.js +0 -16
- package/lib/chunks/7MOL2QVN.js +0 -92635
- package/lib/chunks/A3VFVVHD.js +0 -25
- package/lib/chunks/A6JSOHCP.js +0 -41
- package/lib/chunks/AIT3U3JT.js +0 -22
- package/lib/chunks/ASYQPOQY.js +0 -681
- package/lib/chunks/BVP23YP7.js +0 -13374
- package/lib/chunks/FO6BDVGE.js +0 -25
- package/lib/chunks/GFU5KGSW.js +0 -92
- package/lib/chunks/ICPYP2LP.js +0 -401
- package/lib/chunks/KPMZLKQG.js +0 -79
- package/lib/chunks/KRMBH6JF.js +0 -17902
- package/lib/chunks/NLIKC7UP.js +0 -528
- package/lib/chunks/NW3XJZXQ.js +0 -175
- package/lib/chunks/P6UGG7F6.js +0 -414
- package/lib/chunks/RRC5IDC3.js +0 -2416
- package/lib/chunks/T6UZU3XM.js +0 -17
- package/lib/chunks/TS33ZDKX.js +0 -35
- package/lib/chunks/UUU33DK3.js +0 -125
- package/lib/chunks/VUDTNFRL.js +0 -42
- package/lib/chunks/VXIQEZPR.js +0 -2564
- package/lib/chunks/W7G5WVPB.js +0 -44
- package/lib/chunks/XB6C62FW.js +0 -18497
- package/lib/chunks/XHPY6UJF.js +0 -1638
- package/lib/chunks/Y6DTFCLS.js +0 -15
- package/lib/chunks/Z2664VV5.js +0 -39331
- package/lib/chunks/Z2I5YXYN.js +0 -20272
- package/lib/chunks/ZK3QRKL5.js +0 -129
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __pathDirname } from 'node:path';
|
|
4
|
+
const require = __createRequire(import.meta.url);
|
|
5
|
+
var __filename = __fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __pathDirname(__filename);
|
|
7
|
+
import{a as G}from"./UXH3ZSSV.js";import{c as I,d as N,e as fe,h as q,j as _,k as ue,v as D,w as B}from"./L3YH7RCT.js";import{a as ce,c as pe}from"./C35TOMVY.js";import{b as ae}from"./X6IKW6K4.js";import{B as oe,C as P,O as y,c as b,ca as se,ia as ie,l as $}from"./WNTLDT6L.js";import"./NEWT5A6S.js";import"./RFWIIJFG.js";import{mkdir as Bt,writeFile as zt}from"node:fs/promises";import Ht from"node:path";import*as Ce from"node:process";var Ve=/^[a-zA-Z][a-zA-Z0-9]*(?:[_\-.][a-zA-Z0-9]+)*$/,Fe=/^[0-9a-f-]{8,}$/i,Ye=[["uuid",/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i],["date-time",/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})$/],["date",/^\d{4}-\d{2}-\d{2}$/],["email",/^[^\s@]+@[^\s@]+\.[^\s@]+$/],["uri",/^https?:\/\/\S+$/],["ipv4",/^(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)$/]],J=new WeakMap;function z(e){return{formats:Ye.filter(([,t])=>t.test(e)).map(([t])=>t),values:[e],count:1,overflow:!1}}function C(e,t){if(!e)return t;if(!t)return e;let r={formats:e.formats.filter(n=>t.formats.includes(n)),values:[],count:e.count+t.count,overflow:e.overflow||t.overflow};if(!r.overflow){let n=[...e.values];for(let o of t.values)n.includes(o)||n.push(o);n.length>10?r.overflow=!0:r.values=n}return r}function H(e,t){J.set(e,t)}function L(e){return J.get(e)}function U(e,t){let r=J.get(e);r&&J.set(t,r)}function Ke(e){return e.length<=30&&!Fe.test(e)&&Ve.test(e)}function W(e,t){return e.formats.length>0?{format:e.formats[0]}:t&&!e.overflow&&e.count>=4&&e.values.length>0&&e.values.length<=5&&e.values.length*2<=e.count&&e.values.every(Ke)?{enum:[...e.values].sort()}:{}}function R(e){let t=J.get(e);if(t){let r=typeof e.type=="string"?[e.type]:e.type??[];r.includes("string")&&Object.assign(e,W(t,r.length===1))}for(let r of Object.values(e.properties??{}))R(r);e.additionalProperties&&R(e.additionalProperties),e.items&&R(e.items);for(let r of e.oneOf??[])R(r)}function me(e){for(let t of Object.values(e.paths))for(let r of Object.values(t)){for(let n of Object.values(r.requestBody?.content??{}))R(n.schema);for(let n of Object.values(r.responses))for(let o of Object.values(n.content??{}))R(o.schema)}for(let t of Object.values(e.components?.schemas??{}))R(t);return e}var be=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,F=/^\d+$/,We=/^[0-9a-hjkmnp-tv-z]{26}$/i,Xe=/^[a-z][a-z0-9]*_(?=[0-9a-z]*\d)[0-9a-z]{10,}$/i,Ze=/^[a-z](?=[a-z0-9]*\d)[a-z0-9]{23,24}$/,Z=new Set(ce),Qe=new Set(["get","head"]),de="application/x-www-form-urlencoded",le="multipart/form-data";function et(e){return e?F.test(e)||be.test(e)||We.test(e)||Xe.test(e)||Ze.test(e)?!0:/^[0-9a-f]{16,}$/i.test(e):!1}function Q(e){let t=e.split("/"),r=[],n=new Set;return{template:t.map((s,a)=>{if(!et(s))return s;let i=t[a-1],c=i?`${$(i,1)}Id`:"id",p=1;for(;n.has(c);)p+=1,c=i?`${$(i,1)}Id${p}`:`id${p}`;return n.add(c),r.push({name:c,value:s}),`{${c}}`}).join("/")||"/",params:r}}function A(e){if(e===null)return{type:"null"};if(Array.isArray(e)){if(e.length===0)return{type:"array"};let t=e.slice(0,20).map(A);return{type:"array",items:x(t)}}switch(typeof e){case"string":{let t={type:"string"};return H(t,z(e)),t}case"boolean":return{type:"boolean"};case"number":return Number.isInteger(e)?{type:"integer"}:{type:"number"};case"object":{let t=Object.entries(e);if(t.length>0&&(t.every(([a])=>F.test(a))||t.every(([a])=>be.test(a))))return{type:"object",additionalProperties:x(t.map(([,a])=>A(a)))};let r={},n=[];for(let[s,a]of t)r[s]=A(a),n.push(s);let o={type:"object",properties:r};return n.length>0&&(o.required=n),o}default:return{}}}function x(e){if(e.length===0)return{};let[t,...r]=e,n=t;for(let o of r)n=V(n,o);return n}function he(e){return Object.keys(e).length===0}function k(e){return e.additionalProperties?"map":e.type==="object"?"object":e.type==="array"?"array":"scalar"}function X(e){return e.oneOf?e.oneOf.flatMap(X):Array.isArray(e.type)?e.type.map(t=>{if(t==="object"){let n={type:"object"};return e.properties&&(n.properties=e.properties),e.required&&(n.required=e.required),e.additionalProperties&&(n.additionalProperties=e.additionalProperties),n}if(t==="array")return e.items?{type:"array",items:e.items}:{type:"array"};let r={type:t};return t==="string"&&U(e,r),r}):[e]}var tt=.5,rt=3;function we(e,t){let r=Object.keys(e.properties??{}),n=Object.keys(t.properties??{});if(r.length===0||n.length===0)return 1;let o=new Set(n),s=r.filter(a=>o.has(a)).length;return s/(r.length+n.length-s)}function nt(e,t){let r=k(e);if(r!==k(t))return!1;switch(r){case"scalar":return e.type===t.type||e.type==="integer"&&t.type==="number"||e.type==="number"&&t.type==="integer";case"object":return we(e,t)>=tt;default:return!0}}function ve(e,t){switch(k(e)){case"scalar":{if(e.type!==t.type)return{type:"number"};if(e.type==="string"){let r=C(L(e),L(t));if(r){let n={type:"string"};return H(n,r),n}}return e}case"map":return{type:"object",additionalProperties:V(e.additionalProperties??{},t.additionalProperties??{})};case"object":{let r={...e.properties??{}};for(let[a,i]of Object.entries(t.properties??{}))r[a]=r[a]?V(r[a],i):i;let n=new Set(t.required??[]),o=(e.required??[]).filter(a=>n.has(a)),s={type:"object",properties:r};return o.length>0&&(s.required=o),s}case"array":{if(!e.items||!t.items){let r=e.items??t.items;return r?{type:"array",items:r}:{type:"array"}}return{type:"array",items:V(e.items,t.items)}}}}function ot(e){let t=[...e],r=()=>t.filter(n=>k(n)==="object").length;for(;r()>rt;){let n=-1,o=-1,s=-1;for(let a=0;a<t.length;a++)if(k(t[a])==="object")for(let i=a+1;i<t.length;i++){if(k(t[i])!=="object")continue;let c=we(t[a],t[i]);c>s&&(s=c,n=a,o=i)}t[n]=ve(t[n],t[o]),t.splice(o,1)}return t}var st=["boolean","integer","number","string","null"];function it(e){if(e.length===1)return e[0];let t=[],r=new Set,n;for(let i of e)k(i)==="scalar"&&typeof i.type=="string"?(r.add(i.type),i.type==="string"&&(n=C(n,L(i)))):t.push(i);let o=st.filter(i=>r.has(i)),s=i=>{let c={type:i};return(typeof i=="string"?i==="string":i.includes("string"))&&n&&H(c,n),c};if(t.length===0)return o.length===1?s(o[0]):s(o);if(t.length===1&&o.length===1&&o[0]==="null"&&typeof t[0].type=="string")return{...t[0],type:[t[0].type,"null"]};let a=[...t];return o.length===1?a.push(s(o[0])):o.length>1&&a.push(s(o)),{oneOf:a}}function V(e,t){if(he(e)||he(t))return{};let r=X(e);for(let n of X(t)){let o=r.findIndex(s=>nt(s,n));o===-1?r.push(n):r[o]=ve(r[o],n)}return it(ot(r))}function at(e){if(!e)return;let t=e.trim();if(!(!t.startsWith("{")&&!t.startsWith("[")))try{return JSON.parse(t)}catch{return}}function ct(e,t){let r=t?.match(/boundary="?([^";,]+)"?/i)?.[1];if(!r)return;let n={};for(let o of e.split(`--${r}`)){let s=o.match(/^\r?\n([\s\S]*?)\r?\n\r?\n([\s\S]*)\r?\n$/);if(!s)continue;let[,a,i]=s,c=a.match(/\bname="([^"]*)"/i)?.[1];c!==void 0&&(n[c]=/\bfilename="/i.test(a)?{type:"string",format:"binary"}:A(i))}if(Object.keys(n).length!==0)return{type:"object",properties:n,required:Object.keys(n)}}function ge(e){let t=_(e.contentType);if(e.bodyJson!==void 0)return{mime:ue(t)?t:"application/json",schema:A(e.bodyJson)};if(t===de&&e.bodyText){let n={};for(let[o,s]of new URLSearchParams(e.bodyText))n[o]=s;return Object.keys(n).length===0?void 0:{mime:de,schema:A(n)}}if(t===le&&e.bodyText){let n=ct(e.bodyText,e.contentType);return n?{mime:le,schema:n}:void 0}let r=at(e.bodyText);if(r!==void 0)return{mime:"application/json",schema:A(r)}}function ye(e,t,r){let n=e.get(t);e.set(t,n?x([n,r]):r)}async function Oe(e){let t=await N(e.trafficPath);if(t.length===0)throw new Error("No traffic files found in the provided traffic path.");let r=D(e.server),n=new Map,o=new Set,s=0,a=c=>{let p=c.request.method.toLowerCase();if(!Z.has(p))return;let f=c.request.path||"/";if(r){let u=B(c.request,r);if(u===void 0)return;f=u}else c.request.host&&!fe(c.request.host)&&o.add(`${c.request.protocol}//${c.request.host}`);let{template:l,params:m}=Q(q(f)),w=`${p} ${l}`,d=n.get(w);d||(d={method:p,template:l,pathParams:new Map,queryParams:new Map,requestBodies:new Map,responses:new Map},n.set(w,d));for(let{name:u,value:h}of m){let g=d.pathParams.get(u);d.pathParams.set(u,{numeric:(g?.numeric??!0)&&F.test(h),observations:C(g?.observations,z(h))})}for(let u of new Set(c.request.query.keys())){let h=c.request.query.getAll(u),g=d.queryParams.get(u),v=h.length>0&&h.every(O=>F.test(O)),S=g?.observations;for(let O of h)S=C(S,z(O));d.queryParams.set(u,{numeric:(g?.numeric??!0)&&v,observations:S})}if(!Qe.has(p)){let u=ge(c.request);u&&ye(d.requestBodies,u.mime,u.schema)}if(c.response&&c.response.status>=100){let u=String(c.response.status),h=d.responses.get(u);h||(h={bodies:new Map},d.responses.set(u,h)),h.statusText??=c.response.statusText||void 0;let g=ge(c.response);g&&ye(h.bodies,g.mime,g.schema)}};for(let c of t){let p=await G(c,e.format);if(!p){y.warn(`Skipping traffic file with unrecognized format: ${c}
|
|
8
|
+
`);continue}s+=1;for await(let f of p.parse(c))a(f)}if(s===0)throw new Error("No supported traffic files found to generate an OpenAPI description from.");if(n.size===0)throw new Error(r?`No HTTP exchanges in the traffic matched the server "${r}".`:"No HTTP exchanges were observed in the traffic. Cannot generate an OpenAPI description.");let i=r?[r]:Array.from(o).sort();return pt(n,e.title??"Generated API",i)}function $e(e){return Object.values(e.paths).reduce((t,r)=>t+Object.keys(r).length,0)}function Se(e,t){if(e.numeric)return{type:"integer"};let r={type:"string"};return e.observations&&Object.assign(r,W(e.observations,t)),r}function pt(e,t,r){let n={};for(let o of e.values()){let s=n[o.template]??={},a=[...Array.from(o.pathParams).map(([c,p])=>({name:c,in:"path",required:!0,schema:Se(p,!1)})),...Array.from(o.queryParams).map(([c,p])=>({name:c,in:"query",required:!1,schema:Se(p,!0)}))],i={operationId:ft(o.method,o.template),responses:{}};if(a.length>0&&(i.parameters=a),o.requestBodies.size>0){let c={};for(let[p,f]of o.requestBodies)c[p]={schema:f};i.requestBody={content:c}}if(o.responses.size===0)i.responses.default={description:"Observed response"};else for(let[c,p]of o.responses){let f={description:p.statusText||"Observed response"};if(p.bodies.size>0){let l={};for(let[m,w]of p.bodies)l[m]={schema:w};f.content=l}i.responses[c]=f}s[o.method]=i}return{openapi:"3.2.0",info:{title:t,version:"1.0.0"},...r.length>0?{servers:r.map(o=>({url:o}))}:{},paths:n}}function ft(e,t){let r=t.split("/").filter(Boolean).map(n=>n.replace(/[{}]/g,"")).join("-");return`${e}-${r||"root"}`}function Y(e,t){return`${e.toUpperCase()} ${t}`}function Pe(e,t){let r;if(e.bodyJson!==void 0)try{r=JSON.stringify(e.bodyJson)}catch{r=void 0}if(r??=e.bodyText,!r)return;let n=r.trim();if(n)return n.length>t?`${n.slice(0,t)}\u2026[truncated]`:n}function Te(e){if(!e)return"";let t=e.bodyJson;return t===void 0?e.bodyText?_(e.contentType)||"text":"":t===null?"null":Array.isArray(t)?`array<${t.length>0?Ee(t[0]):""}>`:Ee(t)}function Ee(e){return b(e)?Object.keys(e).sort().join(","):e===null?"null":typeof e}async function Re(e){let t=e.perGroup??2,r=e.perOperation??4,n=e.maxBodyChars??2e3,o=D(e.server),s=await N(e.trafficPath),a=new Map;for(let c of s){let p=await G(c,e.format);if(p)for await(let f of p.parse(c)){let l=f.request.method.toUpperCase();if(!Z.has(l.toLowerCase()))continue;let m=f.request.path||"/";if(o){let ne=B(f.request,o);if(ne===void 0)continue;m=ne}let w=q(m),{template:d}=Q(w),u=f.response&&f.response.status>=100?f.response:void 0,h=u?.status,g=`${Te(f.request)}\u2192${Te(u)}`,v=a.get(Y(l,d));v||(v=new Map,a.set(Y(l,d),v));let S=`${h??""} ${g}`,O=v.get(S);O||(O=[],v.set(S,O)),!(O.length>=t)&&O.push({method:l,path:w,query:f.request.query.toString(),status:h,requestContentType:f.request.contentType,requestBody:Pe(f.request,n),responseContentType:u?.contentType,responseBody:u?Pe(u,n):void 0})}}let i=new Map;for(let[c,p]of a){let f=[];for(let l=0;l<t&&f.length<r;l++)for(let m of p.values()){if(f.length>=r)break;m[l]&&f.push(m[l])}i.set(c,f)}return i}var ut=`You are an expert API designer. You are given one operation from an OpenAPI 3.2 description that was inferred mechanically from recorded HTTP traffic, the component schemas it references, and a sample of the real recorded HTTP exchanges for that operation. The inferred description is only a hypothesis: types are coarse, every observed property is marked required, and descriptions are missing. Alternative body shapes observed in the traffic appear as "oneOf" variants or type unions. Common string formats (uuid, date-time, date, email, uri, ipv4) and small closed enums are detected conservatively from the observed values.
|
|
9
|
+
|
|
10
|
+
Refine the operation into the most accurate OpenAPI 3.2 definition you can justify from the evidence, while staying conservative:
|
|
11
|
+
- Keep the path template and the HTTP method exactly as given. Do not rename path parameters, do not move parameters to the path item level, and keep every response status code. The result is programmatically checked and rejected otherwise.
|
|
12
|
+
- Keep the operationId unless it is clearly wrong.
|
|
13
|
+
- Narrow property types where the samples clearly support it (formats such as date-time, uuid, email, uri; integer vs number; enums when a field only ever takes a small fixed set of values). Verify the formats and enums already detected against the samples; correct or extend them where justified. The detected formats and enums were derived from the full recorded traffic while you see only a subset of it, so never remove a detected format or enum value merely because the samples do not show it \u2014 correct one only when a sample contradicts it.
|
|
14
|
+
- Relax "required" for properties that are plausibly optional (e.g. absent in some samples, or clearly nullable). Express nullable values as type unions such as ["string", "null"].
|
|
15
|
+
- When a request or response body has alternative shapes \u2014 the baseline shows "oneOf" variants, or the samples show clearly different payloads \u2014 model them explicitly with "oneOf". Name each variant in components/schemas, and add a "discriminator" when a property (such as "type" or "kind") selects the variant.
|
|
16
|
+
- Factor structure shared between variants or schemas with "allOf": extract the common base into components/schemas and compose each variant as "allOf" of the base plus its specific properties.
|
|
17
|
+
- Keep the $ref references to the component schemas you were given. You may refine the definition of a referenced component when the samples justify it, and you may add new components, but never rename an existing component and never reuse a reserved component name listed in the input.
|
|
18
|
+
- Add concise, useful "summary" and "description" fields to the operation, its parameters and important schema properties.
|
|
19
|
+
- Add example values drawn from the real samples where helpful, but never copy values that look like secrets or personal data (tokens, API keys, passwords, session identifiers, email addresses, personal names); use clearly fictional placeholder values instead.
|
|
20
|
+
|
|
21
|
+
Output ONLY a YAML document with this exact top-level structure:
|
|
22
|
+
|
|
23
|
+
paths:
|
|
24
|
+
<the path template exactly as given>:
|
|
25
|
+
<the method>:
|
|
26
|
+
...the refined operation...
|
|
27
|
+
components:
|
|
28
|
+
schemas:
|
|
29
|
+
...only the component schemas you changed or added; omit "components" entirely when there are none...
|
|
30
|
+
|
|
31
|
+
Do not wrap the output in Markdown code fences. Do not add any commentary before or after the document.`;function mt(e){return e.length===0?"(no sample exchanges were captured)":e.map((t,r)=>{let n=[],o=t.query?`?${t.query}`:"";return n.push(`### Exchange ${r+1}`),n.push(`${t.method} ${t.path}${o}`),t.requestContentType&&n.push(`Request Content-Type: ${t.requestContentType}`),t.requestBody&&n.push(`Request body: ${t.requestBody}`),t.status!==void 0&&n.push(`Response status: ${t.status}`),t.responseContentType&&n.push(`Response Content-Type: ${t.responseContentType}`),t.responseBody&&n.push(`Response body: ${t.responseBody}`),n.join(`
|
|
32
|
+
`)}).join(`
|
|
33
|
+
|
|
34
|
+
`)}function Ae(e){let t=[];return t.push(`# Operation to refine (inferred from traffic)
|
|
35
|
+
|
|
36
|
+
\`\`\`yaml
|
|
37
|
+
${P({paths:{[e.path]:{[e.method]:e.operation}}})}\`\`\``),Object.keys(e.components).length>0&&t.push(`# Component schemas referenced by this operation (current definitions)
|
|
38
|
+
|
|
39
|
+
\`\`\`yaml
|
|
40
|
+
${P({components:{schemas:e.components}})}\`\`\``),e.reservedComponentNames.length>0&&t.push(`# Reserved component names (used elsewhere in the description; do not redefine or reuse them)
|
|
41
|
+
|
|
42
|
+
${e.reservedComponentNames.join(", ")}`),t.push(`# Recorded HTTP exchanges for this operation
|
|
43
|
+
|
|
44
|
+
${mt(e.samples)}`),t.push(`Refine ${e.method.toUpperCase()} ${e.path} as instructed and output only the YAML document.`),{system:ut,user:t.join(`
|
|
45
|
+
|
|
46
|
+
`)}}import{spawn as dt}from"node:child_process";import{mkdtemp as lt}from"node:fs/promises";import{tmpdir as ht}from"node:os";import gt from"node:path";var ke=3e5,T=class extends Error{},je;function yt(){return je??=lt(gt.join(ht(),"redocly-generate-spec-")),je}async function K(e,t,r,n){let o=await yt();return new Promise((s,a)=>{let i=dt(e,t,{stdio:["pipe","pipe","pipe"],cwd:o,env:{...process.env,...n}}),c="",p="",f=!1,l=setTimeout(()=>{f=!0,i.kill("SIGKILL")},ke);i.stdout.on("data",m=>{c+=m.toString()}),i.stderr.on("data",m=>{p+=m.toString()}),i.on("error",m=>{if(clearTimeout(l),m.code==="ENOENT"){a(new T(`Could not find the "${e}" CLI on PATH. Is it installed?`));return}a(m)}),i.on("close",m=>{if(clearTimeout(l),f){a(new Error(`The "${e}" CLI did not respond within ${ke/1e3} seconds.`));return}s({stdout:c,stderr:p,code:m})}),i.stdin.on("error",()=>{}),i.stdin.end(r)})}async function St(e){let t=["-p","--output-format","text","--tools","","--strict-mcp-config","--setting-sources","","--no-session-persistence","--append-system-prompt",e.system];e.model&&t.push("--model",e.model);let{stdout:r,stderr:n,code:o}=await K("claude",t,e.user,{CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1"});if(o!==0)throw new Error(`claude CLI exited with code ${o}: ${n.trim()}`);if(!r.trim())throw new Error("claude CLI returned no output.");return{text:r}}async function bt(e){let t=["exec","--skip-git-repo-check","--sandbox","read-only","-c","mcp_servers={}","-c","project_doc_max_bytes=0"];e.model&&t.push("--model",e.model),t.push("-");let r=`${e.system}
|
|
47
|
+
|
|
48
|
+
${e.user}`,{stdout:n,stderr:o,code:s}=await K("codex",t,r);if(s!==0)throw new Error(`codex CLI exited with code ${s}: ${o.trim()}`);if(!n.trim())throw new Error("codex CLI returned no output.");return{text:n}}async function wt(e){let t=["-p","--output-format","text","--trust"];e.model&&t.push("--model",e.model);let r=`${e.system}
|
|
49
|
+
|
|
50
|
+
${e.user}`,n;try{n=await K("cursor-agent",t,r)}catch(i){if(!(i instanceof T))throw i;try{n=await K("agent",t,r)}catch(c){throw c instanceof T?new T('Could not find the Cursor CLI ("cursor-agent" or "agent") on PATH. Is it installed?'):c}}let{stdout:o,stderr:s,code:a}=n;if(a!==0)throw new Error(`cursor CLI exited with code ${a}: ${s.trim()}`);if(!o.trim())throw new Error("cursor CLI returned no output.");return{text:o}}async function xe(e,t){switch(e){case"claude":return St(t);case"codex":return bt(t);case"cursor":return wt(t);default:throw new Error(`Unknown AI provider: ${e}`)}}function vt(e){let t=e.trim(),r=t.match(/^```(?:ya?ml|json)?\s*\n([\s\S]*?)\n```$/);return r?r[1]:t}var Me=/^#\/components\/schemas\/(.+)$/;function ee(e,t){if(Array.isArray(e)){for(let r of e)ee(r,t);return}if(b(e)){if(typeof e.$ref=="string"){let r=e.$ref.match(Me);r&&t.add(r[1])}if(b(e.discriminator)&&b(e.discriminator.mapping)){for(let r of Object.values(e.discriminator.mapping))if(typeof r=="string"){let n=r.match(Me);t.add(n?n[1]:r)}}for(let r of Object.values(e))ee(r,t)}}function Ie(e,t){let r=new Set,n=[e];for(;n.length>0;){let o=new Set;ee(n.pop(),o);for(let s of o)!r.has(s)&&s in t&&(r.add(s),n.push(t[s]))}return r}function Ot(e){let t=e.components?.schemas;if(!t)return;let r=Ie(e.paths,t);for(let n of Object.keys(t))r.has(n)||delete t[n];Object.keys(t).length===0&&delete e.components}function $t(e,t,r){let n=vt(e),o;try{o=oe(n)}catch(f){throw new Error(`the provider did not return valid YAML: ${f instanceof Error?f.message:String(f)}`)}if(!b(o))throw new Error('the response is not a YAML document with a "paths" object');let s=o.paths;if(!b(s))throw new Error('the response is not a YAML document with a "paths" object');let a=s[t];if(!b(a))throw new Error(`the response does not keep the path template "${t}"`);let i=a[r];if(!b(i))throw new Error(`the response does not contain the ${r.toUpperCase()} operation`);let c=o.components,p=b(c)?c.schemas:void 0;return{operation:i,components:b(p)?p:{}}}function Pt(e,t){let r=b(t.responses)?t.responses:{};return Object.keys(e.responses).filter(n=>!(n in r))}async function Ne(e,t){let n=(await ie({source:e,config:t})).filter(o=>o.severity==="error");if(n.length>0){let o=n.slice(0,5).map(s=>`${s.ruleId}: ${s.message}`).join("; ");throw new Error(`the result has ${n.length} validation problem(s): ${o}`)}}async function Tt(e){let t=e.document.components?.schemas??{},r=Ie(e.operation,t),n={};for(let m of r)n[m]=t[m];let o=Object.keys(t).filter(m=>!r.has(m)),{system:s,user:a}=Ae({path:e.path,method:e.method,operation:e.operation,components:n,reservedComponentNames:o,samples:e.samples}),{text:i}=await xe(e.provider,{system:s,user:a,model:e.model}),c=$t(i,e.path,e.method),p=Pt(e.operation,c.operation);if(p.length>0)throw new Error(`the response dropped observed response status(es): ${p.join(", ")}`);if(typeof c.operation.operationId!="string")throw new Error("the response dropped the operationId");let f=Object.keys(c.components).filter(m=>o.includes(m));if(f.length>0)throw new Error(`the response redefines reserved component(s): ${f.join(", ")}`);let l={openapi:e.document.openapi,info:e.document.info,paths:{[e.path]:{[e.method]:c.operation}},components:{schemas:{...t,...c.components}}};return await Ne(P(l),e.config),c}function Et(e,t,r,n){e.paths[t][r]=n.operation,Object.keys(n.components).length>0&&(e.components??={schemas:{}},Object.assign(e.components.schemas,n.components))}function Je(e){e.stop(),Ce.stderr.isTTY&&y.info("\x1B[2K")}async function qe(e){let t=structuredClone(e.baseline),r=await se({extends:["spec"]}),n=[];for(let[d,u]of Object.entries(e.baseline.paths))for(let[h,g]of Object.entries(u))n.push({path:d,method:h,operation:g});let o=new pe,s=new Set,a=0,i=0,c=()=>{let[d]=s;if(!d)return;let u=s.size>1?` (+${s.size-1} more)`:"";o.start(`[${a+1}/${n.length}] Refining ${d}${u}`)},p=0,f=!1,l=async()=>{for(;!f&&p<n.length;){let{path:d,method:u,operation:h}=n[p++],g=`${u.toUpperCase()} ${d}`,v=Date.now();s.add(g),c();try{let S=await Tt({provider:e.provider,model:e.model,document:t,path:d,method:u,operation:h,samples:e.samplesByOperation.get(Y(u,d))??[],config:r});Et(t,d,u,S),i+=1,a+=1,s.delete(g),Je(o),y.info(`[${a}/${n.length}] ${g} \u2014 refined (${Math.round((Date.now()-v)/1e3)}s)
|
|
51
|
+
`)}catch(S){if(a+=1,s.delete(g),Je(o),S instanceof T)throw f=!0,S;y.warn(`[${a}/${n.length}] ${g} \u2014 kept the baseline: ${S instanceof Error?S.message:String(S)}
|
|
52
|
+
`)}c()}},m=Math.max(1,Math.min(e.concurrency??1,n.length));for(let d of await Promise.allSettled(Array.from({length:m},l)))if(d.status==="rejected")throw d.reason;if(i===0)throw new Error(`the ${e.provider} provider did not produce a usable refinement for any operation`);Ot(t);let w=P(t);return await Ne(w,r),{yaml:w,document:t,refined:i,total:n.length}}var Rt=2,At=2,kt=.75,jt=2,_e=new Set(["integer","number"]),Ge=new WeakMap;function E(e){let t=Ge.get(e);if(t!==void 0)return t;let r;if(e.$ref!==void 0)r=`ref(${e.$ref})`;else if(e.oneOf)r=`oneOf(${e.oneOf.map(E).sort().join("|")})`;else{let o=[`type=${(Array.isArray(e.type)?[...e.type].sort().join(","):e.type)??""}`];if(e.properties){let s=Object.entries(e.properties).map(([a,i])=>`${JSON.stringify(a)}:${E(i)}`).sort().join(",");o.push(`props{${s}}`)}e.additionalProperties&&o.push(`values(${E(e.additionalProperties)})`),e.items&&o.push(`items(${E(e.items)})`),r=o.join(";")}return Ge.set(e,r),r}function xt(e){return e.$ref===void 0&&e.type==="object"&&e.oneOf===void 0&&e.additionalProperties===void 0&&Object.keys(e.properties??{}).length>=Rt}function De(e,t){for(let r of t)e.set(r,(e.get(r)??0)+1)}function M(e,t,r){if(e.oneOf){e.oneOf.forEach((s,a)=>M(s,{...t,path:`${t.path}/oneOf/${a}`,fallbackHints:[]},r));return}let n=t.container,o=`${t.path}/`;if(xt(e)){let s=E(e),a=r.get(s);a||(a={keys:[s],schemas:[],merged:{},contexts:new Set,primaryVotes:new Map,fallbackVotes:new Map},r.set(s,a)),a.schemas.push(e),a.contexts.add(`${t.container}#${t.path}`),De(a.primaryVotes,t.primaryHints),De(a.fallbackVotes,t.fallbackHints),n=s,o=""}for(let[s,a]of Object.entries(e.properties??{}))M(a,{container:n,path:`${o}${s}`,primaryHints:[s],fallbackHints:[]},r);e.additionalProperties&&M(e.additionalProperties,{container:n,path:`${o}additionalProperties`,primaryHints:t.primaryHints.map(s=>$(s,1)),fallbackHints:t.fallbackHints.map(s=>$(s,1))},r),e.items&&M(e.items,{container:n,path:`${o}items`,primaryHints:t.primaryHints.map(s=>$(s,1)),fallbackHints:t.fallbackHints.map(s=>$(s,1))},r)}function Mt(e){return e.split("/").filter(r=>r&&!r.startsWith("{")).at(-1)}function Jt(e){let t=new Map;for(let[r,n]of Object.entries(e.paths)){let o=Mt(r),s=o?$(o,1):void 0;for(let[a,i]of Object.entries(n)){for(let[c,p]of Object.entries(i.requestBody?.content??{}))M(p.schema,{container:`request ${a} ${r} ${c}`,path:"",primaryHints:s?[s]:[],fallbackHints:s?[`${s} request`]:[]},t);for(let[c,p]of Object.entries(i.responses)){let f=Number(c)>=400;for(let[l,m]of Object.entries(p.content??{}))M(m.schema,{container:`response ${a} ${r} ${c} ${l}`,path:"",primaryHints:f?["error"]:s?[s]:[],fallbackHints:f?s?[`${s} error`]:[]:s?[`${s} response`]:[]},t)}}}return t}function Be(e){return Object.keys(e.properties??{})}function Ct(e,t){let r=Be(e),n=new Set(Be(t)),o=r.filter(a=>n.has(a)).length,s=r.length+n.size-o;return s===0?0:o/s}function ze(e){if(e.$ref!==void 0||e.properties||e.additionalProperties||e.items||e.oneOf)return;let t=typeof e.type=="string"?[e.type]:e.type;if(!(!t||t.some(r=>r==="object"||r==="array")))return t}function te(e){return Object.keys(e).length===0}function Le(e,t){if(E(e)===E(t)||te(e)||te(t))return!0;let r=ze(e),n=ze(t);if(r&&n){let s=new Set(r.filter(i=>i!=="null")),a=new Set(n.filter(i=>i!=="null"));return s.size===a.size&&[...s].every(i=>a.has(i))?!0:[...s].every(i=>_e.has(i))&&[...a].every(i=>_e.has(i))}let o=s=>s.type==="array"||s.items!==void 0;return o(e)&&o(t)?!e.items||!t.items||Le(e.items,t.items):!1}function It(e,t){let r=t.merged.properties??{};return Object.entries(e.merged.properties??{}).every(([n,o])=>!(n in r)||Le(o,r[n]))}function Nt(e){let t=[...e];for(;t.length>1;){let r=-1,n=-1,o=0;for(let i=0;i<t.length;i++)for(let c=i+1;c<t.length;c++){let p=Ct(t[i].merged,t[c].merged);p>=kt&&p>o&&It(t[i],t[c])&&(o=p,r=i,n=c)}if(r===-1)break;let s=t[r],a=t[n];s.keys.push(...a.keys),s.schemas.push(...a.schemas),s.merged=x([s.merged,a.merged]);for(let i of a.contexts)s.contexts.add(i);for(let[i,c]of a.primaryVotes)s.primaryVotes.set(i,(s.primaryVotes.get(i)??0)+c);for(let[i,c]of a.fallbackVotes)s.fallbackVotes.set(i,(s.fallbackVotes.get(i)??0)+c);t.splice(n,1)}return t}function re(e,t){return e<t?-1:e>t?1:0}function qt(e){return e.split(/[^a-zA-Z0-9]+/).filter(Boolean).map(t=>t[0].toUpperCase()+t.slice(1)).join("")}function He(e){return[...e.entries()].sort(([t,r],[n,o])=>o-r||re(t,n)).map(([t])=>t)}function _t(e){let t=[...e].sort((n,o)=>o.contexts.size-n.contexts.size||o.schemas.length-n.schemas.length||re(n.keys[0],o.keys[0])),r=new Set;return t.map(n=>{let o=[...He(n.primaryVotes),...He(n.fallbackVotes)].map(qt).filter(a=>a.length>0);o.length===0&&o.push("Schema");let s=o.find(a=>!r.has(a));for(let a=2;s===void 0;a++){let i=`${o[0]}${a}`;r.has(i)||(s=i)}return r.add(s),{group:n,name:s}})}function j(e,t,r=!1){if(!r){let o=t.get(E(e));if(o!==void 0)return{$ref:`#/components/schemas/${o}`}}let n={...e};return U(e,n),e.properties&&(n.properties=Object.fromEntries(Object.entries(e.properties).map(([o,s])=>[o,j(s,t)]))),e.additionalProperties&&(n.additionalProperties=j(e.additionalProperties,t)),e.items&&(n.items=j(e.items,t)),e.oneOf&&(n.oneOf=e.oneOf.map(o=>j(o,t))),n}function Gt(e){let t=Object.values(e.properties??{}),r=t.filter(n=>n.type==="array"&&(!n.items||te(n.items)));return r.length>0&&t.length-r.length<=jt}function Dt(e){let t=0,r=0;for(let n of e.primaryVotes.values())t+=n,r=Math.max(r,n);return r*2>t}function Ue(e){let t=Jt(e);for(let i of t.values())i.merged=x(i.schemas);let n=Nt([...t.values()]).filter(i=>i.contexts.size>=At&&(Dt(i)||!i.schemas.some(Gt)));if(n.length===0)return e;let o=_t(n),s=new Map;for(let{group:i,name:c}of o)for(let p of i.keys)s.set(p,c);let a={};for(let{group:i,name:c}of[...o].sort((p,f)=>re(p.name,f.name)))a[c]=j(i.merged,s,!0);for(let i of Object.values(e.paths))for(let c of Object.values(i)){for(let p of Object.values(c.requestBody?.content??{}))p.schema=j(p.schema,s);for(let p of Object.values(c.responses))for(let f of Object.values(p.content??{}))f.schema=j(f.schema,s)}return e.components={schemas:a},e}async function Lt(e,t){let r=I(e);await Bt(Ht.dirname(r),{recursive:!0}),await zt(r,t,"utf8")}function Ut(e){let t=Math.round(e/1e3),r=Math.floor(t/60),n=t%60;return r>0?`${r}m ${n}s`:`${n}s`}async function Ir({argv:e}){if(e.type!=="openapi")return ae(`Unsupported spec type "${e.type}". Only "openapi" is supported.`);let t=Date.now(),r=I(e.traffic),n=e["traffic-format"],o=me(Ue(await Oe({trafficPath:r,format:n,title:e.title,server:e.server})));y.info(`Inferred a baseline OpenAPI description from traffic: ${$e(o)} operation(s).
|
|
53
|
+
`);let s=P(o);if(e["with-ai"]){let a=e["ai-provider"];y.info(`Refining the description with AI provider "${a}"...
|
|
54
|
+
`),y.warn(`Note: --with-ai sends samples of the recorded traffic (URLs, query strings, request and response bodies) to the selected AI provider. Make sure the traffic contains no secrets or personal data you are not allowed to share.
|
|
55
|
+
`);let i=await Re({trafficPath:r,format:n,server:e.server});try{let c=await qe({provider:a,model:e["ai-model"],baseline:o,samplesByOperation:i,concurrency:e["ai-concurrency"]});s=c.yaml,y.info(`AI refinement complete: ${c.refined} of ${c.total} operation(s) refined (${a}).
|
|
56
|
+
`)}catch(c){y.warn(`AI refinement failed, falling back to the baseline description: ${c instanceof Error?c.message:String(c)}
|
|
57
|
+
`)}}e.output?(await Lt(e.output,s),y.info(`Written to: ${I(e.output)}
|
|
58
|
+
`)):y.output(s),y.info(`Done in ${Ut(Date.now()-t)}.
|
|
59
|
+
`)}export{Ir as handleGenerateSpec};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __pathDirname } from 'node:path';
|
|
4
|
+
const require = __createRequire(import.meta.url);
|
|
5
|
+
var __filename = __fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __pathDirname(__filename);
|
|
7
|
+
import{b as t,c as i}from"./KLY5RV3W.js";import{c as d,f as n}from"./RFWIIJFG.js";var a=d(e=>{Object.defineProperty(e,"__esModule",{value:!0});e.getMachineId=void 0;var u=(i(),n(t));async function r(){u.diag.debug("could not read machine-id: unsupported platform")}e.getMachineId=r});export default a();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'node:module';
|
|
2
|
+
import { fileURLToPath as __fileURLToPath } from 'node:url';
|
|
3
|
+
import { dirname as __pathDirname } from 'node:path';
|
|
4
|
+
const require = __createRequire(import.meta.url);
|
|
5
|
+
var __filename = __fileURLToPath(import.meta.url);
|
|
6
|
+
var __dirname = __pathDirname(__filename);
|
|
7
|
+
import{b as d,c as s}from"./KLY5RV3W.js";import{a as n,c,f as a}from"./RFWIIJFG.js";var f=c(e=>{Object.defineProperty(e,"__esModule",{value:!0});e.getMachineId=void 0;var u=n("fs"),o=(s(),a(d));async function h(){let i=["/etc/machine-id","/var/lib/dbus/machine-id"];for(let r of i)try{return(await u.promises.readFile(r,{encoding:"utf8"})).trim()}catch(t){o.diag.debug(`error reading machine id: ${t}`)}}e.getMachineId=h});export default f();
|