Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow singleton dynamic value injection and solves #330 #360

Merged
merged 7 commits into from
Sep 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ bundled
typings
.typingsrc
dist
dts
lib
temp
es
Expand Down
2 changes: 0 additions & 2 deletions PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
- [ ] My code follows the code style of this project.
- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.
- [ ] My change requires a change to the type definitions.
- [ ] I have updated the type definitions accordingly.
- [ ] I have read the **CONTRIBUTING** document.
- [ ] I have added tests to cover my changes.
- [ ] All new and existing tests passed.
60 changes: 26 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,55 +57,47 @@ InversifyJS has been developed with 4 main goals:
You can get the latest release and the type definitions using npm:

```
npm install [email protected] reflect-metadata --save
npm install inversify-dts --save-dev
npm install [email protected] reflect-metadata --save
```

You will also need the type definitions files for inversify and reflect-metadata.
The InversifyJS type definitions are included in the inversify npm package.
You will also need the type definitions files for `reflect-metadata`.
The `reflect-metadata` type definitions are included in its npm package.

The InversifyJS type definitions are included in the inversify-dts npm package:
InversifyJS requires the `experimentalDecorators`, `emitDecoratorMetadata`
and `lib` compilation options in your `tsconfig.json` file:

```ts
/// <reference path="node_modules/inversify-dts/inversify/inversify.d.ts" />
```

The reflect-metadata type definitions are included in the npm package:

```ts
/// <reference path="node_modules/reflect-metadata/reflect-metadata.d.ts" />
```

InversifyJS requires a modern JavaScript engine with support for the Promise, Reflect (with metadata) and Proxy objects.
If your environment don't support one of these you will need to import a shim or polyfill. If you are targeting ES5 you will get the following error:

> TypeScript error: node_modules/inversify-dts/inversify/inversify.d.ts(108,13): Error TS2304: Cannot find name 'Promise'.

You can solve this problem by installing type definitions for the Promise API. If you are working on node the node type definitions already include the required definitions. If you are working on a browser app you can use the bluebird type definitions and polyfill:

```
$ typings install --save --global dt~bluebird
{
"compilerOptions": {
"target": "es5",
"lib": ["es6", "dom"],
"module": "commonjs",
"moduleResolution": "node",
"jsx": "react",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noImplicitAny": true
},
"files": [
"./node_modules/reflect-metadata/reflect-metadata.d.ts",
]
}
```

Check out the [Environment support and polyfills](https://github.com/inversify/InversifyJS/blob/master/wiki/environment.md) page in the wiki to learn more.
InversifyJS requires a modern JavaScript engine with support for the Promise, Reflect Metadats and Proxy objects.
If your environment don't support one of these you will need to import a shim or polyfill.

The relect-metadata polyfill can be importing as follows:
At the time of writing this guide (September 2016) it is necesary to
use the `relect-metadata` polyfill. This polyfill can be importing as follows:

```ts
import "reflect-metadata";
```

> **The `reflect-metadata` polyfill should be imported only once in your entire application** because the Reflect object is mean to be a global singleton. More details about this can be found [here](https://github.com/inversify/InversifyJS/issues/262#issuecomment-227593844).

InversifyJS requires the following TypeScript compilation options in your `tsconfig.json` file:

```
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
```
Check out the [Environment support and polyfills](https://github.com/inversify/InversifyJS/blob/master/wiki/environment.md) page in the wiki to learn more.

### The Basics (TypeScript)
Let’s take a look to the basic usage and APIs of InversifyJS with TypeScript:
Expand Down
108 changes: 28 additions & 80 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ require("harmonize")();

var gulp = require("gulp"),
browserify = require("browserify"),
tsify = require("tsify"),
source = require("vinyl-source-stream"),
buffer = require("vinyl-buffer"),
tslint = require("gulp-tslint"),
Expand All @@ -18,7 +17,6 @@ var gulp = require("gulp"),
uglify = require("gulp-uglify"),
rename = require("gulp-rename"),
runSequence = require("run-sequence"),
header = require("gulp-header"),
mocha = require("gulp-mocha"),
istanbul = require("gulp-istanbul"),
karma = require("karma");
Expand All @@ -39,81 +37,21 @@ gulp.task("lint", function() {
});

//******************************************************************************
//* SOURCE
//* BUILD
//******************************************************************************
var banner = ["/**",
" * <%= pkg.name %> v.<%= pkg.version %> - <%= pkg.description %>",
" * Copyright (c) 2015 <%= pkg.author %>",
" * <%= pkg.license %> inversify.io/LICENSE",
" * <%= pkg.homepage %>",
" */",
""].join("\n");

var pkg = require("./package.json");

gulp.task("build-bundle-src", function() {

var mainTsFilePath = "src/inversify.ts";
var outputFolder = "dist/";
var outputFileName = "inversify.js";

var bundler = browserify({
debug: true,
standalone : "inversify"
});

// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify, { typescript: require("typescript") })
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(header(banner, { pkg : pkg } ))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(outputFolder));
});

gulp.task("build-bundle-compress-src", function() {

var mainTsFilePath = "src/inversify.ts";
var outputFolder = "dist/";
var outputFileName = "inversify.min.js";

var bundler = browserify({
debug: true,
standalone : "inversify"
});

// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify)
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(header(banner, { pkg : pkg } ))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(outputFolder));
});

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

gulp.task("build-lib", 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(tsLibProject))
.on("error", function (err) {
process.exit(1);
})
.js
.pipe(header(banner, { pkg : pkg } ))
.pipe(gulp.dest("lib/"));
.js.pipe(gulp.dest("lib/"));
});

