Skip to content

Commit cafc953

Browse files
authored
Merge pull request #64 from inversify/issue-674
Implemented inversify/InversifyJS/issues/674
2 parents 24f7dff + 23d7fae commit cafc953

File tree

5 files changed

+90
-10
lines changed

5 files changed

+90
-10
lines changed

README.md

+29
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,35 @@ class Shuriken implements ThrowableWeapon {
7979

8080
```
8181

82+
### Using @provide multiple times
83+
84+
If you try to apply `@provide` multiple times:
85+
86+
```ts
87+
@provide("Ninja")
88+
@provide("SilentNinja")
89+
class Ninja {
90+
// ...
91+
}
92+
```
93+
94+
The library will throw an exception:
95+
96+
> Cannot apply @injectable decorator multiple times. Please use @provide(ID, true) if you are trying to declare multiple bindings!
97+
98+
We throw an exception to ensure that you are are not trying to apply `@provide` multiple times by mistake.
99+
100+
You can overcome this by passing the `force` argument to `@provide`:
101+
102+
```ts
103+
@provide("Ninja", true)
104+
@provide("SilentNinja", true)
105+
class Ninja {
106+
// ...
107+
}
108+
```
109+
110+
82111
### Using classes, string literals & symbols as identifiers
83112
When you invoke `@provide` using classes:
84113

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "inversify-binding-decorators",
3-
"version": "3.0.1",
3+
"version": "3.1.0",
44
"description": "An utility that allows developers to declare InversifyJS bindings using ES2016 decorators",
55
"main": "lib/index.js",
66
"jsnext:main": "es/index.js",

src/decorator/provide.ts

+26-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,34 @@
1-
import { decorate, injectable } from "inversify";
1+
import { decorate, injectable, METADATA_KEY } from "inversify";
22
import { interfaces } from "inversify";
33

44
function provide(container: interfaces.Container) {
5-
6-
// function is named for testing
7-
return function _provide(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
5+
return function _provide(
6+
serviceIdentifier: interfaces.ServiceIdentifier<any>,
7+
force?: boolean
8+
) {
89
let bindingWhenOnSyntax = container.bind<any>(serviceIdentifier).to(<any>null);
910
return function (target: any) {
10-
decorate(injectable(), target);
11-
let binding: interfaces.Binding<any> = (<any>bindingWhenOnSyntax)._binding;
12-
binding.implementationType = target;
13-
return target;
11+
12+
const isAlreadyDecorated = Reflect.hasOwnMetadata(METADATA_KEY.PARAM_TYPES, target);
13+
const redecorateWithInject = force === true;
14+
15+
if (redecorateWithInject === true && isAlreadyDecorated === false) {
16+
decorate(injectable(), target);
17+
} else if (redecorateWithInject === true && isAlreadyDecorated === true) {
18+
// Do nothing
19+
} else {
20+
try {
21+
decorate(injectable(), target);
22+
} catch (e) {
23+
throw new Error(`${e.message} ` +
24+
"Please use @provide(ID, true) if you are trying to declare multiple bindings!");
25+
}
26+
}
27+
28+
let binding: interfaces.Binding<any> = (<any>bindingWhenOnSyntax)._binding;
29+
binding.implementationType = target;
30+
return target;
31+
1432
};
1533
};
1634
}

test/decorator/provide.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,38 @@ describe("provide", () => {
2929

3030
});
3131

32+
it("Should throw if applied more than once without force flag", () => {
33+
34+
const myContainer = new Container();
35+
const provide = _provide(myContainer);
36+
37+
function shouldThrow() {
38+
@provide("Ninja")
39+
@provide("SilentNinja")
40+
class Ninja {}
41+
return Ninja;
42+
}
43+
44+
expect(shouldThrow).to.throw(
45+
"Cannot apply @injectable decorator multiple times. " +
46+
"Please use @provide(ID, true) if you are trying to declare multiple bindings!");
47+
48+
});
49+
50+
it("Should work if applied more than once with force flag", () => {
51+
52+
const myContainer = new Container();
53+
const provide = _provide(myContainer);
54+
55+
function shouldThrow() {
56+
@provide("Ninja", true)
57+
@provide("SilentWarrior", true)
58+
class Ninja {}
59+
return Ninja;
60+
}
61+
62+
expect(shouldThrow).not.to.throw();
63+
64+
});
65+
3266
});

tslint.json

-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
"no-switch-case-fall-through": false,
3535
"no-trailing-whitespace": true,
3636
"no-unused-expression": true,
37-
"no-use-before-declare": true,
3837
"no-var-keyword": true,
3938
"object-literal-sort-keys": true,
4039
"one-line": [true,

0 commit comments

Comments
 (0)