oapiex 0.3.7 → 0.3.9
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 +11 -11
- package/dist/index.cjs +43 -3
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +43 -3
- package/package.json +1 -1
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={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=()=>({...h,happyDom:{...h.happyDom},puppeteer:h.puppeteer?{...h.puppeteer,args:h.puppeteer.args?[...h.puppeteer.args]:void 0}:void 0,sdkKit:h.sdkKit?{...h.sdkKit,urls:h.sdkKit.urls?{...h.sdkKit.urls}:void 0}:void 0,sdk:h.sdk?{...h.sdk,urls:h.sdk.urls?{...h.sdk.urls}:void 0}:void 0}),_=(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}),v=[`SIGINT`,`SIGTERM`,`SIGTSTP`],y=[`axios`,`happy-dom`,`jsdom`,`puppeteer`];let b=g(),x=!1,S=!1;const C=new Set,w=()=>globalThis.__oapieBrowserSession,T=()=>{!w()&&C.size===0&&D()},E=()=>{if(!S){for(let e of v)process.on(e,k);S=!0}},D=()=>{if(S){for(let e of v)process.off(e,k);S=!1}},O=e=>(E(),C.add(e),()=>{C.delete(e),T()}),ee=async()=>{let e=Array.from(C).reverse();C.clear();for(let t of e)await t();await j()},k=async e=>{if(!x){x=!0,D();try{await ee()}catch(e){console.error(`Failed to close active browser resources:`,e)}finally{x=!1}if(e===`SIGTSTP`){process.kill(process.pid,e);return}process.exit(e===`SIGINT`?130:143)}},A=async(e=b)=>{let t=w();if(t?.browser===e.browser)return t;t&&await j();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`]})),E(),globalThis.__oapieBrowserSession=n,n},j=async()=>{let e=w();if(e){globalThis.__oapieBrowserSession=void 0;for(let t of e.closers.reverse())await t();e.puppeteerBrowser&&await e.puppeteerBrowser.close(),T()}},M=(e,t)=>{let n=w();return!n||n.browser!==e?!1:(n.closers.push(t),!0)},N=e=>y.includes(e),te=async(r,i=b,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=O(()=>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 M(`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=O(()=>t?.close());let i=t.document.documentElement.outerHTML;if(!i)throw Error(`Unable to extract HTML from remote source: ${r}`);let a=t;return M(`jsdom`,()=>a.close())||t.close(),t=void 0,i}finally{n?.(),t&&t.close()}}else if(i.browser===`puppeteer`){let e=w(),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=O(async()=>{o?.connected&&await o.close()})),c=await o.newPage(),u=O(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: ${b.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 P=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 F=e=>typeof e==`object`&&!!e&&!Array.isArray(e),I=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=ye(o),l=Le(c[0]??null),u=be(s);return ue({method:K(i.querySelector(`[data-testid="http-method"]`))?.toUpperCase()??null,url:K(i.querySelector(`[data-testid="serverurl"]`)),description:ve(i),sidebarLinks:xe(r.querySelector(`.rm-Sidebar.hub-sidebar-content`)),requestParams:Se(a),requestCodeSnippets:c,requestExample:c[0]?.body??null,requestExampleNormalized:l,responseSchemas:Ce(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=F(n)&&F(n.document)?n.document.api:null;if(!F(r))return null;let i=typeof r.method==`string`?r.method.toUpperCase():null,a=typeof r.path==`string`?r.path:null,o=F(r.schema)?r.schema:null,s=pe(o,a,i?.toLowerCase()??null),c=Array.isArray(o?.servers)&&F(o.servers[0])&&typeof o.servers[0].url==`string`?o.servers[0].url:null;if(!s&&!i&&!a)return null;let l=ge(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:R(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||!F(e.paths))return null;let r=e.paths[t];return!F(r)||!F(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?L(t):[]},L=(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(...L(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},R=e=>Object.entries(e).map(([e,t])=>({statusCode:e,description:t.description??e})),ge=e=>{let t=[];for(let[n,r]of Object.entries(e))for(let[e,i]of Object.entries(r.content??{})){let a=_e(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},_e=e=>{if(e.example!==void 0)return e.example;let t=e.examples;if(t&&F(t)){for(let e of Object.values(t))if(F(e)&&`value`in e)return e.value??null}return e.schema?.example===void 0?null:e.schema.example},ve=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)},ye=e=>{if(!e)return[];let t=Te(e);return z(e).map(e=>({label:t,body:e}))},be=e=>{if(!e)return[];let t=z(e),n=Oe(e),r=ke(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}})},xe=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:De(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):[],Se=e=>e?Array.from(e.querySelectorAll(`label`)).map(t=>{let n=K(t),r=Ae(t,e),i=je(r,t);return{name:n??``,in:Me(r,t,e),path:Ne(t,n),type:Pe(r,i),required:Fe(r,i),defaultValue:Ee(i),description:Ie(r)}}).filter(e=>e.name.length>0):[],Ce=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=>we(e)).filter(e=>!!e),we=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},
|
|
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)}`},
|
|
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(/^:/,``)}},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}`}},Y=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 Y(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(`
|
|
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)}},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`}
|
|
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:{
|
|
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(
|
|
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(!
|
|
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=
|
|
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/reference/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
|
-
`)}},
|
|
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(!
|
|
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,6 +38,7 @@ 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");
|
|
@@ -2666,7 +2667,8 @@ var OutputGenerator = class {
|
|
|
2666
2667
|
|
|
2667
2668
|
//#endregion
|
|
2668
2669
|
//#region src/generator/SdkPackageGenerator.ts
|
|
2669
|
-
var SdkPackageGenerator = class {
|
|
2670
|
+
var SdkPackageGenerator = class SdkPackageGenerator {
|
|
2671
|
+
static publishedPackageVersionRanges = /* @__PURE__ */ new Map();
|
|
2670
2672
|
typeBuilder = new TypeBuilder();
|
|
2671
2673
|
typeScriptGenerator = new TypeScriptGenerator();
|
|
2672
2674
|
generate(document, options = {}) {
|
|
@@ -2895,6 +2897,7 @@ var SdkPackageGenerator = class {
|
|
|
2895
2897
|
].join("\n");
|
|
2896
2898
|
}
|
|
2897
2899
|
renderPackageJson(options) {
|
|
2900
|
+
const sdkKitPackageName = options.sdkKitPackageName ?? "@oapiex/sdk-kit";
|
|
2898
2901
|
return JSON.stringify({
|
|
2899
2902
|
name: options.packageName ?? "generated-sdk",
|
|
2900
2903
|
type: "module",
|
|
@@ -2917,7 +2920,10 @@ var SdkPackageGenerator = class {
|
|
|
2917
2920
|
"test:watch": "pnpm vitest",
|
|
2918
2921
|
build: "tsdown"
|
|
2919
2922
|
},
|
|
2920
|
-
dependencies: {
|
|
2923
|
+
dependencies: {
|
|
2924
|
+
"@h3ravel/shared": this.resolvePublishedPackageVersionRange("@h3ravel/shared"),
|
|
2925
|
+
[sdkKitPackageName]: this.resolvePublishedPackageVersionRange(sdkKitPackageName)
|
|
2926
|
+
},
|
|
2921
2927
|
devDependencies: {
|
|
2922
2928
|
"@types/node": "^20.14.5",
|
|
2923
2929
|
tsdown: "^0.20.1",
|
|
@@ -2926,6 +2932,40 @@ var SdkPackageGenerator = class {
|
|
|
2926
2932
|
}
|
|
2927
2933
|
}, null, 2);
|
|
2928
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
|
+
}
|
|
2929
2969
|
renderReadme(manifest, options, outputMode, signatureStyle) {
|
|
2930
2970
|
const packageName = options.packageName ?? "generated-sdk";
|
|
2931
2971
|
const title = `# ${packageName}`;
|
|
@@ -3772,7 +3812,7 @@ var InitCommand = class extends _h3ravel_musket.Command {
|
|
|
3772
3812
|
`import { defineConfig } from '${__filename$1.includes("node_modules") ? "oapiex" : "./src/config"}'`,
|
|
3773
3813
|
"",
|
|
3774
3814
|
"/**",
|
|
3775
|
-
" * See https://toneflix.github.io/oapiex/configuration for docs",
|
|
3815
|
+
" * See https://toneflix.github.io/oapiex/reference/configuration for docs",
|
|
3776
3816
|
" */",
|
|
3777
3817
|
"export default defineConfig({",
|
|
3778
3818
|
` outputFormat: '${def.outputFormat}',`,
|
package/dist/index.d.ts
CHANGED
|
@@ -585,6 +585,7 @@ interface SdkPackageGeneratorOptions extends SdkNamingStrategyOptions {
|
|
|
585
585
|
sdkKitPackageName?: string;
|
|
586
586
|
}
|
|
587
587
|
declare class SdkPackageGenerator {
|
|
588
|
+
private static publishedPackageVersionRanges;
|
|
588
589
|
private typeBuilder;
|
|
589
590
|
private typeScriptGenerator;
|
|
590
591
|
generate(document: OpenApiDocumentLike, options?: SdkPackageGeneratorOptions): Record<string, string>;
|
|
@@ -607,6 +608,14 @@ declare class SdkPackageGenerator {
|
|
|
607
608
|
private renderFlatHeaders;
|
|
608
609
|
private renderCoreFile;
|
|
609
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;
|
|
610
619
|
private renderReadme;
|
|
611
620
|
private renderReadmeDescription;
|
|
612
621
|
private renderReadmeUsage;
|
package/dist/index.mjs
CHANGED
|
@@ -6,6 +6,7 @@ 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";
|
|
@@ -2634,7 +2635,8 @@ var OutputGenerator = class {
|
|
|
2634
2635
|
|
|
2635
2636
|
//#endregion
|
|
2636
2637
|
//#region src/generator/SdkPackageGenerator.ts
|
|
2637
|
-
var SdkPackageGenerator = class {
|
|
2638
|
+
var SdkPackageGenerator = class SdkPackageGenerator {
|
|
2639
|
+
static publishedPackageVersionRanges = /* @__PURE__ */ new Map();
|
|
2638
2640
|
typeBuilder = new TypeBuilder();
|
|
2639
2641
|
typeScriptGenerator = new TypeScriptGenerator();
|
|
2640
2642
|
generate(document, options = {}) {
|
|
@@ -2863,6 +2865,7 @@ var SdkPackageGenerator = class {
|
|
|
2863
2865
|
].join("\n");
|
|
2864
2866
|
}
|
|
2865
2867
|
renderPackageJson(options) {
|
|
2868
|
+
const sdkKitPackageName = options.sdkKitPackageName ?? "@oapiex/sdk-kit";
|
|
2866
2869
|
return JSON.stringify({
|
|
2867
2870
|
name: options.packageName ?? "generated-sdk",
|
|
2868
2871
|
type: "module",
|
|
@@ -2885,7 +2888,10 @@ var SdkPackageGenerator = class {
|
|
|
2885
2888
|
"test:watch": "pnpm vitest",
|
|
2886
2889
|
build: "tsdown"
|
|
2887
2890
|
},
|
|
2888
|
-
dependencies: {
|
|
2891
|
+
dependencies: {
|
|
2892
|
+
"@h3ravel/shared": this.resolvePublishedPackageVersionRange("@h3ravel/shared"),
|
|
2893
|
+
[sdkKitPackageName]: this.resolvePublishedPackageVersionRange(sdkKitPackageName)
|
|
2894
|
+
},
|
|
2889
2895
|
devDependencies: {
|
|
2890
2896
|
"@types/node": "^20.14.5",
|
|
2891
2897
|
tsdown: "^0.20.1",
|
|
@@ -2894,6 +2900,40 @@ var SdkPackageGenerator = class {
|
|
|
2894
2900
|
}
|
|
2895
2901
|
}, null, 2);
|
|
2896
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
|
+
}
|
|
2897
2937
|
renderReadme(manifest, options, outputMode, signatureStyle) {
|
|
2898
2938
|
const packageName = options.packageName ?? "generated-sdk";
|
|
2899
2939
|
const title = `# ${packageName}`;
|
|
@@ -3740,7 +3780,7 @@ var InitCommand = class extends Command {
|
|
|
3740
3780
|
`import { defineConfig } from '${__filename.includes("node_modules") ? "oapiex" : "./src/config"}'`,
|
|
3741
3781
|
"",
|
|
3742
3782
|
"/**",
|
|
3743
|
-
" * See https://toneflix.github.io/oapiex/configuration for docs",
|
|
3783
|
+
" * See https://toneflix.github.io/oapiex/reference/configuration for docs",
|
|
3744
3784
|
" */",
|
|
3745
3785
|
"export default defineConfig({",
|
|
3746
3786
|
` outputFormat: '${def.outputFormat}',`,
|
package/package.json
CHANGED