Skip to content

Commit

Permalink
Feature Add getWithTags method (#21)
Browse files Browse the repository at this point in the history
Co-authored-by: Igor Savin <[email protected]>
  • Loading branch information
cameronsmith and kibertoad authored Sep 20, 2023
1 parent e37b0f3 commit 4d2c797
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 2 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,51 @@ const awilixManager = new AwilixManager({
await awilixManager.executeInit() // this will not execute asyncInit, because consumer is disabled
await awilixManager.executeDispose() // this will not execute asyncDispose, because consumer is disabled
```

## Fetching dependencies based on tags

In some cases you may want to get dependencies based on a supplied list of tags.
You can use `tags` parameter in conjunction with the `getWithTags` method for that:

```js
import { AwilixManager } from 'awilix-manager'
import { asClass, createContainer } from 'awilix'

const diContainer = createContainer({
injectionMode: 'PROXY',
})

class QueueConsumerHighPriorityClass {
}

class QueueConsumerLowPriorityClass {
}

diContainer.register(
'dependency1',
asClass(QueueConsumerHighPriorityClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['queue', 'high-priority'],
}),
)
diContainer.register(
'dependency2',
asClass(QueueConsumerLowPriorityClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['queue', 'low-priority'],
}),
)

const awilixManager = new AwilixManager({
diContainer,
asyncInit: true,
asyncDispose: true,
})

// This will return dependency1 and dependency2
const result1 = awilixManager.getWithTags(diContainer, ['queue'])
// This will return only dependency2
const result2 = awilixManager.getWithTags(diContainer, ['queue', 'low-priority'])
```
8 changes: 7 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
export { AwilixManager, eagerInject, asyncInit, asyncDispose } from './lib/awilixManager'
export {
AwilixManager,
eagerInject,
asyncInit,
asyncDispose,
getWithTags,
} from './lib/awilixManager'
export type { AwilixManagerConfig } from './lib/awilixManager'
23 changes: 23 additions & 0 deletions lib/awilixManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare module 'awilix' {
asyncDispose?: boolean | string | ((instance: T) => Promise<unknown>)
asyncDisposePriority?: number // lower means it gets disposed earlier
eagerInject?: boolean | string
tags?: string[]
enabled?: boolean
}
}
Expand Down Expand Up @@ -39,6 +40,11 @@ export class AwilixManager {
async executeDispose() {
await asyncDispose(this.config.diContainer)
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
getWithTags(diContainer: AwilixContainer, tags: string[]): Record<string, any> {
return getWithTags(diContainer, tags)
}
}

export async function asyncInit(diContainer: AwilixContainer) {
Expand Down Expand Up @@ -83,6 +89,23 @@ export function eagerInject(diContainer: AwilixContainer) {
}
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function getWithTags(diContainer: AwilixContainer, tags: string[]): Record<string, any> {
const dependenciesWithTags = Object.entries(diContainer.registrations).filter((entry) => {
return (
entry[1].enabled !== false && tags.every((v) => entry[1].tags && entry[1].tags.includes(v))
)
})

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const resolvedComponents: Record<string, any> = {}
for (const entry of dependenciesWithTags) {
resolvedComponents[entry[0]] = diContainer.resolve(entry[0])
}

return resolvedComponents
}

export async function asyncDispose(diContainer: AwilixContainer) {
const dependenciesWithAsyncDispose = Object.entries(diContainer.registrations)
.filter((entry) => {
Expand Down
83 changes: 82 additions & 1 deletion test/awilixManager.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { asClass, createContainer } from 'awilix'
import { describe, expect, it } from 'vitest'

import { asyncDispose, asyncInit, AwilixManager, eagerInject } from '../lib/awilixManager'
import { asyncDispose, asyncInit, AwilixManager, eagerInject, getWithTags } from "../lib/awilixManager";

class AsyncInitClass {
isInitted = false
Expand Down Expand Up @@ -107,6 +107,87 @@ describe('awilixManager', () => {
expect(dependency3.isInitted).toBe(true)
})

it('execute getWithTags on registered dependencies with valid tags', async () => {
const diContainer = createContainer({
injectionMode: 'PROXY',
})
diContainer.register(
'dependency1',
asClass(AsyncInitClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['engine', 'google'],
}),
)
diContainer.register(
'dependency2',
asClass(AsyncInitClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['engine', 'google'],
}),
)

await asyncInit(diContainer)

const { dependency1, dependency2 } = diContainer.cradle
const expectItemFound = getWithTags(diContainer, ['engine'])
expect(expectItemFound).toStrictEqual({
dependency1: dependency1,
dependency2: dependency2,
})

const expectedItemNotFound = getWithTags(diContainer, ['engine', 'engine2'])
expect(expectedItemNotFound).toStrictEqual({})
})

it('execute awilixManager.getWithTags on registered dependencies with valid tags', async () => {
const diContainer = createContainer({
injectionMode: 'PROXY',
})

class QueueConsumerHighPriorityClass {
}

class QueueConsumerLowPriorityClass {
}

diContainer.register(
'dependency1',
asClass(QueueConsumerHighPriorityClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['queue', 'high-priority'],
}),
)
diContainer.register(
'dependency2',
asClass(QueueConsumerLowPriorityClass, {
lifetime: 'SINGLETON',
asyncInit: true,
tags: ['queue', 'low-priority'],
}),
)

const awilixManager = new AwilixManager({
diContainer,
asyncInit: true,
asyncDispose: true,
})

const { dependency1, dependency2 } = diContainer.cradle
const result1 = awilixManager.getWithTags(diContainer, ['queue'])
expect(result1).toStrictEqual({
dependency1: dependency1,
dependency2: dependency2,
})

const result2 = awilixManager.getWithTags(diContainer, ['queue', 'low-priority'])
expect(result2).toStrictEqual({
dependency2: dependency2,
})
})

it('does bit execute asyncInit on registered dependencies if disabled', async () => {
const diContainer = createContainer({
injectionMode: 'PROXY',
Expand Down

0 comments on commit 4d2c797

Please sign in to comment.