inversify / inversify-express-utils Goto Github PK
View Code? Open in Web Editor NEWSome utilities for the development of Express application with InversifyJS
License: MIT License
Some utilities for the development of Express application with InversifyJS
License: MIT License
The commit d09dfbb adding ESLint to the project (accidentally?) removed the export { interfaces }
from src/interfaces.ts
.
It looks like all packages using inversify-express-utils
that have an import { interfaces } from 'inversify-express-utils'
will break because of this.
Hello,
Do You have any examples with unit test?
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 πͺ
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:
The new version differs by 84 commits.
e2cc27b
Update LKG
6b64fee
Add name property to Declaration temporarily
367e072
Merge pull request #15941 from RyanCavanaugh/release-2.3
e01ea0e
Merge branch 'release-2.3' of https://github.com/Microsoft/TypeScript into release-2.3
930e4c5
Add flag to allow local plugin loading
4dc00a2
Update LKG
1788478
Merge branch 'release-2.3' of https://github.com/Microsoft/TypeScript into release-2.3
507dc76
Fix issue with throw in async delegator.
2dd4c8a
Update LKG
9d2656f
Fix #15463: use intersection types to emulate spread in generic react components (#15851)
a0db9ad
Fix issue with throw in async delegator.
8534a5a
Update LKG
6976dda
Address PR
dbae5d2
Add more tests and update baselines
5eb9fd0
getApparentType of the propsType
There are 84 commits in total.
See the full diff
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄
Having two different files both building InversifyExpressServer
s should result in no errors, even if they have different Containers.
Having two different files both building InversifyExpressServer
s 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).
InversifyExpressServer
with that container, then build and export that server.InversifyExpressServer
with that empty container (any different container should work), then build and export that server.Error: No matching bindings found for serviceIdentifier: Symbol(<name of first unique binding>)
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.
"inversify": "^5.0.1",
"inversify-express-utils": "^6.3.2"
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
The example in the readme is incomplete because FooService.ts
is missing.
Is it available somewhere?
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?
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.
container.getAll() should be fast
container.getAll() takes > 5 minutes, a huge amount of RAM
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
Speeds up the startup of our application, and reduces startup memory utilization from ~6.5 GB to 600MB
node v11.13.0
inversify 5.0.1
inversify-express-utils 6.3.2
express 4.16.2
Private repo
None
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:
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;
}
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
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"
[email protected] should use [email protected]
[email protected] uses [email protected]
Publish inversify-express-utils in proper way
install inversify-express-utils@latest, open its package.json, observe express version
It is impossible to set response cookie with sameSite=none as this fix was provided only in express 4.17
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:
@controller(namespace?: string)
class decorator@handler(events: string | string[])
method decorator@socketId(): string
@socket(): SocketIO.Socket
@body(): any
param decorators.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!
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.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
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?
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);
To bind nextInteractor to the correct one in each case
inversify returns this error
Error: Ambiguous match found for serviceIdentifier: Symbol(NEXT_INTERACTOR)
In my real project, I am trying to create a single Class for All authentication logic. Authentication, Authorization, token refresh, etc.
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
);
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)
Any @provide(CLASSNAMEHERE) on my controllers simply leads to a unbound controller (route throws a 404)
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,
....
);
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?
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)
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.
I would expect this.conflict
to take a generic argument that allows me to explain why the conflict occurred.
I cannot provide an argument, so this.conflict
just returns a 409
code.
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.
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.
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 πͺ
tslint:latest
configuration (#1981)space-before-function-paren
(#1897)typeof-compare
(#1927)import-spacing
(#1935)unified-signatures
(#1944)object-literal-key-quotes
(#1953)no-angle-bracket-type-assertion
(#1979)adjacent-overload-signature
now handles static/computed function names (#1831)file-header
now handles files with only comments (#1913)no-consecutive-blank-lines
now allows blank lines in template strings (#1886)object-literal-key-quotes
no longer throws exception when using rest operator (#1916)restrict-plus-operands
no longer shows false positive in ternary operation (#1925)prefer-for-of
now handles nested for
loops with reused iterator (#1926)tsconfig.json
passed as --project
argument doens't have files (#1933)object-literal-key-quotes
now handles shorthand and spread properties (#1945)arrow-parens
Allow binding patterns ([x, y]) => ...
and ({x, y}) => ...
to have parens (#1958)semicolon
fixer now handles comma separator in interfaces and indicates failure when commas are using in interfaces (#1856)only-arrow-functions
option allow-named-functions
now allows function declarations (#1961)prefer-for-of
no longer shows false positive when array is in parentheses (#1986)prefer-const
now works for TypeScript versions < 2.1.0 (#1989)member-access
narrow location of error (#1964)Thanks to our contributors!
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄
since i am using serverless architecture i want to use only DI and pass container with other event
There are a number of breaking changes in the TypeScript update/modernisation
This was published as v6.4.5
, which I have deprecated in response.
From the README I have encountered:
interfaces.Controller
has changedBut there may be more
@PodaruDragos let's catch up and see what has changed here before releasing, it would be good to minimise changes
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.
Right now middlewares in express-utils are always created using root container which does not allow to inject request scoped variables in constructor.
PR: https://github.com/inversify/inversify-express-utils/pull/325/files
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");
});
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.
NodeJS 12.x.x
Windows
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?
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:
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)
})
})
})
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 }
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' })
}
}
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)
"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",
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
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.
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
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
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.
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.
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.
Is it possible to add some parameter to InversifyExpressServer
? To be able to use controller as a singleton, but by default leave request scoped.
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 :)
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.
There is a collection of frequently asked questions. If those donβt help, you can always ask the humans behind Greenkeeper.
Your Greenkeeper Bot π΄
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.
Is there a way to allow case insensitive parameters? e.g @QueryParam
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
You should be able to extend as many base controllers as you like and keep the methods and URLs
The base endpoints return 404
npm install
controller_inheritance.test.ts
with my gist https://gist.github.com/aescarcha/341db9d36ccff444b8ad1368e2c834c2npm run test
should failI 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
I'm on macOS Catalina, node 14.5.0, using all other deps from inversify-express-utils
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 πͺ
The main addition of this release is a feature that allows library and framework authors to customize the annotation phase.
@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
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.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄
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 πͺ
prefer-switch
: Change default min-cases
to 3. (#2669)outputAbsolutePaths
option (#2667)prefer-object-spread
(#2624)encoding
(#2368)prefer-conditional-expression
(#2363)indent
support indent size (#2723)object-literal-sort-keys
adds ignore-case
(#2592)quotemark
: Add avoid-template
option (#2766)await-promise
: What's considered a "Promise" is now configurable. (#2661)indent
(#2723)typedef-whitespace
(#2718)variable-name
(#2672)typedef
: Use name or parameters for error location (#2460)object-literal-sort-keys
: check shorthand properties (#2592)space-before-function-paren
: Handle get
/set
accessor (#2700)typedef-whitespace
added checks for arrow function, call and construct signature (#2718)no-object-literal-type-assertion
: Allow cast to any
(#2671)-p
option handles directories (#2756)tsconfig.json
is found next to tslint.json
(#2769)return-undefined
: Treat a return type void | undefined
same as void
(#2731)no-unnecessary-initializer
: Handle BindingElement
anywhere, not just in a VariableDeclaration
. (#2707)jsdoc-format
: correctly handle alignment in files with BOM (#2619)jsdoc-format
: don't treat empty comments (/**/
) as jsdoc (#2619)typedef-whitespace
don't warn for leading whitespace if token is preceded by line break (#2718)jsdoc-format
: fixed error position if line ends with \r\n
(#2619)prefer-switch
: add missing checks for some expressions (#2686)prefer-template
: Allow "a" + "b" + "c"
. (#2741)prefer-const
: fix false positive with variable declared outside of for-of or for-in (#2760)--project
: fix file matching with relative path to tsconfig.json
(#2688)no-default-export
: correctly handle export default abstract class {...}
(#2630)no-mergeable-namespace
: display correct line in error message (#2656)object-literal-sort-keys
: handle object spread correctly (#2592)await-promise
: Consider types derived from a Promise in union types too. (#2661)no-unsafe-any
: Fix bug where number literal in type position was flagged as an unsafe any
. (#2712)Lint.Utils.objectify
(#2764)Thanks to our contributors!
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄
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.
The error handler of the express server should be called and respond appropriately to the client.
No server response is sent and the client is left waiting when an error occurs in the AuthProvider.
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.
PLEASE DO NOT REPORT THE ISSUE HERE!
PLEASE USE THE INVERSIFYJS REPO INSTEAD YOU CAN FIND THE REPO AT:
https://github.com/inversify/InversifyJS/issues
YOU CAN ALSO FIND US ON GITTER AT:
https://gitter.im/inversify/InversifyJS
THANKS!
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)?
Using the inversify-express-utils
you can create an express application and configure:
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.
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.
I am using
@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.
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.
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?
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 πͺ
err.headers
is not an objectThe new version differs by 24 commits .
0437c51
4.14.1
1f70b76
build: [email protected]
0b39fa2
build: [email protected]
0d6c64f
deps: type-is@~1.6.14
c238aca
examples: remove big-view example
6b506d8
examples: fix mvc example to ignore files in controllers dir
dc48f27
deps: update example dependencies
8e14e06
deps: serve-static@~1.11.2
572657e
deps: [email protected]
cfae537
deps: [email protected]
a3d6353
deps: proxy-addr@~1.1.3
a2e323a
build: [email protected]
e73913b
build: [email protected]
ddc93aa
deps: [email protected]
6723b44
tests: add test for res.sendFile "cacheContol" option
There are 24 commits in total. See the full diff.
There is a collection of frequently asked questions and of course you may always ask my humans.
Your Greenkeeper Bot π΄
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.