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

[BUG] Injection doesn't work anymore as before 8.4.0 ($beforeInit not called, no Injection via symbol / token) #2953

Closed
KBroichhausen opened this issue Jan 9, 2025 · 6 comments
Assignees
Labels

Comments

@KBroichhausen
Copy link

Describe the bug

I'm currently using "^7.84.1" for all tsed packages and try to migrate to the newest verison 8.4.0.
Basically, I create abstract classes like IAService, create a Token in the same file via export const IAServiceToken: unique symbol = Symbol("IAService"); and implement that abstract class in AService class (usually in a different file then the abstract class definition). I use @Injectable({ provide: IAServiceToken }) decorator at the AService and in other classes I inject via @Inject(IAServiceToken) private readonly aService: IAService; which was working fine in before. Now, it just returns undefined.

Also my $beforeInit hook is not called anymore.

To Reproduce

The main branch is created with

kbro@wsl:~/tsed840$ node --version
v21.7.1
kbro@wsl:~/tsed840$ npm --version
10.5.0
kbro@wsl:~/tsed840$ tsed init
? Choose the target Framework: Express.js
? Choose the architecture for your project: Ts.ED
? Choose the convention file styling: Ts.ED
? Check the features needed for your project Database
? Choose a ORM manager TypeORM
? Which TypeORM you want to install? SQLite
? Choose the runtime: Node.js + SWC
? Choose the package manager: NPM
↓ Write RC files
↓ Write RC files
✔ Initialize package.json
✔ Install plugins
✔ Load plugins
✔ Install plugins dependencies
✔ Generate project files
✔ Generate TypeORM datasource file to 'datasources/SqliteDatasource.ts'
✔ Generate docker-compose configuration
✔ Install dependencies
✔ Generate barrels files

but I created a repro in the following branch: https://github.com/KBroichhausen/tsed840/tree/injection

Expected behavior

I expect the code to work as before. If I understand correctly according to https://tsed.dev/introduction/migrate-from-v7.html there is a new API to use the hooks in a different way but that is optional, no?
Even it changed it should still be called https://tsed.dev/hooks-v8.png

Code snippets

No response

Repository URL example

https://github.com/KBroichhausen/tsed840/tree/injection

OS

Linux / WSL

Node version

v21.7.1

Library version

8.4.0

Additional context

Regarding $beforeInit: I just need two steps. In $beforeInit I read some data from the filesystem in a service, in a different service I use $onInit and data from the first service to combine it with some other data to eventually have the data ready for the controller requests and responses. So, I must ensure that the first service has read the data from the file system before the other service access it in $onInit

@Romakita
Copy link
Collaborator

Romakita commented Jan 9, 2025

Hello @KBroichhausen

$beforeInit in v8 is called before injector.load(), his purpose is to init something because any services. But because services aren't available, this hook cannot be listen using injectable class.

Alternative: Use $onInit, $afterInit hooks instead. Or use functional API to handler $beforeInit

src/config/file.resolver.ts:

import {$on} from "@tsed/hooks";
import {configuration} from "@tsed/di";

$on("$beforeInit", () => {
  const config = configuration()
  
   const data = fs.readFileSync(config.get('path.to.file'))
   
   config.set("resolved_data", data);
});

in src/server.ts

import "./config/file.resolver.ts";


@Configuration({
   path: {
     to: {
        file: process.env.CONFIG_FILE
     }
   }
})
export class Server {
}

See you

@Romakita Romakita closed this as completed Jan 9, 2025
Copy link

github-actions bot commented Jan 9, 2025

🎉 Are you happy?

If you appreciated the support, know that it is free and is carried out on personal time ;)

A support, even a little bit makes a difference for me and continues to bring you answers!

github opencollective

@Romakita
Copy link
Collaborator

Romakita commented Jan 9, 2025

there is a new API to use the hooks in a different way but that is optional, no?

It's optional except for the $beforeInit. my apologize ;)

@KBroichhausen
Copy link
Author

Hi @Romakita,
thanks for your quick reply. I changed the repro to use $onInit and $afterInit but regarding the injection itself, there is still no instance available for IAService using the IAServiceToken. See https://github.com/KBroichhausen/tsed840/blob/injection/src/services/BService.ts

@KBroichhausen
Copy link
Author

I read the DI documentation again with fresh eyes and figured it is now called token and not provide anymore but because Injectable takes a Partial<ProviderOpts> it doesn't even give a type error.
That rename would have been a good information in the migration guide.

@Romakita
Copy link
Collaborator

Yes I missed that. Injectable decorator extra props that explain why you haven't error. I'll make a fix to add depreciation of provide prop and accept the provide prop in v8, to be removed in v9

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

No branches or pull requests

2 participants