Skip to content

Commit 3e5e8fb

Browse files
authored
Merge pull request #118 from JaredCE/allow-use-of-event-request
Allow use of Request Schema Validators
2 parents 022715b + 36e3dbf commit 3e5e8fb

File tree

6 files changed

+144
-11
lines changed

6 files changed

+144
-11
lines changed

README.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Options:
6161
#### Model Details
6262
* [Models](#models)
6363
* [Notes on Schemas](#notes-on-schemas)
64+
* [Request Schema Validators](#serverless-request-schema-validators)
6465
#### Response Headers
6566
* [CORS](#cors)
6667
* [OWASP Secure Headers](#owasp)
@@ -409,6 +410,76 @@ custom:
409410
type: string
410411
```
411412
413+
##### Serverless Request Schema Validators
414+
415+
As of 0.0.64, you can now make use of [Request Schema Validators](https://www.serverless.com/framework/docs/providers/aws/events/apigateway#request-schema-validators). This allows you to define Request models via the `apiGateway` settings:
416+
417+
```yml
418+
provider:
419+
...
420+
apiGateway:
421+
request:
422+
schemas:
423+
post-create-model:
424+
name: PostCreateModel
425+
schema: ${file(api_schema/post_add_schema.json)}
426+
description: "A Model validation for adding posts"
427+
```
428+
429+
which are then used like:
430+
431+
```yml
432+
functions:
433+
create:
434+
handler: posts.create
435+
events:
436+
- http:
437+
path: posts/create
438+
method: post
439+
request:
440+
schemas:
441+
application/json: post-create-model
442+
documentation:
443+
...
444+
```
445+
446+
The generator will match to the model within the `apiGateway` settings model list. If you are using the `apiGateway` to define models, please do not re-use any names that you might define in the [`models`](#models) list.
447+
448+
You can also skip writing a `requestBody` and `requestModels` if you have defined a `request` property in your event.
449+
450+
If you're not using `apiGateway`, you can still make use of `request` by writing in the other styles that serverless accepts for Request Schema Validators:
451+
452+
```yml
453+
functions:
454+
create:
455+
handler: posts.create
456+
events:
457+
- http:
458+
path: posts/create
459+
method: post
460+
request:
461+
schemas:
462+
application/json:
463+
schema: ${file(create_request.json)}
464+
name: PostCreateModel
465+
description: 'Validation model for Creating Posts'
466+
467+
```
468+
469+
or
470+
471+
```yml
472+
functions:
473+
create:
474+
handler: posts.create
475+
events:
476+
- http:
477+
path: posts/create
478+
method: post
479+
request:
480+
schemas:
481+
application/json: ${file(create_request.json)}
482+
```
412483

413484
#### Functions
414485

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "serverless-openapi-documenter",
3-
"version": "0.0.63",
3+
"version": "0.0.64",
44
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
55
"main": "index.js",
66
"keywords": [

src/definitionGenerator.js

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,11 +341,31 @@ class DefinitionGenerator {
341341
if (Object.keys(documentation).includes('deprecated'))
342342
obj.deprecated = documentation.deprecated
343343

344-
if (documentation.requestBody)
345-
obj.requestBody = await this.createRequestBody(documentation)
344+
if (documentation.requestBody || this.currentEvent?.request?.schemas) {
345+
const requestModel = {}
346+
if (documentation.requestBody) {
347+
Object.assign(
348+
requestModel,
349+
{
350+
description: documentation.requestBody.description,
351+
models: documentation.requestModels
352+
}
353+
)
354+
} else {
355+
Object.assign(
356+
requestModel,
357+
{
358+
description: '',
359+
models: this.currentEvent?.request?.schemas
360+
}
361+
)
362+
}
363+
364+
obj.requestBody = await this.createRequestBody(requestModel)
346365
.catch(err => {
347366
throw err
348367
})
368+
}
349369

350370
if (documentation.methodResponses)
351371
obj.responses = await this.createResponses(documentation)
@@ -488,13 +508,13 @@ class DefinitionGenerator {
488508
return obj
489509
}
490510

491-
async createRequestBody(documentation) {
511+
async createRequestBody(requestBodyDetails) {
492512
const obj = {
493-
description: documentation.requestBody.description,
494-
required: documentation.requestBody.required || false,
513+
description: requestBodyDetails.description,
514+
required: false
495515
}
496516

497-
obj.content = await this.createMediaTypeObject(documentation.requestModels, 'requestBody')
517+
obj.content = await this.createMediaTypeObject(requestBodyDetails.models)
498518
.catch(err => {
499519
throw err
500520
})
@@ -548,6 +568,25 @@ class DefinitionGenerator {
548568
Object.assign(mediaTypeObj, { [contentKey]: obj })
549569
}
550570
}
571+
572+
if (Object.keys(mediaTypeObj).length === 0) {
573+
for (const contentKey of Object.keys(models)) {
574+
const obj = {}
575+
const schema = (models[contentKey]?.schema) ? models[contentKey].schema : models[contentKey]
576+
const name = (models[contentKey]?.name) ? models[contentKey].name : uuid()
577+
const schemaRef = await this.schemaHandler.createSchema(name, schema)
578+
.catch(err => {
579+
throw err
580+
})
581+
582+
obj.schema = {
583+
$ref: schemaRef
584+
}
585+
586+
Object.assign(mediaTypeObj, { [contentKey]: obj })
587+
}
588+
}
589+
551590
return mediaTypeObj
552591
}
553592

src/schemaHandler.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const { v4: uuid } = require('uuid')
99

1010
class SchemaHandler {
1111
constructor(serverless, openAPI) {
12+
this.apiGatewayModels = serverless.service?.provider?.apiGateway?.request?.schemas || {}
1213
this.documentation = serverless.service.custom.documentation
1314
this.openAPI = openAPI
1415

@@ -42,7 +43,12 @@ class SchemaHandler {
4243
const standardisedModels = this.documentation?.models?.map(standardModel) || []
4344
const standardisedModelsList = this.documentation?.modelsList?.map(standardModel) || []
4445

45-
this.models = standardisedModels.length ? standardisedModels.concat(standardisedModelsList) : standardisedModelsList
46+
const standardisedGatewayModels = Object.keys(this.apiGatewayModels).flatMap(key => {
47+
const gatewayModel = this.apiGatewayModels[key]
48+
return standardModel(gatewayModel)
49+
}) || []
50+
51+
this.models = standardisedModels.concat(standardisedModelsList, standardisedGatewayModels)
4652
}
4753

4854
async addModelsToOpenAPI() {

test/serverless-tests/schemas/serverless.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ frameworkVersion: ">=3.0.0 < 4.0.0"
33
provider:
44
name: aws
55
runtime: nodejs14.x
6+
apiGateway:
7+
request:
8+
schemas:
9+
post-model:
10+
name: PostModel
11+
description: The POST Model
12+
schema: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/BizTalkServerApplicationSchema.json
613

714
plugins:
815
- ../../../index.js
@@ -16,7 +23,7 @@ custom:
1623
- name: DeleteResponse
1724
description: The Delete response
1825
contentType: application/json
19-
schema: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/BizTalkServerApplicationSchema.json
26+
schema: https://raw.githubusercontent.com/JaredCE/serverless-openapi-documenter/main/test/json/complex.json
2027
- name: GetResponse
2128
description: The Get Response
2229
contentType: application/json
@@ -138,3 +145,13 @@ functions:
138145
description: The response from the delete endpoint
139146
responseModels:
140147
application/json: GetResponse
148+
149+
getUserAtOrg:
150+
handler: handler.getUserAtOrg
151+
events:
152+
- http:
153+
path: getUserAtOrg/
154+
method: get
155+
request:
156+
schemas:
157+
application/json: post-model

0 commit comments

Comments
 (0)