lacis 0.2.6 → 0.2.8
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/README.md +2 -0
- package/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/{chunk-VQ3XR2HC.js → chunk-5BKQSPRW.js} +6 -6
- package/dist/cli/index.js +9 -6
- package/dist/{index-DMyND6f7.d.ts → index-CnWzo9eB.d.ts} +2 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -107,7 +107,9 @@ export async function GET(req: Request, res: Response) {
|
|
|
107
107
|
|---|---|
|
|
108
108
|
| `res.status(code)` | Set status code (chainable) |
|
|
109
109
|
| `res.json(data)` | Send JSON response |
|
|
110
|
+
| `res.html(data)` | Send HTML response |
|
|
110
111
|
| `res.send(data)` | Send string or JSON |
|
|
112
|
+
| `res.redirect(url, status?)` | Redirect to a URL (default 302) |
|
|
111
113
|
| `res.setHeader(name, value)` | Set a response header |
|
|
112
114
|
| `res.cookies.set(name, value, opts?)` | Set a cookie |
|
|
113
115
|
| `res.cookies.delete(name, opts?)` | Delete a cookie |
|
package/dist/adapters/index.d.ts
CHANGED
package/dist/adapters/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{I as bunAdapter,J as getAdapter,H as netlifyAdapter,F as nodeAdapter,G as vercelAdapter}from'../chunk-
|
|
1
|
+
export{I as bunAdapter,J as getAdapter,H as netlifyAdapter,F as nodeAdapter,G as vercelAdapter}from'../chunk-5BKQSPRW.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import N,{join}from'path';import De from'fs/promises';import {existsSync}from'fs';import D from'cluster';import me,{IncomingMessage,ServerResponse}from'http';import Ye from'https';import*as q from'os';import q__default from'os';import {EventEmitter}from'events';import {Socket}from'net';var O={beforeRequest:[],afterRequest:[],onError:[]},T=new Map;function ae(t,e){return O[t].push(e),{remove:()=>{let r=O[t].indexOf(e);r!==-1&&O[t].splice(r,1);}}}function ht(t,e,r){let n=t==="/"?"/":t.replace(/\/+$/,"");return T.has(n)||T.set(n,{beforeRequest:[],afterRequest:[],onError:[]}),T.get(n)[e].push(r),{remove:()=>{if(T.has(n)){let s=T.get(n),i=s[e].indexOf(r);i!==-1&&s[e].splice(i,1);}}}}function Be(t){let r=(t==="/"?"/":t.replace(/\/+$/,"")).split("/").filter(Boolean),n={beforeRequest:[...O.beforeRequest],afterRequest:[...O.afterRequest],onError:[...O.onError]},o="";if(T.has("/")){let s=T.get("/");n.beforeRequest.push(...s.beforeRequest),n.afterRequest.push(...s.afterRequest),n.onError.push(...s.onError);}for(let s of r)if(o+="/"+s,T.has(o)){let i=T.get(o);n.beforeRequest.push(...i.beforeRequest),n.afterRequest.push(...i.afterRequest),n.onError.push(...i.onError);}return n}function k(){return O.beforeRequest.length>0||O.afterRequest.length>0||O.onError.length>0?true:T.size>0}async function H(t,e,r,n){let o=e.url?.split("?")[0]||"/",s=Be(o);if(s[t].length===0)return true;for(let i of s[t])try{if(await i(e,r,n)===!1)return !1}catch(d){if(t!=="onError")try{for(let a of s.onError)await a(e,r,{error:d,phase:t});}catch(a){console.error("Error in error handler:",a);}return false}return true}async function ie(t){T.clear();async function e(r,n=""){try{let o=await De.readdir(r,{withFileTypes:!0}),s=o.find(i=>i.name==="+middleware.ts"||i.name==="+middleware.js");if(s){let i=N.join(r,s.name);try{let a=await import(`${N.resolve(i)}?update=${Date.now()}`);if(T.has(n)||T.set(n,{beforeRequest:[],afterRequest:[],onError:[]}),a.beforeRequest){let l=Array.isArray(a.beforeRequest)?a.beforeRequest:[a.beforeRequest];T.get(n).beforeRequest.push(...l);}if(a.afterRequest){let l=Array.isArray(a.afterRequest)?a.afterRequest:[a.afterRequest];T.get(n).afterRequest.push(...l);}if(a.onError){let l=Array.isArray(a.onError)?a.onError:[a.onError];T.get(n).onError.push(...l);}}catch(d){console.error(`Error loading middleware for ${n}:`,d);}}for(let i of o)i.isDirectory()&&await e(N.join(r,i.name),`${n==="/"?"":n}/${i.name}`);}catch(o){console.error(`Error scanning directory ${r}:`,o);}}await e(t,"/");}function mt(){return T}function gt(){O.beforeRequest=[],O.afterRequest=[],O.onError=[],T.clear();}function I(t){if(t)for(let e of ["beforeRequest","afterRequest","onError"]){let r=t[e];if(r){let n=Array.isArray(r)?r:[r];for(let o of n)ae(e,o);}}}function Ne(t,e){return !e||e==="*"?true:typeof e=="string"?t===e:Array.isArray(e)?e.includes(t):e instanceof RegExp?e.test(t):typeof e=="function"?e(t):false}function We(t){let e=(t.methods??["GET","POST","PUT","DELETE","PATCH","OPTIONS"]).join(", "),r=(t.allowedHeaders??["Content-Type","Authorization"]).join(", "),n=t.exposedHeaders?.join(", "),o=t.maxAge!=null?String(t.maxAge):null,s=!t.origin||t.origin==="*";return async(i,d)=>{let a=i.getHeader("origin");if(!a||!Ne(a,t.origin))return;let l=s&&!t.credentials;if(d.setHeader("Access-Control-Allow-Origin",l?"*":a),l||d.setHeader("Vary","Origin"),t.credentials&&d.setHeader("Access-Control-Allow-Credentials","true"),n&&d.setHeader("Access-Control-Expose-Headers",n),i.method==="OPTIONS")return d.setHeader("Access-Control-Allow-Methods",e),d.setHeader("Access-Control-Allow-Headers",r),o&&d.setHeader("Access-Control-Max-Age",o),d.status(204),d.end(),false}}function L(t){t&&ae("beforeRequest",We(t));}function y(...t){D.isPrimary&&console.log(...t);}function Ge(t){let e=t.match(/^\[(\w+)(\??)]/);return e?{name:e[1],isParam:true,isOptional:e[2]==="?"}:{name:t,isParam:false,isOptional:false}}var Ke=1e3,Qe=100,le=class{rootNode;cachedRoutes;routeCount;lastLoaded;verbose;constructor(){this.rootNode=this.createNode(),this.cachedRoutes=new Map,this.routeCount=0,this.lastLoaded=0,this.verbose=false;}createNode(){return {handlers:Object.create(null),staticChildren:new Map,paramChild:null,wildcardHandler:null,isEndpoint:false}}addRoute(e,r,n){let o=r.split("/").filter(Boolean),s=this.rootNode;for(let i of o){let d=Ge(i);if(d.isParam){if(!s.paramChild)s.paramChild={name:d.name,node:this.createNode(),isOptional:d.isOptional};else if(s.paramChild.name!==d.name)throw new Error(`Route conflict: param name "[${d.name}]" conflicts with existing "[${s.paramChild.name}]" at the same path position. Use the same param name for all methods at this level.`);s=s.paramChild.node;}else {if(i==="*")return s.wildcardHandler||(s.wildcardHandler=Object.create(null)),s.wildcardHandler[e]=n,this.cachedRoutes.clear(),this;s.staticChildren.has(i)||s.staticChildren.set(i,this.createNode()),s=s.staticChildren.get(i);}}return s.isEndpoint=true,s.handlers[e]||this.routeCount++,s.handlers[e]=n,this.cachedRoutes.clear(),this}findRoute(e,r){let n=r==="/"?"/":r.replace(/\/+$/,""),o=e+":"+n,s=this.cachedRoutes.get(o);if(s)return s;let i=n==="/"?[]:n.split("/").filter(Boolean),d=Object.create(null),a=this.traverse(this.rootNode,i,e,d,0)??{handler:null,params:Object.create(null)};if(this.cachedRoutes.size>=Ke){let l=0;for(let u of this.cachedRoutes.keys())if(this.cachedRoutes.delete(u),++l>=Qe)break}return this.cachedRoutes.set(o,a),a}traverse(e,r,n,o,s){if(s===r.length){if(e.isEndpoint){let l=e.handlers[n]??(n==="HEAD"?e.handlers.GET:void 0)??e.handlers[""];if(l)return {handler:l,params:{...o}};let u=Object.keys(e.handlers).filter(h=>h!=="");return {handler:null,params:{},allowedMethods:u}}let a=e.paramChild;if(a?.isOptional&&a.node.isEndpoint){let l=a.node.handlers[n]??(n==="HEAD"?a.node.handlers.GET:void 0)??a.node.handlers[""];if(l)return {handler:l,params:{...o}}}return null}let i=r[s],d=e.staticChildren.get(i);if(d){let a=this.traverse(d,r,n,o,s+1);if(a)return a}if(e.paramChild){let{name:a,node:l}=e.paramChild;o[a]=i;let u=this.traverse(l,r,n,o,s+1);if(u)return u;delete o[a];}if(e.wildcardHandler){let a=e.wildcardHandler[n]??e.wildcardHandler[""],l=r.slice(s).join("/");if(a)return {handler:a,params:{...o,"*":l}};let u=Object.keys(e.wildcardHandler).filter(h=>h!=="");if(u.length>0)return {handler:null,params:{...o,"*":l},allowedMethods:u}}return null}async loadRoutes(e){this.rootNode=this.createNode(),this.cachedRoutes.clear(),this.routeCount=0,await ie(e);let r=this;async function n(o,s=[]){try{let i=await De.readdir(o,{withFileTypes:!0}),d=i.find(a=>!a.isDirectory()&&(a.name==="index.ts"||a.name==="index.js"));if(d)try{let l=await import(`${N.resolve(N.join(o,d.name))}?update=${Date.now()}`),u=["GET","POST","PUT","DELETE","PATCH"],h="/"+s.join("/"),g=!1;for(let R of u)typeof l[R]=="function"&&(r.addRoute(R,h,l[R]),g=!0);!g&&typeof l.default=="function"&&r.addRoute("GET",h,l.default),r.verbose&&y(`Route loaded: ${h}`);}catch(a){console.error(`Error loading index in ${o}:`,a);}for(let a of i)if(a.isDirectory()){let l=a.name.match(/^\[(\w+)(\??)]/),u=l?`[${l[1]}${l[2]}]`:a.name;await n(N.join(o,a.name),[...s,u]);}}catch(i){console.error(`Error scanning directory ${o}:`,i);}}return await n(e),this.lastLoaded=Date.now(),this.verbose&&y(`Loading completed: ${this.routeCount} routes`),true}getRoutes(){let e=[];return this.collectRoutes(this.rootNode,[],e),e}collectRoutes(e,r,n){if(e.isEndpoint){let o=r.length===0?"/":"/"+r.join("/");for(let[s,i]of Object.entries(e.handlers))s!==""&&n.push({method:s,path:o,handler:i});}for(let[o,s]of e.staticChildren)this.collectRoutes(s,[...r,o],n);if(e.paramChild){let{name:o,isOptional:s,node:i}=e.paramChild;this.collectRoutes(i,[...r,s?`:${o}?`:`:${o}`],n);}if(e.wildcardHandler){let o="/"+[...r,"*"].join("/");for(let[s,i]of Object.entries(e.wildcardHandler))s!==""&&n.push({method:s,path:o,handler:i});}}getStats(){return {routeCount:this.routeCount,lastLoaded:this.lastLoaded,uptime:Date.now()-this.lastLoaded,cacheSize:this.cachedRoutes.size}}setVerbose(e){return this.verbose=e,this}reset(){this.rootNode=this.createNode(),this.cachedRoutes=new Map,this.routeCount=0;}},U=new le;function V(t){return t&&typeof t=="object"&&"error"in t}function F(t){for(let{path:e,handlers:r}of t){let n=e.replace(/:(\w+\??)/g,(o,s)=>s.endsWith("?")?`[${s.slice(0,-1)}?]`:`[${s}]`);for(let[o,s]of Object.entries(r))typeof s=="function"&&U.addRoute(o,n,s);}}async function G(t){let e=join(t,"_manifest.js");if(existsSync(e)){U.reset(),await ie(t);let r=await import(e);F(r.routes);return}return U.loadRoutes(t)}function j(t,e="GET"){let r=U.findRoute(e,t);return r.handler?{handler:r.handler,params:r.params}:r.allowedMethods?.length?{error:"Method Not Allowed",status:405,allowedMethods:r.allowedMethods}:null}function _t(t){let e=process.env.NODE_ENV==="production",r=process.env.ROUTES_DIR??t??(e?"dist/routes":"routes"),n=e&&!N.isAbsolute(r)&&!r.startsWith("dist/")?N.join("dist",r):r;return N.resolve(process.cwd(),n)}function kt(){return U.getStats()}function Ht(t){U.setVerbose(t);}function qt(){U.reset();}function Se(t,e={},r={},n){let o=false,s=0,i={},d=[],a=[],l=[],u=null;r.onMessage&&d.push(r.onMessage),r.onClose&&a.push(r.onClose),r.onError&&l.push(r.onError),r.onEvent&&Object.entries(r.onEvent).forEach(([f,m])=>{i[f]||(i[f]=[]),i[f].push(m);});let h=e.reconnectInterval||3e3,g=e.maxRetries||3,R=e.disableReconnect||false,w=e.body,p=e.contentType||(w?"application/json":void 0),c=e.method||(w?"POST":"GET");if(typeof t!="string"){let f=t;return o=true,f.on("data",m=>{v(m.toString());}),f.on("end",()=>{o=false;}),f.on("error",m=>{o=false,console.error("SSE Error:",m);}),E()}if(typeof t=="string")return new Promise((f,m)=>{$().then(()=>f(E())).catch(m);});function v(f){let m=f,S=m.split(`
|
|
2
2
|
|
|
3
3
|
`);m=S.pop()||"";for(let M of S){let A=M.split(`
|
|
4
|
-
`),C="",b="";for(let _ of A)_.startsWith("event:")?b=_.slice(6).trim():_.startsWith("data:")&&(C=_.slice(5).trim());if(C)try{let _=JSON.parse(C);b&&i[b]?i[b].forEach(
|
|
4
|
+
`),C="",b="";for(let _ of A)_.startsWith("event:")?b=_.slice(6).trim():_.startsWith("data:")&&(C=_.slice(5).trim());if(C)try{let _=JSON.parse(C);b&&i[b]?i[b].forEach(W=>W(_)):d.forEach(W=>W(_));}catch{b&&i[b]?i[b].forEach(_=>_(C)):d.forEach(_=>_(C));}}}function E(){return {onMessage(f){return d.push(f),this},onEvent(f,m){return i[f]||(i[f]=[]),i[f].push(m),this},onClose(f){return a.push(f),this},close(){u&&(u.destroy(),u=null),o=false,a.forEach(f=>f());}}}async function $(){if(!o){o=true;try{await x();}catch(f){!R&&s<g?(s++,setTimeout(()=>{$();},h)):l.forEach(m=>m(f));}}}async function x(){return new Promise((f,m)=>{let S=new URL(t);e.params&&(typeof e.params=="object"?Object.entries(e.params).forEach(([C,b])=>{S.searchParams.append(C,String(b));}):typeof e.params=="string"&&new URLSearchParams(e.params).forEach((b,_)=>{S.searchParams.append(_,b);}));let M={hostname:S.hostname,port:S.port||(S.protocol==="https:"?443:80),path:S.pathname+S.search,method:c,headers:{Accept:"text/event-stream",...n?.headers||{},"Cache-Control":"no-cache",Connection:"keep-alive",...p&&{"Content-Type":p},...w&&typeof w=="string"&&{"Content-Length":Buffer.byteLength(w).toString()},...w&&typeof w!="string"&&{"Content-Length":Buffer.byteLength(JSON.stringify(w)).toString()}}};u=(S.protocol==="https:"?Ye:me).request(M,C=>{if(C.statusCode!==200){o=false,m(new Error(`Server responded with status: ${C.statusCode}`));return}C.setEncoding("utf8"),C.on("data",v),C.on("end",()=>{o=false,u?.destroy(),u=null,a.forEach(b=>b()),f(null);}),C.on("close",()=>{o=false,u?.destroy(),u=null,a.forEach(b=>b()),f(null);}),C.on("error",b=>{o=false,u?.destroy(),u=null,a.forEach(_=>_()),m(b);});}),u.on("error",C=>{o=false,u?.destroy(),u=null,m(C);}),w&&(typeof w=="string"?u.write(w):u.write(JSON.stringify(w))),u.end();})}return E()}function ve(t,e){let r=e?.headers?.["Cache-Control"]||"no-cache",n=e?.headers?.Connection||"keep-alive",o=e?.timeout||3e5;t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":r,Connection:n,...e?.headers||{}});let s=setTimeout(()=>{t.end();},o);return t.on("close",()=>{clearTimeout(s);}),s}function Ee(t,e){return t.writableEnded?false:t.write(`data: ${e}
|
|
5
5
|
|
|
6
6
|
`)}function be(t,e){return t.writableEnded?false:t.write(`data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
@@ -19,8 +19,8 @@ import z from'path';import De from'fs/promises';import U from'cluster';import he
|
|
|
19
19
|
`),t.end();}function He(t,e,r,n=500,o){t.writeHead(n,{"Content-Type":"text/event-stream"}),t.write(`event: ${e}
|
|
20
20
|
`);let s={message:r,code:n,details:o||null};t.write(`data: ${JSON.stringify(s)}
|
|
21
21
|
|
|
22
|
-
`),t.end();}var
|
|
22
|
+
`),t.end();}var Ze=10485760,Q=class{_parsed=null;_raw;constructor(e){this._raw=e;}_parse(){if(this._parsed!==null)return this._parsed;if(this._parsed={},!this._raw)return this._parsed;for(let e of this._raw.split(";")){let r=e.indexOf("=");if(r===-1)continue;let n=e.slice(0,r).trim(),o=e.slice(r+1).trim();if(n){let s=o.startsWith('"')&&o.endsWith('"')?o.slice(1,-1):o;try{this._parsed[n]=decodeURIComponent(s);}catch{this._parsed[n]=s;}}}return this._parsed}get(e){return this._parse()[e]}all(){return {...this._parse()}}},X=class{_pending=[];set(e,r,n={}){return this._pending.push({name:e,value:r,opts:n}),this}delete(e,r={}){return this.set(e,"",{...r,maxAge:0,expires:new Date(0)})}serialize(){return this._pending.map(({name:e,value:r,opts:n})=>{let o=`${e}=${encodeURIComponent(r)}`,s=n.path!==void 0?n.path:"/";return s&&(o+=`; Path=${s}`),n.domain&&(o+=`; Domain=${n.domain}`),n.maxAge!=null&&(o+=`; Max-Age=${n.maxAge}`),n.expires&&(o+=`; Expires=${n.expires.toUTCString()}`),n.httpOnly&&(o+="; HttpOnly"),n.secure&&(o+="; Secure"),n.sameSite&&(o+=`; SameSite=${n.sameSite}`),o})}};function qe(t){if(typeof t.get=="function")return t.get("cookie")??void 0;let e=t.cookie;return Array.isArray(e)?e.join("; "):e}function z(t){return class extends t{_zreqCookies;getHeader(e){let r=this.headers;if(typeof r.get=="function")return r.get(e)??void 0;let n=r[e.toLowerCase()];return Array.isArray(n)?n[0]:n}get cookies(){return this._zreqCookies||(this._zreqCookies=new Q(qe(this.headers))),this._zreqCookies}json(){return this.body().then(e=>JSON.parse(e.toString()))}form(){return new Promise((e,r)=>{let n=this.headers,o=typeof n.get=="function"?n.get("content-type")??"":n["content-type"]??"";if(!o.startsWith("multipart/form-data")){r(new Error("Content-Type is not multipart/form-data"));return}let s=o.match(/boundary=(.+)$/);if(!s){r(new Error("Boundary not found"));return}let i=s[1].trim();this.body().then(d=>{let a={},l=Buffer.from(`--${i}`),u=[],h=0,g;for(;(g=d.indexOf(l,h))!==-1;)u.push(d.subarray(h,g)),h=g+l.length;u.push(d.subarray(h));for(let R=1;R<u.length-1;R++){let w=u[R].subarray(2),p=w.indexOf(`\r
|
|
23
23
|
\r
|
|
24
|
-
`);if(p===-1)continue;let c=w.subarray(0,p).toString(),v=w.subarray(p+4,w.length-2),E=c.match(/Content-Disposition: form-data; name="([^"]+)"(?:; filename="([^"]+)")?/i);if(E)if(E[2]){let
|
|
25
|
-
\u{1F4CA} Server Performance Metrics \u{1F4CA}`),y(`Uptime: ${p(s.uptime)}`),y(`Load: ${s.systemLoad[0].toFixed(2)}, ${s.systemLoad[1].toFixed(2)}, ${s.systemLoad[2].toFixed(2)}`),y(`Requests: ${s.requestCount} total, ${S} req/sec`),y(`Active Requests: ${s.activeRequests}`),y(`Errors: ${s.errorCount} (${M}%)`),s.responseTimes.count>0&&(y(`Response Times: avg ${s.responseTimes.avg.toFixed(2)}ms, min ${s.responseTimes.min}ms, max ${s.responseTimes.max}ms`),s.responseTimes.p50&&y(`Response Time Percentiles: p50 ${s.responseTimes.p50}ms, p90 ${s.responseTimes.p90}ms, p99 ${s.responseTimes.p99}ms`)),y(`Memory: ${f.rss}MB (RSS), ${f.heapUsed}MB / ${f.heapTotal}MB (Heap)`),y(`CPU Usage: ${s.cpu.usage.toFixed(2)}%`),Object.keys(s.statusCodes).length>0&&(y("Status Codes:"),Object.entries(s.statusCodes).sort(([A],[C])=>parseInt(A)-parseInt(C)).forEach(([A,C])=>{y(` ${A}: ${C}`);})),y(""),o.lastReport=Date.now();}function R(){let f=Date.now();o.requestCount=0,o.activeRequests=0,o.errorCount=0,o.responseTimes=[],o.responseTimesBucket=Array(100).fill(0),o.statusCodes={},o.lastReport=f,o.lastReset=f,y("\u{1F504} Performance metrics have been reset");}function w(){let f=s.memory.heapUsed/s.memory.heapTotal*100,m=s.requestCount?s.errorCount/s.requestCount*100:0,S=s.responseTimes.avg;s.cpu.usage>r.thresholds.cpu&&!a.cpu?(a.cpu=true,e.emit("alarm","cpu",`High CPU usage: ${s.cpu.usage.toFixed(2)}%`)):s.cpu.usage<=r.thresholds.cpu&&a.cpu&&(a.cpu=false,e.emit("alarm-clear","cpu",`CPU usage returned to normal: ${s.cpu.usage.toFixed(2)}%`)),f>r.thresholds.memory&&!a.memory?(a.memory=true,e.emit("alarm","memory",`High memory usage: ${f.toFixed(2)}%`)):f<=r.thresholds.memory&&a.memory&&(a.memory=false,e.emit("alarm-clear","memory",`Memory usage returned to normal: ${f.toFixed(2)}%`)),S>r.thresholds.responseTime&&!a.responseTime?(a.responseTime=true,e.emit("alarm","responseTime",`High response time: ${S.toFixed(2)}ms`)):S<=r.thresholds.responseTime&&a.responseTime&&(a.responseTime=false,e.emit("alarm-clear","responseTime",`Response time returned to normal: ${S.toFixed(2)}ms`)),m>r.thresholds.errorRate&&!a.errorRate?(a.errorRate=true,e.emit("alarm","errorRate",`High error rate: ${m.toFixed(2)}%`)):m<=r.thresholds.errorRate&&a.errorRate&&(a.errorRate=false,e.emit("alarm-clear","errorRate",`Error rate returned to normal: ${m.toFixed(2)}%`));}function p(f){let m=Math.floor(f/86400),S=Math.floor(f%86400/3600),M=Math.floor(f%3600/60),A=Math.floor(f%60),C=[];return m>0&&C.push(`${m}d`),S>0&&C.push(`${S}h`),M>0&&C.push(`${M}m`),(A>0||C.length===0)&&C.push(`${A}s`),C.join(" ")}function c(){let f=setInterval(h,r.sampleInterval),m=setInterval(g,r.reportInterval),S=setInterval(R,r.resetInterval);return {stop:()=>{clearInterval(f),clearInterval(m),clearInterval(S);}}}function v(){let f=Date.now();return o.activeRequests++,{end:(m,S=false)=>{let M=Date.now()-f;return o.activeRequests--,o.requestCount++,o.responseTimes.push(M),o.responseTimes.length>1e3&&o.responseTimes.shift(),o.statusCodes[m]=(o.statusCodes[m]||0)+1,(S||m>=500)&&o.errorCount++,M}}}function E(){return !Object.values(a).some(f=>f)}function O(){let f=s.memory.heapUsed/s.memory.heapTotal*100,m=s.requestCount?s.errorCount/s.requestCount*100:0;return {status:E()?"healthy":"unhealthy",uptime:s.uptime,responseTimes:{avg:s.responseTimes.avg,p90:s.responseTimes.p90||null,p99:s.responseTimes.p99||null},memory:{usedMB:Math.round(s.memory.heapUsed/1024/1024),totalMB:Math.round(s.memory.heapTotal/1024/1024),percent:f.toFixed(2)},cpu:s.cpu.usage.toFixed(2),requests:{total:s.requestCount,active:s.activeRequests,errors:s.errorCount,errorRate:m.toFixed(2)},alerts:Object.entries(a).filter(([S,M])=>M).map(([S])=>S)}}let x=c();return {trackRequest:v,getMetrics:()=>({...s}),getMetricsHistory:()=>[...i],getHealthMetrics:O,isHealthy:E,stop:x.stop,on:e.on.bind(e),once:e.once.bind(e),off:e.off.bind(e)}}function Oe(t){if(!se){let e=et(t),r=e.stop;e.stop=()=>{r(),se=null;},se=e;}return se}function ue(t={}){let e=t.reportInterval??5e3,r={workers:new Map,workerIds:[]};function n(){if(!U.isWorker)return;let l=process.cpuUsage(),u=()=>{if(!process.send)return;let h=process.memoryUsage(),g=process.cpuUsage(l);l=process.cpuUsage();let R=(g.user+g.system)/(e*1e3),w={type:"stats",stats:{pid:process.pid,load:R,lastUsed:Date.now(),memoryUsage:h}};process.send(w);};u(),setInterval(u,e).unref();}function o(){let l=U.fork();r.workers.set(l.id,{pid:l.process.pid,load:0,lastUsed:Date.now(),memoryUsage:{rss:0,heapTotal:0,heapUsed:0,external:0,arrayBuffers:0}}),r.workerIds.push(l.id),y(`Worker ${l.process.pid} started`);}let s=false,i=[];function d(l=q.cpus().length){if(!U.isPrimary)return n();y(`\u{1F9F5} Launching ${l} workers...`);for(let u=0;u<l;u++)o();U.on("message",(u,h)=>{if(h.type==="stats"&&"stats"in h){let g=r.workers.get(u.id);g&&Object.assign(g,h.stats);}}),U.on("exit",(u,h,g)=>{if(r.workers.delete(u.id),r.workerIds=r.workerIds.filter(R=>R!==u.id),s){i.forEach(R=>R());return}y(`Worker ${u.process.pid} died (${g||h}). Restarting...`),setTimeout(()=>o(),1e3);});}function a(l){s=true;let u=Object.keys(U.workers??{});if(u.length===0){l?.();return}let h=u.length;i.push(()=>{h--,h===0&&l?.();});for(let g of u)U.workers?.[g]?.kill();}return {start:d,shutdown:a,getWorkerStats:()=>Array.from(r.workers.entries()),getActiveWorkerCount:()=>r.workerIds.length}}var ce=class extends he.IncomingMessage{params={};body=Y},fe=class extends W(ce){},pe=class extends F(he.ServerResponse){},Ie={name:"node",createHandler:t=>{if(typeof t!="string")throw new Error("nodeAdapter requires a routesDir string, not a ServerlessConfig.");let e=t;return async(r={})=>{let{port:n=3e3,defaultHeaders:o,isDev:s,cluster:i,monitoring:d={enabled:false}}=r,a=null;s&&d.enabled&&(a=Oe({sampleInterval:d.sampleInterval||5e3,reportInterval:d.reportInterval||6e4,thresholds:d.thresholds,logToConsole:true}),U.isPrimary&&(y("\u{1F4CA} Development performance monitoring enabled"),a.on("alarm",(u,h)=>{y(`\u26A0\uFE0F ALERT: ${h}`);}),a.on("alarm-clear",(u,h)=>{y(`\u2705 RESOLVED: ${h}`);})));let l=o?Object.entries(o):[];if(i?.enabled&&U.isPrimary){let u=i.workers??q__default.cpus().length,h=r.httpsOptions?"https":"http";if(y(`\u{1F9F5} Starting server with ${u} workers`),U.schedulingPolicy!==void 0)try{U.schedulingPolicy=U.SCHED_RR;}catch{}let g=ue();return g.start(u),y(`\u{1F680} Server running at ${h}://localhost:${n}/`+(s?" (dev)":"")),s&&a&&y(`\u{1F4CA} Performance monitoring available at http://localhost:${n}/health`),{close:R=>{a&&a.stop(),g.shutdown(R);}}}if(U.isWorker||!i?.enabled){r.routes||await G(e),L(r.cors),I(r.middleware);let u=async(p,c,v)=>{try{if(s&&a&&p.url==="/health"){c.setHeader("Content-Type","application/json"),c.end(JSON.stringify(a.getHealthMetrics())),v?.end(200);return}let E=p.url||"/",O=ee(E);if(p.query=te(E),k()&&(await H("beforeRequest",p,c)===!1||c.headersSent)){v?.end(c.statusCode||204);return}let x=j(O,p.method||"GET");if(!x){k()&&await H("onError",p,c),c.status(404).json({error:"Route not found"}),v?.end(404);return}if("error"in x){let f=x.status||500;c.status(f).json({error:x.error}),v?.end(f,!0);return}p.params=x.params,await x.handler(p,c),k()&&await H("afterRequest",p,c),c.headersSent||c.end(),v?.end(c.statusCode||200);}catch(E){await P(p,c,E),c.headersSent||c.status(500).json({error:"Internal Server Error"}),v?.end(c.statusCode||500,true);}},h=(p,c)=>{let v=s&&a?a.trackRequest():null;if(l.length>0)for(let E=0;E<l.length;E++)c.setHeader(l[E][0],l[E][1]);u(p,c,v).catch(E=>{s&&console.error("Fatal error:",E),c.headersSent||(c.statusCode=500,c.end("Server Error")),v?.end(500,true);});},g={IncomingMessage:fe,ServerResponse:pe},R=r.httpsOptions?Qe.createServer({...g,...r.httpsOptions},h):he.createServer(g,h);R.on("clientError",(p,c)=>{c.destroyed||c.destroy();});let w=r.httpsOptions?"https":"http";return U.isWorker&&ue().start(),R.listen(n,()=>{i?.enabled?s&&y(`Worker ${process.pid} is listening on port ${n}`):(y(`\u{1F680} Server running at ${w}://localhost:${n}/`+(s?" (dev)":"")),s&&a&&y(`\u{1F4CA} Performance monitoring available at http://localhost:${n}/health`));}),R}return null}}};var Le={name:"vercel",createHandler:t=>{if(typeof t=="string")throw new Error("vercelAdapter.createHandler() requires a ServerlessConfig object, not a routesDir string. Import your routes manifest and pass { routes } instead.");let e=null,r=()=>e||(e=(async()=>{V(t.routes),L(t.cors),I(t.middleware);})(),e);return async(n,o)=>{await r(),Z(n),re(o);let s=n,i=o;try{if(k()&&(await H("beforeRequest",s,i)===!1||i.headersSent))return;let d=j(ee(s.url??"/"),s.method??"GET");if(!d){i.status(404).json({error:"Route not found"});return}if(J(d)){i.status(d.status??500).json({error:d.error});return}s.params=d.params,await d.handler(s,i),k()&&await H("afterRequest",s,i);}catch(d){await P(s,i,d),i.headersSent||i.status(500).json({error:"Internal server error"});}}}};function me(t,e,r,n){let o=Object.keys(r).length>0;return {statusCode:t,headers:e,...o?{multiValueHeaders:r}:{},body:n}}var je={name:"netlify",createHandler:t=>{if(typeof t=="string")throw new Error("netlifyAdapter.createHandler() requires a ServerlessConfig object. Run `lacis build` to generate routes/_manifest.ts and pass { routes } instead.");let e=null,r=()=>e||(e=(async()=>{V(t.routes),L(t.cors),I(t.middleware);})(),e);return async(n,o)=>{await r();let s=n.queryStringParameters?"?"+new URLSearchParams(n.queryStringParameters).toString():"",i=n.path+s,d=new IncomingMessage(new Socket);if(d.url=i,d.method=n.httpMethod,d.headers=n.headers,n.body){let p=n.isBase64Encoded?"base64":"utf-8";d.push(Buffer.from(n.body,p));}d.push(null);let a="",l={},u={},h=false,g=new ServerResponse(d);g.writeHead=function(p,c){return g.statusCode=p,c&&(l={...l,...c}),this},g.setHeader=function(p,c){let v=p.toLowerCase();return Array.isArray(c)?(u[v]=c.map(String),l[v]=String(c[0])):l[v]=String(c),this},g.getHeader=function(p){return l[p.toLowerCase()]},g.end=function(p){return h=true,p!==void 0&&(a=typeof p=="string"?p:p.toString()),this},Object.defineProperty(g,"headersSent",{get:()=>h}),Z(d),re(g);let R=d,w=g;R.query=n.queryStringParameters??{};try{if(k()&&(await H("beforeRequest",R,w)===!1||h))return me(w.statusCode,l,u,a);let p=j(n.path,n.httpMethod);return p?J(p)?{statusCode:p.status??500,body:JSON.stringify({error:p.error})}:(R.params=p.params,await p.handler(R,w),k()&&await H("afterRequest",R,w),me(w.statusCode,l,u,a)):{statusCode:404,body:JSON.stringify({error:"Route not found"})}}catch(p){return await P(R,w,p),h?me(w.statusCode,l,u,a):{statusCode:500,body:JSON.stringify({error:"Internal server error"})}}}}};var it=10485760,lt=new TextEncoder,ge=class{params={};url;method;headers;socket={setTimeout:e=>{}};connection;_req;constructor(e,r,n,o){this._req=e,this.url=r+n,this.method=e.method,this.headers=e.headers,this.connection={remoteAddress:o};}setTimeout(e){}text(){return this._req.text()}body(){return this._req.arrayBuffer().then(e=>{if(e.byteLength>it)throw Object.assign(new Error("Payload Too Large"),{code:413});return Buffer.from(e)})}},ye=class extends W(ge){json(){return this._req.json()}},Re=class{statusCode=200;headersSent=false;get finished(){return this.headersSent}get writableEnded(){return this.headersSent}_body=null;_headers=null;_sseReadable=null;_sseWriter=null;_sseWindowClosed=false;_listeners=null;on(e,r){return (e==="finish"||e==="close")&&(this._listeners||(this._listeners=[]),this._listeners.push(r)),this}once(e,r){return this.on(e,r)}emit(e){if((e==="finish"||e==="close")&&this._listeners)for(let r=0;r<this._listeners.length;r++)this._listeners[r]();return true}setHeader(e,r){if(this._headers||(this._headers=[]),Array.isArray(r))for(let n of r)this._headers.push(e,n);else this._headers.push(e,r);return this}getHeader(e){if(!this._headers)return;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r)return this._headers[n+1]}removeHeader(e){if(!this._headers)return this;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r){this._headers.splice(n,2);break}return this}hasHeader(e){if(!this._headers)return false;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r)return true;return false}writeHead(e,r){if(this.statusCode=e,r)for(let[n,o]of Object.entries(r))this.setHeader(n,o);return this}write(e){return this._sseWriter?(this._sseWriter.write(lt.encode(String(e))),true):(this._body=(this._body??"")+e,true)}end(e){if(e!==void 0&&this.write(e),this._sseWriter&&this._sseWriter.close(),this.headersSent=true,this._listeners)for(let r=0;r<this._listeners.length;r++)this._listeners[r]();return this}_initSseStream(){if(this._sseWindowClosed)throw new Error("[lacis/bun] initSSE() must be called synchronously before any `await` in your handler.");let{readable:e,writable:r}=new TransformStream;this._sseReadable=e,this._sseWriter=r.getWriter();}_closeSseWindow(){this._sseWindowClosed=true;}},we=class extends F(Re){initSSE(e){return this._initSseStream(),super.initSSE(e)}},Ue={name:"bun",createHandler:t=>{if(typeof t!="string")throw new Error("bunAdapter requires a routesDir string, not a ServerlessConfig.");let e=t;return async(r={})=>{let{isDev:n,port:o=3e3,defaultHeaders:s,cluster:i}=r,d=parseInt(process.env.LACIS_BUN_WORKER??"0"),a=d>0;if(i?.enabled&&!a){let h=i.workers??q__default.cpus().length;y(`\u{1F9F5} Starting Bun server with ${h} workers (reusePort)`);let g=Array.from({length:h},()=>Bun.spawn(process.argv,{env:{...process.env,LACIS_BUN_WORKER:String(process.pid)},stdout:"ignore",stderr:"inherit"}));return y(`\u{1F680} Server running at http://localhost:${o}/`),{close:R=>{for(let w of g)w.kill();R?.();}}}if(a){let h=setInterval(()=>{try{process.kill(d,0);}catch{clearInterval(h),process.exit(0);}},2e3);h.unref();}y("\u{1F680} Bun high-performance mode enabled"),r.routes||await G(e),L(r.cors),I(r.middleware);let l=s?Object.entries(s):[],u=Bun.serve({port:o,reusePort:a,async fetch(h,g){let R=new URL(h.url),w=R.pathname,p=new ye(h,w,R.search,g?.requestIP(h)?.address??"");p.query=te(R.search);let c=new we;try{for(let x=0;x<l.length;x++)c.setHeader(l[x][0],l[x][1]);if(k()&&(!await H("beforeRequest",p,c)||c.headersSent))return ne(c);let v=j(w,h.method);if(!v)return k()&&await H("onError",p,c),new Response(JSON.stringify({error:"Route not found"}),{status:404,headers:{"Content-Type":"application/json"}});if("error"in v)return k()&&await H("onError",p,c),new Response(JSON.stringify({error:v.error}),{status:v.status||500,headers:{"Content-Type":"application/json"}});p.params=v.params;let E=null,O=(async()=>{await v.handler(p,c),k()&&await H("afterRequest",p,c),c.headersSent||c.end();})().catch(x=>{E=x,n&&console.error("Server error:",x),c._sseReadable&&!c.headersSent&&c.end();});return c._closeSseWindow(),c._sseReadable?ne(c,c._sseReadable):(await O,E&&(await P(p,c,E),!c.headersSent)?new Response(JSON.stringify({error:"Internal Server Error"}),{status:500,headers:{"Content-Type":"application/json"}}):ne(c))}catch(v){return await P(p,c,v),c.headersSent?ne(c):new Response(JSON.stringify({error:"Internal Server Error"}),{status:500,headers:{"Content-Type":"application/json"}})}}});return y(`\u{1F680} Server started on http://localhost:${o}${n?" (dev)":""}`),{close:()=>{u.stop();}}}}};function ne(t,e){let r=e??t._body;if(!t._headers)return new Response(r,{status:t.statusCode});let n=new Headers;for(let o=0;o<t._headers.length;o+=2){let s=t._headers[o],i=t._headers[o+1];s.toLowerCase()==="set-cookie"?n.append(s,i):n.set(s,i);}return new Response(r,{status:t.statusCode,headers:n})}var dt={node:Ie,vercel:Le,netlify:je,bun:Ue};function Tr(t="node"){let e=dt[t];if(!e)throw new Error(`Platform "${t}" not supported`);return e}
|
|
26
|
-
export{xe as A,Te as B,_e as C,ke as D,He as E,Ie as F,Le as G,je as H,Ue as I,
|
|
24
|
+
`);if(p===-1)continue;let c=w.subarray(0,p).toString(),v=w.subarray(p+4,w.length-2),E=c.match(/Content-Disposition: form-data; name="([^"]+)"(?:; filename="([^"]+)")?/i);if(E)if(E[2]){let $=c.match(/Content-Type:\s*([^\r\n]+)/i);a[E[1]]={filename:E[2],mimetype:$?$[1].trim():"application/octet-stream",data:v,size:v.length};}else a[E[1]]=v.toString("utf-8");}e(a);}).catch(r);})}createSSEClient(e,r){return Se(this,e,r)}}}function Y(){let t=[],e=0,r=false;return new Promise((n,o)=>{this.on("data",s=>{if(e+=s.length,e>Ze){r=true,this.destroy(),o(Object.assign(new Error("Payload Too Large"),{code:413}));return}t.push(s);}).on("end",()=>{r||(r=true,n(Buffer.concat(t)));}).on("error",s=>{r||(r=true,o(s));});})}function Ae(t,e){let r=t.serialize();r.length>0&&!e.headersSent&&e.setHeader("Set-Cookie",r);}function J(t){return class extends t{_zresCookies;get cookies(){return this._zresCookies||(this._zresCookies=new X),this._zresCookies}end(e){return this._zresCookies&&Ae(this._zresCookies,this),super.end(e)}status(e){return this.statusCode=e,this}send(e){return typeof e=="string"?(this.setHeader("Content-Type","text/plain"),this.end(e)):this.json(e),this}json(e){return this.setHeader("Content-Type","application/json"),this.end(JSON.stringify(e)),this}html(e){return this.setHeader("Content-Type","text/html; charset=utf-8"),this.end(e),this}redirect(e,r=302){return this.statusCode=r,this.setHeader("Location",e),this.end(),this}initSSE(e){return ve(this,e)}sseSend(e){Ee(this,e);}sseJson(e){be(this,e);}sseEvent(e,r){Me(this,e,r);}sseComment(e){xe(this,e);}sseId(e){Te(this,e);}sseRetry(e){_e(this,e);}sseClose(e){ke(this,e);}sseError(e,r,n=500,o){He(this,e,r,n,o);}}}var de=class{params={};headers={};body(){return Y.call(this)}},K=z(de).prototype,ue=class{statusCode=200;headersSent=false;setHeader(e,r){}end(e){}write(e){}},et=J(ue).prototype;function Z(t){t.body=Y,t.json=K.json,t.form=K.form,t.getHeader=K.getHeader,t.createSSEClient=K.createSSEClient,t.cookies=new Q(qe(t.headers));}function ee(t){let e=t.indexOf("?");return e===-1?t:t.slice(0,e)}function te(t){let e=t.indexOf("?");return e===-1?{}:Object.fromEntries(new URLSearchParams(t.slice(e+1)).entries())}async function P(t,e,r){console.error("[lacis] Unhandled error:",r),k()&&await H("onError",t,e,{error:r});}function re(t){let e=et;t.status=e.status,t.send=e.send,t.json=e.json,t.html=e.html,t.redirect=e.redirect,t.initSSE=e.initSSE,t.sseSend=e.sseSend,t.sseJson=e.sseJson,t.sseEvent=e.sseEvent,t.sseComment=e.sseComment,t.sseId=e.sseId,t.sseRetry=e.sseRetry,t.sseClose=e.sseClose,t.sseError=e.sseError;let r=new X;t.cookies=r;let n=t.end.bind(t);t.end=function(...o){return Ae(r,this),n(...o)};}var se=null;function rt(t={}){let e=new EventEmitter,r={sampleInterval:t.sampleInterval||5e3,reportInterval:t.reportInterval||6e4,resetInterval:t.resetInterval||1440*60*1e3,enableHistogram:t.enableHistogram!==void 0?t.enableHistogram:true,logToConsole:t.logToConsole!==void 0?t.logToConsole:true,thresholds:{cpu:t.thresholds?.cpu||80,memory:t.thresholds?.memory||80,responseTime:t.thresholds?.responseTime||1e3,errorRate:t.thresholds?.errorRate||5}},n=Date.now(),o={requestCount:0,activeRequests:0,errorCount:0,responseTimes:[],responseTimesBucket:Array(100).fill(0),statusCodes:{},lastReport:n,lastReset:n},s=l(),i=[],d=process.cpuUsage(),a={cpu:false,memory:false,responseTime:false,errorRate:false};function l(){return {timestamp:Date.now(),uptime:process.uptime(),requestCount:0,activeRequests:0,errorCount:0,responseTimes:{min:0,max:0,avg:0,count:0,sum:0},statusCodes:{},memory:process.memoryUsage(),cpu:{usage:0,system:0,user:0},systemLoad:q.loadavg(),systemMemory:{total:q.totalmem(),free:q.freemem(),used:q.totalmem()-q.freemem()}}}function u(){let f=o.responseTimes;if(f.length===0)return {min:0,max:0,avg:0,count:0,sum:0};let m=1/0,S=-1/0,M=0;for(let b of f)m=Math.min(m,b),S=Math.max(S,b),M+=b;let A=M/f.length,C={min:m,max:S,avg:A,count:f.length,sum:M};if(r.enableHistogram){let b=[...f].sort((_,W)=>_-W);C.p50=b[Math.floor(b.length*.5)],C.p90=b[Math.floor(b.length*.9)],C.p99=b[Math.floor(b.length*.99)];}return C}function h(){let f=Date.now(),m=process.uptime(),S=process.memoryUsage(),M=process.cpuUsage(d);d=process.cpuUsage();let C=(M.user+M.system)/1e3/r.sampleInterval*100;s={timestamp:f,uptime:m,requestCount:o.requestCount,activeRequests:o.activeRequests,errorCount:o.errorCount,responseTimes:u(),statusCodes:{...o.statusCodes},memory:S,cpu:{usage:C,system:M.system,user:M.user},systemLoad:q.loadavg(),systemMemory:{total:q.totalmem(),free:q.freemem(),used:q.totalmem()-q.freemem()}},i.push({...s}),i.length>100&&i.shift(),w(),D.isWorker&&process.send&&process.send({type:"metrics",metrics:s});}function g(){if(!r.logToConsole||D.isPrimary===false)return;let f={rss:(s.memory.rss/1024/1024).toFixed(2),heapTotal:(s.memory.heapTotal/1024/1024).toFixed(2),heapUsed:(s.memory.heapUsed/1024/1024).toFixed(2)},m=Date.now()-o.lastReport,S=(s.requestCount/(m/1e3)).toFixed(2),M=s.requestCount?(s.errorCount/s.requestCount*100).toFixed(2):"0.00";y(`
|
|
25
|
+
\u{1F4CA} Server Performance Metrics \u{1F4CA}`),y(`Uptime: ${p(s.uptime)}`),y(`Load: ${s.systemLoad[0].toFixed(2)}, ${s.systemLoad[1].toFixed(2)}, ${s.systemLoad[2].toFixed(2)}`),y(`Requests: ${s.requestCount} total, ${S} req/sec`),y(`Active Requests: ${s.activeRequests}`),y(`Errors: ${s.errorCount} (${M}%)`),s.responseTimes.count>0&&(y(`Response Times: avg ${s.responseTimes.avg.toFixed(2)}ms, min ${s.responseTimes.min}ms, max ${s.responseTimes.max}ms`),s.responseTimes.p50&&y(`Response Time Percentiles: p50 ${s.responseTimes.p50}ms, p90 ${s.responseTimes.p90}ms, p99 ${s.responseTimes.p99}ms`)),y(`Memory: ${f.rss}MB (RSS), ${f.heapUsed}MB / ${f.heapTotal}MB (Heap)`),y(`CPU Usage: ${s.cpu.usage.toFixed(2)}%`),Object.keys(s.statusCodes).length>0&&(y("Status Codes:"),Object.entries(s.statusCodes).sort(([A],[C])=>parseInt(A)-parseInt(C)).forEach(([A,C])=>{y(` ${A}: ${C}`);})),y(""),o.lastReport=Date.now();}function R(){let f=Date.now();o.requestCount=0,o.activeRequests=0,o.errorCount=0,o.responseTimes=[],o.responseTimesBucket=Array(100).fill(0),o.statusCodes={},o.lastReport=f,o.lastReset=f,y("\u{1F504} Performance metrics have been reset");}function w(){let f=s.memory.heapUsed/s.memory.heapTotal*100,m=s.requestCount?s.errorCount/s.requestCount*100:0,S=s.responseTimes.avg;s.cpu.usage>r.thresholds.cpu&&!a.cpu?(a.cpu=true,e.emit("alarm","cpu",`High CPU usage: ${s.cpu.usage.toFixed(2)}%`)):s.cpu.usage<=r.thresholds.cpu&&a.cpu&&(a.cpu=false,e.emit("alarm-clear","cpu",`CPU usage returned to normal: ${s.cpu.usage.toFixed(2)}%`)),f>r.thresholds.memory&&!a.memory?(a.memory=true,e.emit("alarm","memory",`High memory usage: ${f.toFixed(2)}%`)):f<=r.thresholds.memory&&a.memory&&(a.memory=false,e.emit("alarm-clear","memory",`Memory usage returned to normal: ${f.toFixed(2)}%`)),S>r.thresholds.responseTime&&!a.responseTime?(a.responseTime=true,e.emit("alarm","responseTime",`High response time: ${S.toFixed(2)}ms`)):S<=r.thresholds.responseTime&&a.responseTime&&(a.responseTime=false,e.emit("alarm-clear","responseTime",`Response time returned to normal: ${S.toFixed(2)}ms`)),m>r.thresholds.errorRate&&!a.errorRate?(a.errorRate=true,e.emit("alarm","errorRate",`High error rate: ${m.toFixed(2)}%`)):m<=r.thresholds.errorRate&&a.errorRate&&(a.errorRate=false,e.emit("alarm-clear","errorRate",`Error rate returned to normal: ${m.toFixed(2)}%`));}function p(f){let m=Math.floor(f/86400),S=Math.floor(f%86400/3600),M=Math.floor(f%3600/60),A=Math.floor(f%60),C=[];return m>0&&C.push(`${m}d`),S>0&&C.push(`${S}h`),M>0&&C.push(`${M}m`),(A>0||C.length===0)&&C.push(`${A}s`),C.join(" ")}function c(){let f=setInterval(h,r.sampleInterval),m=setInterval(g,r.reportInterval),S=setInterval(R,r.resetInterval);return {stop:()=>{clearInterval(f),clearInterval(m),clearInterval(S);}}}function v(){let f=Date.now();return o.activeRequests++,{end:(m,S=false)=>{let M=Date.now()-f;return o.activeRequests--,o.requestCount++,o.responseTimes.push(M),o.responseTimes.length>1e3&&o.responseTimes.shift(),o.statusCodes[m]=(o.statusCodes[m]||0)+1,(S||m>=500)&&o.errorCount++,M}}}function E(){return !Object.values(a).some(f=>f)}function $(){let f=s.memory.heapUsed/s.memory.heapTotal*100,m=s.requestCount?s.errorCount/s.requestCount*100:0;return {status:E()?"healthy":"unhealthy",uptime:s.uptime,responseTimes:{avg:s.responseTimes.avg,p90:s.responseTimes.p90||null,p99:s.responseTimes.p99||null},memory:{usedMB:Math.round(s.memory.heapUsed/1024/1024),totalMB:Math.round(s.memory.heapTotal/1024/1024),percent:f.toFixed(2)},cpu:s.cpu.usage.toFixed(2),requests:{total:s.requestCount,active:s.activeRequests,errors:s.errorCount,errorRate:m.toFixed(2)},alerts:Object.entries(a).filter(([S,M])=>M).map(([S])=>S)}}let x=c();return {trackRequest:v,getMetrics:()=>({...s}),getMetricsHistory:()=>[...i],getHealthMetrics:$,isHealthy:E,stop:x.stop,on:e.on.bind(e),once:e.once.bind(e),off:e.off.bind(e)}}function $e(t){if(!se){let e=rt(t),r=e.stop;e.stop=()=>{r(),se=null;},se=e;}return se}function ce(t={}){let e=t.reportInterval??5e3,r={workers:new Map,workerIds:[]};function n(){if(!D.isWorker)return;let l=process.cpuUsage(),u=()=>{if(!process.send)return;let h=process.memoryUsage(),g=process.cpuUsage(l);l=process.cpuUsage();let R=(g.user+g.system)/(e*1e3),w={type:"stats",stats:{pid:process.pid,load:R,lastUsed:Date.now(),memoryUsage:h}};process.send(w);};u(),setInterval(u,e).unref();}function o(){let l=D.fork();r.workers.set(l.id,{pid:l.process.pid,load:0,lastUsed:Date.now(),memoryUsage:{rss:0,heapTotal:0,heapUsed:0,external:0,arrayBuffers:0}}),r.workerIds.push(l.id),y(`Worker ${l.process.pid} started`);}let s=false,i=[];function d(l=q.cpus().length){if(!D.isPrimary)return n();y(`\u{1F9F5} Launching ${l} workers...`);for(let u=0;u<l;u++)o();D.on("message",(u,h)=>{if(h.type==="stats"&&"stats"in h){let g=r.workers.get(u.id);g&&Object.assign(g,h.stats);}}),D.on("exit",(u,h,g)=>{if(r.workers.delete(u.id),r.workerIds=r.workerIds.filter(R=>R!==u.id),s){i.forEach(R=>R());return}y(`Worker ${u.process.pid} died (${g||h}). Restarting...`),setTimeout(()=>o(),1e3);});}function a(l){s=true;let u=Object.keys(D.workers??{});if(u.length===0){l?.();return}let h=u.length;i.push(()=>{h--,h===0&&l?.();});for(let g of u)D.workers?.[g]?.kill();}return {start:d,shutdown:a,getWorkerStats:()=>Array.from(r.workers.entries()),getActiveWorkerCount:()=>r.workerIds.length}}var fe=class extends me.IncomingMessage{params={};body=Y},pe=class extends z(fe){},he=class extends J(me.ServerResponse){},Ie={name:"node",createHandler:t=>{if(typeof t!="string")throw new Error("nodeAdapter requires a routesDir string, not a ServerlessConfig.");let e=t;return async(r={})=>{let{port:n=3e3,defaultHeaders:o,isDev:s,cluster:i,monitoring:d={enabled:false}}=r,a=null;s&&d.enabled&&(a=$e({sampleInterval:d.sampleInterval||5e3,reportInterval:d.reportInterval||6e4,thresholds:d.thresholds,logToConsole:true}),D.isPrimary&&(y("\u{1F4CA} Development performance monitoring enabled"),a.on("alarm",(u,h)=>{y(`\u26A0\uFE0F ALERT: ${h}`);}),a.on("alarm-clear",(u,h)=>{y(`\u2705 RESOLVED: ${h}`);})));let l=o?Object.entries(o):[];if(i?.enabled&&D.isPrimary){let u=i.workers??q__default.cpus().length,h=r.httpsOptions?"https":"http";if(y(`\u{1F9F5} Starting server with ${u} workers`),D.schedulingPolicy!==void 0)try{D.schedulingPolicy=D.SCHED_RR;}catch{}let g=ce();return g.start(u),y(`\u{1F680} Server running at ${h}://localhost:${n}/`+(s?" (dev)":"")),s&&a&&y(`\u{1F4CA} Performance monitoring available at http://localhost:${n}/health`),{close:R=>{a&&a.stop(),g.shutdown(R);}}}if(D.isWorker||!i?.enabled){r.routes||await G(e),L(r.cors),I(r.middleware);let u=async(p,c,v)=>{try{if(s&&a&&p.url==="/health"){c.setHeader("Content-Type","application/json"),c.end(JSON.stringify(a.getHealthMetrics())),v?.end(200);return}let E=p.url||"/",$=ee(E);if(p.query=te(E),k()&&(await H("beforeRequest",p,c)===!1||c.headersSent)){v?.end(c.statusCode||204);return}let x=j($,p.method||"GET");if(!x){k()&&await H("onError",p,c),c.status(404).json({error:"Route not found"}),v?.end(404);return}if("error"in x){let f=x.status||500;c.status(f).json({error:x.error}),v?.end(f,!0);return}p.params=x.params,await x.handler(p,c),k()&&await H("afterRequest",p,c),c.headersSent||c.end(),v?.end(c.statusCode||200);}catch(E){await P(p,c,E),c.headersSent||c.status(500).json({error:"Internal Server Error"}),v?.end(c.statusCode||500,true);}},h=(p,c)=>{let v=s&&a?a.trackRequest():null;if(l.length>0)for(let E=0;E<l.length;E++)c.setHeader(l[E][0],l[E][1]);u(p,c,v).catch(E=>{s&&console.error("Fatal error:",E),c.headersSent||(c.statusCode=500,c.end("Server Error")),v?.end(500,true);});},g={IncomingMessage:pe,ServerResponse:he},R=r.httpsOptions?Ye.createServer({...g,...r.httpsOptions},h):me.createServer(g,h);R.on("clientError",(p,c)=>{c.destroyed||c.destroy();});let w=r.httpsOptions?"https":"http";return D.isWorker&&ce().start(),R.listen(n,()=>{i?.enabled?s&&y(`Worker ${process.pid} is listening on port ${n}`):(y(`\u{1F680} Server running at ${w}://localhost:${n}/`+(s?" (dev)":"")),s&&a&&y(`\u{1F4CA} Performance monitoring available at http://localhost:${n}/health`));}),R}return null}}};var Le={name:"vercel",createHandler:t=>{if(typeof t=="string")throw new Error("vercelAdapter.createHandler() requires a ServerlessConfig object, not a routesDir string. Import your routes manifest and pass { routes } instead.");let e=null,r=()=>e||(e=(async()=>{F(t.routes),L(t.cors),I(t.middleware);})(),e);return async(n,o)=>{await r(),Z(n),re(o);let s=n,i=o;try{if(k()&&(await H("beforeRequest",s,i)===!1||i.headersSent))return;let d=j(ee(s.url??"/"),s.method??"GET");if(!d){i.status(404).json({error:"Route not found"});return}if(V(d)){i.status(d.status??500).json({error:d.error});return}s.params=d.params,await d.handler(s,i),k()&&await H("afterRequest",s,i);}catch(d){await P(s,i,d),i.headersSent||i.status(500).json({error:"Internal server error"});}}}};function ge(t,e,r,n){let o=Object.keys(r).length>0;return {statusCode:t,headers:e,...o?{multiValueHeaders:r}:{},body:n}}var je={name:"netlify",createHandler:t=>{if(typeof t=="string")throw new Error("netlifyAdapter.createHandler() requires a ServerlessConfig object. Run `lacis build` to generate routes/_manifest.ts and pass { routes } instead.");let e=null,r=()=>e||(e=(async()=>{F(t.routes),L(t.cors),I(t.middleware);})(),e);return async(n,o)=>{await r();let s=n.queryStringParameters?"?"+new URLSearchParams(n.queryStringParameters).toString():"",i=n.path+s,d=new IncomingMessage(new Socket);if(d.url=i,d.method=n.httpMethod,d.headers=n.headers,n.body){let p=n.isBase64Encoded?"base64":"utf-8";d.push(Buffer.from(n.body,p));}d.push(null);let a="",l={},u={},h=false,g=new ServerResponse(d);g.writeHead=function(p,c){return g.statusCode=p,c&&(l={...l,...c}),this},g.setHeader=function(p,c){let v=p.toLowerCase();return Array.isArray(c)?(u[v]=c.map(String),l[v]=String(c[0])):l[v]=String(c),this},g.getHeader=function(p){return l[p.toLowerCase()]},g.end=function(p){return h=true,p!==void 0&&(a=typeof p=="string"?p:p.toString()),this},Object.defineProperty(g,"headersSent",{get:()=>h}),Z(d),re(g);let R=d,w=g;R.query=n.queryStringParameters??{};try{if(k()&&(await H("beforeRequest",R,w)===!1||h))return ge(w.statusCode,l,u,a);let p=j(n.path,n.httpMethod);return p?V(p)?{statusCode:p.status??500,body:JSON.stringify({error:p.error})}:(R.params=p.params,await p.handler(R,w),k()&&await H("afterRequest",R,w),ge(w.statusCode,l,u,a)):{statusCode:404,body:JSON.stringify({error:"Route not found"})}}catch(p){return await P(R,w,p),h?ge(w.statusCode,l,u,a):{statusCode:500,body:JSON.stringify({error:"Internal server error"})}}}}};var dt=10485760,ut=new TextEncoder,ye=class{params={};url;method;headers;socket={setTimeout:e=>{}};connection;_req;constructor(e,r,n,o){this._req=e,this.url=r+n,this.method=e.method,this.headers=e.headers,this.connection={remoteAddress:o};}setTimeout(e){}text(){return this._req.text()}body(){return this._req.arrayBuffer().then(e=>{if(e.byteLength>dt)throw Object.assign(new Error("Payload Too Large"),{code:413});return Buffer.from(e)})}},Re=class extends z(ye){json(){return this._req.json()}},we=class{statusCode=200;headersSent=false;get finished(){return this.headersSent}get writableEnded(){return this.headersSent}_body=null;_headers=null;_sseReadable=null;_sseWriter=null;_sseWindowClosed=false;_listeners=null;on(e,r){return (e==="finish"||e==="close")&&(this._listeners||(this._listeners=[]),this._listeners.push(r)),this}once(e,r){return this.on(e,r)}emit(e){if((e==="finish"||e==="close")&&this._listeners)for(let r=0;r<this._listeners.length;r++)this._listeners[r]();return true}setHeader(e,r){if(this._headers||(this._headers=[]),Array.isArray(r))for(let n of r)this._headers.push(e,n);else this._headers.push(e,r);return this}getHeader(e){if(!this._headers)return;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r)return this._headers[n+1]}removeHeader(e){if(!this._headers)return this;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r){this._headers.splice(n,2);break}return this}hasHeader(e){if(!this._headers)return false;let r=e.toLowerCase();for(let n=0;n<this._headers.length;n+=2)if(this._headers[n].toLowerCase()===r)return true;return false}writeHead(e,r){if(this.statusCode=e,r)for(let[n,o]of Object.entries(r))this.setHeader(n,o);return this}write(e){return this._sseWriter?(this._sseWriter.write(ut.encode(String(e))),true):(this._body=(this._body??"")+e,true)}end(e){if(e!==void 0&&this.write(e),this._sseWriter&&this._sseWriter.close(),this.headersSent=true,this._listeners)for(let r=0;r<this._listeners.length;r++)this._listeners[r]();return this}_initSseStream(){if(this._sseWindowClosed)throw new Error("[lacis/bun] initSSE() must be called synchronously before any `await` in your handler.");let{readable:e,writable:r}=new TransformStream;this._sseReadable=e,this._sseWriter=r.getWriter();}_closeSseWindow(){this._sseWindowClosed=true;}},Ce=class extends J(we){initSSE(e){return this._initSseStream(),super.initSSE(e)}},Ue={name:"bun",createHandler:t=>{if(typeof t!="string")throw new Error("bunAdapter requires a routesDir string, not a ServerlessConfig.");let e=t;return async(r={})=>{let{isDev:n,port:o=3e3,defaultHeaders:s,cluster:i}=r,d=parseInt(process.env.LACIS_BUN_WORKER??"0"),a=d>0;if(i?.enabled&&!a){let h=i.workers??q__default.cpus().length;y(`\u{1F9F5} Starting Bun server with ${h} workers (reusePort)`);let g=Array.from({length:h},()=>Bun.spawn(process.argv,{env:{...process.env,LACIS_BUN_WORKER:String(process.pid)},stdout:"ignore",stderr:"inherit"}));return y(`\u{1F680} Server running at http://localhost:${o}/`),{close:R=>{for(let w of g)w.kill();R?.();}}}if(a){let h=setInterval(()=>{try{process.kill(d,0);}catch{clearInterval(h),process.exit(0);}},2e3);h.unref();}y("\u{1F680} Bun high-performance mode enabled"),r.routes||await G(e),L(r.cors),I(r.middleware);let l=s?Object.entries(s):[],u=Bun.serve({port:o,reusePort:a,async fetch(h,g){let R=new URL(h.url),w=R.pathname,p=new Re(h,w,R.search,g?.requestIP(h)?.address??"");p.query=te(R.search);let c=new Ce;try{for(let x=0;x<l.length;x++)c.setHeader(l[x][0],l[x][1]);if(k()&&(!await H("beforeRequest",p,c)||c.headersSent))return ne(c);let v=j(w,h.method);if(!v)return k()&&await H("onError",p,c),new Response(JSON.stringify({error:"Route not found"}),{status:404,headers:{"Content-Type":"application/json"}});if("error"in v)return k()&&await H("onError",p,c),new Response(JSON.stringify({error:v.error}),{status:v.status||500,headers:{"Content-Type":"application/json"}});p.params=v.params;let E=null,$=(async()=>{await v.handler(p,c),k()&&await H("afterRequest",p,c),c.headersSent||c.end();})().catch(x=>{E=x,n&&console.error("Server error:",x),c._sseReadable&&!c.headersSent&&c.end();});return c._closeSseWindow(),c._sseReadable?ne(c,c._sseReadable):(await $,E&&(await P(p,c,E),!c.headersSent)?new Response(JSON.stringify({error:"Internal Server Error"}),{status:500,headers:{"Content-Type":"application/json"}}):ne(c))}catch(v){return await P(p,c,v),c.headersSent?ne(c):new Response(JSON.stringify({error:"Internal Server Error"}),{status:500,headers:{"Content-Type":"application/json"}})}}});return y(`\u{1F680} Server started on http://localhost:${o}${n?" (dev)":""}`),{close:()=>{u.stop();}}}}};function ne(t,e){let r=e??t._body;if(!t._headers)return new Response(r,{status:t.statusCode});let n=new Headers;for(let o=0;o<t._headers.length;o+=2){let s=t._headers[o],i=t._headers[o+1];s.toLowerCase()==="set-cookie"?n.append(s,i):n.set(s,i);}return new Response(r,{status:t.statusCode,headers:n})}var ct={node:Ie,vercel:Le,netlify:je,bun:Ue};function qr(t="node"){let e=ct[t];if(!e)throw new Error(`Platform "${t}" not supported`);return e}
|
|
26
|
+
export{xe as A,Te as B,_e as C,ke as D,He as E,Ie as F,Le as G,je as H,Ue as I,qr as J,ae as a,ht as b,Be as c,k as d,H as e,ie as f,mt as g,gt as h,I as i,y as j,U as k,V as l,F as m,G as n,j as o,_t as p,kt as q,Ht as r,qt as s,We as t,L as u,Se as v,ve as w,Ee as x,be as y,Me as z};
|
package/dist/cli/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {resolve,join,relative}from'path';import {writeFile,readdir}from'fs/promises';import {
|
|
3
|
-
`),
|
|
4
|
-
`),
|
|
5
|
-
`);await writeFile(join(e,"_manifest.ts"),
|
|
2
|
+
import {resolve,join,relative}from'path';import {unlink,writeFile,readdir}from'fs/promises';import {spawn}from'child_process';import {watch,existsSync,readFileSync}from'fs';async function N(e){let t=[];async function n(o,s=[]){let c;try{c=await readdir(o,{withFileTypes:!0});}catch{return}let r=c.find(i=>!i.isDirectory()&&(i.name==="index.ts"||i.name==="index.js"));if(r){let i="./"+relative(e,join(o,r.name)).replace(/\\/g,"/").replace(/\.ts$/,".js"),u="/"+s.map(m=>m.replace(/^\[(\w+)\??\]$/,":$1")).join("/");t.push({importPath:i,routePath:u==="//"?"/":u});}for(let i of c)i.isDirectory()&&!i.name.startsWith("+")&&await n(join(o,i.name),[...s,i.name]);}return await n(e),t}async function f(e){let t=await N(e),n=t.map((c,r)=>`import * as _route_${r} from '${c.importPath}'`).join(`
|
|
3
|
+
`),o=t.map((c,r)=>` { path: '${c.routePath}', handlers: _route_${r} }`).join(`,
|
|
4
|
+
`),s=["// AUTO-GENERATED by lacis build \u2014 do not edit",n,"","export const routes = [",o,"]",""].join(`
|
|
5
|
+
`);await writeFile(join(e,"_manifest.ts"),s,"utf-8"),console.log(`[lacis] Generated manifest with ${t.length} route(s)`);}function R(e){if(existsSync(join(e,"netlify.toml")))return "netlify";if(existsSync(join(e,"vercel.json")))return "vercel";try{let t=JSON.parse(readFileSync(join(e,"package.json"),"utf-8")),n={...t.dependencies,...t.devDependencies};if(n["@netlify/functions"]||n["netlify-cli"])return "netlify";if(n.vercel||n["@vercel/node"])return "vercel"}catch{}return process.versions.bun!==void 0||existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?"bun":"node"}function S(e){try{let t=JSON.parse(readFileSync(join(e,"package.json"),"utf-8")),n=t.module??t.main;if(typeof n=="string"&&existsSync(join(e,n)))return n}catch{}for(let t of ["server.ts","index.ts","app.ts","main.ts"])if(existsSync(join(e,t)))return t;return null}function F(e){try{return JSON.parse(readFileSync(join(e,"tsconfig.json"),"utf-8")).compilerOptions?.outDir??null}catch{return null}}async function v(e){let t=[],n;try{n=await readdir(e,{withFileTypes:!0});}catch{return t}for(let o of n)o.isDirectory()?t.push(...await v(join(e,o.name))):o.name.endsWith(".ts")&&o.name!=="_manifest.ts"&&t.push(join(e,o.name));return t}function D(e,t,n){return new Promise((o,s)=>{let c=spawn(e,t,{stdio:"inherit",cwd:n});c.on("close",r=>{r===0?o():s(new Error(`${e} exited with code ${r}`));}),c.on("error",r=>{r.code==="ENOENT"?s(new Error(`Command not found: ${e}. Make sure it is installed.`)):s(r);});})}async function b(e,t){let n=process.cwd(),o=R(n),s=join(e,"_manifest.ts");relative(n,s).replace(/\\/g,"/");if(await f(e),o==="vercel"||o==="netlify"){console.log(`[lacis] ${o} detected \u2014 manifest generated, platform handles compilation`);return}try{if(o==="bun"){let r=t??S(n);if(!r)throw new Error("Entry point not found. Specify one with --entry <file>.");let i=await v(e),u=[join(n,r),s,...i],m=await globalThis.Bun.build({entrypoints:u,outdir:join(n,"dist"),root:n,external:["*"],target:"bun"});if(!m.success){let T=m.logs.map(y=>y.message??String(y)).join(`
|
|
6
|
+
`);throw new Error(`Bun build failed:
|
|
7
|
+
${T}`)}}else {let r=join(n,"node_modules",".bin","tsc");if(!existsSync(r))throw new Error("TypeScript not found. Add it to your project: npm install --save-dev typescript");let i=F(n)??"dist";await D(r,["--outDir",i],n);}}finally{await unlink(s).catch(()=>{});}console.log("[lacis] Build complete \u2192 dist/");}async function d(e){await f(e);let t=null;watch(e,{recursive:true},(n,o)=>{!o||o==="_manifest.ts"||(t&&clearTimeout(t),t=setTimeout(async()=>{console.log(`[lacis] Route changed: ${o}, regenerating manifest...`);try{await f(e);}catch(s){console.error("[lacis] Failed to regenerate manifest:",s);}},100));});}function A(e){if(existsSync(join(e,"netlify.toml")))return "netlify";if(existsSync(join(e,"vercel.json")))return "vercel";try{let t=JSON.parse(readFileSync(join(e,"package.json"),"utf-8")),n={...t.dependencies,...t.devDependencies};if(n["@netlify/functions"]||n["netlify-cli"])return "netlify";if(n.vercel||n["@vercel/node"])return "vercel"}catch{}return "node"}async function P(e){let t=process.cwd();if(process.env.VERCEL==="1"){await f(e);return}if(process.env.NETLIFY==="true"){await d(e);return}let n=A(t);if(console.log(`[lacis] Detected platform: ${n}`),await d(e),n==="node"){console.log("[lacis] Node mode: watching routes for changes...");return}let[o,s]=n==="netlify"?["netlify",["dev"]]:["vercel",["dev"]],c=spawn(o,s,{stdio:"inherit",shell:true,cwd:t});c.on("error",i=>{i.code==="ENOENT"?console.error(`[lacis] ${o} CLI not found. Install it with: ${n==="netlify"?"npm i -g netlify-cli":"npm i -g vercel"}`):console.error(`[lacis] Failed to start ${o} dev:`,i.message);});let r=i=>{process.on(i,()=>c.kill(i));};r("SIGINT"),r("SIGTERM");}function B(e){let t=e.slice(2),n=t[0]??"",o=t.indexOf("--routes"),s=o!==-1?t[o+1]:void 0,c=s?resolve(process.cwd(),s):resolve(process.cwd(),"routes"),r=t.indexOf("--entry"),i=r!==-1?t[r+1]:void 0;return {command:n,routesDir:c,entry:i}}function J(){console.log(`
|
|
6
8
|
Usage: lacis <command> [options]
|
|
7
9
|
|
|
8
10
|
Commands:
|
|
9
|
-
build
|
|
11
|
+
build Compile project to dist/ (Node: tsc/tsup, Bun: bun build)
|
|
10
12
|
watch Watch routes and regenerate manifest on changes
|
|
11
13
|
dev Auto-detect platform and start dev server
|
|
12
14
|
|
|
@@ -14,4 +16,5 @@ To scaffold a new project: npm create lacis@latest
|
|
|
14
16
|
|
|
15
17
|
Options:
|
|
16
18
|
--routes <dir> Path to routes directory (default: ./routes)
|
|
17
|
-
|
|
19
|
+
--entry <file> Entry point for bundlers (default: auto-detected from package.json)
|
|
20
|
+
`);}async function C(){let{command:e,routesDir:t,entry:n}=B(process.argv);switch(e){case "build":await b(t,n);break;case "watch":await d(t);break;case "dev":await P(t);break;default:J(),e&&(console.error(`Unknown command: ${e}`),process.exit(1));}}C().catch(e=>{console.error("[lacis]",e),process.exit(1);});
|
|
@@ -38,6 +38,8 @@ interface Response extends ServerResponse {
|
|
|
38
38
|
body?: any;
|
|
39
39
|
cookies: ResponseCookies;
|
|
40
40
|
json(data: any): void;
|
|
41
|
+
html(data: string): void;
|
|
42
|
+
redirect(url: string, status?: number): void;
|
|
41
43
|
send(data: any): void;
|
|
42
44
|
status(code: number): Response;
|
|
43
45
|
initSSE(options?: SSEOptions): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ServerConfig, A as AdapterRequest, a as AdapterResponse, R as Request, b as Response, c as ServerlessRoute, M as MiddlewareType, d as MiddlewareCallback, P as PathMiddlewares, C as CorsConfig, e as SSEOptions, f as SSEClientOptions, g as SSEEventHandlers, h as SSEClient } from './index-
|
|
2
|
-
export { i as Adapter, j as AdapterContext, k as ClusterConfig, l as CookieOptions, H as Handler, m as MiddlewareModule, n as RequestCookies, o as ResponseCookies, p as Route, q as RouteHandlers, r as ServerlessConfig, U as UploadedFile } from './index-
|
|
1
|
+
import { S as ServerConfig, A as AdapterRequest, a as AdapterResponse, R as Request, b as Response, c as ServerlessRoute, M as MiddlewareType, d as MiddlewareCallback, P as PathMiddlewares, C as CorsConfig, e as SSEOptions, f as SSEClientOptions, g as SSEEventHandlers, h as SSEClient } from './index-CnWzo9eB.js';
|
|
2
|
+
export { i as Adapter, j as AdapterContext, k as ClusterConfig, l as CookieOptions, H as Handler, m as MiddlewareModule, n as RequestCookies, o as ResponseCookies, p as Route, q as RouteHandlers, r as ServerlessConfig, U as UploadedFile } from './index-CnWzo9eB.js';
|
|
3
3
|
import { Server, ServerResponse, IncomingMessage } from 'http';
|
|
4
4
|
|
|
5
5
|
interface VercelRequest {
|
|
@@ -246,7 +246,7 @@ declare class Router {
|
|
|
246
246
|
declare const router: Router;
|
|
247
247
|
declare function isRouteError(obj: any): obj is RouteError;
|
|
248
248
|
declare function registerRoutes(routes: ServerlessRoute[]): void;
|
|
249
|
-
declare function loadRoutes(routesDir: string): Promise<boolean>;
|
|
249
|
+
declare function loadRoutes(routesDir: string): Promise<boolean | undefined>;
|
|
250
250
|
declare function findRoute(url: string, method?: string): FindRouteResult;
|
|
251
251
|
declare function getRoutesDir(customDir?: string): string;
|
|
252
252
|
declare function getRouterStats(): {
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {k as k$1,s,h,m,n,j as j$1,J}from'./chunk-
|
|
2
|
-
Signal ${r} re\xE7u, arr\xEAt en cours...`),y&&typeof y.close=="function"&&await new Promise(t=>{y.close(()=>t()),setTimeout(()=>{j$1("Fermeture forc\xE9e apr\xE8s d\xE9lai"),t();},3e3);}),process.exit(0));};process.on("SIGINT",()=>e("SIGINT")),process.on("SIGTERM",()=>e("SIGTERM")),process.on("SIGHUP",()=>e("SIGHUP"));}var p={OK:200,CREATED:201,NO_CONTENT:204,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,CONFLICT:409,UNPROCESSABLE_ENTITY:422,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504},L={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",409:"Conflict",422:"Unprocessable Entity",429:"Too Many Requests",500:"Internal Server Error",503:"Service Unavailable",504:"Gateway Timeout"};function u(e){let r=e.code||p.INTERNAL_SERVER_ERROR,t=e.message||L[r]||"Unknown Error",a=e.name||`HttpError${r}`,n=new Error(t);return Error.captureStackTrace?.(n,u),{name:a,code:r,message:t,details:e.details,expose:e.expose!==void 0?e.expose:r<500,log:e.log!==void 0?e.log:r>=500,stack:n.stack}}function M(e){let r={error:e.message,code:e.code};return e.expose&&e.details?{...r,details:e.details}:r}function A(e,r){r.headersSent||(r.statusCode=e.code,r.setHeader("Content-Type","application/json"),r.end(JSON.stringify(M(e)))),e.log&&U(e);}function U(e){let r={name:e.name,message:e.message,code:e.code,details:e.details,stack:e.stack};e.code>=500?j$1("\u274C ERROR:",JSON.stringify(r,null,2)):j$1("\u26A0\uFE0F WARNING:",JSON.stringify(r,null,2));}function ke(e,r){return u({name:"BadRequestError",code:p.BAD_REQUEST,message:e,details:r})}function Ne(e,r){return u({name:"UnauthorizedError",code:p.UNAUTHORIZED,message:e,details:r})}function Ie(e,r){return u({name:"ForbiddenError",code:p.FORBIDDEN,message:e,details:r})}function qe(e,r){return u({name:"NotFoundError",code:p.NOT_FOUND,message:e,details:r})}function Pe(e,r){return u({name:"MethodNotAllowedError",code:p.METHOD_NOT_ALLOWED,message:e,details:r})}function De(e,r){return u({name:"ConflictError",code:p.CONFLICT,message:e,details:r})}function Le(e,r){return u({name:"ValidationError",code:p.UNPROCESSABLE_ENTITY,message:e,details:r,expose:true})}function k(e,r){return u({name:"RateLimitError",code:p.TOO_MANY_REQUESTS,message:e,details:r})}function _(e,r){return u({name:"InternalServerError",code:p.INTERNAL_SERVER_ERROR,message:e,details:r})}function B(e,r){return u({name:"ServiceUnavailableError",code:p.SERVICE_UNAVAILABLE,message:e,details:r})}function j(e,r){return u({name:"GatewayTimeoutError",code:p.GATEWAY_TIMEOUT,message:e,details:r})}function Me(e){if(e&&typeof e=="object"&&typeof e.code=="number"&&"message"in e)return e;let r=e?.message||"Unknown error occurred",t=e?.stack?{stack:e.stack}:void 0,a=e?.code||e?.statusCode;return a==="ECONNREFUSED"||a==="ENOTFOUND"?B(`Service connection failed: ${r}`,t):a==="ETIMEDOUT"?j(`Request timed out: ${r}`,t):typeof a=="number"&&a>=400&&a<600?u({code:a,message:r,details:t}):_(r,t)}function Ue(e){return !!(e&&typeof e=="object"&&typeof e.code=="number"&&"message"in e&&"name"in e)}function je(e={}){let r=e.windowMs??6e4,t=e.max??100,a=e.message??"Too Many Requests",n=e.keyGenerator??(i=>{let o=i.headers["x-forwarded-for"];return (typeof o=="string"?o.split(",")[0].trim():i.socket?.remoteAddress)??"unknown"}),s=new Map;return (i,o)=>{let
|
|
1
|
+
import {k as k$1,s,h,m,n,j as j$1,J}from'./chunk-5BKQSPRW.js';export{a as addMiddleware,b as addPathMiddleware,c as collectMiddleware,t as createCorsMiddleware,v as createSSEClient,o as findRoute,g as getPathMiddlewares,q as getRouterStats,p as getRoutesDir,d as hasMiddlewares,w as initSSE,l as isRouteError,f as loadMiddlewares,n as loadRoutes,u as registerCorsConfig,i as registerMiddlewareConfig,m as registerRoutes,h as resetMiddlewares,s as resetRouter,k as router,e as runMiddlewares,x as send,z as sendEvent,y as sendJson,r as setVerboseLogging,D as sseClose,A as sseComment,E as sseEventError,B as sseId,C as sseRetry}from'./chunk-5BKQSPRW.js';import H from'cluster';var g={port:3e3,isDev:process.env.NODE_ENV==="development",timeout:3e4,cluster:{enabled:false,workers:void 0},platform:"node"};function le(e={}){return {...g,...e}}async function S(e,r){let t=await e["~standard"].validate(r);return t.issues?{success:false,issues:t.issues}:{success:true,data:t.value}}function R(e){return Array.from(e).map(r=>({message:r.message,path:r.path?Array.from(r.path).map(t=>typeof t=="object"&&"key"in t?t.key:t):void 0}))}function ye(e){let r=async(t,a)=>{if(e.params){let n=await S(e.params,t.params??{});if(!n.success){a.status(400).json({error:"Validation failed",issues:R(n.issues)});return}t.params=n.data;}if(e.query){let n=await S(e.query,t.query??{});if(!n.success){a.status(400).json({error:"Validation failed",issues:R(n.issues)});return}t.query=n.data;}if(e.body){let n;try{n=await t.json();}catch{a.status(400).json({error:"Invalid JSON body"});return}let s=await S(e.body,n);if(!s.success){a.status(400).json({error:"Validation failed",issues:R(s.issues)});return}t.body=s.data;}await e.handler(t,a);};return r._defineHandler=e,r}async function E(e){let r=e?.["~standard"]?.vendor;if(!r)return null;try{if(r==="zod"){let t=await import('zod');if(typeof t.toJSONSchema=="function")return t.toJSONSchema(e);let a=await import('zod-to-json-schema');return (a.zodToJsonSchema??a.default)(e,{target:"openApi3"})}if(r==="valibot"){let t=await import('@valibot/to-json-schema');return (t.toJsonSchema??t.default)(e)}if(r==="arktype")return e.toJsonSchema()}catch{j$1(`[openapi] no converter found for "${r}" \u2014 install the matching json-schema package`);}return null}function q(e){return e.replace(/:(\w+)\??/g,"{$1}")}async function P(e,r){let t={responses:{200:{description:"Success"}}};r.meta?.summary&&(t.summary=r.meta.summary),r.meta?.description&&(t.description=r.meta.description),r.meta?.tags&&(t.tags=r.meta.tags),r.meta?.deprecated&&(t.deprecated=r.meta.deprecated);let a=[];if(r.params){let n=await E(r.params);if(n?.properties)for(let[s,i]of Object.entries(n.properties))a.push({name:s,in:"path",required:true,schema:i});}if(r.query){let n=await E(r.query);if(n?.properties){let s=n.required??[];for(let[i,o]of Object.entries(n.properties))a.push({name:i,in:"query",required:s.includes(i),schema:o});}}if(a.length>0&&(t.parameters=a),r.body){let n=await E(r.body);n&&(t.requestBody={required:true,content:{"application/json":{schema:n}}});}return t}async function O(e){let r=k$1.getRoutes(),t={};for(let{method:a,path:n,handler:s}of r){let i=s._defineHandler,o=q(n);t[o]||(t[o]={}),t[o][a.toLowerCase()]=i?await P(a,i):{responses:{200:{description:"Success"}}};}return {openapi:"3.1.0",info:e.info,paths:t}}var y=null,w=false,x=false;async function xe(e,r=g){let{platform:t="node"}=r,a=r.isDev&&H.isPrimary&&!process.env.LACIS_BUN_WORKER;try{r.routes?(s(),h(),m(r.routes)):await n(e);let n$1=null,s$1=null;r.openapi&&(n$1=await O(r.openapi),s$1=r.openapi.path??"/openapi.json"),a&&(j$1("\u{1F680} Serveur d\xE9marr\xE9"),j$1(`\u{1F4C2} Routes charg\xE9es depuis: ${e}`)),r.isDev&&a&&j$1("\u{1F525} Mode de d\xE9veloppement activ\xE9");let o=J(t).createHandler(e),c;switch(t){case "node":c=await o(r),y=c;break;case "bun":c=o(r);break;case "vercel":case "netlify":c=o;break;default:throw new Error(`Plateforme "${t}" non support\xE9e`)}return n$1&&s$1&&(k$1.addRoute("GET",s$1,(l,m)=>m.json(n$1)),a&&j$1(`OpenAPI doc available at ${s$1}`)),D(),c}catch(n){throw a&&j$1("\u274C Erreur lors de la cr\xE9ation du serveur:",n),n}}function D(){if(!H.isPrimary||x)return;x=true;let e=async r=>{w||(w=true,j$1(`
|
|
2
|
+
Signal ${r} re\xE7u, arr\xEAt en cours...`),y&&typeof y.close=="function"&&await new Promise(t=>{y.close(()=>t()),setTimeout(()=>{j$1("Fermeture forc\xE9e apr\xE8s d\xE9lai"),t();},3e3);}),process.exit(0));};process.on("SIGINT",()=>e("SIGINT")),process.on("SIGTERM",()=>e("SIGTERM")),process.on("SIGHUP",()=>e("SIGHUP"));}var p={OK:200,CREATED:201,NO_CONTENT:204,BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,CONFLICT:409,UNPROCESSABLE_ENTITY:422,TOO_MANY_REQUESTS:429,INTERNAL_SERVER_ERROR:500,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504},L={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",409:"Conflict",422:"Unprocessable Entity",429:"Too Many Requests",500:"Internal Server Error",503:"Service Unavailable",504:"Gateway Timeout"};function u(e){let r=e.code||p.INTERNAL_SERVER_ERROR,t=e.message||L[r]||"Unknown Error",a=e.name||`HttpError${r}`,n=new Error(t);return Error.captureStackTrace?.(n,u),{name:a,code:r,message:t,details:e.details,expose:e.expose!==void 0?e.expose:r<500,log:e.log!==void 0?e.log:r>=500,stack:n.stack}}function M(e){let r={error:e.message,code:e.code};return e.expose&&e.details?{...r,details:e.details}:r}function A(e,r){r.headersSent||(r.statusCode=e.code,r.setHeader("Content-Type","application/json"),r.end(JSON.stringify(M(e)))),e.log&&U(e);}function U(e){let r={name:e.name,message:e.message,code:e.code,details:e.details,stack:e.stack};e.code>=500?j$1("\u274C ERROR:",JSON.stringify(r,null,2)):j$1("\u26A0\uFE0F WARNING:",JSON.stringify(r,null,2));}function ke(e,r){return u({name:"BadRequestError",code:p.BAD_REQUEST,message:e,details:r})}function Ne(e,r){return u({name:"UnauthorizedError",code:p.UNAUTHORIZED,message:e,details:r})}function Ie(e,r){return u({name:"ForbiddenError",code:p.FORBIDDEN,message:e,details:r})}function qe(e,r){return u({name:"NotFoundError",code:p.NOT_FOUND,message:e,details:r})}function Pe(e,r){return u({name:"MethodNotAllowedError",code:p.METHOD_NOT_ALLOWED,message:e,details:r})}function De(e,r){return u({name:"ConflictError",code:p.CONFLICT,message:e,details:r})}function Le(e,r){return u({name:"ValidationError",code:p.UNPROCESSABLE_ENTITY,message:e,details:r,expose:true})}function k(e,r){return u({name:"RateLimitError",code:p.TOO_MANY_REQUESTS,message:e,details:r})}function _(e,r){return u({name:"InternalServerError",code:p.INTERNAL_SERVER_ERROR,message:e,details:r})}function B(e,r){return u({name:"ServiceUnavailableError",code:p.SERVICE_UNAVAILABLE,message:e,details:r})}function j(e,r){return u({name:"GatewayTimeoutError",code:p.GATEWAY_TIMEOUT,message:e,details:r})}function Me(e){if(e&&typeof e=="object"&&typeof e.code=="number"&&"message"in e)return e;let r=e?.message||"Unknown error occurred",t=e?.stack?{stack:e.stack}:void 0,a=e?.code||e?.statusCode;return a==="ECONNREFUSED"||a==="ENOTFOUND"?B(`Service connection failed: ${r}`,t):a==="ETIMEDOUT"?j(`Request timed out: ${r}`,t):typeof a=="number"&&a>=400&&a<600?u({code:a,message:r,details:t}):_(r,t)}function Ue(e){return !!(e&&typeof e=="object"&&typeof e.code=="number"&&"message"in e&&"name"in e)}function je(e={}){let r=e.windowMs??6e4,t=e.max??100,a=e.message??"Too Many Requests",n=e.keyGenerator??(i=>{let o=i.headers["x-forwarded-for"];return (typeof o=="string"?o.split(",")[0].trim():i.socket?.remoteAddress)??"unknown"}),s=new Map;return (i,o)=>{let c=n(i),l=Date.now(),m=s.get(c);(!m||l>=m.resetAt)&&(m={count:0,resetAt:l+r},s.set(c,m)),m.count++;let N=Math.max(0,t-m.count),I=Math.ceil(m.resetAt/1e3);if(o.setHeader("X-RateLimit-Limit",String(t)),o.setHeader("X-RateLimit-Remaining",String(N)),o.setHeader("X-RateLimit-Reset",String(I)),m.count>t)return o.setHeader("Retry-After",String(Math.ceil((m.resetAt-l)/1e3))),A(k(a),o),false}}export{p as HTTP_STATUS,O as buildOpenApiDoc,ke as createBadRequestError,De as createConflictError,Ie as createForbiddenError,j as createGatewayTimeoutError,u as createHttpError,_ as createInternalServerError,Pe as createMethodNotAllowedError,qe as createNotFoundError,je as createRateLimit,k as createRateLimitError,xe as createServer,B as createServiceUnavailableError,Ne as createUnauthorizedError,Le as createValidationError,g as defaultConfig,ye as defineHandler,le as getConfig,Ue as isHttpError,U as logError,Me as normalizeError,A as sendError};
|