var tsEsProject = tsc.createProject("tsconfig.json", { module : "es2015", typescript: require("typescript") });
Expand All @@ -122,16 +60,33 @@ gulp.task("build-es", 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(tsEsProject))
.on("error", function (err) {
process.exit(1);
})
.js
.pipe(header(banner, { pkg : pkg } ))
.pipe(gulp.dest("es/"));
.js.pipe(gulp.dest("es/"));
});

var tsDtsProject = tsc.createProject("tsconfig.json", {
declaration: true,
noExternalResolve: false,
typescript: require("typescript")
});

gulp.task("build-dts", function() {
return gulp.src([
"typings/index.d.ts",
"node_modules/reflect-metadata/reflect-metadata.d.ts",
"src/**/*.ts"
])
.pipe(tsc(tsDtsProject))
.on("error", function (err) {
process.exit(1);
})
.dts.pipe(gulp.dest("dts"));

});

//******************************************************************************
Expand All @@ -143,7 +98,6 @@ 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 @@ -159,7 +113,6 @@ 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 Expand Up @@ -188,9 +141,9 @@ gulp.task("istanbul:hook", function() {
//******************************************************************************
//* TESTS BROWSER
//******************************************************************************
gulp.task("build-bundle-test", function() {
gulp.task("bundle-test", function() {

var mainTsFilePath = "test/inversify.test.ts";
var mainJsFilePath = "test/inversify.test.js";
var outputFolder = "temp/";
var outputFileName = "bundle.test.js";

Expand All @@ -199,19 +152,16 @@ gulp.task("build-bundle-test", function() {
standalone : "inversify"
});

// TS compiler options are in tsconfig.json file
return bundler.add(mainTsFilePath)
.plugin(tsify, { typescript: require("typescript") })
return bundler.add(mainJsFilePath)
.bundle()
.pipe(source(outputFileName))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(header(banner, { pkg : pkg } ))
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(outputFolder));
});

gulp.task("karma", ["build-bundle-test"], function (done) {
gulp.task("karma", ["bundle-test"], function (done) {
new karma.Server({
configFile: __dirname + "/karma.conf.js"
}, function(code) {
Expand Down Expand Up @@ -242,9 +192,7 @@ if (process.env.APPVEYOR) {
gulp.task("build", function(cb) {
runSequence(
"lint",
"build-bundle-src", // for nodejs
"build-bundle-compress-src", // for browsers
["build-src", "build-es", "build-lib"], // tests + build es and lib
["build-src", "build-es", "build-lib", "build-dts"], // tests + build es and lib
"build-test", cb);
});

Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "A powerful and lightweight inversion of control container for JavaScript and Node.js apps powered by TypeScript.",
"main": "lib/inversify.js",
"jsnext:main": "es/inversify.js",
"typings": "./dts/inversify.d.ts",
"directories": {
"test": "gulp"
},
Expand Down Expand Up @@ -66,10 +67,8 @@
"reflect-metadata": "^0.1.3",
"run-sequence": "^1.2.0",
"sinon": "^1.17.3",
"tsify": "^1.0.3",
"tslint": "^3.12.0",
"typedoc": ">=0.3.9",
"typescript": "^1.8.10",
"typescript": "^2.0.2",
"typings": "^1.0.4",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0"
Expand Down
3 changes: 2 additions & 1 deletion src/annotation/inject.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Metadata from "../planning/metadata";
import interfaces from "../interfaces/interfaces";
import { tagParameter, tagProperty } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";

function inject(serviceIdentifier: (string|Symbol)) {
function inject(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
return function(target: any, targetKey: string, index?: number) {

let metadata = new Metadata(METADATA_KEY.INJECT_TAG, serviceIdentifier);
Expand Down
3 changes: 2 additions & 1 deletion src/annotation/multi_inject.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Metadata from "../planning/metadata";
import interfaces from "../interfaces/interfaces";
import { tagParameter, tagProperty } from "./decorator_utils";
import * as METADATA_KEY from "../constants/metadata_keys";

function multiInject(serviceIdentifier: (string|Symbol)) {
function multiInject(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
return function(target: any, targetKey: string, index?: number) {

let metadata = new Metadata(METADATA_KEY.MULTI_INJECT_TAG, serviceIdentifier);
Expand Down
19 changes: 0 additions & 19 deletions src/interfaces/globals.d.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace interfaces {
new (...args: any[]): T;
}

export type ServiceIdentifier<T> = (string | Symbol | Newable<T>);
export type ServiceIdentifier<T> = (string | symbol | Newable<T>);

export interface Binding<T> extends Clonable<Binding<T>> {
guid: string;
Expand Down Expand Up @@ -112,7 +112,7 @@ namespace interfaces {
metadata: Array<Metadata>;
hasTag(key: string): boolean;
isArray(): boolean;
matchesArray(name: string | Symbol | Newable<any>): boolean;
matchesArray(name: interfaces.ServiceIdentifier<any>): boolean;
isNamed(): boolean;
isTagged(): boolean;
matchesNamedTag(name: string): boolean;
Expand Down Expand Up @@ -188,7 +188,7 @@ namespace interfaces {
to(constructor: { new (...args: any[]): T; }): BindingInWhenOnSyntax<T>;
toSelf(): BindingInWhenOnSyntax<T>;
toConstantValue(value: T): BindingWhenOnSyntax<T>;
toDynamicValue(func: (context: Context) => T): BindingWhenOnSyntax<T>;
toDynamicValue(func: (context: Context) => T): BindingInWhenOnSyntax<T>;
toConstructor<T2>(constructor: Newable<T2>): BindingWhenOnSyntax<T>;
toFactory<T2>(factory: FactoryCreator<T2>): BindingWhenOnSyntax<T>;
toFunction(func: T): BindingWhenOnSyntax<T>;
Expand Down
Loading