@timesplinter/pimple 2.0.0 → 2.1.0
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/lib/cjs/pimple.d.ts +10 -14
- package/lib/cjs/pimple.js +46 -15
- package/lib/cjs/pimple.js.map +1 -1
- package/lib/esm/pimple.d.ts +10 -14
- package/lib/esm/pimple.js +46 -15
- package/lib/esm/pimple.js.map +1 -1
- package/package.json +13 -5
- package/.babelrc +0 -6
- package/.github/workflows/publish.yml +0 -18
- package/.github/workflows/test.yml +0 -13
- package/jest.config.ts +0 -19
- package/src/container.ts +0 -8
- package/src/index.ts +0 -8
- package/src/pimple.ts +0 -171
- package/src/serviceProvider.ts +0 -9
- package/tests/pimple.spec.ts +0 -194
- package/tsconfig-cjs.json +0 -8
- package/tsconfig.json +0 -19
package/lib/cjs/pimple.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type ProviderDeclaration<T> = ServiceProviderFunction<T> | ServiceProvider<T>;
|
|
|
6
6
|
type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
|
|
7
7
|
type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
|
|
8
8
|
type PlainServiceDefinition<S> = S extends Function ? () => S : S;
|
|
9
|
-
type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S
|
|
9
|
+
type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S>;
|
|
10
10
|
type ServiceMap<T> = {
|
|
11
11
|
[key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]>;
|
|
12
12
|
};
|
|
@@ -17,28 +17,24 @@ type ServiceMap<T> = {
|
|
|
17
17
|
* @copyright 2016 SerafimArts <nesk@xakep.ru>
|
|
18
18
|
* @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
|
|
19
19
|
* @license LGPL
|
|
20
|
-
* @version
|
|
20
|
+
* @version 2.1.0
|
|
21
21
|
*/
|
|
22
22
|
export default class Pimple<T> implements Container<T> {
|
|
23
|
-
/**
|
|
24
|
-
* @type {string}
|
|
25
|
-
*/
|
|
26
23
|
static get VERSION(): string;
|
|
27
|
-
/**
|
|
28
|
-
* @type {{}}
|
|
29
|
-
* @private
|
|
30
|
-
*/
|
|
31
24
|
private _definitions;
|
|
32
|
-
/**
|
|
33
|
-
* @type {{}}
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
25
|
private _raw;
|
|
26
|
+
private _resolved;
|
|
27
|
+
private _resolving;
|
|
37
28
|
constructor(services?: Partial<ServiceMap<T>>);
|
|
38
29
|
/**
|
|
39
|
-
* Define a service
|
|
30
|
+
* Define a service (first-time registration only)
|
|
40
31
|
*/
|
|
41
32
|
set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
|
|
33
|
+
/**
|
|
34
|
+
* Replace an existing service definition before it has been resolved
|
|
35
|
+
*/
|
|
36
|
+
replace<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
|
|
37
|
+
private define;
|
|
42
38
|
/**
|
|
43
39
|
* Register a factory
|
|
44
40
|
*/
|
package/lib/cjs/pimple.js
CHANGED
|
@@ -15,33 +15,49 @@ const reservedProperties = [
|
|
|
15
15
|
* @copyright 2016 SerafimArts <nesk@xakep.ru>
|
|
16
16
|
* @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
|
|
17
17
|
* @license LGPL
|
|
18
|
-
* @version
|
|
18
|
+
* @version 2.1.0
|
|
19
19
|
*/
|
|
20
20
|
class Pimple {
|
|
21
|
-
|
|
22
|
-
* @type {string}
|
|
23
|
-
*/
|
|
24
|
-
static get VERSION() { return '3.0.0'; }
|
|
21
|
+
static get VERSION() { return '2.1.0'; }
|
|
25
22
|
constructor(services = {}) {
|
|
26
|
-
/**
|
|
27
|
-
* @type {{}}
|
|
28
|
-
* @private
|
|
29
|
-
*/
|
|
30
23
|
this._definitions = {};
|
|
31
|
-
/**
|
|
32
|
-
* @type {{}}
|
|
33
|
-
* @private
|
|
34
|
-
*/
|
|
35
24
|
this._raw = {};
|
|
25
|
+
this._resolved = new Map();
|
|
26
|
+
this._resolving = [];
|
|
36
27
|
Object.keys(services).forEach((service) => {
|
|
37
28
|
const serviceKey = service;
|
|
38
29
|
this.set(serviceKey, services[serviceKey]);
|
|
39
30
|
}, this);
|
|
40
31
|
}
|
|
41
32
|
/**
|
|
42
|
-
* Define a service
|
|
33
|
+
* Define a service (first-time registration only)
|
|
43
34
|
*/
|
|
44
35
|
set(name, service) {
|
|
36
|
+
if (this.has(name)) {
|
|
37
|
+
throw new Error(`Service "${name.toString()}" is already defined. Use replace() to overwrite it.`);
|
|
38
|
+
}
|
|
39
|
+
return this.define(name, service);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Replace an existing service definition before it has been resolved
|
|
43
|
+
*/
|
|
44
|
+
replace(name, service) {
|
|
45
|
+
var _a;
|
|
46
|
+
if (!this.has(name)) {
|
|
47
|
+
throw new RangeError(`Service "${name.toString()}" is not defined in the container.`);
|
|
48
|
+
}
|
|
49
|
+
if (this._resolved.has(name)) {
|
|
50
|
+
const trace = [];
|
|
51
|
+
let current = name;
|
|
52
|
+
while (current !== null) {
|
|
53
|
+
trace.unshift(current.toString());
|
|
54
|
+
current = (_a = this._resolved.get(current)) !== null && _a !== void 0 ? _a : null;
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Service "${name.toString()}" has already been resolved and cannot be replaced. Resolution trace: ${trace.join(' → ')}`);
|
|
57
|
+
}
|
|
58
|
+
return this.define(name, service);
|
|
59
|
+
}
|
|
60
|
+
define(name, service) {
|
|
45
61
|
this._raw[name] = service;
|
|
46
62
|
this._definitions[name] = service instanceof Function ?
|
|
47
63
|
(function () {
|
|
@@ -55,6 +71,7 @@ class Pimple {
|
|
|
55
71
|
}()) : service;
|
|
56
72
|
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
57
73
|
Object.defineProperty(this, name, {
|
|
74
|
+
configurable: true,
|
|
58
75
|
get: () => {
|
|
59
76
|
return this.get(name);
|
|
60
77
|
}
|
|
@@ -70,6 +87,7 @@ class Pimple {
|
|
|
70
87
|
this._definitions[name] = callback;
|
|
71
88
|
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
72
89
|
Object.defineProperty(this, name, {
|
|
90
|
+
configurable: true,
|
|
73
91
|
get: () => {
|
|
74
92
|
return this.get(name);
|
|
75
93
|
}
|
|
@@ -82,7 +100,20 @@ class Pimple {
|
|
|
82
100
|
*/
|
|
83
101
|
get(name) {
|
|
84
102
|
if (this._definitions[name] instanceof Function) {
|
|
85
|
-
|
|
103
|
+
const firstResolution = !this._resolved.has(name);
|
|
104
|
+
if (firstResolution) {
|
|
105
|
+
const parent = this._resolving.length > 0 ? this._resolving[this._resolving.length - 1] : null;
|
|
106
|
+
this._resolved.set(name, parent);
|
|
107
|
+
this._resolving.push(name);
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
return this._definitions[name](this);
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
if (firstResolution) {
|
|
114
|
+
this._resolving.pop();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
86
117
|
}
|
|
87
118
|
return this._definitions[name];
|
|
88
119
|
}
|
package/lib/cjs/pimple.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAcb;;GAEG;AACH,MAAM,kBAAkB,GAAa;IACjC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IAC9B,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa;IAC7C,WAAW;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAqB,MAAM;IAEvB
|
|
1
|
+
{"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAcb;;GAEG;AACH,MAAM,kBAAkB,GAAa;IACjC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IAC9B,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa;IAC7C,WAAW;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAqB,MAAM;IAEvB,MAAM,KAAK,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC,CAAC;IAUxC,YAAY,WAAmC,EAAE;QARzC,iBAAY,GAA2B,EAAE,CAAC;QAE1C,SAAI,GAA2B,EAAE,CAAC;QAElC,cAAS,GAAmE,IAAI,GAAG,EAAE,CAAC;QAEtF,eAAU,GAAiC,EAAE,CAAC;QAGlD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACtC,MAAM,UAAU,GAAG,OAAwB,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAA2C,CAAC,CAAC;QACzF,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO,EAAE,OAAkC;QAE3E,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,sDAAsD,CAAC,CAAC;SACtG;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACI,OAAO,CAA0B,IAAO,EAAE,OAAkC;;QAE/E,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,UAAU,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,oCAAoC,CAAC,CAAC;SACzF;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC1B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,OAAO,GAAoC,IAAI,CAAC;YACpD,OAAO,OAAO,KAAK,IAAI,EAAE;gBACrB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAClC,OAAO,GAAG,MAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,mCAAI,IAAI,CAAC;aACjD;YACD,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,yEAAyE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SAC5I;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAEO,MAAM,CAA0B,IAAO,EAAE,OAAkC;QAE/E,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QAE1B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,OAAO,YAAY,QAAQ,CAAC,CAAC;YACnD,CAAC;gBACG,IAAI,MAAW,CAAC;gBAChB,OAAO,CAAC,MAAiB,EAAE,EAAE;oBACzB,IAAI,MAAM,KAAK,SAAS,EAAE;wBACtB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;qBAC5B;oBACD,OAAO,MAAM,CAAC;gBAClB,CAAC,CAAC;YACN,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAEnB,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;YACpD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE;gBAC9B,YAAY,EAAE,IAAI;gBAClB,GAAG,EAAE,GAAG,EAAE;oBACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;aACJ,CAAC,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACI,OAAO,CAA0B,IAAO,EAAE,QAAmC;QAChF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAW,QAAQ,CAAC;QACnC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;QAEnC,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;YACpD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE;gBAC9B,YAAY,EAAE,IAAI;gBAClB,GAAG,EAAE,GAAG,EAAE;oBACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;aACJ,CAAC,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,QAAQ,EAAE;YAC7C,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,eAAe,EAAE;gBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC/F,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC9B;YACD,IAAI;gBACA,OAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAoC,CAAC,IAAI,CAAC,CAAC;aAC5E;oBAAS;gBACN,IAAI,eAAe,EAAE;oBACjB,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;iBACzB;aACJ;SACJ;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAS,CAAC;IAC3C,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,OAAO,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,OAAO,CAAqB,IAAO;QACtC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC;IACtB,CAAC;IAED;;OAEG;IACI,MAAM,CAA0B,WAAc,EAAE,OAAiB;QACpE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE;YACjC,MAAM,IAAI,UAAU,CAAC,oBAAoB,WAAW,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;SACjG;QAED,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAEzC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,SAAoB,EAAE,EAAE;YAC7D,IAAI,GAAG,YAAY,QAAQ,EAAE;gBACzB,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;aACxB;YACD,OAAO,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACnC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAA+B,CAAC;IACzD,CAAC;IAED;;OAEG;IACI,QAAQ,CAAC,QAAgC;QAC5C,IAAI,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,YAAY,QAAQ,EAAE;YACnF,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;SAC3B;aAAM,IAAI,QAAQ,YAAY,QAAQ,EAAE;YACrC,QAAQ,CAAC,IAAI,CAAC,CAAC;SAClB;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,yBAAyB,CAAC,MAAW;QACzC,OAAO,UAAU,IAAI,MAAM,CAAC;IAChC,CAAC;CACJ;AA/KD,yBA+KC"}
|
package/lib/esm/pimple.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type ProviderDeclaration<T> = ServiceProviderFunction<T> | ServiceProvider<T>;
|
|
|
6
6
|
type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
|
|
7
7
|
type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
|
|
8
8
|
type PlainServiceDefinition<S> = S extends Function ? () => S : S;
|
|
9
|
-
type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S
|
|
9
|
+
type ServiceDefinition<T, S> = PlainServiceDefinition<S> | LazyServiceDefinition<T, S> | ProtectedServiceDefinition<T, S>;
|
|
10
10
|
type ServiceMap<T> = {
|
|
11
11
|
[key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]>;
|
|
12
12
|
};
|
|
@@ -17,28 +17,24 @@ type ServiceMap<T> = {
|
|
|
17
17
|
* @copyright 2016 SerafimArts <nesk@xakep.ru>
|
|
18
18
|
* @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
|
|
19
19
|
* @license LGPL
|
|
20
|
-
* @version
|
|
20
|
+
* @version 2.1.0
|
|
21
21
|
*/
|
|
22
22
|
export default class Pimple<T> implements Container<T> {
|
|
23
|
-
/**
|
|
24
|
-
* @type {string}
|
|
25
|
-
*/
|
|
26
23
|
static get VERSION(): string;
|
|
27
|
-
/**
|
|
28
|
-
* @type {{}}
|
|
29
|
-
* @private
|
|
30
|
-
*/
|
|
31
24
|
private _definitions;
|
|
32
|
-
/**
|
|
33
|
-
* @type {{}}
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
25
|
private _raw;
|
|
26
|
+
private _resolved;
|
|
27
|
+
private _resolving;
|
|
37
28
|
constructor(services?: Partial<ServiceMap<T>>);
|
|
38
29
|
/**
|
|
39
|
-
* Define a service
|
|
30
|
+
* Define a service (first-time registration only)
|
|
40
31
|
*/
|
|
41
32
|
set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
|
|
33
|
+
/**
|
|
34
|
+
* Replace an existing service definition before it has been resolved
|
|
35
|
+
*/
|
|
36
|
+
replace<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T, T[K]>): Pimple<T>;
|
|
37
|
+
private define;
|
|
42
38
|
/**
|
|
43
39
|
* Register a factory
|
|
44
40
|
*/
|
package/lib/esm/pimple.js
CHANGED
|
@@ -14,33 +14,49 @@ const reservedProperties = [
|
|
|
14
14
|
* @copyright 2016 SerafimArts <nesk@xakep.ru>
|
|
15
15
|
* @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
|
|
16
16
|
* @license LGPL
|
|
17
|
-
* @version
|
|
17
|
+
* @version 2.1.0
|
|
18
18
|
*/
|
|
19
19
|
export default class Pimple {
|
|
20
|
-
|
|
21
|
-
* @type {string}
|
|
22
|
-
*/
|
|
23
|
-
static get VERSION() { return '3.0.0'; }
|
|
20
|
+
static get VERSION() { return '2.1.0'; }
|
|
24
21
|
constructor(services = {}) {
|
|
25
|
-
/**
|
|
26
|
-
* @type {{}}
|
|
27
|
-
* @private
|
|
28
|
-
*/
|
|
29
22
|
this._definitions = {};
|
|
30
|
-
/**
|
|
31
|
-
* @type {{}}
|
|
32
|
-
* @private
|
|
33
|
-
*/
|
|
34
23
|
this._raw = {};
|
|
24
|
+
this._resolved = new Map();
|
|
25
|
+
this._resolving = [];
|
|
35
26
|
Object.keys(services).forEach((service) => {
|
|
36
27
|
const serviceKey = service;
|
|
37
28
|
this.set(serviceKey, services[serviceKey]);
|
|
38
29
|
}, this);
|
|
39
30
|
}
|
|
40
31
|
/**
|
|
41
|
-
* Define a service
|
|
32
|
+
* Define a service (first-time registration only)
|
|
42
33
|
*/
|
|
43
34
|
set(name, service) {
|
|
35
|
+
if (this.has(name)) {
|
|
36
|
+
throw new Error(`Service "${name.toString()}" is already defined. Use replace() to overwrite it.`);
|
|
37
|
+
}
|
|
38
|
+
return this.define(name, service);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Replace an existing service definition before it has been resolved
|
|
42
|
+
*/
|
|
43
|
+
replace(name, service) {
|
|
44
|
+
var _a;
|
|
45
|
+
if (!this.has(name)) {
|
|
46
|
+
throw new RangeError(`Service "${name.toString()}" is not defined in the container.`);
|
|
47
|
+
}
|
|
48
|
+
if (this._resolved.has(name)) {
|
|
49
|
+
const trace = [];
|
|
50
|
+
let current = name;
|
|
51
|
+
while (current !== null) {
|
|
52
|
+
trace.unshift(current.toString());
|
|
53
|
+
current = (_a = this._resolved.get(current)) !== null && _a !== void 0 ? _a : null;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`Service "${name.toString()}" has already been resolved and cannot be replaced. Resolution trace: ${trace.join(' → ')}`);
|
|
56
|
+
}
|
|
57
|
+
return this.define(name, service);
|
|
58
|
+
}
|
|
59
|
+
define(name, service) {
|
|
44
60
|
this._raw[name] = service;
|
|
45
61
|
this._definitions[name] = service instanceof Function ?
|
|
46
62
|
(function () {
|
|
@@ -54,6 +70,7 @@ export default class Pimple {
|
|
|
54
70
|
}()) : service;
|
|
55
71
|
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
56
72
|
Object.defineProperty(this, name, {
|
|
73
|
+
configurable: true,
|
|
57
74
|
get: () => {
|
|
58
75
|
return this.get(name);
|
|
59
76
|
}
|
|
@@ -69,6 +86,7 @@ export default class Pimple {
|
|
|
69
86
|
this._definitions[name] = callback;
|
|
70
87
|
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
71
88
|
Object.defineProperty(this, name, {
|
|
89
|
+
configurable: true,
|
|
72
90
|
get: () => {
|
|
73
91
|
return this.get(name);
|
|
74
92
|
}
|
|
@@ -81,7 +99,20 @@ export default class Pimple {
|
|
|
81
99
|
*/
|
|
82
100
|
get(name) {
|
|
83
101
|
if (this._definitions[name] instanceof Function) {
|
|
84
|
-
|
|
102
|
+
const firstResolution = !this._resolved.has(name);
|
|
103
|
+
if (firstResolution) {
|
|
104
|
+
const parent = this._resolving.length > 0 ? this._resolving[this._resolving.length - 1] : null;
|
|
105
|
+
this._resolved.set(name, parent);
|
|
106
|
+
this._resolving.push(name);
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
return this._definitions[name](this);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
if (firstResolution) {
|
|
113
|
+
this._resolving.pop();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
85
116
|
}
|
|
86
117
|
return this._definitions[name];
|
|
87
118
|
}
|
package/lib/esm/pimple.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAcb;;GAEG;AACH,MAAM,kBAAkB,GAAa;IACjC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IAC9B,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa;IAC7C,WAAW;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IAEvB
|
|
1
|
+
{"version":3,"file":"pimple.js","sourceRoot":"","sources":["../../src/pimple.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAcb;;GAEG;AACH,MAAM,kBAAkB,GAAa;IACjC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IAC9B,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa;IAC7C,WAAW;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IAEvB,MAAM,KAAK,OAAO,KAAK,OAAO,OAAO,CAAC,CAAC,CAAC;IAUxC,YAAY,WAAmC,EAAE;QARzC,iBAAY,GAA2B,EAAE,CAAC;QAE1C,SAAI,GAA2B,EAAE,CAAC;QAElC,cAAS,GAAmE,IAAI,GAAG,EAAE,CAAC;QAEtF,eAAU,GAAiC,EAAE,CAAC;QAGlD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YACtC,MAAM,UAAU,GAAG,OAAwB,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAA2C,CAAC,CAAC;QACzF,CAAC,EAAE,IAAI,CAAC,CAAC;IACb,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO,EAAE,OAAkC;QAE3E,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAChB,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,sDAAsD,CAAC,CAAC;SACtG;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED;;OAEG;IACI,OAAO,CAA0B,IAAO,EAAE,OAAkC;;QAE/E,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,UAAU,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,oCAAoC,CAAC,CAAC;SACzF;QACD,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC1B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,OAAO,GAAoC,IAAI,CAAC;YACpD,OAAO,OAAO,KAAK,IAAI,EAAE;gBACrB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;gBAClC,OAAO,GAAG,MAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,mCAAI,IAAI,CAAC;aACjD;YACD,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,yEAAyE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SAC5I;QAED,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAEO,MAAM,CAA0B,IAAO,EAAE,OAAkC;QAE/E,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;QAE1B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,OAAO,YAAY,QAAQ,CAAC,CAAC;YACnD,CAAC;gBACG,IAAI,MAAW,CAAC;gBAChB,OAAO,CAAC,MAAiB,EAAE,EAAE;oBACzB,IAAI,MAAM,KAAK,SAAS,EAAE;wBACtB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;qBAC5B;oBACD,OAAO,MAAM,CAAC;gBAClB,CAAC,CAAC;YACN,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAEnB,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;YACpD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE;gBAC9B,YAAY,EAAE,IAAI;gBAClB,GAAG,EAAE,GAAG,EAAE;oBACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;aACJ,CAAC,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACI,OAAO,CAA0B,IAAO,EAAE,QAAmC;QAChF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAW,QAAQ,CAAC;QACnC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;QAEnC,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE;YACpD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE;gBAC9B,YAAY,EAAE,IAAI;gBAClB,GAAG,EAAE,GAAG,EAAE;oBACN,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,CAAC;aACJ,CAAC,CAAC;SACN;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,QAAQ,EAAE;YAC7C,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,eAAe,EAAE;gBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC/F,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC9B;YACD,IAAI;gBACA,OAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAoC,CAAC,IAAI,CAAC,CAAC;aAC5E;oBAAS;gBACN,IAAI,eAAe,EAAE;oBACjB,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;iBACzB;aACJ;SACJ;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAS,CAAC;IAC3C,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,OAAO,IAAI,IAAI,IAAI,CAAC,YAAY,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,OAAO,CAAqB,IAAO;QACtC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC;IACtB,CAAC;IAED;;OAEG;IACI,MAAM,CAA0B,WAAc,EAAE,OAAiB;QACpE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE;YACjC,MAAM,IAAI,UAAU,CAAC,oBAAoB,WAAW,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;SACjG;QAED,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAEzC,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,SAAoB,EAAE,EAAE;YAC7D,IAAI,GAAG,YAAY,QAAQ,EAAE;gBACzB,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;aACxB;YACD,OAAO,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACnC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACI,GAAG,CAA0B,IAAO;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAA+B,CAAC;IACzD,CAAC;IAED;;OAEG;IACI,QAAQ,CAAC,QAAgC;QAC5C,IAAI,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,YAAY,QAAQ,EAAE;YACnF,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;SAC3B;aAAM,IAAI,QAAQ,YAAY,QAAQ,EAAE;YACrC,QAAQ,CAAC,IAAI,CAAC,CAAC;SAClB;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,yBAAyB,CAAC,MAAW;QACzC,OAAO,UAAU,IAAI,MAAM,CAAC;IAChC,CAAC;CACJ"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timesplinter/pimple",
|
|
3
3
|
"license": "LGPL-3.0-or-later",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"module": "./lib/esm/index.js",
|
|
6
6
|
"main": "./lib/cjs/index.js",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/TiMESPLiNTER/pimple-js.git"
|
|
10
|
+
},
|
|
7
11
|
"scripts": {
|
|
8
12
|
"test": "jest",
|
|
9
13
|
"test:cov": "jest --collect-coverage",
|
|
14
|
+
"typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig-cjs.json",
|
|
10
15
|
"transpile": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json",
|
|
11
|
-
"
|
|
16
|
+
"prepublishOnly": "npm run transpile"
|
|
12
17
|
},
|
|
18
|
+
"files": [
|
|
19
|
+
"lib/"
|
|
20
|
+
],
|
|
13
21
|
"keywords": [],
|
|
14
22
|
"author": "Pascal Münst <dev@timesplinter.ch>",
|
|
15
23
|
"description": "A simple dependency-injection container written in TypeScript based on PHP's Pimple",
|
|
@@ -17,10 +25,10 @@
|
|
|
17
25
|
"@babel/core": "^7.23.9",
|
|
18
26
|
"@babel/preset-env": "^7.23.9",
|
|
19
27
|
"@babel/preset-typescript": "^7.23.3",
|
|
20
|
-
"@types/jest": "^29.5.
|
|
28
|
+
"@types/jest": "^29.5.14",
|
|
21
29
|
"babel-jest": "^29.7.0",
|
|
22
30
|
"jest": "^29.7.0",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
31
|
+
"ts-node": "^10.9.2",
|
|
32
|
+
"typescript": "^4.9.5"
|
|
25
33
|
}
|
|
26
34
|
}
|
package/.babelrc
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
name: Publish Package to npmjs
|
|
2
|
-
on:
|
|
3
|
-
release:
|
|
4
|
-
types: [published]
|
|
5
|
-
jobs:
|
|
6
|
-
build:
|
|
7
|
-
runs-on: ubuntu-latest
|
|
8
|
-
steps:
|
|
9
|
-
- uses: actions/checkout@v4
|
|
10
|
-
# Setup .npmrc file to publish to npm
|
|
11
|
-
- uses: actions/setup-node@v3
|
|
12
|
-
with:
|
|
13
|
-
node-version: '20.x'
|
|
14
|
-
registry-url: 'https://registry.npmjs.org'
|
|
15
|
-
- run: npm ci
|
|
16
|
-
- run: npm publish --access public
|
|
17
|
-
env:
|
|
18
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/jest.config.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type {Config} from 'jest';
|
|
2
|
-
|
|
3
|
-
const config: Config = {
|
|
4
|
-
coverageDirectory: "./build/coverage",
|
|
5
|
-
coverageReporters: ['text', 'html', 'lcov'],
|
|
6
|
-
coverageThreshold: {
|
|
7
|
-
global: {
|
|
8
|
-
branches: 80,
|
|
9
|
-
functions: 88,
|
|
10
|
-
lines: 93,
|
|
11
|
-
statements: 93
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
collectCoverageFrom: [
|
|
15
|
-
"src/**/*"
|
|
16
|
-
],
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default config;
|
package/src/container.ts
DELETED
package/src/index.ts
DELETED
package/src/pimple.ts
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import Container, {ServiceKey} from "./container";
|
|
4
|
-
import ServiceProvider from "./serviceProvider";
|
|
5
|
-
|
|
6
|
-
/** Declaration types */
|
|
7
|
-
type ServiceProviderFunction<T> = (container: Pimple<T>) => void;
|
|
8
|
-
type ProviderDeclaration<T> = ServiceProviderFunction<T>|ServiceProvider<T>;
|
|
9
|
-
type LazyServiceDefinition<T, S> = (container: Pimple<T>) => S;
|
|
10
|
-
type ProtectedServiceDefinition<T, S> = () => LazyServiceDefinition<T, S>;
|
|
11
|
-
type PlainServiceDefinition<S> = S extends Function ? () => S : S; // If a function, it needs to be wrapped/protected
|
|
12
|
-
type ServiceDefinition<T, S> = PlainServiceDefinition<S>|LazyServiceDefinition<T, S>|ProtectedServiceDefinition<T, S>|(S extends Function ? () => S : S);
|
|
13
|
-
type ServiceMap<T> = { [key in ServiceKey<T>]: ServiceDefinition<T, T[ServiceKey<T>]> };
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Reserved names of properties
|
|
17
|
-
*/
|
|
18
|
-
const reservedProperties: string[] = [
|
|
19
|
-
'get', 'set', 'factory', 'raw',
|
|
20
|
-
'protect', 'share', 'toString', 'constructor',
|
|
21
|
-
'prototype'
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Pimple dependency injection container
|
|
26
|
-
*
|
|
27
|
-
* @copyright 2011 M.PARAISO <mparaiso@online.fr>
|
|
28
|
-
* @copyright 2016 SerafimArts <nesk@xakep.ru>
|
|
29
|
-
* @copyright 2021 TiMESPLiNTER <dev@timesplinter.ch>
|
|
30
|
-
* @license LGPL
|
|
31
|
-
* @version 3.0.0
|
|
32
|
-
*/
|
|
33
|
-
export default class Pimple<T> implements Container<T>
|
|
34
|
-
{
|
|
35
|
-
/**
|
|
36
|
-
* @type {string}
|
|
37
|
-
*/
|
|
38
|
-
static get VERSION() { return '3.0.0'; }
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @type {{}}
|
|
42
|
-
* @private
|
|
43
|
-
*/
|
|
44
|
-
private _definitions: Partial<ServiceMap<T>> = {};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @type {{}}
|
|
48
|
-
* @private
|
|
49
|
-
*/
|
|
50
|
-
private _raw: Partial<ServiceMap<T>> = {};
|
|
51
|
-
|
|
52
|
-
constructor(services: Partial<ServiceMap<T>> = {}) {
|
|
53
|
-
Object.keys(services).forEach((service) => {
|
|
54
|
-
const serviceKey = service as ServiceKey<T>;
|
|
55
|
-
this.set(serviceKey, services[serviceKey] as ServiceDefinition<T, T[ServiceKey<T>]>);
|
|
56
|
-
}, this);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Define a service
|
|
61
|
-
*/
|
|
62
|
-
public set<K extends ServiceKey<T>>(name: K, service: ServiceDefinition<T,T[K]>): Pimple<T>
|
|
63
|
-
{
|
|
64
|
-
this._raw[name] = service;
|
|
65
|
-
|
|
66
|
-
this._definitions[name] = service instanceof Function ?
|
|
67
|
-
(function () {
|
|
68
|
-
let cached: any;
|
|
69
|
-
return (pimple: Pimple<T>) => {
|
|
70
|
-
if (cached === undefined) {
|
|
71
|
-
cached = service(pimple);
|
|
72
|
-
}
|
|
73
|
-
return cached;
|
|
74
|
-
};
|
|
75
|
-
}()) : service;
|
|
76
|
-
|
|
77
|
-
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
78
|
-
Object.defineProperty(this, name, {
|
|
79
|
-
get: () => {
|
|
80
|
-
return this.get(name);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return this;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Register a factory
|
|
90
|
-
*/
|
|
91
|
-
public factory<K extends ServiceKey<T>>(name: K, callback: ServiceDefinition<T,T[K]>): Pimple<T> {
|
|
92
|
-
this._raw[name] = callback;
|
|
93
|
-
this._definitions[name] = callback;
|
|
94
|
-
|
|
95
|
-
if (reservedProperties.indexOf(name.toString()) === -1) {
|
|
96
|
-
Object.defineProperty(this, name, {
|
|
97
|
-
get: () => {
|
|
98
|
-
return this.get(name);
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return this;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Get a service instance
|
|
108
|
-
*/
|
|
109
|
-
public get<K extends ServiceKey<T>>(name: K): T[K] {
|
|
110
|
-
if (this._definitions[name] instanceof Function) {
|
|
111
|
-
return (this._definitions[name] as LazyServiceDefinition<T, T[K]>)(this);
|
|
112
|
-
}
|
|
113
|
-
return this._definitions[name] as T[K];
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Checks whether a service is registered or not
|
|
118
|
-
*/
|
|
119
|
-
public has<K extends ServiceKey<T>>(name: K): boolean {
|
|
120
|
-
return name in this._definitions;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Register a protected function
|
|
125
|
-
*/
|
|
126
|
-
public protect<T extends Function>(func: T): () => T {
|
|
127
|
-
return () => func;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Extend a service
|
|
132
|
-
*/
|
|
133
|
-
public extend<K extends ServiceKey<T>>(serviceName: K, service: Function): Function {
|
|
134
|
-
if (!this._definitions[serviceName]) {
|
|
135
|
-
throw new RangeError(`Definition with "${serviceName.toString()}" not defined in container.`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
let def = this._definitions[serviceName];
|
|
139
|
-
|
|
140
|
-
return this._definitions[serviceName] = (container: Pimple<T>) => {
|
|
141
|
-
if (def instanceof Function) {
|
|
142
|
-
def = def(container);
|
|
143
|
-
}
|
|
144
|
-
return service(def, container);
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get a service raw definition
|
|
150
|
-
*/
|
|
151
|
-
public raw<K extends ServiceKey<T>>(name: K): ServiceDefinition<T, T[K]> {
|
|
152
|
-
return this._raw[name] as ServiceDefinition<T, T[K]>;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Register a service provider
|
|
157
|
-
*/
|
|
158
|
-
public register(provider: ProviderDeclaration<T>): Pimple<T> {
|
|
159
|
-
if (this.instanceOfServiceProvider(provider) && provider.register instanceof Function) {
|
|
160
|
-
provider.register(this);
|
|
161
|
-
} else if (provider instanceof Function) {
|
|
162
|
-
provider(this);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
return this;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private instanceOfServiceProvider(object: any): object is ServiceProvider<T> {
|
|
169
|
-
return 'register' in object;
|
|
170
|
-
}
|
|
171
|
-
}
|
package/src/serviceProvider.ts
DELETED
package/tests/pimple.spec.ts
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import Pimple from '../src/pimple';
|
|
2
|
-
import {ServiceProvider} from "../src/index.js";
|
|
3
|
-
|
|
4
|
-
describe('pimple container', () => {
|
|
5
|
-
it('returns container version', async () => {
|
|
6
|
-
expect(Pimple.VERSION).toBe('3.0.0');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it('stores values', async () => {
|
|
10
|
-
type ServiceMap = {
|
|
11
|
-
'baz': number,
|
|
12
|
-
'foo': string,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const container = new Pimple<ServiceMap>({baz: 42});
|
|
16
|
-
|
|
17
|
-
container.set('foo', 'bar');
|
|
18
|
-
|
|
19
|
-
expect(container.get('foo')).toBe('bar');
|
|
20
|
-
expect(container.get('baz')).toBe(42);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('resolves function', async () => {
|
|
24
|
-
type ServiceMap = {
|
|
25
|
-
'baz': number,
|
|
26
|
-
'foo': string,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const container = new Pimple<ServiceMap>();
|
|
30
|
-
|
|
31
|
-
container.set('foo', () => {
|
|
32
|
-
return 'baz';
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
expect(container.get('foo')).toBe('baz');
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('resolves function only once', async () => {
|
|
39
|
-
type ServiceMap = {
|
|
40
|
-
'foo': number,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const container = new Pimple<ServiceMap>();
|
|
44
|
-
|
|
45
|
-
container.set('foo', () => {
|
|
46
|
-
return Math.random();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
expect(container.get('foo')).toBe(container.get('foo'));
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('returns true if service exists', async () => {
|
|
53
|
-
type ServiceMap = {
|
|
54
|
-
'foo': number,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const container = new Pimple<ServiceMap>();
|
|
58
|
-
|
|
59
|
-
container.set('foo', () => {
|
|
60
|
-
return 42;
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
expect(container.has('foo')).toBe(true);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('returns true if service exists', async () => {
|
|
67
|
-
type ServiceMap = {
|
|
68
|
-
'foo': number,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const container = new Pimple<ServiceMap>();
|
|
72
|
-
|
|
73
|
-
expect(container.has('foo')).toBe(false);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('protects function', async () => {
|
|
77
|
-
type ServiceMap = {
|
|
78
|
-
foo: () => string,
|
|
79
|
-
baz: () => string,
|
|
80
|
-
untyped: Function,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const container = new Pimple<ServiceMap>();
|
|
84
|
-
|
|
85
|
-
const typeProtectedFunction = () => 'baz';
|
|
86
|
-
const untypedProtectedFunction = () => 42;
|
|
87
|
-
|
|
88
|
-
container.set('foo', container.protect(typeProtectedFunction));
|
|
89
|
-
container.set('baz', () => typeProtectedFunction);
|
|
90
|
-
container.set('untyped', container.protect(untypedProtectedFunction));
|
|
91
|
-
|
|
92
|
-
expect(container.get('foo')).toBe(typeProtectedFunction);
|
|
93
|
-
expect(container.get('baz')).toBe(typeProtectedFunction);
|
|
94
|
-
expect(container.get('untyped')).toBe(untypedProtectedFunction);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('returns original function', async () => {
|
|
98
|
-
type ServiceMap = {
|
|
99
|
-
foo: string,
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const container = new Pimple<ServiceMap>();
|
|
103
|
-
|
|
104
|
-
const protectedFunction = () => {
|
|
105
|
-
return 'baz';
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
container.set('foo', protectedFunction);
|
|
109
|
-
|
|
110
|
-
expect(container.raw('foo')).toBe(protectedFunction);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('registers services defined in service provider', async () => {
|
|
114
|
-
type ServiceMap = {
|
|
115
|
-
'foo': string,
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const container = new Pimple<ServiceMap>();
|
|
119
|
-
|
|
120
|
-
const serviceProviderMock: ServiceProvider<ServiceMap> = {
|
|
121
|
-
register: (container: Pimple<ServiceMap>) => {
|
|
122
|
-
container.set('foo', () => {
|
|
123
|
-
return 'baz'
|
|
124
|
-
});
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
container.register(serviceProviderMock);
|
|
129
|
-
|
|
130
|
-
expect(container.get('foo')).toBe('baz');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('registers services defined in function', async () => {
|
|
134
|
-
type ServiceMap = {
|
|
135
|
-
foo: string,
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const container = new Pimple<ServiceMap>();
|
|
139
|
-
|
|
140
|
-
const serviceProviderMock = (container: Pimple<ServiceMap>) => {
|
|
141
|
-
container.set('foo', () => {
|
|
142
|
-
return 'baz'
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
container.register(serviceProviderMock);
|
|
147
|
-
|
|
148
|
-
expect(container.get('foo')).toBe('baz');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('returns new instance from factory', async () => {
|
|
152
|
-
type ServiceMap = {
|
|
153
|
-
foo: number,
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const container = new Pimple<ServiceMap>();
|
|
157
|
-
|
|
158
|
-
container.factory('foo', () => {
|
|
159
|
-
return Math.random();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
expect(container.get('foo')).not.toBe(container.get('foo'));
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('throws exception on extending an undefined service', () => {
|
|
166
|
-
type ServiceMap = {
|
|
167
|
-
foo: string,
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const container = new Pimple<ServiceMap>();
|
|
171
|
-
|
|
172
|
-
expect(() => {
|
|
173
|
-
container.extend('foo', () => {});
|
|
174
|
-
}).toThrow('Definition with "foo" not defined in container.');
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('extends service', () => {
|
|
178
|
-
type ServiceMap = {
|
|
179
|
-
foo: string,
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const container = new Pimple<ServiceMap>({
|
|
183
|
-
foo: () => {
|
|
184
|
-
return 'baz';
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
container.extend('foo', (initialService: string, container: Pimple<ServiceMap>) => {
|
|
189
|
-
return initialService + 'bar';
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
expect(container.get('foo')).toBe('bazbar');
|
|
193
|
-
});
|
|
194
|
-
});
|
package/tsconfig-cjs.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2015",
|
|
4
|
-
"module": "ES2020",
|
|
5
|
-
"strict": true,
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"noImplicitAny": true,
|
|
8
|
-
"declaration": true,
|
|
9
|
-
"sourceMap": true,
|
|
10
|
-
"experimentalDecorators": true,
|
|
11
|
-
"forceConsistentCasingInFileNames": true,
|
|
12
|
-
"moduleResolution": "node",
|
|
13
|
-
"outDir": "./lib/esm",
|
|
14
|
-
"baseUrl": "."
|
|
15
|
-
},
|
|
16
|
-
"include": [
|
|
17
|
-
"src/"
|
|
18
|
-
]
|
|
19
|
-
}
|