diff --git a/src/DefinitionGenerator.ts b/src/DefinitionGenerator.ts index 779c749..da12087 100644 --- a/src/DefinitionGenerator.ts +++ b/src/DefinitionGenerator.ts @@ -68,7 +68,7 @@ export class DefinitionGenerator { } this.definition.components.schemas = await parseModels(models, this.root); - + this.config.models = _.values(this.definition.components.schemas); return this; } @@ -97,7 +97,7 @@ export class DefinitionGenerator { // loop through function configurations for (const funcConfig of config) { // loop through http events - for (const httpEvent of this.getHttpEvents(funcConfig.events)) { + for (const httpEvent of this.getHttpEvents(funcConfig.events || [])) { const httpEventConfig = httpEvent.http; if (httpEventConfig.documentation) { @@ -352,7 +352,7 @@ export class DefinitionGenerator { return responses; } - private getResponseContent(response) { + private getResponseContent(response ={}) { const content = {}; for (const responseKey of Object.keys(response)) { diff --git a/src/__tests__/DefinitionGeneratorSwagger2Syntax.spec.ts b/src/__tests__/DefinitionGeneratorSwagger2Syntax.spec.ts new file mode 100644 index 0000000..37fd6b6 --- /dev/null +++ b/src/__tests__/DefinitionGeneratorSwagger2Syntax.spec.ts @@ -0,0 +1,104 @@ +import _ = require("lodash"); +import * as path from "path"; +import * as Serverless from "serverless"; +import { DefinitionGenerator } from "../DefinitionGenerator"; + +class ServerlessInterface extends Serverless { + public service: any = {}; + public config: any = {}; + public yamlParser: any = {}; + public pluginManager: any = {}; + public variables: any = {}; +} + +describe("OpenAPI Documentation Generator", () => { + let sls: ServerlessInterface; + + const servicePath = path.join(__dirname, "../../test/project-swagger-2.0"); + + beforeEach(async () => { + const serverlessYamlPath = path.join(servicePath, "./serverless.yml"); + sls = new Serverless(); + + sls.config.update({ + servicePath + }); + + const config = await sls.yamlParser.parse(serverlessYamlPath); + sls.pluginManager.cliOptions = { stage: "dev" }; + + await sls.service.load(config); + await sls.variables.populateService(); + + if (!("documentation" in sls.service.custom)) { + throw new Error( + 'Cannot find "documentation" in custom section of "serverless.yml"' + ); + } + }); + + + it("resolves the DTOs recursively using the swagger 2.0 spec : $ref: {{model: OtherDTO}}", async () => { + const docGen = new DefinitionGenerator( + sls.service.custom.documentation, + servicePath + ); + + // implementation copied from ServerlessOpenApiDocumentation.ts + await docGen.parse(); + + const funcConfigs = sls.service.getAllFunctions().map(functionName => { + const func = sls.service.getFunction(functionName); + return _.merge({ _functionName: functionName }, func); + }); + + docGen.readFunctions(funcConfigs); + + + let expected = { + "CompaniesDTO": { + "properties": { + "companies": { + "items": { + "$ref": "#/components/schemas/CompanyDTO" + }, + "type": "array" + } + }, + "type": "object" + }, + "CompanyDTO": { + "properties": { + "client": { + "$ref": "#/components/schemas/UserDTO" + }, + "name": { + "type": "string" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "UserDTO": { + "properties": { + "companyName": { + "type": "string" + }, + "email": { + "type": "string" + }, + "firstName": { + "type": "string" + }, + "surname": { + "type": "string" + } + }, + "type": "object" + } + }; + expect(docGen.definition.components.schemas).toEqual(expected) + }); +}); diff --git a/src/parse.ts b/src/parse.ts index eaaa76c..d617fa4 100644 --- a/src/parse.ts +++ b/src/parse.ts @@ -14,9 +14,12 @@ function updateReferences(schema: JSONSchema7): JSONSchema7 { const cloned = _.cloneDeep(schema); if (cloned.$ref) { + let referencedValue = cloned.$ref + .replace("#/definitions", "#/components/schemas") // json schema syntax + .replace(/{{model: (\w+)}}/, "#/components/schemas/$1"); // swagger 2.0 syntax return { ...cloned, - $ref: cloned.$ref.replace("#/definitions", "#/components/schemas") + $ref: referencedValue }; }