55 AUXILIARY_FIELDS ,
66 analyzePolicies ,
77 getDataModels ,
8+ hasAttribute ,
89 isForeignKeyField ,
910 isIdField ,
1011 isRelationshipField ,
@@ -37,6 +38,9 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
3738 const components = this . generateComponents ( ) ;
3839 const paths = this . generatePaths ( ) ;
3940
41+ // prune unused component schemas
42+ this . pruneComponents ( paths , components ) ;
43+
4044 // generate security schemes, and root-level security
4145 components . securitySchemes = this . generateSecuritySchemes ( ) ;
4246 let security : OAPI . Document [ 'security' ] | undefined = undefined ;
@@ -108,20 +112,24 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
108112 prefix = prefix . substring ( 0 , prefix . length - 1 ) ;
109113 }
110114
115+ const resourceMeta = getModelResourceMeta ( zmodel ) ;
116+
111117 // GET /resource
112118 // POST /resource
113119 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 ) ,
116122 } ;
117123
118124 // GET /resource/{id}
125+ // PUT /resource/{id}
119126 // PATCH /resource/{id}
120127 // DELETE /resource/{id}
121128 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 ) ,
125133 } ;
126134
127135 // paths for related resources and relationships
@@ -131,33 +139,49 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
131139 continue ;
132140 }
133141
134- // GET /resource/{id}/field
142+ // GET /resource/{id}/{relationship}
135143 const relatedDataPath = `${ prefix } /${ lowerCaseFirst ( model . name ) } /{id}/${ field . name } ` ;
136144 let container = result [ relatedDataPath ] ;
137145 if ( ! container ) {
138146 container = result [ relatedDataPath ] = { } ;
139147 }
140- container . get = this . makeRelatedFetch ( zmodel , field , relationDecl ) ;
148+ container . get = this . makeRelatedFetch ( zmodel , field , relationDecl , resourceMeta ) ;
141149
142150 const relationshipPath = `${ prefix } /${ lowerCaseFirst ( model . name ) } /{id}/relationships/${ field . name } ` ;
143151 container = result [ relationshipPath ] ;
144152 if ( ! container ) {
145153 container = result [ relationshipPath ] = { } ;
146154 }
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+
151175 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 ) ;
154178 }
155179 }
156180
157181 return result ;
158182 }
159183
160- private makeResourceList ( model : DataModel , policies : Policies ) {
184+ private makeResourceList ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
161185 return {
162186 operationId : `list-${ model . name } ` ,
163187 description : `List "${ model . name } " resources` ,
@@ -173,11 +197,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
173197 '200' : this . success ( `${ model . name } ListResponse` ) ,
174198 '403' : this . forbidden ( ) ,
175199 } ,
176- security : policies . read === true ? [ ] : undefined ,
200+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
177201 } ;
178202 }
179203
180- private makeResourceCreate ( model : DataModel , policies : Policies ) {
204+ private makeResourceCreate ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
181205 return {
182206 operationId : `create-${ model . name } ` ,
183207 description : `Create a "${ model . name } " resource` ,
@@ -193,11 +217,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
193217 '201' : this . success ( `${ model . name } Response` ) ,
194218 '403' : this . forbidden ( ) ,
195219 } ,
196- security : policies . create === true ? [ ] : undefined ,
220+ security : resourceMeta ?. security ?? policies . create === true ? [ ] : undefined ,
197221 } ;
198222 }
199223
200- private makeResourceFetch ( model : DataModel , policies : Policies ) {
224+ private makeResourceFetch ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
201225 return {
202226 operationId : `fetch-${ model . name } ` ,
203227 description : `Fetch a "${ model . name } " resource` ,
@@ -208,11 +232,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
208232 '403' : this . forbidden ( ) ,
209233 '404' : this . notFound ( ) ,
210234 } ,
211- security : policies . read === true ? [ ] : undefined ,
235+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
212236 } ;
213237 }
214238
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+ ) {
216245 const policies = analyzePolicies ( relationDecl ) ;
217246 const parameters : OAPI . OperationObject [ 'parameters' ] = [ this . parameter ( 'id' ) , this . parameter ( 'include' ) ] ;
218247 if ( field . type . array ) {
@@ -235,14 +264,19 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
235264 '403' : this . forbidden ( ) ,
236265 '404' : this . notFound ( ) ,
237266 } ,
238- security : policies . read === true ? [ ] : undefined ,
267+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
239268 } ;
240269 return result ;
241270 }
242271
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+ ) {
244278 return {
245- operationId : `update- ${ model . name } ` ,
279+ operationId,
246280 description : `Update a "${ model . name } " resource` ,
247281 tags : [ lowerCaseFirst ( model . name ) ] ,
248282 parameters : [ this . parameter ( 'id' ) ] ,
@@ -258,11 +292,11 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
258292 '403' : this . forbidden ( ) ,
259293 '404' : this . notFound ( ) ,
260294 } ,
261- security : policies . update === true ? [ ] : undefined ,
295+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
262296 } ;
263297 }
264298
265- private makeResourceDelete ( model : DataModel , policies : Policies ) {
299+ private makeResourceDelete ( model : DataModel , policies : Policies , resourceMeta : { security ?: object } | undefined ) {
266300 return {
267301 operationId : `delete-${ model . name } ` ,
268302 description : `Delete a "${ model . name } " resource` ,
@@ -273,11 +307,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
273307 '403' : this . forbidden ( ) ,
274308 '404' : this . notFound ( ) ,
275309 } ,
276- security : policies . delete === true ? [ ] : undefined ,
310+ security : resourceMeta ?. security ?? policies . delete === true ? [ ] : undefined ,
277311 } ;
278312 }
279313
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+ ) {
281320 const parameters : OAPI . OperationObject [ 'parameters' ] = [ this . parameter ( 'id' ) ] ;
282321 if ( field . type . array ) {
283322 parameters . push (
@@ -299,11 +338,16 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
299338 '403' : this . forbidden ( ) ,
300339 '404' : this . notFound ( ) ,
301340 } ,
302- security : policies . read === true ? [ ] : undefined ,
341+ security : resourceMeta ?. security ?? policies . read === true ? [ ] : undefined ,
303342 } ;
304343 }
305344
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+ ) {
307351 return {
308352 operationId : `create-${ model . name } -relationship-${ field . name } ` ,
309353 description : `Create new "${ field . name } " relationships for a "${ model . name } "` ,
@@ -321,13 +365,19 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
321365 '403' : this . forbidden ( ) ,
322366 '404' : this . notFound ( ) ,
323367 } ,
324- security : policies . update === true ? [ ] : undefined ,
368+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
325369 } ;
326370 }
327371
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+ ) {
329379 return {
330- operationId : `update- ${ model . name } -relationship- ${ field . name } ` ,
380+ operationId,
331381 description : `Update "${ field . name } " ${ pluralize ( 'relationship' , field . type . array ? 2 : 1 ) } for a "${
332382 model . name
333383 } "`,
@@ -349,7 +399,7 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
349399 '403' : this . forbidden ( ) ,
350400 '404' : this . notFound ( ) ,
351401 } ,
352- security : policies . update === true ? [ ] : undefined ,
402+ security : resourceMeta ?. security ?? policies . update === true ? [ ] : undefined ,
353403 } ;
354404 }
355405
@@ -784,6 +834,7 @@ export class RESTfulOpenAPIGenerator extends OpenAPIGeneratorBase {
784834 if (
785835 mode === 'create' &&
786836 ! field . type . optional &&
837+ ! hasAttribute ( field , '@default' ) &&
787838 // collection relation fields are implicitly optional
788839 ! ( isDataModel ( field . $resolvedType ?. decl ) && field . type . array )
789840 ) {
0 commit comments