atomic-di 0.9.0-beta.1 → 0.9.1-beta.3
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 +240 -1
- package/package.json +4 -10
package/README.md
CHANGED
@@ -1 +1,240 @@
|
|
1
|
-
|
1
|
+
# atomic-di
|
2
|
+
|
3
|
+
> **This is not an IoC container or a service locator.**
|
4
|
+
|
5
|
+
This library provides a set of tools that implement missing features such as lifetimes, scopes and mocking in a pure factory-based dependency injection.
|
6
|
+
|
7
|
+
### Key features
|
8
|
+
|
9
|
+
- **Small & fast.** The usage is based on the use of a thin, performant abstraction that wraps factories, adding a couple of operations needed for resolution in a dynamic context.
|
10
|
+
- **Transparent.** All the logic for creating instances is written by the developer himself.
|
11
|
+
- **Non-invasive.** Does not require adding decorators, registrations or any additional logic to the business logic of the application.
|
12
|
+
- **Atomic.** There's no global container. The creation of instances occurs in factories that can be shared among themselves.
|
13
|
+
|
14
|
+
# Installation
|
15
|
+
|
16
|
+
You can use any package manager.
|
17
|
+
|
18
|
+
```bash
|
19
|
+
npm add atomic-di
|
20
|
+
```
|
21
|
+
|
22
|
+
```bash
|
23
|
+
npx jsr add @ensi/di
|
24
|
+
```
|
25
|
+
|
26
|
+
# Usage
|
27
|
+
|
28
|
+
Not written yet.
|
29
|
+
|
30
|
+
# API
|
31
|
+
|
32
|
+
## `Provider`
|
33
|
+
|
34
|
+
```ts
|
35
|
+
type Provider<T> = (context?: ResolutionContext) => T;
|
36
|
+
```
|
37
|
+
|
38
|
+
A function wrapper around the [resolver](#Resolver)(factory) for contextual dependency resolution. Resolves an instance by calling a resolver with an **optional** [resolution context](#ResolutionContext) that will be propagated throughout a dependency tree. Can act as a transient, singleton or scoped, which is [determined by the lifetime](#Lifetime) at creation.
|
39
|
+
|
40
|
+
```ts
|
41
|
+
provider({ scope, mocks });
|
42
|
+
```
|
43
|
+
|
44
|
+
When passing a [scope](#Scope) it will try to get an instance from it or create a new one and put it there.
|
45
|
+
|
46
|
+
When passing [mocks](#MockMap), it will try to get its own mock version and if there is one, it will use it instead of itself.
|
47
|
+
|
48
|
+
### `provide`
|
49
|
+
|
50
|
+
```ts
|
51
|
+
function provide<T>(lifetime: Lifetime, resolver: Resolver<T>): Provider<T>;
|
52
|
+
```
|
53
|
+
|
54
|
+
Creates a provider instance.
|
55
|
+
|
56
|
+
- `lifetime`: A resolution [lifetime](#Lifetime).
|
57
|
+
- `resolver`: A function that creates an instance using a [resolution context](#ResolutionContext). If the function calls other providers, the context **must** be passed to their calls.
|
58
|
+
|
59
|
+
```ts
|
60
|
+
const getInstance = provide("transient", (context) =>
|
61
|
+
createInstance(getOtherInstance(context)),
|
62
|
+
);
|
63
|
+
```
|
64
|
+
|
65
|
+
### `transient`
|
66
|
+
|
67
|
+
```ts
|
68
|
+
function transient<T>(resolver: Resolver<T>): Provider<T>;
|
69
|
+
```
|
70
|
+
|
71
|
+
An alias for [provide](#provide) with `"transient"` lifetime. Creates a [transient](#Lifetime) provider instance.
|
72
|
+
|
73
|
+
```ts
|
74
|
+
const getInstance = transient((context) =>
|
75
|
+
createInstance(...)
|
76
|
+
)
|
77
|
+
|
78
|
+
getInstance() !== getInstance()
|
79
|
+
```
|
80
|
+
|
81
|
+
### `singleton`
|
82
|
+
|
83
|
+
```ts
|
84
|
+
function singleton<T>(resolver: Resolver<T>): Provider<T>;
|
85
|
+
```
|
86
|
+
|
87
|
+
An alias for [provide](#provide) with `"singleton"` lifetime. Creates a [singleton](#Lifetime) provider instance.
|
88
|
+
|
89
|
+
```ts
|
90
|
+
const getInstance = singleton((context) =>
|
91
|
+
createInstance(...)
|
92
|
+
)
|
93
|
+
|
94
|
+
getInstance() === getInstance()
|
95
|
+
```
|
96
|
+
|
97
|
+
### `scoped`
|
98
|
+
|
99
|
+
```ts
|
100
|
+
function scoped<T>(resolver: Resolver<T>): Provider<T>;
|
101
|
+
```
|
102
|
+
|
103
|
+
An alias for [provide](#provide) with `"scoped"` lifetime. Creates a [scoped](#Lifetime) provider instance.
|
104
|
+
|
105
|
+
```ts
|
106
|
+
const getInstance = scoped((context) =>
|
107
|
+
createInstance(...)
|
108
|
+
)
|
109
|
+
|
110
|
+
getInstance() !== getInstance()
|
111
|
+
getInstance({ scope }) === getInstance({ scope })
|
112
|
+
```
|
113
|
+
|
114
|
+
## `Resolver`
|
115
|
+
|
116
|
+
```ts
|
117
|
+
type Resolver<T> = (context?: ResolutionContext) => T;
|
118
|
+
```
|
119
|
+
|
120
|
+
A function that creates an instance using a [resolution context](#ResolutionContext).
|
121
|
+
|
122
|
+
## `Lifetime`
|
123
|
+
|
124
|
+
```ts
|
125
|
+
type Lifetime = "transient" | "singleton" | "scoped";
|
126
|
+
```
|
127
|
+
|
128
|
+
A resolution lifetime. Passed when [creating a provider](#provide) to determine its behaviour.
|
129
|
+
|
130
|
+
- `"transient"` doesn't provide any modifications to a resolver behaviour, so the resolver will create a new instance on each request.
|
131
|
+
- `"singleton"` forces the resolver to create an instance once and return it in subsequent requests.
|
132
|
+
- `"scoped"` forces the resolver to take its instance from a provided [scope](#Scope) or create a new one and save it if there is none. If no scope is passed, it will create a new instance on each request.
|
133
|
+
|
134
|
+
## `ResolutionContext`
|
135
|
+
|
136
|
+
```ts
|
137
|
+
type ResolutionContext = {
|
138
|
+
scope?: Scope;
|
139
|
+
mocks?: MockMap;
|
140
|
+
};
|
141
|
+
```
|
142
|
+
|
143
|
+
An object that holds information about a [scope](#Scope) and provider [mocks](#MockMap). Passed to the [provider call](#Provider) to resolve scope instances and mock providers.
|
144
|
+
|
145
|
+
## `Scope`
|
146
|
+
|
147
|
+
```ts
|
148
|
+
type Scope = Map<Provider<any>, any>;
|
149
|
+
```
|
150
|
+
|
151
|
+
A `Map` of [providers](#Provider) to their instances. Passed to a provider call in a resolution context object to resolve instances of scoped providers within it.
|
152
|
+
|
153
|
+
```ts
|
154
|
+
const scope = createScope();
|
155
|
+
provider({ scope });
|
156
|
+
```
|
157
|
+
|
158
|
+
### `createScope`
|
159
|
+
|
160
|
+
```ts
|
161
|
+
function createScope(): Scope;
|
162
|
+
```
|
163
|
+
|
164
|
+
Creates a scope instance.
|
165
|
+
|
166
|
+
## `MockMap`
|
167
|
+
|
168
|
+
```ts
|
169
|
+
type MockMap = Omit<Map<Provider<any>, Provider<any>>, "set" | "get"> & {
|
170
|
+
set<T>(provider: Provider<T>, mock: Provider<T>): MockMap;
|
171
|
+
get<T>(provider: Provider<T>): Provider<T> | undefined;
|
172
|
+
};
|
173
|
+
```
|
174
|
+
|
175
|
+
A `Map` of [providers](#Provider) to providers of the same type. [Lifetime](#Lifetime) is not a part of `Provider` type, so you can use a different one if necessary. Passed to a provider call in a [resolution context](#ResolutionContext) object in order to replace providers with their mocks.
|
176
|
+
|
177
|
+
```ts
|
178
|
+
const otherProvider =
|
179
|
+
transitive(() => ...)
|
180
|
+
const otherProviderMock: typeof otherProvider =
|
181
|
+
scoped(() => ...)
|
182
|
+
|
183
|
+
const mocks = createMockMap()
|
184
|
+
mocks.set(otherProvider, otherProviderMock)
|
185
|
+
|
186
|
+
provider({ mocks })
|
187
|
+
```
|
188
|
+
|
189
|
+
### `createMockMap`
|
190
|
+
|
191
|
+
```ts
|
192
|
+
function createMockMap(): MockMap;
|
193
|
+
```
|
194
|
+
|
195
|
+
Creates a mock map instance.
|
196
|
+
|
197
|
+
## Bulk resolutions
|
198
|
+
|
199
|
+
### `resolveList`
|
200
|
+
|
201
|
+
```ts
|
202
|
+
function resolveList<const Providers extends ProviderList>(
|
203
|
+
providers: Providers,
|
204
|
+
context?: ResolutionContext,
|
205
|
+
): AwaitAllValuesInCollection<InferProviderCollectionResolutions<Providers>>;
|
206
|
+
```
|
207
|
+
|
208
|
+
- `providers`: A list of providers.
|
209
|
+
- `context`: A resolution context.
|
210
|
+
|
211
|
+
Calls every provider in a list with a provided resolution context and returns a list of resolutions. Returns a promise of a list of awaited resolutions if there's at least one promise in the resolutions.
|
212
|
+
|
213
|
+
```ts
|
214
|
+
const resolutions = resolveList([getA, getB, getC], { scope, mocks });
|
215
|
+
```
|
216
|
+
|
217
|
+
### `resolveMap`
|
218
|
+
|
219
|
+
```ts
|
220
|
+
function resolveMap<const Providers extends ProviderRecord>(
|
221
|
+
providers: Providers,
|
222
|
+
context?: ResolutionContext,
|
223
|
+
): AwaitAllValuesInCollection<InferProviderCollectionResolutions<Providers>>;
|
224
|
+
```
|
225
|
+
|
226
|
+
- `providers`: A map of providers.
|
227
|
+
- `context`: A resolution context.
|
228
|
+
|
229
|
+
Calsl every provider in a map with a provided resolution context and returns a map with identical keys but with resolutions in values instead. Returns a promise of a map of awaited resolutions if there's at least one promise in the resolutions.
|
230
|
+
|
231
|
+
```ts
|
232
|
+
const resolutionMap = resolveMap(
|
233
|
+
{ a: getA, b: getB, c: getC },
|
234
|
+
{ scope, mocks },
|
235
|
+
);
|
236
|
+
```
|
237
|
+
|
238
|
+
# Contribution
|
239
|
+
|
240
|
+
This is free and open source project licensed under the [MIT License](LICENSE). You could help its development by contributing via [pull requests](https://github.com/ncor/atomic-di/fork) or [submitting an issue](https://github.com/ncor/atomic-di/issues).
|
package/package.json
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
{
|
2
2
|
"name": "atomic-di",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.1-beta.3",
|
4
4
|
"description": "A toolset for containerless dependency injection.",
|
5
|
-
"repository":
|
6
|
-
|
7
|
-
"url": "https://github.com/ncor/atomic-di.git"
|
8
|
-
},
|
9
|
-
"bugs": {
|
10
|
-
"url": "https://github.com/ncor/atomic-di/issues"
|
11
|
-
},
|
5
|
+
"repository": "https://github.com/ncor/atomic-di",
|
6
|
+
"bugs": "https://github.com/ncor/atomic-di/issues",
|
12
7
|
"homepage": "https://github.com/ncor/atomic-di#readme",
|
13
8
|
"exports": {
|
14
9
|
".": {
|
@@ -32,7 +27,6 @@
|
|
32
27
|
},
|
33
28
|
"scripts": {
|
34
29
|
"build": "npx tsup",
|
35
|
-
"test": "pnpx vitest coverage --coverage"
|
36
|
-
"benchmark": "pnpx vitest benchmark"
|
30
|
+
"test": "pnpx vitest coverage --coverage"
|
37
31
|
}
|
38
32
|
}
|