5
5
AUXILIARY_FIELDS ,
6
6
analyzePolicies ,
7
7
getDataModels ,
8
+ hasAttribute ,
8
9
isForeignKeyField ,
9
10
isIdField ,
10
11
isRelationshipField ,
@@ -37,6 +38,9 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
37
38
const components = this . generateComponents ( ) ;
38
39
const paths = this . generatePaths ( ) ;
39
40
41
+ // prune unused component schemas
42
+ this . pruneComponents ( paths , components ) ;
43
+
40
44
// generate security schemes, and root-level security
41
45
components . securitySchemes = this . generateSecuritySchemes ( ) ;
42
46
let security : OAPI . Document [ 'security' ] | undefined = undefined ;
@@ -108,20 +112,24 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
108
112
prefix = prefix . substring ( 0 , prefix . length - 1 ) ;
109
113
}
110
114
115
+ const resourceMeta = getModelResourceMeta ( zmodel ) ;
116
+
111
117
// GET /resource
112
118
// POST /resource
113
119
result [ `${ prefix } /${ lowerCaseFirst ( model . name ) } ` ] = {
114
- get : this . makeResourceList ( zmodel , policies ) ,
115
- post : this . makeResourceCreate ( zmodel , policies ) ,
120
+ get : this . makeResourceList ( zmodel , policies , resourceMeta ) ,
121
+ post : this . makeResourceCreate ( zmodel , policies , resourceMeta ) ,
116
122
} ;
117
123
118
124
// GET /resource/{id}
125
+ // PUT /resource/{id}
119
126
// PATCH /resource/{id}
120
127
// DELETE /resource/{id}
121
128
result [ `${ prefix } /${ lowerCaseFirst ( model . name ) } /{id}` ] = {
122
- get : this . makeResourceFetch ( zmodel , policies ) ,
123
- patch : this . makeResourceUpdate ( zmodel , policies ) ,
124
- delete : this . makeResourceDelete ( zmodel , policies ) ,
129
+ get : this . makeResourceFetch ( zmodel , policies , resourceMeta ) ,
130
+ put : this . makeResourceUpdate ( zmodel , policies , `update-${ model . name } -put` , resourceMeta ) ,
131
+ patch : this . makeResourceUpdate ( zmodel , policies , `update-${ model . name } -patch` , resourceMeta ) ,
132
+ delete : this . makeResourceDelete ( zmodel , policies , resourceMeta ) ,
125
133
} ;
126
134
127
135
// paths for related resources and relationships
@@ -131,33 +139,49 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
131
139
continue ;
132
140
}
133
141
134
- // GET /resource/{id}/field
142
+ // GET /resource/{id}/{relationship}
135
143
const relatedDataPath = `${ prefix } /${ lowerCaseFirst ( model . name ) } /{id}/${ field . name } ` ;
136
144
let container = result [ relatedDataPath ] ;
137
145
if ( ! container ) {
138
146
container = result [ relatedDataPath ] = { } ;
139
147
}
140
- container . get = this . makeRelatedFetch ( zmodel , field , relationDecl ) ;
148
+ container . get = this . makeRelatedFetch ( zmodel , field , relationDecl , resourceMeta ) ;
141
149
142
150
const relationshipPath = `${ prefix } /${ lowerCaseFirst ( model . name ) } /{id}/relationships/${ field . name } ` ;
143
151
container = result [ relationshipPath ] ;
144
152
if ( ! container ) {
145
153
container = result [ relationshipPath ] = { } ;
146
154
}
147
- // GET /resource/{id}/relationships/field
148
- container . get = this . makeRelationshipFetch ( zmodel , field , policies ) ;
149
- // PATCH /resource/{id}/relationships/field
150
- container . patch = this . makeRelationshipUpdate ( zmodel , field , policies ) ;
155
+ // GET /resource/{id}/relationships/{relationship}
156
+ container . get = this . makeRelationshipFetch ( zmodel , field , policies , resourceMeta ) ;
157
+
158
+ // PUT /resource/{id}/relationships/{relationship}
159
+ container . put = this . makeRelationshipUpdate (
160
+ zmodel ,
161
+ field ,
162
+ policies ,
163
+ `update-${ model . name } -relationship-${ field . name } -put` ,
164
+ resourceMeta
165
+ ) ;
166
+ // PATCH /resource/{id}/relationships/{relationship}
167
+ container . patch = this . makeRelationshipUpdate (
168
+ zmodel ,
169
+ field ,
170
+ policies ,
171
+ `update-${ model . name } -relationship-${ field . name } -patch` ,
172
+ resourceMeta
173
+ ) ;
174
+
151
175
if ( field . type . array ) {
152
- // POST /resource/{id}/relationships/field
153
- container . post = this . makeRelationshipCreate ( zmodel , field , policies ) ;
176
+ // POST /resource/{id}/relationships/{relationship}
177
+ container . post = this . makeRelationshipCreate ( zmodel , field , policies , resourceMeta ) ;
154
178
}
155
179
}
156
180
157
181
return result ;
158
182
}
159
183
160
- private makeResourceList ( model : DataModel , policies : Policies ) {
184
+ private makeResourceList ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
161
185
return {
162
186
operationId : `list-${ model . name } ` ,
163
187
description : `List "${ model . name } " resources` ,
@@ -173,11 +197,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
173
197
'200' : this . success ( `${ model . name } ListResponse` ) ,
174
198
'403' : this . forbidden ( ) ,
175
199
} ,
176
- security : policies . read === true ? [ ] : undefined ,
200
+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
177
201
} ;
178
202
}
179
203
180
- private makeResourceCreate ( model : DataModel , policies : Policies ) {
204
+ private makeResourceCreate ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
181
205
return {
182
206
operationId : `create-${ model . name } ` ,
183
207
description : `Create a "${ model . name } " resource` ,
@@ -193,11 +217,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
193
217
'201' : this . success ( `${ model . name } Response` ) ,
194
218
'403' : this . forbidden ( ) ,
195
219
} ,
196
- security : policies . create === true ? [ ] : undefined ,
220
+ security : resourceMeta ?. security ?? policies . create === true ? [ ] : undefined ,
197
221
} ;
198
222
}
199
223
200
- private makeResourceFetch ( model : DataModel , policies : Policies ) {
224
+ private makeResourceFetch ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
201
225
return {
202
226
operationId : `fetch-${ model . name } ` ,
203
227
description : `Fetch a "${ model . name } " resource` ,
@@ -208,11 +232,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
208
232
'403' : this . forbidden ( ) ,
209
233
'404' : this . notFound ( ) ,
210
234
} ,
211
- security : policies . read === true ? [ ] : undefined ,
235
+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
212
236
} ;
213
237
}
214
238
215
- private makeRelatedFetch ( model : DataModel , field : DataModelField , relationDecl : DataModel ) {
239
+ private makeRelatedFetch (
240
+ model : DataModel ,
241
+ field : DataModelField ,
242
+ relationDecl : DataModel ,
243
+ resourceMeta : { security ?: object } | undefined
244
+ ) {
216
245
const policies = analyzePolicies ( relationDecl ) ;
217
246
const parameters : OAPI . OperationObject [ 'parameters' ] = [ this . parameter ( 'id' ) , this . parameter ( 'include' ) ] ;
218
247
if ( field . type . array ) {
@@ -235,14 +264,19 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
235
264
'403' : this . forbidden ( ) ,
236
265
'404' : this . notFound ( ) ,
237
266
} ,
238
- security : policies . read === true ? [ ] : undefined ,
267
+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
239
268
} ;
240
269
return result ;
241
270
}
242
271
243
- private makeResourceUpdate ( model : DataModel , policies : Policies ) {
272
+ private makeResourceUpdate (
273
+ model : DataModel ,
274
+ policies : Policies ,
275
+ operationId : string ,
276
+ resourceMeta : { security ?: object } | undefined
277
+ ) {
244
278
return {
245
- operationId : `update- ${ model . name } ` ,
279
+ operationId,
246
280
description : `Update a "${ model . name } " resource` ,
247
281
tags : [ lowerCaseFirst ( model . name ) ] ,
248
282
parameters : [ this . parameter ( 'id' ) ] ,
@@ -258,11 +292,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
258
292
'403' : this . forbidden ( ) ,
259
293
'404' : this . notFound ( ) ,
260
294
} ,
261
- security : policies . update === true ? [ ] : undefined ,
295
+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
262
296
} ;
263
297
}
264
298
265
- private makeResourceDelete ( model : DataModel , policies : Policies ) {
299
+ private makeResourceDelete ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
266
300
return {
267
301
operationId : `delete-${ model . name } ` ,
268
302
description : `Delete a "${ model . name } " resource` ,
@@ -273,11 +307,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
273
307
'403' : this . forbidden ( ) ,
274
308
'404' : this . notFound ( ) ,
275
309
} ,
276
- security : policies . delete === true ? [ ] : undefined ,
310
+ security : resourceMeta ?. security ?? policies . delete === true ? [ ] : undefined ,
277
311
} ;
278
312
}
279
313
280
- private makeRelationshipFetch ( model : DataModel , field : DataModelField , policies : Policies ) {
314
+ private makeRelationshipFetch (
315
+ model : DataModel ,
316
+ field : DataModelField ,
317
+ policies : Policies ,
318
+ resourceMeta : { security ?: object } | undefined
319
+ ) {
281
320
const parameters : OAPI . OperationObject [ 'parameters' ] = [ this . parameter ( 'id' ) ] ;
282
321
if ( field . type . array ) {
283
322
parameters . push (
@@ -299,11 +338,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
299
338
'403' : this . forbidden ( ) ,
300
339
'404' : this . notFound ( ) ,
301
340
} ,
302
- security : policies . read === true ? [ ] : undefined ,
341
+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
303
342
} ;
304
343
}
305
344
306
- private makeRelationshipCreate ( model : DataModel , field : DataModelField , policies : Policies ) {
345
+ private makeRelationshipCreate (
346
+ model : DataModel ,
347
+ field : DataModelField ,
348
+ policies : Policies ,
349
+ resourceMeta : { security ?: object } | undefined
350
+ ) {
307
351
return {
308
352
operationId : `create-${ model . name } -relationship-${ field . name } ` ,
309
353
description : `Create new "${ field . name } " relationships for a "${ model . name } "` ,
@@ -321,13 +365,19 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
321
365
'403' : this . forbidden ( ) ,
322
366
'404' : this . notFound ( ) ,
323
367
} ,
324
- security : policies . update === true ? [ ] : undefined ,
368
+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
325
369
} ;
326
370
}
327
371
328
- private makeRelationshipUpdate ( model : DataModel , field : DataModelField , policies : Policies ) {
372
+ private makeRelationshipUpdate (
373
+ model : DataModel ,
374
+ field : DataModelField ,
375
+ policies : Policies ,
376
+ operationId : string ,
377
+ resourceMeta : { security ?: object } | undefined
378
+ ) {
329
379
return {
330
- operationId : `update- ${ model . name } -relationship- ${ field . name } ` ,
380
+ operationId,
331
381
description : `Update "${ field . name } " ${ pluralize ( 'relationship' , field . type . array ? 2 : 1 ) } for a "${
332
382
model . name
333
383
} "`,
@@ -349,7 +399,7 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
349
399
'403' : this . forbidden ( ) ,
350
400
'404' : this . notFound ( ) ,
351
401
} ,
352
- security : policies . update === true ? [ ] : undefined ,
402
+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
353
403
} ;
354
404
}
355
405
@@ -784,6 +834,7 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
784
834
if (
785
835
mode === 'create' &&
786
836
! field . type . optional &&
837
+ ! hasAttribute ( field , '@default' ) &&
787
838
// collection relation fields are implicitly optional
788
839
! ( isDataModel ( field . $resolvedType ?. decl ) && field . type . array )
789
840
) {
0 commit comments