@vulppi/intrest
Version:
Backend kit make by Vulppi
71 lines (61 loc) • 11.9 kB
JavaScript
var it=Object.defineProperty;var R=(t,e)=>{for(var n in e)it(t,n,{get:e[n],enumerable:!0})};var K={};R(K,{aliases:()=>ft,command:()=>mt,describe:()=>gt,handler:()=>yt});import lt from"chalk";import{cpSync as pt,writeFileSync as ut}from"fs";import{join as U}from"path";import{fileURLToPath as dt}from"url";import{glob as N}from"glob";import{join as E,normalize as st}from"path";import{pathToFileURL as at}from"url";var p={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}"},h={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},l={compiledFolder:".intrest",compiledRoutes:"routes",workerMultiWorker:"multi.mjs",workerSingleWorker:"single.mjs",workerRouter:"router.mjs",routeIdentity:"__identity.mjs"};function r(t){return st(t).replace(/[\/\\]+/g,"/")}async function v(t){if(!t)return{};let e=at(t);e.searchParams.set("update",Date.now().toString());try{return await import(e.toString()).then(n=>n)||{}}catch{return{}}}async function w(...t){let e=await N(r(E(...t)),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0});return e[0]&&r(e[0])}async function P(...t){return(await N(r(E(...t)),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0})).map(r)}async function W(...t){let e=t.map(o=>r(E(...o)));return(await N(e.reverse(),{ignore:["**/node_modules/**"],windowsPathsNoEscape:!0})).map(r)}function f(t,...e){return r(t).replace(r(E(...e)),"").replace(/^\//,"")}function F(t){return r(t).replace(/\.[a-z0-9]+$/i,"")}async function ct(t){return W(...p.env.map(e=>[t,e]))}async function _(t){return(await ct(t))[0]}async function k(t,e){return(await W(...e.map(n=>[t,n])))[0]||e[1]}var mt="create",ft=["init","new"],gt="Initialize a new backend project powered by Vulppi",yt=async()=>{let t=r(process.cwd());console.log(`Project folder: %s
`,lt.cyan(t));let e=dt(new URL(r(U("../..","templates","starter")),import.meta.url));pt(e,t,{recursive:!0,filter:()=>!0}),ut(r(U(t,".gitignore")),`# Vulppi ignore template
# package
node_modules/
npm-debug.log
# IDE
.idea/
# OS files
.DS_Store
Thumbs.db
# log
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
pnpm-debug.log*
# lock
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock*
# build
.intrest/
build/
dist/
*.gem
*.egg
# temporary
*.swp
*temp/
*tmp/
*.env.*
*.env
# test
coverage/
.nyc_output/
# typescript
*.tsbuildinfo
`,{flag:"w+"}),console.log(`Project created successfully! \u{1F929}\u{1F389}
`)};var q={};R(q,{aliases:()=>$t,builder:()=>Tt,command:()=>At,describe:()=>Ot,handler:()=>Nt});import x from"chalk";import Z from"chokidar";import kt from"dotenv";import jt from"dotenv-expand";import{existsSync as D,lstatSync as B,rmSync as St}from"fs";import{join as g}from"path";import{Worker as Ct}from"worker_threads";import{TsconfigPathsPlugin as G}from"@esbuild-plugins/tsconfig-paths";import j from"chalk";import{build as wt,context as xt}from"esbuild";import{existsSync as S,mkdirSync as Pt,rmSync as H,writeFileSync as vt}from"fs";import{getTsconfig as M}from"get-tsconfig";import{dirname as X,join as y}from"path";import{StatusCodes as me}from"http-status-codes";import ge from"lodash";import he from"range-parser";function ht(t){return t.replace(/[\/\\]?\([A-zÀ-ú0-9-_$]+\)/gi,"").replace(/route\.(mj|cj|j|t)s$/,"").replace(/\/*$/,"").replace(/^\/*/,"/")}function J(t,e){let n=f(t,e),o=ht(n);if(/\[\.\.\.[A-zÀ-ú0-9-_$]+\].+$/.test(o))throw new Error(`Invalid route path: ${n}`);return{pathname:t,route:o,vars:Array.from(o.matchAll(/\[(?:\.{3,3})?([A-zÀ-ú0-9-_$]+)\]/g)).map(i=>i[1]),paramRegexp:new RegExp(o.replace(/\[([A-zÀ-ú0-9-_$]+)\]/g,"([A-z\xC0-\xFA0-9-_:$.@%]+)").replace(/\[\.{3,3}([A-zÀ-ú0-9-_$]+)\]/g,"?([A-z\xC0-\xFA0-9-_:$%.@/]*)").replace(/[\/\\]/,"\\/").replace(/^\^*/,"^").replace(/\$*$/,"\\/?$"))}}async function Q({input:t,output:e,entry:n,config:o}){let i=r(y(e,l.compiledRoutes)),a=r(y(t,n));await wt({entryPoints:{[F(n)]:a},bundle:!0,minify:!0,packages:"external",target:"node18",platform:"node",format:"esm",outExtension:{".js":".mjs"},outdir:i,plugins:[G({tsconfig:M(r(y(process.cwd(),o?.paths?.tsConfig||"tsconfig.json")))?.config}),Y({entry:n,absoluteEntry:a,input:t,output:e})]})}var C=new Map;async function A({input:t,output:e,entry:n,config:o,restart:i}){let a=r(y(e,l.compiledRoutes)),s=r(y(t,n));if(C.has(s))return;let u=await xt({entryPoints:{[F(n)]:s},bundle:!0,minify:!1,packages:"external",target:"node18",platform:"node",format:"esm",outExtension:{".js":".mjs"},outdir:a,logLevel:"silent",plugins:[G({tsconfig:M(y(process.cwd(),o?.paths?.tsConfig||"tsconfig.json"))?.config}),Y({entry:n,absoluteEntry:s,input:t,output:e,restart:i})]});C.set(s,u),u.watch()}function Y({entry:t,absoluteEntry:e,input:n,output:o,restart:i}){return{name:"InteREST",setup(a){a.onStart(async()=>{console.info("%s Building - %s",j.yellow("\u25C9"),j.bold.cyan(t))}),a.onResolve({filter:h.observable},async({path:s,kind:u})=>{if(u!=="entry-point")return null;let d=r(y(f(s,n).replace(/\/?route\.ts$/,""),l.routeIdentity)),m=r(y(o,l.compiledRoutes,d)),c=X(m);return S(c)||Pt(c,{recursive:!0}),vt(m,bt(s,n),{flag:"w+"}),null}),a.onEnd(async()=>{if(S(e))console.info("%s Done - %s",j.green("\u25C9"),j.bold.cyan(t));else{C.get(e)?.dispose(),C.delete(e);return}h.bootstrap.test(t)&&i?.()}),a.onDispose(async()=>{if(!i)return;let s=r(y(o,l.compiledRoutes,F(t)+".mjs"));S(s)&&H(s);let d=r(y(X(s),l.routeIdentity));S(d)&&H(d),h.bootstrap.test(t)&&i()})}}}function bt(t,e){let n=J(t,e),o=[];return o.push(`export const paramExtract = ${n.paramRegexp};`),o.push(`export const paramKeys = ${JSON.stringify(n.vars)};`),o.push(`export const pathname = "${f(n.pathname,e).replace(/\/?route\.ts$/,"").replace(/^\/*/,"/")}";`),o.push(`export const route = "${n.route}";`),o.join(`
`)}import Rt from"crypto";import Et,{existsSync as Ft}from"fs";function b(t){return new Promise(function(e,n){if(!t||!Ft(t))return e("");let o=Rt.createHash("md5"),i=Et.createReadStream(t);i.on("error",n),i.on("data",function(a){o.update(a)}),i.on("close",function(){e(o.digest("hex"))})})}var At="dev",$t=["develop"],Tt={"single-worker":{alias:"s",type:"boolean",default:!1,description:"Start the single-worker mode"}},Ot="Start the development server";async function Nt({singleWorker:t}){let e=r(process.cwd());console.log(`
Starting the application in %s mode...`,x.bold.cyan("development")),console.log(`Project folder: %s
`,x.cyan(e)),process.env.NODE_ENV?process.env.NODE_ENV!=="development"&&console.warn(x.yellow('The NODE_ENV environment variable is not set to "development".')):process.env.NODE_ENV="development";let n=await w(e,p.configFile),o=await _(e),i=await b(n),a=await b(o);L(e,n,o,t);async function s(u){if(!u)return;let d=!1,m=!1;if(h.config.test(u)){let c=await P(e,p.configFile);if(c.length>1)return console.error(x.red("Multiple config files found.")),console.error(x.red(`Please leave one and remove the rest following files:
`)),console.error(x.red(c.map(z=>f(z,e)).join(`
`))),console.error(`
`),process.exit(1);c.length||(d=!0,console.info(x.red(`The config file has removed.
`))),n=c[0]}else if(h.env.test(u)){let c=await _(e);c!==o&&(o=c,m=!0)}if(n){let c=await b(n);i!==c&&(i=c,d=!0,console.info("Config file changed."))}if(o){let c=await b(o);a!==c&&(a=c,m=!0,console.info("Env file changed."))}(d||m)&&L(e,n,o,t)}Z.watch([r(g(e,p.configFile)),r(g(e,p.envFile)),r(g(e,".env"))],{ignoreInitial:!0,awaitWriteFinish:!0,cwd:e}).on("add",s).on("change",s).on("unlink",s)}var $=null,T=null;async function L(t,e,n,o){let i=!0;T&&(clearTimeout(T),T=null),T=setTimeout(async()=>{$&&($.terminate(),$=null,i=!1);let a=(await v(e)).default||{};i?(console.info(` Starting the application...
`),await _t(t,a,()=>{if(i){i=!1;return}L(t,e,n,o)})):console.info(`
Restarting the application...`);let s=n?kt.config({path:n,override:!0}):{parsed:{}};s.parsed||(s.parsed={}),Object.assign(s.parsed,a?.env||{}),jt.expand(s);let u=a.httpVersion||1;$=new Ct(new URL(r(g("..","workers","v"+u+"-"+(o?l.workerSingleWorker:l.workerMultiWorker))),import.meta.url),{env:{NODE_ENV:"development",...structuredClone(process.env),...s.parsed}})},1e3)}async function _t(t,e,n){let o=await k(t,p.entryFolder);console.info(` Application entry folder: %s
`,x.cyan.bold(f(o,t)));async function i(d){if(!d)return;let m=r(d),c=r(g(o,m));if(D(c)&&B(c).isDirectory()){let nt=await P(c,p.entryPoints);return await Promise.all(nt.map(async I=>{let rt=f(I,o);B(I).isDirectory()||await A({input:o,output:r(g(t,l.compiledFolder)),entry:rt,config:e,restart:n})}))}(h.entry.test(m)||h.bootstrap.test(m))&&await A({input:o,output:r(g(t,l.compiledFolder)),entry:m,config:e,restart:n})}Z.watch([r(g(o,p.entryPoints)),r(g(o,p.bootstrapEntry))],{awaitWriteFinish:!0,ignoreInitial:!0,cwd:o}).on("add",i);let a=r(g(t,l.compiledFolder));D(a)&&St(a,{recursive:!0});let s=await P(o,p.entryPoints),u=await w(o,p.bootstrapEntry);return u&&s.push(u),Promise.all(s.map(async d=>{let m=f(d,o);D(d)&&B(d).isDirectory()||await A({input:o,output:r(g(t,l.compiledFolder)),entry:m,config:e,restart:n})}))}var tt={};R(tt,{aliases:()=>Lt,builder:()=>Vt,command:()=>Bt,describe:()=>zt,handler:()=>It});import V from"chalk";import{join as Dt}from"path";var Bt="start",Lt=["serve","server"],Vt={"single-worker":{alias:"s",type:"boolean",default:!1,description:"Start the single-worker mode"}},zt="Start the server";async function It({singleWorker:t}){console.log(`
Starting the application in %s mode...`,V.bold("production")),console.log(`Project folder: %s
`,V.cyan(r(process.cwd()))),process.env.NODE_ENV?process.env.NODE_ENV!=="production"&&console.warn(V.yellow('The NODE_ENV environment variable is not set to "production".')):process.env.NODE_ENV="production",Wt(t)}async function Wt(t){let e=r(process.cwd()),n=await w(e,p.configFile),i=((await v(n)).default||{}).httpVersion||1;await import(new URL(r(Dt("..","workers","v"+i+"-"+(t?l.workerSingleWorker:l.workerMultiWorker))),import.meta.url).toString())}var ot={};R(ot,{builder:()=>Xt,command:()=>Jt,describe:()=>Ht,handler:()=>Gt});import O from"chalk";import{existsSync as Ut,rmSync as Kt}from"fs";import{join as et}from"path";var Jt="build",Ht="Build the project",Xt={};async function Gt(){let t=r(process.cwd()),e=await w(t,p.configFile),n=(await v(e)).default||{};console.info(`
Building application...`),console.log(`Project folder: %s
`,O.cyan(t));let o=await k(t,p.entryFolder);console.info(` Application entry folder: %s
`,O.cyan.bold(f(o,t)));let i=await P(o,p.entryPoints),a=await w(o,p.bootstrapEntry);a&&i.push(a);let s=r(et(t,l.compiledFolder));Ut(s)&&Kt(s,{recursive:!0}),await Promise.all(i.map(async u=>{let d=f(u,o);await Q({input:o,output:r(et(t,l.compiledFolder)),entry:d,config:n})})),console.log(`
%s Application built successfully!
`,O.green("\u2714")),console.log(` run %s to start the application
`,O.cyan("intrest start"))}export{ot as build,q as dev,K as init,tt as server};
//# sourceMappingURL=index.mjs.map