UNPKG

inversify-express-utils

Version:

Some utilities for the development of express applications with Inversify

17 lines (14 loc) 14.4 kB
import"reflect-metadata";import t,{Router as e}from"express";import{injectable as n,inject as r,decorate as o}from"inversify";import{StatusCodes as s}from"http-status-codes"; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */function a(t,e,n,r){var o,s=arguments.length,a=s<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,n,r);else for(var c=t.length-1;c>=0;c--)(o=t[c])&&(a=(s<3?o(a):s>3?o(e,n,a):o(e,n))||a);return s>3&&a&&Object.defineProperty(e,n,a),a}let c=class{httpContext;bind(t){return this.httpContext.container.bind(t)}};c=a([n()],c);const i={AuthProvider:Symbol.for("AuthProvider"),Controller:Symbol.for("Controller"),HttpContext:Symbol.for("HttpContext")},u={controller:"inversify-express-utils:controller",controllerMethod:"inversify-express-utils:controller-method",controllerParameter:"inversify-express-utils:controller-parameter",httpContext:"inversify-express-utils:httpcontext",middleware:"inversify-express-utils:middleware"};var l,d;!function(t){t[t.REQUEST=0]="REQUEST",t[t.RESPONSE=1]="RESPONSE",t[t.PARAMS=2]="PARAMS",t[t.QUERY=3]="QUERY",t[t.BODY=4]="BODY",t[t.HEADERS=5]="HEADERS",t[t.COOKIES=6]="COOKIES",t[t.NEXT=7]="NEXT",t[t.PRINCIPAL=8]="PRINCIPAL"}(l||(l={})),function(t){t.all="all",t.connect="connect",t.delete="delete",t.get="get",t.head="head",t.options="options",t.patch="patch",t.post="post",t.propfind="propfind",t.put="put",t.trace="trace"}(d||(d={}));const h=t=>`Two controllers cannot have the same name: ${t}`,f="No controllers have been found! Please ensure that you have register at least one Controller.",p="/";class R{_content;_headers={};_statusCode;constructor(t=s.OK){this.statusCode=t}get content(){return this._content}get headers(){return this._headers}get statusCode(){return this._statusCode}set content(t){this._content=t}set headers(t){this._headers=t}set statusCode(t){if(t<0||t>999)throw new Error(`${t.toString()} is not a valid status code`);this._statusCode=t}}function y(t,e){if(t.isBound(i.Controller))return t.getAll(i.Controller);if(e)throw new Error(f);return[]}function g(){return(Reflect.getMetadata(u.controller,Reflect)??[]).map((t=>t.target))}function m(t,e){return(Reflect.getMetadata(u.middleware,t)??{})[e]??[]}function C(t){return Reflect.getMetadata(u.controller,t)}function _(t){const e=Reflect.getOwnMetadata(u.controllerMethod,t),n=Reflect.getMetadata(u.controllerMethod,Reflect.getPrototypeOf(t));return void 0!==n&&void 0!==e?e.concat(n):void 0!==n?n:e}function w(t){const e=Reflect.getOwnMetadata(u.controllerParameter,t),n=Reflect.getMetadata(u.controllerParameter,Reflect.getPrototypeOf(t));return void 0!==n&&void 0!==e?{...e,...n}:void 0!==n?n:e}function E(){Reflect.defineMetadata(u.controller,[],Reflect)}function P(t){return null!=t&&"function"==typeof t.executeAsync}function x(t,e,n){return Reflect.hasMetadata(t,e)?Reflect.getMetadata(t,e):(Reflect.defineMetadata(t,n,e),n)}class M{_router;_container;_app;_configFn;_errorConfigFn;_routingConfig;_authProvider;_forceControllers;constructor(n,r,o,s,a,c=!0){this._container=n,this._forceControllers=c,this._router=r||e(),this._routingConfig=o||{rootPath:"/"},this._app=s||t(),a&&(this._authProvider=a,n.bind(i.AuthProvider).to(this._authProvider))}setConfig(t){return this._configFn=t,this}setErrorConfig(t){return this._errorConfigFn=t,this}build(){return this._app.all("*",((t,e,n)=>{(async()=>{const r=await this._createHttpContext(t,e,n);Reflect.defineMetadata(u.httpContext,r,t),n()})()})),this._configFn&&this._configFn.apply(void 0,[this._app]),this.registerControllers(),this._errorConfigFn&&this._errorConfigFn.apply(void 0,[this._app]),this._app}registerControllers(){this._container.bind(i.HttpContext).toConstantValue({});g().forEach((t=>{const{name:e}=t;if(this._container.isBoundNamed(i.Controller,e))throw new Error(h(e));this._container.bind(i.Controller).to(t).whenTargetNamed(e)}));y(this._container,this._forceControllers).forEach((t=>{const e=C(t.constructor),n=_(t.constructor),r=w(t.constructor);if(e&&n){const t=this.resolveMiddlewere(...e.middleware),o={[d.head]:-1};n.sort(((t,e)=>(o[t.method]??0)-(o[e.method]??0))).forEach((n=>{let o=[];r&&(o=r[n.key]||[]);const s=this.handlerFactory(e.target.name,n.key,o),a=this.resolveMiddlewere(...n.middleware),c=this.mergePaths(e.path,n.path);this._router[n.method](c,...t,...a,s)}))}})),this._app.use(this._routingConfig.rootPath,this._router)}mergePaths(...t){return t.map((t=>{let e=t.startsWith("/")||t.startsWith(".")?t:`/${t}`;return t.endsWith("/")&&(e=e.substring(0,e.length-1)),e})).join("")}resolveMiddlewere(...t){return t.map((t=>{if(!this._container.isBound(t))return t;const e=this._container.get(t);return e instanceof c?(e,n,r)=>{const o=this._container.get(t);return o.httpContext=this._getHttpContext(e),o.handler(e,n,r)}:e}))}copyHeadersTo(t,e){for(const n of Object.keys(t)){const r=t[n];e.append(n,"number"==typeof r?r.toString():r)}}async handleHttpResponseMessage(t,e){this.copyHeadersTo(t.headers,e),void 0!==t.content?(this.copyHeadersTo(t.content.headers,e),e.status(t.statusCode).send(await t.content.readAsync())):e.sendStatus(t.statusCode)}handlerFactory(t,e,n){return async(r,o,s)=>{try{const a=this.extractParameters(r,o,s,n),c=this._getHttpContext(r);c.container.bind(i.HttpContext).toConstantValue(c);const u=await c.container.getNamed(i.Controller,t)[e](...a);if(u instanceof R)await this.handleHttpResponseMessage(u,o);else if(P(u)){const t=await u.executeAsync();await this.handleHttpResponseMessage(t,o)}else u instanceof Function?u():o.headersSent||void 0!==u&&o.send(u)}catch(t){s(t)}}}_getHttpContext(t){return Reflect.getMetadata(u.httpContext,t)}async _createHttpContext(t,e,n){const r=await this._getCurrentUser(t,e,n);return{container:this._container.createChild(),request:t,response:e,user:r}}async _getCurrentUser(t,e,n){if(void 0!==this._authProvider){return this._container.get(i.AuthProvider).getUser(t,e,n)}return Promise.resolve({details:null,isAuthenticated:async()=>!1,isInRole:async t=>!1,isResourceOwner:async t=>!1})}extractParameters(t,e,n,r){const o=[];return r&&r.length?(r.forEach((({type:r,index:s,parameterName:a,injectRoot:c})=>{switch(r){case l.REQUEST:o[s]=t;break;case l.NEXT:o[s]=n;break;case l.PARAMS:o[s]=this.getParam(t,"params",c,a);break;case l.QUERY:o[s]=this.getParam(t,"query",c,a);break;case l.BODY:o[s]=t.body;break;case l.HEADERS:o[s]=this.getParam(t,"headers",c,a);break;case l.COOKIES:o[s]=this.getParam(t,"cookies",c,a);break;case l.PRINCIPAL:o[s]=this._getPrincipal(t);break;default:o[s]=e}})),o.push(t,e,n),o):[t,e,n]}getParam(t,e,n,r){const o="headers"===e?"symbol"==typeof r?r.toString():r?.toLowerCase():r,s=t[e];return n?s:s&&o?s[o]:void 0}_getPrincipal(t){return this._getHttpContext(t).user}}const A=r(i.HttpContext);function S(t,e,...n){const r=x(u.middleware,t,{});e in r||(r[e]=[]),r[e]?.push(...n),Reflect.defineMetadata(u.middleware,r,t)}function O(...t){return function(e,n){void 0!==n?S(e,n,...t):function(t){return"function"==typeof t&&void 0!==t.prototype}(e)&&S(e.constructor,e.name,...t)}}function v(t,...e){return r=>{const s=m(r.constructor,r.name),a={middleware:e.concat(s),path:t,target:r};o(n(),r),Reflect.defineMetadata(u.controller,a,r);const c=[a,...Reflect.getMetadata(u.controller,Reflect)??[]];Reflect.defineMetadata(u.controller,c,Reflect)}}function b(t,...e){return D(d.all,t,...e)}function N(t,...e){return D(d.get,t,...e)}function k(t,...e){return D(d.post,t,...e)}function T(t,...e){return D(d.put,t,...e)}function H(t,...e){return D(d.patch,t,...e)}function I(t,...e){return D(d.head,t,...e)}function U(t,...e){return D(d.delete,t,...e)}function j(t,...e){return D(d.options,t,...e)}function D(t,e,...n){return(r,o)=>{const s=m(r,o),a={key:o,method:t,middleware:n.concat(s),path:e,target:r};let c=[];Reflect.hasOwnMetadata(u.controllerMethod,r.constructor)?c=Reflect.getOwnMetadata(u.controllerMethod,r.constructor):Reflect.defineMetadata(u.controllerMethod,c,r.constructor),c.push(a)}}const F=X(l.REQUEST),B=X(l.RESPONSE),Q=X(l.PARAMS),Y=X(l.QUERY),q=X(l.BODY),K=X(l.HEADERS),L=X(l.COOKIES),$=X(l.NEXT),V=X(l.PRINCIPAL);function X(t){return e=>W(t,e)}function W(t,e){return(n,r,o)=>{let s={},a=[];const c={index:o,injectRoot:void 0===e,parameterName:e,type:t};Reflect.hasOwnMetadata(u.controllerParameter,n.constructor)?(s=Reflect.getOwnMetadata(u.controllerParameter,n.constructor),s[r]&&(a=s[r]||[]),a.unshift(c)):a.unshift(c),s[r]=a,Reflect.defineMetadata(u.controllerParameter,s,n.constructor)}}var z=Object.freeze({__proto__:null});class J{_headers={};get headers(){return this._headers}}class G extends J{content;constructor(t){super(),this.content=t,this.headers["content-type"]="text/plain"}async readAsync(){return this.content}}class Z{message;constructor(t){this.message=t}async executeAsync(){const t=new R(s.BAD_REQUEST);return t.content=new G(this.message),t}}class tt{async executeAsync(){return new R(s.BAD_REQUEST)}}class et{async executeAsync(){return new R(s.CONFLICT)}}class nt{location;content;constructor(t,e){this.location=t,this.content=e}async executeAsync(){const t=new R(s.CREATED);return t.content=new G(JSON.stringify(this.content)),t.headers.location=this.location.toString(),t}}class rt{error;constructor(t){this.error=t}async executeAsync(){const t=new R(s.INTERNAL_SERVER_ERROR);return t.content=new G(this.error.toString()),t}}class ot{async executeAsync(){return new R(s.INTERNAL_SERVER_ERROR)}}class st extends J{content;constructor(t){super(),this.content=t,this.headers["content-type"]="application/json"}async readAsync(){return this.content}}class at{json;statusCode;constructor(t,e){this.json=t,this.statusCode=e}async executeAsync(){const t=new R(this.statusCode);return t.content=new st(this.json),t}}class ct{async executeAsync(){return new R(s.NOT_FOUND)}}class it{content;constructor(t){this.content=t}async executeAsync(){const t=new R(s.OK);return"string"==typeof this.content?t.content=new G(this.content):t.content=new st(this.content),t}}class ut{async executeAsync(){return new R(s.OK)}}class lt{location;constructor(t){this.location=t}async executeAsync(){const t=new R(s.MOVED_TEMPORARILY);return t.headers.location=this.location.toString(),t}}class dt{message;constructor(t){this.message=t}async executeAsync(){return this.message}}class ht{statusCode;constructor(t){this.statusCode=t}async executeAsync(){return new R(this.statusCode)}}class ft extends J{content;constructor(t,e){super(),this.content=t,this.headers["content-type"]=e}async readAsync(){return this.content}}class pt{readableStream;contentType;statusCode;constructor(t,e,n){this.readableStream=t,this.contentType=e,this.statusCode=n}async executeAsync(){const t=new R(this.statusCode);return t.content=new ft(this.readableStream,this.contentType),t}}var Rt=Object.freeze({__proto__:null,BadRequestErrorMessageResult:Z,BadRequestResult:tt,ConflictResult:et,CreatedNegotiatedContentResult:nt,ExceptionResult:rt,InternalServerErrorResult:ot,JsonResult:at,NotFoundResult:ct,OkNegotiatedContentResult:it,OkResult:ut,RedirectResult:lt,ResponseMessageResult:dt,StatusCodeResult:ht,StreamResult:pt});let yt=class{httpContext;created(t,e){return new nt(t,e)}conflict(){return new et}ok(t){return void 0===t?new ut:new it(t)}badRequest(t){return void 0===t?new tt:new Z(t)}internalServerError(t){return t?new rt(t):new ot}notFound(){return new ct}redirect(t){return new lt(t)}responseMessage(t){return new dt(t)}statusCode(t){return new ht(t)}json(t,e=s.OK){return new at(t,e)}stream(t,e,n=s.OK){return new pt(t,e,n)}};function gt(t){return mt(t).map((t=>({controller:t.controllerMetadata.target.name,endpoints:t.methodMetadata.map((e=>{const n=e.method.toUpperCase(),r=t.controllerMetadata.path,o=e.path,s=t.parameterMetadata;let a;if(void 0!==s){(s[e.key]||void 0)&&(a=(t.parameterMetadata[e.key]||[]).map((t=>{let e="";switch(t.type){case l.RESPONSE:e="@response";break;case l.REQUEST:e="@request";break;case l.NEXT:e="@next";break;case l.PARAMS:e="@requestParam";break;case l.QUERY:e="queryParam";break;case l.BODY:e="@requestBody";break;case l.HEADERS:e="@requestHeaders";break;case l.COOKIES:e="@cookies";break;case l.PRINCIPAL:e="@principal"}return`${e} ${t.parameterName}`})))}const c={route:`${n} ${r}${o}`};return a&&(c.args=a),c}))})))}function mt(t){return y(t,!0).map((t=>{const{constructor:e}=t;return{controllerMetadata:C(e),methodMetadata:_(e),parameterMetadata:w(e)}}))}a([A,function(t,e){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(t,e)}("design:type",Object)],yt.prototype,"httpContext",void 0),yt=a([n()],yt);export{yt as BaseHttpController,c as BaseMiddleware,p as DEFAULT_ROUTING_ROOT_PATH,h as DUPLICATED_CONTROLLER_NAME,d as HTTP_VERBS_ENUM,J as HttpContent,R as HttpResponseMessage,M as InversifyExpressServer,st as JsonContent,u as METADATA_KEY,f as NO_CONTROLLERS_FOUND,l as PARAMETER_TYPE,G as StringContent,i as TYPE,b as all,E as cleanUpMetadata,v as controller,L as cookies,C as getControllerMetadata,_ as getControllerMethodMetadata,w as getControllerParameterMetadata,y as getControllersFromContainer,g as getControllersFromMetadata,m as getMiddlewareMetadata,x as getOrCreateMetadata,mt as getRawMetadata,gt as getRouteInfo,U as httpDelete,N as httpGet,I as httpHead,D as httpMethod,j as httpOptions,H as httpPatch,k as httpPost,T as httpPut,A as injectHttpContext,P as instanceOfIhttpActionResult,z as interfaces,$ as next,W as params,V as principal,Y as queryParam,F as request,q as requestBody,K as requestHeaders,Q as requestParam,B as response,Rt as results,O as withMiddleware}; //# sourceMappingURL=index.js.map