1
1
import {
2
- ContainerKey ,
2
+ AsyncDependencyFactory ,
3
3
ReadableContainer ,
4
+ ReadableSyncContainer ,
4
5
SyncDependencyFactory ,
5
6
} from './container.ts' ;
6
- import { ParamsToResolverKeys , TupleO , Zip } from './util.ts' ;
7
+ import { ContainerKey , ParamsToResolverKeys , TupleO , Zip } from './util.ts' ;
7
8
8
9
/**
9
10
* Given a dependency factory, returns a new factory that will always resolve
10
11
* the same instance of the dependency.
11
12
*/
12
13
export function singleton <
13
14
TVal ,
14
- TDependencies extends Record < ContainerKey , unknown > ,
15
+ TSyncDependencies extends Record < ContainerKey , unknown > ,
15
16
> (
16
- // eslint-disable-next-line @typescript-eslint/ban-types
17
- factory : SyncDependencyFactory < TVal , ReadableContainer < TDependencies , { } > > ,
18
- // eslint-disable-next-line @typescript-eslint/ban-types
19
- ) : SyncDependencyFactory < TVal , ReadableContainer < TDependencies , { } > > {
17
+ factory : SyncDependencyFactory <
18
+ TVal ,
19
+ ReadableSyncContainer < TSyncDependencies >
20
+ > ,
21
+ ) : SyncDependencyFactory < TVal , ReadableSyncContainer < TSyncDependencies > > {
20
22
let result : Awaited < TVal > | undefined
21
23
22
24
return ( container ) => {
@@ -27,6 +29,33 @@ export function singleton<
27
29
}
28
30
}
29
31
32
+ /**
33
+ * Given a dependency factory, returns a new asynchronous factory that will
34
+ * always resolve the same instance of the dependency.
35
+ */
36
+ export function asyncSingleton <
37
+ TVal ,
38
+ TSyncDependencies extends Record < ContainerKey , unknown > ,
39
+ TAsyncDependencies extends Record < ContainerKey , unknown > ,
40
+ > (
41
+ factory : AsyncDependencyFactory <
42
+ TVal ,
43
+ ReadableContainer < TSyncDependencies , TAsyncDependencies >
44
+ > ,
45
+ ) : AsyncDependencyFactory <
46
+ TVal ,
47
+ ReadableContainer < TSyncDependencies , TAsyncDependencies >
48
+ > {
49
+ let result : TVal | undefined
50
+
51
+ return async ( container ) => {
52
+ if ( ! result ) {
53
+ result = await factory ( container )
54
+ }
55
+ return result
56
+ }
57
+ }
58
+
30
59
/**
31
60
* Given a function, and a list of named dependencies, creates a new dependency
32
61
* factory that will resolve a parameterless function wrapping the original
@@ -35,20 +64,20 @@ export function singleton<
35
64
export function func <
36
65
TParams extends readonly unknown [ ] ,
37
66
TReturn ,
38
- TDependencies extends ParamsToResolverKeys < TParams > ,
67
+ TSyncDependencies extends ParamsToResolverKeys < TParams > ,
39
68
> (
40
69
fn : ( ...args : TParams ) => Awaited < TReturn > ,
41
- ...args : TDependencies
70
+ ...args : TSyncDependencies
42
71
) : SyncDependencyFactory <
43
72
( ) => TReturn ,
44
- SyncFuncContainer < TParams , TDependencies >
73
+ SyncFuncContainer < TParams , TSyncDependencies >
45
74
> {
46
- return ( container : SyncFuncContainer < TParams , TDependencies > ) => {
75
+ return ( container : SyncFuncContainer < TParams , TSyncDependencies > ) => {
47
76
const resolvedArgs = args . map ( ( arg ) =>
48
77
container . resolve (
49
78
// This is ugly as hell, but I did not want to apply ts-ignore
50
79
arg as Parameters <
51
- SyncFuncContainer < TParams , TDependencies > [ 'resolve' ]
80
+ SyncFuncContainer < TParams , TSyncDependencies > [ 'resolve' ]
52
81
> [ 0 ] ,
53
82
) ,
54
83
) as unknown as TParams
@@ -89,11 +118,9 @@ export function constructor<
89
118
type SyncFuncContainer <
90
119
TParams extends readonly unknown [ ] ,
91
120
TSyncDependencies extends ParamsToResolverKeys < TParams > ,
92
- > = ReadableContainer <
121
+ > = ReadableSyncContainer <
93
122
TupleO <
94
123
// eslint-disable-next-line @typescript-eslint/no-explicit-any
95
124
Extract < Zip < TSyncDependencies , TParams > , readonly [ ContainerKey , any ] [ ] >
96
- > ,
97
- // eslint-disable-next-line @typescript-eslint/ban-types
98
- { }
125
+ >
99
126
>
0 commit comments