@owja/ioc
Advanced tools
Comparing version 1.0.0-beta.1 to 1.0.0-beta.2
export { Container } from "./ioc/container"; | ||
export { createDecorator } from "./ioc/inject"; | ||
export { createDecorator, NOCACHE } from "./ioc/inject"; |
@@ -1,2 +0,2 @@ | ||
var t=function(t){this.t=t};t.prototype.inSingletonScope=function(){this.t.singleton=!0};var n=function(t){this.t=t};n.prototype.to=function(n){return this.t.object=n,new t(this.t)},n.prototype.toFactory=function(n){return this.t.factory=n,new t(this.t)},n.prototype.toValue=function(t){if(void 0===t)throw"cannot bind a value of type undefined";this.t.value=t};var i=function(){this.i={},this.o=[]};i.prototype.bind=function(t){return new n(this.u(t))},i.prototype.rebind=function(t){return this.remove(t).bind(t)},i.prototype.remove=function(t){if(void 0===this.i[t.toString()])throw t.toString()+" was never bound";return delete this.i[t.toString()],this},i.prototype.get=function(t){var n=this.i[t.toString()];if(void 0===n)throw"nothing bound to "+t.toString();var i=n.object,o=n.factory,r=n.value,u=n.cache,e=n.singleton,h=function(t){return e&&void 0!==u?u:e?(n.cache=t(),n.cache):t()};if(void 0!==r)return r;if(void 0!==i)return h(function(){return new i});if(void 0!==o)return h(function(){return o()});throw"nothing is bound to "+t.toString()},i.prototype.snapshot=function(){return this.o.push(Object.assign({},this.i)),this},i.prototype.restore=function(){return this.i=this.o.pop()||this.i,this},i.prototype.u=function(t){if("object"==typeof this.i[t.toString()])throw"object can only bound once: "+t.toString();return this.i[t.toString()]={singleton:!1},this.i[t.toString()]},exports.Container=i,exports.createDecorator=function(t){return function(n){return function(t,n){return function(i,o){Object.defineProperty(i,o,{get:function(){return n.get(t)},enumerable:!0})}}(n,t)}}; | ||
var t=function(t){this.t=t};t.prototype.inSingletonScope=function(){this.t.singleton=!0};var n=function(t){this.t=t};n.prototype.to=function(n){return this.t.object=n,new t(this.t)},n.prototype.toFactory=function(n){return this.t.factory=n,new t(this.t)},n.prototype.toValue=function(t){if(void 0===t)throw"cannot bind a value of type undefined";this.t.value=t};var i=function(){this.i={},this.o=[]};i.prototype.bind=function(t){return new n(this.u(t))},i.prototype.rebind=function(t){return this.remove(t).bind(t)},i.prototype.remove=function(t){if(void 0===this.i[t.toString()])throw t.toString()+" was never bound";return delete this.i[t.toString()],this},i.prototype.get=function(t){var n=this.i[t.toString()];if(void 0===n)throw"nothing bound to "+t.toString();var i=n.object,r=n.factory,o=n.value,e=n.cache,u=n.singleton,f=function(t){return u&&void 0!==e?e:u?(n.cache=t(),n.cache):t()};if(void 0!==o)return o;if(void 0!==i)return f(function(){return new i});if(void 0!==r)return f(function(){return r()});throw"nothing is bound to "+t.toString()},i.prototype.snapshot=function(){return this.o.push(Object.assign({},this.i)),this},i.prototype.restore=function(){return this.i=this.o.pop()||this.i,this},i.prototype.u=function(t){if("object"==typeof this.i[t.toString()])throw"object can only bound once: "+t.toString();return this.i[t.toString()]={singleton:!1},this.i[t.toString()]};var r=Symbol.for("NOCACHE");exports.Container=i,exports.createDecorator=function(t){return function(n){for(var i=[],o=arguments.length-1;o-- >0;)i[o]=arguments[o+1];return function(t,n,i){return function(o,e){Object.defineProperty(o,e,{get:function(){var o=n.get(t);return i&&i.indexOf(r)&&Object.defineProperty(this,e,{value:o,enumerable:!0}),o},configurable:!0,enumerable:!0})}}(n,t,i)}},exports.NOCACHE=r; | ||
//# sourceMappingURL=ioc.js.map |
import { Container } from "./container"; | ||
export declare function createDecorator(container: Container): (type: symbol) => (target: object, property: string) => void; | ||
export declare const NOCACHE: unique symbol; | ||
export declare function createDecorator(container: Container): (type: symbol, ...args: symbol[]) => (target: object, property: string) => void; |
{ | ||
"name": "@owja/ioc", | ||
"version": "1.0.0-beta.1", | ||
"version": "1.0.0-beta.2", | ||
"description": "dependency injection for javascript", | ||
@@ -30,5 +30,8 @@ "main": "dist/ioc.js", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/owja/ioc/issues" | ||
}, | ||
"homepage": "https://github.com/owja/ioc", | ||
"author": "Hauke Broer <info@owja.de>", | ||
"license": "CC-BY-4.0", | ||
"homepage": "https://github.com/owja/ioc", | ||
"devDependencies": { | ||
@@ -35,0 +38,0 @@ "@types/jest": "^24.0.13", |
168
README.md
@@ -15,6 +15,132 @@ ![OWJA! IoC](resources/owja-ioc-logo.png) | ||
### Usage | ||
## The Container API | ||
##### Step 1 - Installing the OWJA! IoC library | ||
### Creating a container | ||
The container is the place where all dependencies get bound to. We can have | ||
multiple containers in our project in parallel. | ||
```ts | ||
import {Container} from "@owja/ioc"; | ||
const container = new Container(); | ||
``` | ||
### Binding | ||
#### Binding a class | ||
This is the default way to bind a dependency. The class will get instantiated when the | ||
dependency gets resolved. | ||
```ts | ||
container.bind<ServiceInterface>(symbol).to(Service); | ||
``` | ||
#### Binding a class in singleton scope | ||
This will create only one instance of `Service` | ||
```ts | ||
container.bind<ServiceInterface>(symbol).to(Service).inSingletonScope(); | ||
``` | ||
#### Binding a factory | ||
Factories are functions which will get called when the dependency gets resolved | ||
```ts | ||
container.bind<ServiceInterface>(symbol).toFactory(() => new Service()); | ||
container.bind<string>(symbol).toFactory(() => "just a string"); | ||
``` | ||
A factory can configured for singleton scope too. This way will only executed once. | ||
```ts | ||
container.bind<ServiceInterface>(symbol).toFactory(() => new Service()).inSingletonScope(); | ||
``` | ||
#### Binding a value | ||
This is always like singleton scope, but it should be avoid to instantiate | ||
dependencies here. If they are circular dependencies, they will fail. | ||
```ts | ||
container.bind<ServiceInterface>(symbol).toValue(new Service()); | ||
container.bind<string>(symbol).toValue("just a string"); | ||
container.bind<() => string>(symbol).toValue(() => "i am a function"); | ||
``` | ||
### Rebinding | ||
This is the way how we can rebind a dependency while **unit tests**. We should not need to | ||
rebind in production code. | ||
```ts | ||
container.rebind<ServiceMock>(symbol).toValue(new ServiceMock()); | ||
``` | ||
### Removing | ||
Normally this function is not used in production code. This will remove the | ||
dependency from the container. | ||
```ts | ||
container.remove(symbol); | ||
``` | ||
### Getting a dependency | ||
Getting dependencies without `inject` decorators are only meant for **unit tests**. This is also | ||
the internal way the `inject` decorator gets the dependency it has to resolve. | ||
```ts | ||
container.get<Interface>(symbol); | ||
``` | ||
### Snapshot & Restore | ||
This creates a snapshot of the bound dependencies. After this we can rebind dependencies | ||
and can restore it back to its old state after we made some **unit tests**. | ||
```ts | ||
container.snapshot(); | ||
``` | ||
```ts | ||
container.restore(); | ||
``` | ||
## The `inject` Decorator | ||
We have to create a `inject` decorator for each container. | ||
```ts | ||
import {createDecorator} from "@owja/ioc"; | ||
export const inject = createDecorator(container); | ||
``` | ||
This decorator is needed to resolve our dependencies. | ||
```ts | ||
class Example { | ||
@inject(symbol) | ||
readonly service!: Interface; | ||
} | ||
``` | ||
## The `symbol` | ||
Symbols are used to identify our dependencies. A good practice is to keep them in one place. | ||
```ts | ||
export const TYPE = { | ||
"Service" = Symbol.for("Service"), | ||
// [...] | ||
} | ||
``` | ||
## Usage | ||
#### Step 1 - Installing the OWJA! IoC library | ||
```bash | ||
@@ -24,3 +150,3 @@ npm install --save-dev @owja/ioc | ||
##### Step 2 - Create symbols for our dependencies | ||
#### Step 2 - Create symbols for our dependencies | ||
@@ -35,3 +161,3 @@ Now we create the folder ***services*** and add the new file ***services/types.ts***: | ||
##### Step 3 - Creating a container | ||
#### Step 3 - Creating a container | ||
@@ -57,3 +183,3 @@ Next we need a container to bind our dependencies to. Let's create the file ***services/container.ts*** | ||
##### Step 4 - Injecting dependencies | ||
#### Step 4 - Injecting dependencies | ||
@@ -65,2 +191,3 @@ Lets create a ***example.ts*** file in our source root: | ||
import {IMyService} from "./service/my-service"; | ||
import {IMyOtherService} from "./service/my-other-service"; | ||
@@ -83,4 +210,25 @@ class Example { | ||
### Unit testing with IoC | ||
The dependencies (services) will injected on the first call. This means if you rebind the service after | ||
accessing the properties of the Example class, it will not resolve the new service. If you want a new | ||
service each time you call `example.myService` you have to add the `NOCACHE` tag: | ||
```ts | ||
import {container, TYPE, inject} from "./services/container"; | ||
import {NOCACHE} from "@owja/ioc"; | ||
// [...] | ||
class Example { | ||
@inject(TYPE.MyService, NOCACHE) | ||
readonly myService!: IMyService; | ||
@inject(TYPE.MyOtherSerice, NOCACHE) | ||
readonly myOtherService!: IMyOtherService; | ||
} | ||
// [...] | ||
``` | ||
## Unit testing with IoC | ||
We can snapshot and restore a container for unit testing. | ||
@@ -90,2 +238,4 @@ We are able to make multiple snapshots in a row too. | ||
```ts | ||
import {container, TYPE} from "./services/container"; | ||
beforeEach(() => { | ||
@@ -105,3 +255,3 @@ container.snapshot(); | ||
### Development | ||
## Development | ||
@@ -111,3 +261,3 @@ We are working on the first stable release. Current state of development can be seen in our | ||
### Inspiration | ||
## Inspiration | ||
@@ -122,3 +272,3 @@ This library is highly inspired by [InversifyJS](https://github.com/inversify/InversifyJS) | ||
### License | ||
## License | ||
@@ -125,0 +275,0 @@ License under [Creative Commons Attribution 4.0 International](https://spdx.org/licenses/CC-BY-4.0.html) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
43930
57
0
268