Giter Club home page Giter Club logo

inversify-express-utils's Issues

Unit test

Hello,
Do You have any examples with unit test?

An in-range update of typescript is breaking the build 🚨

Version 2.3.3 of typescript just got published.

Branch Build failing 🚨
Dependency typescript
Current Version 2.3.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As typescript is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes TypeScript 2.3.3

This release include a set of bug fixes reported against TypeScript 2.3.2. For the complete list of fixed issues, check out the fixed issues query for TypeScript 2.3.3.

Download:

Commits

The new version differs by 84 commits.

There are 84 commits in total.

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Inversify-Express-Untils Cannot Build Multiple Servers

Expected Behavior

Having two different files both building InversifyExpressServers should result in no errors, even if they have different Containers.

Current Behavior

Having two different files both building InversifyExpressServers results in an error. The only case in which it does not result in an error is if they have Containers that are set up with identical Bindings (but the constructors can be different).

Steps to Reproduce (for bugs)

  1. Create a file that creates a container and add a binding. Then create a new InversifyExpressServer with that container, then build and export that server.
  2. Create a file that creates a container and adds no bindings. Then create a new InversifyExpressServer with that empty container (any different container should work), then build and export that server.
  3. Have your entry file import both servers, and try to run one. You will get the error: Error: No matching bindings found for serviceIdentifier: Symbol(<name of first unique binding>)

Context

My app exports multiple express servers and then each one is spun up as a serverless function with gcloud. Thus I want to build all of these at the same time even though I only run one at a time. Right now my workaround is to build each server independently.

Your Environment

  • Version used:
"inversify": "^5.0.1",
 "inversify-express-utils": "^6.3.2"
  • Environment name and version (e.g. Chrome 39, node.js 5.4): Node v12.17.0
  • Operating System and version (desktop or mobile): Ubuntu

Stack trace


Error: No matching bindings found for serviceIdentifier: Symbol(<binding name>)
    at _validateActiveBindingCount (root/node_modules/inversify/lib/planning/planner.js:62:23)
    at _getActiveBindings (root/node_modules/inversify/lib/planning/planner.js:48:5)
    at _createSubRequests (root/node_modules/inversify/lib/planning/planner.js:91:26)
    at root/node_modules/inversify/lib/planning/planner.js:115:17
    at Array.forEach (<anonymous>)
    at root/node_modules/inversify/lib/planning/planner.js:114:26
    at Array.forEach (<anonymous>)
    at _createSubRequests (root/node_modules/inversify/lib/planning/planner.js:94:20)
    at Object.plan (root/node_modules/inversify/lib/planning/planner.js:136:9)
    at root/node_modules/inversify/lib/container/container.js:317:37

Incomplete example

The example in the readme is incomplete because FooService.ts is missing.

Is it available somewhere?

How do I get access to http server?

In order to make it work with graphql subscriptions(or socket in general), I need access to the underlying http server(not Express application).

Is there a way to do that?

Handling singletons in creation of large plans

We have a complex application with a huge dependency graph. On startup, when all controllers are initialized at once using inversify-express-utils (container.getAll for controllers) we noticed that the startup takes upward of 5 minutes, with more than 6 GB of memory taken for the plan graph. Most of our bindings are Singleton.

Expected Behavior

container.getAll() should be fast

Current Behavior

container.getAll() takes > 5 minutes, a huge amount of RAM

Possible Solution

in planner.ts, we do not need to create childRequests for singleton Bindings multiple times, as there will be only instance of the object
Will be updating the issue with a pull request

Steps to Reproduce (for bugs)

  1. Application with a large dependency graph
  2. container.get() an object which is dependent on the full dependency graph

Context

Speeds up the startup of our application, and reduces startup memory utilization from ~6.5 GB to 600MB

Your Environment

node v11.13.0
inversify 5.0.1
inversify-express-utils 6.3.2
express 4.16.2

Private repo

Stack trace

None

Async/await not working on service

Hello! I'm calling a method with async/await on service layer and it isn't waiting for the final promise. Is this a normal behavior? Because with 'express' it seems like it doesn't.

I'm using:
"node":"10.13.0"
"inversify": "5.0.1"
"inversify-binding-decorators": "3.2.0"
"inversify-express-utils": "6.2.0"
"typescript": "3.0.3"

To test this behavior using the https://github.com/inversify/inversify-express-example:

  1. Modify the folder 'Basic' and add this snippet to UserService.
  2. run with 'ts-node Basic/bootstrap.ts'
  3. calling curl localhost:3000/user

Behavior: the 'get' ends and the console continue printing. How do I call an async/await method and then return the response to the client??

@injectable()
export class UserService {
  private async run(){
        await this.sleep(2000);
        console.log('Free');
        await this.sleep(2000);
        console.log('Free');
        await this.sleep(2000);
        console.log('Free');
    }
    private sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

