oapiex 0.3.6 → 0.3.8

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/bin/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"axios";import{Logger as r}from"@h3ravel/shared";import i from"node:path";import a,{readFile as o}from"node:fs/promises";import{Command as s,Kernel as c}from"@h3ravel/musket";import l from"prettier";import{pathToFileURL as u}from"node:url";import{existsSync as d,readdirSync as f}from"node:fs";import{fileURLToPath as p}from"url";import{createJiti as m}from"jiti";const h=[`SIGINT`,`SIGTERM`,`SIGTSTP`],g=[`axios`,`happy-dom`,`jsdom`,`puppeteer`],_={outputFormat:`pretty`,outputShape:`raw`,requestTimeout:5e4,maxRedirects:5,userAgent:`Mozilla/5.0 (X11; Linux x64) AppleWebKit/537.36 (KHTML, like Gecko) OpenApiExtractor/1.0.0`,retryCount:3,retryDelay:1e3,browser:`puppeteer`,happyDom:{enableJavaScriptEvaluation:!0,suppressInsecureJavaScriptEnvironmentWarning:!0},puppeteer:{headless:!0,args:[`--no-sandbox`,`--disable-setuid-sandbox`]}};let v=_,y=!1,b=!1;const x=new Set,S=()=>globalThis.__oapieBrowserSession,C=()=>{!S()&&x.size===0&&T()},w=()=>{if(!b){for(let e of h)process.on(e,D);b=!0}},T=()=>{if(b){for(let e of h)process.off(e,D);b=!1}},E=e=>(w(),x.add(e),()=>{x.delete(e),C()}),ee=async()=>{let e=Array.from(x).reverse();x.clear();for(let t of e)await t();await k()},D=async e=>{if(!y){y=!0,T();try{await ee()}catch(e){console.error(`Failed to close active browser resources:`,e)}finally{y=!1}if(e===`SIGTSTP`){process.kill(process.pid,e);return}process.exit(e===`SIGINT`?130:143)}},O=async(e=v)=>{let t=S();if(t?.browser===e.browser)return t;t&&await k();let n={browser:e.browser,closers:[]};return e.browser===`puppeteer`&&(n.puppeteerBrowser=await(await import(`puppeteer`)).launch({headless:e.puppeteer?.headless??!0,args:e.puppeteer?.args??[`--no-sandbox`,`--disable-setuid-sandbox`]})),w(),globalThis.__oapieBrowserSession=n,n},k=async()=>{let e=S();if(e){globalThis.__oapieBrowserSession=void 0;for(let t of e.closers.reverse())await t();e.puppeteerBrowser&&await e.puppeteerBrowser.close(),C()}},A=(e,t)=>{let n=S();return!n||n.browser!==e?!1:(n.closers.push(t),!0)},j=e=>{let t={..._,...e,happyDom:{..._.happyDom,...e.happyDom}};return v=t,t},M=e=>g.includes(e),te=async(r,i=v,a=!1)=>{let{data:o}=i.browser===`puppeteer`?{data:``}:await n.get(r,{timeout:i.requestTimeout,maxRedirects:i.maxRedirects,headers:{"User-Agent":i.userAgent,Accept:`text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8`}});if(i.browser===`axios`)return o;if(i.browser===`happy-dom`){let e=new t({url:r,innerWidth:1024,innerHeight:768,settings:i.happyDom}),n=E(()=>e.happyDOM.close());try{e.document.write(o),await e.happyDOM.waitUntilComplete();let t=e.document.documentElement.outerHTML;if(!t)throw await e.happyDOM.close(),Error(`Unable to extract HTML from remote source: ${r}`);return A(`happy-dom`,()=>e.happyDOM.close())||await e.happyDOM.close(),t}finally{n()}}else if(i.browser===`jsdom`){let t,n;try{({window:t}=new e(o,{url:r,contentType:`text/html`,runScripts:`dangerously`,includeNodeLocations:!0})),n=E(()=>t?.close());let i=t.document.documentElement.outerHTML;if(!i)throw Error(`Unable to extract HTML from remote source: ${r}`);let a=t;return A(`jsdom`,()=>a.close())||t.close(),t=void 0,i}finally{n?.(),t&&t.close()}}else if(i.browser===`puppeteer`){let e=S(),t=Math.max(i.requestTimeout,3e4),o=e?.browser===`puppeteer`?e.puppeteerBrowser:void 0,s=!1,c,l,u;try{o||(o=await(await import(`puppeteer`)).launch({headless:i.puppeteer?.headless??!0,args:i.puppeteer?.args??[`--no-sandbox`,`--disable-setuid-sandbox`]}),s=!0,l=E(async()=>{o?.connected&&await o.close()})),c=await o.newPage(),u=E(async()=>{c&&!c.isClosed()&&await c.close()}),await c.setUserAgent({userAgent:i.userAgent}),await c.setRequestInterception(!0),c.on(`request`,e=>{let t=e.resourceType();if([`image`,`font`,`media`,`stylesheet`].includes(t))return void e.abort();e.continue()});try{await c.goto(r,{waitUntil:`domcontentloaded`,timeout:t})}catch(e){if(!c||!await se(c))throw e}let e=await ie(c,t,a);if(!e)throw Error(`Unable to extract HTML from remote source: ${r}`);if(!e.includes(`id="ssr-props"`)){let{data:t}=await n.get(r,{timeout:i.requestTimeout,maxRedirects:i.maxRedirects,headers:{"User-Agent":i.userAgent,Accept:`text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8`}});e=ce(e,t)}return e}finally{u?.(),c&&!c.isClosed()&&await c.close(),l?.(),s&&o&&await o.close()}}else throw Error(`Unsupported browser specified in configuration: ${v.browser}`)},ne=async(e,t,n=!1)=>{try{n&&await e.waitForSelector(`.hub-sidebar-content .rm-Sidebar-link`),await e.waitForSelector(`[data-testid="http-method"], article#content, script#ssr-props`,{timeout:t})}catch{}},re=async(e,t)=>{try{await e.waitForFunction(()=>{let e=!!document.querySelector(`[data-testid="http-method"]`),t=!!document.querySelector(`form[name="Parameters"]`),n=!!document.querySelector(`.rm-PlaygroundRequest`),r=!!document.querySelector(`.rm-PlaygroundResponse`),i=!!document.querySelector(`script#ssr-props`);return e?t||n||r||i:!1},{timeout:t})}catch{}try{await e.waitForSelector(`.rm-PlaygroundRequest, .rm-PlaygroundResponse, form[name="Parameters"], script#ssr-props`,{timeout:Math.min(t,5e3)})}catch{}try{await e.waitForNetworkIdle?.({idleTime:500,timeout:Math.min(t,5e3)})}catch{}},ie=async(e,t,n=!1,r=3)=>{let i;for(let a=1;a<=r;a+=1)try{return await ne(e,t,n),await re(e,t),await e.content()}catch(n){if(i=n,!oe(n)||a===r)throw n;await ae(e,t)}throw i instanceof Error?i:Error(`Unable to extract stable HTML from remote source`)},ae=async(e,t)=>{try{await e.waitForFunction(()=>document.readyState===`interactive`||document.readyState===`complete`,{timeout:Math.min(t,5e3)})}catch{}try{await e.waitForNetworkIdle?.({idleTime:500,timeout:Math.min(t,5e3)})}catch{}},oe=e=>{if(!(e instanceof Error))return!1;let t=e.message.toLowerCase();return t.includes(`execution context was destroyed`)||t.includes(`cannot find context with specified id`)||t.includes(`most likely because of a navigation`)},se=async e=>!!await e.$(`[data-testid="http-method"], article#content, script#ssr-props`),ce=(e,t)=>{if(e.includes(`id="ssr-props"`))return e;let n=le(t);return n?e.includes(`</body>`)?e.replace(`</body>`,`${n}</body>`):e.includes(`</html>`)?e.replace(`</html>`,`${n}</html>`):`${e}${n}`:e},le=e=>e.match(/<script id="ssr-props"[^>]*>[\s\S]*?<\/script>/i)?.[0]??null;var N=class e{static parsePossiblyTruncated=t=>{let n=new e,r=t.trim();if(!/^(?:\{|\[)/.test(r))return null;try{return JSON.parse(r)}catch{let e=n.repairCommonJsonIssues(r);try{return JSON.parse(e)}catch{return null}}};repairCommonJsonIssues=e=>{let t=this.removeUnexpectedObjectTokens(e),n=this.insertMissingCommas(t);return`${n}${this.buildMissingJsonClosers(n)}`};removeUnexpectedObjectTokens=e=>e.replace(/([[{,]\s*)([A-Za-z_$][\w$-]*)(?=\s*"(?:\\.|[^"\\])*"\s*:)/g,`$1`);insertMissingCommas=e=>{let t=``,n=!1,r=!1,i=``;for(let a=0;a<e.length;a+=1){let o=e[a];if(n){if(t+=o,r){r=!1;continue}if(o===`\\`){r=!0;continue}o===`"`&&(n=!1,i=`"`);continue}if(o===`"`){let r=e.slice(a);/^"(?:\\.|[^"\\])*"\s*:/.test(r)&&this.shouldInsertCommaBeforeKey(i,t)&&(t+=`,`),t+=o,n=!0;continue}t+=o,/\s/.test(o)||(i=o)}return t};shouldInsertCommaBeforeKey=(e,t)=>{if(!e||![`"`,`}`,`]`,`e`,`l`,`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`].includes(e))return!1;let n=t.trimEnd();return!n.endsWith(`,`)&&!n.endsWith(`{`)};buildMissingJsonClosers=e=>{let t=[],n=!1,r=!1;for(let i of e){if(r){r=!1;continue}if(i===`\\`){r=!0;continue}if(i===`"`){n=!n;continue}if(!n){if(i===`{`){t.push(`}`);continue}if(i===`[`){t.push(`]`);continue}(i===`}`||i===`]`)&&t[t.length-1]===i&&t.pop()}}return t.reverse().join(``)}};const P=e=>typeof e==`object`&&!!e&&!Array.isArray(e),F=e=>{let n=new t;n.document.write(e);let{document:r}=n,i=r.querySelector(`article#content`)??r.body,a=i.querySelector(`form[name="Parameters"]`),o=r.querySelector(`.rm-PlaygroundRequest`),s=r.querySelector(`.rm-PlaygroundResponse`),c=ve(o),l=Ie(c[0]??null),u=ye(s);return ue({method:K(i.querySelector(`[data-testid="http-method"]`))?.toUpperCase()??null,url:K(i.querySelector(`[data-testid="serverurl"]`)),description:_e(i),sidebarLinks:be(r.querySelector(`.rm-Sidebar.hub-sidebar-content`)),requestParams:xe(a),requestCodeSnippets:c,requestExample:c[0]?.body??null,requestExampleNormalized:l,responseSchemas:Se(i),responseBodies:u,responseExample:u[0]?.body??null,responseExampleRaw:u[0]?.rawBody??null},de(r))},ue=(e,t)=>t?{method:e.method??t.method,url:e.url??t.url,description:e.description??t.description,sidebarLinks:e.sidebarLinks.length>0?e.sidebarLinks:t.sidebarLinks,requestParams:e.requestParams.length>0?e.requestParams:t.requestParams,requestCodeSnippets:e.requestCodeSnippets.length>0?e.requestCodeSnippets:t.requestCodeSnippets,requestExample:e.requestExample??t.requestExample,requestExampleNormalized:e.requestExampleNormalized??t.requestExampleNormalized,responseSchemas:e.responseSchemas.length>0?e.responseSchemas:t.responseSchemas,responseBodies:e.responseBodies.length>0?e.responseBodies:t.responseBodies,responseExample:e.responseExample??t.responseExample,responseExampleRaw:e.responseExampleRaw??t.responseExampleRaw}:e,de=e=>{let t=e.querySelector(`script#ssr-props`)?.textContent?.trim();if(!t)return null;let n;try{n=JSON.parse(t)}catch{return null}let r=P(n)&&P(n.document)?n.document.api:null;if(!P(r))return null;let i=typeof r.method==`string`?r.method.toUpperCase():null,a=typeof r.path==`string`?r.path:null,o=P(r.schema)?r.schema:null,s=pe(o,a,i?.toLowerCase()??null),c=Array.isArray(o?.servers)&&P(o.servers[0])&&typeof o.servers[0].url==`string`?o.servers[0].url:null;if(!s&&!i&&!a)return null;let l=R(s?.responses??{});return{method:i,url:me(c,a),description:s?.description??null,sidebarLinks:[],requestParams:[...fe(s?.parameters),...he(s?.requestBody)],requestCodeSnippets:[],requestExample:null,requestExampleNormalized:null,responseSchemas:L(s?.responses??{}),responseBodies:l,responseExample:l[0]?.body??null,responseExampleRaw:l[0]?.rawBody??null}},fe=e=>e?e.map(e=>({name:e.name,in:e.in,path:[e.name],type:e.schema?.type??null,required:e.required??!1,defaultValue:e.schema?.default==null?e.example==null?null:String(e.example):String(e.schema.default),description:e.description??e.schema?.description??null})):[],pe=(e,t,n)=>{if(!e||!t||!n||!P(e.paths))return null;let r=e.paths[t];return!P(r)||!P(r[n])?null:r[n]},me=(e,t)=>!e||!t?null:`${e.replace(/\/$/,``)}${t.startsWith(`/`)?t:`/${t}`}`,he=e=>{let t=e?.content?.[`application/json`]?.schema;return t?I(t):[]},I=(e,t=[])=>{if(!e.properties)return[];let n=[];for(let[r,i]of Object.entries(e.properties)){let a=[...t,r],o=e.required?.includes(r)??!1;if(i.type===`object`&&i.properties){n.push(...I(i,a).map(e=>({...e,required:e.path.length===a.length+1?o&&e.required:e.required})));continue}n.push({name:r,in:`body`,path:a,type:i.type??null,required:o,defaultValue:i.default==null?null:String(i.default),description:i.description??null})}return n},L=e=>Object.entries(e).map(([e,t])=>({statusCode:e,description:t.description??e})),R=e=>{let t=[];for(let[n,r]of Object.entries(e))for(let[e,i]of Object.entries(r.content??{})){let a=ge(i);if(a==null)continue;let o=typeof a==`string`?a:JSON.stringify(a,null,2),s=V(o,e);t.push({format:s.format,contentType:e,statusCode:n,label:r.description??n,body:s.body,rawBody:o})}return t},ge=e=>{if(e.example!==void 0)return e.example;let t=e.examples;if(t&&P(t)){for(let e of Object.values(t))if(P(e)&&`value`in e)return e.value??null}return e.schema?.example===void 0?null:e.schema.example},_e=e=>{let t=e.querySelector(`header`);if(!t)return null;let n=Array.from(t.querySelectorAll(`[data-testid="RDMD"]`));return K(n[n.length-1]??null)},ve=e=>{if(!e)return[];let t=we(e);return z(e).map(e=>({label:t,body:e}))},ye=e=>{if(!e)return[];let t=z(e),n=De(e),r=Oe(e);return t.map((e,t)=>{let i=r[t]??r[0]??null,a=n[t]??n[0]??null,o=V(e,a);return{format:o.format,contentType:a,statusCode:i?.match(/\b\d{3}\b/)?.[0]??null,label:i,body:o.body,rawBody:e}})},be=e=>e?Array.from(e.querySelectorAll(`.rm-Sidebar-link`)).map(e=>{let t=e.closest(`.rm-Sidebar-section`),n=K(e.querySelector(`[data-testid="http-method"]`))?.toUpperCase()??null;return{section:K(t?.querySelector(`.rm-Sidebar-heading`)??null),label:Ee(e,n),href:e.getAttribute(`href`),method:n,active:e.classList.contains(`active`)||e.getAttribute(`aria-current`)===`page`,subpage:e.classList.contains(`subpage`)}}).filter(e=>e.label.length>0):[],xe=e=>e?Array.from(e.querySelectorAll(`label`)).map(t=>{let n=K(t),r=ke(t,e),i=Ae(r,t);return{name:n??``,in:je(r,t,e),path:Me(t,n),type:Ne(r,i),required:Pe(r,i),defaultValue:Te(i),description:Fe(r)}}).filter(e=>e.name.length>0):[],Se=e=>{let t=e.querySelector(`#response-schemas`)?.nextElementSibling;return!t||!t.classList.contains(`rm-APIResponseSchemaPicker`)?[]:Array.from(t.querySelectorAll(`button`)).map(e=>{let t=K(e),n=t?.match(/\b\d{3}\b/),r=Array.from(e.querySelectorAll(`[data-testid="RDMD"]`));return{statusCode:n?.[0]??null,description:K(r[0]??null)??t}}).filter(e=>e.statusCode!==null)},z=e=>Array.from(e.querySelectorAll(`.CodeSnippet`)).map(e=>Ce(e)).filter(e=>!!e),Ce=e=>{if(!e)return null;let t=Array.from(e.querySelectorAll(`.CodeMirror-code pre.CodeMirror-line`));return t.length===0?null:t.map(e=>e.textContent?.replace(/\u00a0/g,` `)??``).join(`
2
- `).trimEnd()||null},we=e=>{let t=e.querySelector(`header`);if(!t)return null;let n=Array.from(t.querySelectorAll(`button`)).map(e=>J(e)).filter(e=>!!e);return n.find(e=>e.toLowerCase()!==`examples`)??n[0]??null},Te=e=>e&&e.getAttribute(`value`)?.trim()||null,Ee=(e,t)=>q(e.querySelectorAll(`span`)).filter(e=>!t||e.toUpperCase()!==t).sort((e,t)=>t.length-e.length)[0]??K(e)??``,De=e=>q(e.querySelectorAll(`div`)).filter(e=>/^[\w.+-]+\/[\w.+-]+$/i.test(e)),Oe=e=>Array.from(e.querySelectorAll(`button, [role="button"]`)).map(e=>J(e)).filter(e=>!!e).filter(e=>/\b\d{3}\b/.test(e)),ke=(e,t)=>{let n=e.getAttribute(`for`),r=e;for(;r;){let e=n?r.querySelector(`#${G(n)}`):null,i=r.querySelector(`input, textarea, select`);if((e||i)&&r!==t)return r;r=r.parentElement}return e},Ae=(e,t)=>{let n=t.getAttribute(`for`),r=n?e.querySelector(`#${G(n)}`):null,i=e.querySelector(`input, textarea, select`);return r??i},je=(e,t,n)=>{let r=B(`${t.getAttribute(`for`)?.toLowerCase()??``} ${e.closest(`[id]`)?.getAttribute(`id`)?.toLowerCase()??``}`);if(r)return r;let i=e;for(;i&&i!==n;){let e=i.previousElementSibling;for(;e;){if(e.tagName===`HEADER`){let t=B(K(e)??``);if(t)return t}e=e.previousElementSibling}i=i.parentElement}return null},B=e=>{let t=e.trim().toLowerCase();return t.includes(`query params`)||t.includes(`query-`)?`query`:t.includes(`headers`)||t.includes(`header-`)?`header`:t.includes(`body params`)||t.includes(`request body`)||t.includes(`body-`)?`body`:t.includes(`path params`)||t.includes(`path-`)?`path`:t.includes(`cookie`)||t.includes(`cookie-`)?`cookie`:null},Me=(e,t)=>{let n=e.getAttribute(`for`)??``,r=n.includes(`_`)?n.slice(n.indexOf(`_`)+1):``;return r.includes(`.`)?r.split(`.`).map(e=>e.trim()).filter(e=>e.length>0):t?[t]:[]},Ne=(e,t)=>{let n=t?.getAttribute(`type`)?.toLowerCase();if(n===`text`)return`string`;if(n)return n;let r=Array.from(e.querySelectorAll(`[class]`)).find(e=>(e.getAttribute(`class`)??``).split(/\s+/).some(e=>e.startsWith(`field-`)))?.getAttribute(`class`)?.split(/\s+/).find(e=>e.startsWith(`field-`));return r?r.replace(/^field-/,``):null},Pe=(e,t)=>t?.hasAttribute(`required`)?!0:q(e.querySelectorAll(`*`)).some(e=>e.toLowerCase()===`required`),Fe=e=>K(e.querySelector(`[id$="__description"]`)||(Array.from(e.querySelectorAll(`[data-testid="RDMD"]`))[0]??null)),V=(e,t)=>{let n=e.trim();if(t?.toLowerCase().includes(`json`)||/^(?:\{|\[)/.test(n)){let t=N.parsePossiblyTruncated(n);if(t!==null)return{format:`json`,body:t};let r=W(n);return r===null?{format:`text`,body:e}:{format:`json`,body:r}}return{format:`text`,body:e}},Ie=e=>e?Le(e)??Re(e)??{sourceLabel:e.label,method:null,url:null,headers:{},bodyFormat:null,body:null,rawBody:null}:null,Le=e=>{if(!e.body.startsWith(`curl `))return null;let t=e.body.match(/--request\s+([A-Z]+)/)?.[1]??null,n=e.body.match(/--url\s+(\S+)/)?.[1]??null,r=Object.fromEntries(Array.from(e.body.matchAll(/--header\s+'([^:]+):\s*([^']+)'/g)).map(e=>[e[1].trim(),e[2].trim()])),i=e.body.match(/--data\s+'([\s\S]*)'$/)?.[1]?.trim()??null,a=i?V(i,r[`content-type`]??r[`Content-Type`]??null):null;return{sourceLabel:e.label,method:t,url:n,headers:r,bodyFormat:a?.format??null,body:a?.body??null,rawBody:i}},Re=e=>{let t=e.body.match(/fetch\(\s*(["'])(.*?)\1\s*,\s*\{([\s\S]*)\}\s*\)/);if(!t)return null;let[,,n,r]=t,i=H(r,`method`)?.toUpperCase()??null,a=ze(r),o=Be(r),s=a[`content-type`]??a[`Content-Type`]??null,c=o?Ve(o,s):null;return{sourceLabel:e.label,method:i,url:n,headers:a,bodyFormat:c?.format??null,body:c?.body??null,rawBody:o}},ze=e=>{let t=H(e,`headers`);if(!t)return{};let n=W(t);return P(n)?Object.fromEntries(Object.entries(n).map(([e,t])=>[e,String(t)])):{}},Be=e=>H(e,`body`),Ve=(e,t)=>{let n=W(e);return n!==null&&(t?.toLowerCase().includes(`json`)||/^[[{]/.test(e.trim()))?{format:`json`,body:n}:V(e,t)},H=(e,t)=>{let n=e.match(RegExp(`\\b${t}\\s*:`,`m`));if(!n||n.index===void 0)return null;let r=n.index+n[0].length;for(;/\s/.test(e[r]??``);)r+=1;if(e.startsWith(`JSON.stringify`,r)){let t=e.indexOf(`(`,r);return t===-1?null:U(e,t,`(`,`)`)?.slice(1,-1).trim()??null}if(e[r]===`{`||e[r]===`[`){let t=e[r]===`{`?`}`:`]`;return U(e,r,e[r],t)?.trim()??null}return e[r]===`"`||e[r]===`'`?He(e,r):(e.slice(r).match(/^([^,\n]+)/)?.[1])?.trim()??null},U=(e,t,n,r)=>{let i=0,a=null,o=!1;for(let s=t;s<e.length;s+=1){let c=e[s];if(a){if(o){o=!1;continue}if(c===`\\`){o=!0;continue}c===a&&(a=null);continue}if(c===`"`||c===`'`){a=c;continue}if(c===n){i+=1;continue}if(c===r&&(--i,i===0))return e.slice(t,s+1)}return null},He=(e,t)=>{let n=e[t],r=``,i=!1;for(let a=t+1;a<e.length;a+=1){let t=e[a];if(i){r+=t,i=!1;continue}if(t===`\\`){i=!0;continue}if(t===n)return r;r+=t}return null},W=e=>{let t=We(e).trim();if(!/^[[{]/.test(t))return null;let n=Ue(t.replace(/([{,]\s*)([A-Za-z_$][\w$-]*)(\s*:)/g,`$1"$2"$3`).replace(/,\s*([}\]])/g,`$1`));try{return JSON.parse(n)}catch{return null}},Ue=e=>{let t=``,n=!1,r=!1,i=!1,a=``;for(let o of e){if(r){if(i){a+=o,i=!1;continue}if(o===`\\`){i=!0;continue}if(o===`'`){t+=JSON.stringify(a),a=``,r=!1;continue}a+=o;continue}if(n){if(t+=o,i){i=!1;continue}if(o===`\\`){i=!0;continue}o===`"`&&(n=!1);continue}if(o===`'`){r=!0,a=``;continue}o===`"`&&(n=!0),t+=o}return t},We=e=>{let t=Ge(e);return t=Ke(t),t=qe(t),t},Ge=e=>{let t=``,n=!1,r=!1;for(let i=0;i<e.length;i+=1){let a=e[i],o=e[i+1];if(n){if(t+=a,r){r=!1;continue}if(a===`\\`){r=!0;continue}a===`"`&&(n=!1);continue}if(a===`"`){n=!0,t+=a;continue}if(a===`/`&&o===`/`){for(;i<e.length&&e[i]!==`
3
- `;)i+=1;i<e.length&&(t+=e[i]);continue}t+=a}return t},Ke=e=>e.replace(/([[{]\s*)([A-Za-z_$][\w$-]*)(\s+)(?=")/g,`$1`),qe=e=>{let t=e.trimStart();return!t.startsWith(`{`)||/"data"\s*:\s*\[/.test(t)||!/^\{\s*"[^"]+"\s*:/.test(t)||!/\]\s*,\s*"meta"\s*:/.test(t)?e:`${e.slice(0,e.indexOf(`{`))}{"data": [{${t.slice(1)}`},G=e=>e.replace(/([#.:[\],=])/g,`\\$1`),K=e=>e?.textContent?.replace(/\s+/g,` `).trim()||null,q=e=>Array.from(e).map(e=>K(e)).filter(e=>!!e),J=e=>q(e.querySelectorAll(`span, div, code`)).filter(e=>e.trim().length>0).sort((e,t)=>t.length-e.length)[0]??K(e),Je=(e,t)=>{let n=new URL(t),r=e.sidebarLinks.map(e=>e.href).filter(e=>!!e).map(e=>new URL(e,n).toString()).filter(e=>/^https?:\/\//i.test(e));return Array.from(new Set(r))};var Ye=class{config;constructor(e={}){this.config=j(e)}getConfig(e={}){return{...this.config,...e}}configure(e){return this.config=j({...this.config,...e}),this.config}async crawlReadmeOperations(e,t,n){let i=this.resolveCrawlBaseUrl(e,n);if(!i)throw Error(`Crawl mode requires a remote source URL or --base-url when using a local file`);let a=!!S();a||await O(this.config);try{let e=Je(t,i),n=new URL(i).toString(),a=this.attachSourceUrl(n,t),o=e.filter(e=>e!==n);return{rootSource:n,discoveredUrls:e,operations:[a,...(await Promise.all(o.map(async e=>{let t=Date.now(),n=F(await this.loadHtmlSource(e)),a=Date.now()-t;return n.method?(r.twoColumnDetail(r.log([[`Crawled`,`green`],[`${a/1e3}s`,`gray`]],` `,!1),e.replace(i,``)),this.attachSourceUrl(e,n)):null}))).filter(e=>e!==null)]}}finally{a||await k()}}attachSourceUrl(e,t){return{sourceUrl:e,...t}}resolveCrawlBaseUrl(e,t){return t?new URL(t).toString():/^https?:\/\//i.test(e)?e:null}async loadHtmlSource(e,t){if(!e)throw Error(`A source path or URL is required`);return/^https?:\/\//i.test(e)?te(e,this.config,t):o(i.resolve(process.cwd(),e),`utf8`)}},Xe=class{renderDeclaration(e){switch(e.kind){case`interface`:return this.renderInterface(e);case`interface-alias`:return`export interface ${e.name} extends ${e.target} {}`;case`type-alias`:return`export type ${e.name} = ${e.target}`;case`shape-alias`:return`export type ${e.name} = ${this.renderShape(e.shape)}`}}renderOpenApiDocumentDefinitions(e,t,n){return[`export interface OpenApiInfo {
1
+ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"axios";import{Logger as r}from"@h3ravel/shared";import i from"node:path";import a,{readFile as o}from"node:fs/promises";import{Command as s,Kernel as c}from"@h3ravel/musket";import l from"prettier";import{execFileSync as u}from"node:child_process";import{pathToFileURL as d}from"node:url";import{existsSync as f,readdirSync as p}from"node:fs";import{fileURLToPath as m}from"url";import{createJiti as h}from"jiti";const g={outputFormat:`pretty`,outputShape:`raw`,requestTimeout:5e4,maxRedirects:5,userAgent:`Mozilla/5.0 (X11; Linux x64) AppleWebKit/537.36 (KHTML, like Gecko) OpenApiExtractor/1.0.0`,retryCount:3,retryDelay:1e3,browser:`puppeteer`,happyDom:{enableJavaScriptEvaluation:!0,suppressInsecureJavaScriptEnvironmentWarning:!0},puppeteer:{headless:!0,args:[`--no-sandbox`,`--disable-setuid-sandbox`]}},_=()=>({...g,happyDom:{...g.happyDom},puppeteer:g.puppeteer?{...g.puppeteer,args:g.puppeteer.args?[...g.puppeteer.args]:void 0}:void 0,sdkKit:g.sdkKit?{...g.sdkKit,urls:g.sdkKit.urls?{...g.sdkKit.urls}:void 0}:void 0,sdk:g.sdk?{...g.sdk,urls:g.sdk.urls?{...g.sdk.urls}:void 0}:void 0}),v=(e,t)=>({...e,...t,happyDom:{...e.happyDom,...t.happyDom},puppeteer:t.puppeteer?{...e.puppeteer??{},...t.puppeteer,args:t.puppeteer.args?[...t.puppeteer.args]:e.puppeteer?.args}:e.puppeteer,sdkKit:t.sdkKit?{...e.sdkKit??{},...t.sdkKit,urls:t.sdkKit.urls?{...e.sdkKit?.urls??{},...t.sdkKit.urls}:e.sdkKit?.urls}:e.sdkKit,sdk:t.sdk?{...e.sdk??{},...t.sdk,urls:t.sdk.urls?{...e.sdk?.urls??{},...t.sdk.urls}:e.sdk?.urls}:e.sdk}),y=[`SIGINT`,`SIGTERM`,`SIGTSTP`],b=[`axios`,`happy-dom`,`jsdom`,`puppeteer`];let x=_(),S=!1,C=!1;const w=new Set,T=()=>globalThis.__oapieBrowserSession,E=()=>{!T()&&w.size===0&&O()},D=()=>{if(!C){for(let e of y)process.on(e,A);C=!0}},O=()=>{if(C){for(let e of y)process.off(e,A);C=!1}},k=e=>(D(),w.add(e),()=>{w.delete(e),E()}),ee=async()=>{let e=Array.from(w).reverse();w.clear();for(let t of e)await t();await M()},A=async e=>{if(!S){S=!0,O();try{await ee()}catch(e){console.error(`Failed to close active browser resources:`,e)}finally{S=!1}if(e===`SIGTSTP`){process.kill(process.pid,e);return}process.exit(e===`SIGINT`?130:143)}},j=async(e=x)=>{let t=T();if(t?.browser===e.browser)return t;t&&await M();let n={browser:e.browser,closers:[]};return e.browser===`puppeteer`&&(n.puppeteerBrowser=await(await import(`puppeteer`)).launch({headless:e.puppeteer?.headless??!0,args:e.puppeteer?.args??[`--no-sandbox`,`--disable-setuid-sandbox`]})),D(),globalThis.__oapieBrowserSession=n,n},M=async()=>{let e=T();if(e){globalThis.__oapieBrowserSession=void 0;for(let t of e.closers.reverse())await t();e.puppeteerBrowser&&await e.puppeteerBrowser.close(),E()}},N=(e,t)=>{let n=T();return!n||n.browser!==e?!1:(n.closers.push(t),!0)},P=e=>b.includes(e),te=async(r,i=x,a=!1)=>{let{data:o}=i.browser===`puppeteer`?{data:``}:await n.get(r,{timeout:i.requestTimeout,maxRedirects:i.maxRedirects,headers:{"User-Agent":i.userAgent,Accept:`text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8`}});if(i.browser===`axios`)return o;if(i.browser===`happy-dom`){let e=new t({url:r,innerWidth:1024,innerHeight:768,settings:i.happyDom}),n=k(()=>e.happyDOM.close());try{e.document.write(o),await e.happyDOM.waitUntilComplete();let t=e.document.documentElement.outerHTML;if(!t)throw await e.happyDOM.close(),Error(`Unable to extract HTML from remote source: ${r}`);return N(`happy-dom`,()=>e.happyDOM.close())||await e.happyDOM.close(),t}finally{n()}}else if(i.browser===`jsdom`){let t,n;try{({window:t}=new e(o,{url:r,contentType:`text/html`,runScripts:`dangerously`,includeNodeLocations:!0})),n=k(()=>t?.close());let i=t.document.documentElement.outerHTML;if(!i)throw Error(`Unable to extract HTML from remote source: ${r}`);let a=t;return N(`jsdom`,()=>a.close())||t.close(),t=void 0,i}finally{n?.(),t&&t.close()}}else if(i.browser===`puppeteer`){let e=T(),t=Math.max(i.requestTimeout,3e4),o=e?.browser===`puppeteer`?e.puppeteerBrowser:void 0,s=!1,c,l,u;try{o||(o=await(await import(`puppeteer`)).launch({headless:i.puppeteer?.headless??!0,args:i.puppeteer?.args??[`--no-sandbox`,`--disable-setuid-sandbox`]}),s=!0,l=k(async()=>{o?.connected&&await o.close()})),c=await o.newPage(),u=k(async()=>{c&&!c.isClosed()&&await c.close()}),await c.setUserAgent({userAgent:i.userAgent}),await c.setRequestInterception(!0),c.on(`request`,e=>{let t=e.resourceType();if([`image`,`font`,`media`,`stylesheet`].includes(t))return void e.abort();e.continue()});try{await c.goto(r,{waitUntil:`domcontentloaded`,timeout:t})}catch(e){if(!c||!await se(c))throw e}let e=await ie(c,t,a);if(!e)throw Error(`Unable to extract HTML from remote source: ${r}`);if(!e.includes(`id="ssr-props"`)){let{data:t}=await n.get(r,{timeout:i.requestTimeout,maxRedirects:i.maxRedirects,headers:{"User-Agent":i.userAgent,Accept:`text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8`}});e=ce(e,t)}return e}finally{u?.(),c&&!c.isClosed()&&await c.close(),l?.(),s&&o&&await o.close()}}else throw Error(`Unsupported browser specified in configuration: ${x.browser}`)},ne=async(e,t,n=!1)=>{try{n&&await e.waitForSelector(`.hub-sidebar-content .rm-Sidebar-link`),await e.waitForSelector(`[data-testid="http-method"], article#content, script#ssr-props`,{timeout:t})}catch{}},re=async(e,t)=>{try{await e.waitForFunction(()=>{let e=!!document.querySelector(`[data-testid="http-method"]`),t=!!document.querySelector(`form[name="Parameters"]`),n=!!document.querySelector(`.rm-PlaygroundRequest`),r=!!document.querySelector(`.rm-PlaygroundResponse`),i=!!document.querySelector(`script#ssr-props`);return e?t||n||r||i:!1},{timeout:t})}catch{}try{await e.waitForSelector(`.rm-PlaygroundRequest, .rm-PlaygroundResponse, form[name="Parameters"], script#ssr-props`,{timeout:Math.min(t,5e3)})}catch{}try{await e.waitForNetworkIdle?.({idleTime:500,timeout:Math.min(t,5e3)})}catch{}},ie=async(e,t,n=!1,r=3)=>{let i;for(let a=1;a<=r;a+=1)try{return await ne(e,t,n),await re(e,t),await e.content()}catch(n){if(i=n,!oe(n)||a===r)throw n;await ae(e,t)}throw i instanceof Error?i:Error(`Unable to extract stable HTML from remote source`)},ae=async(e,t)=>{try{await e.waitForFunction(()=>document.readyState===`interactive`||document.readyState===`complete`,{timeout:Math.min(t,5e3)})}catch{}try{await e.waitForNetworkIdle?.({idleTime:500,timeout:Math.min(t,5e3)})}catch{}},oe=e=>{if(!(e instanceof Error))return!1;let t=e.message.toLowerCase();return t.includes(`execution context was destroyed`)||t.includes(`cannot find context with specified id`)||t.includes(`most likely because of a navigation`)},se=async e=>!!await e.$(`[data-testid="http-method"], article#content, script#ssr-props`),ce=(e,t)=>{if(e.includes(`id="ssr-props"`))return e;let n=le(t);return n?e.includes(`</body>`)?e.replace(`</body>`,`${n}</body>`):e.includes(`</html>`)?e.replace(`</html>`,`${n}</html>`):`${e}${n}`:e},le=e=>e.match(/<script id="ssr-props"[^>]*>[\s\S]*?<\/script>/i)?.[0]??null;var F=class e{static parsePossiblyTruncated=t=>{let n=new e,r=t.trim();if(!/^(?:\{|\[)/.test(r))return null;try{return JSON.parse(r)}catch{let e=n.repairCommonJsonIssues(r);try{return JSON.parse(e)}catch{return null}}};repairCommonJsonIssues=e=>{let t=this.removeUnexpectedObjectTokens(e),n=this.insertMissingCommas(t);return`${n}${this.buildMissingJsonClosers(n)}`};removeUnexpectedObjectTokens=e=>e.replace(/([[{,]\s*)([A-Za-z_$][\w$-]*)(?=\s*"(?:\\.|[^"\\])*"\s*:)/g,`$1`);insertMissingCommas=e=>{let t=``,n=!1,r=!1,i=``;for(let a=0;a<e.length;a+=1){let o=e[a];if(n){if(t+=o,r){r=!1;continue}if(o===`\\`){r=!0;continue}o===`"`&&(n=!1,i=`"`);continue}if(o===`"`){let r=e.slice(a);/^"(?:\\.|[^"\\])*"\s*:/.test(r)&&this.shouldInsertCommaBeforeKey(i,t)&&(t+=`,`),t+=o,n=!0;continue}t+=o,/\s/.test(o)||(i=o)}return t};shouldInsertCommaBeforeKey=(e,t)=>{if(!e||![`"`,`}`,`]`,`e`,`l`,`0`,`1`,`2`,`3`,`4`,`5`,`6`,`7`,`8`,`9`].includes(e))return!1;let n=t.trimEnd();return!n.endsWith(`,`)&&!n.endsWith(`{`)};buildMissingJsonClosers=e=>{let t=[],n=!1,r=!1;for(let i of e){if(r){r=!1;continue}if(i===`\\`){r=!0;continue}if(i===`"`){n=!n;continue}if(!n){if(i===`{`){t.push(`}`);continue}if(i===`[`){t.push(`]`);continue}(i===`}`||i===`]`)&&t[t.length-1]===i&&t.pop()}}return t.reverse().join(``)}};const I=e=>typeof e==`object`&&!!e&&!Array.isArray(e),L=e=>{let n=new t;n.document.write(e);let{document:r}=n,i=r.querySelector(`article#content`)??r.body,a=i.querySelector(`form[name="Parameters"]`),o=r.querySelector(`.rm-PlaygroundRequest`),s=r.querySelector(`.rm-PlaygroundResponse`),c=be(o),l=Re(c[0]??null),u=xe(s);return ue({method:q(i.querySelector(`[data-testid="http-method"]`))?.toUpperCase()??null,url:q(i.querySelector(`[data-testid="serverurl"]`)),description:ye(i),sidebarLinks:Se(r.querySelector(`.rm-Sidebar.hub-sidebar-content`)),requestParams:Ce(a),requestCodeSnippets:c,requestExample:c[0]?.body??null,requestExampleNormalized:l,responseSchemas:we(i),responseBodies:u,responseExample:u[0]?.body??null,responseExampleRaw:u[0]?.rawBody??null},de(r))},ue=(e,t)=>t?{method:e.method??t.method,url:e.url??t.url,description:e.description??t.description,sidebarLinks:e.sidebarLinks.length>0?e.sidebarLinks:t.sidebarLinks,requestParams:e.requestParams.length>0?e.requestParams:t.requestParams,requestCodeSnippets:e.requestCodeSnippets.length>0?e.requestCodeSnippets:t.requestCodeSnippets,requestExample:e.requestExample??t.requestExample,requestExampleNormalized:e.requestExampleNormalized??t.requestExampleNormalized,responseSchemas:e.responseSchemas.length>0?e.responseSchemas:t.responseSchemas,responseBodies:e.responseBodies.length>0?e.responseBodies:t.responseBodies,responseExample:e.responseExample??t.responseExample,responseExampleRaw:e.responseExampleRaw??t.responseExampleRaw}:e,de=e=>{let t=e.querySelector(`script#ssr-props`)?.textContent?.trim();if(!t)return null;let n;try{n=JSON.parse(t)}catch{return null}let r=I(n)&&I(n.document)?n.document.api:null;if(!I(r))return null;let i=typeof r.method==`string`?r.method.toUpperCase():null,a=typeof r.path==`string`?r.path:null,o=I(r.schema)?r.schema:null,s=pe(o,a,i?.toLowerCase()??null),c=Array.isArray(o?.servers)&&I(o.servers[0])&&typeof o.servers[0].url==`string`?o.servers[0].url:null;if(!s&&!i&&!a)return null;let l=_e(s?.responses??{});return{method:i,url:me(c,a),description:s?.description??null,sidebarLinks:[],requestParams:[...fe(s?.parameters),...he(s?.requestBody)],requestCodeSnippets:[],requestExample:null,requestExampleNormalized:null,responseSchemas:ge(s?.responses??{}),responseBodies:l,responseExample:l[0]?.body??null,responseExampleRaw:l[0]?.rawBody??null}},fe=e=>e?e.map(e=>({name:e.name,in:e.in,path:[e.name],type:e.schema?.type??null,required:e.required??!1,defaultValue:e.schema?.default==null?e.example==null?null:String(e.example):String(e.schema.default),description:e.description??e.schema?.description??null})):[],pe=(e,t,n)=>{if(!e||!t||!n||!I(e.paths))return null;let r=e.paths[t];return!I(r)||!I(r[n])?null:r[n]},me=(e,t)=>!e||!t?null:`${e.replace(/\/$/,``)}${t.startsWith(`/`)?t:`/${t}`}`,he=e=>{let t=e?.content?.[`application/json`]?.schema;return t?R(t):[]},R=(e,t=[])=>{if(!e.properties)return[];let n=[];for(let[r,i]of Object.entries(e.properties)){let a=[...t,r],o=e.required?.includes(r)??!1;if(i.type===`object`&&i.properties){n.push(...R(i,a).map(e=>({...e,required:e.path.length===a.length+1?o&&e.required:e.required})));continue}n.push({name:r,in:`body`,path:a,type:i.type??null,required:o,defaultValue:i.default==null?null:String(i.default),description:i.description??null})}return n},ge=e=>Object.entries(e).map(([e,t])=>({statusCode:e,description:t.description??e})),_e=e=>{let t=[];for(let[n,r]of Object.entries(e))for(let[e,i]of Object.entries(r.content??{})){let a=ve(i);if(a==null)continue;let o=typeof a==`string`?a:JSON.stringify(a,null,2),s=V(o,e);t.push({format:s.format,contentType:e,statusCode:n,label:r.description??n,body:s.body,rawBody:o})}return t},ve=e=>{if(e.example!==void 0)return e.example;let t=e.examples;if(t&&I(t)){for(let e of Object.values(t))if(I(e)&&`value`in e)return e.value??null}return e.schema?.example===void 0?null:e.schema.example},ye=e=>{let t=e.querySelector(`header`);if(!t)return null;let n=Array.from(t.querySelectorAll(`[data-testid="RDMD"]`));return q(n[n.length-1]??null)},be=e=>{if(!e)return[];let t=Ee(e);return z(e).map(e=>({label:t,body:e}))},xe=e=>{if(!e)return[];let t=z(e),n=ke(e),r=Ae(e);return t.map((e,t)=>{let i=r[t]??r[0]??null,a=n[t]??n[0]??null,o=V(e,a);return{format:o.format,contentType:a,statusCode:i?.match(/\b\d{3}\b/)?.[0]??null,label:i,body:o.body,rawBody:e}})},Se=e=>e?Array.from(e.querySelectorAll(`.rm-Sidebar-link`)).map(e=>{let t=e.closest(`.rm-Sidebar-section`),n=q(e.querySelector(`[data-testid="http-method"]`))?.toUpperCase()??null;return{section:q(t?.querySelector(`.rm-Sidebar-heading`)??null),label:Oe(e,n),href:e.getAttribute(`href`),method:n,active:e.classList.contains(`active`)||e.getAttribute(`aria-current`)===`page`,subpage:e.classList.contains(`subpage`)}}).filter(e=>e.label.length>0):[],Ce=e=>e?Array.from(e.querySelectorAll(`label`)).map(t=>{let n=q(t),r=je(t,e),i=Me(r,t);return{name:n??``,in:Ne(r,t,e),path:Pe(t,n),type:Fe(r,i),required:Ie(r,i),defaultValue:De(i),description:Le(r)}}).filter(e=>e.name.length>0):[],we=e=>{let t=e.querySelector(`#response-schemas`)?.nextElementSibling;return!t||!t.classList.contains(`rm-APIResponseSchemaPicker`)?[]:Array.from(t.querySelectorAll(`button`)).map(e=>{let t=q(e),n=t?.match(/\b\d{3}\b/),r=Array.from(e.querySelectorAll(`[data-testid="RDMD"]`));return{statusCode:n?.[0]??null,description:q(r[0]??null)??t}}).filter(e=>e.statusCode!==null)},z=e=>Array.from(e.querySelectorAll(`.CodeSnippet`)).map(e=>Te(e)).filter(e=>!!e),Te=e=>{if(!e)return null;let t=Array.from(e.querySelectorAll(`.CodeMirror-code pre.CodeMirror-line`));return t.length===0?null:t.map(e=>e.textContent?.replace(/\u00a0/g,` `)??``).join(`
2
+ `).trimEnd()||null},Ee=e=>{let t=e.querySelector(`header`);if(!t)return null;let n=Array.from(t.querySelectorAll(`button`)).map(e=>Y(e)).filter(e=>!!e);return n.find(e=>e.toLowerCase()!==`examples`)??n[0]??null},De=e=>e&&e.getAttribute(`value`)?.trim()||null,Oe=(e,t)=>J(e.querySelectorAll(`span`)).filter(e=>!t||e.toUpperCase()!==t).sort((e,t)=>t.length-e.length)[0]??q(e)??``,ke=e=>J(e.querySelectorAll(`div`)).filter(e=>/^[\w.+-]+\/[\w.+-]+$/i.test(e)),Ae=e=>Array.from(e.querySelectorAll(`button, [role="button"]`)).map(e=>Y(e)).filter(e=>!!e).filter(e=>/\b\d{3}\b/.test(e)),je=(e,t)=>{let n=e.getAttribute(`for`),r=e;for(;r;){let e=n?r.querySelector(`#${K(n)}`):null,i=r.querySelector(`input, textarea, select`);if((e||i)&&r!==t)return r;r=r.parentElement}return e},Me=(e,t)=>{let n=t.getAttribute(`for`),r=n?e.querySelector(`#${K(n)}`):null,i=e.querySelector(`input, textarea, select`);return r??i},Ne=(e,t,n)=>{let r=B(`${t.getAttribute(`for`)?.toLowerCase()??``} ${e.closest(`[id]`)?.getAttribute(`id`)?.toLowerCase()??``}`);if(r)return r;let i=e;for(;i&&i!==n;){let e=i.previousElementSibling;for(;e;){if(e.tagName===`HEADER`){let t=B(q(e)??``);if(t)return t}e=e.previousElementSibling}i=i.parentElement}return null},B=e=>{let t=e.trim().toLowerCase();return t.includes(`query params`)||t.includes(`query-`)?`query`:t.includes(`headers`)||t.includes(`header-`)?`header`:t.includes(`body params`)||t.includes(`request body`)||t.includes(`body-`)?`body`:t.includes(`path params`)||t.includes(`path-`)?`path`:t.includes(`cookie`)||t.includes(`cookie-`)?`cookie`:null},Pe=(e,t)=>{let n=e.getAttribute(`for`)??``,r=n.includes(`_`)?n.slice(n.indexOf(`_`)+1):``;return r.includes(`.`)?r.split(`.`).map(e=>e.trim()).filter(e=>e.length>0):t?[t]:[]},Fe=(e,t)=>{let n=t?.getAttribute(`type`)?.toLowerCase();if(n===`text`)return`string`;if(n)return n;let r=Array.from(e.querySelectorAll(`[class]`)).find(e=>(e.getAttribute(`class`)??``).split(/\s+/).some(e=>e.startsWith(`field-`)))?.getAttribute(`class`)?.split(/\s+/).find(e=>e.startsWith(`field-`));return r?r.replace(/^field-/,``):null},Ie=(e,t)=>t?.hasAttribute(`required`)?!0:J(e.querySelectorAll(`*`)).some(e=>e.toLowerCase()===`required`),Le=e=>q(e.querySelector(`[id$="__description"]`)||(Array.from(e.querySelectorAll(`[data-testid="RDMD"]`))[0]??null)),V=(e,t)=>{let n=e.trim();if(t?.toLowerCase().includes(`json`)||/^(?:\{|\[)/.test(n)){let t=F.parsePossiblyTruncated(n);if(t!==null)return{format:`json`,body:t};let r=G(n);return r===null?{format:`text`,body:e}:{format:`json`,body:r}}return{format:`text`,body:e}},Re=e=>e?H(e)??ze(e)??{sourceLabel:e.label,method:null,url:null,headers:{},bodyFormat:null,body:null,rawBody:null}:null,H=e=>{if(!e.body.startsWith(`curl `))return null;let t=e.body.match(/--request\s+([A-Z]+)/)?.[1]??null,n=e.body.match(/--url\s+(\S+)/)?.[1]??null,r=Object.fromEntries(Array.from(e.body.matchAll(/--header\s+'([^:]+):\s*([^']+)'/g)).map(e=>[e[1].trim(),e[2].trim()])),i=e.body.match(/--data\s+'([\s\S]*)'$/)?.[1]?.trim()??null,a=i?V(i,r[`content-type`]??r[`Content-Type`]??null):null;return{sourceLabel:e.label,method:t,url:n,headers:r,bodyFormat:a?.format??null,body:a?.body??null,rawBody:i}},ze=e=>{let t=e.body.match(/fetch\(\s*(["'])(.*?)\1\s*,\s*\{([\s\S]*)\}\s*\)/);if(!t)return null;let[,,n,r]=t,i=U(r,`method`)?.toUpperCase()??null,a=Be(r),o=Ve(r),s=a[`content-type`]??a[`Content-Type`]??null,c=o?He(o,s):null;return{sourceLabel:e.label,method:i,url:n,headers:a,bodyFormat:c?.format??null,body:c?.body??null,rawBody:o}},Be=e=>{let t=U(e,`headers`);if(!t)return{};let n=G(t);return I(n)?Object.fromEntries(Object.entries(n).map(([e,t])=>[e,String(t)])):{}},Ve=e=>U(e,`body`),He=(e,t)=>{let n=G(e);return n!==null&&(t?.toLowerCase().includes(`json`)||/^[[{]/.test(e.trim()))?{format:`json`,body:n}:V(e,t)},U=(e,t)=>{let n=e.match(RegExp(`\\b${t}\\s*:`,`m`));if(!n||n.index===void 0)return null;let r=n.index+n[0].length;for(;/\s/.test(e[r]??``);)r+=1;if(e.startsWith(`JSON.stringify`,r)){let t=e.indexOf(`(`,r);return t===-1?null:W(e,t,`(`,`)`)?.slice(1,-1).trim()??null}if(e[r]===`{`||e[r]===`[`){let t=e[r]===`{`?`}`:`]`;return W(e,r,e[r],t)?.trim()??null}return e[r]===`"`||e[r]===`'`?Ue(e,r):(e.slice(r).match(/^([^,\n]+)/)?.[1])?.trim()??null},W=(e,t,n,r)=>{let i=0,a=null,o=!1;for(let s=t;s<e.length;s+=1){let c=e[s];if(a){if(o){o=!1;continue}if(c===`\\`){o=!0;continue}c===a&&(a=null);continue}if(c===`"`||c===`'`){a=c;continue}if(c===n){i+=1;continue}if(c===r&&(--i,i===0))return e.slice(t,s+1)}return null},Ue=(e,t)=>{let n=e[t],r=``,i=!1;for(let a=t+1;a<e.length;a+=1){let t=e[a];if(i){r+=t,i=!1;continue}if(t===`\\`){i=!0;continue}if(t===n)return r;r+=t}return null},G=e=>{let t=Ge(e).trim();if(!/^[[{]/.test(t))return null;let n=We(t.replace(/([{,]\s*)([A-Za-z_$][\w$-]*)(\s*:)/g,`$1"$2"$3`).replace(/,\s*([}\]])/g,`$1`));try{return JSON.parse(n)}catch{return null}},We=e=>{let t=``,n=!1,r=!1,i=!1,a=``;for(let o of e){if(r){if(i){a+=o,i=!1;continue}if(o===`\\`){i=!0;continue}if(o===`'`){t+=JSON.stringify(a),a=``,r=!1;continue}a+=o;continue}if(n){if(t+=o,i){i=!1;continue}if(o===`\\`){i=!0;continue}o===`"`&&(n=!1);continue}if(o===`'`){r=!0,a=``;continue}o===`"`&&(n=!0),t+=o}return t},Ge=e=>{let t=Ke(e);return t=qe(t),t=Je(t),t},Ke=e=>{let t=``,n=!1,r=!1;for(let i=0;i<e.length;i+=1){let a=e[i],o=e[i+1];if(n){if(t+=a,r){r=!1;continue}if(a===`\\`){r=!0;continue}a===`"`&&(n=!1);continue}if(a===`"`){n=!0,t+=a;continue}if(a===`/`&&o===`/`){for(;i<e.length&&e[i]!==`
3
+ `;)i+=1;i<e.length&&(t+=e[i]);continue}t+=a}return t},qe=e=>e.replace(/([[{]\s*)([A-Za-z_$][\w$-]*)(\s+)(?=")/g,`$1`),Je=e=>{let t=e.trimStart();return!t.startsWith(`{`)||/"data"\s*:\s*\[/.test(t)||!/^\{\s*"[^"]+"\s*:/.test(t)||!/\]\s*,\s*"meta"\s*:/.test(t)?e:`${e.slice(0,e.indexOf(`{`))}{"data": [{${t.slice(1)}`},K=e=>e.replace(/([#.:[\],=])/g,`\\$1`),q=e=>e?.textContent?.replace(/\s+/g,` `).trim()||null,J=e=>Array.from(e).map(e=>q(e)).filter(e=>!!e),Y=e=>J(e.querySelectorAll(`span, div, code`)).filter(e=>e.trim().length>0).sort((e,t)=>t.length-e.length)[0]??q(e),Ye=(e,t)=>{let n=new URL(t),r=e.sidebarLinks.map(e=>e.href).filter(e=>!!e).map(e=>new URL(e,n).toString()).filter(e=>/^https?:\/\//i.test(e));return Array.from(new Set(r))};var Xe=class{config;constructor(e={}){this.config=v(_(),e)}getConfig(e={}){return{...this.config,...e}}configure(e){return this.config=v(this.config,e),this.config}async crawlReadmeOperations(e,t,n){let i=this.resolveCrawlBaseUrl(e,n);if(!i)throw Error(`Crawl mode requires a remote source URL or --base-url when using a local file`);let a=!!T();a||await j(this.config);try{let e=Ye(t,i),n=new URL(i).toString(),a=this.attachSourceUrl(n,t),o=e.filter(e=>e!==n);return{rootSource:n,discoveredUrls:e,operations:[a,...(await Promise.all(o.map(async e=>{let t=Date.now(),n=L(await this.loadHtmlSource(e)),a=Date.now()-t;return n.method?(r.twoColumnDetail(r.log([[`Crawled`,`green`],[`${a/1e3}s`,`gray`]],` `,!1),e.replace(i,``)),this.attachSourceUrl(e,n)):null}))).filter(e=>e!==null)]}}finally{a||await M()}}attachSourceUrl(e,t){return{sourceUrl:e,...t}}resolveCrawlBaseUrl(e,t){return t?new URL(t).toString():/^https?:\/\//i.test(e)?e:null}async loadHtmlSource(e,t){if(!e)throw Error(`A source path or URL is required`);return/^https?:\/\//i.test(e)?te(e,this.config,t):o(i.resolve(process.cwd(),e),`utf8`)}},Ze=class{renderDeclaration(e){switch(e.kind){case`interface`:return this.renderInterface(e);case`interface-alias`:return`export interface ${e.name} extends ${e.target} {}`;case`type-alias`:return`export type ${e.name} = ${e.target}`;case`shape-alias`:return`export type ${e.name} = ${this.renderShape(e.shape)}`}}renderOpenApiDocumentDefinitions(e,t,n){return[`export interface OpenApiInfo {
4
4
  title: string
5
5
  version: string
6
6
  }`,`export interface OpenApiSchemaDefinition {
@@ -136,7 +136,7 @@ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"a
136
136
  `)}renderValue(e){return this.renderLiteral(e,0)}renderOpenApiDocumentValue(e){return this.renderLiteral(this.normalizeOpenApiDocument(e),0)}toCamelCase(e){let t=this.sanitizeTypeName(e);return t.charAt(0).toLowerCase()+t.slice(1)}renderInterface(e){let t=e.properties.map(e=>` ${this.formatPropertyKey(e.key)}${e.optional?`?`:``}: ${this.renderShape(e.shape)}`).join(`
137
137
  `);return`export interface ${e.name} {\n${t}\n}`}renderShape(e){switch(e.kind){case`primitive`:return e.type;case`array`:return`${this.wrapUnion(this.renderShape(e.item))}[]`;case`union`:return e.types.map(e=>this.renderShape(e)).join(` | `);case`object`:return this.inlineObjectShape(e)}}inlineObjectShape(e){return e.properties.length===0?`Record<string, never>`:`{ ${e.properties.map(e=>`${this.formatPropertyKey(e.key)}${e.optional?`?`:``}: ${this.renderShape(e.shape)}`).join(`; `)} }`}wrapUnion(e){return e.includes(` | `)?`(${e})`:e}derivePathTypeName(e){let t=e.split(`/`).map(e=>e.trim()).filter(Boolean).filter(e=>!/^v\d+$/i.test(e)).map(e=>this.isPathParam(e)?`by ${this.stripPathParam(e)}`:e);return`${this.sanitizeTypeName(t.join(` `))}Path`}deriveOperationInterfaceName(e,t){return`${this.derivePathTypeName(e)}${this.sanitizeTypeName(t)}Operation`}sanitizeTypeName(e){let t=e.replace(/[^A-Za-z0-9]+/g,` `).trim();if(!t)return`GeneratedEntity`;let n=t.split(/\s+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);return/^[A-Za-z_$]/.test(n)?n:`Type${n}`}formatPropertyKey(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)?e:`'${this.escapeStringLiteral(e)}'`}renderSdkMethodSignature(e){let t=[];return e.pathParams.length>0&&t.push(`(params: ${e.paramsType}`),e.queryParams.length>0&&t.push(`${t.length===0?`(`:`, `}query: ${e.queryType}`),e.hasBody&&t.push(`${t.length===0?`(`:`, `}body${e.bodyRequired?``:`?`}: ${e.inputType}`),e.headerParams.length>0&&t.push(`${t.length===0?`(`:`, `}headers?: ${e.headerType}`),t.length===0?`(): Promise<${e.responseType}>`:`${t.join(``)}): Promise<${e.responseType}>`}renderLiteral(e,t){if(e===null)return`null`;if(typeof e==`string`)return`'${this.escapeStringLiteral(e)}'`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(Array.isArray(e)){if(e.length===0)return`[]`;let n=this.indent(t+1),r=this.indent(t);return`[\n${e.map(e=>`${n}${this.renderLiteral(e,t+1)}`).join(`,
138
138
  `)}\n${r}]`}if(typeof e==`object`){let n=Object.entries(e);if(n.length===0)return`{}`;let r=this.indent(t+1),i=this.indent(t);return`{\n${n.map(([e,n])=>`${r}${this.formatPropertyKey(e)}: ${this.renderLiteral(n,t+1)}`).join(`,
139
- `)}\n${i}}`}return`undefined`}normalizeOpenApiDocument(e){return this.normalizeObject(e,(e,t,n)=>{if(e===`example`&&n&&typeof n==`object`&&!Array.isArray(n)){let e=n;if(e.schema&&this.isPlainObject(e.schema))return this.normalizeExample(t,e.schema);if(this.isSchemaLike(e))return this.normalizeExample(t,e)}return t})}normalizeObject(e,t){if(Array.isArray(e))return e.map(e=>this.normalizeObject(e,t)).filter(e=>e!==void 0);if(!this.isPlainObject(e))return e;let n={};for(let[r,i]of Object.entries(e)){let a=t(r,i,e),o=this.normalizeObject(a,t);o!==void 0&&(n[r]=o)}return n}normalizeExample(e,t){if(e===void 0)return;let n=typeof t.type==`string`?t.type:void 0;if(n===`string`)return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):void 0;if(n===`number`||n===`integer`)return typeof e==`number`?e:typeof e==`string`&&e.trim()!==``&&Number.isFinite(Number(e))?Number(e):void 0;if(n===`boolean`)return typeof e==`boolean`?e:e===`true`?!0:e===`false`?!1:void 0;if(n===`array`){if(!Array.isArray(e))return;let n=this.isPlainObject(t.items)?t.items:void 0;return n?e.map(e=>this.normalizeExample(e,n)).filter(e=>e!==void 0):e}if(n===`object`){if(!this.isPlainObject(e))return;let n=this.isPlainObject(t.properties)?t.properties:{},r=Array.isArray(t.required)?t.required.filter(e=>typeof e==`string`):[],i={};for(let[t,r]of Object.entries(e)){let e=n[t],a=e?this.normalizeExample(r,e):r;a!==void 0&&(i[t]=a)}for(let e of r){if(e in i)continue;let t=n[e];if(!t)return;let r=t.default===void 0?t.example===void 0?void 0:this.normalizeExample(t.example,t):this.normalizeExample(t.default,t);if(r===void 0)return;i[e]=r}return i}return e}isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}isSchemaLike(e){return`type`in e||`properties`in e||`items`in e||`required`in e||`default`in e}indent(e){return` `.repeat(e)}escapeStringLiteral(e){return e.replace(/\\/g,String.raw`\\`).replace(/'/g,String.raw`\'`).replace(/\r/g,String.raw`\r`).replace(/\n/g,String.raw`\n`).replace(/\t/g,String.raw`\t`).replace(/\f/g,String.raw`\f`).replace(/\x08/g,String.raw`\b`).replace(/\u2028/g,String.raw`\u2028`).replace(/\u2029/g,String.raw`\u2029`)}isPathParam(e){return e.startsWith(`{`)&&e.endsWith(`}`)||/^:[A-Za-z0-9_]+$/.test(e)}stripPathParam(e){return e.replace(/^\{/,``).replace(/\}$/,``).replace(/^:/,``)}},Ze=class e{static contextualTailSegments=new Set([`history`,`status`,`detail`,`details`]);static irregularSingulars=new Map([[`analyses`,`analysis`],[`diagnoses`,`diagnosis`],[`parentheses`,`parenthesis`],[`statuses`,`status`],[`synopses`,`synopsis`],[`theses`,`thesis`]]);static invariantSingulars=new Set([`analysis`,`diagnosis`,`news`,`series`,`species`,`status`,`synopsis`,`thesis`]);static nestedContextSegments=new Set([`account`,`accounts`,`transaction`,`transactions`,`wallet`,`wallets`,`virtual-account`,`virtual-accounts`,`history`]);static roleSuffixes=[`Input`,`Query`,`Header`,`Params`];sanitizeTypeName(e){let t=e.replace(/[^A-Za-z0-9]+/g,` `).trim();if(!t)return`GeneratedEntity`;let n=t.split(/\s+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);return/^[A-Za-z_$]/.test(n)?n:`Type${n}`}isPathParam(e){return e.startsWith(`{`)&&e.endsWith(`}`)||/^:[A-Za-z0-9_]+$/.test(e)}stripPathParam(e){return e.replace(/^\{/,``).replace(/\}$/,``).replace(/^:/,``)}singularize(t){let n=t.toLowerCase();return e.irregularSingulars.has(n)?e.irregularSingulars.get(n)??t:e.invariantSingulars.has(n)?t:/ies$/i.test(t)?`${t.slice(0,-3)}y`:/(sses|shes|ches|xes|zes)$/i.test(t)||/uses$/i.test(t)?t.slice(0,-2):t.endsWith(`s`)&&!t.endsWith(`ss`)&&t.length>1?t.slice(0,-1):t}pluralize(e){return/y$/i.test(e)?`${e.slice(0,-1)}ies`:/s$/i.test(e)?e:`${e}s`}toCamelCase(e){let t=this.sanitizeTypeName(e);return t.charAt(0).toLowerCase()+t.slice(1)}deriveOperationNaming(t){let n=this.getNormalizedPathSegments(t),r=n.filter(e=>!this.isPathParam(e)).map(e=>this.singularize(e)),i=n.filter(e=>this.isPathParam(e)).map(e=>this.singularize(this.stripPathParam(e))),a=r[r.length-1]??`resource`,o=r[r.length-2]??null,s=n.slice(0,-1).some(e=>this.isPathParam(e)),c=!!(o&&(e.contextualTailSegments.has(a.toLowerCase())||s&&e.nestedContextSegments.has(a.toLowerCase())));return{baseName:this.sanitizeTypeName(c?`${o} ${a}`:a),collisionSuffix:i.length>0?`By ${i.map(e=>this.sanitizeTypeName(e)).join(` And `)}`:o&&!c?this.sanitizeTypeName(o):``}}fallbackCollisionSuffix(e,t,n){let r=this.getNormalizedPathSegments(t),i=r.filter(e=>!this.isPathParam(e)),a=i[i.length-1]??``,o=r.some(e=>this.isPathParam(e));return e===`get`&&!o&&/s$/i.test(a)?`List`:e===`post`&&!o?`Create`:(e===`put`||e===`patch`)&&o?`Update`:e===`delete`?`Delete`:`${this.sanitizeTypeName(e)}${n}`}insertCollisionSuffix(t,n){if(!n)return t;for(let r of e.roleSuffixes)if(t.endsWith(r)&&t.length>r.length)return`${t.slice(0,-r.length)}${n}${r}`;return`${t}${n}`}deriveSdkGroupNamesBySignature(e,t){let n=new Map;for(let t of Object.keys(e.paths)){let e=this.getStaticPathSignature(t);n.has(e)||n.set(e,t)}let r=Array.from(n.entries()).map(([e,n])=>({signature:e,staticSegments:e.split(`/`).filter(Boolean),candidates:this.buildSdkGroupNameCandidates(n,t)})).sort((e,t)=>e.staticSegments.length-t.staticSegments.length||e.signature.localeCompare(t.signature)),i=new Map,a=new Set;for(let e of r){let t=e.candidates.find(e=>!a.has(e))??this.createUniqueSdkGroupName(e.candidates[e.candidates.length-1]??`Resource`,a);a.add(t),i.set(e.signature,t)}return i}getStaticPathSegments(e){return this.getNormalizedPathSegments(e).filter(e=>!this.isPathParam(e)).map(e=>this.singularize(e))}getStaticPathSignature(e){return this.getStaticPathSegments(e).join(`/`)}getNormalizedPathSegments(e){return e.split(`/`).map(e=>e.trim()).filter(Boolean).filter(e=>!/^v\d+$/i.test(e))}deriveSdkMethodName(e,t,n,r){if(r===`operation-id`&&n.operationId)return this.toCamelCase(this.sanitizeTypeName(n.operationId));let i=this.getNormalizedPathSegments(t).some(e=>this.isPathParam(e));return e===`get`?this.endsWithPluralStaticSegment(t)?`list`:i?`get`:`list`:e===`post`?`create`:e===`patch`||e===`put`?`update`:e===`delete`?`delete`:this.toCamelCase(this.sanitizeTypeName(e))}ensureUniqueSdkMethodNames(e){let t=new Map;return e.map(e=>{let n=t.get(e.methodName)??0;if(t.set(e.methodName,n+1),n===0)return e;let r=this.sanitizeTypeName(this.fallbackCollisionSuffix(e.method.toLowerCase(),e.path,`Operation`));return{...e,methodName:`${e.methodName}${r}`}})}createSdkParameterManifest(e,t,n){return[...(e??[]).filter(e=>e.in===t).sort((e,t)=>e.name.localeCompare(t.name)),...this.getInferredPathParameters(n,t,(e??[]).filter(e=>e.in===t))].sort((e,t)=>e.name.localeCompare(t.name)).map(e=>({name:e.name,accessor:this.toParameterAccessor(e.name),in:t,required:e.required??!1,description:e.description}))}getInferredPathParameters(e,t,n){if(t!==`path`||!e)return[];let r=new Set(n.map(e=>e.name));return this.getNormalizedPathSegments(e).filter(e=>this.isPathParam(e)).map(e=>this.stripPathParam(e)).filter(e=>!r.has(e)).map(e=>({name:e,in:`path`,required:!0,schema:{type:`string`}}))}buildSdkGroupNameCandidates(e,t){let n=this.getNormalizedPathSegments(e),r=n.filter(e=>!this.isPathParam(e)),i=r.map(e=>this.singularize(e)),a=this.deriveOperationNaming(e).baseName,o=this.getPreferredSdkGroupName(n,r,i),s=i.map((e,t,n)=>this.sanitizeTypeName(n.slice(t).join(` `))).reverse();return t===`scoped`?Array.from(new Set([o??``,this.sanitizeTypeName(i.join(` `)),...s,a].filter(Boolean))):Array.from(new Set([o??``,a,...s].filter(Boolean)))}getPreferredSdkGroupName(e,t,n){let r=t[t.length-1],i=n[n.length-1],a=n[n.length-2],o=e.some(e=>this.isPathParam(e)),s=e.slice(0,-1).some(e=>this.isPathParam(e));return!r||!i||!a?null:t.length===2&&!o?this.sanitizeTypeName(`${i} ${a}`):s?this.singularize(r)===r?this.sanitizeTypeName(`${i} ${a}`):this.sanitizeTypeName(`${a} ${i}`):null}createUniqueSdkGroupName(e,t){let n=2,r=e;for(;t.has(r);)r=`${e}${n}`,n+=1;return r}endsWithPluralStaticSegment(e){let t=this.getNormalizedPathSegments(e).at(-1);return!t||this.isPathParam(t)?!1:this.singularize(t)!==t}toParameterAccessor(e){let t=e.replace(/[^A-Za-z0-9]+/g,` `).trim();if(!t)return`value`;let[n,...r]=t.split(/\s+/).filter(Boolean),i=[n.toLowerCase(),...r.map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())].join(``);return/^[A-Za-z_$]/.test(i)?i:`value${i}`}},Qe=class{constructor(e){this.naming=e}createContext(){return{declarations:[],declarationByName:new Map,nameBySignature:new Map,usedNames:new Set}}namespaceTopLevelShape(e,t){return e.kind===`object`?{...e,signature:`${t}:${e.signature}`}:e}inferShapeFromExample(e,t){if(e===null)return{kind:`primitive`,type:`null`};if(Array.isArray(e)){if(e.length===0)return{kind:`array`,item:{kind:`primitive`,type:`unknown`}};let n=this.dedupeShapes(e.map(e=>this.inferShapeFromExample(e,this.naming.singularize(t))));return{kind:`array`,item:n.length===1?n[0]:{kind:`union`,types:n}}}if(this.isRecord(e))return this.createObjectShape(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>({key:e,optional:!1,shape:this.inferShapeFromExample(t,e)})));switch(typeof e){case`string`:return{kind:`primitive`,type:`string`};case`number`:return{kind:`primitive`,type:`number`};case`boolean`:return{kind:`primitive`,type:`boolean`};default:return{kind:`primitive`,type:`unknown`}}}registerNamedShape(e,t,n,r){if(e.kind===`object`)return this.registerObjectShape(e,t,n,r,!0);let i=this.createUniqueTypeName(t,n,r),a={kind:`shape-alias`,name:i,shape:this.prepareNestedShape(e,t,n)};return n.declarations.push(a),n.declarationByName.set(i,a),i}registerObjectShape(e,t,n,r,i=!1){let a=n.nameBySignature.get(e.signature),o=this.findCompatibleObjectDeclaration(e,t,n);if(a){if(i&&a!==t&&!n.declarationByName.has(t)){let e=this.createUniqueTypeName(t,n,r);if(e!==a){let t={kind:`interface-alias`,name:e,target:a};n.declarations.push(t),n.declarationByName.set(e,t)}}return a}if(o){if(this.isObjectShapeAssignableTo(e,o.rawShape))return n.nameBySignature.set(e.signature,o.name),o.name;let t=this.mergeObjectShapes(o.rawShape,e);return o.rawShape=t,o.properties=t.properties.map(e=>({...e,shape:this.prepareNestedShape(e.shape,e.key,n)})),n.nameBySignature.set(e.signature,o.name),n.nameBySignature.set(t.signature,o.name),o.name}let s=this.createUniqueTypeName(t,n,r),c={kind:`interface`,name:s,baseName:this.naming.sanitizeTypeName(t),rawShape:e,properties:[]};return n.nameBySignature.set(e.signature,s),n.declarations.push(c),n.declarationByName.set(s,c),c.properties=e.properties.map(e=>({...e,shape:this.prepareNestedShape(e.shape,e.key,n)})),s}resolveSdkResponseType(e,t){let n=Object.entries(e).filter(([e])=>/^2\d\d$/.test(e)).sort(([e],[t])=>e.localeCompare(t))[0]?.[1];if(!n)return t;let r=this.getPreferredMediaType(n.content);if(!r)return t;let i=this.resolveResponsePayloadSchema(r.schema,r.example).schema??r.schema;return i&&this.resolveSchemaType(i)===`array`?`${t}[]`:t}getSuccessResponseShape(e){let t=Object.entries(e).filter(([e])=>/^2\d\d$/.test(e)).sort(([e],[t])=>e.localeCompare(t))[0]?.[1];if(!t)return this.emptyObjectShape;let n=this.getPreferredMediaType(t.content);if(!n)return this.emptyObjectShape;let r=this.resolveResponsePayloadSchema(n.schema,n.example);return r.schema?this.resolveSchemaType(r.schema)===`array`?this.schemaToShape(r.schema.items,`Item`,this.extractExampleArrayItem(r.example)):this.schemaToShape(r.schema,`Response`,r.example):this.schemaToShape(n.schema,`Response`,n.example)}getRequestInputShape(e){if(!e)return this.emptyObjectShape;let t=this.getPreferredMediaType(e.content);return t?this.schemaToShape(t.schema,`Input`,t.example):this.emptyObjectShape}getResponseExampleShape(e){let t=Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).flatMap(([,e])=>{let t=this.getPreferredMediaType(e.content);if(!t)return[];let n=t.example??t.schema?.example;return t.schema?[this.schemaToShape(t.schema,`ResponseExample`,n)]:n===void 0?[]:[this.inferShapeFromExample(n,`ResponseExample`)]}),n=this.dedupeShapes(t);return n.length===0?{kind:`primitive`,type:`unknown`}:n.length===1?n[0]:{kind:`union`,types:n}}createParameterGroupShape(e,t,n){let r=(e??[]).filter(e=>e.in===t).sort((e,t)=>e.name.localeCompare(t.name)),i=[...r,...this.naming.getInferredPathParameters(n,t,r)].sort((e,t)=>e.name.localeCompare(t.name));return i.length===0?this.emptyObjectShape:this.createObjectShape(i.map(e=>({key:e.name,optional:!(e.required??!1),shape:this.schemaToShape(e.schema,e.name,e.example)})))}get emptyObjectShape(){return this.createObjectShape([])}findCompatibleObjectDeclaration(e,t,n){let r=this.naming.sanitizeTypeName(t);return n.declarations.find(t=>t.kind!==`interface`||t.baseName!==r?!1:this.isObjectShapeAssignableTo(e,t.rawShape)||this.isObjectShapeAssignableTo(t.rawShape,e)||this.canMergeObjectShapes(t.rawShape,e))}canMergeObjectShapes(e,t){let n=new Set([...e.properties.map(e=>e.key),...t.properties.map(e=>e.key)]);for(let r of n){let n=e.properties.find(e=>e.key===r),i=t.properties.find(e=>e.key===r);if(!n||!i){if(!(n??i)?.optional)return!1;continue}if(!this.canMergeShapes(n.shape,i.shape))return!1}return!0}isObjectShapeAssignableTo(e,t){let n=new Map(t.properties.map(e=>[e.key,e]));for(let t of e.properties){let e=n.get(t.key);if(!e||t.optional&&!e.optional||!this.isShapeAssignableTo(t.shape,e.shape))return!1}return t.properties.every(t=>e.properties.some(e=>e.key===t.key)||t.optional)}isShapeAssignableTo(e,t){if(t.kind===`union`)return t.types.some(t=>this.isShapeAssignableTo(e,t));switch(e.kind){case`primitive`:return t.kind===`primitive`?e.type===t.type:!1;case`array`:return t.kind===`array`?this.isShapeAssignableTo(e.item,t.item):!1;case`union`:return e.types.every(e=>this.isShapeAssignableTo(e,t));case`object`:return t.kind===`object`?this.isObjectShapeAssignableTo(e,t):!1}}canMergeShapes(e,t){return e.kind===`union`?e.types.every(e=>this.canMergeShapes(e,t)):t.kind===`union`?t.types.every(t=>this.canMergeShapes(e,t)):e.kind===`primitive`&&t.kind===`primitive`?!0:e.kind===`array`&&t.kind===`array`?this.canMergeShapes(e.item,t.item):e.kind===`object`&&t.kind===`object`?this.canMergeObjectShapes(e,t):!1}mergeObjectShapes(e,t){let n=new Set([...e.properties.map(e=>e.key),...t.properties.map(e=>e.key)]);return this.createObjectShape(Array.from(n).map(n=>{let r=e.properties.find(e=>e.key===n),i=t.properties.find(e=>e.key===n);return r&&i?{key:n,optional:r.optional||i.optional,shape:this.mergeShapes(r.shape,i.shape)}:{key:n,optional:!0,shape:(r??i).shape}}))}mergeShapes(e,t){if(e.kind===`union`||t.kind===`union`||e.kind!==t.kind)return this.createUnionShape(e,t);switch(e.kind){case`primitive`:return t.kind===`primitive`&&e.type===t.type?e:this.createUnionShape(e,t);case`array`:return t.kind===`array`?{kind:`array`,item:this.mergeShapes(e.item,t.item)}:e;case`object`:return t.kind===`object`?this.mergeObjectShapes(e,t):e}}createUnionShape(...e){let t=e.flatMap(e=>e.kind===`union`?e.types:[e]),n=this.dedupeShapes(t);return n.length===1?n[0]:{kind:`union`,types:n}}prepareNestedShape(e,t,n){if(e.kind===`object`)return{kind:`primitive`,type:this.registerObjectShape(e,this.naming.sanitizeTypeName(this.naming.singularize(t)),n,this.naming.sanitizeTypeName(t))};if(e.kind===`array`)return{kind:`array`,item:this.prepareNestedShape(e.item,this.naming.singularize(t),n)};if(e.kind===`union`){let r=this.dedupeShapes(e.types.map((e,r)=>this.prepareNestedShape(e,this.getUnionMemberKeyHint(t,r,e),n)));return r.length===1?r[0]:{kind:`union`,types:r}}return e}getUnionMemberKeyHint(e,t,n){if(n.kind!==`object`&&n.kind!==`array`)return e;let r=this.naming.sanitizeTypeName(e);return r.endsWith(`ResponseExample`)?`${r}Variant${t+1}`:e}schemaToShape(e,t,n){if(!e)return this.inferShapeFromExample(n,t);let r=this.resolveSchemaType(e);if(r===`array`)return{kind:`array`,item:this.schemaToShape(e.items,this.naming.singularize(t),this.extractExampleArrayItem(e.example)??this.extractExampleArrayItem(n))};if(r===`object`){let r=this.isRecord(e.example)?e.example:this.isRecord(n)?n:void 0,i=Object.entries(e.properties??{}).sort(([e],[t])=>e.localeCompare(t)).map(([t,n])=>({key:t,optional:!(e.required??[]).includes(t),shape:this.schemaToShape(n,t,r?.[t])}));return i.length>0?this.createObjectShape(i):this.inferShapeFromExample(e.example??n,t)}return r===`integer`||r===`number`?{kind:`primitive`,type:`number`}:r===`string`?{kind:`primitive`,type:`string`}:r===`boolean`?{kind:`primitive`,type:`boolean`}:e.example===null||n===null?{kind:`primitive`,type:`null`}:e.example!==void 0||n!==void 0?this.inferShapeFromExample(e.example??n,t):{kind:`primitive`,type:`unknown`}}dedupeShapes(e){let t=new Set;return e.filter(e=>{let n=this.getShapeSignature(e);return t.has(n)?!1:(t.add(n),!0)})}createObjectShape(e){let t=e.map(e=>({...e})).sort((e,t)=>e.key.localeCompare(t.key));return{kind:`object`,signature:JSON.stringify(t.map(e=>({key:e.key,optional:e.optional,shape:this.getShapeSignature(e.shape)}))),properties:t}}getShapeSignature(e){switch(e.kind){case`primitive`:return`primitive:${e.type}`;case`array`:return`array:${this.getShapeSignature(e.item)}`;case`union`:return`union:${e.types.map(e=>this.getShapeSignature(e)).join(`|`)}`;case`object`:return`object:${e.signature}`}}getPreferredMediaType(e){if(e)return e[`application/json`]??e[`application/*+json`]??Object.values(e)[0]}resolveResponsePayloadSchema(e,t){for(let n of[[`data`],[`meta`,`data`]]){let r=this.getSchemaCandidateAtPath(e,t,n);if(r)return r}return{}}getSchemaCandidateAtPath(e,t,n){let r=this.getSchemaAtPath(e,n),i=this.getExampleAtPath(t,n);if(!(!r&&i===void 0))return r?{schema:r.example===void 0&&i!==void 0?{...r,example:i}:r,example:i??r.example}:{schema:{...this.inferSchemaTypeFromExample(i),example:i},example:i}}getSchemaAtPath(e,t){let n=e;for(let e of t){if(!n?.properties?.[e])return;n=n.properties[e]}return n}getExampleAtPath(e,t){let n=e;for(let e of t){if(!this.isRecord(n)||!(e in n))return;n=n[e]}return n}inferSchemaTypeFromExample(e){return Array.isArray(e)?{type:`array`,items:e.map(e=>this.inferSchemaTypeFromExample(e)).find(e=>this.hasSchemaDetails(e))??{}}:this.isRecord(e)?{type:`object`,properties:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,this.inferSchemaTypeFromExample(t)]))}:typeof e==`string`?{type:`string`}:typeof e==`number`?{type:`number`}:typeof e==`boolean`?{type:`boolean`}:{}}hasSchemaDetails(e){return!!(e?.type||e?.properties||e?.items||e?.example!==void 0)}resolveSchemaType(e){return e.type??(e.properties?`object`:void 0)}extractExampleArrayItem(e){return Array.isArray(e)?e[0]:void 0}createUniqueTypeName(e,t,n){let r=this.naming.sanitizeTypeName(e)||`GeneratedEntity`,i=this.naming.sanitizeTypeName(n),a=r,o=2;if(!t.usedNames.has(a)||(a=this.naming.insertCollisionSuffix(r,i),!t.usedNames.has(a)))return t.usedNames.add(a),a;for(;t.usedNames.has(a);)a=`${r}${o}`,o+=1;return t.usedNames.add(a),a}isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}},Y=class{naming=new Ze;shapes=new Qe(this.naming);createContext(){return this.shapes.createContext()}collectSemanticModels(e){let t=[];for(let[n,r]of Object.entries(e.paths)){let e=this.naming.deriveOperationNaming(n),i=e.baseName,a=Object.entries(r).sort(([,e],[,t])=>this.getOperationPriority(t)-this.getOperationPriority(e));for(let[r,o]of a){let a=e.collisionSuffix||this.naming.fallbackCollisionSuffix(r,n,i);t.push({path:n,method:r,name:i,role:`response`,shape:this.shapes.getSuccessResponseShape(o.responses),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}ResponseExample`,role:`responseExample`,shape:this.shapes.getResponseExampleShape(o.responses),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Input`,role:`input`,shape:this.shapes.getRequestInputShape(o.requestBody),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Query`,role:`query`,shape:this.shapes.createParameterGroupShape(o.parameters,`query`,n),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Header`,role:`header`,shape:this.shapes.createParameterGroupShape(o.parameters,`header`,n),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Params`,role:`params`,shape:this.shapes.createParameterGroupShape(o.parameters,`path`,n),collisionSuffix:a})}}return t}buildSdkManifest(e,t,n={}){let r=this.naming.deriveSdkGroupNamesBySignature(e,n.namespaceStrategy??`smart`),i=new Map,a=this.buildSecuritySchemes(e),o=this.buildSecurityRequirements(e.security);for(let[a,o]of Object.entries(e.paths)){let e=this.naming.getStaticPathSegments(a).join(`/`),s=r.get(e)??`Resource`,c=this.naming.toCamelCase(this.naming.pluralize(s)),l=i.get(c)??{className:s,propertyName:c,operations:[]};for(let[e,r]of Object.entries(o)){let i=t.get(`${a}::${e}`)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};l.operations.push({path:a,method:e.toUpperCase(),methodName:this.naming.deriveSdkMethodName(e,a,r,n.methodStrategy??`smart`),summary:r.summary,description:r.description,operationId:r.operationId,requestBodyDescription:r.requestBody?.description,responseDescription:this.resolveSuccessResponseDescription(r.responses),responseType:this.shapes.resolveSdkResponseType(r.responses,i.response),inputType:i.input,queryType:i.query,headerType:i.header,paramsType:i.params,hasBody:!!r.requestBody,bodyRequired:r.requestBody?.required??!1,pathParams:this.naming.createSdkParameterManifest(r.parameters,`path`,a),queryParams:this.naming.createSdkParameterManifest(r.parameters,`query`,a),headerParams:this.naming.createSdkParameterManifest(r.parameters,`header`,a),security:this.buildSecurityRequirements(r.security)})}i.set(c,l)}return{groups:Array.from(i.values()).map(e=>({...e,operations:this.naming.ensureUniqueSdkMethodNames(e.operations)})).sort((e,t)=>e.propertyName.localeCompare(t.propertyName)),securitySchemes:a,security:o}}inferShapeFromExample(e,t){return this.shapes.inferShapeFromExample(e,t)}sanitizeTypeName(e){return this.naming.sanitizeTypeName(e)}registerNamedShape(e,t,n,r){return this.shapes.registerNamedShape(e,t,n,r)}namespaceTopLevelShape(e,t){return this.shapes.namespaceTopLevelShape(e,t)}registerObjectShape(e,t,n,r,i=!1){return this.shapes.registerObjectShape(e,t,n,r,i)}getOperationPriority(e){return Number(!!e.requestBody)*10}resolveSuccessResponseDescription(e){for(let t of[`200`,`201`,`202`,`204`]){let n=e[t]?.description?.trim();if(n)return n}for(let t of Object.values(e)){let e=t.description?.trim();if(e)return e}}buildSecuritySchemes(e){return Object.entries(e.components?.securitySchemes??{}).map(([e,t])=>this.createSecuritySchemeManifest(e,t)).filter(e=>e!==null).sort((e,t)=>e.name.localeCompare(t.name))}createSecuritySchemeManifest(e,t){let n=this.createSecurityHelperName(e);if(t.type===`apiKey`)return{name:e,helperName:n,description:t.description,type:`apiKey`,authType:`apiKey`,in:t.in,parameterName:t.name};if(t.type===`oauth2`)return{name:e,helperName:n,description:t.description,type:`oauth2`,authType:`oauth2`,scopes:this.collectSecurityScopes(t)};if(t.type===`openIdConnect`)return{name:e,helperName:n,description:t.description,type:`openIdConnect`,authType:`oauth2`,openIdConnectUrl:t.openIdConnectUrl};let r=t.scheme.toLowerCase();return{name:e,helperName:n,description:t.description,type:`http`,authType:r===`basic`?`basic`:`bearer`,scheme:t.scheme,bearerFormat:t.bearerFormat}}buildSecurityRequirements(e){if(!e||e.length===0)return;let t=e.map(e=>({schemes:Object.entries(e).map(([e,t])=>({name:e,scopes:[...t].sort()})).sort((e,t)=>e.name.localeCompare(t.name))})).filter(e=>e.schemes.length>0);return t.length>0?t:void 0}collectSecurityScopes(e){let t=new Set;for(let n of Object.values(e.flows??{}))for(let e of Object.keys(n.scopes??{}))t.add(e);return t.size>0?Array.from(t).sort():void 0}createSecurityHelperName(e){let t=this.naming.sanitizeTypeName(e);return t.endsWith(`Auth`)?`create${t}`:`create${t}Auth`}},X=class e{typeBuilder=new Y;moduleRenderer=new Xe;static generateModule=(t,n=`GeneratedOutput`,r={})=>new e().generate(t,n,r);generate(e,t=`GeneratedOutput`,n={}){return this.isOpenApiDocumentLike(e)?this.generateModule(e,t,n):this.generateGenericModule(e,t)}generateModule(e,t,n={}){let r=this.typeBuilder.createContext(),i=new Map;for(let t of this.typeBuilder.collectSemanticModels(e)){let e=`${t.path}::${t.method}`,n=this.typeBuilder.registerNamedShape(this.typeBuilder.namespaceTopLevelShape(t.shape,t.role),t.name,r,t.collisionSuffix),a=i.get(e)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};a[t.role]=n,i.set(e,a)}let a=r.declarations.map(e=>this.moduleRenderer.renderDeclaration(e)).join(`
139
+ `)}\n${i}}`}return`undefined`}normalizeOpenApiDocument(e){return this.normalizeObject(e,(e,t,n)=>{if(e===`example`&&n&&typeof n==`object`&&!Array.isArray(n)){let e=n;if(e.schema&&this.isPlainObject(e.schema))return this.normalizeExample(t,e.schema);if(this.isSchemaLike(e))return this.normalizeExample(t,e)}return t})}normalizeObject(e,t){if(Array.isArray(e))return e.map(e=>this.normalizeObject(e,t)).filter(e=>e!==void 0);if(!this.isPlainObject(e))return e;let n={};for(let[r,i]of Object.entries(e)){let a=t(r,i,e),o=this.normalizeObject(a,t);o!==void 0&&(n[r]=o)}return n}normalizeExample(e,t){if(e===void 0)return;let n=typeof t.type==`string`?t.type:void 0;if(n===`string`)return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):void 0;if(n===`number`||n===`integer`)return typeof e==`number`?e:typeof e==`string`&&e.trim()!==``&&Number.isFinite(Number(e))?Number(e):void 0;if(n===`boolean`)return typeof e==`boolean`?e:e===`true`?!0:e===`false`?!1:void 0;if(n===`array`){if(!Array.isArray(e))return;let n=this.isPlainObject(t.items)?t.items:void 0;return n?e.map(e=>this.normalizeExample(e,n)).filter(e=>e!==void 0):e}if(n===`object`){if(!this.isPlainObject(e))return;let n=this.isPlainObject(t.properties)?t.properties:{},r=Array.isArray(t.required)?t.required.filter(e=>typeof e==`string`):[],i={};for(let[t,r]of Object.entries(e)){let e=n[t],a=e?this.normalizeExample(r,e):r;a!==void 0&&(i[t]=a)}for(let e of r){if(e in i)continue;let t=n[e];if(!t)return;let r=t.default===void 0?t.example===void 0?void 0:this.normalizeExample(t.example,t):this.normalizeExample(t.default,t);if(r===void 0)return;i[e]=r}return i}return e}isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}isSchemaLike(e){return`type`in e||`properties`in e||`items`in e||`required`in e||`default`in e}indent(e){return` `.repeat(e)}escapeStringLiteral(e){return e.replace(/\\/g,String.raw`\\`).replace(/'/g,String.raw`\'`).replace(/\r/g,String.raw`\r`).replace(/\n/g,String.raw`\n`).replace(/\t/g,String.raw`\t`).replace(/\f/g,String.raw`\f`).replace(/\x08/g,String.raw`\b`).replace(/\u2028/g,String.raw`\u2028`).replace(/\u2029/g,String.raw`\u2029`)}isPathParam(e){return e.startsWith(`{`)&&e.endsWith(`}`)||/^:[A-Za-z0-9_]+$/.test(e)}stripPathParam(e){return e.replace(/^\{/,``).replace(/\}$/,``).replace(/^:/,``)}},Qe=class e{static contextualTailSegments=new Set([`history`,`status`,`detail`,`details`]);static irregularSingulars=new Map([[`analyses`,`analysis`],[`diagnoses`,`diagnosis`],[`parentheses`,`parenthesis`],[`statuses`,`status`],[`synopses`,`synopsis`],[`theses`,`thesis`]]);static invariantSingulars=new Set([`analysis`,`diagnosis`,`news`,`series`,`species`,`status`,`synopsis`,`thesis`]);static nestedContextSegments=new Set([`account`,`accounts`,`transaction`,`transactions`,`wallet`,`wallets`,`virtual-account`,`virtual-accounts`,`history`]);static roleSuffixes=[`Input`,`Query`,`Header`,`Params`];sanitizeTypeName(e){let t=e.replace(/[^A-Za-z0-9]+/g,` `).trim();if(!t)return`GeneratedEntity`;let n=t.split(/\s+/).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``);return/^[A-Za-z_$]/.test(n)?n:`Type${n}`}isPathParam(e){return e.startsWith(`{`)&&e.endsWith(`}`)||/^:[A-Za-z0-9_]+$/.test(e)}stripPathParam(e){return e.replace(/^\{/,``).replace(/\}$/,``).replace(/^:/,``)}singularize(t){let n=t.toLowerCase();return e.irregularSingulars.has(n)?e.irregularSingulars.get(n)??t:e.invariantSingulars.has(n)?t:/ies$/i.test(t)?`${t.slice(0,-3)}y`:/(sses|shes|ches|xes|zes)$/i.test(t)||/uses$/i.test(t)?t.slice(0,-2):t.endsWith(`s`)&&!t.endsWith(`ss`)&&t.length>1?t.slice(0,-1):t}pluralize(e){return/y$/i.test(e)?`${e.slice(0,-1)}ies`:/s$/i.test(e)?e:`${e}s`}toCamelCase(e){let t=this.sanitizeTypeName(e);return t.charAt(0).toLowerCase()+t.slice(1)}deriveOperationNaming(t){let n=this.getNormalizedPathSegments(t),r=n.filter(e=>!this.isPathParam(e)).map(e=>this.singularize(e)),i=n.filter(e=>this.isPathParam(e)).map(e=>this.singularize(this.stripPathParam(e))),a=r[r.length-1]??`resource`,o=r[r.length-2]??null,s=n.slice(0,-1).some(e=>this.isPathParam(e)),c=!!(o&&(e.contextualTailSegments.has(a.toLowerCase())||s&&e.nestedContextSegments.has(a.toLowerCase())));return{baseName:this.sanitizeTypeName(c?`${o} ${a}`:a),collisionSuffix:i.length>0?`By ${i.map(e=>this.sanitizeTypeName(e)).join(` And `)}`:o&&!c?this.sanitizeTypeName(o):``}}fallbackCollisionSuffix(e,t,n){let r=this.getNormalizedPathSegments(t),i=r.filter(e=>!this.isPathParam(e)),a=i[i.length-1]??``,o=r.some(e=>this.isPathParam(e));return e===`get`&&!o&&/s$/i.test(a)?`List`:e===`post`&&!o?`Create`:(e===`put`||e===`patch`)&&o?`Update`:e===`delete`?`Delete`:`${this.sanitizeTypeName(e)}${n}`}insertCollisionSuffix(t,n){if(!n)return t;for(let r of e.roleSuffixes)if(t.endsWith(r)&&t.length>r.length)return`${t.slice(0,-r.length)}${n}${r}`;return`${t}${n}`}deriveSdkGroupNamesBySignature(e,t){let n=new Map;for(let t of Object.keys(e.paths)){let e=this.getStaticPathSignature(t);n.has(e)||n.set(e,t)}let r=Array.from(n.entries()).map(([e,n])=>({signature:e,staticSegments:e.split(`/`).filter(Boolean),candidates:this.buildSdkGroupNameCandidates(n,t)})).sort((e,t)=>e.staticSegments.length-t.staticSegments.length||e.signature.localeCompare(t.signature)),i=new Map,a=new Set;for(let e of r){let t=e.candidates.find(e=>!a.has(e))??this.createUniqueSdkGroupName(e.candidates[e.candidates.length-1]??`Resource`,a);a.add(t),i.set(e.signature,t)}return i}getStaticPathSegments(e){return this.getNormalizedPathSegments(e).filter(e=>!this.isPathParam(e)).map(e=>this.singularize(e))}getStaticPathSignature(e){return this.getStaticPathSegments(e).join(`/`)}getNormalizedPathSegments(e){return e.split(`/`).map(e=>e.trim()).filter(Boolean).filter(e=>!/^v\d+$/i.test(e))}deriveSdkMethodName(e,t,n,r){if(r===`operation-id`&&n.operationId)return this.toCamelCase(this.sanitizeTypeName(n.operationId));let i=this.getNormalizedPathSegments(t).some(e=>this.isPathParam(e));return e===`get`?this.endsWithPluralStaticSegment(t)?`list`:i?`get`:`list`:e===`post`?`create`:e===`patch`||e===`put`?`update`:e===`delete`?`delete`:this.toCamelCase(this.sanitizeTypeName(e))}ensureUniqueSdkMethodNames(e){let t=new Map;return e.map(e=>{let n=t.get(e.methodName)??0;if(t.set(e.methodName,n+1),n===0)return e;let r=this.sanitizeTypeName(this.fallbackCollisionSuffix(e.method.toLowerCase(),e.path,`Operation`));return{...e,methodName:`${e.methodName}${r}`}})}createSdkParameterManifest(e,t,n){return[...(e??[]).filter(e=>e.in===t).sort((e,t)=>e.name.localeCompare(t.name)),...this.getInferredPathParameters(n,t,(e??[]).filter(e=>e.in===t))].sort((e,t)=>e.name.localeCompare(t.name)).map(e=>({name:e.name,accessor:this.toParameterAccessor(e.name),in:t,required:e.required??!1,description:e.description}))}getInferredPathParameters(e,t,n){if(t!==`path`||!e)return[];let r=new Set(n.map(e=>e.name));return this.getNormalizedPathSegments(e).filter(e=>this.isPathParam(e)).map(e=>this.stripPathParam(e)).filter(e=>!r.has(e)).map(e=>({name:e,in:`path`,required:!0,schema:{type:`string`}}))}buildSdkGroupNameCandidates(e,t){let n=this.getNormalizedPathSegments(e),r=n.filter(e=>!this.isPathParam(e)),i=r.map(e=>this.singularize(e)),a=this.deriveOperationNaming(e).baseName,o=this.getPreferredSdkGroupName(n,r,i),s=i.map((e,t,n)=>this.sanitizeTypeName(n.slice(t).join(` `))).reverse();return t===`scoped`?Array.from(new Set([o??``,this.sanitizeTypeName(i.join(` `)),...s,a].filter(Boolean))):Array.from(new Set([o??``,a,...s].filter(Boolean)))}getPreferredSdkGroupName(e,t,n){let r=t[t.length-1],i=n[n.length-1],a=n[n.length-2],o=e.some(e=>this.isPathParam(e)),s=e.slice(0,-1).some(e=>this.isPathParam(e));return!r||!i||!a?null:t.length===2&&!o?this.sanitizeTypeName(`${i} ${a}`):s?this.singularize(r)===r?this.sanitizeTypeName(`${i} ${a}`):this.sanitizeTypeName(`${a} ${i}`):null}createUniqueSdkGroupName(e,t){let n=2,r=e;for(;t.has(r);)r=`${e}${n}`,n+=1;return r}endsWithPluralStaticSegment(e){let t=this.getNormalizedPathSegments(e).at(-1);return!t||this.isPathParam(t)?!1:this.singularize(t)!==t}toParameterAccessor(e){let t=e.replace(/[^A-Za-z0-9]+/g,` `).trim();if(!t)return`value`;let[n,...r]=t.split(/\s+/).filter(Boolean),i=[n.toLowerCase(),...r.map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())].join(``);return/^[A-Za-z_$]/.test(i)?i:`value${i}`}},$e=class{constructor(e){this.naming=e}createContext(){return{declarations:[],declarationByName:new Map,nameBySignature:new Map,usedNames:new Set}}namespaceTopLevelShape(e,t){return e.kind===`object`?{...e,signature:`${t}:${e.signature}`}:e}inferShapeFromExample(e,t){if(e===null)return{kind:`primitive`,type:`null`};if(Array.isArray(e)){if(e.length===0)return{kind:`array`,item:{kind:`primitive`,type:`unknown`}};let n=this.dedupeShapes(e.map(e=>this.inferShapeFromExample(e,this.naming.singularize(t))));return{kind:`array`,item:n.length===1?n[0]:{kind:`union`,types:n}}}if(this.isRecord(e))return this.createObjectShape(Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>({key:e,optional:!1,shape:this.inferShapeFromExample(t,e)})));switch(typeof e){case`string`:return{kind:`primitive`,type:`string`};case`number`:return{kind:`primitive`,type:`number`};case`boolean`:return{kind:`primitive`,type:`boolean`};default:return{kind:`primitive`,type:`unknown`}}}registerNamedShape(e,t,n,r){if(e.kind===`object`)return this.registerObjectShape(e,t,n,r,!0);let i=this.createUniqueTypeName(t,n,r),a={kind:`shape-alias`,name:i,shape:this.prepareNestedShape(e,t,n)};return n.declarations.push(a),n.declarationByName.set(i,a),i}registerObjectShape(e,t,n,r,i=!1){let a=n.nameBySignature.get(e.signature),o=this.findCompatibleObjectDeclaration(e,t,n);if(a){if(i&&a!==t&&!n.declarationByName.has(t)){let e=this.createUniqueTypeName(t,n,r);if(e!==a){let t={kind:`interface-alias`,name:e,target:a};n.declarations.push(t),n.declarationByName.set(e,t)}}return a}if(o){if(this.isObjectShapeAssignableTo(e,o.rawShape))return n.nameBySignature.set(e.signature,o.name),o.name;let t=this.mergeObjectShapes(o.rawShape,e);return o.rawShape=t,o.properties=t.properties.map(e=>({...e,shape:this.prepareNestedShape(e.shape,e.key,n)})),n.nameBySignature.set(e.signature,o.name),n.nameBySignature.set(t.signature,o.name),o.name}let s=this.createUniqueTypeName(t,n,r),c={kind:`interface`,name:s,baseName:this.naming.sanitizeTypeName(t),rawShape:e,properties:[]};return n.nameBySignature.set(e.signature,s),n.declarations.push(c),n.declarationByName.set(s,c),c.properties=e.properties.map(e=>({...e,shape:this.prepareNestedShape(e.shape,e.key,n)})),s}resolveSdkResponseType(e,t){let n=Object.entries(e).filter(([e])=>/^2\d\d$/.test(e)).sort(([e],[t])=>e.localeCompare(t))[0]?.[1];if(!n)return t;let r=this.getPreferredMediaType(n.content);if(!r)return t;let i=this.resolveResponsePayloadSchema(r.schema,r.example).schema??r.schema;return i&&this.resolveSchemaType(i)===`array`?`${t}[]`:t}getSuccessResponseShape(e){let t=Object.entries(e).filter(([e])=>/^2\d\d$/.test(e)).sort(([e],[t])=>e.localeCompare(t))[0]?.[1];if(!t)return this.emptyObjectShape;let n=this.getPreferredMediaType(t.content);if(!n)return this.emptyObjectShape;let r=this.resolveResponsePayloadSchema(n.schema,n.example);return r.schema?this.resolveSchemaType(r.schema)===`array`?this.schemaToShape(r.schema.items,`Item`,this.extractExampleArrayItem(r.example)):this.schemaToShape(r.schema,`Response`,r.example):this.schemaToShape(n.schema,`Response`,n.example)}getRequestInputShape(e){if(!e)return this.emptyObjectShape;let t=this.getPreferredMediaType(e.content);return t?this.schemaToShape(t.schema,`Input`,t.example):this.emptyObjectShape}getResponseExampleShape(e){let t=Object.entries(e).sort(([e],[t])=>e.localeCompare(t)).flatMap(([,e])=>{let t=this.getPreferredMediaType(e.content);if(!t)return[];let n=t.example??t.schema?.example;return t.schema?[this.schemaToShape(t.schema,`ResponseExample`,n)]:n===void 0?[]:[this.inferShapeFromExample(n,`ResponseExample`)]}),n=this.dedupeShapes(t);return n.length===0?{kind:`primitive`,type:`unknown`}:n.length===1?n[0]:{kind:`union`,types:n}}createParameterGroupShape(e,t,n){let r=(e??[]).filter(e=>e.in===t).sort((e,t)=>e.name.localeCompare(t.name)),i=[...r,...this.naming.getInferredPathParameters(n,t,r)].sort((e,t)=>e.name.localeCompare(t.name));return i.length===0?this.emptyObjectShape:this.createObjectShape(i.map(e=>({key:e.name,optional:!(e.required??!1),shape:this.schemaToShape(e.schema,e.name,e.example)})))}get emptyObjectShape(){return this.createObjectShape([])}findCompatibleObjectDeclaration(e,t,n){let r=this.naming.sanitizeTypeName(t);return n.declarations.find(t=>t.kind!==`interface`||t.baseName!==r?!1:this.isObjectShapeAssignableTo(e,t.rawShape)||this.isObjectShapeAssignableTo(t.rawShape,e)||this.canMergeObjectShapes(t.rawShape,e))}canMergeObjectShapes(e,t){let n=new Set([...e.properties.map(e=>e.key),...t.properties.map(e=>e.key)]);for(let r of n){let n=e.properties.find(e=>e.key===r),i=t.properties.find(e=>e.key===r);if(!n||!i){if(!(n??i)?.optional)return!1;continue}if(!this.canMergeShapes(n.shape,i.shape))return!1}return!0}isObjectShapeAssignableTo(e,t){let n=new Map(t.properties.map(e=>[e.key,e]));for(let t of e.properties){let e=n.get(t.key);if(!e||t.optional&&!e.optional||!this.isShapeAssignableTo(t.shape,e.shape))return!1}return t.properties.every(t=>e.properties.some(e=>e.key===t.key)||t.optional)}isShapeAssignableTo(e,t){if(t.kind===`union`)return t.types.some(t=>this.isShapeAssignableTo(e,t));switch(e.kind){case`primitive`:return t.kind===`primitive`?e.type===t.type:!1;case`array`:return t.kind===`array`?this.isShapeAssignableTo(e.item,t.item):!1;case`union`:return e.types.every(e=>this.isShapeAssignableTo(e,t));case`object`:return t.kind===`object`?this.isObjectShapeAssignableTo(e,t):!1}}canMergeShapes(e,t){return e.kind===`union`?e.types.every(e=>this.canMergeShapes(e,t)):t.kind===`union`?t.types.every(t=>this.canMergeShapes(e,t)):e.kind===`primitive`&&t.kind===`primitive`?!0:e.kind===`array`&&t.kind===`array`?this.canMergeShapes(e.item,t.item):e.kind===`object`&&t.kind===`object`?this.canMergeObjectShapes(e,t):!1}mergeObjectShapes(e,t){let n=new Set([...e.properties.map(e=>e.key),...t.properties.map(e=>e.key)]);return this.createObjectShape(Array.from(n).map(n=>{let r=e.properties.find(e=>e.key===n),i=t.properties.find(e=>e.key===n);return r&&i?{key:n,optional:r.optional||i.optional,shape:this.mergeShapes(r.shape,i.shape)}:{key:n,optional:!0,shape:(r??i).shape}}))}mergeShapes(e,t){if(e.kind===`union`||t.kind===`union`||e.kind!==t.kind)return this.createUnionShape(e,t);switch(e.kind){case`primitive`:return t.kind===`primitive`&&e.type===t.type?e:this.createUnionShape(e,t);case`array`:return t.kind===`array`?{kind:`array`,item:this.mergeShapes(e.item,t.item)}:e;case`object`:return t.kind===`object`?this.mergeObjectShapes(e,t):e}}createUnionShape(...e){let t=e.flatMap(e=>e.kind===`union`?e.types:[e]),n=this.dedupeShapes(t);return n.length===1?n[0]:{kind:`union`,types:n}}prepareNestedShape(e,t,n){if(e.kind===`object`)return{kind:`primitive`,type:this.registerObjectShape(e,this.naming.sanitizeTypeName(this.naming.singularize(t)),n,this.naming.sanitizeTypeName(t))};if(e.kind===`array`)return{kind:`array`,item:this.prepareNestedShape(e.item,this.naming.singularize(t),n)};if(e.kind===`union`){let r=this.dedupeShapes(e.types.map((e,r)=>this.prepareNestedShape(e,this.getUnionMemberKeyHint(t,r,e),n)));return r.length===1?r[0]:{kind:`union`,types:r}}return e}getUnionMemberKeyHint(e,t,n){if(n.kind!==`object`&&n.kind!==`array`)return e;let r=this.naming.sanitizeTypeName(e);return r.endsWith(`ResponseExample`)?`${r}Variant${t+1}`:e}schemaToShape(e,t,n){if(!e)return this.inferShapeFromExample(n,t);let r=this.resolveSchemaType(e);if(r===`array`)return{kind:`array`,item:this.schemaToShape(e.items,this.naming.singularize(t),this.extractExampleArrayItem(e.example)??this.extractExampleArrayItem(n))};if(r===`object`){let r=this.isRecord(e.example)?e.example:this.isRecord(n)?n:void 0,i=Object.entries(e.properties??{}).sort(([e],[t])=>e.localeCompare(t)).map(([t,n])=>({key:t,optional:!(e.required??[]).includes(t),shape:this.schemaToShape(n,t,r?.[t])}));return i.length>0?this.createObjectShape(i):this.inferShapeFromExample(e.example??n,t)}return r===`integer`||r===`number`?{kind:`primitive`,type:`number`}:r===`string`?{kind:`primitive`,type:`string`}:r===`boolean`?{kind:`primitive`,type:`boolean`}:e.example===null||n===null?{kind:`primitive`,type:`null`}:e.example!==void 0||n!==void 0?this.inferShapeFromExample(e.example??n,t):{kind:`primitive`,type:`unknown`}}dedupeShapes(e){let t=new Set;return e.filter(e=>{let n=this.getShapeSignature(e);return t.has(n)?!1:(t.add(n),!0)})}createObjectShape(e){let t=e.map(e=>({...e})).sort((e,t)=>e.key.localeCompare(t.key));return{kind:`object`,signature:JSON.stringify(t.map(e=>({key:e.key,optional:e.optional,shape:this.getShapeSignature(e.shape)}))),properties:t}}getShapeSignature(e){switch(e.kind){case`primitive`:return`primitive:${e.type}`;case`array`:return`array:${this.getShapeSignature(e.item)}`;case`union`:return`union:${e.types.map(e=>this.getShapeSignature(e)).join(`|`)}`;case`object`:return`object:${e.signature}`}}getPreferredMediaType(e){if(e)return e[`application/json`]??e[`application/*+json`]??Object.values(e)[0]}resolveResponsePayloadSchema(e,t){for(let n of[[`data`],[`meta`,`data`]]){let r=this.getSchemaCandidateAtPath(e,t,n);if(r)return r}return{}}getSchemaCandidateAtPath(e,t,n){let r=this.getSchemaAtPath(e,n),i=this.getExampleAtPath(t,n);if(!(!r&&i===void 0))return r?{schema:r.example===void 0&&i!==void 0?{...r,example:i}:r,example:i??r.example}:{schema:{...this.inferSchemaTypeFromExample(i),example:i},example:i}}getSchemaAtPath(e,t){let n=e;for(let e of t){if(!n?.properties?.[e])return;n=n.properties[e]}return n}getExampleAtPath(e,t){let n=e;for(let e of t){if(!this.isRecord(n)||!(e in n))return;n=n[e]}return n}inferSchemaTypeFromExample(e){return Array.isArray(e)?{type:`array`,items:e.map(e=>this.inferSchemaTypeFromExample(e)).find(e=>this.hasSchemaDetails(e))??{}}:this.isRecord(e)?{type:`object`,properties:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,this.inferSchemaTypeFromExample(t)]))}:typeof e==`string`?{type:`string`}:typeof e==`number`?{type:`number`}:typeof e==`boolean`?{type:`boolean`}:{}}hasSchemaDetails(e){return!!(e?.type||e?.properties||e?.items||e?.example!==void 0)}resolveSchemaType(e){return e.type??(e.properties?`object`:void 0)}extractExampleArrayItem(e){return Array.isArray(e)?e[0]:void 0}createUniqueTypeName(e,t,n){let r=this.naming.sanitizeTypeName(e)||`GeneratedEntity`,i=this.naming.sanitizeTypeName(n),a=r,o=2;if(!t.usedNames.has(a)||(a=this.naming.insertCollisionSuffix(r,i),!t.usedNames.has(a)))return t.usedNames.add(a),a;for(;t.usedNames.has(a);)a=`${r}${o}`,o+=1;return t.usedNames.add(a),a}isRecord(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}},X=class{naming=new Qe;shapes=new $e(this.naming);createContext(){return this.shapes.createContext()}collectSemanticModels(e){let t=[];for(let[n,r]of Object.entries(e.paths)){let e=this.naming.deriveOperationNaming(n),i=e.baseName,a=Object.entries(r).sort(([,e],[,t])=>this.getOperationPriority(t)-this.getOperationPriority(e));for(let[r,o]of a){let a=e.collisionSuffix||this.naming.fallbackCollisionSuffix(r,n,i);t.push({path:n,method:r,name:i,role:`response`,shape:this.shapes.getSuccessResponseShape(o.responses),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}ResponseExample`,role:`responseExample`,shape:this.shapes.getResponseExampleShape(o.responses),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Input`,role:`input`,shape:this.shapes.getRequestInputShape(o.requestBody),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Query`,role:`query`,shape:this.shapes.createParameterGroupShape(o.parameters,`query`,n),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Header`,role:`header`,shape:this.shapes.createParameterGroupShape(o.parameters,`header`,n),collisionSuffix:a}),t.push({path:n,method:r,name:`${i}Params`,role:`params`,shape:this.shapes.createParameterGroupShape(o.parameters,`path`,n),collisionSuffix:a})}}return t}buildSdkManifest(e,t,n={}){let r=this.naming.deriveSdkGroupNamesBySignature(e,n.namespaceStrategy??`smart`),i=new Map,a=this.buildSecuritySchemes(e),o=this.buildSecurityRequirements(e.security);for(let[a,o]of Object.entries(e.paths)){let e=this.naming.getStaticPathSegments(a).join(`/`),s=r.get(e)??`Resource`,c=this.naming.toCamelCase(this.naming.pluralize(s)),l=i.get(c)??{className:s,propertyName:c,operations:[]};for(let[e,r]of Object.entries(o)){let i=t.get(`${a}::${e}`)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};l.operations.push({path:a,method:e.toUpperCase(),methodName:this.naming.deriveSdkMethodName(e,a,r,n.methodStrategy??`smart`),summary:r.summary,description:r.description,operationId:r.operationId,requestBodyDescription:r.requestBody?.description,responseDescription:this.resolveSuccessResponseDescription(r.responses),responseType:this.shapes.resolveSdkResponseType(r.responses,i.response),inputType:i.input,queryType:i.query,headerType:i.header,paramsType:i.params,hasBody:!!r.requestBody,bodyRequired:r.requestBody?.required??!1,pathParams:this.naming.createSdkParameterManifest(r.parameters,`path`,a),queryParams:this.naming.createSdkParameterManifest(r.parameters,`query`,a),headerParams:this.naming.createSdkParameterManifest(r.parameters,`header`,a),security:this.buildSecurityRequirements(r.security)})}i.set(c,l)}return{groups:Array.from(i.values()).map(e=>({...e,operations:this.naming.ensureUniqueSdkMethodNames(e.operations)})).sort((e,t)=>e.propertyName.localeCompare(t.propertyName)),securitySchemes:a,security:o}}inferShapeFromExample(e,t){return this.shapes.inferShapeFromExample(e,t)}sanitizeTypeName(e){return this.naming.sanitizeTypeName(e)}registerNamedShape(e,t,n,r){return this.shapes.registerNamedShape(e,t,n,r)}namespaceTopLevelShape(e,t){return this.shapes.namespaceTopLevelShape(e,t)}registerObjectShape(e,t,n,r,i=!1){return this.shapes.registerObjectShape(e,t,n,r,i)}getOperationPriority(e){return Number(!!e.requestBody)*10}resolveSuccessResponseDescription(e){for(let t of[`200`,`201`,`202`,`204`]){let n=e[t]?.description?.trim();if(n)return n}for(let t of Object.values(e)){let e=t.description?.trim();if(e)return e}}buildSecuritySchemes(e){return Object.entries(e.components?.securitySchemes??{}).map(([e,t])=>this.createSecuritySchemeManifest(e,t)).filter(e=>e!==null).sort((e,t)=>e.name.localeCompare(t.name))}createSecuritySchemeManifest(e,t){let n=this.createSecurityHelperName(e);if(t.type===`apiKey`)return{name:e,helperName:n,description:t.description,type:`apiKey`,authType:`apiKey`,in:t.in,parameterName:t.name};if(t.type===`oauth2`)return{name:e,helperName:n,description:t.description,type:`oauth2`,authType:`oauth2`,scopes:this.collectSecurityScopes(t)};if(t.type===`openIdConnect`)return{name:e,helperName:n,description:t.description,type:`openIdConnect`,authType:`oauth2`,openIdConnectUrl:t.openIdConnectUrl};let r=t.scheme.toLowerCase();return{name:e,helperName:n,description:t.description,type:`http`,authType:r===`basic`?`basic`:`bearer`,scheme:t.scheme,bearerFormat:t.bearerFormat}}buildSecurityRequirements(e){if(!e||e.length===0)return;let t=e.map(e=>({schemes:Object.entries(e).map(([e,t])=>({name:e,scopes:[...t].sort()})).sort((e,t)=>e.name.localeCompare(t.name))})).filter(e=>e.schemes.length>0);return t.length>0?t:void 0}collectSecurityScopes(e){let t=new Set;for(let n of Object.values(e.flows??{}))for(let e of Object.keys(n.scopes??{}))t.add(e);return t.size>0?Array.from(t).sort():void 0}createSecurityHelperName(e){let t=this.naming.sanitizeTypeName(e);return t.endsWith(`Auth`)?`create${t}`:`create${t}Auth`}},Z=class e{typeBuilder=new X;moduleRenderer=new Ze;static generateModule=(t,n=`GeneratedOutput`,r={})=>new e().generate(t,n,r);generate(e,t=`GeneratedOutput`,n={}){return this.isOpenApiDocumentLike(e)?this.generateModule(e,t,n):this.generateGenericModule(e,t)}generateModule(e,t,n={}){let r=this.typeBuilder.createContext(),i=new Map;for(let t of this.typeBuilder.collectSemanticModels(e)){let e=`${t.path}::${t.method}`,n=this.typeBuilder.registerNamedShape(this.typeBuilder.namespaceTopLevelShape(t.shape,t.role),t.name,r,t.collisionSuffix),a=i.get(e)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};a[t.role]=n,i.set(e,a)}let a=r.declarations.map(e=>this.moduleRenderer.renderDeclaration(e)).join(`
140
140
 
141
141
  `),o=this.moduleRenderer.toCamelCase(t),s=this.typeBuilder.buildSdkManifest(e,i,n);return[a,this.moduleRenderer.renderOpenApiDocumentDefinitions(t,e,i),this.moduleRenderer.renderSdkApiInterface(t,s),this.moduleRenderer.renderSdkManifest(o,s),`export const ${o}: ${t} = ${this.moduleRenderer.renderOpenApiDocumentValue(e)}`,this.moduleRenderer.renderSdkBundle(o,t),``,`export default ${o}`].filter(Boolean).join(`
142
142
 
@@ -144,13 +144,13 @@ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"a
144
144
 
145
145
  `),o,`export const ${s}: ${t} = ${this.moduleRenderer.renderValue(e)}`,``,`export default ${s}`].filter(Boolean).join(`
146
146
 
147
- `)}isOpenApiDocumentLike(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e;if(typeof t.info!=`object`||t.info===null||Array.isArray(t.info))return!1;let n=t.info;return t.openapi===`3.1.0`&&typeof n.title==`string`&&typeof n.version==`string`&&typeof t.paths==`object`&&t.paths!==null&&!Array.isArray(t.paths)}},Z=class{static serializeOutput=async(e,t,n=`ExtractedApiDocument`,r={})=>t===`js`?l.format(`export default ${JSON.stringify(e,null,2)}`,{parser:`babel`,semi:!1,singleQuote:!0}):t===`ts`?l.format(X.generateModule(e,n,r),{parser:`typescript`,semi:!1,singleQuote:!0}):JSON.stringify(e,null,t===`json`?0:2);static buildFilePath=(e,t,n,r)=>{let a={pretty:`txt`,json:`json`,js:`js`,ts:`ts`}[r],o=this.toSafeSourceName(t),s=n===`openapi`?`.openapi`:``;return i.join(e,`output`,`${o||`output`}${s}.${a}`)};static buildArtifactDirectory=(e,t,n)=>{let r=this.toSafeSourceName(t);return i.join(e,`output`,`${r||n}.${n}`)};static toSafeSourceName(e){return e.replace(/[^a-zA-Z0-9_-]+/g,`_`).replace(/^_+|_+$/g,``)}static getRootTypeName=e=>e===`openapi`?`ExtractedApiDocument`:`ExtractedPayload`},Q=class{typeBuilder=new Y;typeScriptGenerator=new X;generate(e,t={}){let n=t.outputMode??`both`,r=t.signatureStyle??`grouped`,i=t.rootTypeName??`ExtractedApiDocument`,a=t.schemaModule??this.typeScriptGenerator.generateModule(e,i,t),o=this.createOperationTypeRefs(e),s=this.typeBuilder.buildSdkManifest(e,o,t),c=s.groups.map(e=>e.className),l={"package.json":this.renderPackageJson(t),"README.md":this.renderReadme(s,t,n,r),"src/Schema.ts":a,"src/index.ts":this.renderIndexFile(c,n,i,s),"tsconfig.json":this.renderTsconfig(),"tsdown.config.ts":this.renderTsdownConfig(),"vitest.config.ts":this.renderVitestConfig(),"tests/exports.test.ts":this.renderExportsTest(i,n)};if(n!==`runtime`){l[`src/BaseApi.ts`]=this.renderBaseApi(),l[`src/ApiBinder.ts`]=this.renderApiBinder(s);for(let e of s.groups)l[`src/Apis/${e.className}.ts`]=this.renderApiClass(e,r);l[`src/Core.ts`]=this.renderCoreFile()}return l}createOperationTypeRefs(e){let t=this.typeBuilder.createContext(),n=new Map;for(let r of this.typeBuilder.collectSemanticModels(e)){let e=`${r.path}::${r.method}`,i=this.typeBuilder.registerNamedShape(this.typeBuilder.namespaceTopLevelShape(r.shape,r.role),r.name,t,r.collisionSuffix),a=n.get(e)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};a[r.role]=i,n.set(e,a)}return n}renderBaseApi(){return[`import { BaseApi as KitBaseApi } from '@oapiex/sdk-kit'`,``,`export class BaseApi extends KitBaseApi {}`].join(`
147
+ `)}isOpenApiDocumentLike(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e;if(typeof t.info!=`object`||t.info===null||Array.isArray(t.info))return!1;let n=t.info;return t.openapi===`3.1.0`&&typeof n.title==`string`&&typeof n.version==`string`&&typeof t.paths==`object`&&t.paths!==null&&!Array.isArray(t.paths)}},Q=class{static serializeOutput=async(e,t,n=`ExtractedApiDocument`,r={})=>t===`js`?l.format(`export default ${JSON.stringify(e,null,2)}`,{parser:`babel`,semi:!1,singleQuote:!0}):t===`ts`?l.format(Z.generateModule(e,n,r),{parser:`typescript`,semi:!1,singleQuote:!0}):JSON.stringify(e,null,t===`json`?0:2);static buildFilePath=(e,t,n,r)=>{let a={pretty:`txt`,json:`json`,js:`js`,ts:`ts`}[r],o=this.toSafeSourceName(t),s=n===`openapi`?`.openapi`:``;return i.join(e,`output`,`${o||`output`}${s}.${a}`)};static buildArtifactDirectory=(e,t,n)=>{let r=this.toSafeSourceName(t);return i.join(e,`output`,`${r||n}.${n}`)};static toSafeSourceName(e){return e.replace(/[^a-zA-Z0-9_-]+/g,`_`).replace(/^_+|_+$/g,``)}static getRootTypeName=e=>e===`openapi`?`ExtractedApiDocument`:`ExtractedPayload`},et=class e{static publishedPackageVersionRanges=new Map;typeBuilder=new X;typeScriptGenerator=new Z;generate(e,t={}){let n=t.outputMode??`both`,r=t.signatureStyle??`grouped`,i=t.rootTypeName??`ExtractedApiDocument`,a=t.schemaModule??this.typeScriptGenerator.generateModule(e,i,t),o=this.createOperationTypeRefs(e),s=this.typeBuilder.buildSdkManifest(e,o,t),c=s.groups.map(e=>e.className),l={"package.json":this.renderPackageJson(t),"README.md":this.renderReadme(s,t,n,r),"src/Schema.ts":a,"src/index.ts":this.renderIndexFile(c,n,i,s),"tsconfig.json":this.renderTsconfig(),"tsdown.config.ts":this.renderTsdownConfig(),"vitest.config.ts":this.renderVitestConfig(),"tests/exports.test.ts":this.renderExportsTest(i,n)};if(n!==`runtime`){l[`src/BaseApi.ts`]=this.renderBaseApi(),l[`src/ApiBinder.ts`]=this.renderApiBinder(s);for(let e of s.groups)l[`src/Apis/${e.className}.ts`]=this.renderApiClass(e,r);l[`src/Core.ts`]=this.renderCoreFile()}return l}createOperationTypeRefs(e){let t=this.typeBuilder.createContext(),n=new Map;for(let r of this.typeBuilder.collectSemanticModels(e)){let e=`${r.path}::${r.method}`,i=this.typeBuilder.registerNamedShape(this.typeBuilder.namespaceTopLevelShape(r.shape,r.role),r.name,t,r.collisionSuffix),a=n.get(e)??{response:`Record<string, never>`,responseExample:`unknown`,input:`Record<string, never>`,query:`Record<string, never>`,header:`Record<string, never>`,params:`Record<string, never>`};a[r.role]=i,n.set(e,a)}return n}renderBaseApi(){return[`import { BaseApi as KitBaseApi } from '@oapiex/sdk-kit'`,``,`export class BaseApi extends KitBaseApi {}`].join(`
148
148
  `)}renderApiBinder(e){return[`import { BaseApi } from './BaseApi'`,``,...e.groups.map(e=>`import { ${e.className} } from './Apis/${e.className}'`),``,`export class ApiBinder extends BaseApi {`,...e.groups.map(e=>` ${e.propertyName}!: ${e.className}`),``,` protected override boot () {`,...e.groups.map(e=>` this.${e.propertyName} = new ${e.className}(this.core)`),` }`,`}`].join(`
149
149
  `)}renderApiClass(e,t){let n=this.createTypeImportContext(e,t),r=[`import { BaseApi } from '../BaseApi'`,`import { Http } from '@oapiex/sdk-kit'`];return n.specifiers.length>0&&r.splice(1,0,`import type { ${n.specifiers.join(`, `)} } from '../Schema'`),[...r,``,`export class ${e.className} extends BaseApi {`,``,...e.operations.flatMap(e=>[this.renderApiMethod(e,t,n.aliasMap),``]).slice(0,-1),`}`].join(`
150
150
  `)}renderApiMethod(e,t,n){let r=t===`flat`?this.renderFlatSignature(e,n):this.renderGroupedSignature(e,n),i=t===`flat`?this.renderFlatObjectLiteral(e.paramsType,e.pathParams):e.pathParams.length>0?`params`:`{}`,a=t===`flat`?this.renderFlatObjectLiteral(e.queryType,e.queryParams):e.queryParams.length>0?`query`:`{}`,o=t===`flat`?this.renderFlatHeaders(e):e.headerParams.length>0?`((headers ? { ...headers } : {}) as Record<string, string | undefined>)`:`{}`,s=t===`flat`?e.hasBody?`body`:`{}`:e.hasBody?`body ?? {}`:`{}`,c=this.renderMethodDocComment(e,t,n);return[...c?[c]:[],` async ${e.methodName} ${r}: Promise<${this.rewriteTypeReference(e.responseType,n)}> {`,` await this.core.validateAccess()`,``,` const { data } = await Http.send<${this.rewriteTypeReference(e.responseType,n)}>(`,` this.core.builder.buildTargetUrl('${e.path}', ${i}, ${a}),`,` '${e.method}',`,` ${s},`,` ${o}`,` )`,``,` return data`,` }`].join(`
151
151
  `)}renderMethodDocComment(e,t,n){let r=[],i=e.summary?.trim(),a=e.description?.trim(),o=e.operationId?.trim(),s=this.rewriteTypeReference(e.responseType,n),c=e.responseDescription?.trim();i&&r.push(i),a&&a!==i&&(r.length>0&&r.push(``),r.push(...this.wrapDocText(a)));let l=[`HTTP ${e.method} ${e.path}`,...o?[`Operation ID: ${o}`]:[]];l.length>0&&(r.length>0&&r.push(``),r.push(...l));let u=t===`flat`?this.renderFlatParameterDocs(e,n):this.renderGroupedParameterDocs(e,n);return u.length>0&&(r.length>0&&r.push(``),r.push(...u)),r.push(`@returns ${c?`${c} `:``}${s}`.trim()),[` /**`,...r.map(e=>e?` * ${e}`:` *`),` */`].join(`
152
152
  `)}renderGroupedParameterDocs(e,t){let n=[];return e.pathParams.length>0&&n.push(this.renderParamDoc(`params`,e.paramsType,t,this.describeParameterGroup(e.pathParams,`path parameters`))),e.queryParams.length>0&&n.push(this.renderParamDoc(`query`,e.queryType,t,this.describeParameterGroup(e.queryParams,`query parameters`))),e.hasBody&&n.push(this.renderParamDoc(`body`,e.inputType,t,e.requestBodyDescription?.trim()||`Request body`)),e.headerParams.length>0&&n.push(this.renderParamDoc(`headers`,e.headerType,t,this.describeParameterGroup(e.headerParams,`request headers`))),n}renderFlatParameterDocs(e,t){return[...e.pathParams.map(n=>this.renderParamDoc(n.accessor,`${e.paramsType}[${JSON.stringify(n.name)}]`,t,n.description?.trim()||`Path parameter ${n.name}`)),...e.queryParams.map(n=>this.renderParamDoc(n.accessor,`${e.queryType}[${JSON.stringify(n.name)}]`,t,n.description?.trim()||`Query parameter ${n.name}`)),...e.hasBody?[this.renderParamDoc(`body`,e.inputType,t,e.requestBodyDescription?.trim()||`Request body`)]:[],...e.headerParams.map(n=>this.renderParamDoc(n.accessor,`${e.headerType}[${JSON.stringify(n.name)}]`,t,n.description?.trim()||`Header ${n.name}`))]}renderParamDoc(e,t,n,r){return`@param ${e} ${r} Type: ${this.rewriteTypeReference(t,n)}`}describeParameterGroup(e,t){let n=e.map(e=>e.description?.trim()?`${e.name}: ${e.description.trim()}`:e.name).filter(Boolean);return n.length===0?t:n.join(`; `)}wrapDocText(e){return e.split(/\r?\n/).map(e=>e.trim()).filter(Boolean)}renderGroupedSignature(e,t){let n=[];return e.pathParams.length>0&&n.push(`params: ${this.rewriteTypeReference(e.paramsType,t)}`),e.queryParams.length>0&&n.push(`query: ${this.rewriteTypeReference(e.queryType,t)}`),e.hasBody&&n.push(`body${e.bodyRequired?``:`?`}: ${this.rewriteTypeReference(e.inputType,t)}`),e.headerParams.length>0&&n.push(`headers?: ${this.rewriteTypeReference(e.headerType,t)}`),`(${n.join(`, `)})`}renderFlatSignature(e,t){return`(${[...e.pathParams.map(n=>`${n.accessor}${n.required?``:`?`}: ${this.rewriteTypeReference(e.paramsType,t)}[${JSON.stringify(n.name)}]`),...e.queryParams.map(n=>`${n.accessor}${n.required?``:`?`}: ${this.rewriteTypeReference(e.queryType,t)}[${JSON.stringify(n.name)}]`),...e.hasBody?[`body${e.bodyRequired?``:`?`}: ${this.rewriteTypeReference(e.inputType,t)}`]:[],...e.headerParams.map(n=>`${n.accessor}${n.required?``:`?`}: ${this.rewriteTypeReference(e.headerType,t)}[${JSON.stringify(n.name)}]`)].join(`, `)})`}createTypeImportContext(e,t){let n=new Set;for(let t of e.operations)n.add(t.responseType),t.hasBody&&n.add(t.inputType),t.queryParams.length>0&&n.add(t.queryType),t.headerParams.length>0&&n.add(t.headerType),t.pathParams.length>0&&n.add(t.paramsType);let r=Array.from(new Set(Array.from(n).flatMap(e=>this.collectTypeIdentifiers(e)))).sort(),i=new Map;return{specifiers:r.map(t=>{if(t===e.className){let e=`${t}Model`;return i.set(t,e),`${t} as ${e}`}return t}),aliasMap:i}}rewriteTypeReference(e,t){let n=e;for(let[e,r]of t.entries())n=n.replace(RegExp(`\\b${e}\\b`,`g`),r);return n}renderFlatObjectLiteral(e,t){return t.length===0?`{}`:`{ ${t.map(e=>`${JSON.stringify(e.name)}: ${e.accessor}`).join(`, `)} }`}renderFlatHeaders(e){return e.headerParams.length===0?`{}`:`({ ${e.headerParams.map(e=>`${JSON.stringify(e.name)}: ${e.accessor}`).join(`, `)} } as Record<string, string | undefined>)`}renderCoreFile(){return[`import { Core as KitCore } from '@oapiex/sdk-kit'`,``,`import { ApiBinder } from './ApiBinder'`,``,`export class Core extends KitCore {`,` static override apiClass = ApiBinder`,``,` declare api: ApiBinder`,`}`].join(`
153
- `)}renderPackageJson(e){return JSON.stringify({name:e.packageName??`generated-sdk`,type:`module`,version:e.packageVersion??`0.1.0`,private:!0,description:e.packageDescription??`Generated SDK scaffold emitted by oapiex.`,main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,exports:{".":{import:`./dist/index.js`,require:`./dist/index.cjs`},"./package.json":`./package.json`},files:[`dist`],scripts:{test:`pnpm vitest --run`,"test:watch":`pnpm vitest`,build:`tsdown`},dependencies:{[e.sdkKitPackageName??`@oapiex/sdk-kit`]:`^0.1.1`},devDependencies:{"@types/node":`^20.14.5`,tsdown:`^0.20.1`,typescript:`^5.4.5`,vitest:`^3.2.4`}},null,2)}renderReadme(e,t,n,r){let i=t.packageName??`generated-sdk`,a=`# ${i}`,o=this.renderReadmeDescription(n),s=this.renderReadmeUsage(e,i,n,r),c=this.renderReadmeExports(n,e);return[a,``,o,``,`## Install`,``,"```bash",`pnpm add ${i}`,"```",``,`## Quick Start`,``,"```ts",s,"```",``,`## Main Exports`,``,...c.map(e=>`- ${e}`),``,`## Commands`,``,"```bash",`pnpm test`,`pnpm build`,"```"].join(`
153
+ `)}renderPackageJson(e){let t=e.sdkKitPackageName??`@oapiex/sdk-kit`;return JSON.stringify({name:e.packageName??`generated-sdk`,type:`module`,version:e.packageVersion??`0.1.0`,private:!0,description:e.packageDescription??`Generated SDK scaffold emitted by oapiex.`,main:`./dist/index.cjs`,module:`./dist/index.js`,types:`./dist/index.d.ts`,exports:{".":{import:`./dist/index.js`,require:`./dist/index.cjs`},"./package.json":`./package.json`},files:[`dist`],scripts:{test:`pnpm vitest --run`,"test:watch":`pnpm vitest`,build:`tsdown`},dependencies:{"@h3ravel/shared":this.resolvePublishedPackageVersionRange(`@h3ravel/shared`),[t]:this.resolvePublishedPackageVersionRange(t)},devDependencies:{"@types/node":`^20.14.5`,tsdown:`^0.20.1`,typescript:`^5.4.5`,vitest:`^3.2.4`}},null,2)}resolvePublishedPackageVersionRange(t){let n=e.publishedPackageVersionRanges.get(t);if(n)return n;try{let n=JSON.parse(u(`npm`,[`view`,t,`version`,`--json`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}));if(typeof n==`string`&&n.trim().length>0){let r=`^${n.trim()}`;return e.publishedPackageVersionRanges.set(t,r),r}}catch{e.publishedPackageVersionRanges.set(t,`latest`)}return`latest`}renderReadme(e,t,n,r){let i=t.packageName??`generated-sdk`,a=`# ${i}`,o=this.renderReadmeDescription(n),s=this.renderReadmeUsage(e,i,n,r),c=this.renderReadmeExports(n,e);return[a,``,o,``,`## Install`,``,"```bash",`pnpm add ${i}`,"```",``,`## Quick Start`,``,"```ts",s,"```",``,`## Main Exports`,``,...c.map(e=>`- ${e}`),``,`## Commands`,``,"```bash",`pnpm test`,`pnpm build`,"```"].join(`
154
154
  `)}renderReadmeDescription(e){return e===`runtime`?`Generated runtime-first TypeScript SDK emitted by oapiex.`:e===`classes`?`Generated class-based TypeScript SDK emitted by oapiex.`:`Generated TypeScript SDK emitted by oapiex with both class-based and runtime-first entrypoints.`}renderReadmeUsage(e,t,n,r){let i=this.pickExampleOperation(e),a=this.renderReadmeClientSnippet(t,`runtime`,r,i);if(n===`runtime`)return a;let o=this.renderReadmeClientSnippet(t,`classes`,r,i);if(n===`classes`)return o;let s=i?this.collectReadmeTypeImports(i.operation):[],c=[`Core`,`createClient`,...i?this.collectReadmeAuthHelperImports(i):[]];return[s.length>0?`import { ${c.join(`, `)}, type ${s.join(`, type `)} } from '${t}'`:`import { ${c.join(`, `)} } from '${t}'`,``,...this.renderReadmeClientBody(`sdk`,`classes`,r,i),``,`// --- OR ---`,``,...this.renderReadmeClientBody(`runtimeSdk`,`runtime`,r,i)].join(`
155
155
  `)}renderReadmeClientSnippet(e,t,n,r){let i=t===`runtime`?[`createClient`]:[`Core`],a=r?this.collectReadmeTypeImports(r.operation):[],o=r?this.collectReadmeAuthHelperImports(r):[],s=[...i,...o],c=a.length>0?`import { ${s.join(`, `)}, type ${a.join(`, type `)} } from '${e}'`:`import { ${s.join(`, `)} } from '${e}'`,l=t===`runtime`?`runtimeSdk`:`sdk`;return[c,``,...this.renderReadmeClientBody(l,t,n,r)].join(`
156
156
  `)}renderReadmeClientBody(e,t,n,r){let i=t===`runtime`?`const ${e} = createClient({`:`const ${e} = new Core({`,a=r?this.renderReadmeOperationCall(e,r,t===`runtime`?`grouped`:n):[];return[i,` clientId: process.env.CLIENT_ID!,`,` clientSecret: process.env.CLIENT_SECRET!,`,` environment: 'sandbox',`,...r?this.renderReadmeAuthLines(r.operation.security??r.groupSecurity??r.globalSecurity):[],`})`,...a.length>0?[``,...a]:[]]}renderReadmeExports(e,t){let n=t.securitySchemes.length>0?[`generated auth helpers derived from OpenAPI security schemes`]:[];return e===`runtime`?["`createClient()` for a typed runtime SDK instance",...n,"`Schema` exports for request, response, params, query, and header types"]:e===`classes`?["`Core` as the class-based SDK entrypoint",...n,"generated API classes plus `Schema` type exports"]:["`Core` for class-based usage","`createClient()` for runtime-first usage",...n,"`Schema` exports for generated request, response, params, query, and header types"]}pickExampleOperation(e){let t=e.groups[0],n=t?.operations[0];return!t||!n?null:{group:t,operation:n,groupSecurity:void 0,globalSecurity:e.security}}renderReadmeAuthLines(e){if(!e||e.length===0)return[];let t=e[0];if(!t||t.schemes.length===0)return[];let n=t.schemes.length===1?this.renderReadmeAuthFactoryCall(t.schemes[0].name):`[
@@ -160,7 +160,7 @@ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"a
160
160
  `)}renderVitestConfig(){return[`import { defineConfig } from 'vitest/config'`,``,`export default defineConfig({`,` test: {`,` name: 'generated-sdk',`,` environment: 'node',`,` include: ['tests/*.{test,spec}.?(c|m)[jt]s?(x)'],`,` },`,`})`].join(`
161
161
  `)}renderExportsTest(e,t){let n=`${e.charAt(0).toLowerCase()}${e.slice(1)}`,r=[` expect(sdk.createClient).toBeTypeOf('function')`,` expect(sdk.createSdk).toBeTypeOf('function')`,` expect(sdk.${n}Sdk).toBeDefined()`,` expect(sdk.${n}Manifest).toBeDefined()`];return t!==`runtime`&&(r.unshift(` expect(sdk.Core).toBeTypeOf('function')`),r.unshift(` expect(sdk.BaseApi).toBeTypeOf('function')`)),[`import { describe, expect, it } from 'vitest'`,``,`import * as sdk from '../src/index'`,``,`describe('generated sdk exports', () => {`,` it('exposes the generated schema and runtime helpers', () => {`,...r,` })`,`})`].join(`
162
162
  `)}renderIndexFile(e,t,n,r){let i=`${n.charAt(0).toLowerCase()}${n.slice(1)}`,a=[`import type { ${n}Api } from './Schema'`,`import { ${i}Manifest, ${i}Sdk } from './Schema'`,`import { createSdk as createBoundSdk } from '@oapiex/sdk-kit'`,`import type { AuthConfig, BaseApi as KitBaseApi, Core as KitCore, InitOptions } from '@oapiex/sdk-kit'`,``,`export * from './Schema'`];if(t!==`runtime`&&(a.push(`export { ApiBinder } from './ApiBinder'`),a.push(`export { BaseApi } from './BaseApi'`),a.push(...e.map(e=>`export { ${e} as ${e}Api } from './Apis/${e}'`)),a.push(`export { Core } from './Core'`)),a.push(``),a.push(`export const securitySchemes = ${i}Manifest.securitySchemes`),a.push(`export const security = ${i}Manifest.security`),r.securitySchemes.length>0){a.push(``);for(let e of r.securitySchemes)a.push(...this.renderSecurityHelper(e)),a.push(``)}return a.push(`export const createClient = (`),a.push(` options: InitOptions`),a.push(`): KitCore & { api: KitBaseApi & ${n}Api } =>`),a.push(` createBoundSdk(${i}Sdk, options) as KitCore & { api: KitBaseApi & ${n}Api }`),a.push(``),a.push(`export {`),a.push(` BadRequestException,`),a.push(` Builder,`),a.push(` ForbiddenRequestException,`),a.push(` Http,`),a.push(` HttpException,`),a.push(` UnauthorizedRequestException,`),a.push(` WebhookValidator,`),a.push(` createSdk,`),a.push(`} from '@oapiex/sdk-kit'`),a.push(``),a.push(`export type {`),a.push(` AuthConfig,`),a.push(` InitOptions,`),a.push(` UnifiedResponse,`),a.push(` XGenericObject,`),a.push(`} from '@oapiex/sdk-kit'`),a.join(`
163
- `)}collectTypeIdentifiers(e){return Array.from(new Set((e.match(/\b[A-Z][A-Za-z0-9_]*/g)??[]).filter(e=>![`Record`,`Promise`].includes(e))))}renderSecurityHelper(e){return e.authType===`basic`?[`export const ${e.helperName} = (username: string, password: string): AuthConfig => ({`,` type: 'basic',`,` username,`,` password,`,`})`]:e.authType===`apiKey`?[`export const ${e.helperName} = (value: string): AuthConfig => ({`,` type: 'apiKey',`,` name: ${JSON.stringify(e.parameterName??e.name)},`,` value,`,` in: ${JSON.stringify(e.in??`header`)},`,`})`]:e.authType===`oauth2`?[`export const ${e.helperName} = (accessToken: string, tokenType = 'Bearer'): AuthConfig => ({`,` type: 'oauth2',`,` accessToken,`,` tokenType,`,`})`]:[`export const ${e.helperName} = (token: string): AuthConfig => ({`,` type: 'bearer',`,` token,`,...e.scheme&&e.scheme.toLowerCase()!==`bearer`?[` prefix: ${JSON.stringify(this.normalizeHttpAuthPrefix(e.scheme))},`]:[],`})`]}createSecurityHelperName(e){let t=this.typeBuilder.sanitizeTypeName(e);return t.endsWith(`Auth`)?`create${t}`:`create${t}Auth`}normalizeHttpAuthPrefix(e){return e.charAt(0).toUpperCase()+e.slice(1)}toConstantCase(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1_$2`).replace(/[^A-Za-z0-9]+/g,`_`).replace(/^_+|_+$/g,``).toUpperCase()||`AUTH`}};const $=new class{createDocument(e,t=`Extracted API`,n=`0.0.0`){let r={};for(let t of e){let e=this.transformOperation(t);!e||this.shouldSkipNormalizedOperation(e)||(r[e.path]??={},r[e.path][e.method]=e.operation)}return{openapi:`3.1.0`,info:{title:t,version:n},paths:r}}transformOperation(e){if(!e.method||!e.url)return null;let t=new URL(e.url);if(this.shouldSkipPlaceholderOperation(t,e))return null;let n=e.method.toLowerCase(),r=this.decodeOpenApiPathname(t.pathname);return{path:r,method:n,operation:{summary:e.sidebarLinks.find(e=>e.active)?.label,description:e.description??void 0,operationId:this.buildOperationId(n,r),parameters:this.createParameters(e.requestParams),requestBody:this.createRequestBody(e.requestParams,e.requestExampleNormalized?.body,this.hasExtractedBodyParams(e.requestParams)?null:this.resolveFallbackRequestBodyExample(e)),responses:this.createResponses(e.responseSchemas,e.responseBodies)}}}shouldSkipNormalizedOperation(e){return e.path===`/`&&e.method===`get`&&e.operation.operationId===`get`&&Object.keys(e.operation.responses).length===0}shouldSkipPlaceholderOperation(e,t){return e.hostname!==`example.com`||e.pathname!==`/`?!1:t.requestParams.length===0&&t.responseSchemas.length===0&&t.responseBodies.length===0&&t.requestExampleNormalized?.url===`https://example.com/`}decodeOpenApiPathname(e){return e.split(`/`).map(e=>{if(!e)return e;try{return decodeURIComponent(e)}catch{return e}}).join(`/`)}hasExtractedBodyParams(e){return e.some(e=>e.in===`body`||e.in===null)}createParameters(e){let t=e.filter(e=>this.isOpenApiParameterLocation(e.in)).map(e=>this.createParameter(e));return t.length>0?t:void 0}createRequestBody(e,t,n){let r=e.filter(e=>e.in===`body`||e.in===null);if(r.length===0&&t==null)return;let i=this.buildRequestBodySchema(r,t,n);return{required:r.length>0?r.some(e=>e.required):!1,content:{"application/json":{schema:i,...t==null?{}:{example:t}}}}}buildRequestBodySchema(e,t,n){let r=this.mergeOpenApiSchemas(this.createExampleSchema(t),this.createExampleSchema(n))??{type:`object`};t==null?n!=null&&(r.example=n):r.example=t;for(let t of e)this.insertRequestBodyParam(r,t);return r}inferSchemaFromExample(e){if(Array.isArray(e))return{type:`array`,items:this.inferSchemaFromExample(e[0])??{},example:e};if(P(e))return{type:`object`,properties:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,this.inferSchemaFromExample(t)??{}])),example:e};if(typeof e==`string`)return{type:`string`,example:e};if(typeof e==`number`)return{type:Number.isInteger(e)?`integer`:`number`,example:e};if(typeof e==`boolean`)return{type:`boolean`,example:e};if(e===null)return{}}insertRequestBodyParam(e,t){let n=t.path.length>0?t.path:[t.name],r=e;for(let[e,i]of n.slice(0,-1).entries())r.properties??={},r.properties[i]??={type:`object`},t.required&&(r.required=Array.from(new Set([...r.required??[],i]))),r=r.properties[i],r.type??=`object`,e===n.length-2&&t.required&&(r.required??=[]);let i=n[n.length-1]??t.name;r.properties??={},r.properties[i]=this.createParameterSchema(t),t.required&&(r.required=Array.from(new Set([...r.required??[],i])))}createParameter(e){return{name:e.name,in:e.in,required:e.in===`path`?!0:e.required,description:e.description??void 0,schema:this.createParameterSchema(e),example:e.defaultValue??void 0}}createParameterSchema(e){return{type:e.type??void 0,description:e.description??void 0,default:e.defaultValue??void 0}}createResponses(e,t){let n={};for(let r of e){if(!r.statusCode)continue;let e=t.filter(e=>e.statusCode===r.statusCode),i=this.createResponseContent(e);n[r.statusCode]={description:r.description??r.statusCode,...i?{content:i}:{}}}for(let e of t){if(!e.statusCode||n[e.statusCode])continue;let t=this.createResponseContent([e]);n[e.statusCode]={description:e.label??e.statusCode,...t?{content:t}:{}}}return n}createResponseContent(e){if(e.length===0)return;let t={};for(let n of e){let e=n.contentType??(n.format===`json`?`application/json`:`text/plain`),r=this.normalizeResponseExampleValue(n.body,n.format);t[e]={schema:this.inferSchemaFromBody(r,n.format),example:r}}return t}inferSchemaFromBody(e,t){if(t===`json`)return this.inferSchemaFromExample(e);if(t===`text`)return{type:`string`,example:e}}normalizeResponseExampleValue(e,t){return t!==`json`||typeof e!=`string`?e:N.parsePossiblyTruncated(e)??W(e)??e}resolveFallbackRequestBodyExample(e){return e.responseBodies.find(e=>e.format===`json`)?.body??(typeof e.responseExample==`object`&&e.responseExample!==null?e.responseExample:typeof e.responseExampleRaw==`string`?N.parsePossiblyTruncated(e.responseExampleRaw):typeof e.responseExample==`string`?N.parsePossiblyTruncated(e.responseExample):null)}createExampleSchema(e){return e==null?null:this.inferSchemaFromExample(e)??null}mergeOpenApiSchemas(e,t){if(!e)return t;if(!t)return e;let n={...t,...e,...e.type||t.type?{type:e.type??t.type}:{},...e.description||t.description?{description:e.description??t.description}:{},...e.default!==void 0||t.default!==void 0?{default:e.default??t.default}:{},...e.example!==void 0||t.example!==void 0?{example:e.example??t.example}:{}};if(e.properties||t.properties){let r=new Set([...Object.keys(e.properties??{}),...Object.keys(t.properties??{})]);n.properties=Object.fromEntries(Array.from(r).map(n=>[n,this.mergeOpenApiSchemas(e.properties?.[n]??null,t.properties?.[n]??null)??{}]))}return(e.items||t.items)&&(n.items=this.mergeOpenApiSchemas(e.items??null,t.items??null)??{}),(e.required||t.required)&&(n.required=Array.from(new Set([...t.required??[],...e.required??[]]))),n}buildOperationId(e,t){return`${e}${t.replace(/\{([^}]+)\}/g,`$1`).split(`/`).filter(Boolean).map(e=>e.replace(/[^a-zA-Z0-9]+/g,` `)).map(e=>e.trim()).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).replace(/\s+(.)/g,(e,t)=>t.toUpperCase())).join(``)}`}isOpenApiParameterLocation(e){return e===`query`||e===`header`||e===`path`||e===`cookie`}};var $e=class extends s{signature=`generate
163
+ `)}collectTypeIdentifiers(e){return Array.from(new Set((e.match(/\b[A-Z][A-Za-z0-9_]*/g)??[]).filter(e=>![`Record`,`Promise`].includes(e))))}renderSecurityHelper(e){return e.authType===`basic`?[`export const ${e.helperName} = (username: string, password: string): AuthConfig => ({`,` type: 'basic',`,` username,`,` password,`,`})`]:e.authType===`apiKey`?[`export const ${e.helperName} = (value: string): AuthConfig => ({`,` type: 'apiKey',`,` name: ${JSON.stringify(e.parameterName??e.name)},`,` value,`,` in: ${JSON.stringify(e.in??`header`)},`,`})`]:e.authType===`oauth2`?[`export const ${e.helperName} = (accessToken: string, tokenType = 'Bearer'): AuthConfig => ({`,` type: 'oauth2',`,` accessToken,`,` tokenType,`,`})`]:[`export const ${e.helperName} = (token: string): AuthConfig => ({`,` type: 'bearer',`,` token,`,...e.scheme&&e.scheme.toLowerCase()!==`bearer`?[` prefix: ${JSON.stringify(this.normalizeHttpAuthPrefix(e.scheme))},`]:[],`})`]}createSecurityHelperName(e){let t=this.typeBuilder.sanitizeTypeName(e);return t.endsWith(`Auth`)?`create${t}`:`create${t}Auth`}normalizeHttpAuthPrefix(e){return e.charAt(0).toUpperCase()+e.slice(1)}toConstantCase(e){return e.replace(/([a-z0-9])([A-Z])/g,`$1_$2`).replace(/[^A-Za-z0-9]+/g,`_`).replace(/^_+|_+$/g,``).toUpperCase()||`AUTH`}};const $=new class{createDocument(e,t=`Extracted API`,n=`0.0.0`){let r={};for(let t of e){let e=this.transformOperation(t);!e||this.shouldSkipNormalizedOperation(e)||(r[e.path]??={},r[e.path][e.method]=e.operation)}return{openapi:`3.1.0`,info:{title:t,version:n},paths:r}}transformOperation(e){if(!e.method||!e.url)return null;let t=new URL(e.url);if(this.shouldSkipPlaceholderOperation(t,e))return null;let n=e.method.toLowerCase(),r=this.decodeOpenApiPathname(t.pathname);return{path:r,method:n,operation:{summary:e.sidebarLinks.find(e=>e.active)?.label,description:e.description??void 0,operationId:this.buildOperationId(n,r),parameters:this.createParameters(e.requestParams),requestBody:this.createRequestBody(e.requestParams,e.requestExampleNormalized?.body,this.hasExtractedBodyParams(e.requestParams)?null:this.resolveFallbackRequestBodyExample(e)),responses:this.createResponses(e.responseSchemas,e.responseBodies)}}}shouldSkipNormalizedOperation(e){return e.path===`/`&&e.method===`get`&&e.operation.operationId===`get`&&Object.keys(e.operation.responses).length===0}shouldSkipPlaceholderOperation(e,t){return e.hostname!==`example.com`||e.pathname!==`/`?!1:t.requestParams.length===0&&t.responseSchemas.length===0&&t.responseBodies.length===0&&t.requestExampleNormalized?.url===`https://example.com/`}decodeOpenApiPathname(e){return e.split(`/`).map(e=>{if(!e)return e;try{return decodeURIComponent(e)}catch{return e}}).join(`/`)}hasExtractedBodyParams(e){return e.some(e=>e.in===`body`||e.in===null)}createParameters(e){let t=e.filter(e=>this.isOpenApiParameterLocation(e.in)).map(e=>this.createParameter(e));return t.length>0?t:void 0}createRequestBody(e,t,n){let r=e.filter(e=>e.in===`body`||e.in===null);if(r.length===0&&t==null)return;let i=this.buildRequestBodySchema(r,t,n);return{required:r.length>0?r.some(e=>e.required):!1,content:{"application/json":{schema:i,...t==null?{}:{example:t}}}}}buildRequestBodySchema(e,t,n){let r=this.mergeOpenApiSchemas(this.createExampleSchema(t),this.createExampleSchema(n))??{type:`object`};t==null?n!=null&&(r.example=n):r.example=t;for(let t of e)this.insertRequestBodyParam(r,t);return r}inferSchemaFromExample(e){if(Array.isArray(e))return{type:`array`,items:this.inferSchemaFromExample(e[0])??{},example:e};if(I(e))return{type:`object`,properties:Object.fromEntries(Object.entries(e).map(([e,t])=>[e,this.inferSchemaFromExample(t)??{}])),example:e};if(typeof e==`string`)return{type:`string`,example:e};if(typeof e==`number`)return{type:Number.isInteger(e)?`integer`:`number`,example:e};if(typeof e==`boolean`)return{type:`boolean`,example:e};if(e===null)return{}}insertRequestBodyParam(e,t){let n=t.path.length>0?t.path:[t.name],r=e;for(let[e,i]of n.slice(0,-1).entries())r.properties??={},r.properties[i]??={type:`object`},t.required&&(r.required=Array.from(new Set([...r.required??[],i]))),r=r.properties[i],r.type??=`object`,e===n.length-2&&t.required&&(r.required??=[]);let i=n[n.length-1]??t.name;r.properties??={},r.properties[i]=this.createParameterSchema(t),t.required&&(r.required=Array.from(new Set([...r.required??[],i])))}createParameter(e){return{name:e.name,in:e.in,required:e.in===`path`?!0:e.required,description:e.description??void 0,schema:this.createParameterSchema(e),example:e.defaultValue??void 0}}createParameterSchema(e){return{type:e.type??void 0,description:e.description??void 0,default:e.defaultValue??void 0}}createResponses(e,t){let n={};for(let r of e){if(!r.statusCode)continue;let e=t.filter(e=>e.statusCode===r.statusCode),i=this.createResponseContent(e);n[r.statusCode]={description:r.description??r.statusCode,...i?{content:i}:{}}}for(let e of t){if(!e.statusCode||n[e.statusCode])continue;let t=this.createResponseContent([e]);n[e.statusCode]={description:e.label??e.statusCode,...t?{content:t}:{}}}return n}createResponseContent(e){if(e.length===0)return;let t={};for(let n of e){let e=n.contentType??(n.format===`json`?`application/json`:`text/plain`),r=this.normalizeResponseExampleValue(n.body,n.format);t[e]={schema:this.inferSchemaFromBody(r,n.format),example:r}}return t}inferSchemaFromBody(e,t){if(t===`json`)return this.inferSchemaFromExample(e);if(t===`text`)return{type:`string`,example:e}}normalizeResponseExampleValue(e,t){return t!==`json`||typeof e!=`string`?e:F.parsePossiblyTruncated(e)??G(e)??e}resolveFallbackRequestBodyExample(e){return e.responseBodies.find(e=>e.format===`json`)?.body??(typeof e.responseExample==`object`&&e.responseExample!==null?e.responseExample:typeof e.responseExampleRaw==`string`?F.parsePossiblyTruncated(e.responseExampleRaw):typeof e.responseExample==`string`?F.parsePossiblyTruncated(e.responseExample):null)}createExampleSchema(e){return e==null?null:this.inferSchemaFromExample(e)??null}mergeOpenApiSchemas(e,t){if(!e)return t;if(!t)return e;let n={...t,...e,...e.type||t.type?{type:e.type??t.type}:{},...e.description||t.description?{description:e.description??t.description}:{},...e.default!==void 0||t.default!==void 0?{default:e.default??t.default}:{},...e.example!==void 0||t.example!==void 0?{example:e.example??t.example}:{}};if(e.properties||t.properties){let r=new Set([...Object.keys(e.properties??{}),...Object.keys(t.properties??{})]);n.properties=Object.fromEntries(Array.from(r).map(n=>[n,this.mergeOpenApiSchemas(e.properties?.[n]??null,t.properties?.[n]??null)??{}]))}return(e.items||t.items)&&(n.items=this.mergeOpenApiSchemas(e.items??null,t.items??null)??{}),(e.required||t.required)&&(n.required=Array.from(new Set([...t.required??[],...e.required??[]]))),n}buildOperationId(e,t){return`${e}${t.replace(/\{([^}]+)\}/g,`$1`).split(`/`).filter(Boolean).map(e=>e.replace(/[^a-zA-Z0-9]+/g,` `)).map(e=>e.trim()).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1).replace(/\s+(.)/g,(e,t)=>t.toUpperCase())).join(``)}`}isOpenApiParameterLocation(e){return e===`query`||e===`header`||e===`path`||e===`cookie`}};var tt=class extends s{signature=`generate
164
164
  {artifact : Artifact to generate [sdk]}
165
165
  {source? : Documentation URL/local source or parsed TypeScript output file}
166
166
  {--d|dir? : Output directory for the generated artifact}
@@ -174,12 +174,12 @@ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"a
174
174
  {--t|timeout? : Request/browser timeout in milliseconds}
175
175
  {--c|crawl : Crawl sidebar links and parse every discovered operation}
176
176
  {--b|base-url? : Base URL used to resolve sidebar links when crawling from a local file}
177
- `;description=`Generate artifacts such as SDK packages from documentation sources or parsed TypeScript outputs`;async handle(){let e=this.app.getConfig(),t=String(this.argument(`artifact`,``)).trim().toLowerCase(),n=String(this.argument(`source`,``)).trim(),i=String(this.option(`browser`,e.browser)).trim().toLowerCase(),a=String(this.option(`timeout`,``)).trim(),o=this.option(`crawl`),s=String(this.option(`baseUrl`,``)).trim()||null,c=await this.resolveOutputDirectory(n),l=this.spinner(`Generating ${t} artifact...`).start(),u=!1;try{let d=Date.now();if(!M(i))throw Error(`Unsupported browser: ${i}`);if(t!==`sdk`)throw Error(`Unsupported artifact: ${t}`);if(!n)throw Error(`The sdk artifact requires a source argument`);if(!this.isTypeScriptArtifactSource(n)&&!M(i))throw Error(`Unsupported browser: ${i}`);let f=this.resolveTimeoutOverride(a,e.requestTimeout),p=this.parseNamespaceStrategy(this.option(`namespaceStrategy`,`smart`)),m=this.parseMethodStrategy(this.option(`methodStrategy`,`smart`)),h=this.parseOutputMode(this.option(`outputMode`,`both`)),g=this.parseSignatureStyle(this.option(`signatureStyle`,`grouped`)),_=String(this.option(`rootTypeName`,`ExtractedApiDocument`)).trim()||`ExtractedApiDocument`;this.app.configure({browser:i,requestTimeout:f}),!this.isTypeScriptArtifactSource(n)&&o&&(await O(this.app.getConfig()),u=!0);let v=await this.resolveSdkSource({source:n,crawl:o,baseUrl:s,rootTypeName:_,namespaceStrategy:p,methodStrategy:m}),y=this.resolvePackageName(c),b=new Q().generate(v.document,{outputMode:h,signatureStyle:g,rootTypeName:_,namespaceStrategy:p,methodStrategy:m,schemaModule:v.schemaModule,packageName:String(this.option(`name`,``)).trim()||y});await this.writePackageFiles(c,b);let x=Date.now()-d;r.twoColumnDetail(r.log([[`Generated`,`green`],[`${x/1e3}s`,`gray`]],` `,!1),c.replace(process.cwd(),`.`)),l.succeed(`Artifact generation completed`)}catch(e){let t=e instanceof Error?e.message:`Unknown error`;l.fail(`Failed to generate artifact: ${t}`),process.exitCode=1}finally{u&&await k()}}async resolveSdkSource(e){if(this.isTypeScriptArtifactSource(e.source))return this.loadSdkSourceFromTypeScriptArtifact(e.source);let t=F(await this.app.loadHtmlSource(e.source,!0)),n=e.crawl?await this.app.crawlReadmeOperations(e.source,t,e.baseUrl):t,r=this.buildOpenApiPayload(n);return{document:r,schemaModule:await l.format(X.generateModule(r,e.rootTypeName,{namespaceStrategy:e.namespaceStrategy,methodStrategy:e.methodStrategy}),{parser:`typescript`,semi:!1,singleQuote:!0})}}async loadSdkSourceFromTypeScriptArtifact(e){let t=i.resolve(process.cwd(),e),n=await a.readFile(t,`utf8`),r=await import(`${u(t).href}?t=${Date.now()}`),o=r.default??Object.values(r).find(e=>this.isOpenApiDocumentLike(e));if(!this.isOpenApiDocumentLike(o))throw Error(`The provided TypeScript source does not export an OpenAPI document`);return{document:o,schemaModule:n}}buildOpenApiPayload(e){return`operations`in e?$.createDocument(e.operations,`Extracted API`,`0.0.0`):$.createDocument([e],`Extracted API`,`0.0.0`)}resolveTimeoutOverride(e,t){if(!e)return t;let n=Number(e);if(!Number.isFinite(n)||n<=0)throw Error(`Invalid timeout override: ${e}`);return n}async resolveOutputDirectory(e,t){t??=String(this.option(`dir`,``)).trim();let n=t?i.resolve(process.cwd(),t):Z.buildArtifactDirectory(process.cwd(),e,`sdk`);if(d(n)&&f(n).length>0)switch(await this.choice(`Output directory (${t}) already exists and is not empty, what would you like to do?`,[{name:`Overwrite`,value:`overwrite`},{name:`Try to merge`,value:`merge`},{name:`Choose a different directory`,value:`choose`},{name:`Cancel`,value:`cancel`}])){case`overwrite`:await a.rm(n,{recursive:!0,force:!0});break;case`choose`:{let n=await this.ask(`Please enter a new output directory (relative to current directory):`,t);return this.resolveOutputDirectory(e,n)}case`cancel`:return this.info(`Operation cancelled by user`),process.exit(0);default:break}return n}resolvePackageName(e){return String(this.option(`name`,``)).trim()||i.basename(e).replace(/[^a-zA-Z0-9._-]+/g,`-`).replace(/^-+|-+$/g,``)||`generated-sdk`}parseOutputMode(e){let t=String(e??`both`).trim().toLowerCase();if(t===`runtime`||t===`classes`||t===`both`)return t;throw Error(`Unsupported sdk output mode: ${t}`)}parseSignatureStyle(e){let t=String(e??`grouped`).trim().toLowerCase();if(t===`flat`||t===`grouped`)return t;throw Error(`Unsupported signature style: ${t}`)}parseNamespaceStrategy(e){let t=String(e??`smart`).trim().toLowerCase();if(t===`smart`||t===`scoped`)return t;throw Error(`Unsupported namespace strategy: ${t}`)}parseMethodStrategy(e){let t=String(e??`smart`).trim().toLowerCase();if(t===`smart`||t===`operation-id`)return t;throw Error(`Unsupported method strategy: ${t}`)}isTypeScriptArtifactSource(e){return/\.(?:[cm]?ts|[cm]?js)$/i.test(e)}isOpenApiDocumentLike(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e,n=t.info;return t.openapi===`3.1.0`&&typeof n==`object`&&!!n&&!Array.isArray(n)&&typeof n.title==`string`&&typeof n.version==`string`&&typeof t.paths==`object`&&t.paths!==null&&!Array.isArray(t.paths)}async writePackageFiles(e,t){await Promise.all(Object.entries(t).map(async([t,n])=>{let r=i.join(e,t);await a.mkdir(i.dirname(r),{recursive:!0}),await a.writeFile(r,n,`utf8`)}))}};const et=p(import.meta.url);var tt=class extends s{signature=`init
177
+ `;description=`Generate artifacts such as SDK packages from documentation sources or parsed TypeScript outputs`;async handle(){let e=this.app.getConfig(),t=String(this.argument(`artifact`,``)).trim().toLowerCase(),n=String(this.argument(`source`,``)).trim(),i=String(this.option(`browser`,e.browser)).trim().toLowerCase(),a=String(this.option(`timeout`,``)).trim(),o=this.option(`crawl`),s=String(this.option(`baseUrl`,``)).trim()||null,c=await this.resolveOutputDirectory(n),l=this.spinner(`Generating ${t} artifact...`).start(),u=!1;try{let d=Date.now();if(!P(i))throw Error(`Unsupported browser: ${i}`);if(t!==`sdk`)throw Error(`Unsupported artifact: ${t}`);if(!n)throw Error(`The sdk artifact requires a source argument`);if(!this.isTypeScriptArtifactSource(n)&&!P(i))throw Error(`Unsupported browser: ${i}`);let f=this.resolveTimeoutOverride(a,e.requestTimeout),p=this.parseNamespaceStrategy(this.option(`namespaceStrategy`,`smart`)),m=this.parseMethodStrategy(this.option(`methodStrategy`,`smart`)),h=this.parseOutputMode(this.option(`outputMode`,`both`)),g=this.parseSignatureStyle(this.option(`signatureStyle`,`grouped`)),_=String(this.option(`rootTypeName`,`ExtractedApiDocument`)).trim()||`ExtractedApiDocument`;this.app.configure({browser:i,requestTimeout:f}),!this.isTypeScriptArtifactSource(n)&&o&&(await j(this.app.getConfig()),u=!0);let v=await this.resolveSdkSource({source:n,crawl:o,baseUrl:s,rootTypeName:_,namespaceStrategy:p,methodStrategy:m}),y=this.resolvePackageName(c),b=new et().generate(v.document,{outputMode:h,signatureStyle:g,rootTypeName:_,namespaceStrategy:p,methodStrategy:m,schemaModule:v.schemaModule,packageName:String(this.option(`name`,``)).trim()||y});await this.writePackageFiles(c,b);let x=Date.now()-d;r.twoColumnDetail(r.log([[`Generated`,`green`],[`${x/1e3}s`,`gray`]],` `,!1),c.replace(process.cwd(),`.`)),l.succeed(`Artifact generation completed`)}catch(e){let t=e instanceof Error?e.message:`Unknown error`;l.fail(`Failed to generate artifact: ${t}`),process.exitCode=1}finally{u&&await M()}}async resolveSdkSource(e){if(this.isTypeScriptArtifactSource(e.source))return this.loadSdkSourceFromTypeScriptArtifact(e.source);let t=L(await this.app.loadHtmlSource(e.source,!0)),n=e.crawl?await this.app.crawlReadmeOperations(e.source,t,e.baseUrl):t,r=this.buildOpenApiPayload(n);return{document:r,schemaModule:await l.format(Z.generateModule(r,e.rootTypeName,{namespaceStrategy:e.namespaceStrategy,methodStrategy:e.methodStrategy}),{parser:`typescript`,semi:!1,singleQuote:!0})}}async loadSdkSourceFromTypeScriptArtifact(e){let t=i.resolve(process.cwd(),e),n=await a.readFile(t,`utf8`),r=await import(`${d(t).href}?t=${Date.now()}`),o=r.default??Object.values(r).find(e=>this.isOpenApiDocumentLike(e));if(!this.isOpenApiDocumentLike(o))throw Error(`The provided TypeScript source does not export an OpenAPI document`);return{document:o,schemaModule:n}}buildOpenApiPayload(e){return`operations`in e?$.createDocument(e.operations,`Extracted API`,`0.0.0`):$.createDocument([e],`Extracted API`,`0.0.0`)}resolveTimeoutOverride(e,t){if(!e)return t;let n=Number(e);if(!Number.isFinite(n)||n<=0)throw Error(`Invalid timeout override: ${e}`);return n}async resolveOutputDirectory(e,t){t??=String(this.option(`dir`,``)).trim();let n=t?i.resolve(process.cwd(),t):Q.buildArtifactDirectory(process.cwd(),e,`sdk`);if(f(n)&&p(n).length>0)switch(await this.choice(`Output directory (${t}) already exists and is not empty, what would you like to do?`,[{name:`Overwrite`,value:`overwrite`},{name:`Try to merge`,value:`merge`},{name:`Choose a different directory`,value:`choose`},{name:`Cancel`,value:`cancel`}])){case`overwrite`:await a.rm(n,{recursive:!0,force:!0});break;case`choose`:{let n=await this.ask(`Please enter a new output directory (relative to current directory):`,t);return this.resolveOutputDirectory(e,n)}case`cancel`:return this.info(`Operation cancelled by user`),process.exit(0);default:break}return n}resolvePackageName(e){return String(this.option(`name`,``)).trim()||i.basename(e).replace(/[^a-zA-Z0-9._-]+/g,`-`).replace(/^-+|-+$/g,``)||`generated-sdk`}parseOutputMode(e){let t=String(e??`both`).trim().toLowerCase();if(t===`runtime`||t===`classes`||t===`both`)return t;throw Error(`Unsupported sdk output mode: ${t}`)}parseSignatureStyle(e){let t=String(e??`grouped`).trim().toLowerCase();if(t===`flat`||t===`grouped`)return t;throw Error(`Unsupported signature style: ${t}`)}parseNamespaceStrategy(e){let t=String(e??`smart`).trim().toLowerCase();if(t===`smart`||t===`scoped`)return t;throw Error(`Unsupported namespace strategy: ${t}`)}parseMethodStrategy(e){let t=String(e??`smart`).trim().toLowerCase();if(t===`smart`||t===`operation-id`)return t;throw Error(`Unsupported method strategy: ${t}`)}isTypeScriptArtifactSource(e){return/\.(?:[cm]?ts|[cm]?js)$/i.test(e)}isOpenApiDocumentLike(e){if(typeof e!=`object`||!e||Array.isArray(e))return!1;let t=e,n=t.info;return t.openapi===`3.1.0`&&typeof n==`object`&&!!n&&!Array.isArray(n)&&typeof n.title==`string`&&typeof n.version==`string`&&typeof t.paths==`object`&&t.paths!==null&&!Array.isArray(t.paths)}async writePackageFiles(e,t){await Promise.all(Object.entries(t).map(async([t,n])=>{let r=i.join(e,t);await a.mkdir(i.dirname(r),{recursive:!0}),await a.writeFile(r,n,`utf8`)}))}};const nt=m(import.meta.url);var rt=class extends s{signature=`init
178
178
  {--f|force : Overwrite existing config}
179
179
  {--S|sdk-kit : Also include default SDK config values.}
180
- `;description=`Generate a default oapiex.config.ts in the current directory`;async handle(){let e=process.cwd(),t=i.join(e,`oapiex.config.js`),n=this.option(`force`,!1),r=this.option(`sdkKit`,!1),o=this.buildConfigTemplate(r);try{await a.access(t),n||(this.error(`Config file already exists at ${t}. Use --force to overwrite.`),process.exit(1))}catch{}await a.writeFile(t,o,`utf8`),this.line(`Created ${t} `)}buildConfigTemplate(e=!1){let t=_;return[`import { defineConfig } from '${et.includes(`node_modules`)?`oapiex`:`./src/Manager`}'`,``,`/**`,` * See https://toneflix.github.io/oapiex/configuration for docs`,` */`,`export default defineConfig({`,` outputFormat: '${t.outputFormat}',`,` outputShape: '${t.outputShape}',`,` browser: '${t.browser}',`,` requestTimeout: ${t.requestTimeout},`,` maxRedirects: ${t.maxRedirects},`,` userAgent: '${t.userAgent}',`,` retryCount: ${t.retryCount},`,` retryDelay: ${t.retryDelay},`,e?this.buildSdkConfigTemplate():void 0,`})`].filter(Boolean).join(`
180
+ `;description=`Generate a default oapiex.config.ts in the current directory`;async handle(){let e=process.cwd(),t=i.join(e,`oapiex.config.js`),n=this.option(`force`,!1),r=this.option(`sdkKit`,!1),o=this.buildConfigTemplate(r);try{await a.access(t),n||(this.error(`Config file already exists at ${t}. Use --force to overwrite.`),process.exit(1))}catch{}await a.writeFile(t,o,`utf8`),this.line(`Created ${t} `)}buildConfigTemplate(e=!1){let t=g;return[`import { defineConfig } from '${nt.includes(`node_modules`)?`oapiex`:`./src/config`}'`,``,`/**`,` * See https://toneflix.github.io/oapiex/configuration for docs`,` */`,`export default defineConfig({`,` outputFormat: '${t.outputFormat}',`,` outputShape: '${t.outputShape}',`,` browser: '${t.browser}',`,` requestTimeout: ${t.requestTimeout},`,` maxRedirects: ${t.maxRedirects},`,` userAgent: '${t.userAgent}',`,` retryCount: ${t.retryCount},`,` retryDelay: ${t.retryDelay},`,e?this.buildSdkConfigTemplate():void 0,`})`].filter(Boolean).join(`
181
181
  `)}buildSdkConfigTemplate(){return[` sdkKit: {`,` clientId: 'your-client-id',`,` clientSecret: 'your-client-secret',`,` encryptionKey: 'your-encryption-key',`,` environment: 'sandbox',`,` urls: {`,` live: 'https://live.oapiex.com',`,` sandbox: 'https://sandbox.oapiex.com',`,` },`,` debugLevel: 0,`,` },`].join(`
182
- `)}},nt=class extends s{signature=`parse
182
+ `)}},it=class extends s{signature=`parse
183
183
  {source : Local HTML file path or remote URL}
184
184
  {--O|output=pretty : Output format [pretty,json,js,ts]}
185
185
  {--S|shape=raw : Result shape [raw,openapi]}
@@ -187,4 +187,4 @@ import{JSDOM as e}from"jsdom";import{Window as t}from"happy-dom";import n from"a
187
187
  {--t|timeout? : Request/browser timeout in milliseconds}
188
188
  {--c|crawl : Crawl sidebar links and parse every discovered operation}
189
189
  {--b|base-url? : Base URL used to resolve sidebar links when crawling from a local file}
190
- `;description=`Parse a saved ReadMe page or remote documentation URL and print normalized output`;async handle(){let e=this.app.getConfig(),t=String(this.argument(`source`,``)).trim(),n=String(this.option(`output`,e.outputFormat)).trim().toLowerCase(),i=String(this.option(`shape`,e.outputShape)).trim().toLowerCase(),a=String(this.option(`browser`,e.browser)).trim().toLowerCase(),o=String(this.option(`timeout`,``)).trim(),s=this.option(`crawl`),c=String(this.option(`baseUrl`,``)).trim()||null,l=this.spinner(`${s?`Crawling and p`:`P`}arsing source...`).start(),u=!1;try{let d=Date.now();if(!M(a))throw Error(`Unsupported browser: ${a}`);let f=this.resolveTimeoutOverride(o,e.requestTimeout);this.app.configure({browser:a,requestTimeout:f}),s&&(await O(this.app.getConfig()),u=!0);let p=F(await this.app.loadHtmlSource(t,!0)),m=s?await this.app.crawlReadmeOperations(t,p,c):p,h=i===`openapi`?this.buildOpenApiPayload(m):m,g=await Z.serializeOutput(h,n,Z.getRootTypeName(i)),_=await this.saveOutputToFile(g,t,i,n),v=Date.now()-d;r.twoColumnDetail(r.log([[`Output`,`green`],[`${v/1e3}s`,`gray`]],` `,!1),_.replace(process.cwd(),`.`)),l.succeed(`Parsing completed`)}catch(e){let t=e instanceof Error?e.message:`Unknown error`;l.fail(`Failed to parse source: ${t}`),process.exitCode=1}finally{u&&await k()}}resolveTimeoutOverride=(e,t)=>{if(!e)return t;let n=Number(e);if(!Number.isFinite(n)||n<=0)throw Error(`Invalid timeout override: ${e}`);return n};buildOpenApiPayload=e=>`operations`in e?$.createDocument(e.operations,`Extracted API`,`0.0.0`):$.createDocument([e],`Extracted API`,`0.0.0`);saveOutputToFile=async(e,t,n,r)=>{let o=Z.buildFilePath(process.cwd(),t,n,r),s=i.dirname(o);return await a.mkdir(s,{recursive:!0}),await a.writeFile(o,e,`utf8`),o}};const rt=[`oapiex.config.ts`,`oapiex.config.js`,`oapiex.config.cjs`];async function it(e=process.cwd()){let t=m(import.meta.url,{interopDefault:!0,moduleCache:!1,fsCache:!1});for(let n of rt){let r=i.join(e,n);try{await a.access(r);let e=await t.import(r),n=typeof e==`object`&&e?e:null,i=n?.default??n?.config??e;if(typeof i==`object`&&i)return i}catch{continue}}return null}async function at(e={}){let t=await it();return{..._,...t,...e,happyDom:{..._.happyDom,...t?.happyDom||{},...e.happyDom||{}}}}const ot=new Ye(await at());await c.init(ot,{name:`OAPIEX`,logo:``,allowRebuilds:!1,packages:[`@h3ravel/musket`],baseCommands:[tt,$e,nt],exceptionHandler(e){console.error(`An unexpected error occurred:`,e),process.exit(1)}});export{};
190
+ `;description=`Parse a saved ReadMe page or remote documentation URL and print normalized output`;async handle(){let e=this.app.getConfig(),t=String(this.argument(`source`,``)).trim(),n=String(this.option(`output`,e.outputFormat)).trim().toLowerCase(),i=String(this.option(`shape`,e.outputShape)).trim().toLowerCase(),a=String(this.option(`browser`,e.browser)).trim().toLowerCase(),o=String(this.option(`timeout`,``)).trim(),s=this.option(`crawl`),c=String(this.option(`baseUrl`,``)).trim()||null,l=this.spinner(`${s?`Crawling and p`:`P`}arsing source...`).start(),u=!1;try{let d=Date.now();if(!P(a))throw Error(`Unsupported browser: ${a}`);let f=this.resolveTimeoutOverride(o,e.requestTimeout);this.app.configure({browser:a,requestTimeout:f}),s&&(await j(this.app.getConfig()),u=!0);let p=L(await this.app.loadHtmlSource(t,!0)),m=s?await this.app.crawlReadmeOperations(t,p,c):p,h=i===`openapi`?this.buildOpenApiPayload(m):m,g=await Q.serializeOutput(h,n,Q.getRootTypeName(i)),_=await this.saveOutputToFile(g,t,i,n),v=Date.now()-d;r.twoColumnDetail(r.log([[`Output`,`green`],[`${v/1e3}s`,`gray`]],` `,!1),_.replace(process.cwd(),`.`)),l.succeed(`Parsing completed`)}catch(e){let t=e instanceof Error?e.message:`Unknown error`;l.fail(`Failed to parse source: ${t}`),process.exitCode=1}finally{u&&await M()}}resolveTimeoutOverride=(e,t)=>{if(!e)return t;let n=Number(e);if(!Number.isFinite(n)||n<=0)throw Error(`Invalid timeout override: ${e}`);return n};buildOpenApiPayload=e=>`operations`in e?$.createDocument(e.operations,`Extracted API`,`0.0.0`):$.createDocument([e],`Extracted API`,`0.0.0`);saveOutputToFile=async(e,t,n,r)=>{let o=Q.buildFilePath(process.cwd(),t,n,r),s=i.dirname(o);return await a.mkdir(s,{recursive:!0}),await a.writeFile(o,e,`utf8`),o}};const at=[`oapiex.config.ts`,`oapiex.config.js`,`oapiex.config.cjs`];async function ot(e=process.cwd()){let t=h(import.meta.url,{interopDefault:!0,moduleCache:!1,fsCache:!1});for(let n of at){let r=i.join(e,n);try{await a.access(r);let e=await t.import(r),n=typeof e==`object`&&e?e:null,i=n?.default??n?.config??e;if(typeof i==`object`&&i)return i}catch{continue}}return null}async function st(e={}){let t=await ot();return v(v(_(),t??{}),e)}const ct=new Xe(await st());await c.init(ct,{name:`OAPIEX`,logo:``,allowRebuilds:!1,packages:[`@h3ravel/musket`],baseCommands:[rt,tt,it],exceptionHandler(e){console.error(`An unexpected error occurred:`,e),process.exit(1)}});export{};
package/dist/index.cjs CHANGED
@@ -38,23 +38,13 @@ node_fs_promises = __toESM(node_fs_promises);
38
38
  let _h3ravel_musket = require("@h3ravel/musket");
39
39
  let prettier = require("prettier");
40
40
  prettier = __toESM(prettier);
41
+ let node_child_process = require("node:child_process");
41
42
  let node_url = require("node:url");
42
43
  let node_fs = require("node:fs");
43
44
  let url = require("url");
44
45
  let jiti = require("jiti");
45
46
 
46
- //#region src/Manager.ts
47
- const terminationSignals = [
48
- "SIGINT",
49
- "SIGTERM",
50
- "SIGTSTP"
51
- ];
52
- const supportedBrowsers = [
53
- "axios",
54
- "happy-dom",
55
- "jsdom",
56
- "puppeteer"
57
- ];
47
+ //#region src/config.ts
58
48
  const defaultConfig = {
59
49
  outputFormat: "pretty",
60
50
  outputShape: "raw",
@@ -73,7 +63,67 @@ const defaultConfig = {
73
63
  args: ["--no-sandbox", "--disable-setuid-sandbox"]
74
64
  }
75
65
  };
76
- let globalConfig = defaultConfig;
66
+ const createDefaultConfig = () => ({
67
+ ...defaultConfig,
68
+ happyDom: { ...defaultConfig.happyDom },
69
+ puppeteer: defaultConfig.puppeteer ? {
70
+ ...defaultConfig.puppeteer,
71
+ args: defaultConfig.puppeteer.args ? [...defaultConfig.puppeteer.args] : void 0
72
+ } : void 0,
73
+ sdkKit: defaultConfig.sdkKit ? {
74
+ ...defaultConfig.sdkKit,
75
+ urls: defaultConfig.sdkKit.urls ? { ...defaultConfig.sdkKit.urls } : void 0
76
+ } : void 0,
77
+ sdk: defaultConfig.sdk ? {
78
+ ...defaultConfig.sdk,
79
+ urls: defaultConfig.sdk.urls ? { ...defaultConfig.sdk.urls } : void 0
80
+ } : void 0
81
+ });
82
+ const mergeConfig = (baseConfig, config) => ({
83
+ ...baseConfig,
84
+ ...config,
85
+ happyDom: {
86
+ ...baseConfig.happyDom,
87
+ ...config.happyDom
88
+ },
89
+ puppeteer: config.puppeteer ? {
90
+ ...baseConfig.puppeteer ?? {},
91
+ ...config.puppeteer,
92
+ args: config.puppeteer.args ? [...config.puppeteer.args] : baseConfig.puppeteer?.args
93
+ } : baseConfig.puppeteer,
94
+ sdkKit: config.sdkKit ? {
95
+ ...baseConfig.sdkKit ?? {},
96
+ ...config.sdkKit,
97
+ urls: config.sdkKit.urls ? {
98
+ ...baseConfig.sdkKit?.urls ?? {},
99
+ ...config.sdkKit.urls
100
+ } : baseConfig.sdkKit?.urls
101
+ } : baseConfig.sdkKit,
102
+ sdk: config.sdk ? {
103
+ ...baseConfig.sdk ?? {},
104
+ ...config.sdk,
105
+ urls: config.sdk.urls ? {
106
+ ...baseConfig.sdk?.urls ?? {},
107
+ ...config.sdk.urls
108
+ } : baseConfig.sdk?.urls
109
+ } : baseConfig.sdk
110
+ });
111
+ const defineConfig = (config) => config;
112
+
113
+ //#endregion
114
+ //#region src/Manager.ts
115
+ const terminationSignals = [
116
+ "SIGINT",
117
+ "SIGTERM",
118
+ "SIGTSTP"
119
+ ];
120
+ const supportedBrowsers = [
121
+ "axios",
122
+ "happy-dom",
123
+ "jsdom",
124
+ "puppeteer"
125
+ ];
126
+ let globalConfig = createDefaultConfig();
77
127
  let cleanupInProgress = false;
78
128
  let terminationHandlersInstalled = false;
79
129
  const activeClosers = /* @__PURE__ */ new Set();
@@ -152,15 +202,8 @@ const registerDeferredCloser = (browserName, closer) => {
152
202
  activeSession.closers.push(closer);
153
203
  return true;
154
204
  };
155
- const defineConfig = (config) => {
156
- const userConfig = {
157
- ...defaultConfig,
158
- ...config,
159
- happyDom: {
160
- ...defaultConfig.happyDom,
161
- ...config.happyDom
162
- }
163
- };
205
+ const updateConfig = (config) => {
206
+ const userConfig = mergeConfig(globalConfig, config);
164
207
  globalConfig = userConfig;
165
208
  return userConfig;
166
209
  };
@@ -1120,7 +1163,7 @@ const resolveReadmeSidebarUrls = (operation, baseUrl) => {
1120
1163
  var Application = class {
1121
1164
  config;
1122
1165
  constructor(config = {}) {
1123
- this.config = defineConfig(config);
1166
+ this.config = mergeConfig(createDefaultConfig(), config);
1124
1167
  }
1125
1168
  getConfig(config = {}) {
1126
1169
  return {
@@ -1129,10 +1172,7 @@ var Application = class {
1129
1172
  };
1130
1173
  }
1131
1174
  configure(config) {
1132
- this.config = defineConfig({
1133
- ...this.config,
1134
- ...config
1135
- });
1175
+ this.config = mergeConfig(this.config, config);
1136
1176
  return this.config;
1137
1177
  }
1138
1178
  async crawlReadmeOperations(source, rootOperation, baseUrl) {
@@ -2627,7 +2667,8 @@ var OutputGenerator = class {
2627
2667
 
2628
2668
  //#endregion
2629
2669
  //#region src/generator/SdkPackageGenerator.ts
2630
- var SdkPackageGenerator = class {
2670
+ var SdkPackageGenerator = class SdkPackageGenerator {
2671
+ static publishedPackageVersionRanges = /* @__PURE__ */ new Map();
2631
2672
  typeBuilder = new TypeBuilder();
2632
2673
  typeScriptGenerator = new TypeScriptGenerator();
2633
2674
  generate(document, options = {}) {
@@ -2856,6 +2897,7 @@ var SdkPackageGenerator = class {
2856
2897
  ].join("\n");
2857
2898
  }
2858
2899
  renderPackageJson(options) {
2900
+ const sdkKitPackageName = options.sdkKitPackageName ?? "@oapiex/sdk-kit";
2859
2901
  return JSON.stringify({
2860
2902
  name: options.packageName ?? "generated-sdk",
2861
2903
  type: "module",
@@ -2878,7 +2920,10 @@ var SdkPackageGenerator = class {
2878
2920
  "test:watch": "pnpm vitest",
2879
2921
  build: "tsdown"
2880
2922
  },
2881
- dependencies: { [options.sdkKitPackageName ?? "@oapiex/sdk-kit"]: "^0.1.1" },
2923
+ dependencies: {
2924
+ "@h3ravel/shared": this.resolvePublishedPackageVersionRange("@h3ravel/shared"),
2925
+ [sdkKitPackageName]: this.resolvePublishedPackageVersionRange(sdkKitPackageName)
2926
+ },
2882
2927
  devDependencies: {
2883
2928
  "@types/node": "^20.14.5",
2884
2929
  tsdown: "^0.20.1",
@@ -2887,6 +2932,40 @@ var SdkPackageGenerator = class {
2887
2932
  }
2888
2933
  }, null, 2);
2889
2934
  }
2935
+ /**
2936
+ * Attempts to resolve the published version range for the given package name by querying npm.
2937
+ * If the package is not found or an error occurs, it falls back to a default version range.
2938
+ *
2939
+ * @param packageName The name of the npm package to query.
2940
+ * @returns The resolved version range for the package.
2941
+ */
2942
+ resolvePublishedPackageVersionRange(packageName) {
2943
+ const cached = SdkPackageGenerator.publishedPackageVersionRanges.get(packageName);
2944
+ if (cached) return cached;
2945
+ try {
2946
+ const version = JSON.parse((0, node_child_process.execFileSync)("npm", [
2947
+ "view",
2948
+ packageName,
2949
+ "version",
2950
+ "--json"
2951
+ ], {
2952
+ encoding: "utf8",
2953
+ stdio: [
2954
+ "ignore",
2955
+ "pipe",
2956
+ "ignore"
2957
+ ]
2958
+ }));
2959
+ if (typeof version === "string" && version.trim().length > 0) {
2960
+ const versionRange = `^${version.trim()}`;
2961
+ SdkPackageGenerator.publishedPackageVersionRanges.set(packageName, versionRange);
2962
+ return versionRange;
2963
+ }
2964
+ } catch {
2965
+ SdkPackageGenerator.publishedPackageVersionRanges.set(packageName, "latest");
2966
+ }
2967
+ return "latest";
2968
+ }
2890
2969
  renderReadme(manifest, options, outputMode, signatureStyle) {
2891
2970
  const packageName = options.packageName ?? "generated-sdk";
2892
2971
  const title = `# ${packageName}`;
@@ -3730,7 +3809,7 @@ var InitCommand = class extends _h3ravel_musket.Command {
3730
3809
  buildConfigTemplate(addSdkConfig = false) {
3731
3810
  const def = defaultConfig;
3732
3811
  return [
3733
- `import { defineConfig } from '${__filename$1.includes("node_modules") ? "oapiex" : "./src/Manager"}'`,
3812
+ `import { defineConfig } from '${__filename$1.includes("node_modules") ? "oapiex" : "./src/config"}'`,
3734
3813
  "",
3735
3814
  "/**",
3736
3815
  " * See https://toneflix.github.io/oapiex/configuration for docs",
@@ -3865,16 +3944,7 @@ async function loadUserConfig(rootDir = process.cwd()) {
3865
3944
  }
3866
3945
  async function resolveConfig(cliOverrides = {}) {
3867
3946
  const userConfig = await loadUserConfig();
3868
- return {
3869
- ...defaultConfig,
3870
- ...userConfig,
3871
- ...cliOverrides,
3872
- happyDom: {
3873
- ...defaultConfig.happyDom,
3874
- ...userConfig?.happyDom || {},
3875
- ...cliOverrides.happyDom || {}
3876
- }
3877
- };
3947
+ return mergeConfig(mergeConfig(createDefaultConfig(), userConfig ?? {}), cliOverrides);
3878
3948
  }
3879
3949
 
3880
3950
  //#endregion
@@ -3890,6 +3960,7 @@ exports.TypeScriptGenerator = TypeScriptGenerator;
3890
3960
  exports.browser = browser;
3891
3961
  exports.buildOperationUrl = buildOperationUrl;
3892
3962
  exports.closeActiveBrowserResources = closeActiveBrowserResources;
3963
+ exports.createDefaultConfig = createDefaultConfig;
3893
3964
  exports.defaultConfig = defaultConfig;
3894
3965
  exports.defineConfig = defineConfig;
3895
3966
  exports.endBrowserSession = endBrowserSession;
@@ -3937,6 +4008,7 @@ exports.isRecord = isRecord;
3937
4008
  exports.isRequiredParameter = isRequiredParameter;
3938
4009
  exports.isSupportedBrowser = isSupportedBrowser;
3939
4010
  exports.loadUserConfig = loadUserConfig;
4011
+ exports.mergeConfig = mergeConfig;
3940
4012
  exports.mergeReadmeOperations = mergeReadmeOperations;
3941
4013
  exports.mergeSsrPropsIntoRenderedHtml = mergeSsrPropsIntoRenderedHtml;
3942
4014
  exports.normalizeCurlSnippet = normalizeCurlSnippet;
@@ -3956,4 +4028,5 @@ exports.resolveReadmeSidebarUrls = resolveReadmeSidebarUrls;
3956
4028
  exports.resolveSsrOperation = resolveSsrOperation;
3957
4029
  exports.startBrowserSession = startBrowserSession;
3958
4030
  exports.supportedBrowsers = supportedBrowsers;
3959
- exports.transformer = transformer;
4031
+ exports.transformer = transformer;
4032
+ exports.updateConfig = updateConfig;
package/dist/index.d.ts CHANGED
@@ -386,6 +386,12 @@ declare class ParseCommand extends Command<Application> {
386
386
  saveOutputToFile: (content: string, source: string, shape: string, outputFormat: UserConfig["outputFormat"]) => Promise<string>;
387
387
  }
388
388
  //#endregion
389
+ //#region src/config.d.ts
390
+ declare const defaultConfig: UserConfig;
391
+ declare const createDefaultConfig: () => UserConfig;
392
+ declare const mergeConfig: (baseConfig: UserConfig, config: Partial<UserConfig>) => UserConfig;
393
+ declare const defineConfig: <TConfig extends Partial<UserConfig>>(config: TConfig) => TConfig;
394
+ //#endregion
389
395
  //#region src/ConfigLoader.d.ts
390
396
  declare function loadUserConfig(rootDir?: string): Promise<Partial<UserConfig> | null>;
391
397
  declare function resolveConfig(cliOverrides?: Partial<UserConfig>): Promise<UserConfig>;
@@ -579,6 +585,7 @@ interface SdkPackageGeneratorOptions extends SdkNamingStrategyOptions {
579
585
  sdkKitPackageName?: string;
580
586
  }
581
587
  declare class SdkPackageGenerator {
588
+ private static publishedPackageVersionRanges;
582
589
  private typeBuilder;
583
590
  private typeScriptGenerator;
584
591
  generate(document: OpenApiDocumentLike, options?: SdkPackageGeneratorOptions): Record<string, string>;
@@ -601,6 +608,14 @@ declare class SdkPackageGenerator {
601
608
  private renderFlatHeaders;
602
609
  private renderCoreFile;
603
610
  private renderPackageJson;
611
+ /**
612
+ * Attempts to resolve the published version range for the given package name by querying npm.
613
+ * If the package is not found or an error occurs, it falls back to a default version range.
614
+ *
615
+ * @param packageName The name of the npm package to query.
616
+ * @returns The resolved version range for the package.
617
+ */
618
+ private resolvePublishedPackageVersionRange;
604
619
  private renderReadme;
605
620
  private renderReadmeDescription;
606
621
  private renderReadmeUsage;
@@ -683,14 +698,13 @@ declare global {
683
698
  var __oapieBrowserSession: BrowserSession | undefined;
684
699
  }
685
700
  declare const supportedBrowsers: BrowserName[];
686
- declare const defaultConfig: UserConfig;
687
701
  declare let globalConfig: UserConfig;
688
702
  declare const getBrowserSession: () => BrowserSession | undefined;
689
703
  declare const registerActiveBrowserCloser: (closer: CleanupCloser) => (() => void);
690
704
  declare const closeActiveBrowserResources: () => Promise<void>;
691
705
  declare const startBrowserSession: (config?: UserConfig) => Promise<BrowserSession>;
692
706
  declare const endBrowserSession: () => Promise<void>;
693
- declare const defineConfig: (config: Partial<UserConfig>) => UserConfig;
707
+ declare const updateConfig: (config: Partial<UserConfig>) => UserConfig;
694
708
  declare const isSupportedBrowser: (value: string) => value is BrowserName;
695
709
  /**
696
710
  * Loads HTML content from a given source URL using the configured browser.
@@ -741,4 +755,4 @@ interface ReadmeCrawledOperation extends ReadmeOperation {
741
755
  }
742
756
  declare const resolveReadmeSidebarUrls: (operation: Pick<ReadmeOperation, "sidebarLinks">, baseUrl: string) => string[];
743
757
  //#endregion
744
- export { Application, AttributeQueryNode, AttributedNode, BrowserName, Declaration, GenerateCommand, GeneratorContext, InitCommand, InterfaceAliasDeclaration, InterfaceDeclaration, JsonLike, JsonRepair, OpenApiDocumentLike, OpenApiMediaType, OpenApiOauthFlowLike, OpenApiOperationLike, OpenApiParameterLike, OpenApiResponse, OpenApiSchema, OpenApiSecurityRequirementLike, OpenApiSecuritySchemeLike, OpenApiTransformer, OperationTypeRefs, OutputGenerator, ParseCommand, PayloadSchemaCandidate, QueryableNode, ReadmeCodeSnippet, ReadmeCrawledOperation, ReadmeNormalizedRequestExample, ReadmeOperation, ReadmeParameter, ReadmeResponseBody, ReadmeResponseSchema, ReadmeSidebarLink, SdkGroupManifest, SdkKitApiKeyAuthConfig, SdkKitAuthConfig, SdkKitAuthRequestConfig, SdkKitBasicAuthConfig, SdkKitBearerAuthConfig, SdkKitConfig, SdkKitCustomAuthConfig, SdkKitDebugLevel, SdkKitEnvironment, SdkKitHttpMethod, SdkKitOAuth2AuthConfig, SdkKitUrls, SdkManifest, SdkMethodNamingStrategy, SdkNamespaceNamingStrategy, SdkNamingStrategyOptions, SdkOperationManifest, SdkPackageGenerator, SdkPackageGeneratorOptions, SdkParameterManifest, SdkSecurityRequirementManifest, SdkSecurityRequirementSchemeManifest, SdkSecuritySchemeManifest, SemanticModel, ShapeAliasDeclaration, ShapeNode, ShapeProperty, TextNodeLike, TypeReferenceAliasDeclaration, TypeScriptGenerator, UserConfig, browser, buildOperationUrl, closeActiveBrowserResources, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, registerActiveBrowserCloser, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer };
758
+ export { Application, AttributeQueryNode, AttributedNode, BrowserName, Declaration, GenerateCommand, GeneratorContext, InitCommand, InterfaceAliasDeclaration, InterfaceDeclaration, JsonLike, JsonRepair, OpenApiDocumentLike, OpenApiMediaType, OpenApiOauthFlowLike, OpenApiOperationLike, OpenApiParameterLike, OpenApiResponse, OpenApiSchema, OpenApiSecurityRequirementLike, OpenApiSecuritySchemeLike, OpenApiTransformer, OperationTypeRefs, OutputGenerator, ParseCommand, PayloadSchemaCandidate, QueryableNode, ReadmeCodeSnippet, ReadmeCrawledOperation, ReadmeNormalizedRequestExample, ReadmeOperation, ReadmeParameter, ReadmeResponseBody, ReadmeResponseSchema, ReadmeSidebarLink, SdkGroupManifest, SdkKitApiKeyAuthConfig, SdkKitAuthConfig, SdkKitAuthRequestConfig, SdkKitBasicAuthConfig, SdkKitBearerAuthConfig, SdkKitConfig, SdkKitCustomAuthConfig, SdkKitDebugLevel, SdkKitEnvironment, SdkKitHttpMethod, SdkKitOAuth2AuthConfig, SdkKitUrls, SdkManifest, SdkMethodNamingStrategy, SdkNamespaceNamingStrategy, SdkNamingStrategyOptions, SdkOperationManifest, SdkPackageGenerator, SdkPackageGeneratorOptions, SdkParameterManifest, SdkSecurityRequirementManifest, SdkSecurityRequirementSchemeManifest, SdkSecuritySchemeManifest, SemanticModel, ShapeAliasDeclaration, ShapeNode, ShapeProperty, TextNodeLike, TypeReferenceAliasDeclaration, TypeScriptGenerator, UserConfig, browser, buildOperationUrl, closeActiveBrowserResources, createDefaultConfig, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, registerActiveBrowserCloser, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer, updateConfig };
package/dist/index.mjs CHANGED
@@ -6,23 +6,13 @@ import path from "node:path";
6
6
  import fs, { readFile } from "node:fs/promises";
7
7
  import { Command } from "@h3ravel/musket";
8
8
  import prettier from "prettier";
9
+ import { execFileSync } from "node:child_process";
9
10
  import { pathToFileURL } from "node:url";
10
11
  import { existsSync, readdirSync } from "node:fs";
11
12
  import { fileURLToPath } from "url";
12
13
  import { createJiti } from "jiti";
13
14
 
14
- //#region src/Manager.ts
15
- const terminationSignals = [
16
- "SIGINT",
17
- "SIGTERM",
18
- "SIGTSTP"
19
- ];
20
- const supportedBrowsers = [
21
- "axios",
22
- "happy-dom",
23
- "jsdom",
24
- "puppeteer"
25
- ];
15
+ //#region src/config.ts
26
16
  const defaultConfig = {
27
17
  outputFormat: "pretty",
28
18
  outputShape: "raw",
@@ -41,7 +31,67 @@ const defaultConfig = {
41
31
  args: ["--no-sandbox", "--disable-setuid-sandbox"]
42
32
  }
43
33
  };
44
- let globalConfig = defaultConfig;
34
+ const createDefaultConfig = () => ({
35
+ ...defaultConfig,
36
+ happyDom: { ...defaultConfig.happyDom },
37
+ puppeteer: defaultConfig.puppeteer ? {
38
+ ...defaultConfig.puppeteer,
39
+ args: defaultConfig.puppeteer.args ? [...defaultConfig.puppeteer.args] : void 0
40
+ } : void 0,
41
+ sdkKit: defaultConfig.sdkKit ? {
42
+ ...defaultConfig.sdkKit,
43
+ urls: defaultConfig.sdkKit.urls ? { ...defaultConfig.sdkKit.urls } : void 0
44
+ } : void 0,
45
+ sdk: defaultConfig.sdk ? {
46
+ ...defaultConfig.sdk,
47
+ urls: defaultConfig.sdk.urls ? { ...defaultConfig.sdk.urls } : void 0
48
+ } : void 0
49
+ });
50
+ const mergeConfig = (baseConfig, config) => ({
51
+ ...baseConfig,
52
+ ...config,
53
+ happyDom: {
54
+ ...baseConfig.happyDom,
55
+ ...config.happyDom
56
+ },
57
+ puppeteer: config.puppeteer ? {
58
+ ...baseConfig.puppeteer ?? {},
59
+ ...config.puppeteer,
60
+ args: config.puppeteer.args ? [...config.puppeteer.args] : baseConfig.puppeteer?.args
61
+ } : baseConfig.puppeteer,
62
+ sdkKit: config.sdkKit ? {
63
+ ...baseConfig.sdkKit ?? {},
64
+ ...config.sdkKit,
65
+ urls: config.sdkKit.urls ? {
66
+ ...baseConfig.sdkKit?.urls ?? {},
67
+ ...config.sdkKit.urls
68
+ } : baseConfig.sdkKit?.urls
69
+ } : baseConfig.sdkKit,
70
+ sdk: config.sdk ? {
71
+ ...baseConfig.sdk ?? {},
72
+ ...config.sdk,
73
+ urls: config.sdk.urls ? {
74
+ ...baseConfig.sdk?.urls ?? {},
75
+ ...config.sdk.urls
76
+ } : baseConfig.sdk?.urls
77
+ } : baseConfig.sdk
78
+ });
79
+ const defineConfig = (config) => config;
80
+
81
+ //#endregion
82
+ //#region src/Manager.ts
83
+ const terminationSignals = [
84
+ "SIGINT",
85
+ "SIGTERM",
86
+ "SIGTSTP"
87
+ ];
88
+ const supportedBrowsers = [
89
+ "axios",
90
+ "happy-dom",
91
+ "jsdom",
92
+ "puppeteer"
93
+ ];
94
+ let globalConfig = createDefaultConfig();
45
95
  let cleanupInProgress = false;
46
96
  let terminationHandlersInstalled = false;
47
97
  const activeClosers = /* @__PURE__ */ new Set();
@@ -120,15 +170,8 @@ const registerDeferredCloser = (browserName, closer) => {
120
170
  activeSession.closers.push(closer);
121
171
  return true;
122
172
  };
123
- const defineConfig = (config) => {
124
- const userConfig = {
125
- ...defaultConfig,
126
- ...config,
127
- happyDom: {
128
- ...defaultConfig.happyDom,
129
- ...config.happyDom
130
- }
131
- };
173
+ const updateConfig = (config) => {
174
+ const userConfig = mergeConfig(globalConfig, config);
132
175
  globalConfig = userConfig;
133
176
  return userConfig;
134
177
  };
@@ -1088,7 +1131,7 @@ const resolveReadmeSidebarUrls = (operation, baseUrl) => {
1088
1131
  var Application = class {
1089
1132
  config;
1090
1133
  constructor(config = {}) {
1091
- this.config = defineConfig(config);
1134
+ this.config = mergeConfig(createDefaultConfig(), config);
1092
1135
  }
1093
1136
  getConfig(config = {}) {
1094
1137
  return {
@@ -1097,10 +1140,7 @@ var Application = class {
1097
1140
  };
1098
1141
  }
1099
1142
  configure(config) {
1100
- this.config = defineConfig({
1101
- ...this.config,
1102
- ...config
1103
- });
1143
+ this.config = mergeConfig(this.config, config);
1104
1144
  return this.config;
1105
1145
  }
1106
1146
  async crawlReadmeOperations(source, rootOperation, baseUrl) {
@@ -2595,7 +2635,8 @@ var OutputGenerator = class {
2595
2635
 
2596
2636
  //#endregion
2597
2637
  //#region src/generator/SdkPackageGenerator.ts
2598
- var SdkPackageGenerator = class {
2638
+ var SdkPackageGenerator = class SdkPackageGenerator {
2639
+ static publishedPackageVersionRanges = /* @__PURE__ */ new Map();
2599
2640
  typeBuilder = new TypeBuilder();
2600
2641
  typeScriptGenerator = new TypeScriptGenerator();
2601
2642
  generate(document, options = {}) {
@@ -2824,6 +2865,7 @@ var SdkPackageGenerator = class {
2824
2865
  ].join("\n");
2825
2866
  }
2826
2867
  renderPackageJson(options) {
2868
+ const sdkKitPackageName = options.sdkKitPackageName ?? "@oapiex/sdk-kit";
2827
2869
  return JSON.stringify({
2828
2870
  name: options.packageName ?? "generated-sdk",
2829
2871
  type: "module",
@@ -2846,7 +2888,10 @@ var SdkPackageGenerator = class {
2846
2888
  "test:watch": "pnpm vitest",
2847
2889
  build: "tsdown"
2848
2890
  },
2849
- dependencies: { [options.sdkKitPackageName ?? "@oapiex/sdk-kit"]: "^0.1.1" },
2891
+ dependencies: {
2892
+ "@h3ravel/shared": this.resolvePublishedPackageVersionRange("@h3ravel/shared"),
2893
+ [sdkKitPackageName]: this.resolvePublishedPackageVersionRange(sdkKitPackageName)
2894
+ },
2850
2895
  devDependencies: {
2851
2896
  "@types/node": "^20.14.5",
2852
2897
  tsdown: "^0.20.1",
@@ -2855,6 +2900,40 @@ var SdkPackageGenerator = class {
2855
2900
  }
2856
2901
  }, null, 2);
2857
2902
  }
2903
+ /**
2904
+ * Attempts to resolve the published version range for the given package name by querying npm.
2905
+ * If the package is not found or an error occurs, it falls back to a default version range.
2906
+ *
2907
+ * @param packageName The name of the npm package to query.
2908
+ * @returns The resolved version range for the package.
2909
+ */
2910
+ resolvePublishedPackageVersionRange(packageName) {
2911
+ const cached = SdkPackageGenerator.publishedPackageVersionRanges.get(packageName);
2912
+ if (cached) return cached;
2913
+ try {
2914
+ const version = JSON.parse(execFileSync("npm", [
2915
+ "view",
2916
+ packageName,
2917
+ "version",
2918
+ "--json"
2919
+ ], {
2920
+ encoding: "utf8",
2921
+ stdio: [
2922
+ "ignore",
2923
+ "pipe",
2924
+ "ignore"
2925
+ ]
2926
+ }));
2927
+ if (typeof version === "string" && version.trim().length > 0) {
2928
+ const versionRange = `^${version.trim()}`;
2929
+ SdkPackageGenerator.publishedPackageVersionRanges.set(packageName, versionRange);
2930
+ return versionRange;
2931
+ }
2932
+ } catch {
2933
+ SdkPackageGenerator.publishedPackageVersionRanges.set(packageName, "latest");
2934
+ }
2935
+ return "latest";
2936
+ }
2858
2937
  renderReadme(manifest, options, outputMode, signatureStyle) {
2859
2938
  const packageName = options.packageName ?? "generated-sdk";
2860
2939
  const title = `# ${packageName}`;
@@ -3698,7 +3777,7 @@ var InitCommand = class extends Command {
3698
3777
  buildConfigTemplate(addSdkConfig = false) {
3699
3778
  const def = defaultConfig;
3700
3779
  return [
3701
- `import { defineConfig } from '${__filename.includes("node_modules") ? "oapiex" : "./src/Manager"}'`,
3780
+ `import { defineConfig } from '${__filename.includes("node_modules") ? "oapiex" : "./src/config"}'`,
3702
3781
  "",
3703
3782
  "/**",
3704
3783
  " * See https://toneflix.github.io/oapiex/configuration for docs",
@@ -3833,17 +3912,8 @@ async function loadUserConfig(rootDir = process.cwd()) {
3833
3912
  }
3834
3913
  async function resolveConfig(cliOverrides = {}) {
3835
3914
  const userConfig = await loadUserConfig();
3836
- return {
3837
- ...defaultConfig,
3838
- ...userConfig,
3839
- ...cliOverrides,
3840
- happyDom: {
3841
- ...defaultConfig.happyDom,
3842
- ...userConfig?.happyDom || {},
3843
- ...cliOverrides.happyDom || {}
3844
- }
3845
- };
3915
+ return mergeConfig(mergeConfig(createDefaultConfig(), userConfig ?? {}), cliOverrides);
3846
3916
  }
3847
3917
 
3848
3918
  //#endregion
3849
- export { Application, GenerateCommand, InitCommand, JsonRepair, OpenApiTransformer, OutputGenerator, ParseCommand, SdkPackageGenerator, TypeScriptGenerator, browser, buildOperationUrl, closeActiveBrowserResources, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, registerActiveBrowserCloser, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer };
3919
+ export { Application, GenerateCommand, InitCommand, JsonRepair, OpenApiTransformer, OutputGenerator, ParseCommand, SdkPackageGenerator, TypeScriptGenerator, browser, buildOperationUrl, closeActiveBrowserResources, createDefaultConfig, defaultConfig, defineConfig, endBrowserSession, escapeSelector, extractBalancedSegment, extractButtonText, extractCodeMirrorText, extractCodeSnippets, extractFetchBody, extractFetchHeaders, extractObjectPropertyValue, extractOperationDescription, extractOperationParametersFromOpenApi, extractParameterDescription, extractReadmeOperationFromHtml, extractReadmeOperationFromSsrProps, extractRequestCodeSnippets, extractRequestParams, extractRequestParamsFromOpenApi, extractRequestSnippetLabel, extractResponseBodies, extractResponseBodiesFromOpenApi, extractResponseContentTypes, extractResponseLabels, extractResponseSchemas, extractResponseSchemasFromOpenApi, extractSidebarLinkLabel, extractSidebarLinks, extractStablePageHtml, extractStringLiteralValue, findParameterRoot, flattenOpenApiSchemaProperties, getBrowserSession, globalConfig, inferParameterLocation, inferParameterLocationFromText, inferParameterPath, inferParameterType, isRecord, isRequiredParameter, isSupportedBrowser, loadUserConfig, mergeConfig, mergeReadmeOperations, mergeSsrPropsIntoRenderedHtml, normalizeCurlSnippet, normalizeFetchSnippet, normalizeRequestCodeSnippet, normalizeResponseBody, normalizeStructuredRequestBody, parseLooseStructuredValue, readInputValue, readText, readTexts, registerActiveBrowserCloser, resolveConfig, resolveOpenApiMediaExample, resolveParameterInput, resolveReadmeSidebarUrls, resolveSsrOperation, startBrowserSession, supportedBrowsers, transformer, updateConfig };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oapiex",
3
3
  "type": "module",
4
- "version": "0.3.6",
4
+ "version": "0.3.8",
5
5
  "description": "CLI and TypeScript toolkit for turning documentation pages into usable developer artifacts.",
6
6
  "main": "./dist/index.cjs",
7
7
  "private": false,