3
3
// This file is licensed under the MIT License.
4
4
// License text available at https://opensource.org/licenses/MIT
5
5
6
- import { Binding } from './binding' ;
6
+ import { Binding , ValueOrPromise , BoundValue } from './binding' ;
7
7
import { Injection } from './inject' ;
8
+ import { isPromise } from './is-promise' ;
8
9
import * as debugModule from 'debug' ;
9
10
import { DecoratorFactory } from '@loopback/metadata' ;
10
11
11
12
const debugSession = debugModule ( 'loopback:context:resolver:session' ) ;
12
13
const getTargetName = DecoratorFactory . getTargetName ;
14
+
15
+ /**
16
+ * A function to be executed with the resolution session
17
+ */
18
+ export type ResolutionAction = (
19
+ session ?: ResolutionSession ,
20
+ ) => ValueOrPromise < BoundValue > ;
21
+
13
22
/**
14
23
* Object to keep states for a session to resolve bindings and their
15
24
* dependencies within a context
@@ -42,7 +51,7 @@ export class ResolutionSession {
42
51
* @param binding Binding
43
52
* @param session Resolution session
44
53
*/
45
- static enterBinding (
54
+ private static enterBinding (
46
55
binding : Binding ,
47
56
session ?: ResolutionSession ,
48
57
) : ResolutionSession {
@@ -51,12 +60,48 @@ export class ResolutionSession {
51
60
return session ;
52
61
}
53
62
63
+ /**
64
+ * Run the given action with the given binding and session
65
+ * @param action A function to do some work with the resolution session
66
+ * @param binding The current binding
67
+ * @param session The current resolution session
68
+ */
69
+ static runWithBinding (
70
+ action : ResolutionAction ,
71
+ binding : Binding ,
72
+ session ?: ResolutionSession ,
73
+ ) {
74
+ const resolutionSession = ResolutionSession . enterBinding ( binding , session ) ;
75
+ let result : ValueOrPromise < BoundValue > ;
76
+ try {
77
+ result = action ( resolutionSession ) ;
78
+ } catch ( e ) {
79
+ resolutionSession . popBinding ( ) ;
80
+ throw e ;
81
+ }
82
+ if ( isPromise ( result ) ) {
83
+ result = result . then (
84
+ val => {
85
+ resolutionSession . popBinding ( ) ;
86
+ return val ;
87
+ } ,
88
+ err => {
89
+ resolutionSession . popBinding ( ) ;
90
+ throw err ;
91
+ } ,
92
+ ) ;
93
+ } else {
94
+ resolutionSession . popBinding ( ) ;
95
+ }
96
+ return result ;
97
+ }
98
+
54
99
/**
55
100
* Push an injection into the session
56
101
* @param injection Injection
57
102
* @param session Resolution session
58
103
*/
59
- static enterInjection (
104
+ private static enterInjection (
60
105
injection : Injection ,
61
106
session ?: ResolutionSession ,
62
107
) : ResolutionSession {
@@ -65,6 +110,45 @@ export class ResolutionSession {
65
110
return session ;
66
111
}
67
112
113
+ /**
114
+ * Run the given action with the given injection and session
115
+ * @param action A function to do some work with the resolution session
116
+ * @param binding The current injection
117
+ * @param session The current resolution session
118
+ */
119
+ static runWithInjection (
120
+ action : ResolutionAction ,
121
+ injection : Injection ,
122
+ session ?: ResolutionSession ,
123
+ ) {
124
+ const resolutionSession = ResolutionSession . enterInjection (
125
+ injection ,
126
+ session ,
127
+ ) ;
128
+ let result : ValueOrPromise < BoundValue > ;
129
+ try {
130
+ result = action ( resolutionSession ) ;
131
+ } catch ( e ) {
132
+ resolutionSession . popInjection ( ) ;
133
+ throw e ;
134
+ }
135
+ if ( isPromise ( result ) ) {
136
+ result = result . then (
137
+ val => {
138
+ resolutionSession . popInjection ( ) ;
139
+ return val ;
140
+ } ,
141
+ err => {
142
+ resolutionSession . popInjection ( ) ;
143
+ throw err ;
144
+ } ,
145
+ ) ;
146
+ } else {
147
+ resolutionSession . popInjection ( ) ;
148
+ }
149
+ return result ;
150
+ }
151
+
68
152
/**
69
153
* Describe the injection for debugging purpose
70
154
* @param injection
0 commit comments