Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.121",
"version": "0.0.122",
"description": "Generate OpenAPI v3 documentation and Postman Collections from your Serverless Config",
"main": "index.js",
"keywords": [
Expand Down
88 changes: 49 additions & 39 deletions src/definitionGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,12 @@ class DefinitionGenerator {

if (documentation.contact) {
const contactObj = {};
contactObj.name = documentation.contact.name || "";

if (documentation.contact.name) contactObj.name = documentation.contact.name;

if (documentation.contact.url) contactObj.url = documentation.contact.url;

contactObj.email = documentation.contact.email || "";
if (documentation.contact.email) contactObj.email = documentation.contact.email;

const extendedSpec = this.extendSpecification(documentation.contact);

Expand Down Expand Up @@ -591,7 +592,9 @@ class DefinitionGenerator {
obj.headers = corsHeaders;
addHeaders(owaspHeaders);
} else {
obj.headers = owaspHeaders;
if (Object.keys(owaspHeaders).length) {
obj.headers = owaspHeaders;
}
}
}

Expand Down Expand Up @@ -677,10 +680,13 @@ class DefinitionGenerator {

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

if (requestBodyDetails.description) {
obj.description = requestBodyDetails.description;
}

obj.content = await this.createMediaTypeObject(
requestBodyDetails.models
).catch((err) => {
Expand All @@ -692,56 +698,60 @@ class DefinitionGenerator {

async createMediaTypeObject(models, type) {
const mediaTypeObj = {};

for (const mediaTypeDocumentation of this.schemaHandler.models) {
if (models === undefined || models === null) {
throw new Error(
`${this.currentFunctionName} is missing a Response Model for statusCode ${this.currentStatusCode}`
);
}

if (Object.values(models).includes(mediaTypeDocumentation.name)) {
let contentKey = "";
for (const [key, value] of Object.entries(models)) {
if (value === mediaTypeDocumentation.name) contentKey = key;
for (const modelContentType in models) {
let contentKey

if (models[modelContentType] === mediaTypeDocumentation.name) {
contentKey = modelContentType;
}
const obj = {};

let schema;
if (mediaTypeDocumentation?.content) {
if (mediaTypeDocumentation.content[contentKey]?.example)
obj.example = mediaTypeDocumentation.content[contentKey].example;
if (contentKey) {

if (mediaTypeDocumentation.content[contentKey]?.examples)
obj.examples = this.createExamples(
mediaTypeDocumentation.content[contentKey].examples
);
const obj = {};
let schema;
if (mediaTypeDocumentation.content) {
if (mediaTypeDocumentation.content[contentKey]?.example) {
obj.example = mediaTypeDocumentation.content[contentKey]?.example;
}

schema = mediaTypeDocumentation.content[contentKey].schema;
} else if (
mediaTypeDocumentation?.contentType &&
mediaTypeDocumentation.schema
) {
if (mediaTypeDocumentation?.example)
obj.example = mediaTypeDocumentation.example;
if (mediaTypeDocumentation.content[contentKey]?.examples) {
obj.examples = this.createExamples(
mediaTypeDocumentation.content[contentKey].examples
);
}

if (mediaTypeDocumentation?.examples)
obj.examples = this.createExamples(mediaTypeDocumentation.examples);
schema = (mediaTypeDocumentation.schema) ? mediaTypeDocumentation.schema : mediaTypeDocumentation.schemas[contentKey];
} else if (mediaTypeDocumentation?.contentType && mediaTypeDocumentation.schema) {
if (mediaTypeDocumentation.example) {
obj.example = mediaTypeDocumentation.example;
}

schema = mediaTypeDocumentation.schema;
}
if (mediaTypeDocumentation.examples) {
obj.example = mediaTypeDocumentation.examples;
}

const schemaRef = await this.schemaHandler
.createSchema(mediaTypeDocumentation.name)
.catch((err) => {
throw err;
});
schema = mediaTypeDocumentation.schema;
}

obj.schema = {
$ref: schemaRef,
};
const schemaRef = await this.schemaHandler
.createSchema(mediaTypeDocumentation.name)
.catch((err) => {
throw err;
});

Object.assign(mediaTypeObj, { [contentKey]: obj });
obj.schema = {
$ref: schemaRef,
};

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

Expand Down Expand Up @@ -861,7 +871,7 @@ class DefinitionGenerator {
if (
this.openAPI.components[type][name] &&
isEqual(schemaObj[name], this.openAPI.components[type][name]) ===
false
false
) {
delete schemaObj[name];
newName = `${name}-${uuid()}`;
Expand Down
94 changes: 58 additions & 36 deletions src/schemaHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,21 @@ class SchemaHandler {
return model;
}

const contentType = Object.keys(model.content)[0];
model.contentType = contentType;
model.schema = model.content[contentType].schema;
if (Object.keys(model.content).length === 1) {
const contentType = Object.keys(model.content)[0];
model.contentType = contentType;
model.contentTypes = [contentType];
model.schema = model.content[contentType].schema;
} else {
model.contentType = null;
model.contentTypes = Object.keys(model.content);
model.schema = null;
model.schemas = {};
for (const key in model.content) {
Object.assign(model.schemas, {[key]: {schema: model.content[key].schema}});
}
// model.schema = model.content[contentType].schema;
}

return model;
};
Expand All @@ -69,43 +81,53 @@ class SchemaHandler {
async addModelsToOpenAPI() {
for (const model of this.models) {
const modelName = model.name;
const modelSchema = model.schema;
const schemas = []
if (model.schema){
// const modelSchema = model.schema;
schemas.push(model.schema)
} else {
for (const key in model.schemas) {
schemas.push(model.schemas[key].schema);
}
}

const convertedSchemas = await this.__dereferenceAndConvert(
modelSchema,
modelName,
model
).catch((err) => {
if (err instanceof Error) throw err;
else return err;
});
for (const modelSchema of schemas) {
const convertedSchemas = await this.__dereferenceAndConvert(
modelSchema,
modelName,
model
).catch((err) => {
if (err instanceof Error) throw err;
else return err;
});

if (
typeof convertedSchemas.schemas === "object" &&
!Array.isArray(convertedSchemas.schemas) &&
convertedSchemas.schemas !== null
) {
for (const [schemaName, schemaValue] of Object.entries(
convertedSchemas.schemas
)) {
if (schemaName === modelName) {
this.modelReferences[
schemaName
] = `#/components/schemas/${modelName}`;
}

if (
typeof convertedSchemas.schemas === "object" &&
!Array.isArray(convertedSchemas.schemas) &&
convertedSchemas.schemas !== null
) {
for (const [schemaName, schemaValue] of Object.entries(
convertedSchemas.schemas
)) {
if (schemaName === modelName) {
this.modelReferences[
schemaName
] = `#/components/schemas/${modelName}`;
this.__addToComponents("schemas", schemaValue, schemaName);
}

this.__addToComponents("schemas", schemaValue, schemaName);
} else {
throw new Error(
`There was an error converting the ${
model.name
} schema. Model received looks like: \n\n${JSON.stringify(
model
)}. The convereted schema looks like \n\n${JSON.stringify(
convertedSchemas
)}`
);
}
} else {
throw new Error(
`There was an error converting the ${
model.name
} schema. Model received looks like: \n\n${JSON.stringify(
model
)}. The convereted schema looks like \n\n${JSON.stringify(
convertedSchemas
)}`
);
}
}
}
Expand Down
Loading