ditox 3.1.0 → 3.3.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/README.md +135 -32
- package/dist/index.cjs +518 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{umd/index.d.ts → index.d.cts} +195 -197
- package/dist/{browser/index.d.ts → index.d.ts} +195 -197
- package/dist/index.js +501 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +524 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +22 -19
- package/src/container.test.ts +34 -33
- package/src/container.ts +12 -6
- package/src/index.ts +26 -23
- package/src/modules.test.ts +172 -37
- package/src/modules.ts +22 -5
- package/src/tokens.test.ts +9 -8
- package/src/tokens.ts +2 -2
- package/src/utils.test.ts +18 -17
- package/src/utils.ts +21 -21
- package/dist/browser/index.js +0 -2
- package/dist/browser/index.js.map +0 -1
- package/dist/cjs/container.d.ts +0 -88
- package/dist/cjs/container.js +0 -216
- package/dist/cjs/container.js.map +0 -1
- package/dist/cjs/index.d.ts +0 -7
- package/dist/cjs/index.js +0 -24
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/modules.d.ts +0 -121
- package/dist/cjs/modules.js +0 -143
- package/dist/cjs/modules.js.map +0 -1
- package/dist/cjs/tokens.d.ts +0 -56
- package/dist/cjs/tokens.js +0 -20
- package/dist/cjs/tokens.js.map +0 -1
- package/dist/cjs/utils.d.ts +0 -137
- package/dist/cjs/utils.js +0 -156
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/container.d.ts +0 -88
- package/dist/esm/container.js +0 -211
- package/dist/esm/container.js.map +0 -1
- package/dist/esm/index.d.ts +0 -7
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/modules.d.ts +0 -121
- package/dist/esm/modules.js +0 -136
- package/dist/esm/modules.js.map +0 -1
- package/dist/esm/tokens.d.ts +0 -56
- package/dist/esm/tokens.js +0 -15
- package/dist/esm/tokens.js.map +0 -1
- package/dist/esm/utils.d.ts +0 -137
- package/dist/esm/utils.js +0 -145
- package/dist/esm/utils.js.map +0 -1
- package/dist/umd/index.js +0 -2
- package/dist/umd/index.js.map +0 -1
package/src/container.test.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { describe, expect, it, test, vi } from 'vitest';
|
|
1
2
|
import {
|
|
2
3
|
CONTAINER,
|
|
3
4
|
createContainer,
|
|
4
5
|
PARENT_CONTAINERS,
|
|
5
6
|
ResolverError,
|
|
6
7
|
} from './container';
|
|
7
|
-
import {optional, token} from './tokens';
|
|
8
|
-
import {injectable} from './utils';
|
|
8
|
+
import { optional, token } from './tokens';
|
|
9
|
+
import { injectable } from './utils';
|
|
9
10
|
|
|
10
11
|
const NUMBER = token<number>('number');
|
|
11
12
|
const STRING = token<string>('string');
|
|
@@ -28,7 +29,7 @@ describe('Container', () => {
|
|
|
28
29
|
it('should bind a result of a factory and prevent invoking it', () => {
|
|
29
30
|
const container = createContainer();
|
|
30
31
|
|
|
31
|
-
const factory =
|
|
32
|
+
const factory = vi.fn(() => 1);
|
|
32
33
|
container.bindFactory(NUMBER, factory);
|
|
33
34
|
container.bindValue(NUMBER, 2);
|
|
34
35
|
|
|
@@ -54,7 +55,7 @@ describe('Container', () => {
|
|
|
54
55
|
const container = createContainer();
|
|
55
56
|
|
|
56
57
|
let containerArg;
|
|
57
|
-
const factory =
|
|
58
|
+
const factory = vi.fn((arg) => {
|
|
58
59
|
containerArg = arg;
|
|
59
60
|
return 1;
|
|
60
61
|
});
|
|
@@ -68,8 +69,8 @@ describe('Container', () => {
|
|
|
68
69
|
it('should rebind a factory in case it was bound', () => {
|
|
69
70
|
const container = createContainer();
|
|
70
71
|
|
|
71
|
-
const factory1 =
|
|
72
|
-
const factory2 =
|
|
72
|
+
const factory1 = vi.fn(() => 1);
|
|
73
|
+
const factory2 = vi.fn(() => 2);
|
|
73
74
|
container.bindFactory(NUMBER, factory1);
|
|
74
75
|
container.bindFactory(NUMBER, factory2);
|
|
75
76
|
|
|
@@ -87,7 +88,7 @@ describe('Container', () => {
|
|
|
87
88
|
container.bindValue(START, 20);
|
|
88
89
|
|
|
89
90
|
let counter = 0;
|
|
90
|
-
const factory =
|
|
91
|
+
const factory = vi.fn((start) => start + ++counter);
|
|
91
92
|
parent.bindFactory(NUMBER, injectable(factory, START), {
|
|
92
93
|
scope: 'singleton',
|
|
93
94
|
});
|
|
@@ -113,7 +114,7 @@ describe('Container', () => {
|
|
|
113
114
|
container.bindValue(START, 20);
|
|
114
115
|
|
|
115
116
|
let counter = 0;
|
|
116
|
-
const factory =
|
|
117
|
+
const factory = vi.fn((start) => start + ++counter);
|
|
117
118
|
parent.bindFactory(NUMBER, injectable(factory, START), {
|
|
118
119
|
scope: 'scoped',
|
|
119
120
|
});
|
|
@@ -129,7 +130,7 @@ describe('Container', () => {
|
|
|
129
130
|
it('should inherit a factory with "scoped" scope', async () => {
|
|
130
131
|
const parentParent = createContainer();
|
|
131
132
|
let counter = 0;
|
|
132
|
-
const factory =
|
|
133
|
+
const factory = vi.fn(() => ++counter);
|
|
133
134
|
|
|
134
135
|
parentParent.bindFactory(NUMBER, factory);
|
|
135
136
|
|
|
@@ -163,7 +164,7 @@ describe('Container', () => {
|
|
|
163
164
|
container.bindValue(START, 20);
|
|
164
165
|
|
|
165
166
|
let counter = 0;
|
|
166
|
-
const factory =
|
|
167
|
+
const factory = vi.fn((start) => start + ++counter);
|
|
167
168
|
parent.bindFactory(NUMBER, injectable(factory, START));
|
|
168
169
|
|
|
169
170
|
expect(container.get(NUMBER)).toBe(11);
|
|
@@ -190,7 +191,7 @@ describe('Container', () => {
|
|
|
190
191
|
container3.bindValue(START, 30);
|
|
191
192
|
|
|
192
193
|
let counter = 0;
|
|
193
|
-
const factory =
|
|
194
|
+
const factory = vi.fn((start) => start + ++counter);
|
|
194
195
|
parent.bindFactory(NUMBER, injectable(factory, START), {
|
|
195
196
|
scope: 'scoped',
|
|
196
197
|
});
|
|
@@ -235,7 +236,7 @@ describe('Container', () => {
|
|
|
235
236
|
container.bindValue(START, 20);
|
|
236
237
|
|
|
237
238
|
let counter = 0;
|
|
238
|
-
const factory =
|
|
239
|
+
const factory = vi.fn((start) => start + ++counter);
|
|
239
240
|
parent.bindFactory(NUMBER, injectable(factory, START), {
|
|
240
241
|
scope: 'transient',
|
|
241
242
|
});
|
|
@@ -251,9 +252,9 @@ describe('Container', () => {
|
|
|
251
252
|
it('should bind a factory with "onRemoved" callback', () => {
|
|
252
253
|
const container = createContainer();
|
|
253
254
|
|
|
254
|
-
const factory =
|
|
255
|
-
const callback =
|
|
256
|
-
container.bindFactory(NUMBER, factory, {onRemoved: callback});
|
|
255
|
+
const factory = vi.fn(() => 1);
|
|
256
|
+
const callback = vi.fn();
|
|
257
|
+
container.bindFactory(NUMBER, factory, { onRemoved: callback });
|
|
257
258
|
|
|
258
259
|
expect(container.get(NUMBER)).toBe(1);
|
|
259
260
|
container.remove(NUMBER);
|
|
@@ -284,9 +285,9 @@ describe('Container', () => {
|
|
|
284
285
|
it('should remove "singleton" factory silently in case its value has never been resolved', () => {
|
|
285
286
|
const container = createContainer();
|
|
286
287
|
|
|
287
|
-
const factory =
|
|
288
|
-
const onRemoved =
|
|
289
|
-
container.bindFactory(NUMBER, factory, {scope: 'singleton', onRemoved});
|
|
288
|
+
const factory = vi.fn(() => 1);
|
|
289
|
+
const onRemoved = vi.fn();
|
|
290
|
+
container.bindFactory(NUMBER, factory, { scope: 'singleton', onRemoved });
|
|
290
291
|
container.remove(NUMBER);
|
|
291
292
|
|
|
292
293
|
expect(container.get(NUMBER)).toBeUndefined();
|
|
@@ -297,9 +298,9 @@ describe('Container', () => {
|
|
|
297
298
|
it('should remove "singleton" factory with calling "onRemoved" in case its value has been resolved', () => {
|
|
298
299
|
const container = createContainer();
|
|
299
300
|
|
|
300
|
-
const factory =
|
|
301
|
-
const onRemoved =
|
|
302
|
-
container.bindFactory(NUMBER, factory, {scope: 'singleton', onRemoved});
|
|
301
|
+
const factory = vi.fn(() => 100);
|
|
302
|
+
const onRemoved = vi.fn();
|
|
303
|
+
container.bindFactory(NUMBER, factory, { scope: 'singleton', onRemoved });
|
|
303
304
|
|
|
304
305
|
expect(container.get(NUMBER)).toBe(100);
|
|
305
306
|
container.remove(NUMBER);
|
|
@@ -315,9 +316,9 @@ describe('Container', () => {
|
|
|
315
316
|
const container = createContainer(parent);
|
|
316
317
|
|
|
317
318
|
let count = 1;
|
|
318
|
-
const factory =
|
|
319
|
-
const onRemoved =
|
|
320
|
-
parent.bindFactory(NUMBER, factory, {scope: 'scoped', onRemoved});
|
|
319
|
+
const factory = vi.fn(() => count++);
|
|
320
|
+
const onRemoved = vi.fn();
|
|
321
|
+
parent.bindFactory(NUMBER, factory, { scope: 'scoped', onRemoved });
|
|
321
322
|
|
|
322
323
|
expect(parent.get(NUMBER)).toBe(1);
|
|
323
324
|
expect(container.get(NUMBER)).toBe(1);
|
|
@@ -332,8 +333,8 @@ describe('Container', () => {
|
|
|
332
333
|
it('should remove "transient" factory in case its value has never been resolved', () => {
|
|
333
334
|
const container = createContainer();
|
|
334
335
|
|
|
335
|
-
const factory =
|
|
336
|
-
container.bindFactory(NUMBER, factory, {scope: 'transient'});
|
|
336
|
+
const factory = vi.fn(() => 1);
|
|
337
|
+
container.bindFactory(NUMBER, factory, { scope: 'transient' });
|
|
337
338
|
container.remove(NUMBER);
|
|
338
339
|
|
|
339
340
|
expect(container.get(NUMBER)).toBeUndefined();
|
|
@@ -343,8 +344,8 @@ describe('Container', () => {
|
|
|
343
344
|
it('should remove "transient" factory in case its value has been resolved', () => {
|
|
344
345
|
const container = createContainer();
|
|
345
346
|
|
|
346
|
-
const factory =
|
|
347
|
-
container.bindFactory(NUMBER, factory, {scope: 'transient'});
|
|
347
|
+
const factory = vi.fn(() => 1);
|
|
348
|
+
container.bindFactory(NUMBER, factory, { scope: 'transient' });
|
|
348
349
|
expect(container.get(NUMBER)).toBe(1);
|
|
349
350
|
|
|
350
351
|
container.remove(NUMBER);
|
|
@@ -382,8 +383,8 @@ describe('Container', () => {
|
|
|
382
383
|
const F1 = token('f1');
|
|
383
384
|
const F2 = token('f2');
|
|
384
385
|
|
|
385
|
-
const unbind1 =
|
|
386
|
-
const unbind2 =
|
|
386
|
+
const unbind1 = vi.fn();
|
|
387
|
+
const unbind2 = vi.fn();
|
|
387
388
|
|
|
388
389
|
const container = createContainer();
|
|
389
390
|
container.bindFactory(F1, () => 10, {
|
|
@@ -419,7 +420,7 @@ describe('Container', () => {
|
|
|
419
420
|
|
|
420
421
|
describe('hasToken()', () => {
|
|
421
422
|
it('should check if a container hierarchy has the token', () => {
|
|
422
|
-
const factory =
|
|
423
|
+
const factory = vi.fn();
|
|
423
424
|
|
|
424
425
|
const token1 = token();
|
|
425
426
|
const token2 = token();
|
|
@@ -621,8 +622,8 @@ describe('Container', () => {
|
|
|
621
622
|
|
|
622
623
|
it('should resolve a value by shared tokens', () => {
|
|
623
624
|
const key = 'token-' + Date.now();
|
|
624
|
-
const t1 = token({key});
|
|
625
|
-
const t2 = token({key});
|
|
625
|
+
const t1 = token({ key });
|
|
626
|
+
const t2 = token({ key });
|
|
626
627
|
expect(t1).not.toBe(t2);
|
|
627
628
|
|
|
628
629
|
const container = createContainer();
|
package/src/container.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Token, token} from './tokens';
|
|
1
|
+
import { Token, token } from './tokens';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ResolverError is thrown by the resolver when a token is not found in a container.
|
|
@@ -79,6 +79,12 @@ export type Container = {
|
|
|
79
79
|
removeAll(): void;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* A subset of Container interface that provides read-only access to dependency resolution.
|
|
84
|
+
* This type is used for parent containers to allow token resolution without exposing mutation methods.
|
|
85
|
+
*/
|
|
86
|
+
export type ContainerResolver = Pick<Container, 'hasToken' | 'get' | 'resolve'>;
|
|
87
|
+
|
|
82
88
|
/** @internal */
|
|
83
89
|
export const CONTAINER: Token<Container> = token('ditox.Container');
|
|
84
90
|
/** @internal */
|
|
@@ -143,9 +149,9 @@ function isInternalToken<T>(token: Token<T>): boolean {
|
|
|
143
149
|
* @param parentArg - Optional parent container or an array of containers.
|
|
144
150
|
*/
|
|
145
151
|
export function createContainer(
|
|
146
|
-
parentArg?:
|
|
152
|
+
parentArg?: ContainerResolver | ReadonlyArray<ContainerResolver>,
|
|
147
153
|
): Container {
|
|
148
|
-
const parents: ReadonlyArray<
|
|
154
|
+
const parents: ReadonlyArray<ContainerResolver> | undefined = parentArg
|
|
149
155
|
? Array.isArray(parentArg)
|
|
150
156
|
? [...parentArg]
|
|
151
157
|
: [parentArg]
|
|
@@ -172,7 +178,7 @@ export function createContainer(
|
|
|
172
178
|
return;
|
|
173
179
|
}
|
|
174
180
|
|
|
175
|
-
factories.set(token.symbol, {factory, options});
|
|
181
|
+
factories.set(token.symbol, { factory, options });
|
|
176
182
|
},
|
|
177
183
|
|
|
178
184
|
remove<T>(token: Token<T>): void {
|
|
@@ -324,7 +330,7 @@ export function createContainer(
|
|
|
324
330
|
}
|
|
325
331
|
|
|
326
332
|
function parentContainersHaveToken<T>(
|
|
327
|
-
parents: ReadonlyArray<
|
|
333
|
+
parents: ReadonlyArray<ContainerResolver> | undefined,
|
|
328
334
|
token: Token<T>,
|
|
329
335
|
): boolean {
|
|
330
336
|
if (!parents) return false;
|
|
@@ -339,7 +345,7 @@ function parentContainersHaveToken<T>(
|
|
|
339
345
|
}
|
|
340
346
|
|
|
341
347
|
function parentContainersResolveToken<T>(
|
|
342
|
-
parents: ReadonlyArray<
|
|
348
|
+
parents: ReadonlyArray<ContainerResolver>,
|
|
343
349
|
token: Token<T>,
|
|
344
350
|
origin: Container,
|
|
345
351
|
): T | typeof NOT_FOUND {
|
package/src/index.ts
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
injectableClass,
|
|
16
|
-
} from './utils';
|
|
17
|
-
|
|
1
|
+
export type {
|
|
2
|
+
Container,
|
|
3
|
+
ContainerResolver,
|
|
4
|
+
FactoryOptions,
|
|
5
|
+
FactoryScope,
|
|
6
|
+
} from './container';
|
|
7
|
+
export { createContainer, ResolverError } from './container';
|
|
8
|
+
export type {
|
|
9
|
+
AnyModuleDeclaration,
|
|
10
|
+
BindModuleOptions,
|
|
11
|
+
Module,
|
|
12
|
+
ModuleBindingEntry,
|
|
13
|
+
ModuleDeclaration,
|
|
14
|
+
} from './modules';
|
|
18
15
|
export {
|
|
19
16
|
bindModule,
|
|
20
17
|
bindModules,
|
|
21
18
|
declareModule,
|
|
22
19
|
declareModuleBindings,
|
|
23
20
|
} from './modules';
|
|
24
|
-
export type {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
export type { OptionalToken, RequiredToken, Token } from './tokens';
|
|
22
|
+
export { optional, token } from './tokens';
|
|
23
|
+
export {
|
|
24
|
+
bindMultiValue,
|
|
25
|
+
injectable,
|
|
26
|
+
injectableClass,
|
|
27
|
+
isToken,
|
|
28
|
+
resolveValue,
|
|
29
|
+
resolveValues,
|
|
30
|
+
tryResolveValue,
|
|
31
|
+
tryResolveValues,
|
|
32
|
+
} from './utils';
|
package/src/modules.test.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { createContainer } from './container';
|
|
2
3
|
import {
|
|
3
4
|
bindModule,
|
|
4
5
|
bindModules,
|
|
5
6
|
declareModule,
|
|
6
7
|
declareModuleBindings,
|
|
7
8
|
Module,
|
|
9
|
+
ModuleBindingEntry,
|
|
8
10
|
ModuleDeclaration,
|
|
9
11
|
} from './modules';
|
|
10
|
-
import {token} from './tokens';
|
|
11
|
-
import {injectable} from './utils';
|
|
12
|
+
import { token } from './tokens';
|
|
13
|
+
import { injectable } from './utils';
|
|
12
14
|
|
|
13
15
|
describe('bindModule()', () => {
|
|
14
|
-
type TestQueries = {getValue: () => number};
|
|
15
|
-
type TestModule = Module<{queries: TestQueries}>;
|
|
16
|
+
type TestQueries = { getValue: () => number };
|
|
17
|
+
type TestModule = Module<{ queries: TestQueries }>;
|
|
16
18
|
|
|
17
19
|
const MODULE_TOKEN = token<TestModule>();
|
|
18
20
|
const QUERIES_TOKEN = token<TestQueries>();
|
|
@@ -39,7 +41,7 @@ describe('bindModule()', () => {
|
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
it('should destroy the module on removing the module token and remove tokens of its exported props', () => {
|
|
42
|
-
const destroy =
|
|
44
|
+
const destroy = vi.fn();
|
|
43
45
|
const container = createContainer();
|
|
44
46
|
|
|
45
47
|
bindModule(container, {
|
|
@@ -65,10 +67,10 @@ describe('bindModule()', () => {
|
|
|
65
67
|
const token1 = token();
|
|
66
68
|
const token2 = token();
|
|
67
69
|
|
|
68
|
-
const beforeBinding =
|
|
70
|
+
const beforeBinding = vi.fn((container) =>
|
|
69
71
|
container.bindValue(token1, 'foo'),
|
|
70
72
|
);
|
|
71
|
-
const afterBinding =
|
|
73
|
+
const afterBinding = vi.fn((container) => {
|
|
72
74
|
const value = container.resolve(QUERIES_TOKEN).getValue();
|
|
73
75
|
container.bindValue(token2, value * 10);
|
|
74
76
|
});
|
|
@@ -86,6 +88,139 @@ describe('bindModule()', () => {
|
|
|
86
88
|
expect(container.resolve(token2)).toBe(10);
|
|
87
89
|
});
|
|
88
90
|
|
|
91
|
+
it('should support "eager" strategy', () => {
|
|
92
|
+
const container = createContainer();
|
|
93
|
+
const factory = vi.fn(() => ({}));
|
|
94
|
+
|
|
95
|
+
const MODULE = declareModule({
|
|
96
|
+
factory,
|
|
97
|
+
strategy: 'eager',
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
bindModule(container, MODULE);
|
|
101
|
+
expect(factory).toBeCalledTimes(1);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should support "lazy" strategy by default', () => {
|
|
105
|
+
const container = createContainer();
|
|
106
|
+
const factory = vi.fn(() => ({}));
|
|
107
|
+
|
|
108
|
+
const MODULE = declareModule({
|
|
109
|
+
factory,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
bindModule(container, MODULE);
|
|
113
|
+
expect(factory).toBeCalledTimes(0);
|
|
114
|
+
|
|
115
|
+
container.resolve(MODULE.token);
|
|
116
|
+
expect(factory).toBeCalledTimes(1);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should support "eager" strategy in imports', () => {
|
|
120
|
+
const container = createContainer();
|
|
121
|
+
const factory1 = vi.fn(() => ({}));
|
|
122
|
+
const factory2 = vi.fn(() => ({}));
|
|
123
|
+
|
|
124
|
+
const MODULE1 = declareModule({
|
|
125
|
+
factory: factory1,
|
|
126
|
+
strategy: 'eager',
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
const MODULE2 = declareModule({
|
|
130
|
+
factory: factory2,
|
|
131
|
+
imports: [MODULE1],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
bindModule(container, MODULE2);
|
|
135
|
+
expect(factory1).toBeCalledTimes(1);
|
|
136
|
+
expect(factory2).toBeCalledTimes(0);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should throw an error during binding if "eager" factory fails', () => {
|
|
140
|
+
const container = createContainer();
|
|
141
|
+
const error = new Error('Eager factory failed');
|
|
142
|
+
const factory = vi.fn(() => {
|
|
143
|
+
throw error;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const MODULE = declareModule({
|
|
147
|
+
factory,
|
|
148
|
+
strategy: 'eager',
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(() => bindModule(container, MODULE)).toThrow(error);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should throw an error during binding if imported "eager" factory fails', () => {
|
|
155
|
+
const container = createContainer();
|
|
156
|
+
const error = new Error('Eager factory failed');
|
|
157
|
+
const factory1 = vi.fn(() => {
|
|
158
|
+
throw error;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const MODULE1 = declareModule({
|
|
162
|
+
factory: factory1,
|
|
163
|
+
strategy: 'eager',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const MODULE2 = declareModule({
|
|
167
|
+
factory: () => ({}),
|
|
168
|
+
imports: [MODULE1],
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
expect(() => bindModule(container, MODULE2)).toThrow(error);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should execute "eager" factories in reverse BFS order', () => {
|
|
175
|
+
const route: string[] = [];
|
|
176
|
+
|
|
177
|
+
const declareEagerModule = (id: string, imports?: ModuleBindingEntry[]) =>
|
|
178
|
+
declareModule({
|
|
179
|
+
imports,
|
|
180
|
+
strategy: 'eager',
|
|
181
|
+
factory: () => {
|
|
182
|
+
route.push(id);
|
|
183
|
+
return {};
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Structure:
|
|
189
|
+
* m1
|
|
190
|
+
* / | \
|
|
191
|
+
* m2 m3 m4
|
|
192
|
+
*
|
|
193
|
+
* BFS order: m1, m2, m3, m4
|
|
194
|
+
* Expected execution order (reverse): m4, m3, m2, m1
|
|
195
|
+
*/
|
|
196
|
+
const m4 = declareEagerModule('m4');
|
|
197
|
+
const m3 = declareEagerModule('m3');
|
|
198
|
+
const m2 = declareEagerModule('m2');
|
|
199
|
+
const m1 = declareEagerModule('m1', [m2, m3, m4]);
|
|
200
|
+
|
|
201
|
+
const container = createContainer();
|
|
202
|
+
bindModule(container, m1);
|
|
203
|
+
|
|
204
|
+
expect(route).toEqual(['m4', 'm3', 'm2', 'm1']);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('should throw an error during resolution if "lazy" factory fails', () => {
|
|
208
|
+
const container = createContainer();
|
|
209
|
+
const error = new Error('Lazy factory failed');
|
|
210
|
+
const factory = vi.fn(() => {
|
|
211
|
+
throw error;
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const MODULE = declareModule({
|
|
215
|
+
factory,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
bindModule(container, MODULE);
|
|
219
|
+
expect(factory).toBeCalledTimes(0);
|
|
220
|
+
|
|
221
|
+
expect(() => container.resolve(MODULE.token)).toThrow(error);
|
|
222
|
+
});
|
|
223
|
+
|
|
89
224
|
it('should bind the module as singleton by default', () => {
|
|
90
225
|
const parent = createContainer();
|
|
91
226
|
const container = createContainer(parent);
|
|
@@ -98,7 +233,7 @@ describe('bindModule()', () => {
|
|
|
98
233
|
const parent = createContainer();
|
|
99
234
|
const container = createContainer(parent);
|
|
100
235
|
|
|
101
|
-
bindModule(parent, MODULE, {scope: 'singleton'});
|
|
236
|
+
bindModule(parent, MODULE, { scope: 'singleton' });
|
|
102
237
|
expect(parent.get(MODULE_TOKEN)).toBe(container.get(MODULE_TOKEN));
|
|
103
238
|
});
|
|
104
239
|
|
|
@@ -106,7 +241,7 @@ describe('bindModule()', () => {
|
|
|
106
241
|
const parent = createContainer();
|
|
107
242
|
const container = createContainer(parent);
|
|
108
243
|
|
|
109
|
-
bindModule(parent, MODULE, {scope: 'scoped'});
|
|
244
|
+
bindModule(parent, MODULE, { scope: 'scoped' });
|
|
110
245
|
expect(parent.get(MODULE_TOKEN)).toBe(container.get(MODULE_TOKEN));
|
|
111
246
|
expect(parent.get(QUERIES_TOKEN)).toBe(container.get(QUERIES_TOKEN));
|
|
112
247
|
});
|
|
@@ -115,10 +250,10 @@ describe('bindModule()', () => {
|
|
|
115
250
|
const parent = createContainer();
|
|
116
251
|
const container = createContainer(parent);
|
|
117
252
|
|
|
118
|
-
const destroy =
|
|
253
|
+
const destroy = vi.fn();
|
|
119
254
|
bindModule(parent, {
|
|
120
255
|
token: MODULE_TOKEN,
|
|
121
|
-
factory: (container) => ({...MODULE.factory(container), destroy}),
|
|
256
|
+
factory: (container) => ({ ...MODULE.factory(container), destroy }),
|
|
122
257
|
});
|
|
123
258
|
|
|
124
259
|
parent.resolve(MODULE_TOKEN);
|
|
@@ -134,12 +269,12 @@ describe('bindModule()', () => {
|
|
|
134
269
|
const parent = createContainer();
|
|
135
270
|
const container = createContainer(parent);
|
|
136
271
|
|
|
137
|
-
const destroy =
|
|
272
|
+
const destroy = vi.fn();
|
|
138
273
|
bindModule(
|
|
139
274
|
parent,
|
|
140
275
|
{
|
|
141
276
|
token: MODULE_TOKEN,
|
|
142
|
-
factory: (container) => ({...MODULE.factory(container), destroy}),
|
|
277
|
+
factory: (container) => ({ ...MODULE.factory(container), destroy }),
|
|
143
278
|
},
|
|
144
279
|
{
|
|
145
280
|
scope: 'scoped',
|
|
@@ -159,23 +294,23 @@ describe('bindModule()', () => {
|
|
|
159
294
|
});
|
|
160
295
|
|
|
161
296
|
it('should bind modules and binding entries from "imports" to the container', () => {
|
|
162
|
-
type TestModule = Module<{value: number}>;
|
|
297
|
+
type TestModule = Module<{ value: number }>;
|
|
163
298
|
|
|
164
299
|
const MODULE1_TOKEN = token<TestModule>();
|
|
165
300
|
const MODULE1: ModuleDeclaration<TestModule> = {
|
|
166
301
|
token: MODULE1_TOKEN,
|
|
167
|
-
factory: () => ({value: 1}),
|
|
302
|
+
factory: () => ({ value: 1 }),
|
|
168
303
|
};
|
|
169
304
|
|
|
170
305
|
const MODULE2_TOKEN = token<TestModule>();
|
|
171
306
|
const MODULE2: ModuleDeclaration<TestModule> = {
|
|
172
307
|
token: MODULE2_TOKEN,
|
|
173
|
-
factory: () => ({value: 2}),
|
|
308
|
+
factory: () => ({ value: 2 }),
|
|
174
309
|
};
|
|
175
310
|
|
|
176
311
|
const MODULE2_ALTERED: ModuleDeclaration<TestModule> = {
|
|
177
312
|
token: MODULE2_TOKEN,
|
|
178
|
-
factory: () => ({value: 22}),
|
|
313
|
+
factory: () => ({ value: 22 }),
|
|
179
314
|
};
|
|
180
315
|
|
|
181
316
|
const parent = createContainer();
|
|
@@ -188,7 +323,7 @@ describe('bindModule()', () => {
|
|
|
188
323
|
factory: () => ({}),
|
|
189
324
|
imports: [
|
|
190
325
|
MODULE1,
|
|
191
|
-
{module: MODULE2_ALTERED, options: {scope: 'scoped'}},
|
|
326
|
+
{ module: MODULE2_ALTERED, options: { scope: 'scoped' } },
|
|
192
327
|
],
|
|
193
328
|
}),
|
|
194
329
|
);
|
|
@@ -204,13 +339,13 @@ describe('bindModule()', () => {
|
|
|
204
339
|
const ARG_TOKEN = token<string>('arg');
|
|
205
340
|
const RESULT_TOKEN = token<string>('result');
|
|
206
341
|
|
|
207
|
-
type TestModule = Module<{value: string}>;
|
|
342
|
+
type TestModule = Module<{ value: string }>;
|
|
208
343
|
|
|
209
344
|
const MODULE1: ModuleDeclaration<TestModule> = declareModule({
|
|
210
345
|
beforeBinding: (container) =>
|
|
211
346
|
container.bindValue(ARG_TOKEN, container.resolve(ARG_TOKEN) + '2'),
|
|
212
|
-
factory: injectable((arg) => ({value: arg + '3'}), ARG_TOKEN),
|
|
213
|
-
exports: {value: RESULT_TOKEN},
|
|
347
|
+
factory: injectable((arg) => ({ value: arg + '3' }), ARG_TOKEN),
|
|
348
|
+
exports: { value: RESULT_TOKEN },
|
|
214
349
|
});
|
|
215
350
|
|
|
216
351
|
const container = createContainer();
|
|
@@ -293,23 +428,23 @@ describe('bindModule()', () => {
|
|
|
293
428
|
});
|
|
294
429
|
|
|
295
430
|
describe('bindModules()', () => {
|
|
296
|
-
type TestModule = Module<{value: number}>;
|
|
431
|
+
type TestModule = Module<{ value: number }>;
|
|
297
432
|
|
|
298
433
|
const MODULE1_TOKEN = token<TestModule>();
|
|
299
434
|
const MODULE1: ModuleDeclaration<TestModule> = {
|
|
300
435
|
token: MODULE1_TOKEN,
|
|
301
|
-
factory: () => ({value: 1}),
|
|
436
|
+
factory: () => ({ value: 1 }),
|
|
302
437
|
};
|
|
303
438
|
|
|
304
439
|
const MODULE2_TOKEN = token<TestModule>();
|
|
305
440
|
const MODULE2: ModuleDeclaration<TestModule> = {
|
|
306
441
|
token: MODULE2_TOKEN,
|
|
307
|
-
factory: () => ({value: 2}),
|
|
442
|
+
factory: () => ({ value: 2 }),
|
|
308
443
|
};
|
|
309
444
|
|
|
310
445
|
const MODULE2_ALTERED: ModuleDeclaration<TestModule> = {
|
|
311
446
|
token: MODULE2_TOKEN,
|
|
312
|
-
factory: () => ({value: 22}),
|
|
447
|
+
factory: () => ({ value: 22 }),
|
|
313
448
|
};
|
|
314
449
|
|
|
315
450
|
it('should bind modules and binding entries to the container', () => {
|
|
@@ -320,7 +455,7 @@ describe('bindModules()', () => {
|
|
|
320
455
|
|
|
321
456
|
bindModules(container, [
|
|
322
457
|
MODULE1,
|
|
323
|
-
{module: MODULE2_ALTERED, options: {scope: 'scoped'}},
|
|
458
|
+
{ module: MODULE2_ALTERED, options: { scope: 'scoped' } },
|
|
324
459
|
]);
|
|
325
460
|
|
|
326
461
|
expect(parent.get(MODULE1_TOKEN)).toBeUndefined();
|
|
@@ -336,16 +471,16 @@ describe('declareModule()', () => {
|
|
|
336
471
|
const container = createContainer();
|
|
337
472
|
|
|
338
473
|
const VALUE_TOKEN = token<number>();
|
|
339
|
-
const MODULE_TOKEN = token<Module<{value: number}>>();
|
|
474
|
+
const MODULE_TOKEN = token<Module<{ value: number }>>();
|
|
340
475
|
const MODULE = declareModule({
|
|
341
476
|
token: MODULE_TOKEN,
|
|
342
|
-
factory: () => ({value: 1}),
|
|
343
|
-
exports: {value: VALUE_TOKEN},
|
|
477
|
+
factory: () => ({ value: 1 }),
|
|
478
|
+
exports: { value: VALUE_TOKEN },
|
|
344
479
|
});
|
|
345
480
|
|
|
346
481
|
bindModule(container, MODULE);
|
|
347
482
|
expect(container.get(VALUE_TOKEN)).toBe(1);
|
|
348
|
-
expect(container.get(MODULE_TOKEN)).toEqual({value: 1});
|
|
483
|
+
expect(container.get(MODULE_TOKEN)).toEqual({ value: 1 });
|
|
349
484
|
});
|
|
350
485
|
|
|
351
486
|
it('should declare a binding for the anonymous module', () => {
|
|
@@ -353,8 +488,8 @@ describe('declareModule()', () => {
|
|
|
353
488
|
|
|
354
489
|
const VALUE_TOKEN = token<number>();
|
|
355
490
|
const MODULE = declareModule({
|
|
356
|
-
factory: () => ({value: 1}),
|
|
357
|
-
exports: {value: VALUE_TOKEN},
|
|
491
|
+
factory: () => ({ value: 1 }),
|
|
492
|
+
exports: { value: VALUE_TOKEN },
|
|
358
493
|
});
|
|
359
494
|
|
|
360
495
|
bindModule(container, MODULE);
|
|
@@ -368,14 +503,14 @@ describe('declareModuleBindings()', () => {
|
|
|
368
503
|
|
|
369
504
|
const VALUE1_TOKEN = token<number>();
|
|
370
505
|
const MODULE1 = declareModule({
|
|
371
|
-
factory: () => ({value: 1}),
|
|
372
|
-
exports: {value: VALUE1_TOKEN},
|
|
506
|
+
factory: () => ({ value: 1 }),
|
|
507
|
+
exports: { value: VALUE1_TOKEN },
|
|
373
508
|
});
|
|
374
509
|
|
|
375
510
|
const VALUE2_TOKEN = token<number>();
|
|
376
511
|
const MODULE2 = declareModule({
|
|
377
|
-
factory: () => ({value: 2}),
|
|
378
|
-
exports: {value: VALUE2_TOKEN},
|
|
512
|
+
factory: () => ({ value: 2 }),
|
|
513
|
+
exports: { value: VALUE2_TOKEN },
|
|
379
514
|
});
|
|
380
515
|
|
|
381
516
|
const MODULE_BINDINGS = declareModuleBindings([MODULE1, MODULE2]);
|