atomic-di 0.9.0-beta.1 → 0.9.1-beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. package/README.md +240 -1
  2. package/package.json +4 -10
package/README.md CHANGED
@@ -1 +1,240 @@
1
- Not documented yet.
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.0-beta.1",
3
+ "version": "0.9.1-beta.3",
4
4
  "description": "A toolset for containerless dependency injection.",
5
- "repository": {
6
- "type": "git",
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
  }