@vulppi/intrest
Version:
Backend kit make by Vulppi
7 lines (6 loc) • 9.71 kB
JavaScript
import U from"chalk";import{existsSync as Oe,mkdirSync as Ne,rmSync as Ce}from"fs";import{createServer as $e}from"http";import{join as De}from"path";var O=()=>process.env.NODE_ENV==="development",b={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}"},N={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},P={compiledFolder:".intrest",compiledRoutes:"routes",workerMultiWorker:"multi.mjs",workerSingleWorker:"single.mjs",workerRouter:"router.mjs",routeIdentity:"__identity.mjs"};import{randomUUID as he}from"crypto";import{Worker as W}from"worker_threads";import{join as Re}from"path";import{glob as fe}from"glob";import{join as ge,normalize as we}from"path";import{pathToFileURL as ye}from"url";function w(o){return we(o).replace(/[\/\\]+/g,"/")}async function x(o){if(!o)return{};let c=ye(o);c.searchParams.set("update",Date.now().toString());try{return await import(c.toString()).then(t=>t)||{}}catch{return{}}}async function k(...o){let c=await fe(w(ge(...o)),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0});return c[0]&&w(c[0])}function G(o){return new URL(w(Re(".",o)),import.meta.url)}var C=new Map;async function V(o){for(let c=0;c<o;c++){let t=new W(G(P.workerRouter),{env:process.env});t.setMaxListeners(1/0),C.set(t.threadId,{weight:0,worker:t,workerId:t.threadId})}}async function J({basePath:o,data:c,config:t},e){return new Promise((f,h)=>{let s=he(),g=Array.from(C.values()),i=g.find(r=>r.weight===0),p,A;if(!i&&g.length<(t.limits?.maxWorkerPoolSize||20)){let r=new W(G(P.workerRouter),{env:process.env});r.setMaxListeners(1/0),i={weight:0,worker:r,workerId:r.threadId},C.set(r.threadId,i)}else i||(i=g.reduce((r,I)=>r.weight<I.weight?r:I));i.weight++,p=i.worker,A=i.workerId;let d=r=>{C.delete(A),p.off("exit",d),h(new Error(`Worker stopped with exit code ${r}`))};p.once("exit",d);let T=r=>{h(r),i&&i.weight--,p.off("error",T),p.off("exit",d)};p.once("error",T);let R=r=>{r.requestId===s&&(e(r.state,r.data),r.state==="end"&&(i&&i.weight--,p.off("message",R),p.off("error",T),p.off("exit",d),f()))};p.on("message",R),p.postMessage({data:c,basePath:o,config:t,requestId:s})})}import Te from"busboy";import $ from"chalk";import Ee from"concat-stream";import H from"cookie";import{randomUUID as Se}from"crypto";import{XMLParser as xe,XMLValidator as ke}from"fast-xml-parser";import{createWriteStream as ve,rmSync as Ae}from"fs";import{StatusCodes as y,getReasonPhrase as Ie}from"http-status-codes";import Y from"lodash";import{join as K}from"path";import{performance as ee}from"perf_hooks";import{createDeflate as Ye,createGunzip as Ke,createGzip as Ze,createInflate as et,deflate as tt,gunzip as be,gzip as ot,inflate as Pe}from"zlib";function Q(o){if(typeof o!="string")return o;let[,c,t]=o.match(/^(\d+)([kmgt]b?)$/i)||[];if(!c||!t)return 0;let e=parseInt(c);if(isNaN(e))return 0;switch(t.toLowerCase()){case"tb":return e*1024*1024*1024*1024;case"gb":return e*1024*1024*1024;case"mb":return e*1024*1024;case"kb":return e*1024;default:return e}}function q(o){switch(!0){case o==null:return;case/^(no|n|false|f|off)$/i.test(o):return!1;case/^(yes|y|true|t|on)$/i.test(o):return!0;case!isNaN(parseFloat(o)):return parseFloat(o);default:return o}}async function X(o,c=["identity"]){let t=o;for(let e of c)/^gzip$/i.test(e)?t=await new Promise((f,h)=>{be(t,(s,g)=>{if(s)return h(s);f(g)})}):/^deflate$/i.test(e)&&(t=await new Promise((f,h)=>{Pe(t,(s,g)=>{if(s)return h(s);f(g)})}));return t}import Z from"ms";function v(o,c,t,e=200){console.debug("%s(%s - %s) - %s %s",$.yellow(c),$.green(e),Ie(e),$.bold(t),$.cyan(`${(ee.now()-o).toPrecision(5)}ms`))}function te(o){return async function(t,e){let f=process.cwd(),h=await k(f,b.configFile),s=(await x(h)).default||{},g=w(K(f,s.paths?.uploadTemp||".tmp")),i=t.method?.toUpperCase()||"GET",[p,A]=(t.url||"/").split("?"),d=decodeURIComponent(p),T=A||"",R=t.headers["content-type"]||"application/json",r=t.headers.origin||t.headers.host||"",I=t.socket.remoteAddress,re=r.replace(/^[a-z]+:\/\//,""),z=/^[a-z]+:\/\//.test(r)?r:r.includes("localhost")||O()?`http://${r||"localhost"}`:r?`https://${r}`:"*";if(s.limits?.allowOrigin&&!O()){let m=(Array.isArray(s.limits.allowOrigin)?s.limits.allowOrigin:[s.limits.allowOrigin]).map(n=>n.replace(/^[a-z]+:\/\//,"")).find(n=>re.endsWith(n));m?e.setHeader("Access-Control-Allow-Origin",m):e.setHeader("Access-Control-Allow-Origin","*")}else e.setHeader("Access-Control-Allow-Origin",z);e.setHeader("Server","IntREST"),e.setHeader("Accept",["application/json","application/xml","x-www-form-urlencoded","multipart/form-data"]),e.setHeader("Accept-Encoding",["gzip","x-gzip","deflate","identity"]),e.setHeader("Access-Control-Allow-Methods",["GET","POST","PUT","PATCH","DELETE","OPTIONS"]),e.setHeader("Access-Control-Allow-Headers",["Content-Length","Content-Type","Authorization","Range","*",...s.limits?.allowHeaders||[]]),e.setHeader("Access-Control-Allow-Credentials","true"),e.setHeader("Access-Control-Max-Age","86400"),e.setHeader("Accept-Ranges","bytes"),e.setHeader("Connection","keep-alive"),e.setHeader("Keep-Alive",["timeout=5","max=30"]);let E=ee.now();if(/^options$/i.test(i)){e.statusCode=y.NO_CONTENT,e.end();return}if(!N.isAcceptableContentType.test(R))return e.writeHead(y.UNSUPPORTED_MEDIA_TYPE,{"Content-Type":"application/json"}),v(E,i,d,y.UNSUPPORTED_MEDIA_TYPE),e.end(JSON.stringify({message:s.messages?.UNSUPPORTED_MEDIA_TYPE||"Unsupported media type"}));let S={},ne=t.headers["content-length"]&&parseInt(t.headers["content-length"])||0,se=Q(s.limits?.bodyMaxSize||"10mb");if(ne>se)return e.writeHead(y.REQUEST_TOO_LONG,{"Content-Type":"application/json"}),v(E,i,d,y.REQUEST_TOO_LONG),e.end(JSON.stringify({message:s.messages?.REQUEST_TOO_LONG||"Request entity too large"}));let M=[];if(!/^get$/i.test(i))try{if(N.isBusboyContentType.test(R))await new Promise((l,m)=>{let n=Te({headers:t.headers});n.on("file",(a,u,ae)=>{let{filename:ce,encoding:le,mimeType:pe}=ae,me=Se(),j=w(K(g,me)),de={absolutePath:j,filename:ce,encoding:le,mimetype:pe};Y.set(S,a,de),M.push(j);let ue=ve(j,{flags:"w"});u.pipe(ue,{end:!0})}),n.on("field",(a,u)=>{Y.set(S,a,q(u))}),n.on("close",l),n.on("error",m),t.pipe(n,{end:!0})});else{let l=await new Promise(a=>{let u=Ee(a);t.pipe(u)}),m=t.headers["content-encoding"]||"identity",n=(await X(l,m.split(/, */))).toString()||"{}";if(N.isJSONContentType.test(R))S=JSON.parse(n);else{let a=new xe({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(!ke.validate(n))throw new Error("Invalid XML");S=a.parse(n)}}}catch(l){return e.writeHead(y.BAD_REQUEST,{"Content-Type":"application/json"}),v(E,i,d,y.BAD_REQUEST),e.end(JSON.stringify({message:"Invalid body",error:l.message||l.toString()}))}let ie=H.parse(t.headers.cookie||"");try{await o({basePath:f,config:s,data:{method:i,path:d,custom:{},headers:t.headers,cookies:ie,body:S,query:T,origin:{url:z==="*"?void 0:new URL(z),ip:I}}},(l,m)=>{if(l==="cookie"){let{name:n,value:a,options:u}=m;u?.maxAge&&typeof u?.maxAge=="string"&&(u.maxAge=Z(u.maxAge)),e.appendHeader("Set-Cookie",H.serialize(n,a,u))}else if(l==="clear-cookie"){let{name:n,options:a}=m;a?.maxAge&&typeof a?.maxAge=="string"&&(a.maxAge=Z(a.maxAge)),e.appendHeader("Set-Cookie",H.serialize(n,"",a))}else if(l==="set"){let[n,a]=m;e.setHeader(n,a||"")}else if(l==="write"){let n=m;e.write(n)}else if(l==="status")e.statusCode=m;else if(l==="end"){if(M.length&&s.removeUploadFilesAfterResponse)for(let n of M)try{Ae(n)}catch(a){console.error(`Error removing file ${n}`,a.message)}v(E,i,d,e.statusCode),e.end()}})}catch(l){return console.error(l),e.writeHead(y.INTERNAL_SERVER_ERROR,{"Content-Type":"application/json"}),v(E,i,d,y.INTERNAL_SERVER_ERROR),e.end(JSON.stringify({message:s.messages?.INTERNAL_SERVER_ERROR||"Internal server error"}))}}}var B=process.cwd(),_e=await k(B,b.configFile),_=(await x(_e)).default||{},ze=await k(B,P.compiledFolder,P.compiledRoutes,b.bootstrapCompiled),oe=await x(ze),F=oe.bootstrap||oe.default;F&&typeof F=="function"&&(console.log(`
Bootstrapping...
`),await F(_));var D=_.port||+(process.env.PORT||4e3),L=w(De(B,_.paths?.uploadTemp||".tmp"));Oe(L)&&Ce(L,{recursive:!0});Ne(L,{recursive:!0});V(_.limits?.minWorkerPoolSize||5);var Me=$e({noDelay:!0,keepAlive:!0,keepAliveTimeout:3e4,keepAliveInitialDelay:5e3,connectionsCheckingInterval:5e3},te(J));Me.listen(D,()=>{console.log(`
Server running on port %s`,U.yellow(D)),console.log(` You can access the server at %s or %s
`,U.yellow(`http://localhost:${D}`),U.yellow(`http://127.0.0.1:${D}`))});
//# sourceMappingURL=v1-multi.mjs.map