How to inject a repository with typedi and typeorm - typeorm

Im using typeorm, typedi and typegraphql (not nest.js) and am trying to inject my typeorm repository into the the service but its not working
Container.set("UserRepository", dataSource.getRepository(UserEntity));
#Service()
export class UserService {
constructor(private userRepository: Repository<UserEntity>) {}
async createUser({
name,
email,
password,
}: Input {...}
The error im getting is
Service with \"MaybeConstructable<Repository>\" identifier was not found in the container. Register it before usage via explicitly calling the \"Container.set\" function or using the \"#Service()\" decorator."
even though I can print out the repository with Container.get(UserRepository)
Does anyone know what im doing wrong?

try adding this annotation to your injected repo
import { InjectRepository } from 'typeorm-typedi-extensions';
constructor(#InjectRepository() private userRepository: Repository<UserEntity>) {}
you may need to install the typeorm-typedi-extensions package
and make sure you have useContainer(Container); in your bootstrapping process to register the typeorm container which should be the container from the above package

This was the solution:
Add the container to the buildSchema function that apollo gives us:
await dataSource.initialize();
const schema = await buildSchema({
resolvers,
emitSchemaFile: true,
container: Container,
});
Set the repositories on bootstrapping the app:
export const UserRepository = dataSource.getRepository(UserEntity).extend({});
Container.set("UserRepository", UserRepository);
Use it in your service:
export class UserService {
constructor(
#Inject("UserRepository") private userRepository: Repository<UserEntity>
) {}
}

Related

Object gotten from the NestFactory has all the internal dependencies as undefined - NestJS

I get an object from NestFactory and then I call a function. There is another class injected inside service class. All the dependencies inside the service are not accessible.
const FASTIFY = new FastifyAdapter();
const app = await NestFactory.create<NestFastifyApplication>(AppModule, FASTIFY, {
bufferLogs: true, // do wait till LoggerService is available
});
const service = app.get<ServiceClass>(ServiceClass); // service object is obtained from container
console.log(service.anotherRepository); // repository and injected objects are undefined.
Service object is obtained from container and then I can see the code goes into service class but all the dependencies defined inside the service class are undefined.
I have set the scope of all of them to DEFAULT.
#Injectable({ scope: Scope.DEFAULT })
Even if the classes are created with scope: Scope.REQUEST. You can still get the objects using
const serviceClass = await app.resolve<ServiceClass>(ServiceClass);
This has been fixed in the newer versions.

NestJS inject service in guard

I am pretty new to developing REST APIs using the NestJS framework (started using it last week).
For Authorization purposes I want to implement a CanActivate Guard to my app. This guard simply looks for an authorization header to extract the jwt. Furthermore the user needs to be fetched via a service to get its role and check for the required permission. Additionally there is a #Permission decorator, which is used on protected routes, that takes in a permission string.
This decorator file looks like this:
export const PERMISSION_KEY = "requiredPermission"
export const Permission = (permission: string) => {
return SetMetadata(PERMISSION_KEY, permission);
}
But I am experiencing strange behaviour: Only injecting the Reflector (so I can look up the required permission from the route) is working fine. When now trying to inject a service, let's say AuthService, the constructor of the AuthenticationGuard isn't even called, so the service results in undefined. Event the reflector instance is undefined, though it worked before. Here is how it looks in my authentication.guard.ts:
#Injectable()
export class AuthenticationGuard implements CanActivate {
constructor(
private reflector: Reflector,
private authService: AuthService
) {}
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
// ... do some things to extract jwt from header ...
console.log(this.authService); // Results in undefined
// This line does not work because reflector also is undefined.
const requiredPermission = this.reflector.get<string>(PERMISSION_KEY, context.getHandler());
console.log(requiredPermission);
}
}
This guard is imported as a provider in a feature module called AuthModule:
#Module({
imports: [
JwtModule.register({
secret: "EXTREMELY_SECRET"
})
],
providers: [
AuthService,
{
provide: APP_GUARD,
useClass: AuthenticationGuard
}
],
controllers: [ AuthController ],
exports: [
AuthService
]
})
export class AuthModule {}
Now when removing the service from dependency injection and make a console.log, I can see that it gets instantiated as the first dependency of the whole app. Does this maybe cause the service to fail injecting? How would I possibly change fix that?
Or does injecting services not work for guards in general? I think this is not the problem.
Maybe someone can help me with this problem and give me some advice on to fix this issue.
Thank you very kindly in advance for your support!

Dynamically inject repository in generic services with nestjs