  public getUsers(): IUser[] {
    this.run().then(()=>{
      console.log('finish');
    });

    return this.userStorage;
  }

Release of a new npm version with peer dependency Express 4.17.0+

Hello inversify-express-utils maintainers,

I'm writing to ask if it would be possible for you to release a new version of this package into NPM from commit 8766292 or later?

My team's project depends on a change added in Express 4.17.0, published in May 2019 which added SameSite=none support to res.cookie(). inversify-express-utils last NPM release was in Jan 2019, with Express 4.16. As noted above, you've already made the upgrade we are looking for in the master branch.

My team got around this issue by forking the repository and storing a build in version control. I would like to clean this up and go back to using a public version from NPM. The only way I see to do this is to get a new public NPM version released. Kindly also let me know if there is a cleaner workaround (for example I looked at the constructor of InversifyExpressServer() thinking it may accept an express module as an argument, but it doesn't appear to support that).

Thanks,
-Andrew

inversify-express-utils, support of express 4.17.1

I can see here that express was updated to 4.17.1 long time ago but when I install the latest [email protected] it contains dependency "express": "4.16.2"

Expected Behavior

[email protected] should use [email protected]

Current Behavior

[email protected] uses [email protected]

Possible Solution

Publish inversify-express-utils in proper way

Steps to Reproduce (for bugs)

install inversify-express-utils@latest, open its package.json, observe express version

Context

It is impossible to set response cookie with sameSite=none as this fix was provided only in express 4.17

Your Environment

  • Version used: 6.3.2
  • Environment name and version (e.g. Chrome 39, node.js 5.4): node 12.16.1
  • Operating System and version (desktop or mobile): macOS

inversify-socket-io-utils - new project submission

Hey guys, wasn't sure how else to get in contact.

I've put together a package for defining controllers and handlers using inversify for a socket.io server (https://socket.io/) based heavily on the inversify-express-utils package you have.

Setup looks like

const ioServer = new InversifySocketIOServer(
    inversifyContainer,
    httpServer,
    socketConfig
)

ioServer.build()

with an example controller looking like

@controller('/')
export class OnlineStatusController {
  constructor(
    @inject(SERVICE_TYPES.UserService) private userService: UserService
  ) {}

  @handler(CONNECT_USER)
  private async handleConnect(@socketId() socketId: string, @body() body: ConnectUserBody) {
    const {userId} = body

    // save socketId and userId somewhere

    this.userService.setUserOnline(userId)
  }

  @handler([SOCKET_IO_EVENT.DISCONNECT, DISCONNECT_USER])
  private async handleDisconnect(@socketId() socketId: string) {

    // retrieve userId given socketId
    
    this.userService.setUserOffline(userId)
  }
}

It currently supports:

  • auto discovery and binding of controllers using @controller(namespace?: string) class decorator
  • auto registration of event handlers using the @handler(events: string | string[]) method decorator
  • @socketId(): string @socket(): SocketIO.Socket @body(): any param decorators.
  • optional debug and logging feature
  • optional redis adapter feature

If this is a repo you guys would be interested in bringing in to your org, then I'd be happy to write up a proper readme and maintain it for you. I can zip up and send over the code for you to check out.

Let me know!

An in-range update of moq.ts is breaking the build 🚨

The devDependency moq.ts was updated from 2.8.4 to 2.8.5.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

moq.ts is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes for v2.8.5

2.8.5 (2019-02-23)

Bug Fixes

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Can not inject dependency in my CustomAuthProvider

i'm trying initialize AuthProvider as described on readme.

but i can not inject dependency in my CustomAuthProvider

If inject without constructor as described on readme, All injected dependencies are undefined.

@injectable()
export class CustomAuthProvider implements interfaces.AuthProvider {

    @inject(LoggerService.name) private readonly _loggerService!: LoggerService;
    @inject(DBService.name) private readonly _db!: DBService;
    @injectHttpContext private readonly _httpContext!: HttpContext;

    public async getUser(
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ): Promise<interfaces.Principal> {
        let user: Auth.User|null = null;
        try {
            user = await this._db.SelectUserInfo(req.session.user.email);
            // this._db is undefined
        } catch (error) {
            this._loggerService.logger.error(error);
            // this._loggerService is undefined too.
        }
        const principal = new Principal(user);
        return principal;
    }

}

And if inject a dependency to CustomAuthProvider on constructor of CustomAuthProvider, error occured on line of initializing InversifyExpressServer.

//customAuthProvider.ts

@injectable()
export class CustomAuthProvider implements interfaces.AuthProvider {

    constructor (
        @inject(LoggerService.name) private readonly _loggerService: LoggerService,
        @inject(DBService.name) private readonly _db: DBService,
        @injectHttpContext private readonly _httpContext: HttpContext
    ) {
    }

    public async getUser(
        req: express.Request,
        res: express.Response,
        next: express.NextFunction
    ): Promise<interfaces.Principal> {
        let user: Auth.User|null = null;
        try {
            user = await this._db.SelectUserInfo(req.session.user.email);
        } catch (error) {
            this._loggerService.logger.error(error);
        }
        const principal = new Principal(user);
        return principal;
    }

}

// app.ts
this.container = new Container();
this.container.bind(LoggerService.name).to(LoggerService);
this.container.bind(DBService.name).to(DBService).inSingletonScope();
this.container.bind(CustomAuthProvider.name).to(CustomAuthProvider).inSingletonScope();

this.server = new InversifyExpressServer(this.container, null, null, null, CustomAuthProvider); // error is occured on this line.
//Argument of type 'typeof CustomAuthProvider' is not assignable to parameter of type 'new () => AuthProvider'.
//Types of construct signatures are incompatible.
//Type 'new (_loggerService: LoggerService, _db: DBService, _httpContext: HttpContext) => CustomAuthProvider' is not assignable to type 'new () => AuthProvider'.ts(2345)

How can i use another dependencies on CustomAuthProvider?

Contextual injection not working with express utils decorators (inversify-express-utils)

I want to use contextual binding in my inversify-express application. I have a problem using contextual injection. Here is a minimal example. Suppose we have the following interfaces and classes

export type AuthenticationParams = {
    userId: string,
}

export interface NextInteractor<T>{
    execute(params: T): void;
}

@injectable()
export class AuthenticationInteractor<T extends AuthenticationParams>{
    constructor(@inject(TYPES.NEXT_INTERACTOR) private nextInteractor: NextInteractor<T>){}

    execute(params: T){
        console.log(`continuing as user with userId ${params.userId}`);
        this.nextInteractor.execute(params);
    }
}

And theses are some classes implementing NextInteractor

export type FirstParams = {
    userId: string
}

@injectable()
export class FirstInteractor implements NextInteractor<FirstParams>{
    execute(params: FirstParams) {
        console.log(`printing from first interactor ${params.userId}`)
    }
}


export type SecondParams = {
    userId: string,
    otherParam: string,
}

@injectable()
export class SecondInteractor implements NextInteractor<SecondParams>{
    execute(params: SecondParams) {
        console.log(`printing from second interactor, ${params.userId}, ${params.otherParam}`)
    }
}

And I use AuthenticationInteractor in the following file

@controller('/first')
export class FirstInput {
    constructor(@inject(TYPES.AUTHENTICATION_INTERACTOR) private authInteractor: AuthenticationInteractor<FirstParams>) {}

    @httpGet('/')
    get(@queryParam('userId') userId: string) {
        this.authInteractor.execute({ userId });
        return 'first url';
    }
}

@controller('/second')
export class SecondInput {
    constructor(@inject(TYPES.AUTHENTICATION_INTERACTOR) private authInteractor: AuthenticationInteractor<SecondParams>) { }

    @httpGet('/')
    get(@queryParam('userId') userId: string, @queryParam('otherParam') otherParam: string) {
        this.authInteractor.execute({ userId, otherParam });
        return 'second url';
    }
}

My intention is to call AuthenticationInteractor as the first step in every controller and only then continuing to the main logic. I hoped to achieve this with contextual binding as follows

container.bind<AuthenticationInteractor<any>>(TYPES.AUTHENTICATION_INTERACTOR).to(AuthenticationInteractor);

container.bind<NextInteractor<FirstParams>>(TYPES.NEXT_INTERACTOR).to(FirstInteractor).whenAnyAncestorIs(FirstInput);
container.bind<NextInteractor<SecondParams>>(TYPES.NEXT_INTERACTOR).to(SecondInteractor).whenAnyAncestorIs(SecondInput);

Expected Behavior

To bind nextInteractor to the correct one in each case

Current Behavior

inversify returns this error

Error: Ambiguous match found for serviceIdentifier: Symbol(NEXT_INTERACTOR)

Possible Solution

Steps to Reproduce (for bugs)

  1. clone https://gitlab.com/dadsetan.ali/inversify-express-contextual-binding-issue.git
  2. npm i
  3. npm start

Context

In my real project, I am trying to create a single Class for All authentication logic. Authentication, Authorization, token refresh, etc.

Your Environment

Stack trace

[inversify-express-utils] - No support for @controller on inevrfisy-binding-decorators?

Hey folks, I'm trying to implement here the inversify-binding-decorators together with the inversify-express-utils lib. Unfortunately, I wasn't didn't manage to make my @controller bindings to work properly. They do not seem to be recognized and I'm having to load all of them through a container.load

for example:

container.load(
  buildProviderModule(),
  assetControllerContainer,
  collectionControllerContainer,
  userControllerContainer,
  trackerControllerContainer,
  quoteControllerContainer,
  indicatorControllerContainer,
  portfolioControllerContainer,
  companyControllerContainer,
  orderControllerContainer,
  newsControllerContainer
);

Expected Behavior

I was expecting to add a @provide() on any of my controllers and it's automatically bound into my inversify container, so I don't need to load all of them manually with container.load (like above)

Current Behavior

Any @provide(CLASSNAMEHERE) on my controllers simply leads to a unbound controller (route throws a 404)

Possible Solution

A temporary workaround is binding modules manually and them loading them on container.load.

For example:

export const assetControllerContainer = new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind) => {
  bind<CreateAssetController>(CreateAssetController).toSelf();
  bind<FilterAssetController>(FilterAssetController).toSelf();
  bind<ReadAssetController>(ReadAssetController).toSelf();
});

