@vulppi/intrest
Version:
Backend kit make by Vulppi
7 lines (6 loc) • 14.7 kB
JavaScript
import Q from"chalk";import{existsSync as Ye,mkdirSync as Ze,rmSync as qe}from"fs";import{createServer as et}from"http";import{join as tt}from"path";var $=()=>process.env.NODE_ENV==="development",E={env:[".env",".env{.local,.development,.production}"],entryFolder:["routes","src/routes"],assetsFolder:["assets","src/assets"],staticFolder:["static","src/static","public","src/public"],configFile:"intrest.config.{mjs,cjs,js}",envFile:".env{.local,.development,.production}",bootstrapEntry:"bootstrap.ts",bootstrapCompiled:"bootstrap.mjs",entryPoints:"**/{route,middleware,validation}.ts",identityPoints:"**/__identity.mjs",middlewarePoints:"**/middleware.mjs",routeFile:"route.{mjs,cjs,js,ts}",middlewareFile:"middleware.{mjs,cjs,js,ts}"},I={env:/^\.env(?:\.[a-z-_]*)?$/,config:/^intrest\.config\.[mc]?js$/,bootstrap:/^bootstrap\.ts$/,entry:/(?:^|\/)(?:route|middleware|validation)\.ts$/,observable:/(?:route)\.ts$/,reservedChars:/(?:[.*+?^=!:${}()|\[\]\/\\])/g,startSlashesOrNot:/^[\\\/]*/,endSlashesOrNot:/[\\\/]*$/,multiSlashes:/[\\\/]+/g,isBusboyContentType:/^(?:x-www-form-urlencoded|multipart\/form-data.*)$/i,isJSONContentType:/^application\/json$/i,isXMLContentType:/^application\/xml$/i,isAcceptableContentType:/^(?:x-www-form-urlencoded|multipart\/form-data.*|application\/(?:json|xml))$/i},b={compiledFolder:".intrest",compiledRoutes:"routes",workerMultiWorker:"multi.mjs",workerSingleWorker:"single.mjs",workerRouter:"router.mjs",routeIdentity:"__identity.mjs"};import{glob as V}from"glob";import{join as G,normalize as xe}from"path";import{pathToFileURL as Ce}from"url";function f(e){return xe(e).replace(/[\/\\]+/g,"/")}async function _(e){if(!e)return{};let n=Ce(e);n.searchParams.set("update",Date.now().toString());try{return await import(n.toString()).then(o=>o)||{}}catch{return{}}}async function v(...e){let n=await V(f(G(...e)),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0});return n[0]&&f(n[0])}async function L(...e){return(await V(f(G(...e)),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0})).map(f)}async function Oe(...e){let n=e.map(t=>f(G(...t)));return(await V(n.reverse(),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0})).map(f)}async function ee(e,n){return(await Oe(...n.map(o=>[e,o])))[0]||n[1]}function k(e){return $()?`${e}?update=${Date.now()}`:e}import $e from"busboy";import z from"chalk";import _e from"concat-stream";import W from"cookie";import{randomUUID as je}from"crypto";import{XMLParser as De,XMLValidator as Fe}from"fast-xml-parser";import{createWriteStream as Ie,rmSync as Le}from"fs";import{StatusCodes as A,getReasonPhrase as ke}from"http-status-codes";import ne from"lodash";import{join as ae}from"path";import{performance as ie}from"perf_hooks";import{createDeflate as mt,createGunzip as ut,createGzip as ft,createInflate as gt,deflate as ht,gunzip as ve,gzip as yt,inflate as Ne}from"zlib";function te(e){if(typeof e!="string")return e;let[,n,o]=e.match(/^(\d+)([kmgt]b?)$/i)||[];if(!n||!o)return 0;let t=parseInt(n);if(isNaN(t))return 0;switch(o.toLowerCase()){case"tb":return t*1024*1024*1024*1024;case"gb":return t*1024*1024*1024;case"mb":return t*1024*1024;case"kb":return t*1024;default:return t}}function oe(e){switch(!0){case e==null:return;case/^(no|n|false|f|off)$/i.test(e):return!1;case/^(yes|y|true|t|on)$/i.test(e):return!0;case!isNaN(parseFloat(e)):return parseFloat(e);default:return e}}async function re(e,n=["identity"]){let o=e;for(let t of n)/^gzip$/i.test(t)?o=await new Promise((a,d)=>{ve(o,(r,c)=>{if(r)return d(r);a(c)})}):/^deflate$/i.test(t)&&(o=await new Promise((a,d)=>{Ne(o,(r,c)=>{if(r)return d(r);a(c)})}));return o}import se from"ms";function j(e,n,o,t=200){console.debug("%s(%s - %s) - %s %s",z.yellow(n),z.green(t),ke(t),z.bold(o),z.cyan(`${(ie.now()-e).toPrecision(5)}ms`))}function ce(e){return async function(o,t){let a=process.cwd(),d=await v(a,E.configFile),r=(await _(d)).default||{},c=f(ae(a,r.paths?.uploadTemp||".tmp")),i=o.method?.toUpperCase()||"GET",[s,l]=(o.url||"/").split("?"),u=decodeURIComponent(s),h=l||"",x=o.headers["content-type"]||"application/json",R=o.headers.origin||o.headers.host||"",C=o.socket.remoteAddress,S=R.replace(/^[a-z]+:\/\//,""),T=/^[a-z]+:\/\//.test(R)?R:R.includes("localhost")||$()?`http://${R||"localhost"}`:R?`https://${R}`:"*";if(r.limits?.allowOrigin&&!$()){let w=(Array.isArray(r.limits.allowOrigin)?r.limits.allowOrigin:[r.limits.allowOrigin]).map(p=>p.replace(/^[a-z]+:\/\//,"")).find(p=>S.endsWith(p));w?t.setHeader("Access-Control-Allow-Origin",w):t.setHeader("Access-Control-Allow-Origin","*")}else t.setHeader("Access-Control-Allow-Origin",T);t.setHeader("Server","IntREST"),t.setHeader("Accept",["application/json","application/xml","x-www-form-urlencoded","multipart/form-data"]),t.setHeader("Accept-Encoding",["gzip","x-gzip","deflate","identity"]),t.setHeader("Access-Control-Allow-Methods",["GET","POST","PUT","PATCH","DELETE","OPTIONS"]),t.setHeader("Access-Control-Allow-Headers",["Content-Length","Content-Type","Authorization","Range","*",...r.limits?.allowHeaders||[]]),t.setHeader("Access-Control-Allow-Credentials","true"),t.setHeader("Access-Control-Max-Age","86400"),t.setHeader("Accept-Ranges","bytes"),t.setHeader("Connection","keep-alive"),t.setHeader("Keep-Alive",["timeout=5","max=30"]);let y=ie.now();if(/^options$/i.test(i)){t.statusCode=A.NO_CONTENT,t.end();return}if(!I.isAcceptableContentType.test(x))return t.writeHead(A.UNSUPPORTED_MEDIA_TYPE,{"Content-Type":"application/json"}),j(y,i,u,A.UNSUPPORTED_MEDIA_TYPE),t.end(JSON.stringify({message:r.messages?.UNSUPPORTED_MEDIA_TYPE||"Unsupported media type"}));let O={},he=o.headers["content-length"]&&parseInt(o.headers["content-length"])||0,ye=te(r.limits?.bodyMaxSize||"10mb");if(he>ye)return t.writeHead(A.REQUEST_TOO_LONG,{"Content-Type":"application/json"}),j(y,i,u,A.REQUEST_TOO_LONG),t.end(JSON.stringify({message:r.messages?.REQUEST_TOO_LONG||"Request entity too large"}));let U=[];if(!/^get$/i.test(i))try{if(I.isBusboyContentType.test(x))await new Promise((g,w)=>{let p=$e({headers:o.headers});p.on("file",(m,P,Re)=>{let{filename:Te,encoding:Pe,mimeType:be}=Re,Ee=je(),B=f(ae(c,Ee)),Se={absolutePath:B,filename:Te,encoding:Pe,mimetype:be};ne.set(O,m,Se),U.push(B);let Ae=Ie(B,{flags:"w"});P.pipe(Ae,{end:!0})}),p.on("field",(m,P)=>{ne.set(O,m,oe(P))}),p.on("close",g),p.on("error",w),o.pipe(p,{end:!0})});else{let g=await new Promise(m=>{let P=_e(m);o.pipe(P)}),w=o.headers["content-encoding"]||"identity",p=(await re(g,w.split(/, */))).toString()||"{}";if(I.isJSONContentType.test(x))O=JSON.parse(p);else{let m=new De({ignoreAttributes:!1,allowBooleanAttributes:!0,attributeNamePrefix:"",attributesGroupName:"$attributes",commentPropName:"$comment",cdataPropName:"$cdata",textNodeName:"$text",alwaysCreateTextNode:!0,parseTagValue:!0,unpairedTags:["meta","link","img","br","hr","input"]});if(!Fe.validate(p))throw new Error("Invalid XML");O=m.parse(p)}}}catch(g){return t.writeHead(A.BAD_REQUEST,{"Content-Type":"application/json"}),j(y,i,u,A.BAD_REQUEST),t.end(JSON.stringify({message:"Invalid body",error:g.message||g.toString()}))}let we=W.parse(o.headers.cookie||"");try{await e({basePath:a,config:r,data:{method:i,path:u,custom:{},headers:o.headers,cookies:we,body:O,query:h,origin:{url:T==="*"?void 0:new URL(T),ip:C}}},(g,w)=>{if(g==="cookie"){let{name:p,value:m,options:P}=w;P?.maxAge&&typeof P?.maxAge=="string"&&(P.maxAge=se(P.maxAge)),t.appendHeader("Set-Cookie",W.serialize(p,m,P))}else if(g==="clear-cookie"){let{name:p,options:m}=w;m?.maxAge&&typeof m?.maxAge=="string"&&(m.maxAge=se(m.maxAge)),t.appendHeader("Set-Cookie",W.serialize(p,"",m))}else if(g==="set"){let[p,m]=w;t.setHeader(p,m||"")}else if(g==="write"){let p=w;t.write(p)}else if(g==="status")t.statusCode=w;else if(g==="end"){if(U.length&&r.removeUploadFilesAfterResponse)for(let p of U)try{Le(p)}catch(m){console.error(`Error removing file ${p}`,m.message)}j(y,i,u,t.statusCode),t.end()}})}catch(g){return console.error(g),t.writeHead(A.INTERNAL_SERVER_ERROR,{"Content-Type":"application/json"}),j(y,i,u,A.INTERNAL_SERVER_ERROR),t.end(JSON.stringify({message:r.messages?.INTERNAL_SERVER_ERROR||"Internal server error"}))}}}import{createReadStream as Ge}from"fs";import{StatusCodes as D}from"http-status-codes";import me from"lodash";import{lookup as We}from"mime-types";import{join as F}from"path";import{unescape as Je}from"querystring";import{pathToFileURL as K}from"url";import{StatusCodes as J}from"http-status-codes";import pe from"lodash";import Be from"range-parser";import{Readable as Ve}from"stream";import{isAnyArrayBuffer as ze,isUint16Array as He,isUint32Array as Me,isUint8Array as Ue}from"util/types";function le(e){return!!(ze(e)||Ue(e)||He(e)||Me(e))}function H(e){return!!(e&&Array.isArray(e)&&e.length&&e.type==="bytes")}async function de(e,n,o,t){let a=Object.keys(e.headers||{}).find(s=>/^content-length$/i.test(s)),d=Object.keys(e.headers||{}).find(s=>/^content-type$/i.test(s)),r=pe.get(e.headers||{},a||"Content-Length",1/0),c=pe.get(e.headers||{},d||"Content-Type"),i=n.range?Be(+r,n.range,{combine:!0}):void 0;H(i)&&(e.status=!e.status||e.status===J.OK?J.PARTIAL_CONTENT:e.status,e.headers={...e.headers,"Content-Range":`bytes ${i[0].start}-${i[0].end}`+(r&&isFinite(+r)?`/${r}`:"")},delete e.headers[a||"Content-Length"]);for(let s of Object.entries(e.headers||{}))t({requestId:o,state:"set",data:s});for(let[s,l]of Object.entries(e.cookies||{}))if(Array.isArray(l))for(let u of l)t({requestId:o,state:"cookie",data:{name:s,value:u.value,options:u.options}});else t({requestId:o,state:"cookie",data:{name:s,value:l.value,options:l.options}});for(let[s,l]of Object.entries(e.clearCookies||{}))if(Array.isArray(l))for(let u of l)t({requestId:o,state:"clear-cookie",data:{name:s,options:u}});else t({requestId:o,state:"clear-cookie",data:{name:s,options:l}});if(t({requestId:o,state:"status",data:e.status||J.OK}),e.body)if(typeof e.body=="string"||le(e.body)){c||t({requestId:o,state:"set",data:["Content-Type","text/plain"]});let s=Buffer.from(e.body);H(i)?t({requestId:o,state:"write",data:s.subarray(i[0].start,i[0].end+1)}):t({requestId:o,state:"write",data:s})}else if(e.body instanceof Ve){c||t({requestId:o,state:"set",data:["Content-Type","application/octet-stream"]});let s=e.body;if(H(i)){let l=i[0].start,u=i[0].end,h=0;await new Promise((x,R)=>{s.on("data",C=>{let S=Buffer.from(C);if(S.length+h<l){h+=S.length;return}if(h>u)return s.destroy(),x();let T=Math.max(l-h,0),y=Math.min(u+1-h,S.length);h+=y;let O=S.subarray(T,T+y);t({requestId:o,state:"write",data:O})}),s.on("end",()=>{x()}),s.on("error",C=>{R(C)})})}else await new Promise((l,u)=>{s.on("data",h=>{t({requestId:o,state:"write",data:h})}),s.on("end",()=>{l()}),s.on("error",h=>{u(h)})})}else{c||t({requestId:o,state:"set",data:["Content-Type","application/json"]});let s=JSON.stringify(e.body),l=Buffer.from(s);H(i)?t({requestId:o,state:"write",data:l.subarray(i[0].start,i[0].end+1)}):t({requestId:o,state:"write",data:l})}t({requestId:o,state:"end",data:void 0})}async function ue({data:e,config:n,basePath:o},t){let a={...e,params:{},query:new URLSearchParams(e.query||"")},d=await ee(o,E.staticFolder);if(d){let r=await v(d,a.path);if(r){let c=We(r);if(c)return await N({status:D.OK,body:Ge(r),headers:{"Content-Type":c}},a.headers,t)}}try{let r=await Ke(a.path);if(!r.length)return await N({status:D.NOT_FOUND,body:{message:n.messages?.NOT_FOUND||"Not found"},headers:{"Content-Type":"application/json"}},a.headers,t);let c=a.method,i=f(F(b.compiledFolder,b.compiledRoutes)),l=(await Promise.all(r.map(async T=>{let y=await import(k(K(f(F(i,T.pathname,"route.mjs"))).toString()));return{handler:y[c]||y.ALL||y.default,identity:T}}))).find(T=>typeof T.handler=="function");if(!l?.handler)return await N({status:D.METHOD_NOT_ALLOWED,body:{message:n.messages?.METHOD_NOT_ALLOWED||"Method not allowed"},headers:{"Content-Type":"application/json"}},a.headers,t);let u=l.identity.paramExtract,h=l.identity.pathname,x=l.identity.paramKeys,R=Array.from(e.path.match(u)||[]).slice(1);a.params=me.zipObject(x,R.map(Je));let C=await Qe(h),S=await fe({middlewares:C,context:a,config:n,requestHandler:l.handler});if(!S)throw new Error("Response not found");return await N(S,a.headers,t)}catch(r){if(console.error(r),r instanceof Error)return await N({status:D.INTERNAL_SERVER_ERROR,body:{message:r.message},headers:{"Content-Type":"application/json"}},a.headers,t);if(typeof r=="object"&&r!=null)return await N(r,a.headers,t);throw r}}async function N(e,n,o){return await de(e,n,"void",t=>{let{state:a,data:d}=t;o(a,d)})}async function Ke(e){let n=f(F(process.cwd(),b.compiledFolder,b.compiledRoutes)),o=await L(n,E.identityPoints);return(await Promise.all(o.map(a=>import(k(K(a).toString())).then(d=>d)))).filter(a=>a.paramExtract.test(e)).sort((a,d)=>a.pathname>d.pathname?1:-1).sort(Xe)}async function Qe(e){let n=f(F(process.cwd(),b.compiledFolder,b.compiledRoutes)),o=e.split("/").map((r,c,i)=>c>0?i.slice(0,c+1).join("/"):"/").map(r=>f(F(n,r,"middleware.mjs"))),a=(await L(n,E.middlewarePoints)).filter(r=>o.some(c=>r===c));return(await Promise.all(a.map(async r=>({handler:await import(k(K(r).toString())).then(c=>c.middleware||c.default),pathname:r.replace(n,"")})))).filter(r=>typeof r.handler=="function")}function Xe(e,n){let o=e.pathname.split("/"),t=n.pathname.split("/");for(let a=0;a<o.length;a++)if(!(o[a][0]==="["&&t[a]?.[0]==="[")){if(o[a][0]==="[")return 1;if(t[a]?.[0]==="[")return-1}return n.route.toLowerCase()>e.route.toLowerCase()?-1:n.route.toLowerCase()<e.route.toLowerCase()?1:0}async function fe({middlewares:e,context:n,config:o,requestHandler:t}){if(!e.length)return await t(n)||{status:D.NOT_FOUND};let a=e[0],d=setTimeout(()=>{throw new Error(`Middleware handler timeout: ${a.pathname}`)},o.limits?.middleware?.timeout||5e3),r=await a.handler(n,async c=>(clearTimeout(d),n.custom=me.merge(n.custom,c),fe({middlewares:e.slice(1),context:n,config:o,requestHandler:t})));return clearTimeout(d),r}var Z=process.cwd(),ot=await v(Z,E.configFile),q=(await _(ot)).default||{},rt=await v(Z,b.compiledFolder,b.compiledRoutes,E.bootstrapCompiled),ge=await _(rt),X=ge.bootstrap||ge.default;X&&typeof X=="function"&&(console.log(`
Bootstrapping...
`),await X(q));var M=q.port||+(process.env.PORT||4e3),Y=f(tt(Z,q.paths?.uploadTemp||".tmp"));Ye(Y)&&qe(Y,{recursive:!0});Ze(Y,{recursive:!0});var nt=et({noDelay:!0,keepAlive:!0,keepAliveTimeout:3e4,keepAliveInitialDelay:5e3,connectionsCheckingInterval:5e3},ce(ue));nt.listen(M,()=>{console.log(`
Server running on port %s`,Q.yellow(M)),console.log(` You can access the server at %s or %s
`,Q.yellow(`http://localhost:${M}`),Q.yellow(`http://127.0.0.1:${M}`))});
//# sourceMappingURL=v1-single.mjs.map