Search code examples
node.jstypescriptinversifyjs

Missing @Injectable annotation when importing json value


I'm currently trying to inject a json file into a service that I am building. This class is injecting the json via a @inject() tag in the constructor. Below you can find the code that I'm using.

DiContainer.ts

import { Container, decorate, injectable } from "inversify";
import { IResponseBuilder, InjectionTypes, IUserIdGenerator, ILogger, IResponseRepository, IResponseService, IContextService, IFileWriter, IBoardSessionService, IIntent } from "./src/common/types";
import GoogleResponseBuilder from "./src/common/builders/googleResponseBuilder";
import UserIdGenerator from "./src/common/helpers/userIdGenerator";
import { DialogflowConversation } from "actions-on-google";
import WinstonLogger from "./src/common/winstonLogger";
import FileWriter from "./src/common/helpers/fileWriter";
import TextResponseRepository from "./src/repositories/textResponseRepository";
import SsmlResponseRepository from "./src/repositories/ssmlResponseRepository";
import ResponseSerivce from "./src/services/responseService";
import ContextService from "./src/services/contextService";
import { BoardService } from "./src/services/boardService";
import { BoardSessionService } from "./src/services/boardSessionService";
import WelcomeIntent from "./src/intents/new/welcomeIntent";
import uuid from "uuid/v4";

const sessionJson = require("./src/data/boardSessions.json");



const DIContainer = new Container();

DIContainer.bind<IResponseBuilder<DialogflowConversation>>(InjectionTypes.GoogleResponseBuilder).to(GoogleResponseBuilder);
DIContainer.bind<ILogger>(InjectionTypes.WinstonLogger).to(WinstonLogger);
DIContainer.bind<IFileWriter>(InjectionTypes.FileWriter).to(FileWriter);
DIContainer.bind<IUserIdGenerator>(InjectionTypes.UserIdGenerator).to(UserIdGenerator);

DIContainer.bind<IIntent>(InjectionTypes.WelcomeIntent).to(WelcomeIntent);

DIContainer.bind<IResponseRepository>(InjectionTypes.TextResponseRepository).to(TextResponseRepository);
DIContainer.bind<IResponseRepository>(InjectionTypes.SsmlResponseRepository).to(SsmlResponseRepository);
DIContainer.bind<IResponseService>(InjectionTypes.ResponseService).to(ResponseSerivce);
DIContainer.bind<IBoardSessionService>(InjectionTypes.BoardSessionService).to(BoardSessionService);
DIContainer.bind<IContextService>(InjectionTypes.ContextService).to(ContextService);

DIContainer.bind(InjectionTypes.SessionJSON).to(sessionJson);
DIContainer.bind(InjectionTypes.UUIDv4).toFunction(uuid);


export default DIContainer;


Solution

  • Every dependency you try to inject via @inject has to be marked with @injectable and registered through bind. I don't really know how the decorate function works (so I don't know if you can use it to mark a function, and not a class, as injectable).

    By the way, I think you can achieve what you want just registering your dependency as a dynamic value and returning the desired function, as stated here. In your case, something like this:

    DIContainer.bind(InjectionTypes.UUIDv4).toDynamicValue((context: interfaces.Context) => { return uuid });
    

    Alternatively, you could just directly import the function in your service without injecting it, or wrap the function in another service you can mark as injectable (let say, an uuid provider service).