then

container.load(
  buildProviderModule(),
  assetControllerContainer,
  ....
);

Latest inversify-express-utils is throwing build errors

Previous version of inversify-express-utils is throwing us build errors:
Previous version: 6.3.2
Latest version: 6.4.3 (latest)

tsc

node_modules/inversify-express-utils/node_modules/inversify/lib/annotation/injectable.d.ts:1:52 - error TS1005: ',' expected.

1 declare function injectable(): <T extends abstract new (...args: never) => unknown>(target: T) => T;
~~~
node_modules/inversify-express-utils/node_modules/inversify/lib/annotation/injectable.d.ts:1:83 - error TS1144: '{' or ';' expected.

1 declare function injectable(): <T extends abstract new (...args: never) => unknown>(target: T) => T;
~
node_modules/inversify-express-utils/node_modules/inversify/lib/annotation/injectable.d.ts:1:91 - error TS1005: ')' expected.

1 declare function injectable(): <T extends abstract new (...args: never) => unknown>(target: T) => T;
~
node_modules/inversify-express-utils/node_modules/inversify/lib/annotation/injectable.d.ts:1:94 - error TS1005: ';' expected.

1 declare function injectable(): <T extends abstract new (...args: never) => unknown>(target: T) => T;
~
node_modules/inversify-express-utils/node_modules/inversify/lib/annotation/injectable.d.ts:1:96 - error TS1128: Declaration or statement expected.

