GithubHelp home page GithubHelp logo

inversify / inversifyjs Goto Github PK

View Code? Open in Web Editor NEW
10.8K 10.8K 711.0 2.31 MB

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.

Home Page: http://inversify.io/

License: MIT License

TypeScript 100.00%
dependency-injection inversifyjs ioc javascript nodejs typescript

inversifyjs's People

Contributors

dcavanagh avatar dependabot[bot] avatar dmitry-nizovsky avatar endel avatar goenning avatar greenkeeper[bot] avatar greenkeeperio-bot avatar huan avatar jamesadarich avatar jameskmonger avatar johnjacobkenny avatar lautarobock avatar leonardssh avatar lholznagel avatar lukas-zech-software avatar nlight avatar notaphplover avatar offirmo avatar oguimbal avatar oppianmatt avatar parisholley avatar pitamar avatar podarudragos avatar razzeee avatar remojansen avatar sanex3339 avatar tenowg avatar theodesp avatar tonyhallett avatar zandroid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

inversifyjs's Issues

Cannot find module 'inversify'

I have installed Inversify version 1.2.0 from NPM and have saved it to my dependencies in package.json, and I have installed the typings with TSD also.

When I import Inject from the inversify module, I get an error Cannot find module 'inversify'.

/// <reference path="../typings/inversify/inversify.d.ts" />

import { Inject } from 'inversify';

The /// reference is pointing to the correct typings file.

Drop support for bower

At the moment, too much is being distributed with the bower distribution.

Included in the distribution is the TypeScript source, the Karma configuration, and the test files.

The package size could be slimmed down considerably by only distributing the compiled JS, the LICENSE and the bower.json.

Fix 1.3.0 npm download

I upgraded to 1.3.0 using npm update to try finally get the class decorators to work, but it seems now it doesn't download the actual .js \ .ts files, it downloads only typings.

Screenshott

Proposal: Decorators

