@@ -21,15 +21,22 @@ export class FastifyServer implements Process {
21
21
private port : number = 8080 ,
22
22
private host : string = "127.0.0.1"
23
23
) {
24
- for ( let route of routes ) {
24
+ /*
25
+ To handle limitations in Find My Way (Fastify's internal routing library)
26
+ Strontium provides a preprocess format for routes to prevent certain conflicts.
27
+ */
28
+ let processedRoutes = FastifyServer . preProcessRoutes ( routes )
29
+
30
+ for ( let route of processedRoutes ) {
25
31
switch ( route . method ) {
26
32
case "GET" :
27
33
this . server . get (
28
34
route . route ,
29
35
this . requestHandler (
30
36
route . endpointController ,
31
37
route . route ,
32
- "GET"
38
+ "GET" ,
39
+ route . metadata
33
40
)
34
41
)
35
42
break
@@ -39,7 +46,8 @@ export class FastifyServer implements Process {
39
46
this . requestHandler (
40
47
route . endpointController ,
41
48
route . route ,
42
- "POST"
49
+ "POST" ,
50
+ route . metadata
43
51
)
44
52
)
45
53
break
@@ -49,7 +57,8 @@ export class FastifyServer implements Process {
49
57
this . requestHandler (
50
58
route . endpointController ,
51
59
route . route ,
52
- "PATCH"
60
+ "PATCH" ,
61
+ route . metadata
53
62
)
54
63
)
55
64
break
@@ -59,7 +68,8 @@ export class FastifyServer implements Process {
59
68
this . requestHandler (
60
69
route . endpointController ,
61
70
route . route ,
62
- "PUT"
71
+ "PUT" ,
72
+ route . metadata
63
73
)
64
74
)
65
75
break
@@ -69,7 +79,8 @@ export class FastifyServer implements Process {
69
79
this . requestHandler (
70
80
route . endpointController ,
71
81
route . route ,
72
- "DELETE"
82
+ "DELETE" ,
83
+ route . metadata
73
84
)
74
85
)
75
86
break
@@ -79,14 +90,100 @@ export class FastifyServer implements Process {
79
90
this . requestHandler (
80
91
route . endpointController ,
81
92
route . route ,
82
- "OPTIONS"
93
+ "OPTIONS" ,
94
+ route . metadata
83
95
)
84
96
)
85
97
break
86
98
}
87
99
}
88
100
}
89
101
102
+ public static preProcessRoutes ( routes : RouterMap ) : RouterMap {
103
+ let processedRoutes : RouterMap = [ ]
104
+ for ( let route of routes ) {
105
+ // Check if there are any enum param blocks
106
+ let enumeratedBlocks = route . route . match (
107
+ / { ( [ a - z A - Z 0 - 9 _ - ] * ) \| ( [ a - z A - Z 0 - 9 _ , - ] * ) } / g
108
+ )
109
+
110
+ if ( enumeratedBlocks === null ) {
111
+ processedRoutes . push ( route )
112
+ } else {
113
+ const generatePermutations = (
114
+ index : number
115
+ ) : Array < Array < string > > => {
116
+ // Typescript correctly identifies this function may run when enumeratedBlocks is null
117
+ // however within this context that is not possible - so ! to overcome
118
+ let currentBlock = enumeratedBlocks ! [ index ]
119
+
120
+ let childPermutations : Array < Array < string > > = [ ]
121
+ if ( index < enumeratedBlocks ! . length - 1 ) {
122
+ childPermutations = generatePermutations ( index + 1 )
123
+ }
124
+
125
+ let permutations : Array < Array < string > > = [ ]
126
+
127
+ // Use a more direct method because the absence of "matchAll" in Node would make the RegEx method uglier
128
+ let fieldContents = currentBlock
129
+ . replace ( "{" , "" )
130
+ . replace ( "}" , "" )
131
+
132
+ let [
133
+ fieldName ,
134
+ serializedFieldValues ,
135
+ ] = fieldContents . split ( "|" )
136
+ let fieldValues = serializedFieldValues . split ( "," )
137
+
138
+ for ( let value of fieldValues ) {
139
+ if ( childPermutations . length === 0 ) {
140
+ permutations . push ( [ value ] )
141
+ } else {
142
+ for ( let childPermutation of childPermutations ) {
143
+ permutations . push ( [ value , ...childPermutation ] )
144
+ }
145
+ }
146
+ }
147
+
148
+ return permutations
149
+ }
150
+
151
+ let routePermutations = generatePermutations ( 0 )
152
+
153
+ for ( let permutation of routePermutations ) {
154
+ let pathPermutation = route . route
155
+ let parameters : { [ key : string ] : string } = {
156
+ ...( route . metadata || { } ) ,
157
+ }
158
+
159
+ for ( let i = 0 ; i < enumeratedBlocks . length ; i ++ ) {
160
+ let currentBlock = enumeratedBlocks [ i ]
161
+ let fieldContents = currentBlock
162
+ . replace ( "{" , "" )
163
+ . replace ( "}" , "" )
164
+ let [ fieldName ] = fieldContents . split ( "|" )
165
+
166
+ parameters [ fieldName ] = permutation [ i ]
167
+
168
+ pathPermutation = pathPermutation . replace (
169
+ currentBlock ,
170
+ permutation [ i ]
171
+ )
172
+ }
173
+
174
+ processedRoutes . push ( {
175
+ endpointController : route . endpointController ,
176
+ method : route . method ,
177
+ route : pathPermutation ,
178
+ metadata : parameters ,
179
+ } )
180
+ }
181
+ }
182
+ }
183
+
184
+ return processedRoutes
185
+ }
186
+
90
187
public isHealthy ( ) : boolean {
91
188
return this . isAlive
92
189
}
@@ -147,7 +244,8 @@ export class FastifyServer implements Process {
147
244
protected requestHandler (
148
245
controller : ConstructorOf < EndpointController > ,
149
246
path : string ,
150
- method : string
247
+ method : string ,
248
+ routeMetadata : { [ key : string ] : any } = { }
151
249
) : (
152
250
request : Fastify . FastifyRequest < any , any , any , any , any > ,
153
251
response : Fastify . FastifyReply < any >
@@ -197,7 +295,10 @@ export class FastifyServer implements Process {
197
295
headers : request . headers ,
198
296
query : request . query ,
199
297
params : request . params ,
200
- meta : this . getRequestMetadata ( request ) ,
298
+ meta : {
299
+ ...routeMetadata ,
300
+ ...this . getRequestMetadata ( request ) ,
301
+ } ,
201
302
} )
202
303
203
304
rawResponse = await endpointController . handle ( validatedInput )
0 commit comments