1 declare function injectable(): <T extends abstract new (...args: never) => unknown>(target: T) => T;

Can't build with the latest version, is there an update thats needed to something that I'm not aware of?

Can't set headers after they are sent.

Hi. I decided to try an example. But on the request I get 204 code and an error in the logs. How I understand it before my error handler, some other one works.

@controller('/foo')
class FooController implements interfaces.Controller {
    @httpGet('/')
    private index(req: express.Request, res: express.Response, next: express.NextFunction) {
        return next(new Error());
    }
}
const container = new Container();
const server = new InversifyExpressServer(container);
server.setErrorConfig((app) => {
    app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
        res.status(500).send('Something broke!');
    });
});
const app = server.build();
app.listen(3000);
Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:491:11)
    at ServerResponse.setHeader (_http_outgoing.js:498:3)
    at ServerResponse.header (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\response.js:767:10)
    at ServerResponse.contentType (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\response.js:595:15)
    at ServerResponse.send (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\response.js:145:14)
    at app.use (E:\workplace\wx-meteor-v2\src\index.ts:37:25)
    at Layer.handle_error (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\router\layer.js:71:5)
    at trim_prefix (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\router\index.js:315:13)
    at E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (E:\workplace\wx-meteor-v2\node_modules\inversify-express-utils\node_modules\express\lib\router\index.js:335:12)

inversify-express-utils: BaseHttpController's conflict should take an argument

This is a feature request for inversify-express-utils. Controllers that extend BaseHttpController have access to a this.conflict method, but this method does not take any arguments. Using this.json is an easy workaround, but I would still like this.conflict to take an optional generic argument.

Expected Behavior

I would expect this.conflict to take a generic argument that allows me to explain why the conflict occurred.

Current Behavior

I cannot provide an argument, so this.conflict just returns a 409 code.

Context

Let's say I get a POST /users request. It may conflict because (1) the provided username already exists or (2) the provided email already exists. The API should return which conflict actually occurred.

[Feature Request] Add request, response, next to BaseHttpController

For inversify-express-utils package.

To get the express req, res, next functions, we need to inject them into the action method with @request, @response, @next.

It would be much neater to have them on the BaseHttpController base class, so we can just do this.request, this.response, this.next.

Same thing for other related injectable things, like principal.

This would also avoid the "no-shadowed-variable" linting error when we have an argument like @next() next: express.NextFunction, which is really annoying.

An in-range update of tslint is breaking the build 🚨

Version 4.3.0 of tslint just got published.

