From 168cf5fbb9d90368d9e3c872214d946f7f0b3249 Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Wed, 20 Mar 2024 17:21:39 +0100 Subject: [PATCH 1/6] #45 Fix documentation preview with nested model --- README.md | 2 +- src/generateDocumentation.js | 23 ++++++++++++++++++++++- src/generateDocumentation.spec.js | 6 ++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d796fc8..ca989b3 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/generateDocumentation.js b/src/generateDocumentation.js index ee869cb..fe4c441 100644 --- a/src/generateDocumentation.js +++ b/src/generateDocumentation.js @@ -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; diff --git a/src/generateDocumentation.spec.js b/src/generateDocumentation.spec.js index 8aef2a5..70a51b3 100644 --- a/src/generateDocumentation.spec.js +++ b/src/generateDocumentation.spec.js @@ -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 ({ @@ -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 ({ From 3b5d91aadb396c6942db82391dc51da12669b0e2 Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Thu, 21 Mar 2024 08:31:25 +0100 Subject: [PATCH 2/6] #45 Add test case for URL reference --- src/generateDocumentation.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/generateDocumentation.spec.js b/src/generateDocumentation.spec.js index 70a51b3..6f86f11 100644 --- a/src/generateDocumentation.spec.js +++ b/src/generateDocumentation.spec.js @@ -346,6 +346,7 @@ 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": "http://path/to/AnyOtherModel" } } }]} | ${{ 'AnyModel': { type: 'array', items: { "$ref": "http://path/to/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" } } } } }} @@ -378,6 +379,7 @@ 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": "http://path/to/AnyOtherModel" } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { "$ref": "http://path/to/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: {} }} From 459548cbe2527f742e86a47d534ed9e612c1b72a Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Mon, 25 Mar 2024 08:25:18 +0100 Subject: [PATCH 3/6] #45 Minor improvement on object validation --- src/generateDocumentation.js | 2 +- src/generateDocumentation.spec.js | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/generateDocumentation.js b/src/generateDocumentation.js index fe4c441..4bf31b6 100644 --- a/src/generateDocumentation.js +++ b/src/generateDocumentation.js @@ -309,7 +309,7 @@ function generateModelSchema(templateSchema) { if (match) { field = `#/components/schemas/${match[1]}`; } - } else if (!Array.isArray(field) && typeof field === "object" && field) { + } else if (field.constructor === Object && field) { // NOTE: We are only interested in looping through "items" and "properties" fields (which are both objects)! field = generateModelSchema(field); } diff --git a/src/generateDocumentation.spec.js b/src/generateDocumentation.spec.js index 6f86f11..09a8e87 100644 --- a/src/generateDocumentation.spec.js +++ b/src/generateDocumentation.spec.js @@ -346,10 +346,11 @@ 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": "http://path/to/AnyOtherModel" } } }]} | ${{ 'AnyModel': { type: 'array', items: { "$ref": "http://path/to/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" } } } } }} + ${[{ name: 'AnyModel', schema: { type: 'array', items: { '$ref': 'http://path/to/AnyOtherModel' } } }]} | ${{ 'AnyModel': { type: 'array', items: { '$ref': 'http://path/to/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: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }]} | ${{ 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }} + ${[{ 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 ({ @@ -379,10 +380,11 @@ 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": "http://path/to/AnyOtherModel" } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { "$ref": "http://path/to/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: {} }} + ${[{ name: 'AnyModel', schema: { type: 'array', items: { '$ref': 'http://path/to/AnyOtherModel' } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { '$ref': 'http://path/to/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: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }, 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 ({ From 2edba654645d21298a43fa187a69ac84b8f40a87 Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Mon, 25 Mar 2024 08:36:58 +0100 Subject: [PATCH 4/6] #45 Add empty string test case --- src/generateDocumentation.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/generateDocumentation.spec.js b/src/generateDocumentation.spec.js index 09a8e87..91f4cba 100644 --- a/src/generateDocumentation.spec.js +++ b/src/generateDocumentation.spec.js @@ -348,6 +348,7 @@ describe('ServerlessAWSDocumentation', function () { ${[{ name: 'AnyModel', schema: { type: 'any-type' } }, { name: 'AnyOtherModel', schema: {} }]} | ${{ 'AnyModel': { type: 'any-type' }, 'AnyOtherModel': {} }} ${[{ name: 'AnyModel', schema: { type: 'array', items: { '$ref': 'http://path/to/AnyOtherModel' } } }]} | ${{ 'AnyModel': { type: 'array', items: { '$ref': 'http://path/to/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: { type: 'string', default: '' } } } }]} | ${{ 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'string', default: '' } } } }} ${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }]} | ${{ 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }} ${[{ 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' } } } } }} @@ -382,6 +383,7 @@ describe('ServerlessAWSDocumentation', function () { ${[{ name: 'AnyModel', schema: { type: 'any-type' } }, { name: 'AnyOtherModel', schema: {} }]} | ${{ schemas: { 'AnyModel': { type: 'any-type' }, 'AnyOtherModel': {} }, securitySchemes: {} }} ${[{ name: 'AnyModel', schema: { type: 'array', items: { '$ref': 'http://path/to/AnyOtherModel' } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { '$ref': 'http://path/to/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: { type: 'string', default: '' } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'string', default: '' } } } }, securitySchemes: {} }} ${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }, 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: {} }} From 42afb43aea4f81559999af74428ef170748c6931 Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Mon, 25 Mar 2024 08:40:19 +0100 Subject: [PATCH 5/6] #45 Add false boolean test case --- src/generateDocumentation.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generateDocumentation.spec.js b/src/generateDocumentation.spec.js index 91f4cba..ef1d1b5 100644 --- a/src/generateDocumentation.spec.js +++ b/src/generateDocumentation.spec.js @@ -383,7 +383,7 @@ describe('ServerlessAWSDocumentation', function () { ${[{ name: 'AnyModel', schema: { type: 'any-type' } }, { name: 'AnyOtherModel', schema: {} }]} | ${{ schemas: { 'AnyModel': { type: 'any-type' }, 'AnyOtherModel': {} }, securitySchemes: {} }} ${[{ name: 'AnyModel', schema: { type: 'array', items: { '$ref': 'http://path/to/AnyOtherModel' } } }]} | ${{ schemas: { 'AnyModel': { type: 'array', items: { '$ref': 'http://path/to/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: { type: 'string', default: '' } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'string', default: '' } } } }, securitySchemes: {} }} + ${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { type: 'string', default: '', nullable: false } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'string', default: '', nullable: false } } } }, securitySchemes: {} }} ${[{ name: 'AnyModel', schema: { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }]} | ${{ schemas: { 'AnyModel': { type: 'object', required: ['id'], properties: { id: { type: 'integer', minimum: 1, exclusiveMinimum: false } } } }, 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: {} }} From dda9ce16694488a618d454b99785c6b1bd143f74 Mon Sep 17 00:00:00 2001 From: Paolo Rovelli Date: Tue, 26 Mar 2024 08:02:18 +0100 Subject: [PATCH 6/6] #45 Minor if condition reordering --- src/generateDocumentation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generateDocumentation.js b/src/generateDocumentation.js index 4bf31b6..5b91925 100644 --- a/src/generateDocumentation.js +++ b/src/generateDocumentation.js @@ -304,12 +304,12 @@ function generateModelSchema(templateSchema) { let schema = {}; Object.keys(templateSchema).forEach((key) => { let field = templateSchema[key]; - if (key === "$ref") { + if (field && key === "$ref") { const match = /{{\s*model\s*:\s*([\-\w]+)\s*}}/.exec(field); if (match) { field = `#/components/schemas/${match[1]}`; } - } else if (field.constructor === Object && field) { + } else if (field && field.constructor === Object) { // NOTE: We are only interested in looping through "items" and "properties" fields (which are both objects)! field = generateModelSchema(field); }