Skip to content

Commit

Permalink
Merge pull request #118 from JaredCE/allow-use-of-event-request
Browse files Browse the repository at this point in the history
Allow use of Request Schema Validators
  • Loading branch information
JaredCE authored Jun 2, 2023
2 parents 022715b + 36e3dbf commit 3e5e8fb
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 11 deletions.
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Options:
#### Model Details
* [Models](#models)
* [Notes on Schemas](#notes-on-schemas)
* [Request Schema Validators](#serverless-request-schema-validators)
#### Response Headers
* [CORS](#cors)
* [OWASP Secure Headers](#owasp)
Expand Down Expand Up @@ -409,6 +410,76 @@ custom:
type: string
```
##### Serverless Request Schema Validators
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:
```yml
provider:
...
apiGateway:
request:
schemas:
post-create-model:
name: PostCreateModel
schema: ${file(api_schema/post_add_schema.json)}
description: "A Model validation for adding posts"
```

which are then used like:

```yml
functions:
create:
handler: posts.create
events:
- http:
path: posts/create
method: post
request:
schemas:
application/json: post-create-model
documentation:
...
```
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.

You can also skip writing a `requestBody` and `requestModels` if you have defined a `request` property in your event.

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:

```yml
functions:
create:
handler: posts.create
events:
- http:
path: posts/create
method: post
request:
schemas:
application/json:
schema: ${file(create_request.json)}
name: PostCreateModel
description: 'Validation model for Creating Posts'
```

or

```yml
functions:
create:
handler: posts.create
events:
- http:
path: posts/create
method: post
request:
schemas:
application/json: ${file(create_request.json)}
```

#### Functions

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serverless-openapi-documenter",
"version": "0.0.63",
"version": "0.0.64",
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
"main": "index.js",
"keywords": [
Expand Down
51 changes: 45 additions & 6 deletions src/definitionGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,11 +341,31 @@ class DefinitionGenerator {
if (Object.keys(documentation).includes('deprecated'))
obj.deprecated = documentation.deprecated

if (documentation.requestBody)
obj.requestBody = await this.createRequestBody(documentation)
if (documentation.requestBody || this.currentEvent?.request?.schemas) {
const requestModel = {}
if (documentation.requestBody) {
Object.assign(
requestModel,
{
description: documentation.requestBody.description,
models: documentation.requestModels
}
)
} else {
Object.assign(
requestModel,
{
description: '',
models: this.currentEvent?.request?.schemas
}
)
}

obj.requestBody = await this.createRequestBody(requestModel)
.catch(err => {
throw err
})
}

if (documentation.methodResponses)
obj.responses = await this.createResponses(documentation)
Expand Down Expand Up @@ -488,13 +508,13 @@ class DefinitionGenerator {
return obj
}

async createRequestBody(documentation) {
async createRequestBody(requestBodyDetails) {
const obj = {
description: documentation.requestBody.description,
required: documentation.requestBody.required || false,
description: requestBodyDetails.description,
required: false
}

obj.content = await this.createMediaTypeObject(documentation.requestModels, 'requestBody')
obj.content = await this.createMediaTypeObject(requestBodyDetails.models)
.catch(err => {
throw err
})
Expand Down Expand Up @@ -548,6 +568,25 @@ class DefinitionGenerator {
Object.assign(mediaTypeObj, { [contentKey]: obj })
}
}

if (Object.keys(mediaTypeObj).length === 0) {
for (const contentKey of Object.keys(models)) {
const obj = {}
const schema = (models[contentKey]?.schema) ? models[contentKey].schema : models[contentKey]
const name = (models[contentKey]?.name) ? models[contentKey].name : uuid()
const schemaRef = await this.schemaHandler.createSchema(name, schema)
.catch(err => {
throw err
})

obj.schema = {
$ref: schemaRef
}

Object.assign(mediaTypeObj, { [contentKey]: obj })
}
}

return mediaTypeObj
}

Expand Down
8 changes: 7 additions & 1 deletion src/schemaHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const { v4: uuid } = require('uuid')

class SchemaHandler {
constructor(serverless, openAPI) {
this.apiGatewayModels = serverless.service?.provider?.apiGateway?.request?.schemas || {}
this.documentation = serverless.service.custom.documentation
this.openAPI = openAPI

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

this.models = standardisedModels.length ? standardisedModels.concat(standardisedModelsList) : standardisedModelsList
const standardisedGatewayModels = Object.keys(this.apiGatewayModels).flatMap(key => {
const gatewayModel = this.apiGatewayModels[key]
return standardModel(gatewayModel)
}) || []

this.models = standardisedModels.concat(standardisedModelsList, standardisedGatewayModels)
}

async addModelsToOpenAPI() {
Expand Down
19 changes: 18 additions & 1 deletion test/serverless-tests/schemas/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ frameworkVersion: ">=3.0.0 < 4.0.0"
provider:
name: aws
runtime: nodejs14.x
apiGateway:
request:
schemas:
post-model:
name: PostModel
description: The POST Model
schema: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/BizTalkServerApplicationSchema.json

plugins:
- ../../../index.js
Expand All @@ -16,7 +23,7 @@ custom:
- name: DeleteResponse
description: The Delete response
contentType: application/json
schema: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/BizTalkServerApplicationSchema.json
schema: https://raw.githubusercontent.com/JaredCE/serverless-openapi-documenter/main/test/json/complex.json
- name: GetResponse
description: The Get Response
contentType: application/json
Expand Down Expand Up @@ -138,3 +145,13 @@ functions:
description: The response from the delete endpoint
responseModels:
application/json: GetResponse

getUserAtOrg:
handler: handler.getUserAtOrg
events:
- http:
path: getUserAtOrg/
method: get
request:
schemas:
application/json: post-model

0 comments on commit 3e5e8fb

Please sign in to comment.