Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
remojansen authored Jun 20, 2016
1 parent bf8b836 commit d06f799
Show file tree
Hide file tree
Showing 128 changed files with 2,903 additions and 2,952 deletions.
41 changes: 18 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,9 @@ InversifyJS has been developed with 4 main goals:
### Installation

You can get the latest release and the type definitions using npm:
```
npm install [email protected] inversify-dts reflect-metadata --save
```

The InversifyJS type definitions are included in the inversify-dts npm package:

```ts
/// <reference path="node_modules/inversify-dts/inversify/inversify.d.ts" />
```
npm install inversify@2.0.0-beta.9 @types/inversify reflect-metadata --save
```

The reflect-metadata type definitions are included in the npm package:
Expand Down Expand Up @@ -106,24 +101,24 @@ This means that we should "depend upon Abstractions and do not depend upon concr
Let's start by declaring some interfaces (abstractions).

```ts
interface INinja {
interface Ninja {
fight(): string;
sneak(): string;
}

interface IKatana {
interface Katana {
hit(): string;
}

interface IShuriken {
interface Shuriken {
throw(): string;
}
```

#### Step 2: Declare dependencies using the `@injectable` & `@inject` decorators
Let's continue by declaring some classes (concretions). The classes are implementations of the interfaces that we just declared. All the classes must be annotated with the `@injectable` decorator.

When a class has a dependency on an interface we also need to use the `@inject` decorator to define an identifier for the interface that will be available at runtime. In this case we will use the string literals `"IKatana"` and `"IShuriken"` as runtime identifiers.
When a class has a dependency on an interface we also need to use the `@inject` decorator to define an identifier for the interface that will be available at runtime. In this case we will use the string literals `"Katana"` and `"Shuriken"` as runtime identifiers.

> **Note**: InversifyJS also support the usage of Classes and Symbols (continue reading to learn more about this).
Expand All @@ -132,28 +127,28 @@ import { injectable, inject } from "inversify";
import "reflect-metadata";

@injectable()
class Katana implements IKatana {
class Katana implements Katana {
public hit() {
return "cut!";
}
}

@injectable()
class Shuriken implements IShuriken {
class Shuriken implements Shuriken {
public throw() {
return "hit!";
}
}

@injectable()
class Ninja implements INinja {
class Ninja implements Ninja {

private _katana: IKatana;
private _shuriken: IShuriken;
private _katana: Katana;
private _shuriken: Shuriken;

public constructor(
@inject("IKatana") katana: IKatana,
@inject("IShuriken") shuriken: IShuriken
@inject("Katana") katana: Katana,
@inject("Shuriken") shuriken: Shuriken
) {
this._katana = katana;
this._shuriken = shuriken;
Expand All @@ -176,9 +171,9 @@ import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";

var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
kernel.bind<Ninja>("Ninja").to(Ninja);
kernel.bind<Katana>("Katana").to(Katana);
kernel.bind<Shuriken>("Shuriken").to(Shuriken);

export default kernel;
```
Expand All @@ -191,13 +186,13 @@ to avoid the [service locator anti-pattern](http://blog.ploeh.dk/2010/02/03/Serv
```ts
import kernel = from "./inversify.config";

var ninja = kernel.get<INinja>("INinja");
var ninja = kernel.get<Ninja>("Ninja");

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
```

As we can see the `IKatana` and `IShuriken` were successfully resolved and injected into `Ninja`.
As we can see the `Katana` and `Shuriken` were successfully resolved and injected into `Ninja`.

InversifyJS supports ES5 and ES6 and can work without TypeScript.
Head to the [**JavaScript example**](https://github.com/inversify/InversifyJS/blob/master/wiki/basic_js_example.md) to learn more!
Expand Down
24 changes: 18 additions & 6 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ gulp.task("build-bundle-src", function() {

// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify)
.plugin(tsify, { typescript: require("typescript") })
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
Expand Down Expand Up @@ -98,13 +98,16 @@ gulp.task("build-bundle-compress-src", function() {
.pipe(gulp.dest(outputFolder));
});

var tsLibProject = tsc.createProject("tsconfig.json", { module : "commonjs" });
var tsLibProject = tsc.createProject("tsconfig.json", { module : "commonjs", typescript: require("typescript") });

gulp.task("build-lib", function() {
return gulp.src([
"src/**/*.ts"
"typings/index.d.ts",
"node_modules/reflect-metadata/reflect-metadata.d.ts",
"src/interfaces/globals.d.ts",
"src/inversify.ts"
])
.pipe(tsc(tsLibProject ))
.pipe(tsc(tsLibProject))
.on("error", function (err) {
process.exit(1);
})
Expand All @@ -113,11 +116,14 @@ gulp.task("build-lib", function() {
.pipe(gulp.dest("lib/"));
});

var tsEsProject = tsc.createProject("tsconfig.json", { module : "es2015" });
var tsEsProject = tsc.createProject("tsconfig.json", { module : "es2015", typescript: require("typescript") });

gulp.task("build-es", function() {
return gulp.src([
"src/**/*.ts"
"typings/index.d.ts",
"node_modules/reflect-metadata/reflect-metadata.d.ts",
"src/interfaces/globals.d.ts",
"src/inversify.ts"
])
.pipe(tsc(tsEsProject))
.on("error", function (err) {
Expand All @@ -135,6 +141,9 @@ var tstProject = tsc.createProject("tsconfig.json");

gulp.task("build-src", function() {
return gulp.src([
"typings/index.d.ts",
"node_modules/reflect-metadata/reflect-metadata.d.ts",
"src/interfaces/globals.d.ts",
"src/**/*.ts"
])
.pipe(tsc(tstProject))
Expand All @@ -148,6 +157,9 @@ var tsTestProject = tsc.createProject("tsconfig.json");

gulp.task("build-test", function() {
return gulp.src([
"typings/index.d.ts",
"node_modules/reflect-metadata/reflect-metadata.d.ts",
"src/interfaces/globals.d.ts",
"test/**/*.ts"
])
.pipe(tsc(tsTestProject))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "inversify",
"version": "2.0.0-beta.8",
"version": "2.0.0-beta.9",
"description": "A lightweight IoC container written in TypeScript.",
"main": "lib/inversify.js",
"jsnext:main": "es/inversify.js",
Expand Down
33 changes: 13 additions & 20 deletions src/annotation/decorator_utils.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,42 @@
///<reference path="../interfaces/interfaces.d.ts" />

import interfaces from "../interfaces/interfaces";
import * as METADATA_KEY from "../constants/metadata_keys";
import * as ERROR_MSGS from "../constants/error_msgs";

interface IReflectResult {
[key: string]: IMetadata[];
}

function tagParameter(annotationTarget: any, propertyName: string, parameterIndex: number, metadata: IMetadata) {
function tagParameter(annotationTarget: any, propertyName: string, parameterIndex: number, metadata: interfaces.Metadata) {
let metadataKey = METADATA_KEY.TAGGED;
return _tagParameterOrProperty(metadataKey, annotationTarget, propertyName, metadata, parameterIndex);
}

function tagProperty(annotationTarget: any, propertyName: string, metadata: IMetadata) {
function tagProperty(annotationTarget: any, propertyName: string, metadata: interfaces.Metadata) {
let metadataKey = METADATA_KEY.TAGGED_PROP;
return _tagParameterOrProperty(metadataKey, annotationTarget.constructor, propertyName, metadata);
}

function _tagParameterOrProperty(
metadataKey: string, annotationTarget: any, propertyName: string, metadata: IMetadata, parameterIndex?: number
metadataKey: string, annotationTarget: any, propertyName: string, metadata: interfaces.Metadata, parameterIndex?: number
) {

let paramsOrPropertiesMetadata: IReflectResult = null;
let paramsOrPropertiesMetadata: interfaces.ReflectResult = {};
let isParameterDecorator = (typeof parameterIndex === "number");
let key: string = (isParameterDecorator) ? parameterIndex.toString() : propertyName;
let key: string = (parameterIndex !== undefined && isParameterDecorator) ? parameterIndex.toString() : propertyName;

// If the decorator is used as a parameter decorator property name must be provided
if (isParameterDecorator === true && propertyName !== undefined) {
throw new Error(ERROR_MSGS.INVALID_DECORATOR_OPERATION);
}

// read metadata if avalible
if (Reflect.hasOwnMetadata(metadataKey, annotationTarget) !== true) {
paramsOrPropertiesMetadata = {};
} else {
if (Reflect.hasOwnMetadata(metadataKey, annotationTarget) === true) {
paramsOrPropertiesMetadata = Reflect.getMetadata(metadataKey, annotationTarget);
}

// get metadata for the decorated parameter by its index
let paramOrPropertyMetadata: IMetadata[] = paramsOrPropertiesMetadata[key];
let paramOrPropertyMetadata: interfaces.Metadata[] = paramsOrPropertiesMetadata[key];
if (Array.isArray(paramOrPropertyMetadata) !== true) {
paramOrPropertyMetadata = [];
} else {
for (let i = 0; i < paramOrPropertyMetadata.length; i++) {
let m: IMetadata = paramOrPropertyMetadata[i];
let m: interfaces.Metadata = paramOrPropertyMetadata[i];
if (m.key === metadata.key) {
throw new Error(`${ERROR_MSGS.DUPLICATED_METADATA} ${m.key}`);
}
Expand All @@ -58,16 +51,16 @@ function _tagParameterOrProperty(

}

function _decorate(decorators: ClassDecorator[], target: any): void {
function _decorate(decorators: any[], target: any): void {
Reflect.decorate(decorators, target);
}

function _param(paramIndex: number, decorator: ParameterDecorator): ClassDecorator {
return function (target: any, key?: string) { decorator(target, key, paramIndex); };
function _param(paramIndex: number, decorator: ParameterDecorator) {
return function (target: any, key: string) { decorator(target, key, paramIndex); };
}

// Allows VanillaJS developers to use decorators:
// decorate(injectable("IFoo", "IBar"), FooBar);
// decorate(injectable("Foo", "Bar"), FooBar);
// decorate(targetName("foo", "bar"), FooBar);
// decorate(named("foo"), FooBar, 0);
// decorate(tagged("bar"), FooBar, 1);
Expand Down
2 changes: 0 additions & 2 deletions src/annotation/inject.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import Metadata from "../planning/metadata";
import { tagParameter } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";
Expand Down
2 changes: 0 additions & 2 deletions src/annotation/injectable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import * as METADATA_KEY from "../constants/metadata_keys";
import * as ERRORS_MSGS from "../constants/error_msgs";

Expand Down
2 changes: 0 additions & 2 deletions src/annotation/multi_inject.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import Metadata from "../planning/metadata";
import { tagParameter } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";
Expand Down
2 changes: 0 additions & 2 deletions src/annotation/named.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import Metadata from "../planning/metadata";
import { tagParameter, tagProperty } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";
Expand Down
18 changes: 9 additions & 9 deletions src/annotation/property_injectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
///<reference path="../interfaces/interfaces.d.ts" />
import interfaces from "../interfaces/interfaces";

const INJECTION = Symbol();

Expand Down Expand Up @@ -26,8 +26,8 @@ function _proxyGetter(
});
}

function makePropertyInjectDecorator(kernel: IKernel) {
return function(serviceIdentifier: (string|Symbol|INewable<any>)) {
function makePropertyInjectDecorator(kernel: interfaces.Kernel) {
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
return function(proto: any, key: string): void {

let resolve = () => {
Expand All @@ -40,8 +40,8 @@ function makePropertyInjectDecorator(kernel: IKernel) {
};
}

function makePropertyInjectNamedDecorator(kernel: IKernel) {
return function(serviceIdentifier: (string|Symbol|INewable<any>), named: string) {
function makePropertyInjectNamedDecorator(kernel: interfaces.Kernel) {
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>, named: string) {
return function(proto: any, key: string): void {

let resolve = () => {
Expand All @@ -54,8 +54,8 @@ function makePropertyInjectNamedDecorator(kernel: IKernel) {
};
}

function makePropertyInjectTaggedDecorator(kernel: IKernel) {
return function(serviceIdentifier: (string|Symbol|INewable<any>), key: string, value: any) {
function makePropertyInjectTaggedDecorator(kernel: interfaces.Kernel) {
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>, key: string, value: any) {
return function(proto: any, propertyName: string): void {

let resolve = () => {
Expand All @@ -68,8 +68,8 @@ function makePropertyInjectTaggedDecorator(kernel: IKernel) {
};
}

function makePropertyMultiInjectDecorator(kernel: IKernel) {
return function(serviceIdentifier: (string|Symbol|INewable<any>)) {
function makePropertyMultiInjectDecorator(kernel: interfaces.Kernel) {
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
return function(proto: any, key: string): void {

let resolve = () => {
Expand Down
2 changes: 0 additions & 2 deletions src/annotation/tagged.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import Metadata from "../planning/metadata";
import { tagParameter, tagProperty } from "./decorator_utils";

Expand Down
2 changes: 0 additions & 2 deletions src/annotation/target_name.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
///<reference path="../interfaces/interfaces.d.ts" />

import Metadata from "../planning/metadata";
import { tagParameter } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";
Expand Down
Loading

0 comments on commit d06f799

Please sign in to comment.