@andrewcaires/express 2.2.1 → 2.4.0

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/dist/index.cjs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/express v2.2.1
2
+ * @andrewcaires/express v2.4.0
3
3
  * Decorators for express
4
4
  * (c) 2026 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- "use strict";var e=require("@andrewcaires/decorator"),t=require("@andrewcaires/node"),s=require("@andrewcaires/utils.js"),r=require("compression"),o=require("cookie-parser"),i=require("cors"),n=require("express"),a=require("express-session"),l=require("fs"),u=require("http"),d=require("https"),h=require("net"),c=require("path"),p=require("request-ip"),E=require("multer");function _(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,r.get?r:{enumerable:!0,get:function(){return e[s]}})}}),t.default=e,Object.freeze(t)}var v=_(u),R=_(d),m=_(h);function T(e,t,s,r){return new(s||(s=Promise))(function(o,i){function n(e){try{l(r.next(e))}catch(e){i(e)}}function a(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof s?t:new s(function(e){e(t)})).then(n,a)}l((r=r.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class g{}g.CONTINUE=100,g.SWITCHING_PROTOCOLS=101,g.PROCESSING=102,g.OK=200,g.CREATED=201,g.ACCEPTED=202,g.NON_AUTHORITATIVE_INFORMATION=203,g.NO_CONTENT=204,g.RESET_CONTENT=205,g.PARTIAL_CONTENT=206,g.MULTI_STATUS=207,g.ALREADY_REPORTED=208,g.IM_USED=226,g.MULTIPLE_CHOICES=300,g.MOVED_PERMANENTLY=301,g.FOUND=302,g.SEE_OTHER=303,g.NOT_MODIFIED=304,g.USE_PROXY=305,g.TEMPORARY_REDIRECT=307,g.PERMANENT_REDIRECT=308,g.BAD_REQUEST=400,g.UNAUTHORIZED=401,g.PAYMENT_REQUIRED=402,g.FORBIDDEN=403,g.NOT_FOUND=404,g.METHOD_NOT_ALLOWED=405,g.NOT_ACCEPTABLE=406,g.PROXY_AUTHENTICATION_REQUIRED=407,g.REQUEST_TIMEOUT=408,g.CONFLICT=409,g.GONE=410,g.LENGTH_REQUIRED=411,g.PRECONDITION_FAILED=412,g.PAYLOAD_TOO_LARGE=413,g.REQUEST_URI_TOO_LONG=414,g.UNSUPPORTED_MEDIA_TYPE=415,g.REQUESTED_RANGE_NOT_SATISFIABLE=416,g.EXPECTATION_FAILED=417,g.IM_A_TEAPOT=418,g.MISDIRECTED_REQUEST=421,g.UNPROCESSABLE_ENTITY=422,g.LOCKED=423,g.FAILED_DEPENDENCY=424,g.UPGRADE_REQUIRED=426,g.PRECONDITION_REQUIRED=428,g.TOO_MANY_REQUESTS=429,g.REQUEST_HEADER_FIELDS_TOO_LARGE=431,g.CONNECTION_CLOSED_WITHOUT_RESPONSE=444,g.UNAVAILABLE_FOR_LEGAL_REASONS=451,g.CLIENT_CLOSED_REQUEST=499,g.INTERNAL_SERVER_ERROR=500,g.NOT_IMPLEMENTED=501,g.BAD_GATEWAY=502,g.SERVICE_UNAVAILABLE=503,g.GATEWAY_TIMEOUT=504,g.HTTP_VERSION_NOT_SUPPORTED=505,g.VARIANT_ALSO_NEGOCIATES=506,g.INSUFFICIENT_STORAGE=507,g.LOOP_DETECTED=508,g.NOT_EXTENDED=510,g.NETWORK_AUTHENTICATION_REQUIRED=511,g.NETWORK_CONNECTION_TIMEOUT_ERROR=599;class O{}O[100]="Continue",O[101]="Switching Protocols",O[102]="Processing",O[200]="OK",O[201]="Created",O[202]="Accepted",O[203]="Non-Authoritative Information",O[204]="No Content",O[205]="Reset Content",O[206]="Partial Content",O[207]="Multi-Status",O[226]="IM Used",O[300]="Multiple Choices",O[301]="Moved Permanently",O[302]="Found",O[303]="See Other",O[304]="Not Modified",O[305]="Use Proxy",O[307]="Temporary Redirect",O[308]="Permanent Redirect",O[400]="Bad Request",O[401]="Unauthorized",O[402]="Payment Required",O[403]="Forbidden",O[404]="Not Found",O[405]="Method Not Allowed",O[406]="Not Acceptable",O[407]="Proxy Authentication Required",O[408]="Request Timeout",O[409]="Conflict",O[410]="Gone",O[411]="Length Required",O[412]="Precondition Failed",O[413]="Payload Too Large",O[414]="URI Too Long",O[415]="Unsupported Media Type",O[416]="Range Not Satisfiable",O[417]="Expectation Failed",O[418]="I'm a teapot",O[422]="Unprocessable Entity",O[423]="Locked",O[424]="Failed Dependency",O[426]="Upgrade Required",O[428]="Precondition Required",O[429]="Too Many Requests",O[431]="Request Header Fields Too Large",O[451]="Unavailable For Legal Reasons",O[500]="Internal Server Error",O[501]="Not Implemented",O[502]="Bad Gateway",O[503]="Service Unavailable",O[504]="Gateway Time-out",O[505]="HTTP Version Not Supported",O[506]="Variant Also Negotiates",O[507]="Insufficient Storage",O[511]="Network Authentication Required";class N extends Error{constructor(e,t=g.INTERNAL_SERVER_ERROR){super(e),this.status=t}}class S extends N{constructor(e="Not Found"){super(e,g.NOT_FOUND)}}class f extends N{constructor(e){super(e,g.UNPROCESSABLE_ENTITY)}}class A{static created(e,t,s){var r,o;const i=g.CREATED,n={success:!0,status:i,data:t?{id:t}:{},meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return e.status(i).json(n),n}static noContent(e){e.status(g.NO_CONTENT).end()}static ok(e,t,s){var r,o;const i=g.OK,n={success:!0,status:i,data:t,meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return e.status(i).json(n),n}static error(e,t,s){var r,o;const{status:i,message:n}=this.normalizeError(s),a=Object.assign({success:!1,status:i,error:null!==(r=null==O?void 0:O[i])&&void 0!==r?r:"Internal Server Error",message:n,path:null!==(o=e.originalUrl)&&void 0!==o?o:e.url,timestamp:(new Date).toISOString()},this.isDev()&&s instanceof Error&&s.stack?{stack:s.stack}:{});return t.status(i).json(a),a}static isDev(){return"production"!==process.env.NODE_ENV}static normalizeError(e){let t=g.INTERNAL_SERVER_ERROR,r=O[500];if(e instanceof N)return t=this.safeStatus(e.status),r=this.safeMessage(e.message)||r,{status:t,message:r};if(e instanceof Error){const o=e;return s.isNumber(o.statusCode)?t=this.safeStatus(o.statusCode):s.isNumber(o.status)&&(t=this.safeStatus(o.status)),r=this.safeMessage(e.message)||r,{status:t,message:r}}if(s.isString(e))return r=this.safeMessage(e)||r,{status:t,message:r};if(e&&s.isObject(e)){const o=e;return s.isNumber(o.statusCode)?t=this.safeStatus(o.statusCode):s.isNumber(o.status)&&(t=this.safeStatus(o.status)),s.isString(o.message)&&(r=this.safeMessage(o.message)||r),{status:t,message:r}}return{status:t,message:r}}static safeStatus(e){if(!Number.isFinite(e))return g.INTERNAL_SERVER_ERROR;const t=Math.trunc(e);return t<400||t>599?g.INTERNAL_SERVER_ERROR:t}static safeMessage(e){if(!s.isString(e))return"";const t=e.trim();return t.length>2e3?t.slice(0,2e3)+"...":t}}class x{constructor(e,t,r,o,i){this.storage={},this.req=e,this.res=t,this.next=r,this.id=s.uuidv7(),this.app=o,this.controller=i}cache(e){const t=Object.assign({},e),r=[];t.private?r.push("private"):t.public&&r.push("public"),t.noStore&&(t.noCache=!0,r.push("no-store")),t.noCache&&(t.maxAge=0,delete t.sMaxAge,r.push("no-cache")),t.noTransform&&r.push("no-transform"),t.proxyRevalidate&&r.push("proxy-revalidate"),t.mustRevalidate?r.push("must-revalidate"):t.noCache||(s.isNumber(t.staleIfError)&&r.push(`stale-if-error=${t.staleIfError}`),s.isNumber(t.staleWhileRevalidate)&&r.push(`stale-while-revalidate=${t.staleWhileRevalidate}`)),s.isNumber(t.maxAge)&&r.push(`max-age=${t.maxAge}`),s.isNumber(t.sMaxAge)&&r.push(`s-maxage=${t.sMaxAge}`),r.length&&(this.res.setHeader("Cache-Control",r.join(",")),t.noCache&&s.forEachKey({"Surrogate-Control":"no-store",Pragma:"no-cache",ETag:"false",Expires:"0"},(e,t)=>this.res.setHeader(t,e)))}clearCookie(e,t){this.res.clearCookie(e,t)}close(e){this.isResponded()||this.res.json(null!=e?e:this.storage)}destroy(e){var t;e&&this.error(e),null===(t=this.res.socket)||void 0===t||t.destroy(e)}error(e){this.isResponded()||A.error(this.req,this.res,e)}file(e){this.isResponded()||(this.status(g.OK),this.res.sendFile(c.resolve(e)))}getBody(){var e,t;return null!==(t=null===(e=this.req)||void 0===e?void 0:e.body)&&void 0!==t?t:{}}getBodyValue(e){var t;return null===(t=this.req.body)||void 0===t?void 0:t[e]}getCookie(e){var t;return this.normalize(null===(t=this.req.cookies)||void 0===t?void 0:t[e])}getCookies(){var e,t;return s.map(null!==(t=null===(e=this.req)||void 0===e?void 0:e.cookies)&&void 0!==t?t:{},e=>this.normalize(e))}getFiles(){var e,t;return null!==(t=null===(e=this.req)||void 0===e?void 0:e.files)&&void 0!==t?t:{}}getFullUrl(){return`${this.getUrl()}${this.req.originalUrl}`}getHeader(e){var t;return this.normalize(null===(t=this.req.headers)||void 0===t?void 0:t[e])}getHeaders(){var e,t;return s.map(null!==(t=null===(e=this.req)||void 0===e?void 0:e.headers)&&void 0!==t?t:{},e=>this.normalize(e))}getIp(){return p.getClientIp(this.req)||"0.0.0.0"}getQuery(e){var t;return this.normalize(null===(t=this.req.query)||void 0===t?void 0:t[e])}getQueries(){var e,t;return s.map(null!==(t=null===(e=this.req)||void 0===e?void 0:e.query)&&void 0!==t?t:{},e=>this.normalize(e))}getParam(e){var t;const r=null===(t=this.req.params)||void 0===t?void 0:t[e];return s.isUndefined(r)?void 0:String(r)}getParams(){var e,t;return s.map(null!==(t=null===(e=this.req)||void 0===e?void 0:e.params)&&void 0!==t?t:{},e=>{if(!s.isUndefined(e)&&!s.isNull(e))return String(e)})}getUrl(){let e=this.getHeader("x-forwarded-proto")||this.req.protocol||"http";s.isString(e)&&e.includes(",")&&(e=e.split(",")[0].trim());const t=this.getHeader("cf-visitor");if(t){const r=s.parseJson(t);(null==r?void 0:r.scheme)&&(e=r.scheme)}return`${e}://${this.getHeader("host")}`}isResponded(){return this.res.headersSent||this.res.writableEnded}json(e){this.send(g.OK,e)}normalize(e){if(!s.isUndefined(e)&&!s.isNull(e))return s.isObject(e)?JSON.stringify(e):String(e)}ok(e,t){this.isResponded()||A.ok(this.res,e,t)}prepare(e,t){this.isResponded()||(this.status(e),this.storage=t)}redirect(e){this.isResponded()||this.res.redirect(e)}send(e,t){this.isResponded()||(this.status(e),204===e||304===e||s.isUndefined(t)?this.res.end():this.res.json(t))}setCookie(e,t,s){this.res.cookie(e,t,null!=s?s:{})}status(e){return s.isUndefined(e)||this.res.status(e),this.res.statusCode}success(e){this.send(g.OK,{message:e})}}class y{static extends(t){return e.metadata(y.EXTENDS,t,[])}static middleware(t){return e.metadata(y.MIDDLEWARE,t,[])}static parameters(t){return e.metadata(y.PARAMETERS,t,[])}static path(t,s){return e.metadata(y.PATH,t,s)}static routers(t){return e.metadata(y.ROUTERS,t,[])}}y.EXTENDS=Symbol("EXTENDS"),y.MIDDLEWARE=Symbol("MIDDLEWARE"),y.PARAMETERS=Symbol("PARAMETERS"),y.PATH=Symbol("PATH"),y.ROUTERS=Symbol("ROUTERS");class I extends s.EventEmitter{get controllers(){return[...this._controllers]}get instance(){return this._app}get router(){return this._globalRouter}get server(){return this._server}constructor(t,u){var d,h;super(),this._app=n(),this._boundServers=[],this._options={},this._baseRouter=n.Router(),this._globalRouter=n.Router(),this._controllers=[],this._controllers.push(...t.map(t=>s.isConstructor(t)?new t(...e.getInjectionArgs(t)):t)),this._options=s.merge({},{cross:!1,path:"/",port:3e3,session:{secret:"yoursecret",resave:!0,saveUninitialized:!1,cookie:{maxAge:864e5}}},null!=u?u:{}),this._app.use(n.json(this._options.json)),this._app.disable("x-powered-by"),this._options.proxy&&this._app.set("trust proxy",this._options.proxy),this._app.use(n.urlencoded({extended:!0})),this._options.cross&&this._app.use(i(s.isObject(this._options.cross)?this._options.cross:{})),this._app.use(r(this._options.compression)),this._app.use(o(null===(d=this._options.cookie)||void 0===d?void 0:d.secret,this._options.cookie)),this._app.use(a(this._options.session)),this.init(),this._app.use(this._globalRouter);const p=(null===(h=this._options.path)||void 0===h?void 0:h.length)?this._options.path:"/";if(this._app.use(p,this._baseRouter),this._app.all(p+"/*path",(e,t)=>{this._options.redirect?t.redirect(this._options.redirect):A.error(e,t,new S("Endpoint Not Found"))}),this._options.public){const e=c.resolve(this._options.public);l.existsSync(e)&&this._app.use(n.static(e)),this._app.get("*path",(t,s)=>{l.existsSync(e)?s.sendFile(e+"/index.html"):this._options.notfound?s.redirect(this._options.notfound):A.error(t,s,new S('FILE "index.html" Not Found'))})}else this._app.all("*path",(e,t)=>{this._options.redirect?t.redirect(this._options.redirect):A.error(e,t,new S("Endpoint not found"))});this._controllers.forEach(e=>{const t=n.Router(),r=this._collectMiddlewares(e),o=y.parameters(e);this._collectExtends(e).forEach(e=>{r.push(...this._collectMiddlewares(e)),o.push(...y.parameters(e))}),y.routers(e).forEach(i=>{const n=i.propertyKey.toString();if(s.isFunction(e[n])){if(!s.isFunction(t[i.method]))return this._logRouteNotFound(i.method);const a=this._buildMiddlewareChain(e,n,r,o);return t[i.method](i.path,...a,(t,r,i)=>T(this,void 0,void 0,function*(){const a=new x(t,r,i,this,e),l=this._resolveArgs(a,this._filterParamsByKey(n,o)),u=yield e[n](...l);a.close(s.isArray(u)||s.isObject(u)?u:void 0)}))}this._logRouteNotFound(`${e.name}.${n}`)}),this._collectExtends(e).forEach(i=>{y.routers(i).forEach(i=>{const n=i.propertyKey.toString();if(s.isFunction(e[n])){if(!s.isFunction(t[i.method]))return this._logRouteNotFound(i.method);const a=this._buildMiddlewareChain(e,n,r,o);return t[i.method](i.path,...a,(t,r,i)=>T(this,void 0,void 0,function*(){const a=new x(t,r,i,this,e),l=this._resolveArgs(a,this._filterParamsByKey(n,o)),u=yield e[n](...l);a.close(s.isArray(u)||s.isObject(u)?u:void 0)}))}this._logRouteNotFound(`${e.constructor.name}.${n}`)})}),this._baseRouter.use(y.path(e,"/"),t)})}init(){}error(e,s){t.Log.error(e)}log(e,s){t.Log.info(e)}_resolveArgs(e,t,s){const r=[],o={ctx:e,key:"",app:this,argument:s};return t.forEach(e=>{r[e.parameterIndex]=e.callback(Object.assign(Object.assign({},o),{key:e.key}))}),r}_buildMiddlewareChain(e,t,r,o){return r.filter(e=>e.propertyKey==t).map(t=>{if(t.callback!=s.noop){const r=this._filterParamsByKey(t.method,o);return(o,i,n)=>T(this,void 0,void 0,function*(){const a=new x(o,i,n,this,e),l=s.isFunction(t.argument)?t.argument(a):t.argument,u=yield t.callback.call(e,...this._resolveArgs(a,r,l));(s.isArray(u)||s.isObject(u))&&a.close(u)})}this._logRouteNotFound(t.method)}).filter(s.isFunction)}_collectExtends(e){return y.extends(e).reduce((e,t)=>(e.push(t,...this._collectExtends(t)),e),[]).filter((e,t,s)=>s.indexOf(e)===t)}_filterParamsByKey(e,t){return t.filter(t=>t.propertyKey==e)}_collectMiddlewares(e){return[...y.middleware(e)].reverse()}_logRouteNotFound(e){this.error(new Error(`Router "${e}" not found`),"express")}_formatListeningMessage(e){return`Server listening on port ${e}`}listen(){return T(this,void 0,void 0,function*(){var e;const t=this._resolveMode(),s={http:this._startHttp,https:this._startHttps,hybrid:this._startHybrid,redirect:this._startHttpsWithRedirect};yield(null!==(e=s[t])&&void 0!==e?e:this._startHttp).call(this)})}close(){return T(this,void 0,void 0,function*(){yield Promise.all(this._boundServers.map(e=>new Promise((t,s)=>{e.close(e=>e?s(e):t())}))),this._boundServers.length=0,this._server=void 0})}_resolveMode(){return this._resolveTls()&&this._options.mode?this._options.mode:"http"}_resolveTls(){if(this._options.tls&&this._options.tls.key&&this._options.tls.cert)return this._options.tls}_bindServer(e,t,s){return new Promise((r,o)=>{const i=t=>{e.off("listening",n),o(t)},n=()=>{e.off("error",i),this.log(this._formatListeningMessage(t),"express"),r()};e.once("error",i),e.once("listening",n),e.listen(t,s)})}_startHttp(){return T(this,void 0,void 0,function*(){var e;const t=v.createServer(this._app);this._server=t,this._boundServers.push(t),yield this._bindServer(t,null!==(e=this._options.port)&&void 0!==e?e:3e3,this._options.host)})}_startHttps(){return T(this,void 0,void 0,function*(){var e;const t=R.createServer(this._resolveTls(),this._app);this._server=t,this._boundServers.push(t),yield this._bindServer(t,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host)})}_startHttpsWithRedirect(){return T(this,void 0,void 0,function*(){var e,t;const s=R.createServer(this._resolveTls(),this._app),r=v.createServer((e,t)=>{var s,r;const o=(null!==(s=e.headers.host)&&void 0!==s?s:"").split(":")[0];t.writeHead(g.MOVED_PERMANENTLY,{Location:`https://${o}${null!==(r=e.url)&&void 0!==r?r:""}`}),t.end()});this._server=s,this._boundServers.push(s,r),yield Promise.all([this._bindServer(s,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host),this._bindServer(r,null!==(t=this._options.redirectPort)&&void 0!==t?t:80,this._options.host)])})}_startHybrid(){return T(this,void 0,void 0,function*(){var e;const t=v.createServer(this._app),s=R.createServer(this._resolveTls(),this._app),r=m.createServer(e=>{const r=setTimeout(()=>e.destroy(),5e3);e.once("data",o=>{clearTimeout(r),e.pause(),e.unshift(o),(22===o[0]?s:t).emit("connection",e),process.nextTick(()=>e.resume())}),e.once("error",()=>clearTimeout(r))});return this._server=s,this._boundServers.push(r,s,t),yield this._bindServer(r,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host),s})}}const C=e=>t=>(s,r,o)=>{y.parameters(s).push({callback:e,key:t,propertyKey:r,parameterIndex:o})},b=C(({app:e})=>e),D=C(({argument:e})=>e),P=C(({ctx:e,key:t})=>t?e.getBodyValue(t):e.getBody()),U=C(({ctx:e,key:t})=>t?e.getCookie(t):e.getCookies()),L=C(({ctx:e})=>e),F=C(({ctx:e})=>e.getFiles()),M=C(({ctx:e,key:t})=>t?e.getHeader(t):e.getHeaders()),q=C(({ctx:e,key:t})=>t?e.getParam(t):e.getParams()),k=C(({ctx:e,key:t})=>t?e.getQuery(t):e.getQueries()),w=C(({ctx:e})=>{var t;return null===(t=e.req)||void 0===t?void 0:t.session}),H=(e,t)=>(r,o)=>{const i=s.uuidv7();L()(r,i,0),y.middleware(r).push({method:i,argument:t,propertyKey:o,callback:e})},j={ALL:"all",GET:"get",POST:"post",PUT:"put",HEAD:"head",DELETE:"delete",OPTIONS:"options",PATCH:"patch"},B=e=>t=>(s,r)=>{y.routers(s).push({method:e,path:(null==t?void 0:t.length)?t:"/",propertyKey:r})},V=B(j.ALL),K=B(j.DELETE),G=B(j.GET),Q=B(j.HEAD),$=B(j.OPTIONS),z=B(j.PATCH),Y=B(j.POST),W=B(j.PUT),X=e=>{var t;return(null===(t=e.split(".").pop())||void 0===t?void 0:t.toLowerCase())||"bin"},Z=(e,t)=>{var s;return null!==(s=e[t])&&void 0!==s?s:null},J=(e,t)=>{const r=s.uuidv7()+"."+t;return l.existsSync(c.join(e,r))?J(e,t):r};exports.All=V,exports.App=b,exports.Application=I,exports.Argument=D,exports.BadRequestError=class extends N{constructor(e="Bad Request"){super(e,g.BAD_REQUEST)}},exports.Body=P,exports.Cache=e=>(t,s,r)=>{H(t=>{t.cache(Object.assign({},e)),t.next()})(t,s,r)},exports.Context=x,exports.Controller=e=>t=>{y.path(t,(null==e?void 0:e.length)?e:"/")},exports.Cookies=U,exports.Ctx=L,exports.Delete=K,exports.Extends=e=>t=>{y.extends(t).push(e)},exports.Files=F,exports.ForbiddenError=class extends N{constructor(e="Forbidden"){super(e,g.FORBIDDEN)}},exports.Get=G,exports.Head=Q,exports.Headers=M,exports.HttpResponse=A,exports.InternalServerError=class extends N{constructor(e="Internal server error"){super(e,g.INTERNAL_SERVER_ERROR)}},exports.Metadata=y,exports.Methods=j,exports.Middleware=(e,t)=>(r,o)=>{let i=s.noop;if(s.isString(o)){const t=r;s.isFunction(t[e])&&(i=t[e])}y.middleware(r).push({method:e,argument:t,propertyKey:o,callback:i})},exports.NotFoundError=S,exports.Options=$,exports.Params=q,exports.Patch=z,exports.Post=Y,exports.Put=W,exports.Query=k,exports.ResponseError=N,exports.Session=w,exports.StatusCodes=g,exports.StatusText=O,exports.UnauthorizedError=class extends N{constructor(e="Unauthorized"){super(e,g.UNAUTHORIZED)}},exports.Upload=e=>{const t=s.merge({},e),r=E.diskStorage({destination(e,s,r){var o;const i=Z(t,s.fieldname);r(null,null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./")},filename(e,s,r){var o;const i=Z(t,s.fieldname);r(null,J(null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./",X(s.originalname)))}}),o=Math.max(...Object.values(t).map(e=>{var t;return null!==(t=e.size)&&void 0!==t?t:0})),i=E({storage:r,fileFilter(e,s,r){var o;const i=Z(t,s.fieldname);return i?((e,t)=>!t.length||t.includes(X(e.originalname))||t.includes(e.mimetype.toLowerCase()))(s,null!==(o=null==i?void 0:i.types)&&void 0!==o?o:[])?void r(null,!0):r(new Error(`FILE TYPE NOT ALLOWED FOR "${s.fieldname}"`)):r(new Error(`UPLOAD FIELD "${s.fieldname}" IS NOT CONFIGURED`))},limits:{fileSize:1024*o*1024}}).fields(Object.keys(t).map(e=>{var s,r;return{name:e,maxCount:null!==(r=null===(s=t[e])||void 0===s?void 0:s.count)&&void 0!==r?r:1}}));return(e,t,s)=>{H(e=>{i(e.req,e.res,t=>{if(!t)return e.next();"LIMIT_UNEXPECTED_FILE"==t.code&&(t.message=`FIELD "${t.field}" EXCEEDS MAX SIZE`),e.destroy(t)})})(e,t,s)}},exports.Use=H,exports.Validate=e=>{const t=s.Validation.object(s.isFunction(e)?e(s.Validation):e).parse();return(e,s,r)=>{H(e=>T(void 0,void 0,void 0,function*(){var s,r;const{error:o,message:i,value:n}=yield t.validateAsync(null!==(r=null===(s=e.req)||void 0===s?void 0:s.body)&&void 0!==r?r:{});if(o)return e.error(new f(null!=i?i:o));e.req.body=n,e.next()}))(e,s,r)}},exports.ValidationError=f,exports.methodFactory=B,exports.parameterFactory=C;
7
+ "use strict";var t=require("@andrewcaires/decorator"),e=require("@andrewcaires/node"),s=require("@andrewcaires/utils.js"),r=require("compression"),o=require("cookie-parser"),i=require("cors"),a=require("express"),n=require("express-session"),u=require("fs"),d=require("http"),l=require("https"),c=require("net"),p=require("path"),h=require("request-ip"),E=require("multer");function S(t){var e=Object.create(null);return t&&Object.keys(t).forEach(function(s){if("default"!==s){var r=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,r.get?r:{enumerable:!0,get:function(){return t[s]}})}}),e.default=t,Object.freeze(e)}var T=S(d),_=S(l),v=S(c);function R(t,e,s,r){return new(s||(s=Promise))(function(o,i){function a(t){try{u(r.next(t))}catch(t){i(t)}}function n(t){try{u(r.throw(t))}catch(t){i(t)}}function u(t){var e;t.done?o(t.value):(e=t.value,e instanceof s?e:new s(function(t){t(e)})).then(a,n)}u((r=r.apply(t,e||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class StatusCodes{}StatusCodes.CONTINUE=100,StatusCodes.SWITCHING_PROTOCOLS=101,StatusCodes.PROCESSING=102,StatusCodes.OK=200,StatusCodes.CREATED=201,StatusCodes.ACCEPTED=202,StatusCodes.NON_AUTHORITATIVE_INFORMATION=203,StatusCodes.NO_CONTENT=204,StatusCodes.RESET_CONTENT=205,StatusCodes.PARTIAL_CONTENT=206,StatusCodes.MULTI_STATUS=207,StatusCodes.ALREADY_REPORTED=208,StatusCodes.IM_USED=226,StatusCodes.MULTIPLE_CHOICES=300,StatusCodes.MOVED_PERMANENTLY=301,StatusCodes.FOUND=302,StatusCodes.SEE_OTHER=303,StatusCodes.NOT_MODIFIED=304,StatusCodes.USE_PROXY=305,StatusCodes.TEMPORARY_REDIRECT=307,StatusCodes.PERMANENT_REDIRECT=308,StatusCodes.BAD_REQUEST=400,StatusCodes.UNAUTHORIZED=401,StatusCodes.PAYMENT_REQUIRED=402,StatusCodes.FORBIDDEN=403,StatusCodes.NOT_FOUND=404,StatusCodes.METHOD_NOT_ALLOWED=405,StatusCodes.NOT_ACCEPTABLE=406,StatusCodes.PROXY_AUTHENTICATION_REQUIRED=407,StatusCodes.REQUEST_TIMEOUT=408,StatusCodes.CONFLICT=409,StatusCodes.GONE=410,StatusCodes.LENGTH_REQUIRED=411,StatusCodes.PRECONDITION_FAILED=412,StatusCodes.PAYLOAD_TOO_LARGE=413,StatusCodes.REQUEST_URI_TOO_LONG=414,StatusCodes.UNSUPPORTED_MEDIA_TYPE=415,StatusCodes.REQUESTED_RANGE_NOT_SATISFIABLE=416,StatusCodes.EXPECTATION_FAILED=417,StatusCodes.IM_A_TEAPOT=418,StatusCodes.MISDIRECTED_REQUEST=421,StatusCodes.UNPROCESSABLE_ENTITY=422,StatusCodes.LOCKED=423,StatusCodes.FAILED_DEPENDENCY=424,StatusCodes.UPGRADE_REQUIRED=426,StatusCodes.PRECONDITION_REQUIRED=428,StatusCodes.TOO_MANY_REQUESTS=429,StatusCodes.REQUEST_HEADER_FIELDS_TOO_LARGE=431,StatusCodes.CONNECTION_CLOSED_WITHOUT_RESPONSE=444,StatusCodes.UNAVAILABLE_FOR_LEGAL_REASONS=451,StatusCodes.CLIENT_CLOSED_REQUEST=499,StatusCodes.INTERNAL_SERVER_ERROR=500,StatusCodes.NOT_IMPLEMENTED=501,StatusCodes.BAD_GATEWAY=502,StatusCodes.SERVICE_UNAVAILABLE=503,StatusCodes.GATEWAY_TIMEOUT=504,StatusCodes.HTTP_VERSION_NOT_SUPPORTED=505,StatusCodes.VARIANT_ALSO_NEGOCIATES=506,StatusCodes.INSUFFICIENT_STORAGE=507,StatusCodes.LOOP_DETECTED=508,StatusCodes.NOT_EXTENDED=510,StatusCodes.NETWORK_AUTHENTICATION_REQUIRED=511,StatusCodes.NETWORK_CONNECTION_TIMEOUT_ERROR=599;class StatusText{}StatusText[100]="Continue",StatusText[101]="Switching Protocols",StatusText[102]="Processing",StatusText[200]="OK",StatusText[201]="Created",StatusText[202]="Accepted",StatusText[203]="Non-Authoritative Information",StatusText[204]="No Content",StatusText[205]="Reset Content",StatusText[206]="Partial Content",StatusText[207]="Multi-Status",StatusText[226]="IM Used",StatusText[300]="Multiple Choices",StatusText[301]="Moved Permanently",StatusText[302]="Found",StatusText[303]="See Other",StatusText[304]="Not Modified",StatusText[305]="Use Proxy",StatusText[307]="Temporary Redirect",StatusText[308]="Permanent Redirect",StatusText[400]="Bad Request",StatusText[401]="Unauthorized",StatusText[402]="Payment Required",StatusText[403]="Forbidden",StatusText[404]="Not Found",StatusText[405]="Method Not Allowed",StatusText[406]="Not Acceptable",StatusText[407]="Proxy Authentication Required",StatusText[408]="Request Timeout",StatusText[409]="Conflict",StatusText[410]="Gone",StatusText[411]="Length Required",StatusText[412]="Precondition Failed",StatusText[413]="Payload Too Large",StatusText[414]="URI Too Long",StatusText[415]="Unsupported Media Type",StatusText[416]="Range Not Satisfiable",StatusText[417]="Expectation Failed",StatusText[418]="I'm a teapot",StatusText[422]="Unprocessable Entity",StatusText[423]="Locked",StatusText[424]="Failed Dependency",StatusText[426]="Upgrade Required",StatusText[428]="Precondition Required",StatusText[429]="Too Many Requests",StatusText[431]="Request Header Fields Too Large",StatusText[451]="Unavailable For Legal Reasons",StatusText[500]="Internal Server Error",StatusText[501]="Not Implemented",StatusText[502]="Bad Gateway",StatusText[503]="Service Unavailable",StatusText[504]="Gateway Time-out",StatusText[505]="HTTP Version Not Supported",StatusText[506]="Variant Also Negotiates",StatusText[507]="Insufficient Storage",StatusText[511]="Network Authentication Required";class ResponseError extends Error{constructor(t,e=StatusCodes.INTERNAL_SERVER_ERROR){super(t),this.status=e,this.name=this.constructor.name}}class NotFoundError extends ResponseError{constructor(t="Not Found"){super(t,StatusCodes.NOT_FOUND)}}class ValidationError extends ResponseError{constructor(t){super(t,StatusCodes.UNPROCESSABLE_ENTITY)}}class HttpResponse{static created(t,e,s){var r,o;const i=StatusCodes.CREATED,a={success:!0,status:i,data:e?{id:e}:{},meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return t.status(i).json(a),a}static noContent(t){t.status(StatusCodes.NO_CONTENT).end()}static ok(t,e,s){var r,o;const i=StatusCodes.OK,a={success:!0,status:i,data:e,meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return t.status(i).json(a),a}static error(t,e,s){var r,o;const{status:i,message:a}=this.normalizeError(s),n=null!==(r=null==StatusText?void 0:StatusText[i])&&void 0!==r?r:"Internal Server Error",u=this.getErrorCode(s),d=this.getErrorName(s),l=Object.assign(Object.assign(Object.assign(Object.assign({success:!1,status:i,statusText:n,message:a,path:null!==(o=t.originalUrl)&&void 0!==o?o:t.url},u?{code:u}:{}),d?{name:d}:{}),{timestamp:(new Date).toISOString()}),this.isDev()&&s instanceof Error&&s.stack?{stack:s.stack}:{});return e.status(i).json(l),l}static getErrorCode(t){return t&&s.isObject(t)&&s.isString(t.code)?this.safeMessage(t.code):""}static getErrorName(t){return t instanceof ResponseError?t.constructor.name:this.isDev()?t instanceof Error?t.name||t.constructor.name:s.isObject(t)&&s.isString(t.name)?t.name:typeof t:""}static isDev(){return"production"!==process.env.NODE_ENV}static normalizeError(t){let e=StatusCodes.INTERNAL_SERVER_ERROR,r=StatusText[500];if(t instanceof ResponseError)return e=this.safeStatus(t.status),r=this.safeMessage(t.message)||r,{status:e,message:r};if(t instanceof Error){const o=t;return s.isNumber(o.statusCode)?e=this.safeStatus(o.statusCode):s.isNumber(o.status)&&(e=this.safeStatus(o.status)),r=this.safeMessage(t.message)||r,{status:e,message:r}}if(s.isString(t))return r=this.safeMessage(t)||r,{status:e,message:r};if(t&&s.isObject(t)){const o=t;return s.isNumber(o.statusCode)?e=this.safeStatus(o.statusCode):s.isNumber(o.status)&&(e=this.safeStatus(o.status)),s.isString(o.message)&&(r=this.safeMessage(o.message)||r),{status:e,message:r}}return{status:e,message:r}}static safeStatus(t){if(!Number.isFinite(t))return StatusCodes.INTERNAL_SERVER_ERROR;const e=Math.trunc(t);return e<400||e>599?StatusCodes.INTERNAL_SERVER_ERROR:e}static safeMessage(t){if(!s.isString(t))return"";const e=t.trim();return e.length>2e3?e.slice(0,2e3)+"...":e}}class Context{constructor(t,e,r,o,i){this.storage={},this.req=t,this.res=e,this.next=r,this.id=s.uuidv7(),this.app=o,this.controller=i}cache(t){const e=Object.assign({},t),r=[];e.private?r.push("private"):e.public&&r.push("public"),e.noStore&&(e.noCache=!0,r.push("no-store")),e.noCache&&(e.maxAge=0,delete e.sMaxAge,r.push("no-cache")),e.noTransform&&r.push("no-transform"),e.proxyRevalidate&&r.push("proxy-revalidate"),e.mustRevalidate?r.push("must-revalidate"):e.noCache||(s.isNumber(e.staleIfError)&&r.push(`stale-if-error=${e.staleIfError}`),s.isNumber(e.staleWhileRevalidate)&&r.push(`stale-while-revalidate=${e.staleWhileRevalidate}`)),s.isNumber(e.maxAge)&&r.push(`max-age=${e.maxAge}`),s.isNumber(e.sMaxAge)&&r.push(`s-maxage=${e.sMaxAge}`),r.length&&(this.res.setHeader("Cache-Control",r.join(",")),e.noCache&&s.forEachKey({"Surrogate-Control":"no-store",Pragma:"no-cache",ETag:"false",Expires:"0"},(t,e)=>this.res.setHeader(e,t)))}clearCookie(t,e){this.res.clearCookie(t,e)}close(t){this.isResponded()||this.res.json(null!=t?t:this.storage)}destroy(t){var e;t&&this.error(t),null===(e=this.res.socket)||void 0===e||e.destroy(t)}error(t){this.isResponded()||HttpResponse.error(this.req,this.res,t)}file(t){this.isResponded()||(this.status(StatusCodes.OK),this.res.sendFile(p.resolve(t)))}getBody(){var t,e;return null!==(e=null===(t=this.req)||void 0===t?void 0:t.body)&&void 0!==e?e:{}}getBodyValue(t){var e;return null===(e=this.req.body)||void 0===e?void 0:e[t]}getCookie(t){var e;return this.normalize(null===(e=this.req.cookies)||void 0===e?void 0:e[t])}getCookies(){var t,e;return s.map(null!==(e=null===(t=this.req)||void 0===t?void 0:t.cookies)&&void 0!==e?e:{},t=>this.normalize(t))}getFiles(){var t,e;return null!==(e=null===(t=this.req)||void 0===t?void 0:t.files)&&void 0!==e?e:{}}getFullUrl(){return`${this.getUrl()}${this.req.originalUrl}`}getHeader(t){var e;return this.normalize(null===(e=this.req.headers)||void 0===e?void 0:e[t])}getHeaders(){var t,e;return s.map(null!==(e=null===(t=this.req)||void 0===t?void 0:t.headers)&&void 0!==e?e:{},t=>this.normalize(t))}getIp(){return h.getClientIp(this.req)||"0.0.0.0"}getQuery(t){var e;return this.normalize(null===(e=this.req.query)||void 0===e?void 0:e[t])}getQueries(){var t,e;return s.map(null!==(e=null===(t=this.req)||void 0===t?void 0:t.query)&&void 0!==e?e:{},t=>this.normalize(t))}getParam(t){var e;const r=null===(e=this.req.params)||void 0===e?void 0:e[t];return s.isUndefined(r)?void 0:String(r)}getParams(){var t,e;return s.map(null!==(e=null===(t=this.req)||void 0===t?void 0:t.params)&&void 0!==e?e:{},t=>{if(!s.isUndefined(t)&&!s.isNull(t))return String(t)})}getUrl(){let t=this.getHeader("x-forwarded-proto")||this.req.protocol||"http";s.isString(t)&&t.includes(",")&&(t=t.split(",")[0].trim());const e=this.getHeader("cf-visitor");if(e){const r=s.parseJson(e);(null==r?void 0:r.scheme)&&(t=r.scheme)}return`${t}://${this.getHeader("host")}`}isResponded(){return this.res.headersSent||this.res.writableEnded}json(t){this.send(StatusCodes.OK,t)}normalize(t){if(!s.isUndefined(t)&&!s.isNull(t))return s.isObject(t)?JSON.stringify(t):String(t)}ok(t,e){this.isResponded()||HttpResponse.ok(this.res,t,e)}prepare(t,e){this.isResponded()||(this.status(t),this.storage=e)}redirect(t){this.isResponded()||this.res.redirect(t)}send(t,e){this.isResponded()||(this.status(t),204===t||304===t||s.isUndefined(e)?this.res.end():this.res.json(e))}setCookie(t,e,s){this.res.cookie(t,e,null!=s?s:{})}status(t){return s.isUndefined(t)||this.res.status(t),this.res.statusCode}success(t){this.send(StatusCodes.OK,{message:t})}}class Metadata{static extends(e){return t.metadata(Metadata.EXTENDS,e,[])}static middleware(e){return t.metadata(Metadata.MIDDLEWARE,e,[])}static parameters(e){return t.metadata(Metadata.PARAMETERS,e,[])}static path(e,s){return t.metadata(Metadata.PATH,e,s)}static routers(e){return t.metadata(Metadata.ROUTERS,e,[])}}Metadata.EXTENDS=Symbol("EXTENDS"),Metadata.MIDDLEWARE=Symbol("MIDDLEWARE"),Metadata.PARAMETERS=Symbol("PARAMETERS"),Metadata.PATH=Symbol("PATH"),Metadata.ROUTERS=Symbol("ROUTERS");class Application extends s.EventEmitter{get controllers(){return[...this._controllers]}get instance(){return this._app}get router(){return this._globalRouter}get server(){return this._server}constructor(e,d){var l,c;super(),this._app=a(),this._boundServers=[],this._options={},this._baseRouter=a.Router(),this._globalRouter=a.Router(),this._controllers=[],this._controllers.push(...e.map(e=>s.isConstructor(e)?new e(...t.getInjectionArgs(e)):e)),this._options=s.merge({},{cross:!1,path:"/",port:3e3,session:{secret:"yoursecret",resave:!0,saveUninitialized:!1,cookie:{maxAge:864e5},proxy:Boolean(null==d?void 0:d.proxy)}},null!=d?d:{}),this._app.use(a.json(this._options.json)),this._app.disable("x-powered-by"),this._options.proxy&&this._app.set("trust proxy",this._options.proxy),this._app.use(a.urlencoded({extended:!0})),this._options.cross&&this._app.use(i(s.isObject(this._options.cross)?this._options.cross:{})),this._app.use(r(this._options.compression)),this._app.use(o(null===(l=this._options.cookie)||void 0===l?void 0:l.secret,this._options.cookie)),this._app.use(n(this._options.session)),this.init(),this._app.use(this._globalRouter);const h=(null===(c=this._options.path)||void 0===c?void 0:c.length)?this._options.path:"/";if(this._app.use(h,this._baseRouter),this._app.all(h+"/*path",(t,e)=>{this._options.redirect?e.redirect(this._options.redirect):HttpResponse.error(t,e,new NotFoundError("Endpoint Not Found"))}),this._options.public){const t=p.resolve(this._options.public);u.existsSync(t)&&this._app.use(a.static(t)),this._app.get("*path",(e,s)=>{u.existsSync(t)?s.sendFile(t+"/index.html"):this._options.notFound?s.redirect(this._options.notFound):HttpResponse.error(e,s,new NotFoundError("File not found"))})}else this._app.all("*path",(t,e)=>{this._options.redirect?e.redirect(this._options.redirect):HttpResponse.error(t,e,new NotFoundError("Endpoint not found"))});this._controllers.forEach(t=>{const e=a.Router(),r=this._collectMiddlewares(t),o=Metadata.parameters(t);this._collectExtends(t).forEach(t=>{r.push(...this._collectMiddlewares(t)),o.push(...Metadata.parameters(t))}),Metadata.routers(t).forEach(i=>{const a=i.propertyKey.toString();if(s.isFunction(t[a])){if(!s.isFunction(e[i.method]))return this._logRouteNotFound(i.method);const n=this._buildMiddlewareChain(t,a,r,o);return e[i.method](i.path,...n,(e,r,i)=>R(this,void 0,void 0,function*(){const n=new Context(e,r,i,this,t),u=this._resolveArgs(n,this._filterParamsByKey(a,o)),d=yield t[a](...u);n.close(s.isArray(d)||s.isObject(d)?d:void 0)}))}this._logRouteNotFound(`${t.name}.${a}`)}),this._collectExtends(t).forEach(i=>{Metadata.routers(i).forEach(i=>{const a=i.propertyKey.toString();if(s.isFunction(t[a])){if(!s.isFunction(e[i.method]))return this._logRouteNotFound(i.method);const n=this._buildMiddlewareChain(t,a,r,o);return e[i.method](i.path,...n,(e,r,i)=>R(this,void 0,void 0,function*(){const n=new Context(e,r,i,this,t),u=this._resolveArgs(n,this._filterParamsByKey(a,o)),d=yield t[a](...u);n.close(s.isArray(d)||s.isObject(d)?d:void 0)}))}this._logRouteNotFound(`${t.constructor.name}.${a}`)})}),this._baseRouter.use(Metadata.path(t,"/"),e)}),this._app.use((t,e,s,r)=>{s.headersSent?r(t):HttpResponse.error(e,s,t)})}init(){}error(t,s){e.Log.error(t)}log(t,s){e.Log.info(t)}_resolveArgs(t,e,s){const r=[],o={ctx:t,key:"",app:this,argument:s};return e.forEach(t=>{r[t.parameterIndex]=t.callback(Object.assign(Object.assign({},o),{key:t.key}))}),r}_buildMiddlewareChain(t,e,r,o){return r.filter(t=>t.propertyKey==e).map(e=>{if(e.callback!=s.noop){const r=this._filterParamsByKey(e.method,o);return(o,i,a)=>R(this,void 0,void 0,function*(){const n=new Context(o,i,a,this,t),u=s.isFunction(e.argument)?e.argument(n):e.argument,d=yield e.callback.call(t,...this._resolveArgs(n,r,u));(s.isArray(d)||s.isObject(d))&&n.close(d)})}this._logRouteNotFound(e.method)}).filter(s.isFunction)}_collectExtends(t){return Metadata.extends(t).reduce((t,e)=>(t.push(e,...this._collectExtends(e)),t),[]).filter((t,e,s)=>s.indexOf(t)===e)}_filterParamsByKey(t,e){return e.filter(e=>e.propertyKey==t)}_collectMiddlewares(t){return[...Metadata.middleware(t)].reverse()}_logRouteNotFound(t){this.error(new Error(`Router "${t}" not found`),"express")}_formatListeningMessage(t){return`Server listening on port ${t}`}listen(){return R(this,void 0,void 0,function*(){var t;const e=this._resolveMode(),s={http:this._startHttp,https:this._startHttps,hybrid:this._startHybrid,redirect:this._startHttpsWithRedirect};yield(null!==(t=s[e])&&void 0!==t?t:this._startHttp).call(this)})}close(){return R(this,void 0,void 0,function*(){yield Promise.all(this._boundServers.map(t=>new Promise((e,s)=>{t.close(t=>t?s(t):e())}))),this._boundServers.length=0,this._server=void 0})}_resolveMode(){return this._resolveTls()&&this._options.mode?this._options.mode:"http"}_resolveTls(){if(this._options.tls&&this._options.tls.key&&this._options.tls.cert)return this._options.tls}_bindServer(t,e,s){return new Promise((r,o)=>{const i=e=>{t.off("listening",a),o(e)},a=()=>{t.off("error",i),this.log(this._formatListeningMessage(e),"express"),r()};t.once("error",i),t.once("listening",a),t.listen(e,s)})}_startHttp(){return R(this,void 0,void 0,function*(){var t;const e=T.createServer(this._app);this._server=e,this._boundServers.push(e),yield this._bindServer(e,null!==(t=this._options.port)&&void 0!==t?t:3e3,this._options.host)})}_startHttps(){return R(this,void 0,void 0,function*(){var t;const e=_.createServer(this._resolveTls(),this._app);this._server=e,this._boundServers.push(e),yield this._bindServer(e,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host)})}_startHttpsWithRedirect(){return R(this,void 0,void 0,function*(){var t,e;const s=_.createServer(this._resolveTls(),this._app),r=T.createServer((t,e)=>{var s,r;const o=(null!==(s=t.headers.host)&&void 0!==s?s:"").split(":")[0];e.writeHead(StatusCodes.MOVED_PERMANENTLY,{Location:`https://${o}${null!==(r=t.url)&&void 0!==r?r:""}`}),e.end()});this._server=s,this._boundServers.push(s,r),yield Promise.all([this._bindServer(s,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host),this._bindServer(r,null!==(e=this._options.redirectPort)&&void 0!==e?e:80,this._options.host)])})}_startHybrid(){return R(this,void 0,void 0,function*(){var t;const e=T.createServer(this._app),s=_.createServer(this._resolveTls(),this._app),r=v.createServer(t=>{const r=setTimeout(()=>t.destroy(),5e3);t.once("data",o=>{clearTimeout(r),t.pause(),t.unshift(o),(22===o[0]?s:e).emit("connection",t),process.nextTick(()=>t.resume())}),t.once("error",()=>clearTimeout(r))});return this._server=s,this._boundServers.push(r,s,e),yield this._bindServer(r,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host),s})}}const C=t=>e=>(s,r,o)=>{Metadata.parameters(s).push({callback:t,key:e,propertyKey:r,parameterIndex:o})},x=C(({app:t})=>t),m=C(({argument:t})=>t),g=C(({ctx:t,key:e})=>e?t.getBodyValue(e):t.getBody()),O=C(({ctx:t,key:e})=>e?t.getCookie(e):t.getCookies()),N=C(({ctx:t})=>t),A=C(({ctx:t})=>t.getFiles()),f=C(({ctx:t,key:e})=>e?t.getHeader(e):t.getHeaders()),I=C(({ctx:t,key:e})=>e?t.getParam(e):t.getParams()),y=C(({ctx:t,key:e})=>e?t.getQuery(e):t.getQueries()),D=C(({ctx:t})=>{var e;return null===(e=t.req)||void 0===e?void 0:e.session}),b=(t,e)=>(r,o)=>{const i=s.uuidv7();N()(r,i,0),Metadata.middleware(r).push({method:i,argument:e,propertyKey:o,callback:t})},M={ALL:"all",GET:"get",POST:"post",PUT:"put",HEAD:"head",DELETE:"delete",OPTIONS:"options",PATCH:"patch"},P=t=>e=>(s,r)=>{Metadata.routers(s).push({method:t,path:(null==e?void 0:e.length)?e:"/",propertyKey:r})},U=P(M.ALL),L=P(M.DELETE),F=P(M.GET),H=P(M.HEAD),q=P(M.OPTIONS),k=P(M.PATCH),w=P(M.POST),j=P(M.PUT),B=(t,e=StatusCodes.BAD_REQUEST)=>{const s=new Error(t);return s.status=e,s},V=t=>{var e;return(null===(e=t.split(".").pop())||void 0===e?void 0:e.toLowerCase())||"bin"},G=(t,e)=>{var s;return null!==(s=t[e])&&void 0!==s?s:null},K=(t,e)=>{const r=s.uuidv7()+"."+e;return u.existsSync(p.join(t,r))?K(t,e):r};exports.All=U,exports.App=x,exports.Application=Application,exports.Argument=m,exports.BadRequestError=class BadRequestError extends ResponseError{constructor(t="Bad Request"){super(t,StatusCodes.BAD_REQUEST)}},exports.Body=g,exports.Cache=t=>(e,s,r)=>{b(e=>{e.cache(Object.assign({},t)),e.next()})(e,s,r)},exports.Context=Context,exports.Controller=t=>e=>{Metadata.path(e,(null==t?void 0:t.length)?t:"/")},exports.Cookies=O,exports.Ctx=N,exports.Delete=L,exports.Extends=t=>e=>{Metadata.extends(e).push(t)},exports.Files=A,exports.ForbiddenError=class ForbiddenError extends ResponseError{constructor(t="Forbidden"){super(t,StatusCodes.FORBIDDEN)}},exports.Get=F,exports.Head=H,exports.Headers=f,exports.HttpResponse=HttpResponse,exports.InternalServerError=class InternalServerError extends ResponseError{constructor(t="Internal server error"){super(t,StatusCodes.INTERNAL_SERVER_ERROR)}},exports.Metadata=Metadata,exports.Methods=M,exports.Middleware=(t,e)=>(r,o)=>{let i=s.noop;if(s.isString(o)){const e=r;s.isFunction(e[t])&&(i=e[t])}Metadata.middleware(r).push({method:t,argument:e,propertyKey:o,callback:i})},exports.NotFoundError=NotFoundError,exports.Options=q,exports.Params=I,exports.Patch=k,exports.Post=w,exports.Put=j,exports.Query=y,exports.ResponseError=ResponseError,exports.Session=D,exports.StatusCodes=StatusCodes,exports.StatusText=StatusText,exports.UnauthorizedError=class UnauthorizedError extends ResponseError{constructor(t="Unauthorized"){super(t,StatusCodes.UNAUTHORIZED)}},exports.Upload=t=>{const e=s.merge({},t),r=E.diskStorage({destination(t,s,r){var o;const i=G(e,s.fieldname);r(null,null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./")},filename(t,s,r){var o;const i=G(e,s.fieldname);r(null,K(null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./",V(s.originalname)))}}),o=Math.max(...Object.values(e).map(t=>{var e;return null!==(e=t.size)&&void 0!==e?e:0})),i=E({storage:r,fileFilter(t,s,r){var o;const i=G(e,s.fieldname);return i?((t,e)=>!e.length||e.includes(V(t.originalname))||e.includes(t.mimetype.toLowerCase()))(s,null!==(o=null==i?void 0:i.types)&&void 0!==o?o:[])?void r(null,!0):r(B(`FILE TYPE NOT ALLOWED FOR "${s.fieldname}"`)):r(B(`UPLOAD FIELD "${s.fieldname}" IS NOT CONFIGURED`))},limits:{fileSize:1024*o*1024}}).fields(Object.keys(e).map(t=>{var s,r;return{name:t,maxCount:null!==(r=null===(s=e[t])||void 0===s?void 0:s.count)&&void 0!==r?r:1}}));return(t,e,s)=>{b(t=>{i(t.req,t.res,e=>{if(!e)return t.next();t.error((t=>"LIMIT_FILE_SIZE"==t.code?(t.message=t.field?`FILE "${t.field}" EXCEEDS MAX SIZE`:"FILE EXCEEDS MAX SIZE",t.status=StatusCodes.PAYLOAD_TOO_LARGE,t):"LIMIT_UNEXPECTED_FILE"==t.code?(t.message=t.field?`FIELD "${t.field}" IS UNEXPECTED OR EXCEEDS MAX COUNT`:"UPLOAD FIELD IS UNEXPECTED OR EXCEEDS MAX COUNT",t.status=StatusCodes.BAD_REQUEST,t):t)(e))})})(t,e,s)}},exports.Use=b,exports.Validate=t=>{const e=s.Validation.object(s.isFunction(t)?t(s.Validation):t).parse();return(t,s,r)=>{b(t=>{var s,r,o;const i=e.validate(null!==(r=null===(s=t.req)||void 0===s?void 0:s.body)&&void 0!==r?r:{});if(i.error)return t.error(new ValidationError(null!==(o=i.message)&&void 0!==o?o:i.error));t.req.body=i.value,t.next()})(t,s,r)}},exports.ValidationError=ValidationError,exports.methodFactory=P,exports.parameterFactory=C;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @andrewcaires/express v2.2.1
2
+ * @andrewcaires/express v2.4.0
3
3
  * Decorators for express
4
4
  * (c) 2026 Andrew Caires
5
5
  * @license: MIT
@@ -14,6 +14,11 @@ import { CorsOptions } from 'cors';
14
14
  import { SessionOptions } from 'express-session';
15
15
  import { CookieParseOptions } from 'cookie-parser';
16
16
 
17
+ interface ExpressError extends Error {
18
+ code?: string;
19
+ status?: number;
20
+ }
21
+
17
22
  interface ICookie extends CookieParseOptions {
18
23
  secret?: string | Array<string>;
19
24
  }
@@ -34,7 +39,7 @@ interface ExpressOptions {
34
39
  proxy?: boolean | number;
35
40
  json?: OptionsJson;
36
41
  mode?: ServerMode;
37
- notfound?: string;
42
+ notFound?: string;
38
43
  path?: string;
39
44
  port?: number;
40
45
  public?: string;
@@ -428,10 +433,12 @@ interface HttpResponseCreated extends HttpResponseBase<{
428
433
  interface HttpResponseError {
429
434
  success: false;
430
435
  status: number;
431
- error: string;
436
+ statusText: string;
432
437
  message: string;
433
- path?: string;
434
- timestamp?: string;
438
+ path: string;
439
+ timestamp: string;
440
+ code?: string;
441
+ name?: string;
435
442
  stack?: string;
436
443
  }
437
444
 
@@ -440,6 +447,10 @@ interface HttpResponseOptions {
440
447
  meta?: TypeAnyObject;
441
448
  }
442
449
 
450
+ interface UploadError extends ExpressError {
451
+ field?: string;
452
+ }
453
+
443
454
  interface UploadOptions {
444
455
  count?: number;
445
456
  path?: string;
@@ -571,6 +582,8 @@ declare class HttpResponse {
571
582
  static noContent(res: Response): void;
572
583
  static ok<T = TypeAnyObject | Array<TypeAnyObject>>(res: Response, data: T, options?: HttpResponseOptions): HttpResponseBase<T>;
573
584
  static error(req: Request, res: Response, error: unknown): HttpResponseError;
585
+ private static getErrorCode;
586
+ private static getErrorName;
574
587
  private static isDev;
575
588
  private static normalizeError;
576
589
  private static safeStatus;
@@ -716,4 +729,4 @@ declare class StatusText {
716
729
  }
717
730
 
718
731
  export { All, App, Application, Argument, BadRequestError, Body, Cache, Context, Controller, Cookies, Ctx, Delete, Extends, Files, ForbiddenError, Get, Head, Headers, HttpResponse, InternalServerError, Metadata, Methods, Middleware, NotFoundError, Options, Params, Patch, Post, Put, Query, ResponseError, Session, StatusCodes, StatusText, UnauthorizedError, Upload, Use, Validate, ValidationError, methodFactory, parameterFactory };
719
- export type { CallbackObject, ComponentsObject, ContactObject, EncodingObject, ExampleObject, ExpressOptions, ExternalDocumentationObject, FileUpload, HeaderObject, HttpResponseBase, HttpResponseCreated, HttpResponseError, HttpResponseOptions, IArgs, ICache, ICookie, IHandler, IMiddlewares, IParameter, IRouter, IStore, IUse, InfoObject, LicenseObject, LinkObject, MediaTypeObject, Method, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterObject, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SecurityRequirementObject, SecuritySchemeObject, ServerMode, ServerObject, ServerVariableObject, TagObject, TlsOptions, UploadOptions, ValidationFunction };
732
+ export type { CallbackObject, ComponentsObject, ContactObject, EncodingObject, ExampleObject, ExpressError, ExpressOptions, ExternalDocumentationObject, FileUpload, HeaderObject, HttpResponseBase, HttpResponseCreated, HttpResponseError, HttpResponseOptions, IArgs, ICache, ICookie, IHandler, IMiddlewares, IParameter, IRouter, IStore, IUse, InfoObject, LicenseObject, LinkObject, MediaTypeObject, Method, OAuthFlowObject, OAuthFlowsObject, OpenAPIObject, OperationObject, ParameterObject, PathItemObject, PathsObject, ReferenceObject, RequestBodyObject, ResponseObject, ResponsesObject, SchemaObject, SecurityRequirementObject, SecuritySchemeObject, ServerMode, ServerObject, ServerVariableObject, TagObject, TlsOptions, UploadError, UploadOptions, ValidationFunction };
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @andrewcaires/express v2.2.1
2
+ * @andrewcaires/express v2.4.0
3
3
  * Decorators for express
4
4
  * (c) 2026 Andrew Caires
5
5
  * @license: MIT
6
6
  */
7
- import{metadata as e,getInjectionArgs as t}from"@andrewcaires/decorator";import{Log as s}from"@andrewcaires/node";import{isNumber as r,isString as o,isObject as i,uuidv7 as n,forEachKey as a,map as l,isUndefined as u,isNull as d,parseJson as h,EventEmitter as c,isConstructor as p,merge as E,isFunction as _,noop as v,isArray as m,Validation as R}from"@andrewcaires/utils.js";import T from"compression";import g from"cookie-parser";import N from"cors";import O,{Router as f,json as S,urlencoded as A}from"express";import I from"express-session";import{existsSync as y}from"fs";import*as D from"http";import*as C from"https";import*as P from"net";import{resolve as L,join as U}from"path";import{getClientIp as b}from"request-ip";import x,{diskStorage as M}from"multer";function F(e,t,s,r){return new(s||(s=Promise))(function(o,i){function n(e){try{l(r.next(e))}catch(e){i(e)}}function a(e){try{l(r.throw(e))}catch(e){i(e)}}function l(e){var t;e.done?o(e.value):(t=e.value,t instanceof s?t:new s(function(e){e(t)})).then(n,a)}l((r=r.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class w{}w.CONTINUE=100,w.SWITCHING_PROTOCOLS=101,w.PROCESSING=102,w.OK=200,w.CREATED=201,w.ACCEPTED=202,w.NON_AUTHORITATIVE_INFORMATION=203,w.NO_CONTENT=204,w.RESET_CONTENT=205,w.PARTIAL_CONTENT=206,w.MULTI_STATUS=207,w.ALREADY_REPORTED=208,w.IM_USED=226,w.MULTIPLE_CHOICES=300,w.MOVED_PERMANENTLY=301,w.FOUND=302,w.SEE_OTHER=303,w.NOT_MODIFIED=304,w.USE_PROXY=305,w.TEMPORARY_REDIRECT=307,w.PERMANENT_REDIRECT=308,w.BAD_REQUEST=400,w.UNAUTHORIZED=401,w.PAYMENT_REQUIRED=402,w.FORBIDDEN=403,w.NOT_FOUND=404,w.METHOD_NOT_ALLOWED=405,w.NOT_ACCEPTABLE=406,w.PROXY_AUTHENTICATION_REQUIRED=407,w.REQUEST_TIMEOUT=408,w.CONFLICT=409,w.GONE=410,w.LENGTH_REQUIRED=411,w.PRECONDITION_FAILED=412,w.PAYLOAD_TOO_LARGE=413,w.REQUEST_URI_TOO_LONG=414,w.UNSUPPORTED_MEDIA_TYPE=415,w.REQUESTED_RANGE_NOT_SATISFIABLE=416,w.EXPECTATION_FAILED=417,w.IM_A_TEAPOT=418,w.MISDIRECTED_REQUEST=421,w.UNPROCESSABLE_ENTITY=422,w.LOCKED=423,w.FAILED_DEPENDENCY=424,w.UPGRADE_REQUIRED=426,w.PRECONDITION_REQUIRED=428,w.TOO_MANY_REQUESTS=429,w.REQUEST_HEADER_FIELDS_TOO_LARGE=431,w.CONNECTION_CLOSED_WITHOUT_RESPONSE=444,w.UNAVAILABLE_FOR_LEGAL_REASONS=451,w.CLIENT_CLOSED_REQUEST=499,w.INTERNAL_SERVER_ERROR=500,w.NOT_IMPLEMENTED=501,w.BAD_GATEWAY=502,w.SERVICE_UNAVAILABLE=503,w.GATEWAY_TIMEOUT=504,w.HTTP_VERSION_NOT_SUPPORTED=505,w.VARIANT_ALSO_NEGOCIATES=506,w.INSUFFICIENT_STORAGE=507,w.LOOP_DETECTED=508,w.NOT_EXTENDED=510,w.NETWORK_AUTHENTICATION_REQUIRED=511,w.NETWORK_CONNECTION_TIMEOUT_ERROR=599;class k{}k[100]="Continue",k[101]="Switching Protocols",k[102]="Processing",k[200]="OK",k[201]="Created",k[202]="Accepted",k[203]="Non-Authoritative Information",k[204]="No Content",k[205]="Reset Content",k[206]="Partial Content",k[207]="Multi-Status",k[226]="IM Used",k[300]="Multiple Choices",k[301]="Moved Permanently",k[302]="Found",k[303]="See Other",k[304]="Not Modified",k[305]="Use Proxy",k[307]="Temporary Redirect",k[308]="Permanent Redirect",k[400]="Bad Request",k[401]="Unauthorized",k[402]="Payment Required",k[403]="Forbidden",k[404]="Not Found",k[405]="Method Not Allowed",k[406]="Not Acceptable",k[407]="Proxy Authentication Required",k[408]="Request Timeout",k[409]="Conflict",k[410]="Gone",k[411]="Length Required",k[412]="Precondition Failed",k[413]="Payload Too Large",k[414]="URI Too Long",k[415]="Unsupported Media Type",k[416]="Range Not Satisfiable",k[417]="Expectation Failed",k[418]="I'm a teapot",k[422]="Unprocessable Entity",k[423]="Locked",k[424]="Failed Dependency",k[426]="Upgrade Required",k[428]="Precondition Required",k[429]="Too Many Requests",k[431]="Request Header Fields Too Large",k[451]="Unavailable For Legal Reasons",k[500]="Internal Server Error",k[501]="Not Implemented",k[502]="Bad Gateway",k[503]="Service Unavailable",k[504]="Gateway Time-out",k[505]="HTTP Version Not Supported",k[506]="Variant Also Negotiates",k[507]="Insufficient Storage",k[511]="Network Authentication Required";class H extends Error{constructor(e,t=w.INTERNAL_SERVER_ERROR){super(e),this.status=t}}class q extends H{constructor(e="Bad Request"){super(e,w.BAD_REQUEST)}}class B extends H{constructor(e="Forbidden"){super(e,w.FORBIDDEN)}}class K extends H{constructor(e="Internal server error"){super(e,w.INTERNAL_SERVER_ERROR)}}class G extends H{constructor(e="Not Found"){super(e,w.NOT_FOUND)}}class Q extends H{constructor(e="Unauthorized"){super(e,w.UNAUTHORIZED)}}class V extends H{constructor(e){super(e,w.UNPROCESSABLE_ENTITY)}}class ${static created(e,t,s){var r,o;const i=w.CREATED,n={success:!0,status:i,data:t?{id:t}:{},meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return e.status(i).json(n),n}static noContent(e){e.status(w.NO_CONTENT).end()}static ok(e,t,s){var r,o;const i=w.OK,n={success:!0,status:i,data:t,meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return e.status(i).json(n),n}static error(e,t,s){var r,o;const{status:i,message:n}=this.normalizeError(s),a=Object.assign({success:!1,status:i,error:null!==(r=null==k?void 0:k[i])&&void 0!==r?r:"Internal Server Error",message:n,path:null!==(o=e.originalUrl)&&void 0!==o?o:e.url,timestamp:(new Date).toISOString()},this.isDev()&&s instanceof Error&&s.stack?{stack:s.stack}:{});return t.status(i).json(a),a}static isDev(){return"production"!==process.env.NODE_ENV}static normalizeError(e){let t=w.INTERNAL_SERVER_ERROR,s=k[500];if(e instanceof H)return t=this.safeStatus(e.status),s=this.safeMessage(e.message)||s,{status:t,message:s};if(e instanceof Error){const o=e;return r(o.statusCode)?t=this.safeStatus(o.statusCode):r(o.status)&&(t=this.safeStatus(o.status)),s=this.safeMessage(e.message)||s,{status:t,message:s}}if(o(e))return s=this.safeMessage(e)||s,{status:t,message:s};if(e&&i(e)){const i=e;return r(i.statusCode)?t=this.safeStatus(i.statusCode):r(i.status)&&(t=this.safeStatus(i.status)),o(i.message)&&(s=this.safeMessage(i.message)||s),{status:t,message:s}}return{status:t,message:s}}static safeStatus(e){if(!Number.isFinite(e))return w.INTERNAL_SERVER_ERROR;const t=Math.trunc(e);return t<400||t>599?w.INTERNAL_SERVER_ERROR:t}static safeMessage(e){if(!o(e))return"";const t=e.trim();return t.length>2e3?t.slice(0,2e3)+"...":t}}class j{constructor(e,t,s,r,o){this.storage={},this.req=e,this.res=t,this.next=s,this.id=n(),this.app=r,this.controller=o}cache(e){const t=Object.assign({},e),s=[];t.private?s.push("private"):t.public&&s.push("public"),t.noStore&&(t.noCache=!0,s.push("no-store")),t.noCache&&(t.maxAge=0,delete t.sMaxAge,s.push("no-cache")),t.noTransform&&s.push("no-transform"),t.proxyRevalidate&&s.push("proxy-revalidate"),t.mustRevalidate?s.push("must-revalidate"):t.noCache||(r(t.staleIfError)&&s.push(`stale-if-error=${t.staleIfError}`),r(t.staleWhileRevalidate)&&s.push(`stale-while-revalidate=${t.staleWhileRevalidate}`)),r(t.maxAge)&&s.push(`max-age=${t.maxAge}`),r(t.sMaxAge)&&s.push(`s-maxage=${t.sMaxAge}`),s.length&&(this.res.setHeader("Cache-Control",s.join(",")),t.noCache&&a({"Surrogate-Control":"no-store",Pragma:"no-cache",ETag:"false",Expires:"0"},(e,t)=>this.res.setHeader(t,e)))}clearCookie(e,t){this.res.clearCookie(e,t)}close(e){this.isResponded()||this.res.json(null!=e?e:this.storage)}destroy(e){var t;e&&this.error(e),null===(t=this.res.socket)||void 0===t||t.destroy(e)}error(e){this.isResponded()||$.error(this.req,this.res,e)}file(e){this.isResponded()||(this.status(w.OK),this.res.sendFile(L(e)))}getBody(){var e,t;return null!==(t=null===(e=this.req)||void 0===e?void 0:e.body)&&void 0!==t?t:{}}getBodyValue(e){var t;return null===(t=this.req.body)||void 0===t?void 0:t[e]}getCookie(e){var t;return this.normalize(null===(t=this.req.cookies)||void 0===t?void 0:t[e])}getCookies(){var e,t;return l(null!==(t=null===(e=this.req)||void 0===e?void 0:e.cookies)&&void 0!==t?t:{},e=>this.normalize(e))}getFiles(){var e,t;return null!==(t=null===(e=this.req)||void 0===e?void 0:e.files)&&void 0!==t?t:{}}getFullUrl(){return`${this.getUrl()}${this.req.originalUrl}`}getHeader(e){var t;return this.normalize(null===(t=this.req.headers)||void 0===t?void 0:t[e])}getHeaders(){var e,t;return l(null!==(t=null===(e=this.req)||void 0===e?void 0:e.headers)&&void 0!==t?t:{},e=>this.normalize(e))}getIp(){return b(this.req)||"0.0.0.0"}getQuery(e){var t;return this.normalize(null===(t=this.req.query)||void 0===t?void 0:t[e])}getQueries(){var e,t;return l(null!==(t=null===(e=this.req)||void 0===e?void 0:e.query)&&void 0!==t?t:{},e=>this.normalize(e))}getParam(e){var t;const s=null===(t=this.req.params)||void 0===t?void 0:t[e];return u(s)?void 0:String(s)}getParams(){var e,t;return l(null!==(t=null===(e=this.req)||void 0===e?void 0:e.params)&&void 0!==t?t:{},e=>{if(!u(e)&&!d(e))return String(e)})}getUrl(){let e=this.getHeader("x-forwarded-proto")||this.req.protocol||"http";o(e)&&e.includes(",")&&(e=e.split(",")[0].trim());const t=this.getHeader("cf-visitor");if(t){const s=h(t);(null==s?void 0:s.scheme)&&(e=s.scheme)}return`${e}://${this.getHeader("host")}`}isResponded(){return this.res.headersSent||this.res.writableEnded}json(e){this.send(w.OK,e)}normalize(e){if(!u(e)&&!d(e))return i(e)?JSON.stringify(e):String(e)}ok(e,t){this.isResponded()||$.ok(this.res,e,t)}prepare(e,t){this.isResponded()||(this.status(e),this.storage=t)}redirect(e){this.isResponded()||this.res.redirect(e)}send(e,t){this.isResponded()||(this.status(e),204===e||304===e||u(t)?this.res.end():this.res.json(t))}setCookie(e,t,s){this.res.cookie(e,t,null!=s?s:{})}status(e){return u(e)||this.res.status(e),this.res.statusCode}success(e){this.send(w.OK,{message:e})}}class Y{static extends(t){return e(Y.EXTENDS,t,[])}static middleware(t){return e(Y.MIDDLEWARE,t,[])}static parameters(t){return e(Y.PARAMETERS,t,[])}static path(t,s){return e(Y.PATH,t,s)}static routers(t){return e(Y.ROUTERS,t,[])}}Y.EXTENDS=Symbol("EXTENDS"),Y.MIDDLEWARE=Symbol("MIDDLEWARE"),Y.PARAMETERS=Symbol("PARAMETERS"),Y.PATH=Symbol("PATH"),Y.ROUTERS=Symbol("ROUTERS");class W extends c{get controllers(){return[...this._controllers]}get instance(){return this._app}get router(){return this._globalRouter}get server(){return this._server}constructor(e,s){var r,o;super(),this._app=O(),this._boundServers=[],this._options={},this._baseRouter=f(),this._globalRouter=f(),this._controllers=[],this._controllers.push(...e.map(e=>p(e)?new e(...t(e)):e)),this._options=E({},{cross:!1,path:"/",port:3e3,session:{secret:"yoursecret",resave:!0,saveUninitialized:!1,cookie:{maxAge:864e5}}},null!=s?s:{}),this._app.use(S(this._options.json)),this._app.disable("x-powered-by"),this._options.proxy&&this._app.set("trust proxy",this._options.proxy),this._app.use(A({extended:!0})),this._options.cross&&this._app.use(N(i(this._options.cross)?this._options.cross:{})),this._app.use(T(this._options.compression)),this._app.use(g(null===(r=this._options.cookie)||void 0===r?void 0:r.secret,this._options.cookie)),this._app.use(I(this._options.session)),this.init(),this._app.use(this._globalRouter);const n=(null===(o=this._options.path)||void 0===o?void 0:o.length)?this._options.path:"/";if(this._app.use(n,this._baseRouter),this._app.all(n+"/*path",(e,t)=>{this._options.redirect?t.redirect(this._options.redirect):$.error(e,t,new G("Endpoint Not Found"))}),this._options.public){const e=L(this._options.public);y(e)&&this._app.use(O.static(e)),this._app.get("*path",(t,s)=>{y(e)?s.sendFile(e+"/index.html"):this._options.notfound?s.redirect(this._options.notfound):$.error(t,s,new G('FILE "index.html" Not Found'))})}else this._app.all("*path",(e,t)=>{this._options.redirect?t.redirect(this._options.redirect):$.error(e,t,new G("Endpoint not found"))});this._controllers.forEach(e=>{const t=f(),s=this._collectMiddlewares(e),r=Y.parameters(e);this._collectExtends(e).forEach(e=>{s.push(...this._collectMiddlewares(e)),r.push(...Y.parameters(e))}),Y.routers(e).forEach(o=>{const n=o.propertyKey.toString();if(_(e[n])){if(!_(t[o.method]))return this._logRouteNotFound(o.method);const a=this._buildMiddlewareChain(e,n,s,r);return t[o.method](o.path,...a,(t,s,o)=>F(this,void 0,void 0,function*(){const a=new j(t,s,o,this,e),l=this._resolveArgs(a,this._filterParamsByKey(n,r)),u=yield e[n](...l);a.close(m(u)||i(u)?u:void 0)}))}this._logRouteNotFound(`${e.name}.${n}`)}),this._collectExtends(e).forEach(o=>{Y.routers(o).forEach(o=>{const n=o.propertyKey.toString();if(_(e[n])){if(!_(t[o.method]))return this._logRouteNotFound(o.method);const a=this._buildMiddlewareChain(e,n,s,r);return t[o.method](o.path,...a,(t,s,o)=>F(this,void 0,void 0,function*(){const a=new j(t,s,o,this,e),l=this._resolveArgs(a,this._filterParamsByKey(n,r)),u=yield e[n](...l);a.close(m(u)||i(u)?u:void 0)}))}this._logRouteNotFound(`${e.constructor.name}.${n}`)})}),this._baseRouter.use(Y.path(e,"/"),t)})}init(){}error(e,t){s.error(e)}log(e,t){s.info(e)}_resolveArgs(e,t,s){const r=[],o={ctx:e,key:"",app:this,argument:s};return t.forEach(e=>{r[e.parameterIndex]=e.callback(Object.assign(Object.assign({},o),{key:e.key}))}),r}_buildMiddlewareChain(e,t,s,r){return s.filter(e=>e.propertyKey==t).map(t=>{if(t.callback!=v){const s=this._filterParamsByKey(t.method,r);return(r,o,n)=>F(this,void 0,void 0,function*(){const a=new j(r,o,n,this,e),l=_(t.argument)?t.argument(a):t.argument,u=yield t.callback.call(e,...this._resolveArgs(a,s,l));(m(u)||i(u))&&a.close(u)})}this._logRouteNotFound(t.method)}).filter(_)}_collectExtends(e){return Y.extends(e).reduce((e,t)=>(e.push(t,...this._collectExtends(t)),e),[]).filter((e,t,s)=>s.indexOf(e)===t)}_filterParamsByKey(e,t){return t.filter(t=>t.propertyKey==e)}_collectMiddlewares(e){return[...Y.middleware(e)].reverse()}_logRouteNotFound(e){this.error(new Error(`Router "${e}" not found`),"express")}_formatListeningMessage(e){return`Server listening on port ${e}`}listen(){return F(this,void 0,void 0,function*(){var e;const t=this._resolveMode(),s={http:this._startHttp,https:this._startHttps,hybrid:this._startHybrid,redirect:this._startHttpsWithRedirect};yield(null!==(e=s[t])&&void 0!==e?e:this._startHttp).call(this)})}close(){return F(this,void 0,void 0,function*(){yield Promise.all(this._boundServers.map(e=>new Promise((t,s)=>{e.close(e=>e?s(e):t())}))),this._boundServers.length=0,this._server=void 0})}_resolveMode(){return this._resolveTls()&&this._options.mode?this._options.mode:"http"}_resolveTls(){if(this._options.tls&&this._options.tls.key&&this._options.tls.cert)return this._options.tls}_bindServer(e,t,s){return new Promise((r,o)=>{const i=t=>{e.off("listening",n),o(t)},n=()=>{e.off("error",i),this.log(this._formatListeningMessage(t),"express"),r()};e.once("error",i),e.once("listening",n),e.listen(t,s)})}_startHttp(){return F(this,void 0,void 0,function*(){var e;const t=D.createServer(this._app);this._server=t,this._boundServers.push(t),yield this._bindServer(t,null!==(e=this._options.port)&&void 0!==e?e:3e3,this._options.host)})}_startHttps(){return F(this,void 0,void 0,function*(){var e;const t=C.createServer(this._resolveTls(),this._app);this._server=t,this._boundServers.push(t),yield this._bindServer(t,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host)})}_startHttpsWithRedirect(){return F(this,void 0,void 0,function*(){var e,t;const s=C.createServer(this._resolveTls(),this._app),r=D.createServer((e,t)=>{var s,r;const o=(null!==(s=e.headers.host)&&void 0!==s?s:"").split(":")[0];t.writeHead(w.MOVED_PERMANENTLY,{Location:`https://${o}${null!==(r=e.url)&&void 0!==r?r:""}`}),t.end()});this._server=s,this._boundServers.push(s,r),yield Promise.all([this._bindServer(s,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host),this._bindServer(r,null!==(t=this._options.redirectPort)&&void 0!==t?t:80,this._options.host)])})}_startHybrid(){return F(this,void 0,void 0,function*(){var e;const t=D.createServer(this._app),s=C.createServer(this._resolveTls(),this._app),r=P.createServer(e=>{const r=setTimeout(()=>e.destroy(),5e3);e.once("data",o=>{clearTimeout(r),e.pause(),e.unshift(o),(22===o[0]?s:t).emit("connection",e),process.nextTick(()=>e.resume())}),e.once("error",()=>clearTimeout(r))});return this._server=s,this._boundServers.push(r,s,t),yield this._bindServer(r,null!==(e=this._options.port)&&void 0!==e?e:443,this._options.host),s})}}const z=e=>t=>{Y.path(t,(null==e?void 0:e.length)?e:"/")},X=e=>t=>{Y.extends(t).push(e)},Z=e=>t=>(s,r,o)=>{Y.parameters(s).push({callback:e,key:t,propertyKey:r,parameterIndex:o})},J=Z(({app:e})=>e),ee=Z(({argument:e})=>e),te=Z(({ctx:e,key:t})=>t?e.getBodyValue(t):e.getBody()),se=Z(({ctx:e,key:t})=>t?e.getCookie(t):e.getCookies()),re=Z(({ctx:e})=>e),oe=Z(({ctx:e})=>e.getFiles()),ie=Z(({ctx:e,key:t})=>t?e.getHeader(t):e.getHeaders()),ne=Z(({ctx:e,key:t})=>t?e.getParam(t):e.getParams()),ae=Z(({ctx:e,key:t})=>t?e.getQuery(t):e.getQueries()),le=Z(({ctx:e})=>{var t;return null===(t=e.req)||void 0===t?void 0:t.session}),ue=(e,t)=>(s,r)=>{const o=n();re()(s,o,0),Y.middleware(s).push({method:o,argument:t,propertyKey:r,callback:e})},de=e=>(t,s,r)=>{ue(t=>{t.cache(Object.assign({},e)),t.next()})(t,s,r)},he={ALL:"all",GET:"get",POST:"post",PUT:"put",HEAD:"head",DELETE:"delete",OPTIONS:"options",PATCH:"patch"},ce=e=>t=>(s,r)=>{Y.routers(s).push({method:e,path:(null==t?void 0:t.length)?t:"/",propertyKey:r})},pe=ce(he.ALL),Ee=ce(he.DELETE),_e=ce(he.GET),ve=ce(he.HEAD),me=ce(he.OPTIONS),Re=ce(he.PATCH),Te=ce(he.POST),ge=ce(he.PUT),Ne=(e,t)=>(s,r)=>{let i=v;if(o(r)){const t=s;_(t[e])&&(i=t[e])}Y.middleware(s).push({method:e,argument:t,propertyKey:r,callback:i})},Oe=e=>{var t;return(null===(t=e.split(".").pop())||void 0===t?void 0:t.toLowerCase())||"bin"},fe=(e,t)=>{var s;return null!==(s=e[t])&&void 0!==s?s:null},Se=(e,t)=>{const s=n()+"."+t;return y(U(e,s))?Se(e,t):s},Ae=e=>{const t=E({},e),s=M({destination(e,s,r){var o;const i=fe(t,s.fieldname);r(null,null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./")},filename(e,s,r){var o;const i=fe(t,s.fieldname);r(null,Se(null!==(o=null==i?void 0:i.path)&&void 0!==o?o:"./",Oe(s.originalname)))}}),r=Math.max(...Object.values(t).map(e=>{var t;return null!==(t=e.size)&&void 0!==t?t:0})),o=x({storage:s,fileFilter(e,s,r){var o;const i=fe(t,s.fieldname);return i?((e,t)=>!t.length||t.includes(Oe(e.originalname))||t.includes(e.mimetype.toLowerCase()))(s,null!==(o=null==i?void 0:i.types)&&void 0!==o?o:[])?void r(null,!0):r(new Error(`FILE TYPE NOT ALLOWED FOR "${s.fieldname}"`)):r(new Error(`UPLOAD FIELD "${s.fieldname}" IS NOT CONFIGURED`))},limits:{fileSize:1024*r*1024}}).fields(Object.keys(t).map(e=>{var s,r;return{name:e,maxCount:null!==(r=null===(s=t[e])||void 0===s?void 0:s.count)&&void 0!==r?r:1}}));return(e,t,s)=>{ue(e=>{o(e.req,e.res,t=>{if(!t)return e.next();"LIMIT_UNEXPECTED_FILE"==t.code&&(t.message=`FIELD "${t.field}" EXCEEDS MAX SIZE`),e.destroy(t)})})(e,t,s)}},Ie=e=>{const t=R.object(_(e)?e(R):e).parse();return(e,s,r)=>{ue(e=>F(void 0,void 0,void 0,function*(){var s,r;const{error:o,message:i,value:n}=yield t.validateAsync(null!==(r=null===(s=e.req)||void 0===s?void 0:s.body)&&void 0!==r?r:{});if(o)return e.error(new V(null!=i?i:o));e.req.body=n,e.next()}))(e,s,r)}};export{pe as All,J as App,W as Application,ee as Argument,q as BadRequestError,te as Body,de as Cache,j as Context,z as Controller,se as Cookies,re as Ctx,Ee as Delete,X as Extends,oe as Files,B as ForbiddenError,_e as Get,ve as Head,ie as Headers,$ as HttpResponse,K as InternalServerError,Y as Metadata,he as Methods,Ne as Middleware,G as NotFoundError,me as Options,ne as Params,Re as Patch,Te as Post,ge as Put,ae as Query,H as ResponseError,le as Session,w as StatusCodes,k as StatusText,Q as UnauthorizedError,Ae as Upload,ue as Use,Ie as Validate,V as ValidationError,ce as methodFactory,Z as parameterFactory};
7
+ import{metadata as t,getInjectionArgs as e}from"@andrewcaires/decorator";import{Log as s}from"@andrewcaires/node";import{isObject as r,isString as o,isNumber as a,uuidv7 as i,forEachKey as n,map as u,isUndefined as d,isNull as l,parseJson as h,EventEmitter as c,isConstructor as p,merge as E,isFunction as S,noop as T,isArray as _,Validation as v}from"@andrewcaires/utils.js";import R from"compression";import m from"cookie-parser";import C from"cors";import g,{Router as O,json as N,urlencoded as x}from"express";import f from"express-session";import{existsSync as A}from"fs";import*as I from"http";import*as y from"https";import*as D from"net";import{resolve as M,join as P}from"path";import{getClientIp as L}from"request-ip";import U,{diskStorage as b}from"multer";function F(t,e,s,r){return new(s||(s=Promise))(function(o,a){function i(t){try{u(r.next(t))}catch(t){a(t)}}function n(t){try{u(r.throw(t))}catch(t){a(t)}}function u(t){var e;t.done?o(t.value):(e=t.value,e instanceof s?e:new s(function(t){t(e)})).then(i,n)}u((r=r.apply(t,e||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;class StatusCodes{}StatusCodes.CONTINUE=100,StatusCodes.SWITCHING_PROTOCOLS=101,StatusCodes.PROCESSING=102,StatusCodes.OK=200,StatusCodes.CREATED=201,StatusCodes.ACCEPTED=202,StatusCodes.NON_AUTHORITATIVE_INFORMATION=203,StatusCodes.NO_CONTENT=204,StatusCodes.RESET_CONTENT=205,StatusCodes.PARTIAL_CONTENT=206,StatusCodes.MULTI_STATUS=207,StatusCodes.ALREADY_REPORTED=208,StatusCodes.IM_USED=226,StatusCodes.MULTIPLE_CHOICES=300,StatusCodes.MOVED_PERMANENTLY=301,StatusCodes.FOUND=302,StatusCodes.SEE_OTHER=303,StatusCodes.NOT_MODIFIED=304,StatusCodes.USE_PROXY=305,StatusCodes.TEMPORARY_REDIRECT=307,StatusCodes.PERMANENT_REDIRECT=308,StatusCodes.BAD_REQUEST=400,StatusCodes.UNAUTHORIZED=401,StatusCodes.PAYMENT_REQUIRED=402,StatusCodes.FORBIDDEN=403,StatusCodes.NOT_FOUND=404,StatusCodes.METHOD_NOT_ALLOWED=405,StatusCodes.NOT_ACCEPTABLE=406,StatusCodes.PROXY_AUTHENTICATION_REQUIRED=407,StatusCodes.REQUEST_TIMEOUT=408,StatusCodes.CONFLICT=409,StatusCodes.GONE=410,StatusCodes.LENGTH_REQUIRED=411,StatusCodes.PRECONDITION_FAILED=412,StatusCodes.PAYLOAD_TOO_LARGE=413,StatusCodes.REQUEST_URI_TOO_LONG=414,StatusCodes.UNSUPPORTED_MEDIA_TYPE=415,StatusCodes.REQUESTED_RANGE_NOT_SATISFIABLE=416,StatusCodes.EXPECTATION_FAILED=417,StatusCodes.IM_A_TEAPOT=418,StatusCodes.MISDIRECTED_REQUEST=421,StatusCodes.UNPROCESSABLE_ENTITY=422,StatusCodes.LOCKED=423,StatusCodes.FAILED_DEPENDENCY=424,StatusCodes.UPGRADE_REQUIRED=426,StatusCodes.PRECONDITION_REQUIRED=428,StatusCodes.TOO_MANY_REQUESTS=429,StatusCodes.REQUEST_HEADER_FIELDS_TOO_LARGE=431,StatusCodes.CONNECTION_CLOSED_WITHOUT_RESPONSE=444,StatusCodes.UNAVAILABLE_FOR_LEGAL_REASONS=451,StatusCodes.CLIENT_CLOSED_REQUEST=499,StatusCodes.INTERNAL_SERVER_ERROR=500,StatusCodes.NOT_IMPLEMENTED=501,StatusCodes.BAD_GATEWAY=502,StatusCodes.SERVICE_UNAVAILABLE=503,StatusCodes.GATEWAY_TIMEOUT=504,StatusCodes.HTTP_VERSION_NOT_SUPPORTED=505,StatusCodes.VARIANT_ALSO_NEGOCIATES=506,StatusCodes.INSUFFICIENT_STORAGE=507,StatusCodes.LOOP_DETECTED=508,StatusCodes.NOT_EXTENDED=510,StatusCodes.NETWORK_AUTHENTICATION_REQUIRED=511,StatusCodes.NETWORK_CONNECTION_TIMEOUT_ERROR=599;class StatusText{}StatusText[100]="Continue",StatusText[101]="Switching Protocols",StatusText[102]="Processing",StatusText[200]="OK",StatusText[201]="Created",StatusText[202]="Accepted",StatusText[203]="Non-Authoritative Information",StatusText[204]="No Content",StatusText[205]="Reset Content",StatusText[206]="Partial Content",StatusText[207]="Multi-Status",StatusText[226]="IM Used",StatusText[300]="Multiple Choices",StatusText[301]="Moved Permanently",StatusText[302]="Found",StatusText[303]="See Other",StatusText[304]="Not Modified",StatusText[305]="Use Proxy",StatusText[307]="Temporary Redirect",StatusText[308]="Permanent Redirect",StatusText[400]="Bad Request",StatusText[401]="Unauthorized",StatusText[402]="Payment Required",StatusText[403]="Forbidden",StatusText[404]="Not Found",StatusText[405]="Method Not Allowed",StatusText[406]="Not Acceptable",StatusText[407]="Proxy Authentication Required",StatusText[408]="Request Timeout",StatusText[409]="Conflict",StatusText[410]="Gone",StatusText[411]="Length Required",StatusText[412]="Precondition Failed",StatusText[413]="Payload Too Large",StatusText[414]="URI Too Long",StatusText[415]="Unsupported Media Type",StatusText[416]="Range Not Satisfiable",StatusText[417]="Expectation Failed",StatusText[418]="I'm a teapot",StatusText[422]="Unprocessable Entity",StatusText[423]="Locked",StatusText[424]="Failed Dependency",StatusText[426]="Upgrade Required",StatusText[428]="Precondition Required",StatusText[429]="Too Many Requests",StatusText[431]="Request Header Fields Too Large",StatusText[451]="Unavailable For Legal Reasons",StatusText[500]="Internal Server Error",StatusText[501]="Not Implemented",StatusText[502]="Bad Gateway",StatusText[503]="Service Unavailable",StatusText[504]="Gateway Time-out",StatusText[505]="HTTP Version Not Supported",StatusText[506]="Variant Also Negotiates",StatusText[507]="Insufficient Storage",StatusText[511]="Network Authentication Required";class ResponseError extends Error{constructor(t,e=StatusCodes.INTERNAL_SERVER_ERROR){super(t),this.status=e,this.name=this.constructor.name}}class BadRequestError extends ResponseError{constructor(t="Bad Request"){super(t,StatusCodes.BAD_REQUEST)}}class ForbiddenError extends ResponseError{constructor(t="Forbidden"){super(t,StatusCodes.FORBIDDEN)}}class InternalServerError extends ResponseError{constructor(t="Internal server error"){super(t,StatusCodes.INTERNAL_SERVER_ERROR)}}class NotFoundError extends ResponseError{constructor(t="Not Found"){super(t,StatusCodes.NOT_FOUND)}}class UnauthorizedError extends ResponseError{constructor(t="Unauthorized"){super(t,StatusCodes.UNAUTHORIZED)}}class ValidationError extends ResponseError{constructor(t){super(t,StatusCodes.UNPROCESSABLE_ENTITY)}}class HttpResponse{static created(t,e,s){var r,o;const a=StatusCodes.CREATED,i={success:!0,status:a,data:e?{id:e}:{},meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return t.status(a).json(i),i}static noContent(t){t.status(StatusCodes.NO_CONTENT).end()}static ok(t,e,s){var r,o;const a=StatusCodes.OK,i={success:!0,status:a,data:e,meta:null!==(r=null==s?void 0:s.meta)&&void 0!==r?r:{},message:null!==(o=null==s?void 0:s.message)&&void 0!==o?o:null};return t.status(a).json(i),i}static error(t,e,s){var r,o;const{status:a,message:i}=this.normalizeError(s),n=null!==(r=null==StatusText?void 0:StatusText[a])&&void 0!==r?r:"Internal Server Error",u=this.getErrorCode(s),d=this.getErrorName(s),l=Object.assign(Object.assign(Object.assign(Object.assign({success:!1,status:a,statusText:n,message:i,path:null!==(o=t.originalUrl)&&void 0!==o?o:t.url},u?{code:u}:{}),d?{name:d}:{}),{timestamp:(new Date).toISOString()}),this.isDev()&&s instanceof Error&&s.stack?{stack:s.stack}:{});return e.status(a).json(l),l}static getErrorCode(t){return t&&r(t)&&o(t.code)?this.safeMessage(t.code):""}static getErrorName(t){return t instanceof ResponseError?t.constructor.name:this.isDev()?t instanceof Error?t.name||t.constructor.name:r(t)&&o(t.name)?t.name:typeof t:""}static isDev(){return"production"!==process.env.NODE_ENV}static normalizeError(t){let e=StatusCodes.INTERNAL_SERVER_ERROR,s=StatusText[500];if(t instanceof ResponseError)return e=this.safeStatus(t.status),s=this.safeMessage(t.message)||s,{status:e,message:s};if(t instanceof Error){const r=t;return a(r.statusCode)?e=this.safeStatus(r.statusCode):a(r.status)&&(e=this.safeStatus(r.status)),s=this.safeMessage(t.message)||s,{status:e,message:s}}if(o(t))return s=this.safeMessage(t)||s,{status:e,message:s};if(t&&r(t)){const r=t;return a(r.statusCode)?e=this.safeStatus(r.statusCode):a(r.status)&&(e=this.safeStatus(r.status)),o(r.message)&&(s=this.safeMessage(r.message)||s),{status:e,message:s}}return{status:e,message:s}}static safeStatus(t){if(!Number.isFinite(t))return StatusCodes.INTERNAL_SERVER_ERROR;const e=Math.trunc(t);return e<400||e>599?StatusCodes.INTERNAL_SERVER_ERROR:e}static safeMessage(t){if(!o(t))return"";const e=t.trim();return e.length>2e3?e.slice(0,2e3)+"...":e}}class Context{constructor(t,e,s,r,o){this.storage={},this.req=t,this.res=e,this.next=s,this.id=i(),this.app=r,this.controller=o}cache(t){const e=Object.assign({},t),s=[];e.private?s.push("private"):e.public&&s.push("public"),e.noStore&&(e.noCache=!0,s.push("no-store")),e.noCache&&(e.maxAge=0,delete e.sMaxAge,s.push("no-cache")),e.noTransform&&s.push("no-transform"),e.proxyRevalidate&&s.push("proxy-revalidate"),e.mustRevalidate?s.push("must-revalidate"):e.noCache||(a(e.staleIfError)&&s.push(`stale-if-error=${e.staleIfError}`),a(e.staleWhileRevalidate)&&s.push(`stale-while-revalidate=${e.staleWhileRevalidate}`)),a(e.maxAge)&&s.push(`max-age=${e.maxAge}`),a(e.sMaxAge)&&s.push(`s-maxage=${e.sMaxAge}`),s.length&&(this.res.setHeader("Cache-Control",s.join(",")),e.noCache&&n({"Surrogate-Control":"no-store",Pragma:"no-cache",ETag:"false",Expires:"0"},(t,e)=>this.res.setHeader(e,t)))}clearCookie(t,e){this.res.clearCookie(t,e)}close(t){this.isResponded()||this.res.json(null!=t?t:this.storage)}destroy(t){var e;t&&this.error(t),null===(e=this.res.socket)||void 0===e||e.destroy(t)}error(t){this.isResponded()||HttpResponse.error(this.req,this.res,t)}file(t){this.isResponded()||(this.status(StatusCodes.OK),this.res.sendFile(M(t)))}getBody(){var t,e;return null!==(e=null===(t=this.req)||void 0===t?void 0:t.body)&&void 0!==e?e:{}}getBodyValue(t){var e;return null===(e=this.req.body)||void 0===e?void 0:e[t]}getCookie(t){var e;return this.normalize(null===(e=this.req.cookies)||void 0===e?void 0:e[t])}getCookies(){var t,e;return u(null!==(e=null===(t=this.req)||void 0===t?void 0:t.cookies)&&void 0!==e?e:{},t=>this.normalize(t))}getFiles(){var t,e;return null!==(e=null===(t=this.req)||void 0===t?void 0:t.files)&&void 0!==e?e:{}}getFullUrl(){return`${this.getUrl()}${this.req.originalUrl}`}getHeader(t){var e;return this.normalize(null===(e=this.req.headers)||void 0===e?void 0:e[t])}getHeaders(){var t,e;return u(null!==(e=null===(t=this.req)||void 0===t?void 0:t.headers)&&void 0!==e?e:{},t=>this.normalize(t))}getIp(){return L(this.req)||"0.0.0.0"}getQuery(t){var e;return this.normalize(null===(e=this.req.query)||void 0===e?void 0:e[t])}getQueries(){var t,e;return u(null!==(e=null===(t=this.req)||void 0===t?void 0:t.query)&&void 0!==e?e:{},t=>this.normalize(t))}getParam(t){var e;const s=null===(e=this.req.params)||void 0===e?void 0:e[t];return d(s)?void 0:String(s)}getParams(){var t,e;return u(null!==(e=null===(t=this.req)||void 0===t?void 0:t.params)&&void 0!==e?e:{},t=>{if(!d(t)&&!l(t))return String(t)})}getUrl(){let t=this.getHeader("x-forwarded-proto")||this.req.protocol||"http";o(t)&&t.includes(",")&&(t=t.split(",")[0].trim());const e=this.getHeader("cf-visitor");if(e){const s=h(e);(null==s?void 0:s.scheme)&&(t=s.scheme)}return`${t}://${this.getHeader("host")}`}isResponded(){return this.res.headersSent||this.res.writableEnded}json(t){this.send(StatusCodes.OK,t)}normalize(t){if(!d(t)&&!l(t))return r(t)?JSON.stringify(t):String(t)}ok(t,e){this.isResponded()||HttpResponse.ok(this.res,t,e)}prepare(t,e){this.isResponded()||(this.status(t),this.storage=e)}redirect(t){this.isResponded()||this.res.redirect(t)}send(t,e){this.isResponded()||(this.status(t),204===t||304===t||d(e)?this.res.end():this.res.json(e))}setCookie(t,e,s){this.res.cookie(t,e,null!=s?s:{})}status(t){return d(t)||this.res.status(t),this.res.statusCode}success(t){this.send(StatusCodes.OK,{message:t})}}class Metadata{static extends(e){return t(Metadata.EXTENDS,e,[])}static middleware(e){return t(Metadata.MIDDLEWARE,e,[])}static parameters(e){return t(Metadata.PARAMETERS,e,[])}static path(e,s){return t(Metadata.PATH,e,s)}static routers(e){return t(Metadata.ROUTERS,e,[])}}Metadata.EXTENDS=Symbol("EXTENDS"),Metadata.MIDDLEWARE=Symbol("MIDDLEWARE"),Metadata.PARAMETERS=Symbol("PARAMETERS"),Metadata.PATH=Symbol("PATH"),Metadata.ROUTERS=Symbol("ROUTERS");class Application extends c{get controllers(){return[...this._controllers]}get instance(){return this._app}get router(){return this._globalRouter}get server(){return this._server}constructor(t,s){var o,a;super(),this._app=g(),this._boundServers=[],this._options={},this._baseRouter=O(),this._globalRouter=O(),this._controllers=[],this._controllers.push(...t.map(t=>p(t)?new t(...e(t)):t)),this._options=E({},{cross:!1,path:"/",port:3e3,session:{secret:"yoursecret",resave:!0,saveUninitialized:!1,cookie:{maxAge:864e5},proxy:Boolean(null==s?void 0:s.proxy)}},null!=s?s:{}),this._app.use(N(this._options.json)),this._app.disable("x-powered-by"),this._options.proxy&&this._app.set("trust proxy",this._options.proxy),this._app.use(x({extended:!0})),this._options.cross&&this._app.use(C(r(this._options.cross)?this._options.cross:{})),this._app.use(R(this._options.compression)),this._app.use(m(null===(o=this._options.cookie)||void 0===o?void 0:o.secret,this._options.cookie)),this._app.use(f(this._options.session)),this.init(),this._app.use(this._globalRouter);const i=(null===(a=this._options.path)||void 0===a?void 0:a.length)?this._options.path:"/";if(this._app.use(i,this._baseRouter),this._app.all(i+"/*path",(t,e)=>{this._options.redirect?e.redirect(this._options.redirect):HttpResponse.error(t,e,new NotFoundError("Endpoint Not Found"))}),this._options.public){const t=M(this._options.public);A(t)&&this._app.use(g.static(t)),this._app.get("*path",(e,s)=>{A(t)?s.sendFile(t+"/index.html"):this._options.notFound?s.redirect(this._options.notFound):HttpResponse.error(e,s,new NotFoundError("File not found"))})}else this._app.all("*path",(t,e)=>{this._options.redirect?e.redirect(this._options.redirect):HttpResponse.error(t,e,new NotFoundError("Endpoint not found"))});this._controllers.forEach(t=>{const e=O(),s=this._collectMiddlewares(t),o=Metadata.parameters(t);this._collectExtends(t).forEach(t=>{s.push(...this._collectMiddlewares(t)),o.push(...Metadata.parameters(t))}),Metadata.routers(t).forEach(a=>{const i=a.propertyKey.toString();if(S(t[i])){if(!S(e[a.method]))return this._logRouteNotFound(a.method);const n=this._buildMiddlewareChain(t,i,s,o);return e[a.method](a.path,...n,(e,s,a)=>F(this,void 0,void 0,function*(){const n=new Context(e,s,a,this,t),u=this._resolveArgs(n,this._filterParamsByKey(i,o)),d=yield t[i](...u);n.close(_(d)||r(d)?d:void 0)}))}this._logRouteNotFound(`${t.name}.${i}`)}),this._collectExtends(t).forEach(a=>{Metadata.routers(a).forEach(a=>{const i=a.propertyKey.toString();if(S(t[i])){if(!S(e[a.method]))return this._logRouteNotFound(a.method);const n=this._buildMiddlewareChain(t,i,s,o);return e[a.method](a.path,...n,(e,s,a)=>F(this,void 0,void 0,function*(){const n=new Context(e,s,a,this,t),u=this._resolveArgs(n,this._filterParamsByKey(i,o)),d=yield t[i](...u);n.close(_(d)||r(d)?d:void 0)}))}this._logRouteNotFound(`${t.constructor.name}.${i}`)})}),this._baseRouter.use(Metadata.path(t,"/"),e)}),this._app.use((t,e,s,r)=>{s.headersSent?r(t):HttpResponse.error(e,s,t)})}init(){}error(t,e){s.error(t)}log(t,e){s.info(t)}_resolveArgs(t,e,s){const r=[],o={ctx:t,key:"",app:this,argument:s};return e.forEach(t=>{r[t.parameterIndex]=t.callback(Object.assign(Object.assign({},o),{key:t.key}))}),r}_buildMiddlewareChain(t,e,s,o){return s.filter(t=>t.propertyKey==e).map(e=>{if(e.callback!=T){const s=this._filterParamsByKey(e.method,o);return(o,a,i)=>F(this,void 0,void 0,function*(){const n=new Context(o,a,i,this,t),u=S(e.argument)?e.argument(n):e.argument,d=yield e.callback.call(t,...this._resolveArgs(n,s,u));(_(d)||r(d))&&n.close(d)})}this._logRouteNotFound(e.method)}).filter(S)}_collectExtends(t){return Metadata.extends(t).reduce((t,e)=>(t.push(e,...this._collectExtends(e)),t),[]).filter((t,e,s)=>s.indexOf(t)===e)}_filterParamsByKey(t,e){return e.filter(e=>e.propertyKey==t)}_collectMiddlewares(t){return[...Metadata.middleware(t)].reverse()}_logRouteNotFound(t){this.error(new Error(`Router "${t}" not found`),"express")}_formatListeningMessage(t){return`Server listening on port ${t}`}listen(){return F(this,void 0,void 0,function*(){var t;const e=this._resolveMode(),s={http:this._startHttp,https:this._startHttps,hybrid:this._startHybrid,redirect:this._startHttpsWithRedirect};yield(null!==(t=s[e])&&void 0!==t?t:this._startHttp).call(this)})}close(){return F(this,void 0,void 0,function*(){yield Promise.all(this._boundServers.map(t=>new Promise((e,s)=>{t.close(t=>t?s(t):e())}))),this._boundServers.length=0,this._server=void 0})}_resolveMode(){return this._resolveTls()&&this._options.mode?this._options.mode:"http"}_resolveTls(){if(this._options.tls&&this._options.tls.key&&this._options.tls.cert)return this._options.tls}_bindServer(t,e,s){return new Promise((r,o)=>{const a=e=>{t.off("listening",i),o(e)},i=()=>{t.off("error",a),this.log(this._formatListeningMessage(e),"express"),r()};t.once("error",a),t.once("listening",i),t.listen(e,s)})}_startHttp(){return F(this,void 0,void 0,function*(){var t;const e=I.createServer(this._app);this._server=e,this._boundServers.push(e),yield this._bindServer(e,null!==(t=this._options.port)&&void 0!==t?t:3e3,this._options.host)})}_startHttps(){return F(this,void 0,void 0,function*(){var t;const e=y.createServer(this._resolveTls(),this._app);this._server=e,this._boundServers.push(e),yield this._bindServer(e,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host)})}_startHttpsWithRedirect(){return F(this,void 0,void 0,function*(){var t,e;const s=y.createServer(this._resolveTls(),this._app),r=I.createServer((t,e)=>{var s,r;const o=(null!==(s=t.headers.host)&&void 0!==s?s:"").split(":")[0];e.writeHead(StatusCodes.MOVED_PERMANENTLY,{Location:`https://${o}${null!==(r=t.url)&&void 0!==r?r:""}`}),e.end()});this._server=s,this._boundServers.push(s,r),yield Promise.all([this._bindServer(s,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host),this._bindServer(r,null!==(e=this._options.redirectPort)&&void 0!==e?e:80,this._options.host)])})}_startHybrid(){return F(this,void 0,void 0,function*(){var t;const e=I.createServer(this._app),s=y.createServer(this._resolveTls(),this._app),r=D.createServer(t=>{const r=setTimeout(()=>t.destroy(),5e3);t.once("data",o=>{clearTimeout(r),t.pause(),t.unshift(o),(22===o[0]?s:e).emit("connection",t),process.nextTick(()=>t.resume())}),t.once("error",()=>clearTimeout(r))});return this._server=s,this._boundServers.push(r,s,e),yield this._bindServer(r,null!==(t=this._options.port)&&void 0!==t?t:443,this._options.host),s})}}const H=t=>e=>{Metadata.path(e,(null==t?void 0:t.length)?t:"/")},k=t=>e=>{Metadata.extends(e).push(t)},w=t=>e=>(s,r,o)=>{Metadata.parameters(s).push({callback:t,key:e,propertyKey:r,parameterIndex:o})},q=w(({app:t})=>t),B=w(({argument:t})=>t),V=w(({ctx:t,key:e})=>e?t.getBodyValue(e):t.getBody()),G=w(({ctx:t,key:e})=>e?t.getCookie(e):t.getCookies()),K=w(({ctx:t})=>t),Q=w(({ctx:t})=>t.getFiles()),j=w(({ctx:t,key:e})=>e?t.getHeader(e):t.getHeaders()),$=w(({ctx:t,key:e})=>e?t.getParam(e):t.getParams()),X=w(({ctx:t,key:e})=>e?t.getQuery(e):t.getQueries()),Y=w(({ctx:t})=>{var e;return null===(e=t.req)||void 0===e?void 0:e.session}),z=(t,e)=>(s,r)=>{const o=i();K()(s,o,0),Metadata.middleware(s).push({method:o,argument:e,propertyKey:r,callback:t})},W=t=>(e,s,r)=>{z(e=>{e.cache(Object.assign({},t)),e.next()})(e,s,r)},Z={ALL:"all",GET:"get",POST:"post",PUT:"put",HEAD:"head",DELETE:"delete",OPTIONS:"options",PATCH:"patch"},J=t=>e=>(s,r)=>{Metadata.routers(s).push({method:t,path:(null==e?void 0:e.length)?e:"/",propertyKey:r})},tt=J(Z.ALL),et=J(Z.DELETE),st=J(Z.GET),rt=J(Z.HEAD),ot=J(Z.OPTIONS),at=J(Z.PATCH),it=J(Z.POST),nt=J(Z.PUT),ut=(t,e)=>(s,r)=>{let a=T;if(o(r)){const e=s;S(e[t])&&(a=e[t])}Metadata.middleware(s).push({method:t,argument:e,propertyKey:r,callback:a})},dt=(t,e=StatusCodes.BAD_REQUEST)=>{const s=new Error(t);return s.status=e,s},lt=t=>{var e;return(null===(e=t.split(".").pop())||void 0===e?void 0:e.toLowerCase())||"bin"},ht=(t,e)=>{var s;return null!==(s=t[e])&&void 0!==s?s:null},ct=(t,e)=>{const s=i()+"."+e;return A(P(t,s))?ct(t,e):s},pt=t=>{const e=E({},t),s=b({destination(t,s,r){var o;const a=ht(e,s.fieldname);r(null,null!==(o=null==a?void 0:a.path)&&void 0!==o?o:"./")},filename(t,s,r){var o;const a=ht(e,s.fieldname);r(null,ct(null!==(o=null==a?void 0:a.path)&&void 0!==o?o:"./",lt(s.originalname)))}}),r=Math.max(...Object.values(e).map(t=>{var e;return null!==(e=t.size)&&void 0!==e?e:0})),o=U({storage:s,fileFilter(t,s,r){var o;const a=ht(e,s.fieldname);return a?((t,e)=>!e.length||e.includes(lt(t.originalname))||e.includes(t.mimetype.toLowerCase()))(s,null!==(o=null==a?void 0:a.types)&&void 0!==o?o:[])?void r(null,!0):r(dt(`FILE TYPE NOT ALLOWED FOR "${s.fieldname}"`)):r(dt(`UPLOAD FIELD "${s.fieldname}" IS NOT CONFIGURED`))},limits:{fileSize:1024*r*1024}}).fields(Object.keys(e).map(t=>{var s,r;return{name:t,maxCount:null!==(r=null===(s=e[t])||void 0===s?void 0:s.count)&&void 0!==r?r:1}}));return(t,e,s)=>{z(t=>{o(t.req,t.res,e=>{if(!e)return t.next();t.error((t=>"LIMIT_FILE_SIZE"==t.code?(t.message=t.field?`FILE "${t.field}" EXCEEDS MAX SIZE`:"FILE EXCEEDS MAX SIZE",t.status=StatusCodes.PAYLOAD_TOO_LARGE,t):"LIMIT_UNEXPECTED_FILE"==t.code?(t.message=t.field?`FIELD "${t.field}" IS UNEXPECTED OR EXCEEDS MAX COUNT`:"UPLOAD FIELD IS UNEXPECTED OR EXCEEDS MAX COUNT",t.status=StatusCodes.BAD_REQUEST,t):t)(e))})})(t,e,s)}},Et=t=>{const e=v.object(S(t)?t(v):t).parse();return(t,s,r)=>{z(t=>{var s,r,o;const a=e.validate(null!==(r=null===(s=t.req)||void 0===s?void 0:s.body)&&void 0!==r?r:{});if(a.error)return t.error(new ValidationError(null!==(o=a.message)&&void 0!==o?o:a.error));t.req.body=a.value,t.next()})(t,s,r)}};export{tt as All,q as App,Application,B as Argument,BadRequestError,V as Body,W as Cache,Context,H as Controller,G as Cookies,K as Ctx,et as Delete,k as Extends,Q as Files,ForbiddenError,st as Get,rt as Head,j as Headers,HttpResponse,InternalServerError,Metadata,Z as Methods,ut as Middleware,NotFoundError,ot as Options,$ as Params,at as Patch,it as Post,nt as Put,X as Query,ResponseError,Y as Session,StatusCodes,StatusText,UnauthorizedError,pt as Upload,z as Use,Et as Validate,ValidationError,J as methodFactory,w as parameterFactory};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andrewcaires/express",
3
- "version": "2.2.1",
3
+ "version": "2.4.0",
4
4
  "description": "Decorators for express",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs.js",
@@ -21,7 +21,8 @@
21
21
  "scripts": {
22
22
  "dev": "tsx-dev --watch --clear ./src/dev.ts",
23
23
  "build": "npm run lint && rollup --bundleConfigAsCjs -c rollup.config.js",
24
- "lint": "eslint \"src/**/*.{ts,tsx,js,jsx}\" --max-warnings=0"
24
+ "lint": "eslint \"src/**/*.{ts,tsx,js,jsx}\" \"test/**/*.mjs\" --max-warnings=0",
25
+ "test": "npm run build && node --test \"test/**/*.test.mjs\""
25
26
  },
26
27
  "repository": {
27
28
  "type": "git",
@@ -37,9 +38,9 @@
37
38
  },
38
39
  "homepage": "https://github.com/andrewcaires/npm/tree/main/api#readme",
39
40
  "dependencies": {
40
- "@andrewcaires/decorator": "^1.1.1",
41
- "@andrewcaires/node": "^1.3.3",
42
- "@andrewcaires/utils.js": "^0.4.34",
41
+ "@andrewcaires/decorator": "^1.2.0",
42
+ "@andrewcaires/node": "^1.4.0",
43
+ "@andrewcaires/utils.js": "^0.5.0",
43
44
  "compression": "^1.8.1",
44
45
  "cookie-parser": "^1.4.7",
45
46
  "cors": "^2.8.6",
@@ -50,23 +51,24 @@
50
51
  },
51
52
  "devDependencies": {
52
53
  "@eslint/js": "^10.0.1",
53
- "@rollup/plugin-commonjs": "^29.0.2",
54
+ "@rollup/plugin-commonjs": "^29.0.3",
54
55
  "@rollup/plugin-terser": "^1.0.0",
55
56
  "@rollup/plugin-typescript": "^12.3.0",
56
- "@rollup/rollup-darwin-arm64": "^4.60.3",
57
+ "@rollup/rollup-darwin-arm64": "^4.60.4",
57
58
  "@types/compression": "^1.8.1",
58
59
  "@types/cookie-parser": "^1.4.10",
59
60
  "@types/cors": "^2.8.19",
60
61
  "@types/express": "^5.0.6",
61
62
  "@types/express-session": "^1.19.0",
62
63
  "@types/multer": "^2.1.0",
63
- "@types/node": "^25.6.0",
64
+ "@types/node": "^25.9.1",
64
65
  "@types/request-ip": "^0.0.41",
65
66
  "@types/swagger-ui-express": "^4.1.8",
66
- "eslint": "^10.3.0",
67
+ "eslint": "^10.4.1",
68
+ "globals": "^17.6.0",
67
69
  "rollup-plugin-dts": "^6.4.1",
68
70
  "swagger-ui-express": "^5.0.1",
69
71
  "tslib": "^2.8.1",
70
- "typescript-eslint": "^8.59.2"
72
+ "typescript-eslint": "^8.60.0"
71
73
  }
72
74
  }