@joist/di 3.0.5 → 3.0.7
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/package.json +2 -1
- package/src/lib/environment.test.ts +30 -0
- package/src/lib/environment.ts +17 -0
- package/src/lib/inject.test.ts +71 -0
- package/src/lib/inject.ts +20 -0
- package/src/lib/injectable.test.ts +144 -0
- package/src/lib/injectable.ts +69 -0
- package/src/lib/injector.test.ts +86 -0
- package/src/lib/injector.ts +105 -0
- package/src/lib/provider.ts +10 -0
- package/src/lib.ts +5 -0
- package/target/lib/environment.d.ts +2 -0
- package/target/lib/environment.js +3 -0
- package/target/lib/environment.js.map +1 -1
- package/target/lib.d.ts +1 -0
- package/target/lib.js +1 -0
- package/target/lib.js.map +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { Injector } from './injector.js';
|
|
4
|
+
import { environment, clearEnvironment } from './environment.js';
|
|
5
|
+
import { injectable } from './injectable.js';
|
|
6
|
+
import { inject } from './inject.js';
|
|
7
|
+
|
|
8
|
+
describe('environment', () => {
|
|
9
|
+
afterEach(clearEnvironment);
|
|
10
|
+
|
|
11
|
+
it('should create a global Injector instance', () => {
|
|
12
|
+
expect(environment()).to.be.instanceOf(Injector);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should use the root injector when creating services', async () => {
|
|
16
|
+
@injectable
|
|
17
|
+
class MyService { }
|
|
18
|
+
|
|
19
|
+
@injectable
|
|
20
|
+
class MyElement extends HTMLElement {
|
|
21
|
+
my = inject(MyService);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
customElements.define('env-1', MyElement);
|
|
25
|
+
|
|
26
|
+
const el = await fixture<MyElement>(html`<env-1></env-1>`);
|
|
27
|
+
|
|
28
|
+
expect(el.my()).to.equal(environment().get(MyService));
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Injector } from './injector.js';
|
|
2
|
+
import { Provider } from './provider.js';
|
|
3
|
+
|
|
4
|
+
const rootInjector = new Injector();
|
|
5
|
+
|
|
6
|
+
export function environment(): Injector {
|
|
7
|
+
return rootInjector;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function defineEnvironment(providers: Provider<any>[]) {
|
|
11
|
+
environment().providers = providers;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function clearEnvironment(): void {
|
|
15
|
+
rootInjector.providers = [];
|
|
16
|
+
rootInjector.clear();
|
|
17
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { inject } from './inject.js';
|
|
4
|
+
import { injectable } from './injectable.js';
|
|
5
|
+
import { Injector } from './injector.js';
|
|
6
|
+
|
|
7
|
+
describe('inject', () => {
|
|
8
|
+
it('should work', () => {
|
|
9
|
+
class HelloService { }
|
|
10
|
+
|
|
11
|
+
@injectable
|
|
12
|
+
class HelloWorld extends HTMLElement {
|
|
13
|
+
hello = inject(HelloService);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
customElements.define('inject-1', HelloWorld);
|
|
17
|
+
|
|
18
|
+
expect(new HelloWorld().hello()).to.be.instanceOf(HelloService);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should throw error if called in constructor', () => {
|
|
22
|
+
class FooService {
|
|
23
|
+
value = '1';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@injectable
|
|
27
|
+
class BarService {
|
|
28
|
+
foo = inject(FooService);
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
this.foo();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const parent = new Injector();
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
parent.get(BarService);
|
|
39
|
+
|
|
40
|
+
throw new Error('Should not succeed');
|
|
41
|
+
} catch (err) {
|
|
42
|
+
const error = err as Error;
|
|
43
|
+
|
|
44
|
+
expect(error.message).to.equal(
|
|
45
|
+
`BarService is either not injectable or a service is being called in the constructor. \n Either add the @injectable to your class or use the onInject callback method.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should use the calling injector as parent', () => {
|
|
51
|
+
class FooService {
|
|
52
|
+
value = '1';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@injectable
|
|
56
|
+
class BarService {
|
|
57
|
+
foo = inject(FooService);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const parent = new Injector([
|
|
61
|
+
{
|
|
62
|
+
provide: FooService,
|
|
63
|
+
use: class extends FooService {
|
|
64
|
+
value = '100';
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
|
|
69
|
+
expect(parent.get(BarService).foo().value).to.equal('100');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ProviderToken } from './provider.js';
|
|
2
|
+
import { Injectable } from './injector.js';
|
|
3
|
+
|
|
4
|
+
export type Injected<T> = () => T;
|
|
5
|
+
|
|
6
|
+
export function inject<This extends Injectable, T extends object>(
|
|
7
|
+
token: ProviderToken<T>
|
|
8
|
+
): Injected<T> {
|
|
9
|
+
return function (this: This) {
|
|
10
|
+
if (this.injector$$ === undefined) {
|
|
11
|
+
const name = Object.getPrototypeOf(this.constructor).name;
|
|
12
|
+
|
|
13
|
+
throw new Error(
|
|
14
|
+
`${name} is either not injectable or a service is being called in the constructor. \n Either add the @injectable to your class or use the onInject callback method.`
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return this.injector$$.get(token);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { injectable } from './injectable.js';
|
|
4
|
+
import { inject } from './inject.js';
|
|
5
|
+
import { Injector } from './injector.js';
|
|
6
|
+
|
|
7
|
+
describe('@injectable()', () => {
|
|
8
|
+
it('should allow a custom element to be injected with deps', () => {
|
|
9
|
+
class Foo {}
|
|
10
|
+
class Bar {}
|
|
11
|
+
|
|
12
|
+
@injectable
|
|
13
|
+
class MyElement extends HTMLElement {
|
|
14
|
+
foo = inject(Foo);
|
|
15
|
+
bar = inject(Bar);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
customElements.define('injectable-1', MyElement);
|
|
19
|
+
|
|
20
|
+
const el = document.createElement('injectable-1') as MyElement;
|
|
21
|
+
|
|
22
|
+
expect(el.foo()).to.be.instanceOf(Foo);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should locally override a provider', () => {
|
|
26
|
+
class Foo {}
|
|
27
|
+
|
|
28
|
+
class Bar extends Foo {}
|
|
29
|
+
|
|
30
|
+
const MyElement = injectable(
|
|
31
|
+
class {
|
|
32
|
+
static providers = [{ provide: Foo, use: Bar }];
|
|
33
|
+
|
|
34
|
+
foo = inject(Foo);
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const el = new MyElement();
|
|
39
|
+
|
|
40
|
+
expect(el.foo()).to.be.instanceOf(Bar);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should call the onInject lifecycle hook', () => {
|
|
44
|
+
class A {}
|
|
45
|
+
|
|
46
|
+
@injectable
|
|
47
|
+
class B {
|
|
48
|
+
a = inject(A);
|
|
49
|
+
|
|
50
|
+
onInject() {
|
|
51
|
+
expect(this.a()).to.be.instanceOf(A);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
new Injector().get(B);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should handle parent HTML Injectors', async () => {
|
|
59
|
+
@injectable
|
|
60
|
+
class A {}
|
|
61
|
+
|
|
62
|
+
const B = injectable(
|
|
63
|
+
class {
|
|
64
|
+
a = inject(A);
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
class AltA implements A {}
|
|
69
|
+
|
|
70
|
+
@injectable
|
|
71
|
+
class Parent extends HTMLElement {
|
|
72
|
+
static providers = [
|
|
73
|
+
{ provide: B, use: B },
|
|
74
|
+
{ provide: A, use: AltA },
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@injectable
|
|
79
|
+
class Child extends HTMLElement {
|
|
80
|
+
b = inject(B);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
customElements.define('injectable-parent-1', Parent);
|
|
84
|
+
customElements.define('injectable-child-1', Child);
|
|
85
|
+
|
|
86
|
+
const el = await fixture(html`
|
|
87
|
+
<injectable-parent-1>
|
|
88
|
+
<injectable-child-1></injectable-child-1>
|
|
89
|
+
</injectable-parent-1>
|
|
90
|
+
`);
|
|
91
|
+
|
|
92
|
+
const child = el.querySelector<Child>('injectable-child-1')!;
|
|
93
|
+
|
|
94
|
+
expect(child.b().a()).to.be.instanceOf(AltA);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should handle changing contexts', async () => {
|
|
98
|
+
class A {}
|
|
99
|
+
class AltA implements A {}
|
|
100
|
+
|
|
101
|
+
@injectable
|
|
102
|
+
class Ctx1 extends HTMLElement {
|
|
103
|
+
static providers = [{ provide: A, use: A }];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@injectable
|
|
107
|
+
class Ctx2 extends HTMLElement {
|
|
108
|
+
static providers = [{ provide: A, use: AltA }];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@injectable
|
|
112
|
+
class Child extends HTMLElement {
|
|
113
|
+
a = inject(A);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
customElements.define('ctx-1', Ctx1);
|
|
117
|
+
customElements.define('ctx-2', Ctx2);
|
|
118
|
+
customElements.define('ctx-child', Child);
|
|
119
|
+
|
|
120
|
+
const el = await fixture(html`
|
|
121
|
+
<div>
|
|
122
|
+
<ctx-1>
|
|
123
|
+
<ctx-child></ctx-child>
|
|
124
|
+
</ctx-1>
|
|
125
|
+
|
|
126
|
+
<ctx-2></ctx-2>
|
|
127
|
+
</div>
|
|
128
|
+
`);
|
|
129
|
+
|
|
130
|
+
const ctx2 = el.querySelector('ctx-2')!;
|
|
131
|
+
|
|
132
|
+
let child = el.querySelector<Child>('ctx-child')!;
|
|
133
|
+
|
|
134
|
+
expect(child.a()).to.be.instanceOf(A);
|
|
135
|
+
|
|
136
|
+
child.remove();
|
|
137
|
+
|
|
138
|
+
ctx2.append(child);
|
|
139
|
+
|
|
140
|
+
child = el.querySelector<Child>('ctx-child')!;
|
|
141
|
+
|
|
142
|
+
expect(child.a()).to.be.instanceOf(AltA);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ProviderToken } from './provider.js';
|
|
2
|
+
import { Injectable, Injector } from './injector.js';
|
|
3
|
+
import { environment } from './environment.js';
|
|
4
|
+
|
|
5
|
+
export function injectable<T extends ProviderToken<any>>(Base: T, _?: unknown) {
|
|
6
|
+
return class InjectableNode extends Base implements Injectable {
|
|
7
|
+
injector$$ = new Injector(Base.providers);
|
|
8
|
+
|
|
9
|
+
constructor(..._: any[]) {
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
if (this instanceof HTMLElement) {
|
|
14
|
+
this.addEventListener('finddiroot', (e) => {
|
|
15
|
+
const parentInjector = findInjectorRoot(e);
|
|
16
|
+
|
|
17
|
+
if (parentInjector !== null) {
|
|
18
|
+
this.injector$$.setParent(parentInjector);
|
|
19
|
+
} else {
|
|
20
|
+
this.injector$$.setParent(environment());
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onInject() {
|
|
28
|
+
if (super.onInject) {
|
|
29
|
+
super.onInject();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
connectedCallback() {
|
|
34
|
+
try {
|
|
35
|
+
if (this instanceof HTMLElement) {
|
|
36
|
+
this.dispatchEvent(new Event('finddiroot'));
|
|
37
|
+
|
|
38
|
+
if (super.connectedCallback) {
|
|
39
|
+
super.connectedCallback();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
disconnectedCallback() {
|
|
46
|
+
this.injector$$.setParent(undefined);
|
|
47
|
+
|
|
48
|
+
if (super.disconnectedCallback) {
|
|
49
|
+
super.disconnectedCallback();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function findInjectorRoot(e: Event): Injector | null {
|
|
56
|
+
const path = e.composedPath();
|
|
57
|
+
|
|
58
|
+
// find firt parent
|
|
59
|
+
// skips the first item which is the target
|
|
60
|
+
for (let i = 1; i < path.length; i++) {
|
|
61
|
+
const part = path[i];
|
|
62
|
+
|
|
63
|
+
if ('injector$$' in part && part.injector$$ instanceof Injector) {
|
|
64
|
+
return part.injector$$;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing';
|
|
2
|
+
|
|
3
|
+
import { Injector } from './injector.js';
|
|
4
|
+
import { inject } from './inject.js';
|
|
5
|
+
import { injectable } from './injectable.js';
|
|
6
|
+
|
|
7
|
+
describe('Injector', () => {
|
|
8
|
+
it('should create a new instance of a single provider', () => {
|
|
9
|
+
class A { }
|
|
10
|
+
|
|
11
|
+
const app = new Injector();
|
|
12
|
+
|
|
13
|
+
expect(app.get(A)).to.be.instanceOf(A);
|
|
14
|
+
expect(app.get(A)).to.equal(app.get(A));
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should inject providers in the correct order', () => {
|
|
18
|
+
class A { }
|
|
19
|
+
class B { }
|
|
20
|
+
|
|
21
|
+
@injectable
|
|
22
|
+
class MyService {
|
|
23
|
+
a = inject(A);
|
|
24
|
+
b = inject(B);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const app = new Injector();
|
|
28
|
+
const instance = app.get(MyService);
|
|
29
|
+
|
|
30
|
+
expect(instance.a()).to.be.instanceOf(A);
|
|
31
|
+
expect(instance.b()).to.be.instanceOf(B);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should create a new instance of a provider that has a full dep tree', () => {
|
|
35
|
+
class A { }
|
|
36
|
+
|
|
37
|
+
@injectable
|
|
38
|
+
class B {
|
|
39
|
+
a = inject(A);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@injectable
|
|
43
|
+
class C {
|
|
44
|
+
b = inject(B);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@injectable
|
|
48
|
+
class D {
|
|
49
|
+
c = inject(C);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@injectable
|
|
53
|
+
class E {
|
|
54
|
+
d = inject(D);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const app = new Injector();
|
|
58
|
+
const instance = app.get(E);
|
|
59
|
+
|
|
60
|
+
expect(instance.d().c().b().a()).to.be.instanceOf(A);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should override a provider if explicitly instructed', () => {
|
|
64
|
+
class A { }
|
|
65
|
+
|
|
66
|
+
@injectable
|
|
67
|
+
class B {
|
|
68
|
+
a = inject(A);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
class AltA extends A { }
|
|
72
|
+
const app = new Injector([{ provide: A, use: AltA }]);
|
|
73
|
+
|
|
74
|
+
expect(app.get(B).a()).to.be.instanceOf(AltA);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should return an existing instance from a parent injector', () => {
|
|
78
|
+
class A { }
|
|
79
|
+
|
|
80
|
+
const parent = new Injector();
|
|
81
|
+
|
|
82
|
+
const app = new Injector([], parent);
|
|
83
|
+
|
|
84
|
+
expect(parent.get(A)).to.equal(app.get(A));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ProviderToken, Provider } from './provider.js';
|
|
2
|
+
|
|
3
|
+
// defines available properties that will be on a class instance that can use the inject function
|
|
4
|
+
export type Injectable = object & {
|
|
5
|
+
injector$$?: Injector;
|
|
6
|
+
onInject?(): void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Injectors create and store instances of services.
|
|
11
|
+
* A service is any constructable class.
|
|
12
|
+
* When calling Injector.get, the injector will resolve as following.
|
|
13
|
+
*
|
|
14
|
+
* 1. Do I have a cached instance locally?
|
|
15
|
+
* 2. Do I have a local provider definition for the token?
|
|
16
|
+
* 3. Do I have a parent? Check parent for 1 and 2
|
|
17
|
+
* 5. All clear, go ahead and construct and cache the requested service
|
|
18
|
+
*
|
|
19
|
+
* RootInjector |--> InjectorA |--> InjectorB
|
|
20
|
+
* |--> InjectorC
|
|
21
|
+
* |--> InjectorD |--> InjectorE
|
|
22
|
+
*
|
|
23
|
+
* in the above tree, if InjectorE requests a service, it will navigate up to the RootInjector and cache.
|
|
24
|
+
* If Inject B then requests the same token, it will recieve the same cached instance from RootInjector.
|
|
25
|
+
*/
|
|
26
|
+
export class Injector {
|
|
27
|
+
// ke track of isntances. One Token can have one instance
|
|
28
|
+
#instances = new WeakMap<ProviderToken<any>, any>();
|
|
29
|
+
|
|
30
|
+
#parent: Injector | undefined = undefined;
|
|
31
|
+
|
|
32
|
+
constructor(public providers: Provider<any>[] = [], parent?: Injector) {
|
|
33
|
+
this.setParent(parent);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// resolves and retuns and instance of the requested service
|
|
37
|
+
get<T extends Injectable>(token: ProviderToken<T>): T {
|
|
38
|
+
// check for a local instance
|
|
39
|
+
if (this.#instances.has(token)) {
|
|
40
|
+
return this.#instances.get(token)!;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const provider = this.#findProvider(token);
|
|
44
|
+
|
|
45
|
+
// check for a provider definition
|
|
46
|
+
if (provider) {
|
|
47
|
+
return this.#createAndCache<T>(provider.use);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// check for a parent and attempt to get there
|
|
51
|
+
if (this.#parent) {
|
|
52
|
+
return this.#parent.get(token);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this.#createAndCache(token);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setParent(parent: Injector | undefined) {
|
|
59
|
+
this.#parent = parent;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
clear() {
|
|
63
|
+
this.#instances = new WeakMap();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#createAndCache<T extends Injectable>(token: ProviderToken<T>): T {
|
|
67
|
+
const instance = new token();
|
|
68
|
+
|
|
69
|
+
this.#instances.set(token, instance);
|
|
70
|
+
|
|
71
|
+
if (instance.injector$$ instanceof Injector) {
|
|
72
|
+
/**
|
|
73
|
+
* set the this injector instance as a parent.
|
|
74
|
+
* this means that each calling injector will be the parent of what it creates.
|
|
75
|
+
* this allows the created service to navigate up it's chain to find a root
|
|
76
|
+
*/
|
|
77
|
+
instance.injector$$.setParent(this);
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* the on inject lifecycle hook should be called after the parent is defined.
|
|
81
|
+
* this ensures that services are initialized when the chain is settled
|
|
82
|
+
* this is required since the parent is set after the instance is constructed
|
|
83
|
+
*/
|
|
84
|
+
if (instance.onInject) {
|
|
85
|
+
instance.onInject();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return instance;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
#findProvider(token: ProviderToken<any>): Provider<any> | undefined {
|
|
93
|
+
if (!this.providers) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < this.providers.length; i++) {
|
|
98
|
+
if (this.providers[i].provide === token) {
|
|
99
|
+
return this.providers[i];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/lib.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Injector, Injectable } from './lib/injector.js';
|
|
2
|
+
export { Provider, ProviderToken } from './lib/provider.js';
|
|
3
|
+
export { injectable } from './lib/injectable.js';
|
|
4
|
+
export { inject, Injected } from './lib/inject.js';
|
|
5
|
+
export { defineEnvironment, clearEnvironment } from './lib/environment.js';
|
|
@@ -3,6 +3,9 @@ const rootInjector = new Injector();
|
|
|
3
3
|
export function environment() {
|
|
4
4
|
return rootInjector;
|
|
5
5
|
}
|
|
6
|
+
export function defineEnvironment(providers) {
|
|
7
|
+
environment().providers = providers;
|
|
8
|
+
}
|
|
6
9
|
export function clearEnvironment() {
|
|
7
10
|
rootInjector.providers = [];
|
|
8
11
|
rootInjector.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/lib/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/lib/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,MAAM,YAAY,GAAG,IAAI,QAAQ,EAAE,CAAC;AAEpC,MAAM,UAAU,WAAW;IACzB,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAA0B;IAC1D,WAAW,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,YAAY,CAAC,SAAS,GAAG,EAAE,CAAC;IAC5B,YAAY,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC"}
|
package/target/lib.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { Injector, Injectable } from './lib/injector.js';
|
|
|
2
2
|
export { Provider, ProviderToken } from './lib/provider.js';
|
|
3
3
|
export { injectable } from './lib/injectable.js';
|
|
4
4
|
export { inject, Injected } from './lib/inject.js';
|
|
5
|
+
export { defineEnvironment, clearEnvironment } from './lib/environment.js';
|
package/target/lib.js
CHANGED
package/target/lib.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAc,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAY,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAc,MAAM,mBAAmB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAY,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|