@visulima/api-platform
Version:
Visulima API platform is a set of tools to build and consume web APIs
6 lines • 12 kB
JavaScript
var child_process=require('child_process'),fs=require('fs'),oe=require('process'),path=require('@visulima/path'),d=require('chalk'),jsdocOpenApi=require('@visulima/jsdoc-open-api'),promises=require('fs/promises'),utils=require('@visulima/path/utils');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var oe__default=/*#__PURE__*/_interopDefault(oe);var d__default=/*#__PURE__*/_interopDefault(d);var ne=(e,t)=>{if(t.length===0)throw new Error("must include at least one key to map");let r=e.toString();return t.forEach(o=>{r=o.optional?r.replace("(?:\\/([^\\/]+?))?\\",`/:${o.name}?`):r.replace("(?:([^\\/]+?))",`:${o.name}`);}),r.replace("/?(?=\\/|$)/i","").replace("/^","").replaceAll("\\","").replaceAll(/\/{2,}/gu,"/")},T=ne;var ie=(e,t)=>{if(typeof e=="string")return e;if(e.fast_slash)return "";if(e.fast_star)return "*";let r="";t.length>0&&(r=T(e,t));let o=/^\/\^((?:\\[$()*+./?[\\\]^{|}]|[^$()*+./?[\\\]^{|}])*)\$\//u.exec(e.toString().replace("\\/?","").replace("(?=\\/|$)","$"));return Array.isArray(o)&&o.length>1?o[1].replaceAll(/\\(.)/gu,"$1").slice(1):r?r.slice(1):e.toString()},j=ie;var pe=(e,t,r)=>{let o=e.route.stack.at(-1),s=t.map(i=>({in:"path",name:i.name,required:!i.optional})),a=e.route.stack.filter(i=>i.handle.metadata);if(a.length>1)throw new Error("Only one metadata middleware is allowed per route");let c=(r+e.route.path).replaceAll(/\/{2,}/gu,"/");return a.length===0?{method:o.method,path:c,pathParams:s}:{metadata:a[0].handle.metadata,method:o.method,path:c,pathParams:s}},L=(e,t,r,o)=>{if(o=[...o,...r.keys],r.name==="router"&&r.handle?.stack!==void 0)for(let s of r.handle.stack)t=t||"",L(e,`${t}/${j(r.regexp,r.keys)}`,s,o);!r.route||r.route.stack.length===0||e.push(pe(r,o,t));},ce=e=>{let t=e._router||e.router,r=[];for(let o of t.stack)L(r,"",o,[]);return r},$=ce;var le=e=>{let t=[];return $(e).forEach(r=>{t.push({file:"unknown",method:r.method.toUpperCase(),path:r.path,tags:[]});}),t},N=le;var I=e=>e.replaceAll(/ \(.*\)/gu,"").trim(),C=e=>e.trim().split(" ")[1].slice(1,-1),me=e=>{let r=e.printRoutes().replaceAll(/[─│└├]/gu," ").trimEnd().split(`
`),o=r.reduce((a,c,i)=>{let p=I(c);if(I(r[i-1]??"")===p){let R=a.filter(F=>F.index<i&&F.segment===p),{methods:O}=R.at(-1);return O!==null&&O.push(C(c)),a}let l=c.replaceAll(/ \(.*\)/gu,"").match(/ /gu);if(l===null)throw new Error("Invalid spaces");let n=l.length/4,f=c.includes("("),P=f?[C(c)]:null;return a.push({depth:n,index:i,isRoute:f,methods:P,segment:p}),a},[]),s=[];return o.filter(a=>a.isRoute).forEach(a=>{let i=[...o.filter(p=>p.index<a.index&&p.depth<a.depth).filter((p,m,l)=>!l.find(n=>n.depth===p.depth&&n.index>p.index)).map(p=>p.segment),a.segment].join("");if(a.methods===null)throw new Error("Invalid methods");a.methods.forEach(p=>{s.push({file:"unknown",method:p.toUpperCase(),path:i,tags:[]});});}),s},_=me;var ue=e=>{let r=e._core.router.routes,o=[];return [...r.keys()].forEach(s=>{r.get(s).routes.forEach(a=>{o.push({file:"unknown",method:a.route.method.toUpperCase(),path:a.path,tags:[]});});}),o},K=ue;var fe=e=>{let t=[];return e.middleware.filter(r=>r.router).flatMap(r=>r.router.stack).forEach(r=>{t.push({file:"unknown",method:r.methods.join("|").toUpperCase(),path:r.path,tags:[]});}),t},M=fe;var W=/\.(js|ts|mjs|cjs)$/u,Ee=(e,t,r=false)=>{e=path.toNamespacedPath(e);let o=path.toNamespacedPath(oe.cwd()),s=[],a=jsdocOpenApi.parseFile(e,jsdocOpenApi.jsDocumentCommentsToOpenApi,r);s=[...s,...a.map(p=>p.spec)];let c=jsdocOpenApi.parseFile(e,jsdocOpenApi.swaggerJsDocumentCommentsToOpenApi,r);s=[...s,...c.map(p=>p.spec)];let i=[];return s.length===0?(fs.readFileSync(e,"utf8").split(/\r?\n/u).forEach(m=>{let l=/[=aces|]+\s["'|](GET|POST|PUT|PATCH|HEAD|DELETE|OPTIONS)["'|]/u.exec(m);if(l){let[,n]=l;n==="GET"&&(n="GET|HEAD"),i.push({file:e.replace(`${o}/`,""),method:n,path:path.toNamespacedPath(e.replace(t,"").replace(W,"")),tags:[]});}}),i.length===0&&i.push({file:e.replace(`${o}/`,""),method:"GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS",path:path.toNamespacedPath(e.replace(t,"").replace(W,"")),tags:[]}),i):(s.forEach(p=>{Object.entries(p?.paths??{}).forEach(([l,n])=>{Object.entries(n).forEach(([P,R])=>{i.push({file:e.replace(`${o}/`,""),method:P.toUpperCase(),path:path.toNamespacedPath(l),tags:R.tags});});});}),i)},H=Ee;var xe=Object.defineProperty,Se=(e,t)=>xe(e,"name",{value:t,configurable:true}),we=Object.defineProperty,Pe=Se((e,t)=>we(e,"name",{value:t,configurable:true}),"n"),J=Pe(e=>{if(!e||!(e instanceof URL)&&typeof e!="string")throw new TypeError("Path must be a non-empty string or URL.")},"assertValidFileOrDirectoryPath");var Re=Object.defineProperty,G=(e,t)=>Re(e,"name",{value:t,configurable:true}),ke=Object.defineProperty,ve=G((e,t)=>ke(e,"name",{value:t,configurable:true}),"t"),g=class extends Error{static{G(this,"i");}static{ve(this,"WalkError");}root;constructor(t,r){super(`${t instanceof Error?t.message:t} for path "${r}"`),this.cause=t,this.root=r;}get name(){return "WalkError"}set name(t){throw new Error("Cannot overwrite name of WalkError")}};var be=Object.defineProperty,B=(e,t)=>be(e,"name",{value:t,configurable:true}),Ae=Object.defineProperty,De=B((e,t)=>Ae(e,"name",{value:t,configurable:true}),"r"),k=De(e=>{let t=e.replace(/\.\*/g,".([^/]*)").replace(/\*\*/g,"(.*)").replace(/(?<!\.)\*(?!\*)/g,"([^/]*)").replace(/\?/g,"[^/]").replace(/\.(?!\*)/g,"\\.").replace(/\{/g,"(").replace(/\}/g,")").replace(/,/g,"|").replace(/\[!(.*?)\]/g,"[^$1]");return new RegExp(`^${t}$`)},"globToRegExp"),Oe=Object.defineProperty,Fe=B((e,t)=>Oe(e,"name",{value:t,configurable:true}),"n"),E=Fe((e,t,r,o)=>Array.isArray(t)&&t.length>0&&!t.some(s=>e.endsWith(s))||r&&!r.some(s=>s.test(e))?false:!o?.some(s=>s.test(e)),"walkInclude");var Te=Object.defineProperty,X=(e,t)=>Te(e,"name",{value:t,configurable:true}),Me=Object.defineProperty,y=X((e,t)=>Me(e,"name",{value:t,configurable:true}),"r"),Ue=y(async e=>{let t=path.normalize(e),r=path.basename(t),o=await promises.stat(t);return {isDirectory:y(()=>o.isDirectory(),"isDirectory"),isFile:y(()=>o.isFile(),"isFile"),isSymbolicLink:y(()=>o.isSymbolicLink(),"isSymbolicLink"),name:r,path:t}},"_createWalkEntry");async function*x(e,{extensions:t,followSymlinks:r=false,includeDirs:o=true,includeFiles:s=true,includeSymlinks:a=true,match:c,maxDepth:i=Number.POSITIVE_INFINITY,skip:p}={}){if(J(e),i<0)return;let m=c?c.map(n=>typeof n=="string"?k(n):n):void 0,l=p?p.map(n=>typeof n=="string"?k(n):n):void 0;if(e=path.resolve(utils.toPath(e)),o&&E(e,t,m,l)&&(yield await Ue(e)),!(i<1||!E(e,void 0,void 0,l)))try{for await(let n of await promises.readdir(e,{withFileTypes:!0})){let f=path.join(e,n.name);if(n.isSymbolicLink())if(r)f=await promises.realpath(f);else if(a&&E(f,t,m,l))yield {isDirectory:n.isDirectory,isFile:n.isFile,isSymbolicLink:n.isSymbolicLink,name:n.name,path:f};else continue;n.isSymbolicLink()||n.isDirectory()?yield*x(f,{extensions:t,followSymlinks:r,includeDirs:o,includeFiles:s,includeSymlinks:a,match:m,maxDepth:i-1,skip:l}):n.isFile()&&s&&E(f,t,m,l)&&(yield {isDirectory:y(()=>n.isDirectory(),"isDirectory"),isFile:y(()=>n.isFile(),"isFile"),isSymbolicLink:y(()=>n.isSymbolicLink(),"isSymbolicLink"),name:n.name,path:f});}}catch(n){throw n instanceof g?n:new g(n,e)}}X(x,"d");y(x,"walk");var We=Object.defineProperty,He=(e,t)=>We(e,"name",{value:t,configurable:true}),Je=Object.defineProperty,Ge=He((e,t)=>Je(e,"name",{value:t,configurable:true}),"e"),v=Ge(async(e,t={})=>{Array.isArray(t.extensions)||(t.extensions=["js","mjs","cjs","ts"]);let r=[];for await(let o of x(e,t))r.push(o.path);return r},"collect");var w=[".js",".ts",".mjs",".cjs"],Y=e=>{let t=path.parse(e);for(;t.base&&t.root!==t.dir;){if(fs.readdirSync(t.dir).find(s=>s==="package.json"))return t.dir;t=path.parse(t.dir);}return null},z=e=>{let t=`${e}/package.json`,{dependencies:r}=JSON.parse(fs.readFileSync(t).toString());return r?.express?"express":r?.koa&&(r["@koa/router"]||r["koa-router"])?"koa":r?.next?"next":r?.["@hapi/hapi"]?"hapi":r?.fastify?"fastify":null},V=(e,t)=>Object.keys(e).length===0?null:t==="hapi"?typeof e.app.app=="string"?e.app:e:e.app??e;var Z=e=>{try{return fs.statSync(e).isDirectory()}catch{return false}},Ye=async(e="")=>{let t=path.join(e,"pages/api");return !Z(t)&&(t=path.join(e,"src/pages/api"),!Z(t))?[]:v(t,{extensions:w,includeDirs:false})},ee=Ye;var b=async(e,t,r)=>{if(t==="express")return N(e);if(t==="koa")return M(e);if(t==="hapi")return K(e);if(t==="fastify")return _(e);if(t==="next"){let o=await ee(e);if(o.length===0)throw new Error(`No API routes found, in "${e}".`);return o.flatMap(s=>H(s,e,r))}return null};var ze=(e,t)=>{let r=new Map;return e.forEach(o=>{let s=t(o),a=r.get(s);a?a.push(o):r.set(s,[o]);}),r},te=ze;var Ve=(e,t)=>{let r={ANY:d__default.default.redBright,DELETE:d__default.default.redBright,GET:d__default.default.blue,HEAD:d__default.default.hex("#6C7280"),OPTIONS:d__default.default.hex("#6C7280"),PATCH:d__default.default.yellow,POST:d__default.default.yellow,PUT:d__default.default.yellow},o;if(e==="GET|HEAD")o=`${d__default.default.blue("GET")}${d__default.default.grey("|HEAD")}`;else {let m=r[e](e);o=e==="GET"?`${m}${d__default.default.grey("|HEAD")}`:m;}let s=e==="GET"?6:14-e.length,a=Array.from({length:s}).fill(" ").join(""),c=process.stdout.columns-16-t.length-4,i=c>0?Array.from({length:c}).fill(".").join(""):"",p=t.split("/").map(m=>[":","["].includes(m[0]??"")?d__default.default.yellowBright(m):m).join("/");return ` ${o}${a}${p}${d__default.default.grey(i)}`},Qe=(e,t={})=>e.map(r=>{if(!(Array.isArray(t.methods)&&t.methods.includes(r.method)))return r.method==="GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS"&&(r.method="ANY"),Ve(r.method,r.path.replace("/pages",""))}).filter(Boolean),A=Qe;var tt=async(e,t,r={})=>{let o=path.join(oe__default.default.cwd(),t);if(!fs.existsSync(o))throw new Error("No such file, invalid path provided.");let s=Y(o);if(!s)throw new Error("Please initialize local package.json.");if(e===void 0){let c=z(s);if(!c)throw new Error("Couldn't detect supported back-end framework.");e=c;}let a=null;if(e==="next")a=await b(o,"next",r.verbose??false);else {if(!fs.statSync(o).isFile())throw new Error(`${o} is directory, but file expected.`);if(!w.includes(path.extname(o)))throw new Error("Please specify application .ts/.js/.mjs/.cjs file.");let c=`${s}/.env`;fs.existsSync(c)&&(await import(`${s}/node_modules/dotenv/lib/main.js`)).config({path:c});let i=path.extname(o)===".ts",p=path.join(s,"node_modules/.bin/tsc");if(i&&!fs.existsSync(p))throw new Error(`Please install typescript in ${s}`);try{if(i)try{child_process.execSync(`${p} --outDir framework-list >&2`,{cwd:s});}catch(n){console.log(`TSC compilation failed. Please resolve issues in your project.
`),console.log(n),fs.rmSync(path.join(s,"framework-list"),{recursive:!0});}let m=i?path.join(s,"framework-list",o.replace(s,"").replace(".ts",".js")):o,{default:l}=await import(m);a=await b(["AsyncFunction","Function"].includes(l.constructor.name)?await l():V(l,e),e,r.verbose??!1);}finally{i&&fs.rmSync(path.join(s,"framework-list"),{recursive:true});}}if(a===null)throw new Error(`Framework "${e}" is not supported.`);if(Array.isArray(r.includePaths)&&r.includePaths.length>0&&(a=r.includePaths.flatMap(c=>a.filter(i=>i.path.startsWith(c)))),Array.isArray(r.excludePaths)&&r.excludePaths.length>0&&(a=r.excludePaths.flatMap(c=>a.filter(i=>!i.path.startsWith(c)))),typeof r.group=="string"&&r.group!==""){console.log();let c=te(a,p=>r.group==="path"?p.path.replace("/pages","").split("/")[1]:p.tags[0]??"unsorted"),i=0;c.forEach((p,m)=>{i>0&&console.log();let l=(oe__default.default.stdout.columns-16-m.length)/2,n=l>0?Array.from({length:l}).fill(" ").join(""):"";console.log(n+d__default.default.bold.underline(m)),A(p,r).forEach(f=>{console.log(f);}),i+=1;});}else console.log(),A(a,r).forEach(c=>{console.log(c);});console.log(`
Listed ${d__default.default.greenBright(String(a.length))} HTTP ${a.length===1?"route":"routes"}.
`);},Rr=tt;exports.a=Rr;//# sourceMappingURL=chunk-Y63T5JGD.js.map
//# sourceMappingURL=chunk-Y63T5JGD.js.map
;