@northern/di 1.0.3 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -23
- package/lib/index.d.ts +7 -0
- package/lib/index.js +42 -62
- package/package.json +15 -15
- package/.npmingore +0 -1
- package/di.sublime-project +0 -8
- package/di.sublime-workspace +0 -825
- package/src/index.js +0 -43
- package/src/index.test.js +0 -6
- package/yarn.lock +0 -3577
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DI
|
|
2
2
|
|
|
3
|
-
A simple Dependency Injection container for JavaScript.
|
|
3
|
+
A simple Dependency Injection container for JavaScript & TypeScript.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -20,48 +20,49 @@ import Container from '@northern/di'
|
|
|
20
20
|
|
|
21
21
|
const container = new Container()
|
|
22
22
|
````
|
|
23
|
-
With the newly instantiated container, you can start registering services. There are two ways you can register a service, the
|
|
23
|
+
With the newly instantiated container, you can start registering services. There are two ways you can register a service, either use the `service` method or you can use the `factory` method.
|
|
24
24
|
|
|
25
25
|
## Registering a service
|
|
26
26
|
|
|
27
27
|
With the `service` method a new service provider can be registered. The `service` method takes three parameters:
|
|
28
28
|
|
|
29
|
-
Container.service(name, provider[, lazy = false])
|
|
29
|
+
Container.service(name, provider[, lazy = true, overwrite = false])
|
|
30
30
|
|
|
31
|
-
The `name` is a string with the "name" of the service, e.g. `
|
|
31
|
+
The `name` is a string with the "name" of the service, e.g. `logger`. The `provider` is a function that, when called, "returns" the service instance. The `lazy` parameter specifies whether the service is "lazy" or not, more on that later and the `overwrite` parameter allows you to re-register a service if it already exists in the service registry of the container (handy during integration tests when you want to swap a service with a mock).
|
|
32
32
|
|
|
33
|
-
A "service" instance is only ever created once (as opposed to a factory, which returns a new instance each time).
|
|
33
|
+
A "service" instance is only ever created once (as opposed to a factory, which returns a new instance of the service each time).
|
|
34
|
+
|
|
35
|
+
Let's look at a simple service registration example:
|
|
34
36
|
````
|
|
35
37
|
class Logger {
|
|
36
38
|
info(message) {
|
|
37
|
-
console.
|
|
39
|
+
console.info(message)
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
container.service('logger', container => {
|
|
42
44
|
return new Logger()
|
|
43
45
|
})
|
|
44
|
-
|
|
45
46
|
````
|
|
46
|
-
It's that simple. We can now get the "logger" by using the `get` method on the container:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
logger.info("Hello DI")
|
|
47
|
+
It's that simple. We can now get the "logger" service by using the `get` method on the container:
|
|
48
|
+
````
|
|
49
|
+
const logger = container.get('logger')
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
logger.info("Hello DI")
|
|
52
|
+
````
|
|
53
|
+
Since the `Container` instance is passed into the service provider, it is possible to "wire" multiple services together (i.e. create service dependencies by having one service require another already registered service). A service provider can use already registered services and "inject" them into other services. E.g. if we register a service then we can pass an instance of the `logger` service into that other service:
|
|
53
54
|
````
|
|
54
55
|
class PaymentService {
|
|
55
56
|
constructor(logger) {
|
|
56
57
|
this.logger = logger
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
processPayment(paymentObject) {
|
|
60
61
|
this.logger.info("Starting payment process.")
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
container.service('
|
|
65
|
+
container.service('paymentService', container => {
|
|
65
66
|
const logger = container.get('logger')
|
|
66
67
|
|
|
67
68
|
const service = new PaymentService(logger)
|
|
@@ -69,20 +70,20 @@ container.service('payment', container => {
|
|
|
69
70
|
return service
|
|
70
71
|
})
|
|
71
72
|
|
|
72
|
-
const paymentService = container.get('
|
|
73
|
-
paymentService.
|
|
73
|
+
const paymentService = container.get('paymentService')
|
|
74
|
+
paymentService.processPayment({ ... })
|
|
74
75
|
````
|
|
75
76
|
|
|
76
77
|
### Lazy services
|
|
77
78
|
|
|
78
|
-
When a service is not "lazy" then the instance of that service will be created the moment the service is registered (i.e. when the `service` method is called). This is not
|
|
79
|
-
|
|
80
|
-
To create a lazy service, simply pass the 3rd parameter of the `service` method as `true`.
|
|
79
|
+
When a service is not "lazy" then the instance of that service will be created the moment the service is registered (i.e. when the `service` method is called). This is not usually desireable (and why `lazy` by default is `true`). E.g. if the dependency graph is large and not all services are always used, i.e. usage depends of the code path of the application, it might be better to instantiate a service on a need by need basis. This what a "lazy" service does; the instance is created the first time the service is requested rather than when the service was registered.
|
|
81
80
|
|
|
82
81
|
## Registering a factory
|
|
83
82
|
|
|
84
|
-
With the `factory` method a new factory provider can be created. A factory will always return a new instance each time it is requested from the container. The factory registration is the same as that of a service except that a factory cannot be lazy
|
|
83
|
+
With the `factory` method a new factory provider can be created. A factory will always return a new instance each time it is requested from the container. The factory registration is the same as that of a service except that a factory cannot be lazy (i.e. its always lazy).
|
|
84
|
+
|
|
85
|
+
The `factory` method only has three parameters:
|
|
85
86
|
|
|
86
|
-
Container.factory(name, provider)
|
|
87
|
+
Container.factory(name, provider[, overwrite = false])
|
|
87
88
|
|
|
88
|
-
That's it.
|
|
89
|
+
That's it. Have fun wiring!
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export default class Container {
|
|
2
|
+
private services;
|
|
3
|
+
constructor();
|
|
4
|
+
service(name: string, provider: Function | any, lazy?: boolean, overwrite?: boolean): void;
|
|
5
|
+
factory(name: string, provider: Function | any, overwrite?: boolean): void;
|
|
6
|
+
get(name: string): any;
|
|
7
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -1,66 +1,46 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
8
|
-
|
|
9
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
10
|
-
|
|
11
|
-
var Container = function () {
|
|
12
|
-
function Container() {
|
|
13
|
-
_classCallCheck(this, Container);
|
|
14
|
-
|
|
15
|
-
this.services = {};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
_createClass(Container, [{
|
|
19
|
-
key: "service",
|
|
20
|
-
value: function service(name, callback) {
|
|
21
|
-
var _this = this;
|
|
22
|
-
|
|
23
|
-
var lazy = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
24
|
-
|
|
25
|
-
if (this.services[name]) {
|
|
26
|
-
throw new Error("Service with name '" + name + "' already exists.");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (lazy) {
|
|
30
|
-
this.services[name] = function (container) {
|
|
31
|
-
return _this.services[name] = callback.call(null, container);
|
|
32
|
-
};
|
|
33
|
-
} else {
|
|
34
|
-
this.services[name] = callback.call(null, this);
|
|
35
|
-
}
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class Container {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.services = new Map();
|
|
36
6
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
7
|
+
service(name, provider, lazy = true, overwrite = false) {
|
|
8
|
+
if (this.services.has(name) && !overwrite) {
|
|
9
|
+
throw new Error(`Service with name '${name}' already exists.`);
|
|
10
|
+
}
|
|
11
|
+
if (provider instanceof Function) {
|
|
12
|
+
if (lazy) {
|
|
13
|
+
this.services.set(name, (container) => {
|
|
14
|
+
return this.services.set(name, provider.call(null, container));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.services.set(name, provider.call(null, this));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.services.set(name, provider);
|
|
23
|
+
}
|
|
45
24
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
var service = this.services[name];
|
|
54
|
-
|
|
55
|
-
if (service instanceof Function) {
|
|
56
|
-
return service.call(null, this);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return service;
|
|
25
|
+
factory(name, provider, overwrite = false) {
|
|
26
|
+
if (this.services.has(name) && !overwrite) {
|
|
27
|
+
throw new Error(`Service with name '${name}' already exists.`);
|
|
28
|
+
}
|
|
29
|
+
this.services.set(name, provider);
|
|
60
30
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
31
|
+
get(name) {
|
|
32
|
+
if (!this.services.has(name)) {
|
|
33
|
+
throw new Error(`Service with name '${name}' does not exist.`);
|
|
34
|
+
}
|
|
35
|
+
const service = this.services.get(name);
|
|
36
|
+
if (service instanceof Function) {
|
|
37
|
+
const result = service.call(null, this);
|
|
38
|
+
if ('get' in result) {
|
|
39
|
+
return result.get(name);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
return service;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = Container;
|
package/package.json
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@northern/di",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A simple Dependency Injection container for JavaScript",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"lib/**/*"
|
|
8
|
+
],
|
|
6
9
|
"scripts": {
|
|
10
|
+
"build": "tsc --removeComments",
|
|
7
11
|
"test": "jest",
|
|
8
|
-
"test:watch": "jest --watch",
|
|
9
|
-
"
|
|
12
|
+
"test:watch": "jest --watch --no-coverage",
|
|
13
|
+
"test:coverage": "jest --coverage",
|
|
14
|
+
"prepare": "npm run build",
|
|
15
|
+
"prepublishOnly": "npm test"
|
|
10
16
|
},
|
|
11
17
|
"repository": {
|
|
12
18
|
"type": "git",
|
|
@@ -24,18 +30,12 @@
|
|
|
24
30
|
"url": "https://github.com/northern/di.js/issues"
|
|
25
31
|
},
|
|
26
32
|
"homepage": "https://github.com/northern/di.js#readme",
|
|
27
|
-
"babel": {
|
|
28
|
-
"presets": [
|
|
29
|
-
"es2015"
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
"jest": {
|
|
33
|
-
"modulePathIgnorePatterns": ["node_mdules", "lib"]
|
|
34
|
-
},
|
|
35
33
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"jest": "^
|
|
34
|
+
"@types/jest": "^25.1.4",
|
|
35
|
+
"@types/uuid": "^7.0.0",
|
|
36
|
+
"jest": "^25.1.0",
|
|
37
|
+
"ts-jest": "^25.2.1",
|
|
38
|
+
"typescript": "^4.6.3",
|
|
39
|
+
"uuid": "^7.0.2"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/.npmingore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
src
|