Skip to content

Commit 37b58a1

Browse files
authored
Add containerKeyValues function (#31)
1 parent d51f5f0 commit 37b58a1

File tree

13 files changed

+102
-27
lines changed

13 files changed

+102
-27
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [0.2.2]
4+
5+
- Add `containerKeyValues` function
6+
37
## [0.2.1]
48

59
- Change behaviour of `IContainerBuilder.define` so that already-defined services are not overwritten

README.md

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -173,38 +173,73 @@ const myCustomLoggingModule: ContainerModule<
173173
)
174174
```
175175

176-
We can also use decorators to achieve features that aren't explicitly implemented in this library, such as service tagging, which we can do by defining a service as an array:
176+
We can also use decorators to achieve features that aren't explicitly implemented in this library, such as service tagging, which we can do by defining a service as a key-value object (actually, a simple array might do for some cases but using key-values prevents accidental duplicates if modules are reused):
177177

178178
```typescript
179-
import type { ContainerModule } from '@mgdigital/tsinject'
179+
import type { ContainerKey, ContainerModule } from '@mgdigital/tsinject'
180+
import { containerKeyValues } from '@mgdigital/tsinject'
181+
182+
// Assume a type of service that we wish to tag, along with a sevice that depends on the tagged services.
180183

181-
type TaggedServiceType = { foo: string }
184+
class TaggedService {}
185+
186+
class TaggedServiceConsumer {
187+
constructor (
188+
public readonly taggedServices: TaggedService[]
189+
) {}
190+
}
182191

183192
const serviceTag = Symbol('serviceTag')
193+
const taggedServiceConsumer = Symbol('taggedServiceConsumer')
184194

185-
type ServiceMap = {
186-
[serviceTag]: TaggedServiceType[]
195+
type ParentModuleServiceMap = {
196+
// `TaggedServiceConsumer` depends on an array, but using an object here prevents accidental duplicates.
197+
[serviceTag]: Record<ContainerKey, TaggedService>
198+
[taggedServiceConsumer]: TaggedServiceConsumer
187199
}
188200

189-
const myModule: ContainerModule<
190-
ServiceMap
201+
const parentModule: ContainerModule<
202+
ParentModuleServiceMap
191203
> = builder => builder
204+
// Define an empty object of tagged services
192205
.define(
193206
serviceTag,
194-
() => []
207+
() => ({})
195208
)
209+
.define(
210+
taggedServiceConsumer,
211+
container => new TaggedServiceConsumer(
212+
// This utility method converts the tagged service object to an array
213+
containerKeyValues(
214+
container.get(serviceTag)
215+
)
216+
)
217+
)
218+
219+
// Then define child modules that will provide tagged services
196220

197-
const myOtherModule: ContainerModule<
198-
ServiceMap
221+
const taggedService = Symbol('taggedService')
222+
223+
type ChildModuleServiceMap = {
224+
[taggedService]: TaggedService
225+
}
226+
227+
const childModule: ContainerModule<
228+
ParentModuleServiceMap &
229+
ChildModuleServiceMap
199230
> = builder => builder
200-
.use(myModule)
231+
.use(parentModule)
232+
.define(
233+
taggedService,
234+
() => new TaggedService()
235+
)
201236
.decorate(
202237
serviceTag,
203238
// Add a service to the array of already tagged services
204-
factory => container => [
239+
factory => container => ({
205240
...factory(container),
206-
{ foo: 'bar' }
207-
]
241+
[taggedService]: container.get(taggedService)
242+
})
208243
)
209244
```
210245

docs/assets/search.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)