A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
Why is @injectable() necessary?
Is it possible to make a library inversify-compatible without either 1. having a dependency on inversify so you can @injectable() the classes in the lib itself or 2. putting the burden on the application to decorate() everything after the fact?
bind<IAuthorizer>(TYPE_ID.Authorizer).to(LocationActionAuthorizer).whenTargetNamed('LOCATION');
bind<IAuthorizer>(TYPE_ID.Authorizer).to(TokenActionAuthorizer).whenTargetNamed('TOKEN');
container.rebind(TYPE_ID.Authorizer).toConstantValue(mockLocationActionAuthorizer).whenTargetNamed('LOCATION');
container.rebind(TYPE_ID.Authorizer).toConstantValue(mockTokenActionAuthorizer).whenTargetNamed('TOKEN');
@injectable()
export class AuthorizationService {
constructor(
@inject(TYPE_ID.Authorizer) @named('LOCATION') private readonly locationAuthorizer: IAuthorizer,
@inject(TYPE_ID.Authorizer) @named('TOKEN') private readonly tokenAuthorizer: IAuthorizer,
) {}
...
}
No matching bindings found for serviceIdentifier: Symbol(Authoriser)
Symbol(Authoriser) - named: LOCATION
46 | container.rebind(TYPE_ID.Authorizer).toConstantValue(mockTokenActionAuthorizer).whenTargetNamed('TOKEN');
47 |
> 48 | authService = container.get(AuthorizationService);
| ^
49 | });
50 |
51 | beforeEach(() => {
@multiInject
instead? Can I even rebind named bindings?
It started working if I change the rebinding in the tests to:
container.rebind(TYPE_ID.Authorizer).toConstantValue(mockLocationActionAuthorizer).whenTargetNamed('LOCATION');
container.bind(TYPE_ID.Authorizer).toConstantValue(mockTokenActionAuthorizer).whenTargetNamed('TOKEN');
I don't understand why that works at all (surely you have to bind
before you can rebind
?) but maybe this info will be useful for someone else...
Hi! I'm trying to use an Inversify-based library in non-Typescript codebase. How would I go about changing code that looks like this:
constructor(@inject('Display') display, @inject('Text') text) {
super()
to a more ES5-friendly version? I have enough Babel plugins running that the above works correctly, though it makes my eslint deeply unhappy.
Thanks—
injectable()
which doesn't take a Class as a parameter. I've tried making a decorator alias (e.g., @providesAlias
with no param) that applies @provides(<Class>)
which gets around the jest issue, but doesn't work for retrieving the instance when I use container.get(<Class>);
Hello folks,
I have a little question :) I really hope you could help me:
I have a problem when importing lodash (or any lib/file that exports a default
) like this: import _ from 'lodash';
. As soon as I use @injectable
on my Typescript class, it compiles the code differently and lodash is becoming undefined. I've set esModuleInterop:true
but it seems that as soon as I'm using @injectable
, it's like it doesn't care about it anymore
hello,
I have some issues with Inversify package(which is a peer-dep) when running webpack serve
. The error:
ERROR in ../node_modules/mana-syringe/src/inversify/index.ts 1:12
Module parse failed: Unexpected token (1:12)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> import type { interfaces } from 'inversify';
| import { Container } from 'inversify';
| import { Syringe, Utils } from '../core';
ℹ 「wdm」: Failed to compile.
I use webpack and babel loader with the following configs:tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"declaration": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["dom", "dom.iterable", "esnext", "es6"],
"module": "es6",
"moduleResolution": "node",
"noEmit": true,
"noImplicitAny": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"target": "es5",
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"types": ["reflect-metadata"]
},
"include": ["src"],
"exclude": ["node_modules", "dist", "config"]
}
webpack.config.js
const isDev = environment === 'development';
const babelOptions = {
babelrc: false,
presets: [
[
// 'es2017', 'es2016', 'es2015',
'@babel/preset-env',
{
targets: 'last 3 versions'
}
],
'@babel/preset-react'
],
plugins: []
};
module.exports = {
cache: true,
context: paths.appSrc,
plugins: [
new ForkTsCheckerWebpackPlugin({
async: isDev,
typescript: {
configFile: paths.appTSJson,
context: paths.appPath,
configOverwrite: {
compilerOptions: {
sourceMap: isDev,
inlineSourceMap: false,
declarationMap: false
},
exclude: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx']
}
}
}),
new CopyPlugin({
patterns: [
{
from: 'assets',
to: 'assets/',
cacheTransform: true
}
]
}),
new HtmlWebPackPlugin({
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: false
}
}),
new webpack.DefinePlugin({
'process.env': JSON.stringify(env)
})
],
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(js|jsx)?$/,
include: [paths.appSrc],
exclude: [paths.appNodeModules],
use: [
{
loader: 'babel-loader',
options: babelOptions
}
]
},
{
test: /\.(ts|tsx)?$/,
include: [
paths.appSrc
// path.resolve(paths.appNodeModules, 'mana-syringe'),
// path.resolve(paths.appNodeModules, 'inversify')
],
exclude: [paths.appNodeModules],
use: [
{
loader: 'babel-loader',
options: {
...babelOptions,
presets: [
...babelOptions.presets,
['@babel/preset-typescript', { onlyRemoveTypeImports: true }]
],
plugins: [
...babelOptions.plugins,
'babel-plugin-transform-typescript-metadata',
['@babel/plugin-proposal-class-properties', { legacy: true }],
['@babel/plugin-proposal-decorators', { legacy: true }]
]
}
}
// {
// loader: 'ts-loader',
// options: {
// configFile: paths.appTSJson,
// allowTsInNodeModules: true,
// transpileOnly: true
// }
// }
]
}
]
}
};
Hi guys! I am starting a new project creating a Telegram bot with inversify. I have previously used it on my web servers and it worked creating a child container for the requests to initiate some context for each request. I am wondering how to do that with my custom set up, as I am not sure how @injectable works as it magically injects the class from the main container. Could you point me to the documentation if I can specify a container to inject from?
An example of one of the classes I am injecting the instances:
import {injectable} from 'inversify';
import {GameService} from '../services';
@injectable()
export class GameController extends BaseController {
private service: GameService;
constructor(bot: TelegramBot, private readonly gameService: GameService) {
super(bot);
Hi,
I have inherited a react project that uses inversify ioc. It all works well but I'm having trouble writing unit tests. I'm sure my issue is caused by a problem in my configuration somewhere.
I'm getting this error when running the tests...
C:\xxx\src\app\services\auth\JWTAuthentication.service.ts:31
constructor(@(0, _inversify.inject)(_ICookieStorage.ICookieStorageService$) ^
SyntaxError: Invalid or unexpected token
So it seems to me that it can't resolve the @inject in my constructor...
constructor(
@inject(ICookieStorageService$) cookieStorageService: ICookieStorageService,
@inject(ILocalStorageService$) localStorageService: ILocalStorageService,
@inject(ISessionStorageService$) sessionStorageService: ISessionStorageService
) {
...code here
}
In the root index.ts of my application, I wrap the application in
import { Provider } from 'inversify-react';
<Provider container={container}>
...the app
</Provider>
and container is defined in inversify.config.ts.
Obviously this doesn't get wired up when running tests. I'm not sure how to fix my issue. There is almost zero information out there on unit testing with inversify.
I've tried putting import 'reflect-metadata'; everywhere. That didn't help. Also, I don't use babel.
Please help.