@lppedd/di-wise-neo 0.3.1 → 0.3.2
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 +64 -8
- package/dist/cjs/index.d.ts +26 -26
- package/dist/cjs/index.js +10 -10
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.d.mts +26 -26
- package/dist/es/index.mjs +9 -9
- package/dist/es/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
@@ -2,7 +2,13 @@
|
|
2
2
|
<div align="center">
|
3
3
|
<h1>di-wise-neo</h1>
|
4
4
|
<p>Lightweight, type-safe, flexible dependency injection library for TypeScript and JavaScript</p>
|
5
|
-
|
5
|
+
|
6
|
+
[](https://github.com/lppedd/di-wise-neo/actions/workflows/test.yml)
|
7
|
+
[](https://www.npmjs.com/package/@lppedd/di-wise-neo)
|
8
|
+
[](https://bundlejs.com/?q=@lppedd/di-wise-neo)
|
9
|
+
[](https://github.com/lppedd/di-wise-neo/blob/main/LICENSE)
|
10
|
+
|
11
|
+
<img src="./.github/images/neo-wall.jpg" alt="di-wise-neo" style="border: 3px solid black; border-radius: 15px;" />
|
6
12
|
<div><sub>yes, I like The Matrix</sub></div>
|
7
13
|
</div>
|
8
14
|
|
@@ -16,12 +22,14 @@
|
|
16
22
|
|
17
23
|
- [Why yet another library](#why-yet-another-library)
|
18
24
|
- [Installation](#installation)
|
25
|
+
- [API reference](#api-reference)
|
19
26
|
- [Ergonomics](#ergonomics)
|
20
27
|
- [Quickstart](#quickstart)
|
21
28
|
- [Container scopes](#container-scopes)
|
22
29
|
- [Token registration](#token-registration)
|
23
30
|
- [Function-based injection](#function-based-injection)
|
24
31
|
- [Decorator-based injection](#decorator-based-injection)
|
32
|
+
- [Behavioral decorators](#behavioral-decorators)
|
25
33
|
- [Testing support](#testing-support)
|
26
34
|
|
27
35
|
## Why yet another library
|
@@ -75,7 +83,7 @@ production needs.
|
|
75
83
|
## Installation
|
76
84
|
|
77
85
|
```sh
|
78
|
-
npm
|
86
|
+
npm i @lppedd/di-wise-neo
|
79
87
|
```
|
80
88
|
|
81
89
|
```sh
|
@@ -85,6 +93,9 @@ pnpm add @lppedd/di-wise-neo
|
|
85
93
|
```sh
|
86
94
|
yarn add @lppedd/di-wise-neo
|
87
95
|
```
|
96
|
+
## API reference
|
97
|
+
|
98
|
+
You can find the complete API reference at https://lppedd.github.io/di-wise-neo
|
88
99
|
|
89
100
|
## Ergonomics
|
90
101
|
|
@@ -139,7 +150,7 @@ const container = createContainer({
|
|
139
150
|
defaultScope: Scope.Container,
|
140
151
|
});
|
141
152
|
|
142
|
-
// Register our managed dependencies
|
153
|
+
// Register our managed dependencies in the container
|
143
154
|
container.register(ExtensionContext)
|
144
155
|
.register(SecretStore)
|
145
156
|
.register(ContributionRegistrar);
|
@@ -209,7 +220,7 @@ Alternatively, use an explicit `ClassProvider` object - useful when registering
|
|
209
220
|
an interface or abstract type:
|
210
221
|
|
211
222
|
```ts
|
212
|
-
const Store =
|
223
|
+
const Store = createType<Store>("Store");
|
213
224
|
container.register(Store, {
|
214
225
|
useClass: SecretStore, // class SecretStore implements Store
|
215
226
|
});
|
@@ -223,7 +234,7 @@ caching it according to the configured scope.
|
|
223
234
|
A lazily computed value can be registered using a factory function:
|
224
235
|
|
225
236
|
```ts
|
226
|
-
const Env =
|
237
|
+
const Env = createType<string>("Env")
|
227
238
|
container.register(Env, {
|
228
239
|
useFactory: () => isNode() ? "Node.js" : "browser",
|
229
240
|
});
|
@@ -237,7 +248,7 @@ according to the configured scope.
|
|
237
248
|
A static value - always taken as-is and unaffected by scopes - can be registered using:
|
238
249
|
|
239
250
|
```ts
|
240
|
-
const PID =
|
251
|
+
const PID = createType<number>("PID");
|
241
252
|
const processId = spawnProcess();
|
242
253
|
container.register(PID, {
|
243
254
|
useValue: processId,
|
@@ -253,7 +264,7 @@ Registers an alias to another token, allowing multiple identifiers to resolve to
|
|
253
264
|
Using the previous `PID` example, we can register a `TaskID` alias:
|
254
265
|
|
255
266
|
```ts
|
256
|
-
const TaskID =
|
267
|
+
const TaskID = createType<number>("TaskID");
|
257
268
|
container.register(TaskID, {
|
258
269
|
useExisting: PID,
|
259
270
|
});
|
@@ -424,10 +435,55 @@ export class ExtensionContext {
|
|
424
435
|
}
|
425
436
|
```
|
426
437
|
|
438
|
+
## Behavioral decorators
|
439
|
+
|
440
|
+
The library includes two behavioral decorators that influence how classes are registered in the container.
|
441
|
+
These decorators attach metadata to the class type, which is then interpreted by the container during registration.
|
442
|
+
|
443
|
+
### `@Scoped`
|
444
|
+
|
445
|
+
Specifies a default scope for the decorated class:
|
446
|
+
|
447
|
+
```ts
|
448
|
+
@Scoped(Scope.Container)
|
449
|
+
export class ExtensionContext {
|
450
|
+
/* ... */
|
451
|
+
}
|
452
|
+
```
|
453
|
+
|
454
|
+
Applying `@Scoped(Scope.Container)` to the `ExtensionContext` class instructs the DI container
|
455
|
+
to register it with the **Container** scope by default.
|
456
|
+
|
457
|
+
This default can be overridden by explicitly providing registration options:
|
458
|
+
|
459
|
+
```ts
|
460
|
+
container.register(
|
461
|
+
ExtensionContext,
|
462
|
+
{ useClass: ExtensionContext },
|
463
|
+
{ scope: Scope.Resolution },
|
464
|
+
);
|
465
|
+
```
|
466
|
+
|
467
|
+
In this example, `ExtensionContext` will be registered with **Resolution** scope instead.
|
468
|
+
|
469
|
+
### `@AutoRegister`
|
470
|
+
|
471
|
+
Enables automatic registration of the decorated class if it has not been registered explicitly.
|
472
|
+
|
473
|
+
```ts
|
474
|
+
@AutoRegister()
|
475
|
+
export class ExtensionContext {
|
476
|
+
/* ... */
|
477
|
+
}
|
478
|
+
|
479
|
+
// Resolve the class without prior registration. It works!
|
480
|
+
container.resolve(ExtensionContext);
|
481
|
+
```
|
482
|
+
|
427
483
|
## Testing support
|
428
484
|
|
429
485
|
Testing is an important part of software development, and dependency injection is meant to make it easier.
|
430
|
-
The
|
486
|
+
The container API exposes methods to more easily integrate with testing scenarios.
|
431
487
|
|
432
488
|
### `resetRegistry`
|
433
489
|
|
package/dist/cjs/index.d.ts
CHANGED
@@ -1,19 +1,3 @@
|
|
1
|
-
/**
|
2
|
-
* Constructor type.
|
3
|
-
*/
|
4
|
-
interface Constructor<Instance extends object> {
|
5
|
-
new (...args: any[]): Instance;
|
6
|
-
readonly name: string;
|
7
|
-
readonly length: number;
|
8
|
-
}
|
9
|
-
/**
|
10
|
-
* Token type.
|
11
|
-
*/
|
12
|
-
type Token<Value = any> = [Value] extends [object] ? Type<Value> | Constructor<Value> : Type<Value>;
|
13
|
-
/**
|
14
|
-
* Describes a {@link Token} array with at least one element.
|
15
|
-
*/
|
16
|
-
type Tokens<Value = any> = [Token<Value>, ...Token<Value>[]];
|
17
1
|
/**
|
18
2
|
* Type API.
|
19
3
|
*/
|
@@ -27,8 +11,8 @@ interface Type<A> {
|
|
27
11
|
*
|
28
12
|
* @example
|
29
13
|
* ```ts
|
30
|
-
* const A =
|
31
|
-
* const B =
|
14
|
+
* const A = createType<A>("A");
|
15
|
+
* const B = createType<B>("B");
|
32
16
|
*
|
33
17
|
* A.inter("I", B); // => Type<A & B>
|
34
18
|
* ```
|
@@ -39,25 +23,41 @@ interface Type<A> {
|
|
39
23
|
*
|
40
24
|
* @example
|
41
25
|
* ```ts
|
42
|
-
* const A =
|
43
|
-
* const B =
|
26
|
+
* const A = createType<A>("A");
|
27
|
+
* const B = createType<B>("B");
|
44
28
|
*
|
45
29
|
* A.union("U", B); // => Type<A | B>
|
46
30
|
* ```
|
47
31
|
*/
|
48
32
|
union<B>(typeName: string, B: Type<B>): Type<A | B>;
|
49
33
|
}
|
34
|
+
/**
|
35
|
+
* Constructor type.
|
36
|
+
*/
|
37
|
+
interface Constructor<Instance extends object> {
|
38
|
+
new (...args: any[]): Instance;
|
39
|
+
readonly name: string;
|
40
|
+
readonly length: number;
|
41
|
+
}
|
42
|
+
/**
|
43
|
+
* Token type.
|
44
|
+
*/
|
45
|
+
type Token<Value = any> = [Value] extends [object] ? Type<Value> | Constructor<Value> : Type<Value>;
|
46
|
+
/**
|
47
|
+
* Describes a {@link Token} array with at least one element.
|
48
|
+
*/
|
49
|
+
type Tokens<Value = any> = [Token<Value>, ...Token<Value>[]];
|
50
50
|
/**
|
51
51
|
* Create a type token.
|
52
52
|
*
|
53
53
|
* @example
|
54
54
|
* ```ts
|
55
|
-
* const Spell =
|
55
|
+
* const Spell = createType<Spell>("Spell");
|
56
56
|
* ```
|
57
57
|
*
|
58
58
|
* @__NO_SIDE_EFFECTS__
|
59
59
|
*/
|
60
|
-
declare function
|
60
|
+
declare function createType<T>(typeName: string): Type<T>;
|
61
61
|
|
62
62
|
/**
|
63
63
|
* Provides a class instance for a token via a class constructor.
|
@@ -115,7 +115,7 @@ interface RegistrationOptions {
|
|
115
115
|
* ```ts
|
116
116
|
* class Wizard {
|
117
117
|
* wand = inject(
|
118
|
-
*
|
118
|
+
* build(() => {
|
119
119
|
* const wand = inject(Wand);
|
120
120
|
* wand.owner = this;
|
121
121
|
* // ...
|
@@ -127,7 +127,7 @@ interface RegistrationOptions {
|
|
127
127
|
*
|
128
128
|
* @__NO_SIDE_EFFECTS__
|
129
129
|
*/
|
130
|
-
declare function
|
130
|
+
declare function build<Value>(factory: (...args: []) => Value): Type<Value>;
|
131
131
|
|
132
132
|
/**
|
133
133
|
* Container creation options.
|
@@ -768,5 +768,5 @@ interface Middleware {
|
|
768
768
|
*/
|
769
769
|
declare function applyMiddleware(container: Container, middlewares: Middleware[]): Container;
|
770
770
|
|
771
|
-
export { AutoRegister,
|
772
|
-
export type { ClassProvider, Constructor, Container, ContainerOptions, ExistingProvider, FactoryProvider, Middleware, MiddlewareComposer, Provider, RegistrationOptions, Token, TokenRef, Tokens, TokensRef, ValueProvider };
|
771
|
+
export { AutoRegister, Inject, InjectAll, Injectable, Injector, Optional, OptionalAll, Scope, Scoped, applyMiddleware, build, createContainer, createType, forwardRef, inject, injectAll, injectBy };
|
772
|
+
export type { ClassProvider, Constructor, Container, ContainerOptions, ExistingProvider, FactoryProvider, Middleware, MiddlewareComposer, Provider, RegistrationOptions, Token, TokenRef, Tokens, TokensRef, Type, ValueProvider };
|
package/dist/cjs/index.js
CHANGED
@@ -235,15 +235,15 @@ const Scope = {
|
|
235
235
|
*
|
236
236
|
* @example
|
237
237
|
* ```ts
|
238
|
-
* const Spell =
|
238
|
+
* const Spell = createType<Spell>("Spell");
|
239
239
|
* ```
|
240
240
|
*
|
241
241
|
* @__NO_SIDE_EFFECTS__
|
242
|
-
*/ function
|
242
|
+
*/ function createType(typeName) {
|
243
243
|
const type = {
|
244
244
|
name: `Type<${typeName}>`,
|
245
|
-
inter:
|
246
|
-
union:
|
245
|
+
inter: createType,
|
246
|
+
union: createType,
|
247
247
|
toString () {
|
248
248
|
return type.name;
|
249
249
|
}
|
@@ -349,7 +349,7 @@ function isBuilder(provider) {
|
|
349
349
|
* ```ts
|
350
350
|
* class Wizard {
|
351
351
|
* wand = inject(
|
352
|
-
*
|
352
|
+
* build(() => {
|
353
353
|
* const wand = inject(Wand);
|
354
354
|
* wand.owner = this;
|
355
355
|
* // ...
|
@@ -360,8 +360,8 @@ function isBuilder(provider) {
|
|
360
360
|
* ```
|
361
361
|
*
|
362
362
|
* @__NO_SIDE_EFFECTS__
|
363
|
-
*/ function
|
364
|
-
const token =
|
363
|
+
*/ function build(factory) {
|
364
|
+
const token = createType(`Build<${getTypeName(factory)}>`);
|
365
365
|
const provider = {
|
366
366
|
useFactory: factory
|
367
367
|
};
|
@@ -961,7 +961,7 @@ function OptionalAll(token) {
|
|
961
961
|
* const wizard = container.resolve(Wizard);
|
962
962
|
* wizard.getWand(); // => Wand
|
963
963
|
* ```
|
964
|
-
*/ const Injector = /*@__PURE__*/
|
964
|
+
*/ const Injector = /*@__PURE__*/ build(function Injector() {
|
965
965
|
const context = ensureInjectionContext(Injector);
|
966
966
|
const resolution = context.resolution;
|
967
967
|
const dependentFrame = resolution.stack.peek();
|
@@ -1036,7 +1036,6 @@ function OptionalAll(token) {
|
|
1036
1036
|
}
|
1037
1037
|
|
1038
1038
|
exports.AutoRegister = AutoRegister;
|
1039
|
-
exports.Build = Build;
|
1040
1039
|
exports.Inject = Inject;
|
1041
1040
|
exports.InjectAll = InjectAll;
|
1042
1041
|
exports.Injectable = Injectable;
|
@@ -1045,9 +1044,10 @@ exports.Optional = Optional;
|
|
1045
1044
|
exports.OptionalAll = OptionalAll;
|
1046
1045
|
exports.Scope = Scope;
|
1047
1046
|
exports.Scoped = Scoped;
|
1048
|
-
exports.Type = Type;
|
1049
1047
|
exports.applyMiddleware = applyMiddleware;
|
1048
|
+
exports.build = build;
|
1050
1049
|
exports.createContainer = createContainer;
|
1050
|
+
exports.createType = createType;
|
1051
1051
|
exports.forwardRef = forwardRef;
|
1052
1052
|
exports.inject = inject;
|
1053
1053
|
exports.injectAll = injectAll;
|