@@ -24,29 +24,25 @@ import * as fs from 'fs'
24
24
import * as yaml from 'js-yaml'
25
25
26
26
/**
27
- * Scan the API folders in the specification to locate examples
27
+ * Scan the API folders in the specification to locate examples
28
28
* for all the API endpoints. Then add the examples to the model.
29
29
*/
30
30
export default class ExamplesProcessor {
31
-
32
31
specsFolder : string
33
32
34
- constructor ( specsFolder : string )
35
- {
33
+ constructor ( specsFolder : string ) {
36
34
this . specsFolder = specsFolder
37
35
}
38
36
39
- // Add request and response examples for all the endpoints in the model.
37
+ // Add request and response examples for all the endpoints in the model.
40
38
// Note that the 'jsonSpec' is a parameter that is passed to a 'Step'.
41
39
// We don't need that parameter for the the 'addExamples' functionality.
42
40
async addExamples ( model : model . Model , jsonSpec : Map < string , JsonSpec > ) : Promise < model . Model > {
43
41
const requestExamplesProcessor = new RequestExamplesProcessor ( model , this . specsFolder )
44
42
const responseExamplesProcessor = new ResponseExamplesProcessor ( model , this . specsFolder )
45
43
for ( const endpoint of model . endpoints ) {
46
- if ( endpoint . request != null )
47
- requestExamplesProcessor . addExamples ( endpoint . request )
48
- if ( endpoint . response != null )
49
- responseExamplesProcessor . addExamples ( endpoint . response )
44
+ if ( endpoint . request != null ) { requestExamplesProcessor . addExamples ( endpoint . request ) }
45
+ if ( endpoint . response != null ) { responseExamplesProcessor . addExamples ( endpoint . response ) }
50
46
}
51
47
return model
52
48
}
@@ -65,18 +61,18 @@ class BaseExamplesProcessor {
65
61
}
66
62
67
63
// Log a 'warning' message.
68
- warning ( message : string ) : void {
69
- console . warn ( " === [ExamplesProcessor]: " + message )
64
+ warning ( message : string ) : void {
65
+ console . warn ( ' === [ExamplesProcessor]: ' + message )
70
66
}
71
67
72
- // Get all the subfolders in a folder.
68
+ // Get all the subfolders in a folder.
73
69
getSubfolders ( folderPath : string ) : string [ ] {
74
70
const entries = fs . readdirSync ( folderPath , { withFileTypes : true } )
75
71
const folders = entries
76
72
. filter ( entry => entry . isDirectory ( ) )
77
73
. map ( entry => entry . name )
78
74
return folders
79
- }
75
+ }
80
76
81
77
// Get all the files in a folder.
82
78
getFilesInFolder ( folderPath : string ) : string [ ] {
@@ -90,39 +86,41 @@ class BaseExamplesProcessor {
90
86
// Check if a path exists and is a directory.
91
87
isDirectory ( path : string ) : boolean {
92
88
try {
93
- const stats = fs . statSync ( path ) ;
94
- return stats . isDirectory ( ) ;
89
+ const stats = fs . statSync ( path )
90
+ return stats . isDirectory ( )
95
91
} catch ( error ) {
96
92
if ( error . code === 'ENOENT' ) {
97
93
// Path does not exist
98
- return false ;
94
+ return false
99
95
} else {
100
96
// Other error, rethrow
101
- throw error ;
97
+ throw error
102
98
}
103
99
}
104
100
}
105
101
106
102
// Given the spec location of a request or response,
107
103
// return the path to the examples folder for that
108
104
// request or response.
109
- getExamplesFolder ( specLocation : string ) : string | undefined {
105
+ getExamplesFolder ( specLocation : string ) : string | undefined {
110
106
const specDir = path . dirname ( specLocation )
111
107
const specPath = path . join ( this . specsFolder , specDir )
112
- const examplesFolder = path . join ( specPath , "examples" )
113
- if ( this . isDirectory ( examplesFolder ) )
114
- return examplesFolder
108
+ const examplesFolder = path . join ( specPath , 'examples' )
109
+ if ( this . isDirectory ( examplesFolder ) ) {
110
+ return examplesFolder
111
+ }
115
112
return undefined
116
113
}
117
114
118
115
// Given an examples request or response folder, return all the
119
116
// valid example files in that folder.
120
117
getExampleFiles ( folder : string ) : string [ ] {
121
- if ( ! this . isDirectory ( folder ) )
118
+ if ( ! this . isDirectory ( folder ) ) {
122
119
return [ ]
123
- // Currently we only allow YAML example files.
120
+ }
121
+ // Currently we only allow YAML example files.
124
122
const exampleFiles = this . getFilesInFolder ( folder )
125
- . filter ( file => file . endsWith ( '.yml' ) || file . endsWith ( '.yaml' ) )
123
+ . filter ( file => file . endsWith ( '.yml' ) || file . endsWith ( '.yaml' ) )
126
124
if ( exampleFiles . length === 0 ) {
127
125
this . warning ( `No example files found in ${ folder } ` )
128
126
return [ ]
@@ -132,34 +130,33 @@ class BaseExamplesProcessor {
132
130
133
131
// Look up all the example files in a folder. Use the filename without extension
134
132
// as the name of the example, and the YAML content as the example value.
135
- // Return a map of example names to example values.
136
- getExampleMap ( folder : string ) : Map < string , model . Example > {
133
+ // Return a map of example names to example values.
134
+ getExampleMap ( folder : string ) : Map < string , model . Example > {
137
135
const exampleFiles = this . getExampleFiles ( folder )
138
136
const examples = new Map < string , model . Example > ( )
139
137
for ( const fileName of exampleFiles ) {
140
- const filePath = path . join ( folder , fileName )
138
+ const filePath = path . join ( folder , fileName )
141
139
const exampleFileContent = fs . readFileSync ( filePath , 'utf8' )
142
140
const exampleName = path . basename ( fileName , path . extname ( fileName ) )
143
141
const example : model . Example = yaml . load ( exampleFileContent )
144
- // Some of the example files set their 'value' as a JSON string,
142
+ // Some of the example files set their 'value' as a JSON string,
145
143
// and some files set their 'value' as an object. For consistency,
146
144
// if the value is not a JSON string, convert it to a JSON string.
147
145
if ( typeof example . value !== 'string' ) {
148
146
// Convert to prettified JSON string
149
- example . value = JSON . stringify ( example . value , null , 2 )
150
- }
147
+ example . value = JSON . stringify ( example . value , null , 2 )
148
+ }
151
149
examples [ exampleName ] = example
152
150
}
153
151
return examples
154
- }
152
+ }
155
153
}
156
154
157
155
/*
158
156
* Class to add the examples for an API request
159
157
*/
160
158
class RequestExamplesProcessor extends BaseExamplesProcessor {
161
-
162
- // Traverse all the types in the model to find a type that is
159
+ // Traverse all the types in the model to find a type that is
163
160
// of type 'request' and has the same name and namespace as the request.
164
161
getRequestDefinition ( model : model . Model , request : model . TypeName ) : model . Request {
165
162
for ( const type of model . types ) {
@@ -174,32 +171,34 @@ class RequestExamplesProcessor extends BaseExamplesProcessor {
174
171
175
172
// Given the spec location, return the request examples folder, if it exists.
176
173
getExamplesRequestSubfolder ( examplesSubfolder : string ) : string | undefined {
177
- const subFolder = path . join ( examplesSubfolder , " request" )
178
- if ( this . isDirectory ( subFolder ) )
174
+ const subFolder = path . join ( examplesSubfolder , ' request' )
175
+ if ( this . isDirectory ( subFolder ) ) {
179
176
return subFolder
177
+ }
180
178
return undefined
181
179
}
182
180
183
181
// Find all the request examples for this request and add them to the model.
184
182
addExamples ( request : model . TypeName ) : void {
185
183
const requestDefinition = this . getRequestDefinition ( this . model , request )
186
184
const examplesFolder = this . getExamplesFolder ( requestDefinition . specLocation )
187
- if ( ! examplesFolder )
185
+ if ( examplesFolder === undefined ) {
188
186
return
189
- // Get the request examples subfolder.
187
+ }
188
+ // Get the request examples subfolder.
190
189
const examplesRequestSubfolder = this . getExamplesRequestSubfolder ( examplesFolder )
191
190
// If there is an examples/request folder, add the request examples to the model.
192
- if ( examplesRequestSubfolder )
191
+ if ( examplesRequestSubfolder !== undefined ) {
193
192
requestDefinition . examples = this . getExampleMap ( examplesRequestSubfolder )
193
+ }
194
194
}
195
195
}
196
196
197
197
/*
198
198
* Class to add the examples for an API response
199
199
*/
200
200
class ResponseExamplesProcessor extends BaseExamplesProcessor {
201
-
202
- // Traverse all the types in the model to find a type that is
201
+ // Traverse all the types in the model to find a type that is
203
202
// of type 'response' and has the same name and namespace as the response.
204
203
getResponseDefinition ( model : model . Model , response : model . TypeName ) : model . Response {
205
204
for ( const type of model . types ) {
@@ -209,51 +208,54 @@ class ResponseExamplesProcessor extends BaseExamplesProcessor {
209
208
}
210
209
}
211
210
}
212
- throw new Error ( `Can't find the request definiton for ${ response . namespace } .${ response . name } ` )
211
+ throw new Error ( `Can't find the response definiton for ${ response . namespace } .${ response . name } ` )
213
212
}
214
213
215
214
// Given the spec location, return the response example folders if they exists.
216
215
// A response example folder can be of either of these forms:
217
216
// response
218
217
// {nnn}_response
219
218
// Where {nnn} is the HTTP response code. If the folder is named 'response',
220
- // assume that the response code is 200, otherwise pick up the response code
219
+ // assume that the response code is 200, otherwise pick up the response code
221
220
// from the folder name.
222
- // Return a map of status code to the folder path.
221
+ // Return a map of status code to the folder path.
223
222
getExamplesResponseSubfolderMap ( examplesSubfolder : string ) : Map < string , string > | undefined {
224
223
const subfolders = this . getSubfolders ( examplesSubfolder )
225
224
// If we have a "response" subfolder, stop there and return.
226
- // We should not have a mix of response and {nnn}_response folders.
227
- if ( " response" in subfolders ) {
228
- const response_subfolder = path . join ( examplesSubfolder , " response" )
229
- return new Map ( [ [ " 200" , response_subfolder ] ] )
225
+ // We should not have a mix of response and {nnn}_response folders.
226
+ if ( ' response' in subfolders ) {
227
+ const responseSubfolder = path . join ( examplesSubfolder , ' response' )
228
+ return new Map ( [ [ ' 200' , responseSubfolder ] ] )
230
229
}
231
230
// Look for subfolders of the format '{nnn}_response'.
232
- const rspSubfolders = subfolders . filter ( folder => folder . endsWith ( " _response" ) )
231
+ const rspSubfolders = subfolders . filter ( folder => folder . endsWith ( ' _response' ) )
233
232
const responseTypeMap = new Map < string , string > ( )
234
233
for ( const rspSubfolder of rspSubfolders ) {
235
234
const match = rspSubfolder . match ( / ^ ( [ 0 - 9 ] { 3 } ) _ r e s p o n s e $ / )
236
- if ( ! match )
235
+ if ( match == null ) {
237
236
throw new Error ( `Unexpected response folder: ${ rspSubfolder } ` )
237
+ }
238
238
const statusCode = match [ 1 ]
239
239
const responseSubfolder = path . join ( examplesSubfolder , rspSubfolder )
240
- responseTypeMap . set ( statusCode , responseSubfolder )
240
+ responseTypeMap . set ( statusCode , responseSubfolder )
241
241
}
242
242
return responseTypeMap
243
243
}
244
244
245
245
// Find all the response examples for this request and add them to the model.
246
246
addExamples ( response : model . TypeName ) : void {
247
247
const responseDefinition = this . getResponseDefinition ( this . model , response )
248
- const examplesFolder = this . getExamplesFolder ( responseDefinition . specLocation )
249
- if ( ! examplesFolder )
248
+ const examplesFolder = this . getExamplesFolder ( responseDefinition . specLocation )
249
+ if ( examplesFolder === undefined ) {
250
250
return
251
- // Get a map of status code to response example subfolder.
251
+ }
252
+ // Get a map of status code to response example subfolder.
252
253
const examplesResponseSubfolderMap = this . getExamplesResponseSubfolderMap ( examplesFolder )
253
- const examples200ResponseSubfolder = examplesResponseSubfolderMap ?. get ( " 200" )
254
- // If there is an examples/response or examples/200_response folder,
254
+ const examples200ResponseSubfolder = examplesResponseSubfolderMap ?. get ( ' 200' )
255
+ // If there is an examples/response or examples/200_response folder,
255
256
// add the response examples to the model.
256
- if ( examples200ResponseSubfolder )
257
+ if ( examples200ResponseSubfolder !== undefined ) {
257
258
responseDefinition . examples = this . getExampleMap ( examples200ResponseSubfolder )
259
+ }
258
260
}
259
261
}
0 commit comments