I am building an authorization service for my nestjs app.
For every protected resource on my app (Media, Game, ...), I have a *RoleEntity associated (MediaRoleEntity, GameRoleEntity, ...) that defines what a user can do with a specific resource. Each one of this *RoleEntity implements RoleEntityInterface:
export interface RoleEntityInterface<T extends ResourceEntity> {
resource: T;
user: UserEntity;
role: string;
}
Each protected entity (MediaEntity, GameEntity, ...) extends ResourceEntity.
Now I want to build a generic provider RoleService, responsible for database interaction:
#Injectable()
export class RoleService<T extends ResourceEntity> {
readonly roleRepository: Repository<RoleEntityInterface<T>>;
async read(roleDto: Partial<RoleDto<T>>): Promise<RoleEntityInterface<T>> {
return this.roleRepository.findOne({
where: { ...roleDto },
});
}
async create(roleDto: RoleDto<T> | RoleDto<T>[]): Promise<void> {
await this.roleRepository.insert(roleDto);
}
}
And I want inject this service in guards, interceptors...
Problem, I don't know how to do that, more precisely:
How can I dynamically inject the roleRepository ? (I imagine some kind of factory has to be involved.)
REAL USE CASE
I want to be able to protect resources with a guard:
#Injectable()
export class RoleGuard<T extends ResourceEntity> implements CanActivate {
constructor(
private authService: AuthService,
private roleService: RoleService<T>,
private readonly reflector: Reflector,
) {}
...
}
Now in a controller, when I use
#Role('Admin')
#UseGuards(RoleGuard<MediaEntity>)
Get()
...
It would be perfect if the whole thing magically works :), ie correct roleService with correct roleRepository are properly injected.
I am completely new to nestjs and typescript (and never played with angular neither) so maybe the whole approach is wrong..

Angular 2 nested injection

I am struggling with angular2's dependency injection. In my example I have two Services.
Service1 injects Service2 and gets data from it.
A Component injects Service1 and fetches the data from Service1
I have to provide Service2 in my Component
#Component({
providers: [Service1, Service2]
})
But why? I injected Service2 in Service1. Why do I have to provide Service2 in my Component, when there's no reference to Service2 in my Component?
I am aware, that I could provide services in my bootsrap function, but I would like to provide my Services to my Component...
bootstrap(AppComponent, [... Service1, Service2])
Here is my example code, which is not working because of the missing provider
component.ts
import {Service1} from "service1.ts";
#Component({
providers: [Service1]
})
export class Component{
constructor(private s: Service1) {
//get data from Service1
}
}
service1.ts
import {Service2} from "service2.ts";
#Injectable()
export class service1{
constructor(private s2: Service2) {
//get data from service2
//edit data
//return data
}
}
service2.ts
#Injectable()
export class service2{
constructor() {
//return data
}
}
Angular needs to know, where to find the services. That's what providers array (either in the component or in the bootstrap call) is used for. You can think of it as of a hierarchical registry. If you want the services to be injected, you need to feed them to the registry.
In Angular1 the services were registered in the registry by calling the factory function or alike. Here the logic is different.
All in all, even if the component is not directly bound to the service, it has to register it, so that Angular becomes aware it exists.

Can you only inject services into services through bootstrap?

I am trying to wire up a basic Angular2 app that uses the Http service. (Most of the tutorials I've seen do this by having a Component consume the Http service, which seems wrong unless the basic philosophy of thin controllers has changed – but that's a different question.)
I would like to create a service that uses Angular's Http service. But I can't figure out how to inject the Http service other than this:
boot.ts:
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
import {HTTP_PROVIDERS } from 'angular2/http';
bootstrap(AppComponent, [HTTP_PROVIDERS]);
myService.ts:
import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
#Injectable()
export class aService{
constructor(http:Http){
}
/** do some stuff *//
}
This works, but it seem very wrong to require the user of the service to know the service's dependencies and be required to inject them into the bootstrap process. It seems like there should be a way to directly hand a providers array to a service the same way you can a component, but I can't find it. Am I just missing something?
Update
This way if a parent injector provides an implementation for OtherService this one is used, otherwise OtherServiceImpl is used (default).
#Injectable()
class SomeService {
OtherService _other;
SomeService(Injector injector) {
_other = injector.getOptional(OtherService);
if (_other == null) {
_other = injector.resolveAndCreateChild([
provide(OtherService, useClass: OtherServiceImpl)
]).get(OtherService);
}
_other.doSomething();
}
}
If you provide another one like
bootstrap(AppElement, [
provide(OtherService, useClass: OtherServiceImpl2)
]);
OtherServiceImpl2 is used.
See also https://github.com/angular/angular/issues/5622
Original
You could just make the http service optional (using the #Optional() annotation) and if none is provided just create an instance inside the constructor with new Http().
This way the user doesn't need to know about the services dependencies, but is able to pass alternative implementations if necessary (for example for testing).
If creating the dependeny inside the service requires DI itself, you can inject an injector and use it to get dependencies.
See also optional dependencies in http://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html
What also could work (not tried myself yet) is just to create a child injector and instruct it to skip self
From the SkipSelfMetadata documentation
class Dependency {
}
#Injectable()
class NeedsDependency {
dependency;
constructor(#SkipSelf() dependency:Dependency) {
this.dependency = dependency;
}
}
var parent = Injector.resolveAndCreate([Dependency]);
var child = parent.resolveAndCreateChild([NeedsDependency]);
expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true);
var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
expect(() => inj.get(NeedsDependency)).toThrowError();
I don't know yet if this still resolves from "self" if parent can't provide the requested type.

Resources