Problem: Currently we rely on the constructor argument names to inject dependencies. This causes problems with minification (as the argument name is changed) and injecting two dependencies of the same type into a class (as they both can't have the same argument name).

Proposed Solution: Decorators

As an addition to being able to resolve the dependencies of the class by argument name, it should also possible to do so via decorator (see example below)


class A {
   constructor (@Inject("IB") be: IB) {
      be.fancy();
   }
}

interface IB {
    fancy(): void;
}

class B implements IB {
     fancy() { 
        console.log("this does something I promise");
     }
}

The decorator should be given the string which relates to the binding registered in the kernel i.e. in this scenario...


let kernel = new inversify.Kernel();
kernel.bind(new inversify.TypeBinding<IB>("IB", B));

In terms of solutions I have already developed a brief concept so I suggest that we add the following...


let Inject = function (typeIdentifier: string) {
     return function (target: InjectableConstructorInterface, propertyName: string, argumentIndex: number) {
         //if there are no decorated argument types associated with this type
         //then add them as the argument names (as currently implemented)
         if (!target.argumentTypes) {
            // Regular expressions used to get a list containing
            // the names of the arguments of a function
            let STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
            let ARGUMENT_NAMES = /([^\s,]+)/g;

            let fnStr = target.toString().replace(STRIP_COMMENTS, '');
            let argsInit = fnStr.indexOf('(') + 1;
            let argsEnd = fnStr.indexOf(')');

            target.argumentTypes = fnStr.slice(argsInit, argsEnd).match(ARGUMENT_NAMES);
         }
         //override assumed type with the decorated type
         target.argumentTypes[argumentIndex] = typeIdentifier;
     };
 };
 export { Inject };

then adjust how _getConstructorArguments works slightly to always return the argumentTypes array in favor of the new decorator defined arguments if these are available.


 interface InjectableConstructorInterface {
     argumentTypes: Array<string>;
 }

private _getConstructorArguments(func : InjectableConstructorInterface) {
     if (func.argumentTypes) {
        return func.argumentTypes;
     }
    ... (continues to execute the existing code)

What are your thoughts @remojansen? I can have this code ready in a PR if you're happy, I'm also happy to discuss naming or tweaks/additions in functionality.

This should resolve #29 and #14 :)

Supporting Modules [toValue binding]

Is there anyway to use the container to inject commonjs modules in to your classes as well? Based on the .d.ts, whatever you pass in as the implementation type must have a constructor. Essentially, I would like to use the container to inject modules like express in to the constructors of my classes.

Also, is there any way to support dependencies with callbacks? What if a class needs to do some IO ops when it is being constructed. I would guess these needs to be synchronous, otherwise the container might inject the dependency before its ready.

Attributes don't compile in Typescript?

*I put this question on Stackoverflow, but there's no InversifyJS tag there yet: http://stackoverflow.com/questions/35149514/why-does-inversifyjs-not-compile-this-attribute

I'm copying the Inversify documentation almost exactly (version 1.2.2) and it fails to compile, giving me Typescript error TS1238. Why?

'use strict';
import './tools/typescriptImports';
import IServer = require('./iServer.ts');
import IDatabase = require('../database/iDatabase');
import express = require('express');
import bodyParser = require('body-parser');
import config = require('../config');
import types = require('../tools/types.ts');
import _ = require('lodash');
import async_ = require('async');
import { Inject } from "inversify";

@Inject("IDatabase") // <- error TS1238: Unable to resolve signature of class decorator when called as an expression. Supplied parameters do not match any signature of call target.
class Server implements IServer
{
    db : IDatabase;
    expressApp : express.Express;

    constructor(db : IDatabase)
    {
        this.db = db;
        ..

Create angularjs 2.x example code

It would be good to demonstrate how Inversify can be used in an angular (preferably angular 2) as it will help people understand from a wider perspective the importance of DI.

options.className in constructor makes injection fail

example

export class MyClass extends AnotherClass implements IMyClass {
    constructor( 
      IShouldbeInjected: IShouldbeInjected ) {
        var options: any = {}
        options.el = '#mydiv';
        options.className = "row";
        super(options);
        this.childView = ChildView;
        this.collection = IShouldbeInjected;
    }
}

comes from kernel.ts _getConstructorArguments at line 96 in
if ('function' === typeof Map &&
fnStr.indexOf("class") !== -1 &&
fnStr.indexOf("constructor") === -1) {

        result = null;
    }

you probably have to replace fnStr.indexOf("class") with fnStr.indexOf("class ")

Node/Express example

I'm just going to create some issues for some required examples.

We need a Node/express example at:

https://github.com/inversify/inversify-code-samples

I've been doing some analysis and we should be able to integrate InversifyJS with Express without problems.

Feel free to send PRs.

integration test for .d.ts

Hi guys!

I have added a label to track all the .d.ts related issues:

https://github.com/inversify/InversifyJS/labels/.d.ts

I think we need to focus on fixing this issues before we add new features.

Also we need to do something so this issues can be spotted in the future, at the moment the issues are are there but the Travis CI build thinks that everything is OK.

So we need integration tests so the build ensures that we don't merge to master broken code:

  • Import InversifyJS as a global (reference ``)
  • Import InversifyJS as an external module using the TS external module syntax
  • import InversifyJS as an external module using the ES6 (import { inject } from "inversify")

Any ideas about how to implement it? @inversify/collaborators

Add warning "Deprecated injections without @inject"

We need to remove the old way of detecting injections (function.toString() + regex).

Can we add:

console.log("WARNING! Injections without inject decorator won't be supported in the upcoming releases");

Add prepublish npm hook

Hey @Jameskmonger,

As discussed we should be running automated scripts prepublish to ensure breaking builds cannot be published.

For now just run gulp test and we will add more checks as necessary to ensure InversifyJS is as stable as possible.

Recent Pull request didn't fix "not a module" issue

My recent #32 pull request failed for fix the issue that I was attempting to fix. It seems that you can't use

declare module 'inversify'

inside the .d.ts used by the typings declared in package.json, which was the reason for the extra inversify-node.d.ts
notamodule

the typings declared in package.json should remove the need to use /// <reference calls.

Can't resolve es6 native types with dependencies

Using node 4.0 and native ES6 classes:

class A{

}

class B{
  constructor(a){}
}

var kernel = new inversify.Kernel();
kernel.bind(new inversify.TypeBinding('a', A));
kernel.bind(new inversify.TypeBinding('b', B));
kernel.resolve('b');

results in Error: Could not resolve service class

The road to 2.0

Hi guys,

I'm going to share with you my plans for 2.0...

I was thinking about finishing the 2.0 branch and doing a massive pull request but I changed my mind...

I'm going to use the 2.0 branch just as a reference and I'm going to be working on a fork to do small merges.

So instead of doing a massive pull request to move from 1.x to 2.0, I would like to move from the current version to 2.0 slowly.

The roadmap in my head looks as follows:

NOTE: This is just s roadmap, final APIs will probably be different and some of the items in the roadmap may never be implemented.

1.3

  • Change folder structure to allow the project to grow with ease. At the moment al source files are in one folder but it will soon change to some subfolders.
src/
├── activation
│   ├── metadata.ts
│   ├── metadata_keys.ts
│   ├── queryable_string.ts
│   └── target.ts
├── bindings
│   ├── binding.ts
│   └── binding_scope.ts
├── decorators
│   ├── decorator_utils.ts
│   ├── inject.ts
│   ├── named.ts
│   ├── paramnames.ts
│   └── tagged.ts
├── interfaces
│   ├── activation
│   │   ├── metadata.d.ts
│   │   ├── queryable_string.d.ts
│   │   └── target.d.ts
│   ├── bindings
│   │   └── binding.d.ts
│   ├── decorators
│   │   └── inject.d.ts
│   ├── interfaces.d.ts
│   └── kernel
│       ├── kernel.d.ts
│       ├── key_value_pair.d.ts
│       └── lookup.d.ts
├── inversify.ts
└── kernel
    ├── kernel.ts
    ├── key_value_pair.ts
    └── lookup.ts
  • Initial implementation of the activation process. Before we can inject we need to add some metadata, this metadata is created during the activation process and includes classes like Metadata and Target.
  • Initial implementation of the planning process. After metadata has been generated InversifyJS creates a resolution plan for the dependencies.
  • Initial implementation of the resolution plan. Once the resolution plan has been created we just need to execute it to obtain a dependency.

1.4

  • Fluent binding interface. kernel.bind<X>("X").to().inTransientScope()
  • Meaningful error for cyclic dependencies Type X has a cyclic dependency on type Y
  • Parent kernel support new Kernel(parentKernel)

1.5

  • Value injection. Injects an instance that don't need to be resolved. It will be something like bind<X>("X").toValue(someInstance).
  • Factory injection. Injects a function that provides an instance in a synchronous way. It will be something like bind<X>("X").toFactory(someFactory).
  • Provider injection. Injects an asynchronous factory. It will be something like bind<X>("X").toProvider(someFactoryAsync).

1.x

  • ??

2.0

  • Allow multiple bindings with the same identifier
kernel.bind(new Binding<IWeapon>("IWeapon").to(Katana));
kernel.bind(new Binding<IWeapon>("IWeapon").to(Shuriken));
@inject("IWeapon","IWeapon")
class Warrior {
    private _primaryWeapon : IWeapon;
    private _secondaryWeapon : IWeapon;

    constructor(
      @Tagged("canThrow", false) primary : IWeapon,
      @Tagged("canThrow", true) secondary : IWeapon) {
        // ...
    }
}

kernel.bind<IWeapon>("IWeapon").to(Katana).tagged("canThrow", false);
kernel.bind<IWeapon>("IWeapon").to(Shuriken).tagged("canThrow", true);

// We should also be able to do:
var canThrow = Tagged.bind(null, ["canThrow", false]);

@inject("IWeapon","IWeapon")
class Warrior {
    private _primaryWeapon : IWeapon;
    private _secondaryWeapon : IWeapon;

    constructor(
      @canThrow() primary : IWeapon,
      @canThrow() secondary : IWeapon) {
        // ...
    }
}
@inject("IWeapon","IWeapon")
class Soldier {

  private _mainWeapon : IWeapon;
  private _secondaryWeapon : IWeapon;

  constructor(
    @named("main") weapon: IWeapon, 
    @named("secondary") weapon: IWeapon
  ) {

    this._mainWeapon = main;
    this._secondaryWeapon = secondary;
  }

}

kernel.bind<IWeapon>("IWeapon").to(Katana).named("main");
kernel.bind<IWeapon>("IWeapon").to(Shuriken).named("secondary");
  • Multi Injection
kernel.bind<IWeapon>("IWeapon").to(Katana).named("main");
kernel.bind<IWeapon>("IWeapon").to(Shuriken).named("secondary");

@inject("IWeapon[]")

2.1

  • Contextual bindings
.when(request => { return request.target.name.equal("katana") })
.whenInjectedInto(SomeClass)

2.2

  • Nested context when using when(request => {}) the requests object will provide access to the depth, parentContext & parentRequest values.
when(request => { return request.parentRequests.target.name.equal("katana") })

My plan is to implement 1.3 and then I will start creating tickets and accepting pull requests for all the other releases.

I think guys is really important that we spend the time necessary to create a good architecture don't be afraid to ask for advice from the community.

I'm going to document the glossary and an architecture overview.

Thanks for being part the team 👪 !

error TS2656: Exported external package?

I get this error when I compile with typescript v1.7.3

error TS2656: Exported external package typings file '<path>/node_modules/inversify/type_definitions/inversify.d.ts' is not a module. Please contact the package author to update the package definition.

I made it work by manualy removing "typings": "type_definitions/inversify.d.ts" from inversify package.json and importing inversify.d.ts file in my tsd.d.ts file

Use with vanilla javascript

this project is promising, but is possible to be used without Typescript, at least for a start?

Me, as many javascript coders out there, might be interested in Typescript in the near future, but for now a DI library without dependencies is even more attractive :)

Add "transaction" scope support

When adding a binding allow "transaction" as scope.

Users can then create a "transaction" with:

kernel.beginTransaction("inteface");

And finish it with:

kernel.endTransaction("inteface");

Between beginTransaction and endTransaction if resolve is invoked:

kernel.resolve<inteface>("inteface");

The IoC container will use singleton scope.

If resolve is invoked before beginTransaction has been invoked the IoC container will use transient scope.

This is useful when we want a module to be a singleton within a scope. If we are in a scope (e.g.controller) and we navigate to a different scope (e.g. another controller) we might want our module to stop using singleton scope or create a new singleton within the new scope. All we need to do is to invoke beginTransaction when creating a scope (e.g. navigating to a controller) and endTransaction when leaving the scope (e.g. disposing the controller).

Inversify does not run? Error TS2656

I've downloaded the latest version of Inversify (1.2.0) and have Typescript (1.7.3). But when trying to use your documentation to change just two files in my project and compile with tsc I get:

error TS2656: Exported external package typings file 'node_modules/inversify/type_definitions/inversify.d.ts' is not a module. Please contact the package author to update the package definition.

Is there a typo in the latest version of Inversify perhaps?


I'm referencing Inversify like this:
/// <reference path="../../node_modules/inversify/type_definitions/inversify.d.ts" />

and using it like this:

import { TypeBinding, Kernel, TypeBindingScopeEnum } from "inversify";
import IDatabase = require('../database/iDatabase');
import Database = require('../database/Database');

class Ioc
{
    public container : Kernel;
    constructor()
    {
        let c = new Kernel();
        c.bind(new TypeBinding<IDatabase>("IDatabase", Database, TypeBindingScopeEnum.Transient));
        this.container = c;
    }
}
export = Ioc;

Missing release tags for versions after 1.0.2

Makes quite difficult tracking dependencies, basically the current package in npm is on 1.2.2 but you miss tag 1.2.2 (and anything lesser than that until 1.0.2)

Should be a good idea including at least the latest one to address it

Use Mocha to run tests

At the moment, we are using Karma to test the project after it has been passed through browserify. This means that we test some of the code added by browserify, which we shouldn't be testing (such as var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f).

This results in skewed test coverage results (of 99.78%) because some of the lines are not possible to test with Karma.

By using Mocha, we can directly test our compiled commonjs code, which will give us a true reflection of our test coverage.

Bloated npm distribution

At the moment, too much is being distributed with the npm distribution.

Included in the distribution is the TypeScript source, the Karma configuration, and the test files.

The package size could be slimmed down considerably by only distributing the compiled JS and the package.json.

Create an instance without relying on interfaces [toValue binding]

If I have simple class which is not implementing any interface.

export class Something{
        constructor(*/../*) { }
        public static CustomMethodFromNotReallySomething(*/params/*) { }
    }

And a module which exports NotReallySomething relying on third party node module

export var NotReallySomething= GetNotReallySomethingFromThirdParty();

In my app I am swapping Something with NotReallySomething manually using imports so this way is working for me but I am thinking to improve that so just wondering is there any way I can configure inversify to create a single instantiate of Something or NotReallySomething so I can use it in my calling module like var something = kernel.instance('SomethingOrNotReallySomething'); by configuring inversify.config.ts something like:

if (app.get('env') === 'dev') {
kernel.bind(new TypeInstance<Something>('SomethingOrNotReallySomething'));
} 
else if (app.get('env') === 'stg') {
kernel.bind(new TypeInstance<NotReallySomething>('SomethingOrNotReallySomething'));
}

Upgrade Marionette example

We need to upgrade the marionette example at https://github.com/inversify/inversify-code-samples to use the latest version of its dependencies. This includes:

  • Upgrade TypeScript
  • Upgrade InversiyJS
  • Upgrade Marionette
  • Use typings instead of TSD
  • Use bower instead of RequireJS
  • Use ES6 modules
  • Update documentation

So there is a good bit of work in this upgrade.

Compilation errors in build

There is an error in the build logs:

https://travis-ci.org/inversify/InversifyJS/builds/103853460

[14:19:34] Starting 'build-test'...
test/inject_annotation.test.ts(1,1): error TS6053: File '/home/travis/build/inversify/InversifyJS/typings/tsd.d.ts' not found.
test/inject_annotation.test.ts(3,24): error TS2307: Cannot find module 'chai'.
test/inject_annotation.test.ts(6,1): error TS2304: Cannot find name 'describe'.
test/inject_annotation.test.ts(7,4): error TS2304: Cannot find name 'it'.
test/inject_annotation.test.ts(19,4): error TS2304: Cannot find name 'it'.
test/inject_annotation.test.ts(32,4): error TS2304: Cannot find name 'it'.
test/inject_annotation.test.ts(45,4): error TS2304: Cannot find name 'it'.
test/inject_annotation.test.ts(58,4): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(1,1): error TS6053: File '/home/travis/build/inversify/InversifyJS/typings/tsd.d.ts' not found.
test/kernel.test.ts(3,24): error TS2307: Cannot find module 'chai'.
test/kernel.test.ts(9,1): error TS2304: Cannot find name 'describe'.
test/kernel.test.ts(11,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(23,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(51,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(66,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(87,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(111,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(131,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(143,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(177,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(213,3): error TS2304: Cannot find name 'it'.
test/kernel.test.ts(249,3): error TS2304: Cannot find name 'it'.
test/lookup.test.ts(1,1): error TS6053: File '/home/travis/build/inversify/InversifyJS/typings/tsd.d.ts' not found.
test/lookup.test.ts(3,24): error TS2307: Cannot find module 'chai'.
test/lookup.test.ts(6,1): error TS2304: Cannot find name 'describe'.
test/lookup.test.ts(8,3): error TS2304: Cannot find name 'it'.
test/lookup.test.ts(15,3): error TS2304: Cannot find name 'it'.
test/lookup.test.ts(20,3): error TS2304: Cannot find name 'it'.
test/lookup.test.ts(25,3): error TS2304: Cannot find name 'it'.
test/lookup.test.ts(34,3): error TS2304: Cannot find name 'it'.
test/type_binding.test.ts(1,1): error TS6053: File '/home/travis/build/inversify/InversifyJS/typings/tsd.d.ts' not found.
test/type_binding.test.ts(3,24): error TS2307: Cannot find module 'chai'.
test/type_binding.test.ts(7,1): error TS2304: Cannot find name 'describe'.
test/type_binding.test.ts(9,3): error TS2304: Cannot find name 'it'.
test/type_binding.test.ts(30,3): error TS2304: Cannot find name 'it'.
test/type_binding.test.ts(38,3): error TS2304: Cannot find name 'it'.
[14:19:34] TypeScript: 36 semantic errors
[14:19:34] TypeScript: emit succeeded (with errors)

I think this issues was introduced by #39

It looks like is missing the tsd.d.ts file:

'/home/travis/build/inversify/InversifyJS/typings/tsd.d.ts' not found.

We need to fix it but even more important is to ensure that the Travis CI build fails if there are compilation errors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.