Branch Build failing 🚨
Dependency tslint
Current Version 4.2.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As tslint is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details
Release Notes v4.3.0
  • Enabled additional rules in tslint:latest configuration (#1981)
  • [new-rule] space-before-function-paren (#1897)
  • [new-rule] typeof-compare (#1927)
  • [new-rule] import-spacing (#1935)
  • [new-rule] unified-signatures (#1944)
  • [new-fixer] object-literal-key-quotes (#1953)
  • [new-fixer] no-angle-bracket-type-assertion (#1979)
  • [bugfix] adjacent-overload-signature now handles static/computed function names (#1831)
  • [bugfix] file-header now handles files with only comments (#1913)
  • [bugfix] no-consecutive-blank-lines now allows blank lines in template strings (#1886)
  • [bugfix] object-literal-key-quotes no longer throws exception when using rest operator (#1916)
  • [bugfix] restrict-plus-operands no longer shows false positive in ternary operation (#1925)
  • [bugfix] prefer-for-of now handles nested for loops with reused iterator (#1926)
  • [bugfix] Exit gracefully when tsconfig.json passed as --project argument doens't have files (#1933)
  • [bugfix] object-literal-key-quotes now handles shorthand and spread properties (#1945)
  • [bugfix] arrow-parens Allow binding patterns ([x, y]) => ... and ({x, y}) => ... to have parens (#1958)
  • [bugfix] semicolon fixer now handles comma separator in interfaces and indicates failure when commas are using in interfaces (#1856)
  • [bugfix] only-arrow-functions option allow-named-functions now allows function declarations (#1961)
  • [bugfix] prefer-for-of no longer shows false positive when array is in parentheses (#1986)
  • [bugfix] prefer-const now works for TypeScript versions < 2.1.0 (#1989)
  • [enhancement] member-access narrow location of error (#1964)

Thanks to our contributors!

  • Andrii Dieiev
  • @andy-ms
  • Andy Hanson
  • Josh Goldberg
  • Klaus Meinhardt
  • Linda_pp
  • Mohsen Azimi
  • Victor Grigoriu
  • Yuichi Nukiyama
  • cameron-mcateer
Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

[inversify-express-utils] allow to inject dependencies into middleware constructor

Expected Behavior

Middlewares should be created by http request scoped container.
Since by default they are not singleton it does make sense to create them using per-request container, which allows to inject request-scoped dependencies in constructor instead calling this.httpContext.container.get(...). For middlewares that are registered as singleton nothing will be changed, so it should add any performance difference.

Current Behavior

Right now middlewares in express-utils are always created using root container which does not allow to inject request scoped variables in constructor.

Possible Solution

PR: https://github.com/inversify/inversify-express-utils/pull/325/files

Steps to Reproduce (for bugs)

    it("Should allow constructor injections from http-scope in middlewares", async () => {

        const TYPES = {
            Value: Symbol.for("Value"),
            ReadValue: Symbol.for("ReadValue"),
            HttpContextValueSetMiddleware: Symbol.for("HttpContextValueSetMiddleware"),
            HttpContextValueReadMiddleware: Symbol.for("HttpContextValueReadMiddleware"),
        };

        class HttpContextValueSetMiddleware extends BaseMiddleware {
            public handler(
                req: express.Request,
                res: express.Response,
                next: express.NextFunction
            ) {
                this.bind<string>(TYPES.Value).toConstantValue(`MyValue`);
                next();
            }
        }

        class HttpContextValueReadMiddleware extends BaseMiddleware {
            constructor(@inject(TYPES.Value) private value: string) {
                super();
            }

            public handler(
                req: express.Request,
                res: express.Response,
                next: express.NextFunction
            ) {
                this.bind(TYPES.ReadValue).toConstantValue(`${this.value} is read`);
                next();
            }
        }

        @controller("/http-scope-middleware-injection-test")
        class MiddlewareInjectionTestController extends BaseHttpController {

            constructor(@inject(TYPES.ReadValue) @optional() private value: string) {
                super();
            }

            @httpGet(
                "/get-value",
                TYPES.HttpContextValueSetMiddleware,
                TYPES.HttpContextValueReadMiddleware
            )
            public getValue() {
                return this.value;
            }
        }

        const container = new Container();

        container.bind<HttpContextValueReadMiddleware>(TYPES.HttpContextValueReadMiddleware)
            .to(HttpContextValueReadMiddleware);
        container.bind<HttpContextValueSetMiddleware>(TYPES.HttpContextValueSetMiddleware)
            .to(HttpContextValueSetMiddleware);
        container.bind<string>(TYPES.Value).toConstantValue("DefaultValue");
        const app = new InversifyExpressServer(container).build();

        await supertest(app)
            .get("/http-scope-middleware-injection-test/get-value")
            .expect(200, "MyValue is read");
    });

Context

In application I would like to register some values in middlewares at the beginning of the request and then use classes that abstract HTTP specific things for the consumers. Allowing to inject dependencies into middleware constructor simplifies unit testing of those middlewares.

Your Environment

NodeJS 12.x.x
Windows

Registering controllers to modules instead of global scope

I've noticed that controllers are automatically registered to global scope when they are imported. A cleaner way would be to allow each package to export its controllers and then load them into the required container, as with any other dependencies.

Is there a way to do so now or would I need to implement this feature?

Error trying to instantiate controller in a test (Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext))

I'm trying to write a unit test for a controller that has an injected service at the constructor, that's why (unlike the docs where controllers are instantiated with the new keyword in a test) i need to instantiate it with the container.
The controller extends the BaseHttpController from inversify-express-utils I'm failing trying to do:

Test

import { expect } from "chai"
import { container } from '../../src/container/inversify.config'
import { HealthControllerV1 } from "../../src/controllers/v1/HealthControllerV1"
import { results } from "inversify-express-utils"

describe("ExampleController", () => {
    let controller: HealthControllerV1

    beforeEach(() => {
        controller = container.get<HealthControllerV1>(HealthControllerV1)
    })

    describe("Health", () => {
        it("should return 200 status with Json response", async () => {
            const response = controller.health()
            expect(response).to.be.an.instanceof(results.JsonResult)
        })
    })
})  

Container:

import { Container } from "inversify";
import { HealthControllerV1 } from "../controllers/v1/HealthControllerV1";
import { GoalsService, IGoalsService } from "../services/GoalsService";

const container = new Container()

container.bind<HealthControllerV1>(HealthControllerV1).toSelf()
container.bind<IGoalsService>('goalsService').to(GoalsService)

export { container }

Controller:

import 'reflect-metadata'
import { BaseHttpController, controller, httpGet, interfaces, results } from 'inversify-express-utils'
import { inject } from 'inversify'
import { IGoalsService } from '../../services/GoalsService'

@controller('/v1/health')
export class HealthControllerV1 extends BaseHttpController implements interfaces.Controller {

    constructor(@inject('goalsService') private goalsService: IGoalsService){super()}
    
    @httpGet('/')
    health(): results.JsonResult {
        this.goalsService.log('111')
        return this.json({ msg: 'OK' })
    }
}   

Error:

HealthControllerV1
    Health
      1) "before each" hook for "should return 200 status with Json response"


  0 passing (8ms)
  1 failing

  1) HealthControllerV1
       "before each" hook for "should return 200 status with Json response":
     Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)

My Environment

"inversify": "^5.0.5",
"inversify-express-utils": "^6.3.2",
"node": "12.20.0"
"chai": "^4.3.0",
"express": "^4.17.1",
"mocha": "^8.3.0",
"reflect-metadata": "^0.1.13",

Stack trace

 Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)
      at _validateActiveBindingCount (node_modules/inversify/lib/planning/planner.js:63:23)
      at _getActiveBindings (node_modules/inversify/lib/planning/planner.js:49:5)
      at _createSubRequests (node_modules/inversify/lib/planning/planner.js:92:26)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/planning/planner.js:116:17
      at Array.forEach (<anonymous>)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/planning/planner.js:115:26
      at Array.forEach (<anonymous>)
      at _createSubRequests (node_modules/inversify/lib/planning/planner.js:95:20)
      at Object.plan (node_modules/inversify/lib/planning/planner.js:137:9)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/container/container.js:319:37
      at Container._get (node_modules/inversify/lib/container/container.js:312:44)
      at Container.get (node_modules/inversify/lib/container/container.js:232:21)
      at Context.<anonymous> (test/unit/health.test.ts:10:32)
      at processImmediate (internal/timers.js:461:21)

thanks a lot

An in-range update of http-status-codes is breaking the build 🚨

The dependency http-status-codes was updated from 1.3.0 to 1.3.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

http-status-codes is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Commits

The new version differs by 3 commits.

  • 338aa64 Bump patch version and publish
  • 3821d30 Added the http statuses as an enum. (#29)
  • 427963b Update README.md

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Create a Principal decorator

I'm trying to create a new decorator to make it simpler to obtain the Principal information, something like:

@httpGet("/")
public async getByUser(@principal() principal: Principal): Promise<any> {
    console.log(principal.details);
}

However, I'm having a hard time understanding the code and can't seem to find out where is it that the parameters values are altered by the @controller and/or @httpMethod decorators.

Would someone please point me to the right direction so I can do PR?

EDIT
As it turns out, I found previous commit #161 that shows some changes in server.ts, which I believe might be the right place to do the changes I'm proposing.

handlerFactory calls res.send() breaking controllers wanting to stream to the response body

i've got this endpoint:

  @httpGet('/')
  async getTheThing(@response() res: Response) {
    try {
      const fileStream = await this.storage.getTheThing();
      res.setHeader('content-type', 'application/tar');
      fileStream.pipe(res);
    } catch (error) {
      return res.status(404).send(error);
    }

This fails with:

Error: write after end
    at write_ (_http_outgoing.js:631:15)
    at ServerResponse.write (_http_outgoing.js:626:10)
    at IncomingMessage.ondata (_stream_readable.js:646:20)
    at IncomingMessage.emit (events.js:160:13)
    at IncomingMessage.Readable.read (_stream_readable.js:482:10)
    at flow (_stream_readable.js:853:34)
    at resume_ (_stream_readable.js:835:3)
    at process._tickCallback (internal/process/next_tick.js:152:19)

Because the handlerFactory at this line calls res.send() which closes the request while the stream is still being written.

I think if a controller uses @response() to get access to the response object then the handler factory shouldn't touch the response object at all.

Injection scope for controller (singleton instead request scoped)

This issue might be a duplicate of inversify/InversifyJS#781 which one is already closed. However, I want to consider some nuances for further project improvement.

I started experimenting with those utils and stuck exactly with injection scope of controllers.
This doesn't fit to my tasks and approaches on my servers, so I would like to discuss this moment once again.

I have some questions.

  1. Is it possible to add some parameter to InversifyExpressServer? To be able to use controller as a singleton, but by default leave request scoped.

  2. Is it possible to bind controller more explicit? I mean not just import the file, but import particular controller and inject it into container (with defined scope parameters).

Something like:

@controller('api')
class ApiController implements interfaces.Controller {}

const container = new Container();
const server = new InversifyExpressServer(container);
// or maybe allow here some factory to provide custom controllers
server.bindController(ApiController).in*Scope();

I see that we have BaseHttpController class, so, in case of singleton scope, we might restrict to add controller which extends/implements HttpBaseController, and maybe amend it:

server.bindControllerSingletonScope(ApiController);
server.bindControllerRequestScope(ApiController); // might raise type error since it is not extending BaseHttpRequest class

Just before trying to make a fork and consideration of further using of those utils, want to consider my view with author's perspective :)

An in-range update of moq.ts is breaking the build 🚨

Version 2.7.0 of moq.ts was just published.

Branch Build failing 🚨
Dependency moq.ts
Current Version 2.6.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

moq.ts is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ❌ continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

JsonContent doesn't send correctly

When using the BaseHttpController helper method BaseHttpController.json(...) the resulting express call coerces the json object to a string.

This causes problems when using express middleware that validates JSON responses (in this case using openapi-validator-middleware) as the data is no-longer a JSON object.

The root cause of this appears to be that the use of HttpContent enforcing all data as a string in readAsStringAsync().

My understanding is that this is to avoid potential issues where numeric data is interpreted by express as a status code, but I believe that it would be safe to all string | object types to be sent.

I will open a PR shortly with a proposed fix for this.

Inversify Express controller inheritance fail if inheriting from more than 1 controller

After updating to the latest version of inversify and inversify-express-utils, I can't have controller inheritance working with more than 1 base controller, like BaseController -> BaseApiController -> PostController, URLs from BaseController return 404

Expected Behavior

You should be able to extend as many base controllers as you like and keep the methods and URLs

Current Behavior

The base endpoints return 404

Steps to Reproduce (for bugs)

  1. Get a fresh copy of https://github.com/inversify/inversify-express-utils and npm install
  2. Replace controller_inheritance.test.ts with my gist https://gist.github.com/aescarcha/341db9d36ccff444b8ad1368e2c834c2
  3. npm run test should fail

Context

I like splitting my controllers and using a lot of inheritances, like having a base controller, then a query controller, and a paginateable controller all inheriting the previous one

Your Environment

I'm on macOS Catalina, node 14.5.0, using all other deps from inversify-express-utils

An in-range update of inversify is breaking the build 🚨

Version 3.2.0 of inversify just got published.

Branch Build failing 🚨
Dependency inversify
Current Version 3.1.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As inversify is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Release Notes 3.2.0

The main addition of this release is a feature that allows library and framework authors to customize the annotation phase.

Commits

@remojansen Refactoring binding (#491) … 0ee96ad
@greenkeeper Update gulp-mocha to version 4.0.0 (#494) … 83491d0
@remojansen Bug fix 496 (#502) … a92d13f
@Dirrk Update bluebird to 3.5.0 (#503) f5354a9
@Dirrk Updated sinon to 2.0.0 (#511) 96230ab
@remojansen Support for metadata middleware (#507) … d60a053

Commits

The new version differs by 7 commits .

  • 1410309 Update package.json
  • d60a053 Support for metadata middleware (#507)
  • 96230ab Updated sinon to 2.0.0 (#511)
  • f5354a9 update bluebird to 3.5.0 (#503)
  • a92d13f Bug fix 496 (#502)
  • 83491d0 chore(package): update gulp-mocha to version 4.0.0 (#494)
  • 0ee96ad Refactoring binding (#491)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of tslint is breaking the build 🚨

Version 5.3.0 of tslint just got published.

Branch Build failing 🚨
Dependency tslint
Current Version 5.2.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As tslint is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ

Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details

Release Notes v5.3.0

This change may require a change to tslint.json

πŸŽ‰ Notable features & enhancements

Thanks to our contributors!

  • Andy Hanson
  • Klaus Meinhardt
  • Martin Probst
  • Filipe Silva
  • walkerburgin
  • RenΓ© Scheibe
Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

[inversify-express-utils] AuthProvider Unhandled Promise Rejection

When an error is thrown/a promise is rejected in the AuthProvider's getUser() method, the server does not ever respond to the client and an Unhandled Promise Rejection Warning is written on the console.

Expected Behavior

The error handler of the express server should be called and respond appropriately to the client.

Current Behavior

No server response is sent and the client is left waiting when an error occurs in the AuthProvider.

Steps to Reproduce

  async getUser(req: Request, res: Response, next: NextFunction): Promise<interfaces.Principal> {
    console.log('[AUTH_MD]');
    const token = req.header('X-CONTROL-CENTER-AUTH') as string;
    if (!token) return new Principal(undefined);
    try {
      const user = await this.userService
        .validate(token);
      if (!user) {
        return Promise.reject(new Unauthorized({ path: '' }));
      }
      return new Principal(user);
    } catch (e) {
      return Promise.reject(new InternalServerError({ path: '' }));
    }
  }
}

Note: The Unauthorized and InternalServerError classes are from express-openapi-validator but the result is the same using even a simple Error.

Your Environment

  • Version used: inversify: ^5.0.1 && inversify-express-utils: ^6.3.2
  • Environment name and version (e.g. Chrome 39, node.js 5.4): Docker-node:alpine3.12

Per-controller error handling

I couldn't find a way to handle all errors in a controller in one handler.
For example:

@controller('/user')
export default class UserController implements interfaces.Controller {
    @httpGet('/')
    private async get(@request() req: Request, @response() res: Response) {
        throw new Error('This should be handled in the error handler')
    }

    @httpPost('/')
    private async create(@request() req: Request, @response() res: Response) {
        throw new Error('This should be handled in the error handler')
    }
    
    // Ideally I would want something like
    private errorHandler(err, req, res) {
        // handle any error in the controller here
    }
}

It's not working also in application level,

app.use(function (err, req, res, next) {
  // errors in the controllers doesn't trigger this
});

Is there an elegant way to handle errors without repeating the code? (If I want for example to log any error to some logger)?

[inversify-express-utils]: Auth provider cannot rely on server-level middleware

Using the inversify-express-utils you can create an express application and configure:

  • an auth(orization) provider
  • server level middleware

When building the server application the http context is created before the server level middleware is registered.

Here's an excerpt of the build method.

this._app.all("*", (
  req: express.Request,
  res: express.Response,
  next: express.NextFunction
) => {
  (async () => {
      const httpContext = await _self._createHttpContext(req, res, next);
      ...
      next();
  })();
});

// register server-level middleware before anything else
if (this._configFn) {
  this._configFn.apply(undefined, [this._app]);
}

For each request the http context will be created, which in turn creates the principal. After that the server level middleware configured via the setConfig is executed.

 private async _createHttpContext(
   req: express.Request,
   res: express.Response,
   next: express.NextFunction
) {
  const principal = await this._getCurrentUser(req, res, next);
  ...
}

Let's assume a use case where you have to read data from the body in the authorization provider. If you configure the body-parser via the setConfig it's too late. This is called after the principal is created. When trying to compose a principal (getCurrentUser) you cannot ready the body as it is undefined at the time. The same probably applies for cookies as this requires the cookie-parser middleware to be setup.

[Inversify Express Utils] Controller is Reconstructed on Every Request

import {controller, interfaces, httpGet} from 'inversify-express-utils'

@controller('')
export class IndexController implements interfaces.Controller {
  constructor() {
    console.log('Construct index controller')
  }

  @httpGet('/hello')
  index() {
    return 'hello\n'
  }
}

In my logs I can see, that every time I make a get request to /hello, the IndexController constructor is called.
Is this behaviour expected?

Is there a way to call the constructor only once on, application start?
I have controllers that run logic in the constructor. And it would be really redundant to rerun this code on every single incoming request.

Passing additional data to Middleware

I am using

  • inversify 5.0.1
  • inversify-binding-decorators 4.0.0
  • inversify-express-utils 6.3.2
    The code I am working on can be seen at this Link
    The Problem
    I need to pass an additional parameter to the Middleware so that it will act as a factory,
    Example, I need to pass a role onto a middleware so that the system can check if the user has permission to access the API
    an example we need to create a middleware as follows
@provide("roles")
class RoleValidator extends BaseMiddleware {
    role(role){
        return handler(req: Request, res: Response, next: NextFunction) {
            if(req.user.role === role){
                next();
            } else {
                res.end();
            }
        }
    }
}

And the middleware is called by a controller

@controller('/test')
class UserController extends BaseHttpController {
    @httpPost('/', "roles=>'currentRole'")
    private test(
        @requestParam('param') param: string,
        res: Response,
        next: NextFunction
      ){
        //code
      }
}

How can this be achieved, this is a common scenario, that has to be used. Is it that, the feature is not supported.

[inversify-express-utils] Nesting controllers and maintaining route context

I'm just getting into InversifyJS and I'm struggling to get my head around the concept of Express controllers.

Usually I write my code in such a fashion that the routing chain is executed step by step and the context of the request is incrementally stored inside the request object.

routes/index.ts

router.use("/users", usersRouter);

export default router;

routes/users/index.ts

router.use("/:userId", (req, res, next) => {
  let user = fakedSyncGetUserById(req.params.userId);

  req.context.user = user;

  next();
});

router.use("/:userId/posts", postsRouter);

router.get("/:userId", (req, res) => {
  res.status(200).json(req.context.user);
});

routes/users/posts.ts

router.get("/", (req, res) => {
  let posts = fakeGetPostsByUser(req.context.user);

  res.status(200).json(posts);
});

This way I don't have to validate the user in the controller that manages the posts. How would this be achieved in a sane way using InversifyJS?

Another issue I couldn't find the answer to is the order routes are executed, such /users/me being executed before /users/:userId is evaluated.

integrating inversify-express-utils with inversify-socket-utils

There is a nice utils library called inversify-socket-utils which nicely wraps a lot of socketio logic and gives the ability to use decorators in controllers to handle event emits in controllers.

The problem is both of the libraries:
Socket utils:
https://github.com/alxshelepenok/inversify-socket-utils
Express utils:
https://github.com/inversify/inversify-express-utils

Return Inversify server so I haven't figured out how could I integrate these two to run on the same server and port.

Has anyone successfully done it by any chance?

An in-range update of express is breaking the build 🚨

Version 4.14.1 of express just got published.

Branch Build failing 🚨
Dependency express
Current Version 4.14.0
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

As express is a direct dependency of this project this is very likely breaking your project right now. If other packages depend on you it’s very likely also breaking them.
I recommend you give this issue a very high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Release Notes 4.14.1
Commits

The new version differs by 24 commits .

There are 24 commits in total. See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.