Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incompatibility with recent versions of inversifyJS #1717

Closed
3 of 4 tasks
helios-ag opened this issue Nov 10, 2024 · 4 comments · Fixed by #1718
Closed
3 of 4 tasks

Incompatibility with recent versions of inversifyJS #1717

helios-ag opened this issue Nov 10, 2024 · 4 comments · Fixed by #1718

Comments

@helios-ag
Copy link
Contributor

Sorting

  • I'm submitting a ...

    • bug report
    • feature request
    • support request
  • I confirm that I

    • used the search to make sure that a similar issue hasn't already been submit

Expected Behavior

If you define container configuration according to current docs

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };
and point to it in the tsoa.json as iocModule,

Container expected to be compiled

Current Behavior

If you define container configuration according to current docs

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };

and point to it in the tsoa.json as iocModule

And during build we getting error

tsoa-generated/routes.ts:622:23 - error TS2322: Type 'Container | IocContainer' is not assignable to type 'IocContainer'.
  Type 'Container' is not assignable to type 'IocContainer'.
    Types of property 'get' are incompatible.
      Type '<T>(serviceIdentifier: ServiceIdentifier<T>) => T' is not assignable to type '{ <T>(controller: { prototype: T; }): T; <T>(controller: { prototype: T; }): Promise<T>; }'.
        Types of parameters 'serviceIdentifier' and 'controller' are incompatible.
          Type '{ prototype: any; }' is not assignable to type 'ServiceIdentifier<any>'.
            Type '{ prototype: any; }' is missing the following properties from type 'Function': apply, call, bind, length, and 4 more.
                 const container: IocContainer = typeof ioc === 'function' ? (ioc as IocContainerFactory)(request) : ioc;

Possible Solution

This happens due to recent changes in the InversifyJS

Signature of export type ServiceIdentifier<T = unknown> = (string | symbol | Newable<T> | Abstract<T>);
has been changed to

https://github.com/inversify/InversifyJS/blob/master/src/interfaces/interfaces.ts#L66

that borrowed from here:

https://github.com/inversify/monorepo/blob/main/packages/container/libraries/common/src/services/models/ServiceIdentifier.ts#L3C8-L8C14

The simplest solution without doing changes to libraries itself to make wrapper, in TSyringe way:

# Previously if you have, for example:  
decorate(injectable(), Controller);

ioc.bind<IServer>(Types.IServer).to(Server);
ioc.load(buildProviderModule());
export { ioc };
and point to it in the tsoa.json as iocModule,

Now you need to wrap it up:

import { IocContainer } from '@tsoa/runtime';
import { ioc } from './ioc';

export const iocContainer: IocContainer = {
   get: <T>(controller: { prototype: T }): T => {
      return ioc.resolve<T>(controller as never);
   },
};

And point to it in tsoa.json

Another way to fix behavior is to update signature of container definition here
https://github.com/lukeautry/tsoa/blob/master/packages/runtime/src/interfaces/iocModule.ts#L2

Context (Environment)

Version of the library: 6.5.0
Version of NodeJS: 22.11

  • Confirm you were using yarn not npm: [ ]

Detailed Description

Breaking change?

Copy link

Hello there helios-ag 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

@VincentClair
Copy link
Contributor

Hello,

I have used another workaround. Cast is a bad practice, but it makes the deal for a temporary fix :

const createIocContainer = (): IocContainer & Container => {
    const iocContainer = new Container({ autoBindInjectable: true, defaultScope: 'Singleton' });
    iocContainer.load(buildProviderModule());
    return iocContainer as IocContainer & Container;
};

@helios-ag
Copy link
Contributor Author

@VincentClair thanks for sharing, but any current solution will require kind of typecast

@helios-ag
Copy link
Contributor Author

@WoH any suggestions? I mean IoCModule was introduced as transition from inversify-express-utils in #803 by @alxwrd
Can we narrow possible types for container get?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants