Skip to content

Commit

Permalink
failsafe-engineering#45 Fix documentation preview with nested model
Browse files Browse the repository at this point in the history
  • Loading branch information
rovellipaolo committed Mar 20, 2024
1 parent b2f7bab commit 168cf5f
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ To download it in YAML format, simply use `yml` or `yaml` extension in the "outp
By default, the documentation will be generated in OpenAPI 2.0 (Swagger).
To generate it in OpenAPI 3.0, use `oas30` or `openapi30` type in the "exportType" argument: `serverless generateDocumentation --outputFileName=filename.ext --exportType oas30`

**NOTE:** The documentation preview generated locally might be invalid (e.g., when some mandatory fields are missing from the `serverless.yml` documentation) and might differt from the final documentation deployed to and downloaded from AWS.
**NOTE:** The documentation preview generated locally might be invalid (e.g., when some mandatory fields are missing from the `serverless.yml` documentation) and might differ from the final documentation deployed to and downloaded from AWS.

### Download the documentation from AWS API Gateway

Expand Down
23 changes: 22 additions & 1 deletion src/generateDocumentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,33 @@ function generateModels(templateModels) {

templateModels.forEach((templateModel) => {
if (!templateModel.name || !templateModel.schema) return;
models[templateModel.name] = templateModel.schema;
models[templateModel.name] = generateModelSchema(templateModel.schema);
});

return models;
}

function generateModelSchema(templateSchema) {
if (!templateSchema) return templateSchema;

let schema = {};
Object.keys(templateSchema).forEach((key) => {
let field = templateSchema[key];
if (key === "$ref") {
const match = /{{\s*model\s*:\s*([\-\w]+)\s*}}/.exec(field);
if (match) {
field = `#/components/schemas/${match[1]}`;
}
} else if (!Array.isArray(field) && typeof field === "object" && field) {
// NOTE: We are only interested in looping through "items" and "properties" fields (which are both objects)!
field = generateModelSchema(field);
}
schema[key] = field;
});

return schema;
}

function generateSchema(field, excludeKeys) {
if (field.schema) return field.schema;

Expand Down
6 changes: 6 additions & 0 deletions src/generateDocumentation.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ describe('ServerlessAWSDocumentation', function () {
${[{ name: 'AnyModel', schema: { type: 'any-type' } }]} | ${{ 'AnyModel': { type: 'any-type' } }}
${[{ name: 'AnyModel', contentType: 'application/json', schema: { type: 'any-type' } }]} | ${{ 'AnyModel': { type: 'any-type' } }}
${[{ name: 'AnyModel', schema: { type: 'any-type' } }, { name: 'AnyOtherModel', schema: {} }]} | ${{ 'AnyModel': { type: 'any-type' }, 'AnyOtherModel': {} }}
${[{ name: 'AnyModel', schema: { type: 'array', items: { "$ref": "{{model: AnyOtherModel}}" } } }]} | ${{ 'AnyModel': { type: 'array', items: { "$ref": "#/components/schemas/AnyOtherModel" } } }}
${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { "$ref": "{{model: AnyOtherModel}}" } } } }]} | ${{ 'AnyModel': { type: 'object', required: ['id'], properties: { id: { "$ref": "#/components/schemas/AnyOtherModel" } } } }}
${[{ name: 'AnyModel', schema: { type: 'object', properties: { ids: { type: 'array', items: { "$ref": "{{model: AnyOtherModel}}" } } } } }]} | ${{ 'AnyModel': { type: 'object', properties: { ids: { type: 'array', items: { "$ref": "#/components/schemas/AnyOtherModel" } } } } }}
`(
'generates definitions field when exportType: swagger and models: $models',
async ({
Expand Down Expand Up @@ -375,6 +378,9 @@ describe('ServerlessAWSDocumentation', function () {
${[{ name: 'AnyModel', schema: { type: 'any-type' } }]} | ${{ schemas: { 'AnyModel': { type: 'any-type' } }, securitySchemes: {} }}
${[{ name: 'AnyModel', contentType: 'application/json', schema: { type: 'any-type' } }]} | ${{ schemas: { 'AnyModel': { type: 'any-type' } }, securitySchemes: {} }}
${[{ name: 'AnyModel', schema: { type: 'any-type' } }, { name: 'AnyOtherModel', schema: {} }]} | ${{ schemas: { 'AnyModel': { type: 'any-type' }, 'AnyOtherModel': {} }, securitySchemes: {} }}
${[{ name: 'AnyModel', schema: { type: 'array', items: { "$ref": "{{model: AnyOtherModel}}" } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { "$ref": "#/components/schemas/AnyOtherModel" } } }, securitySchemes: {} }}
${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { "$ref": "{{model: AnyOtherModel}}" } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { "$ref": "#/components/schemas/AnyOtherModel" } } } }, securitySchemes: {} }}
${[{ name: 'AnyModel', schema: { type: 'object', properties: { ids: { type: 'array', items: { "$ref": "{{model: AnyOtherModel}}" } } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', properties: { ids: { type: 'array', items: { "$ref": "#/components/schemas/AnyOtherModel" } }} } }, securitySchemes: {} }}
`(
'generates components.schemas field when exportType: oas30 and models: $models',
async ({
Expand Down

0 comments on commit 168cf5f

Please sign in to comment.