question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

question: <ServiceNotFoundError: Service with "MaybeConstructable<ApplicationContext>" identifier was not found in the container.>

See original GitHub issue

Description

I updated the typedi version in my project and now I’m getting this error: ServiceNotFoundError: Service with "MaybeConstructable<ApplicationContext>" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@Service()" decorator.

My old version: “typedi”: “^0.8.0”, My current version: “typedi”: “^0.10.0”,

ApplicationContext

import { Service, Inject, Container } from 'typedi';

import { UserDomain } from 'src/domain/UserDomain';
import { KeycloackService } from 'src/infra/service/internal/KeycloackInternalService';

@Service('ApplicationContext')
export class ApplicationContext {
  private user: UserDomain;
  private accessToken: string;
  private static instance: ApplicationContext;

  constructor(
    @Inject(() => KeycloackService) private keycloackService: KeycloackService,
  ) {}

  public getApplicationContext(): ApplicationContext {
    if (!ApplicationContext.instance) {
      ApplicationContext.instance = new ApplicationContext(
        Container.get(KeycloackService),
      );
    }

    return ApplicationContext.instance;
  }

  public setAccessToken(token: string) {
    this.accessToken = token;
  }

  public getAccessToken() {
    return this.accessToken;
  }

  public async setUserLoggedInfo() {
    this.user = await this.keycloackService.getUserInfo(this.accessToken);
  }

  public async getUserInfo(): Promise<UserDomain> {
    return this.user;
  }
}

Method that consumes the application context

import 'reflect-metadata';
import { Container } from 'typedi';

import { Roles } from 'src/commons/enums/Roles';
import { ApplicationContext } from 'src/app/context/ApplicationContext';
import { UserDomain } from 'src/domain/UserDomain';

export default function Authorize(allowedRolles: Array<Roles>) {
  const applicationContext: ApplicationContext =
    Container.get(ApplicationContext);

  return function (
    _target: any,
    _propertyKey: string,
    descriptor: PropertyDescriptor,
  ) {
    const { value } = descriptor;

    descriptor.value = async function (...args: any) {
      const userDomain: UserDomain = await applicationContext
        .getApplicationContext()
        .getUserInfo();

      userDomain.checkPermission(allowedRolles);

      return value.apply(this, args);
    };
  };
}

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
attilaoroszcommented, Apr 3, 2022

I investigated a little and I might have found the source of the problem. In version 0.8.0 an instance was created for a given constructable even if it had no @Service() decorator. This is the only reason your example was working in that version. When you create a service and provide a name or id, that becomes the injection token, so you should only access it by that token. For example:

// myservice.ts
@Service('MyService')
class MyService {
}

// index.ts
const instance = Container.get('MyService');

This fails in both versions, because MyService never actually registers until you use MyService as a value. Also this shows another problem and I think the main idea behind the auto registration process being removed:

import "reflect-metadata";
import { Container } from 'typedi';
import { ServiceA } from './servicea';

console.log(ServiceA); // Dummy usage

const instance: any = Container.get('ServiceA');
const instance2: any = Container.get(ServiceA);
console.log(instance === instance2); // Logs false

Technically, you get two instances because you provide two different injection tokens. So it turns out the “incorrect” usage was keeping your code running.

So the main issue we have: for the @Service() decorator to execute, the service itself must be used as a value, otherwise it gets omitted from the compiled version (as tsc removes all type related stuff). Also this is the reason why importing the class and using it as the generic parameter doesn’t work either.

I’ll continue investigating a way to force the class to be included in the compiled result.

0reactions
sgentilecommented, Mar 28, 2022

I should add, the @Service is used so the error is invalid:

ie.

ServiceNotFoundError: Service with “MaybeConstructable<DocumentService>” identifier was not found in the container. Register it before usage via explicitly calling the “Container.set” function or using the “@Service()” decorator.

Read more comments on GitHub >

github_iconTop Results From Across the Web

fix: TypeDI integration not working as expected on docs #642
"stack": "ServiceNotFoundError: Service with \"MaybeConstructable<CollaboratorService>\" identifier was not found in the container.
Read more >
I'd like to inject Repositories container at Service constructor ...
The error like this : ServiceNotFoundError: Service with "repositories" identifier was not found in the container. Register it before usage ...
Read more >
Usage Guide - TypeDI
The Token and string identifier can be used to register other values than classes. Both tokens and string identifiers can register any type...
Read more >
Invalid Bundle ID for container | Apple Developer Forums
This is only a problem for the app. The database is fully editable from the dashboard. I tried creating new apps and new...
Read more >
typedi - Bountysource
error log: ServiceNotFoundError: Service with "MaybeConstructable<AlanService>" identifier was not found in the container. Register it before usage via ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found